Ticket #11431: trac11431_singular_sage_conversion.patch

File trac11431_singular_sage_conversion.patch, 15.8 KB (added by SimonKing, 10 years ago)

Conversion Singular -> Sage

  • sage/interfaces/singular.py

    # HG changeset patch
    # User Simon King <simon.king@uni-jena.de>
    # Date 1307359301 -7200
    # Node ID 0a7417c540b58f8ce06b2c59c0de87cb87cdbb61
    # Parent  44c3067ccecfdf1456b785f4e8602cbdc42225aa
    #11431: Conversion of ideals, polynomials, (quotient) rings from Singular to Sage
    
    diff --git a/sage/interfaces/singular.py b/sage/interfaces/singular.py
    a b  
    13291329        """
    13301330        return str(self).replace('^','**')
    13311331
     1332    def sage_basering(self):
     1333        """
     1334        Return the current basering in Singular as a polynomial ring or quotient ring.
    13321335
    1333     def sage_poly(self, R, kcache=None):
     1336        EXAMPLE::
     1337
     1338            sage: singular.eval('ring r1 = (9,x),(a,b,c,d,e,f),(M((1,2,3,0)),wp(2,3),lp)')
     1339            'ring r1 = (9,x),(a,b,c,d,e,f),(M((1,2,3,0)),wp(2,3),lp);'
     1340            sage: R = singular('r1').sage_basering()
     1341            sage: R
     1342            Multivariate Polynomial Ring in a, b, c, d, e, f over Finite Field in x of size 3^2
     1343            sage: R.term_order()
     1344            Block term order with blocks:
     1345            (Matrix term order with matrix
     1346            [1 2]
     1347            [3 0],
     1348             Weighted degree reverse lexicographic term order with weights (2, 3),
     1349             Lexicographic term order of length 2)
     1350
     1351        ::
     1352
     1353            sage: singular.eval('ring r2 = (0,x),(a,b,c),dp')
     1354            'ring r2 = (0,x),(a,b,c),dp;'
     1355            sage: singular('r2').sage_basering()
     1356            Multivariate Polynomial Ring in a, b, c over Fraction Field of Univariate Polynomial Ring in x over Rational Field
     1357
     1358        ::
     1359
     1360            sage: singular.eval('ring r3 = (3,z),(a,b,c),dp')
     1361            'ring r3 = (3,z),(a,b,c),dp;'
     1362            sage: singular.eval('minpoly = 1+z+z2+z3+z4')
     1363            'minpoly = 1+z+z2+z3+z4;'
     1364            sage: singular('r3').sage_basering()
     1365            Multivariate Polynomial Ring in a, b, c over Univariate Quotient Polynomial Ring in z over Finite Field of size 3 with modulus z^4 + z^3 + z^2 + z + 1
     1366
     1367        The case of complex coefficients is not fully supported, yet, since
     1368        the generator of a complex field in Sage is always called "I"::
     1369
     1370            sage: singular.eval('ring r4 = (complex,15,j),(a,b,c),dp')
     1371            'ring r4 = (complex,15,j),(a,b,c),dp;'
     1372            sage: R = singular('r4').sage_basering(); R
     1373            Multivariate Polynomial Ring in a, b, c over Complex Field with 54 bits of precision
     1374            sage: R.base_ring()('j')
     1375            Traceback (most recent call last):
     1376            ...
     1377            NameError: name 'j' is not defined
     1378            sage: R.base_ring()('I')
     1379            1.00000000000000*I
     1380
     1381        In our last example, the base ring is a quotient ring::
     1382
     1383            sage: singular.eval('ring r5 = (9,a), (x,y,z),lp')
     1384            'ring r5 = (9,a), (x,y,z),lp;'
     1385            sage: Q = singular('std(ideal(x^2,x+y^2+z^3))', type='qring')
     1386            sage: Q.sage_basering()
     1387            Quotient of Multivariate Polynomial Ring in x, y, z over Finite Field in a of size 3^2 by the ideal (y^4 - y^2*z^3 + z^6, x + y^2 + z^3)
     1388
     1389        AUTHOR:
     1390
     1391        - Simon King (2011-06-06)
     1392
     1393        """
     1394        # extract the ring of coefficients
     1395        singular = self.parent()
     1396        charstr = singular.eval('charstr(basering)').split(',',1)
     1397        from sage.all import ZZ
     1398        is_extension = len(charstr)==2
     1399        if charstr[0]=='integer':
     1400            br = ZZ
     1401            is_extension = False
     1402        elif charstr[0]=='0':
     1403            from sage.all import QQ
     1404            br = QQ
     1405        elif charstr[0]=='real':
     1406            from sage.all import RR
     1407            br = RR
     1408            is_extension = False
     1409        elif charstr[0]=='complex':
     1410            from sage.all import ComplexField, ceil, log
     1411            prec, I = charstr[1].split(',')
     1412            br = ComplexField(ceil((ZZ(prec)+1)/log(2,10)))
     1413            is_extension = False
     1414        else:
     1415            # it ought to be a finite field
     1416            q = ZZ(charstr[0])
     1417            from sage.all import GF
     1418            if q.is_prime():
     1419                br = GF(q)
     1420            else:
     1421                br = GF(q,charstr[1])
     1422                # Singular has no extension of a non-prime field
     1423                is_extension = False
     1424
     1425        # We have the base ring of the base ring. But is it
     1426        # an extension?
     1427        if is_extension:
     1428            minpoly = singular.eval('minpoly')
     1429            if minpoly == '0':
     1430                from sage.all import Frac
     1431                BR = Frac(br[charstr[1]])
     1432            else:
     1433                is_short = singular.eval('short')
     1434                if is_short!='0':
     1435                    singular.eval('short=0')
     1436                    minpoly = ZZ[charstr[1]](singular.eval('minpoly'))
     1437                    singular.eval('short=%s'%is_short)
     1438                else:
     1439                    minpoly = ZZ[charstr[1]](minpoly)
     1440                BR = br.extension(minpoly)
     1441        else:
     1442            BR = br
     1443       
     1444        # Now, we form the polynomial ring over BR with the given variables,
     1445        # using Singular's term order
     1446        from sage.rings.polynomial.term_order import TermOrder_from_Singular
     1447        from sage.all import PolynomialRing
     1448        if singular.eval('typeof(basering)')=='ring':
     1449            return PolynomialRing(BR, names=singular.eval('varstr(basering)'), order=TermOrder_from_Singular(singular))
     1450        P = PolynomialRing(BR, names=singular.eval('varstr(basering)'), order=TermOrder_from_Singular(singular))
     1451        return P.quotient(singular('ringlist(basering)[4]')._sage_(P), names=singular.eval('varstr(basering)'))
     1452
     1453    def sage_poly(self, R=None, kcache=None):
    13341454        """
    13351455        Returns a Sage polynomial in the ring r matching the provided poly
    13361456        which is a singular polynomial.
     
    13381458        INPUT:
    13391459       
    13401460       
    1341         -  ``R`` - PolynomialRing: you *must* take care it
     1461        -  ``R`` - (default: None); an optional polynomial ring.
     1462           If it is provided, then you *must* take care it
    13421463           matches the current singular ring as, e.g., returned by
    1343            singular.current_ring()
     1464           singular.current_ring(). By default, the output of
     1465           :meth:`sage_basering` is used.
    13441466       
    13451467        -  ``kcache`` - (default: None); an optional dictionary
    13461468           for faster finite field lookups, this is mainly useful for finite
     
    13501472        OUTPUT: MPolynomial
    13511473       
    13521474        EXAMPLES::
    1353        
     1475
    13541476            sage: R = PolynomialRing(GF(2^8,'a'),2,'xy')
    13551477            sage: f=R('a^20*x^2*y+a^10+x')
    13561478            sage: f._singular_().sage_poly(R)==f
     
    13691491            x*y^3-1/9*x+1
    13701492            sage: P(singular(f))
    13711493            x*y^3 - 1/9*x + 1
    1372        
    1373         AUTHOR:
     1494
     1495        TESTS::
     1496
     1497            sage: singular.eval('ring r = (3,z),(a,b,c),dp')
     1498            'ring r = (3,z),(a,b,c),dp;'
     1499            sage: singular.eval('minpoly = 1+z+z2+z3+z4')
     1500            'minpoly = 1+z+z2+z3+z4;'
     1501            sage: p = singular('z^4*a^3+z^2*a*b*c')
     1502            sage: p.sage_poly()
     1503            (2*z^3 + 2*z^2 + 2*z + 2)*a^3 + z^2*a*b*c
     1504            sage: singular('z^4')
     1505            (-z3-z2-z-1)
     1506
     1507        AUTHORS:
    13741508
    13751509        - Martin Albrecht (2006-05-18)
     1510        - Simon King (2011-06-06): Deal with Singular's short polynomial representation,
     1511          automatic construction of a polynomial ring, if it is not explicitly given.
    13761512       
    13771513        .. note::
    13781514
     
    13921528        from sage.rings.quotient_ring import QuotientRing_generic
    13931529        from sage.rings.quotient_ring_element import QuotientRingElement
    13941530
     1531        ring_is_fine = False
     1532        if R is None:
     1533            ring_is_fine = True
     1534            R = self.sage_basering()
     1535
    13951536        sage_repr = {}
    13961537        k = R.base_ring()
    13971538
     
    14101551        # [[['x','3'],['y','3']],'a']. We may do this quickly,
    14111552        # as we know what to expect.
    14121553
    1413         if isinstance(R, MPolynomialRing_libsingular):
    1414             return R(self)
    1415 
    1416         singular_poly_list = self.parent().eval("string(coef(%s,%s))"%(\
    1417                                    self.name(),variable_str)).split(",")
     1554        is_short = self.parent().eval('short')
     1555        if is_short!='0':
     1556            self.parent().eval('short=0')
     1557            if isinstance(R, MPolynomialRing_libsingular):
     1558                out = R(self)
     1559                self.parent().eval('short=%s'%is_short)
     1560                return out
     1561            singular_poly_list = self.parent().eval("string(coef(%s,%s))"%(\
     1562                    self.name(),variable_str)).split(",")
     1563            self.parent().eval('short=%s'%is_short)
     1564        else:
     1565            if isinstance(R, MPolynomialRing_libsingular):
     1566                return R(self)
     1567            singular_poly_list = self.parent().eval("string(coef(%s,%s))"%(\
     1568                    self.name(),variable_str)).split(",")
    14181569
    14191570        if singular_poly_list == ['1','0'] :
    14201571            return R(0)
    14211572
    14221573        coeff_start = int(len(singular_poly_list)/2)
    14231574
    1424         if isinstance(R,(MPolynomialRing_polydict,QuotientRing_generic)) and can_convert_to_singular(R):
     1575        if isinstance(R,(MPolynomialRing_polydict,QuotientRing_generic)) and (ring_is_fine or can_convert_to_singular(R)):
    14251576            # we need to lookup the index of a given variable represented
    14261577            # through a string
    14271578            var_dict = dict(zip(R.variable_names(),range(R.ngens())))
     
    14561607            else:
    14571608                return QuotientRingElement(R,p,reduce=False)
    14581609
    1459         elif is_PolynomialRing(R) and can_convert_to_singular(R):
     1610        elif is_PolynomialRing(R) and (ring_is_fine or can_convert_to_singular(R)):
    14601611
    14611612            sage_repr = [0]*int(self.deg()+1)
    14621613
     
    14871638    def sage_matrix(self, R, sparse=True):
    14881639        """
    14891640        Returns Sage matrix for self
    1490        
     1641
     1642        INPUT:
     1643
     1644        -  ``R`` - (default: None); an optional ring, over which
     1645           the resulting matrix is going to be defined.
     1646           By default, the output of :meth:`sage_basering` is used.
     1647
     1648        - ``sparse`` - (default: True); determines whether the
     1649          resulting matrix is sparse or not.
     1650
    14911651        EXAMPLES::
    14921652       
    14931653            sage: R = singular.ring(0, '(x,y,z)', 'dp')
     
    15021662        from sage.matrix.constructor import Matrix
    15031663        nrows, ncols = int(self.nrows()),int(self.ncols())
    15041664
     1665        if R is None:
     1666            R = self.sage_basering()
     1667            A = Matrix(R, nrows, ncols, sparse=sparse)
     1668            #this is slow
     1669            for x in range(nrows):
     1670                for y in range(ncols):
     1671                    A[x,y]=self[x+1,y+1].sage_poly(R)
     1672            return A
     1673
    15051674        A = Matrix(R, nrows, ncols, sparse=sparse)
    15061675        #this is slow
    15071676        for x in range(nrows):
     
    15111680        return A
    15121681
    15131682    def _sage_(self, R=None):
    1514         """
     1683        r"""
    15151684        Coerces self to Sage.
    15161685       
    15171686        EXAMPLES::
     
    15331702            [ -8   2   0]
    15341703            [  0   1  -1]
    15351704            [  2   1 -95]
     1705
     1706        ::
     1707
     1708            sage: singular.eval('ring R = integer, (x,y,z),lp')
     1709            '// ** You are using coefficient rings which are not fields...'
     1710            sage: I = singular.ideal(['x^2','y*z','z+x'])
     1711            sage: I.sage()  # indirect doctest
     1712            Ideal (x^2, y*z, x + z) of Multivariate Polynomial Ring in x, y, z over Integer Ring
     1713
     1714        ::
     1715
     1716            sage: singular('ringlist(basering)').sage()
     1717            [['integer'], ['x', 'y', 'z'], [['lp', (1, 1, 1)], ['C', (0)]], Ideal (0) of Multivariate Polynomial Ring in x, y, z over Integer Ring]
     1718
     1719        ::
     1720
     1721            sage: singular.eval('ring r10 = (9,a), (x,y,z),lp')
     1722            'ring r10 = (9,a), (x,y,z),lp;'
     1723            sage: singular.eval('setring R')           
     1724            'setring R;'
     1725            sage: singular('r10').sage()
     1726            Multivariate Polynomial Ring in x, y, z over Finite Field in a of size 3^2
     1727
     1728        Note that the current base ring has not been changed by asking for another ring::
     1729
     1730            sage: singular('basering')
     1731            //   coeff. ring is : Integers
     1732            //   number of vars : 3
     1733            //        block   1 : ordering lp
     1734            //                  : names    x y z
     1735            //        block   2 : ordering C
     1736
     1737        ::
     1738
     1739            sage: singular.eval('setring r10')
     1740            'setring r10;'
     1741            sage: Q = singular('std(ideal(x^2,x+y^2+z^3))', type='qring')
     1742            sage: Q.sage()
     1743            Quotient of Multivariate Polynomial Ring in x, y, z over Finite Field in a of size 3^2 by the ideal (y^4 - y^2*z^3 + z^6, x + y^2 + z^3)
     1744            sage: singular('x^2+y').sage()
     1745            x^2 + y
     1746            sage: singular('x^2+y').sage().parent()
     1747            Quotient of Multivariate Polynomial Ring in x, y, z over Finite Field in a of size 3^2 by the ideal (y^4 - y^2*z^3 + z^6, x + y^2 + z^3)
     1748
    15361749        """
    15371750        typ = self.type()
    15381751        if typ=='poly':
     
    15541767                for j in xrange(A.ncols()):
    15551768                    A[i,j] = sage.rings.integer.Integer(str(self[i+1,j+1]))
    15561769            return A
    1557         else:
    1558             raise NotImplementedError, "Coercion of this datatype not implemented yet"
     1770        elif typ == 'string':
     1771            return repr(self)
     1772        elif typ == 'ideal':
     1773            R = R or self.sage_basering()
     1774            return R.ideal([p.sage_poly(R) for p in self])
     1775        elif typ in ['ring', 'qring']:
     1776            br = singular('basering')
     1777            self.set_ring()
     1778            R = self.sage_basering()
     1779            br.set_ring()
     1780            return R
     1781        raise NotImplementedError, "Coercion of this datatype not implemented yet"
    15591782
    15601783    def set_ring(self):
    15611784        """
  • sage/rings/polynomial/term_order.py

    diff --git a/sage/rings/polynomial/term_order.py b/sage/rings/polynomial/term_order.py
    a b  
    18581858            True
    18591859        """           
    18601860        return self._weights is not None
     1861
     1862def TermOrder_from_Singular(S):
     1863    """
     1864    Return the Sage term order of the basering in the given Singular interface
     1865
     1866    INPUT:
     1867
     1868    An instance of the Singular interface.
     1869
     1870    NOTE:
     1871
     1872    A term order in Singular also involves information on
     1873    orders for modules. This is not taken into account in
     1874    Sage.
     1875
     1876    EXAMPLE::
     1877
     1878        sage: singular.eval('ring r1 = (9,x),(a,b,c,d,e,f),(M((1,2,3,0)),wp(2,3),lp)')
     1879        'ring r1 = (9,x),(a,b,c,d,e,f),(M((1,2,3,0)),wp(2,3),lp);'
     1880        sage: from sage.rings.polynomial.term_order import TermOrder_from_Singular
     1881        sage: TermOrder_from_Singular(singular)
     1882        Block term order with blocks:
     1883        (Matrix term order with matrix
     1884        [1 2]
     1885        [3 0],
     1886         Weighted degree reverse lexicographic term order with weights (2, 3),
     1887         Lexicographic term order of length 2)
     1888
     1889    AUTHOR:
     1890
     1891    - Simon King (2011-06-06)
     1892
     1893    """
     1894    from sage.all import ZZ
     1895    singular = S
     1896    T = singular('ringlist(basering)[3]')
     1897    nblocks = ZZ(singular.eval('size(%s)'%T.name()))
     1898    order = []
     1899    for block in T:
     1900        blocktype = singular.eval('%s[1]'%block.name())
     1901        if blocktype in ['c','C','a']:
     1902            continue
     1903        elif blocktype == 'M':
     1904            from sage.matrix.constructor import matrix   
     1905            coefs = list(block[2].sage())
     1906            n = ZZ(len(coefs)).sqrt()
     1907            order.append(TermOrder(matrix(n,coefs)))
     1908        elif blocktype[0] in ['w','W']:
     1909            order.append(TermOrder(inv_singular_name_mapping[blocktype], list(block[2].sage())))
     1910        else:
     1911            order.append(TermOrder(inv_singular_name_mapping[blocktype], ZZ(singular.eval("size(%s[2])"%block.name()))))
     1912    if not order:
     1913        raise ValueError, "Invalid termorder in Singular"
     1914    out = order.pop(0)
     1915    while order:
     1916        out = out + order.pop(0)
     1917    return out