Differences between revisions 4 and 7 (spanning 3 versions)
Revision 4 as of 2007-05-20 12:14:47
Size: 4753
Comment: updated to reflect libSINGULAR
Revision 7 as of 2007-07-08 14:55:43
Size: 6677
Comment: more verbose description of SAGE's Singular interface
Deletions are marked like this. Additions are marked like this.
Line 14: Line 14:
Singular is integrated in two ways:
 * by using the Pexpect interface which means that every functionality of Singular is accessible from SAGE. However, this communication channel via pseudo ttys and string parsing may be pretty slow depending on the task at hand. Please refer to the SAGE reference manual, the SAGE tutorial, and the Singular manual for details.
 * by linking directly against a shared library called libSINGULAR which we derive from Singular. This way multivariate polynomial arithmetic over $Q$ and $GF(p)$ is provided through Singular. Other base fields (rings) will follow. In shared library mode no support for the Singular interpreter is provided which means that only a basic subset of Singular's capabilities are available. All of Singular's capabilities are however provided through the pexpect interface and convenient conversion methods are provided.
The [:pexpect:pexpect] interface allows to deal with Singular objects from within SAGE. This allows to perform almost any Singular calculation
from within SAGE.

{{{#!python
sage: r = singular.ring(0,'(x,y,z)','dp')
sage: f = singular('x + 2*y + 2*z - 1')
sage: g = singular('x^2 + 2*y^2 + 2*z^2 - x')
sage: h = singular('2*x*y + 2*y*z - y')
sage: I = singular.ideal(f,g,h)
sage: I.std()

x+2*y+2*z-1,
10*y*z+12*z^2-y-4*z,
4*y^2+2*y*z-y,
210*z^3-79*z^2+7*y+3*z

}}}

Alternatively, commands can be passed to the Singular interpreter directly, allowing SAGE to perform every calculation Singular is capable of.

{{{#!python
sage: ret = singular.eval('ring r = 0,(x,y,z),dp')
sage: ret = singular.eval('poly f= x + 2*y + 2*z - 1')
sage: ret = singular.eval('poly g = x^2 + 2*y^2 + 2*z^2 - x')
sage: ret = singular.eval('poly h = 2*x*y + 2*y*z - y')
sage: ret = singular.eval('ideal i = f,g,h')
sage: print singular.eval('std(i)')
_[1]=x+2y+2z-1
_[2]=10yz+12z2-y-4z
_[3]=4y2+2yz-y
_[4]=210z3-79z2+7y+3z
}}}

This functionality is used by several 'native' SAGE objects to perform calculations. For instance, if a Gröbner basis is to be calculated in SAGE Singular is used by default:

{{{#!python
sage: P.<x,y,z> = PolynomialRing(QQ,3)
sage: I = sage.rings.ideal.Katsura(P,3)
sage: I.groebner_basis() # calls Singular in background
[x + 2*y + 2*z - 1, 10*y*z + 12*z^2 - y - 4*z, 5*y^2 - 3*z^2 - y + z, 210*z^3 - 79*z^2 + 7*y + 3*z]
}}}

However, the communication channel via pseudo ttys and string parsing may be pretty slow depending on the task at hand.

To use Singular's high performance multivariate polynomial arithmetic SAGE links directly against a shared library called libSINGULAR which we derive from Singular. So far, multivariate polynomial arithmetic over $Q$, $GF(p)$, and $GF(p^n)$ is implemented this way. However, in this shared library mode no support for the Singular interpreter is provided which means that only a basic subset of Singular's capabilities are available, i.e. those written in C/C++. All of Singular's capabilities are however available through the forementioned [:pexpect:pexpect] interface and convenient conversion methods are provided.
Line 24: Line 66:
sage: I.groebner_basis() # calls Singular via the  pexpect interface in background sage: I.groebner_basis() # calls Singular via the pexpect interface in background
Line 27: Line 69:
sage: g = f._singular_() # -> pexpect interface
sage: P(g) # -> shared library mode
sage: x + 2*y + 2*z - 1
sage: g = f._singular_() # shared library implementation -> pexpect interface
sage: P(g) # pexpect interface implementation -> shared library mode
x + 2*y + 2*z - 1
Line 33: Line 75:
Singular provides a very fast multivariate polynomial implementation. Please note, that benchmarking these things in the Singular interpreter will probably give false results as the interpreter is very basic. To gather some simple performance datapoints consider: Singular provides a very fast multivariate polynomial implementation. Please note, that benchmarking these things in the Singular interpreter will probably give false results as the interpreter is very basic. To gather some simple performance datapoints consider Richard Fateman's [http://www.sigsam.org/cca/articles/143/fastmult.pdf fastmult] benchmark
Line 63: Line 105:
sage: print "MAGMA %0.2f"%magma.cputime(t) sage: print "MAGMA  %0.2f"%magma.cputime(t)
Line 66: Line 108:
{{{
{{{#!python
over QQ
SAGE/Singular 2.35
MAGMA 0.86
over GF(32003)
SAGE/Singular 0.24
MAGMA 0.52
Line 70: Line 117:
{{{ {{{#!python
Line 76: Line 123:
MAGMA 0.39 MAGMA  0.39
Line 81: Line 128:
 * As the pseudo tty interface may be slow it is always better to throw data at Singular in large chunks instead of small pieces. Consider this example: As the pseudo tty interface may be slow it is always better to throw data at Singular in large chunks instead of small pieces. Consider this example:
Line 91: Line 138:
sage: time for i in range(1000): f+=x^i
CPU times: user 0.95 s, sys: 0.12 s, total: 1.08 s
Wall time: 1.69
sage: time _ = singular.eval("poly f=0; for(i=0; i<1000 ; i=i+1) { f=f+x^i; }; f")
CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s
Wall time: 0.15
sage: time for i in range(10000): f+=x^i
CPU times: user 4.30 s, sys: 1.28 s, total: 5.58 s
Wall time: 6.47

sage: ret =singular.eval('int i')

sage: time _ = singular.eval("poly f=0; for(i=0; i<10000 ; i=i+1) { f=f+x^i; }; f")
CPU times: user 0.00 s, sys: 0.00 s, total: 0.01 s
Wall time: 1.24
Line 98: Line 148:
Please note, that this calculation can be done much faster by using the libSINGULAR interface.
{{{#!python
sage: P.<x,y> = PolynomialRing(QQ,2)
sage: f= 0
sage: sage: time for i in range(10000): f+=x^i
CPU times: user 0.82 s, sys: 0.00 s, total: 0.82 s
Wall time: 0.83
}}}

Description

Singular is a Computer Algebra System for polynomial computations with special emphasis on the needs of commutative algebra, algebraic geometry, and singularity theory.

Singular is distributed freely under the GNU General Public License (version 2 of the License); with the following additional restrictions (which override any conflicting restrictions in the GPL): The following software used with SINGULAR have their own copyright: the omalloc library, the readline library, the Gnu Multiple Precision Library (GMP), NTL: A Library for doing Number Theory (NTL), the MultiProtocol library (MP), the Singular-Factory library, the Singular-libfac library, and, for the Windows distributions the Cygwin DLL and the Cygwin tools (Cygwin), and the XEmacs editor (XEmacs). Their copyrights and licenses can be found in the accompanying files which are distributed along with these packages.

The Singular team won the ISAAC 2004 Richard D. Jenks Memorial Prize for Excellence in Software Engineering for Computer Algebra.

Website

http://www.singular.uni-kl.de/

Integration into SAGE

The [:pexpect:pexpect] interface allows to deal with Singular objects from within SAGE. This allows to perform almost any Singular calculation from within SAGE.

   1 sage: r = singular.ring(0,'(x,y,z)','dp')
   2 sage: f = singular('x + 2*y + 2*z - 1')
   3 sage: g = singular('x^2 + 2*y^2 + 2*z^2 - x')
   4 sage: h = singular('2*x*y + 2*y*z - y')
   5 sage: I = singular.ideal(f,g,h)
   6 sage: I.std()
   7 
   8 x+2*y+2*z-1,
   9 10*y*z+12*z^2-y-4*z,
  10 4*y^2+2*y*z-y,
  11 210*z^3-79*z^2+7*y+3*z

Alternatively, commands can be passed to the Singular interpreter directly, allowing SAGE to perform every calculation Singular is capable of.

   1 sage: ret = singular.eval('ring r = 0,(x,y,z),dp')
   2 sage: ret = singular.eval('poly f= x + 2*y + 2*z - 1')
   3 sage: ret = singular.eval('poly g = x^2 + 2*y^2 + 2*z^2 - x')
   4 sage: ret = singular.eval('poly h = 2*x*y + 2*y*z - y')
   5 sage: ret = singular.eval('ideal i = f,g,h')
   6 sage: print singular.eval('std(i)')
   7 _[1]=x+2y+2z-1
   8 _[2]=10yz+12z2-y-4z
   9 _[3]=4y2+2yz-y
  10 _[4]=210z3-79z2+7y+3z

This functionality is used by several 'native' SAGE objects to perform calculations. For instance, if a Gröbner basis is to be calculated in SAGE Singular is used by default:

   1 sage: P.<x,y,z> = PolynomialRing(QQ,3)
   2 sage: I = sage.rings.ideal.Katsura(P,3)
   3 sage: I.groebner_basis() # calls Singular in background
   4 [x + 2*y + 2*z - 1, 10*y*z + 12*z^2 - y - 4*z, 5*y^2 - 3*z^2 - y + z, 210*z^3 - 79*z^2 + 7*y + 3*z]

However, the communication channel via pseudo ttys and string parsing may be pretty slow depending on the task at hand.

To use Singular's high performance multivariate polynomial arithmetic SAGE links directly against a shared library called libSINGULAR which we derive from Singular. So far, multivariate polynomial arithmetic over Q, GF(p), and GF(p^n) is implemented this way. However, in this shared library mode no support for the Singular interpreter is provided which means that only a basic subset of Singular's capabilities are available, i.e. those written in C/C++. All of Singular's capabilities are however available through the forementioned [:pexpect:pexpect] interface and convenient conversion methods are provided.

Examples

   1 sage: P.<x,y,z> = PolynomialRing(QQ,3) # uses Singular in shared library mode
   2 sage: type(P)
   3 <type 'sage.rings.polynomial.multi_polynomial_libsingular.MPolynomialRing_libsingular'>
   4 sage: I = sage.rings.ideal.Katsura(P)
   5 sage: I.groebner_basis() # calls Singular via the pexpect interface in background
   6 [x + 2*y + 2*z - 1, 10*y*z + 12*z^2 - y - 4*z, 5*y^2 - 3*z^2 - y + z, 210*z^3 - 79*z^2 + 7*y + 3*z]
   7 sage: f = I.gens()[0]
   8 sage: g = f._singular_() # shared library implementation -> pexpect interface
   9 sage: P(g) # pexpect interface implementation -> shared library mode
  10 x + 2*y + 2*z - 1

Performance

Singular provides a very fast multivariate polynomial implementation. Please note, that benchmarking these things in the Singular interpreter will probably give false results as the interpreter is very basic. To gather some simple performance datapoints consider Richard Fateman's [http://www.sigsam.org/cca/articles/143/fastmult.pdf fastmult] benchmark

   1 sage: print "over QQ"
   2 
   3 sage: P.<x,y,z> = PolynomialRing(QQ,3)
   4 sage: p = (x + y + z + 1)^20 # the Fateman fastmult benchmark
   5 sage: q = p + 1
   6 sage: t = cputime()
   7 sage: r = p*q
   8 sage: print "SAGE/Singular %0.2f"%cputime(t)
   9 
  10 sage: p = p._magma_() # MAGMA 2.13-2
  11 sage: q = q._magma_()
  12 sage: t = magma.cputime()
  13 sage: r = p*q
  14 sage: print "MAGMA         %0.2f"%magma.cputime(t)
  15 
  16 sage: print "over GF(32003)"
  17 
  18 sage: P.<x,y,z> = PolynomialRing(GF(32003),3)
  19 sage: p = (x + y + z + 1)^20 # the Fateman fastmult benchmark
  20 sage: q = p + 1
  21 sage: t = cputime()
  22 sage: r = p*q
  23 sage: print "SAGE/Singular %0.2f"%cputime(t)
  24 
  25 sage: p = p._magma_() # MAGMA 2.13-2
  26 sage: q = q._magma_()
  27 sage: t = magma.cputime()
  28 sage: r = p*q
  29 sage: print "MAGMA         %0.2f"%magma.cputime(t)

On http://sage.math.washington.edu (1.8Ghz Opteron) and SAGE 2.5.1 (with a libSINGULAR without debugging options) this produces

   1 over QQ
   2 SAGE/Singular 2.35
   3 MAGMA         0.86
   4 over GF(32003)
   5 SAGE/Singular 0.24
   6 MAGMA         0.52

as output. On a 2.33Ghu Core2Duo Macbook Pro running a 64-bit Debian/Linux and the same software configuration this produces

   1 over QQ
   2 SAGE/Singular 1.42
   3 MAGMA         0.76
   4 over GF(32003)
   5 SAGE/Singular 0.15
   6 MAGMA         0.39

as output.

Tips, Tricks, and Pitfalls

As the pseudo tty interface may be slow it is always better to throw data at Singular in large chunks instead of small pieces. Consider this example:

   1 sage: singular.ring(0,'(x,y)','dp')
   2 //   characteristic : 0
   3 //   number of vars : 2
   4 //        block   1 : ordering dp
   5 //                  : names    x y
   6 //        block   2 : ordering C
   7 sage: x=singular("x")
   8 sage: f=0
   9 sage: time for i in range(10000): f+=x^i
  10 CPU times: user 4.30 s, sys: 1.28 s, total: 5.58 s
  11 Wall time: 6.47
  12 
  13 sage: ret =singular.eval('int i')
  14 sage: time _ = singular.eval("poly f=0; for(i=0; i<10000 ; i=i+1) { f=f+x^i; }; f")
  15 CPU times: user 0.00 s, sys: 0.00 s, total: 0.01 s
  16 Wall time: 1.24

Please note, that this calculation can be done much faster by using the libSINGULAR interface.

   1 sage: P.<x,y> = PolynomialRing(QQ,2)
   2 sage: f= 0
   3 sage: sage: time for i in range(10000): f+=x^i
   4 CPU times: user 0.82 s, sys: 0.00 s, total: 0.82 s
   5 Wall time: 0.83

Singular (last edited 2008-11-14 13:41:59 by anonymous)