Ticket #14832: trac_14832_make_irreducible_polynomial.patch

File trac_14832_make_irreducible_polynomial.patch, 10.0 KB (added by pbruin, 10 years ago)

based on 5.11.beta3

  • sage/rings/polynomial/polynomial_gf2x.pyx

    # HG changeset patch
    # User Peter Bruin <peter.bruin@math.uzh.ch>
    # Date 1372186250 -7200
    # Node ID 15c4954a1e738ebc79f550edab54282af3f50fa0
    # Parent  739c6c4c4f751f2fe95f291c9b4e75cd7e51e4c2
    Trac 14832: construct irreducible polynomials over finite fields
    
    diff --git a/sage/rings/polynomial/polynomial_gf2x.pyx b/sage/rings/polynomial/polynomial_gf2x.pyx
    a b  
    276276            return False
    277277        else:
    278278            return True
     279
     280
     281# The three functions below are used in polynomial_ring.py, but are in
     282# this Cython file since they call C++ functions.  They return
     283# polynomials as lists so that no variable has to be specified.
     284# AUTHOR: Peter Bruin (June 2013)
     285
     286def GF2X_BuildIrred_list(n):
     287    """
     288    Return the list of coefficients of the lexicographically smallest
     289    irreducible polynomial of degree `n` over the field of 2 elements.
     290
     291    EXAMPLE:
     292
     293        sage: from sage.rings.polynomial.polynomial_gf2x import GF2X_BuildIrred_list
     294        sage: GF2X_BuildIrred_list(2)
     295        [1, 1, 1]
     296        sage: GF2X_BuildIrred_list(3)
     297        [1, 1, 0, 1]
     298        sage: GF2X_BuildIrred_list(4)
     299        [1, 1, 0, 0, 1]
     300        sage: GF(2)['x'](GF2X_BuildIrred_list(33))
     301        x^33 + x^6 + x^3 + x + 1
     302    """
     303    from sage.rings.finite_rings.constructor import FiniteField
     304    cdef GF2X_c f
     305    GF2 = FiniteField(2)
     306    GF2X_BuildIrred(f, int(n))
     307    return [GF2(not GF2_IsZero(GF2X_coeff(f, i))) for i in xrange(n + 1)]
     308
     309def GF2X_BuildSparseIrred_list(n):
     310    """
     311    Return the list of coefficients of an irreducible polynomial of
     312    degree `n` of minimal weight over the field of 2 elements.
     313
     314    EXAMPLE:
     315
     316        sage: from sage.rings.polynomial.polynomial_gf2x import GF2X_BuildIrred_list, GF2X_BuildSparseIrred_list
     317        sage: all([GF2X_BuildSparseIrred_list(n) == GF2X_BuildIrred_list(n)
     318        ....:      for n in range(1,33)])
     319        True
     320        sage: GF(2)['x'](GF2X_BuildSparseIrred_list(33))
     321        x^33 + x^10 + 1
     322    """
     323    from sage.rings.finite_rings.constructor import FiniteField
     324    cdef GF2X_c f
     325    GF2 = FiniteField(2)
     326    GF2X_BuildSparseIrred(f, int(n))
     327    return [GF2(not GF2_IsZero(GF2X_coeff(f, i))) for i in xrange(n + 1)]
     328
     329def GF2X_BuildRandomIrred_list(n):
     330    """
     331    Return the list of coefficients of an irreducible polynomial of
     332    degree `n` of minimal weight over the field of 2 elements.
     333
     334    EXAMPLE:
     335
     336        sage: from sage.rings.polynomial.polynomial_gf2x import GF2X_BuildRandomIrred_list
     337        sage: GF2X_BuildRandomIrred_list(2)
     338        [1, 1, 1]
     339        sage: GF2X_BuildRandomIrred_list(3) in [[1, 1, 0, 1], [1, 0, 1, 1]]
     340        True
     341    """
     342    from sage.misc.randstate import current_randstate
     343    from sage.rings.finite_rings.constructor import FiniteField
     344    cdef GF2X_c tmp, f
     345    GF2 = FiniteField(2)
     346    current_randstate().set_seed_ntl(False)
     347    GF2X_BuildSparseIrred(tmp, int(n))
     348    GF2X_BuildRandomIrred(f, tmp)
     349    return [GF2(not GF2_IsZero(GF2X_coeff(f, i))) for i in xrange(n + 1)]
  • sage/rings/polynomial/polynomial_ring.py

    diff --git a/sage/rings/polynomial/polynomial_ring.py b/sage/rings/polynomial/polynomial_ring.py
    a b  
    17981798                self._fraction_field = FractionField_1poly_field(self)
    17991799            return self._fraction_field
    18001800
     1801class PolynomialRing_dense_finite_field(PolynomialRing_field):
     1802    """
     1803    Univariate polynomial ring over a finite field.
     1804    """
     1805    def irreducible_element(self, n, algorithm=None):
     1806        """
     1807        Construct an irreducible polynomial of degree `n`.
     1808
     1809        INPUT:
     1810
     1811        - ``n`` -- integer: degree of the polynomial to construct
     1812
     1813        - ``algorithm`` -- string: algorithm to use, or ``None``
     1814
     1815          - ``'random'``: try random polynomials until an irreducible
     1816            one is found.  This is currently the only algorithm
     1817            available over non-prime finite fields.
     1818
     1819        OUTPUT:
     1820
     1821        A monic irreducible polynomial of degree `n` in ``self``.
     1822
     1823        EXAMPLES:
     1824
     1825            sage: GF(5^3, 'a')['x'].irreducible_element(2)
     1826            x^2 + (4*a^2 + a + 4)*x + 2*a^2 + 2
     1827
     1828        AUTHOR:
     1829
     1830            Peter Bruin (June 2013)
     1831        """
     1832        if n < 1:
     1833            raise ValueError("degree must be at least 1")
     1834
     1835        if algorithm is None or algorithm == "random":
     1836            while True:
     1837                f = self.gen()**n + self.random_element(n - 1)
     1838                if f.is_irreducible():
     1839                    return f
     1840        else:
     1841            raise ValueError("no such algorithm for finding an irreducible polynomial: %s" % algorithm)
     1842
    18011843class PolynomialRing_dense_padic_ring_generic(PolynomialRing_integral_domain):
    18021844    pass
    18031845
     
    19952037        return s + self._implementation_repr
    19962038
    19972039
    1998 class PolynomialRing_dense_mod_p(PolynomialRing_field,
     2040class PolynomialRing_dense_mod_p(PolynomialRing_dense_finite_field,
    19992041                                 PolynomialRing_dense_mod_n,
    20002042                                 PolynomialRing_singular_repr):
    20012043    def __init__(self, base_ring, name="x", implementation=None):
     
    20542096        from sage.rings.polynomial.polynomial_singular_interface import can_convert_to_singular
    20552097        self._has_singular = can_convert_to_singular(self)
    20562098
     2099    def irreducible_element(self, n, algorithm=None):
     2100        """
     2101        Construct an irreducible polynomial of degree `n`.
     2102
     2103        INPUT:
     2104
     2105        - ``n`` -- integer: the degree of the polynomial to construct
     2106
     2107        - ``algorithm`` -- string: algorithm to use, or ``None``.
     2108          Currently available options are:
     2109
     2110          - ``'adleman-lenstra'``: a variant of the Adleman--Lenstra
     2111              algorithm as implemented in PARI.
     2112
     2113          - ``'conway'``: look up the Conway polynomial of degree `n`
     2114            over the field of `p` elements in the database; raise a
     2115            ``RuntimeError`` if it is not found.
     2116
     2117          - ``'first_lexicographic'``: return the lexicographically
     2118            smallest irreducible polynomial of degree `n`.  Only
     2119            implemented for `p = 2`.
     2120
     2121          - ``'minimal_weight'``: return an irreducible polynomial of
     2122            degree `n` with minimal number of non-zero coefficients.
     2123            Only implemented for `p = 2`.
     2124
     2125          - ``'random'``: try random polynomials until an irreducible
     2126            one is found.
     2127
     2128          If ``algorithm`` is ``None``, the Conway polynomial is used
     2129          if it is found in the database.  If no Conway polynomial is
     2130          found, the algorithm ``minimal_weight`` is used if `p = 2`,
     2131          and the algorithm ``adleman-lenstra`` if `p > 2`.
     2132
     2133        OUTPUT:
     2134
     2135        A monic irreducible polynomial of degree `n` in ``self``.
     2136
     2137        EXAMPLES:
     2138
     2139            sage: GF(5)['x'].irreducible_element(2)
     2140            x^2 + 4*x + 2
     2141            sage: GF(5)['x'].irreducible_element(2, algorithm="adleman-lenstra")
     2142            x^2 + x + 1
     2143
     2144            sage: GF(2)['x'].irreducible_element(33)
     2145            x^33 + x^13 + x^12 + x^11 + x^10 + x^8 + x^6 + x^3 + 1
     2146            sage: GF(2)['x'].irreducible_element(33, algorithm="minimal_weight")
     2147            x^33 + x^10 + 1
     2148
     2149        AUTHOR:
     2150
     2151            Peter Bruin (June 2013)
     2152        """
     2153        from sage.libs.pari.all import pari
     2154        from sage.rings.finite_rings.constructor import (conway_polynomial,
     2155                                                         exists_conway_polynomial)
     2156        from polynomial_gf2x import (GF2X_BuildIrred_list, GF2X_BuildSparseIrred_list,
     2157                                     GF2X_BuildRandomIrred_list)
     2158
     2159        p = self.characteristic()
     2160        n = int(n)
     2161        if n < 1:
     2162            raise ValueError("degree must be at least 1")
     2163        if algorithm is None:
     2164            if exists_conway_polynomial(p, n):
     2165                algorithm = "conway"
     2166            elif p == 2:
     2167                algorithm = "minimal_weight"
     2168            else:
     2169                algorithm = "adleman-lenstra"
     2170
     2171        if algorithm == "adleman-lenstra":
     2172            return self(pari(p).ffinit(n))
     2173        elif algorithm == "conway":
     2174            return self(conway_polynomial(p, n))
     2175        elif algorithm == "first_lexicographic":
     2176            if p == 2:
     2177                return self(GF2X_BuildIrred_list(n))
     2178            else:
     2179                raise NotImplementedError("'first_lexicographic' option only implemented for p = 2")
     2180        elif algorithm == "minimal_weight":
     2181            if p == 2:
     2182                return self(GF2X_BuildSparseIrred_list(n))
     2183            else:
     2184                raise NotImplementedError("'minimal_weight' option only implemented for p = 2")
     2185        elif algorithm == "random":
     2186            if p == 2:
     2187                return self(GF2X_BuildRandomIrred_list(n))
     2188            else:
     2189                pass
     2190
     2191        # No suitable algorithm found, try algorithms from the base class.
     2192        return PolynomialRing_dense_finite_field.irreducible_element(self, n, algorithm)
     2193
    20572194
    20582195def polygen(ring_or_element, name="x"):
    20592196    """
  • sage/rings/polynomial/polynomial_ring_constructor.py

    diff --git a/sage/rings/polynomial/polynomial_ring_constructor.py b/sage/rings/polynomial/polynomial_ring_constructor.py
    a b  
    4040import sage.rings.padics.padic_base_leaves as padic_base_leaves
    4141
    4242from sage.rings.integer import Integer
     43from sage.rings.finite_rings.constructor import is_FiniteField
    4344from sage.rings.finite_rings.integer_mod_ring import is_IntegerModRing
    4445
    4546from sage.misc.cachefunc import weak_cached_function
     
    533534            else:  # n == 1!
    534535                R = m.PolynomialRing_integral_domain(base_ring, name)   # specialized code breaks in this case.
    535536
     537        elif is_FiniteField(base_ring) and not sparse:
     538            R = m.PolynomialRing_dense_finite_field(base_ring, name)
     539
    536540        elif isinstance(base_ring, padic_base_leaves.pAdicFieldCappedRelative):
    537541            R = m.PolynomialRing_dense_padic_field_capped_relative(base_ring, name)
    538542