Ticket #14832: trac_14832-irreducible_polynomial.patch

File trac_14832-irreducible_polynomial.patch, 8.5 KB (added by pbruin, 10 years ago)

method irreducible_element()

  • sage/rings/polynomial/polynomial_gf2x.pyx

    # HG changeset patch
    # User Peter Bruin <peter.bruin@math.uzh.ch>
    # Date 1372186250 -7200
    # Node ID 960d2140d302de19c94a6d2c29843df807fb3353
    # Parent  2a761815a0cb361db7d96cdd3d009a4d8eebf5a0
    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  
    18111811        PolynomialRing_field.__init__(self, base_ring, sparse=False, name=name,
    18121812                                      element_class=element_class)
    18131813
     1814    def irreducible_element(self, n, algorithm=None):
     1815        """
     1816        Construct an irreducible polynomial of degree `n`.
     1817
     1818        INPUT:
     1819
     1820        - ``n`` -- integer: degree of the polynomial to construct
     1821
     1822        - ``algorithm`` -- string: algorithm to use, or ``None``
     1823
     1824          - ``'random'``: try random polynomials until an irreducible
     1825            one is found.  This is currently the only algorithm
     1826            available over non-prime finite fields.
     1827
     1828        OUTPUT:
     1829
     1830        A monic irreducible polynomial of degree `n` in ``self``.
     1831
     1832        EXAMPLES:
     1833
     1834            sage: GF(5^3, 'a')['x'].irreducible_element(2)
     1835            x^2 + (4*a^2 + a + 4)*x + 2*a^2 + 2
     1836
     1837        AUTHORS:
     1838
     1839        - Peter Bruin (June 2013)
     1840        """
     1841        if n < 1:
     1842            raise ValueError("degree must be at least 1")
     1843
     1844        if algorithm is None or algorithm == "random":
     1845            while True:
     1846                f = self.gen()**n + self.random_element(n - 1)
     1847                if f.is_irreducible():
     1848                    return f
     1849        else:
     1850            raise ValueError("no such algorithm for finding an irreducible polynomial: %s" % algorithm)
     1851
    18141852class PolynomialRing_dense_padic_ring_generic(PolynomialRing_integral_domain):
    18151853    pass
    18161854
     
    20672105        from sage.rings.polynomial.polynomial_singular_interface import can_convert_to_singular
    20682106        self._has_singular = can_convert_to_singular(self)
    20692107
     2108    def irreducible_element(self, n, algorithm=None):
     2109        """
     2110        Construct an irreducible polynomial of degree `n`.
     2111
     2112        INPUT:
     2113
     2114        - ``n`` -- integer: the degree of the polynomial to construct
     2115
     2116        - ``algorithm`` -- string: algorithm to use, or ``None``.
     2117          Currently available options are:
     2118
     2119          - ``'adleman-lenstra'``: a variant of the Adleman--Lenstra
     2120              algorithm as implemented in PARI.
     2121
     2122          - ``'conway'``: look up the Conway polynomial of degree `n`
     2123            over the field of `p` elements in the database; raise a
     2124            ``RuntimeError`` if it is not found.
     2125
     2126          - ``'first_lexicographic'``: return the lexicographically
     2127            smallest irreducible polynomial of degree `n`.  Only
     2128            implemented for `p = 2`.
     2129
     2130          - ``'minimal_weight'``: return an irreducible polynomial of
     2131            degree `n` with minimal number of non-zero coefficients.
     2132            Only implemented for `p = 2`.
     2133
     2134          - ``'random'``: try random polynomials until an irreducible
     2135            one is found.
     2136
     2137          If ``algorithm`` is ``None``, the Conway polynomial is used
     2138          if it is found in the database.  If no Conway polynomial is
     2139          found, the algorithm ``minimal_weight`` is used if `p = 2`,
     2140          and the algorithm ``adleman-lenstra`` if `p > 2`.
     2141
     2142        OUTPUT:
     2143
     2144        A monic irreducible polynomial of degree `n` in ``self``.
     2145
     2146        EXAMPLES:
     2147
     2148            sage: GF(5)['x'].irreducible_element(2)
     2149            x^2 + 4*x + 2
     2150            sage: GF(5)['x'].irreducible_element(2, algorithm="adleman-lenstra")
     2151            x^2 + x + 1
     2152
     2153            sage: GF(2)['x'].irreducible_element(33)
     2154            x^33 + x^13 + x^12 + x^11 + x^10 + x^8 + x^6 + x^3 + 1
     2155            sage: GF(2)['x'].irreducible_element(33, algorithm="minimal_weight")
     2156            x^33 + x^10 + 1
     2157
     2158        AUTHORS:
     2159
     2160        - Peter Bruin (June 2013)
     2161        """
     2162        from sage.libs.pari.all import pari
     2163        from sage.rings.finite_rings.constructor import (conway_polynomial,
     2164                                                         exists_conway_polynomial)
     2165        from polynomial_gf2x import (GF2X_BuildIrred_list, GF2X_BuildSparseIrred_list,
     2166                                     GF2X_BuildRandomIrred_list)
     2167
     2168        p = self.characteristic()
     2169        n = int(n)
     2170        if n < 1:
     2171            raise ValueError("degree must be at least 1")
     2172        if algorithm is None:
     2173            if exists_conway_polynomial(p, n):
     2174                algorithm = "conway"
     2175            elif p == 2:
     2176                algorithm = "minimal_weight"
     2177            else:
     2178                algorithm = "adleman-lenstra"
     2179
     2180        if algorithm == "adleman-lenstra":
     2181            return self(pari(p).ffinit(n))
     2182        elif algorithm == "conway":
     2183            return self(conway_polynomial(p, n))
     2184        elif algorithm == "first_lexicographic":
     2185            if p == 2:
     2186                return self(GF2X_BuildIrred_list(n))
     2187            else:
     2188                raise NotImplementedError("'first_lexicographic' option only implemented for p = 2")
     2189        elif algorithm == "minimal_weight":
     2190            if p == 2:
     2191                return self(GF2X_BuildSparseIrred_list(n))
     2192            else:
     2193                raise NotImplementedError("'minimal_weight' option only implemented for p = 2")
     2194        elif algorithm == "random":
     2195            if p == 2:
     2196                return self(GF2X_BuildRandomIrred_list(n))
     2197            else:
     2198                pass
     2199
     2200        # No suitable algorithm found, try algorithms from the base class.
     2201        return PolynomialRing_dense_finite_field.irreducible_element(self, n, algorithm)
    20702202
    20712203def polygen(ring_or_element, name="x"):
    20722204    """