Ticket #11431: trac11431_singular_sage_conversion.patch
File trac11431_singular_sage_conversion.patch, 15.8 KB (added by , 10 years ago) 


sage/interfaces/singular.py
# HG changeset patch # User Simon King <simon.king@unijena.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 1329 1329 """ 1330 1330 return str(self).replace('^','**') 1331 1331 1332 def sage_basering(self): 1333 """ 1334 Return the current basering in Singular as a polynomial ring or quotient ring. 1332 1335 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 (20110606) 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 nonprime 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): 1334 1454 """ 1335 1455 Returns a Sage polynomial in the ring r matching the provided poly 1336 1456 which is a singular polynomial. … … 1338 1458 INPUT: 1339 1459 1340 1460 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 1342 1463 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. 1344 1466 1345 1467  ``kcache``  (default: None); an optional dictionary 1346 1468 for faster finite field lookups, this is mainly useful for finite … … 1350 1472 OUTPUT: MPolynomial 1351 1473 1352 1474 EXAMPLES:: 1353 1475 1354 1476 sage: R = PolynomialRing(GF(2^8,'a'),2,'xy') 1355 1477 sage: f=R('a^20*x^2*y+a^10+x') 1356 1478 sage: f._singular_().sage_poly(R)==f … … 1369 1491 x*y^31/9*x+1 1370 1492 sage: P(singular(f)) 1371 1493 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 (z3z2z1) 1506 1507 AUTHORS: 1374 1508 1375 1509  Martin Albrecht (20060518) 1510  Simon King (20110606): Deal with Singular's short polynomial representation, 1511 automatic construction of a polynomial ring, if it is not explicitly given. 1376 1512 1377 1513 .. note:: 1378 1514 … … 1392 1528 from sage.rings.quotient_ring import QuotientRing_generic 1393 1529 from sage.rings.quotient_ring_element import QuotientRingElement 1394 1530 1531 ring_is_fine = False 1532 if R is None: 1533 ring_is_fine = True 1534 R = self.sage_basering() 1535 1395 1536 sage_repr = {} 1396 1537 k = R.base_ring() 1397 1538 … … 1410 1551 # [[['x','3'],['y','3']],'a']. We may do this quickly, 1411 1552 # as we know what to expect. 1412 1553 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(",") 1418 1569 1419 1570 if singular_poly_list == ['1','0'] : 1420 1571 return R(0) 1421 1572 1422 1573 coeff_start = int(len(singular_poly_list)/2) 1423 1574 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)): 1425 1576 # we need to lookup the index of a given variable represented 1426 1577 # through a string 1427 1578 var_dict = dict(zip(R.variable_names(),range(R.ngens()))) … … 1456 1607 else: 1457 1608 return QuotientRingElement(R,p,reduce=False) 1458 1609 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)): 1460 1611 1461 1612 sage_repr = [0]*int(self.deg()+1) 1462 1613 … … 1487 1638 def sage_matrix(self, R, sparse=True): 1488 1639 """ 1489 1640 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 1491 1651 EXAMPLES:: 1492 1652 1493 1653 sage: R = singular.ring(0, '(x,y,z)', 'dp') … … 1502 1662 from sage.matrix.constructor import Matrix 1503 1663 nrows, ncols = int(self.nrows()),int(self.ncols()) 1504 1664 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 1505 1674 A = Matrix(R, nrows, ncols, sparse=sparse) 1506 1675 #this is slow 1507 1676 for x in range(nrows): … … 1511 1680 return A 1512 1681 1513 1682 def _sage_(self, R=None): 1514 """1683 r""" 1515 1684 Coerces self to Sage. 1516 1685 1517 1686 EXAMPLES:: … … 1533 1702 [ 8 2 0] 1534 1703 [ 0 1 1] 1535 1704 [ 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 1536 1749 """ 1537 1750 typ = self.type() 1538 1751 if typ=='poly': … … 1554 1767 for j in xrange(A.ncols()): 1555 1768 A[i,j] = sage.rings.integer.Integer(str(self[i+1,j+1])) 1556 1769 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" 1559 1782 1560 1783 def set_ring(self): 1561 1784 """ 
sage/rings/polynomial/term_order.py
diff git a/sage/rings/polynomial/term_order.py b/sage/rings/polynomial/term_order.py
a b 1858 1858 True 1859 1859 """ 1860 1860 return self._weights is not None 1861 1862 def 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 (20110606) 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