Sage provides an interface to the GAP system. This system provides extensive group theory, combinatorics, etc.
The GAP interface will only work if GAP is installed on your computer; this should be the case, since GAP is included with Sage. The interface offers three pieces of functionality:
We factor an integer using GAP:
sage: n = gap(20062006); n
20062006
sage: n.parent()
Gap
sage: fac = n.Factors(); fac
[ 2, 17, 59, 73, 137 ]
sage: fac.parent()
Gap
sage: fac[1]
2
This example illustrates conversion between Singular and GAP via Sage as an intermediate step. First we create and factor a Singular polynomial.
sage: singular(389)
389
sage: R1 = singular.ring(0, '(x,y)', 'dp')
sage: f = singular('9*x^16-18*x^13*y^2-9*x^12*y^3+9*x^10*y^4-18*x^11*y^2+36*x^8*y^4+18*x^7*y^5-18*x^5*y^6+9*x^6*y^4-18*x^3*y^6-9*x^2*y^7+9*y^8')
sage: F = f.factorize()
sage: print F
[1]:
_[1]=9
_[2]=x^6-2*x^3*y^2-x^2*y^3+y^4
_[3]=-x^5+y^2
[2]:
1,1,2
Next we convert the factor to a Sage multivariate polynomial. Note that it is important to let and be the generators of a polynomial ring, so the eval command works.
sage: R.<x,y> = PolynomialRing(QQ,2)
sage: s = F[1][3].sage_polystring(); s
'-x**5+y**2'
sage: g = eval(s); g
-x^5 + y^2
Next we create a polynomial ring in GAP and obtain its indeterminates:
sage: R = gap.PolynomialRing('Rationals', 2); R
PolynomialRing( Rationals, ["x_1", "x_2"] )
sage: I = R.IndeterminatesOfPolynomialRing(); I
[ x_1, x_2 ]
In order to eval in GAP, we need to tell GAP to view the variables x0 and x1 as the two generators of . This is the one tricky part. In the GAP interpreter the object I has its own name (which isn’t I). We can access its name using I.name().
sage: _ = gap.eval("x := %s[1];; y := %s[2];;"%(I.name(), I.name()))
Now and are defined, so we can construct the GAP polynomial corresponding to :
sage: R.<x,y> = PolynomialRing(QQ,2)
sage: f = gap(str(g)); f
-x_1^5+x_2^2
We can call GAP functions on . For example, we evaluate the GAP Value function, which evaluates at the point .
sage: f.Value(I, [1,2])
3
sage: g(1,2) # agrees
3
Saving and loading GAP objects (using the dumps method, etc.) is not supported, since the output string representation of Gap objects is sometimes not valid input to GAP. Creating classes that wrap GAP objects is supported, via simply defining the a _gap_init_ member function that returns a string that when evaluated in GAP constructs the object. See groups/permutation_group.py for a nontrivial example of this.
The GAP interface reads in even very long input (using files) in a robust manner, as long as you are creating a new object.
Note
Using gap.eval for long input is much less robust, and is not recommended.
sage: t = '"%s"'%10^10000 # ten thousand character string.
sage: a = gap(t)
Use this code to change which GAP interpreter is run. E.g.,
import sage.interfaces.gap
sage.interfaces.gap.gap_cmd = "/usr/local/bin/gap"
AUTHORS:
Bases: sage.interfaces.gap.Gap_generic
Interface to the GAP interpreter.
AUTHORS:
Spawn a new GAP command-line session.
EXAMPLES:
sage: gap.console() #not tested
GAP4, Version: 4.4.12 of 17-Dec-2008, powerpc-apple-darwin9.8.0-gcc
gap>
Returns the amount of CPU time that the GAP session has used. If t is not None, then it returns the difference between the current CPU time and t.
EXAMPLES:
sage: t = gap.cputime()
sage: t #random
0.13600000000000001
sage: gap.Order(gap.SymmetricGroup(5))
120
sage: gap.cputime(t) #random
0.059999999999999998
Get the string representation of the variable var.
EXAMPLES:
sage: gap.set('x', '2')
sage: gap.get('x')
'2'
Print help on a given topic.
EXAMPLES:
sage: print gap.help('SymmetricGroup', pager=False)
Basic Groups _____________________________________________ Group Libraries
...
Set the variable var to the given value.
EXAMPLES:
sage: gap.set('x', '2')
sage: gap.get('x')
'2'
EXAMPLES:
sage: c = gap.trait_names()
sage: len(c) > 100
True
sage: 'Order' in c
True
Bases: sage.interfaces.gap.GapElement_generic
EXAMPLES:
sage: print gap(2)
2
EXAMPLES:
sage: s5 = gap.SymmetricGroup(5)
sage: 'Centralizer' in s5.trait_names()
True
Bases: sage.interfaces.expect.ExpectElement
Generic interface to the GAP3/GAP4 interpreters.
AUTHORS:
EXAMPLES:
sage: bool(gap(2))
True
sage: gap(0).bool()
False
sage: gap('false').bool()
False
Bases: sage.interfaces.expect.Expect
Generic interface to the GAP3/GAP4 interpreters.
AUTHORS:
Send the code in the string s to the GAP interpreter and return the output as a string.
INPUT:
EXAMPLES:
sage: gap.eval('2+2')
'4'
sage: gap.eval('Print(4); #test\n Print(6);')
'46'
sage: gap.eval('Print("#"); Print(6);')
'#6'
sage: gap.eval('4; \n 6;')
'4\n6'
Calls the GAP function with args and kwds.
EXAMPLES:
sage: gap.function_call('SymmetricGroup', [5])
SymmetricGroup( [ 1 .. 5 ] )
If the GAP function does not return a value, but prints something to the screen, then a string of the printed output is returned.
sage: s = gap.function_call('Display', [gap.SymmetricGroup(5).CharacterTable()])
sage: type(s)
<class 'sage.interfaces.expect.AsciiArtString'>
sage: s.startswith('CT')
True
Return the element of a GAP record identified by name.
INPUT:
OUTPUT:
EXAMPLES:
sage: rec = gap('rec( a := 1, b := "2" )')
sage: gap.get_record_element(rec, 'a')
1
sage: gap.get_record_element(rec, 'b')
2
TESTS:
sage: rec = gap('rec( a := 1, b := "2" )')
sage: type(gap.get_record_element(rec, 'a'))
<class 'sage.interfaces.gap.GapElement'>
Load the Gap package with the given name.
If loading fails, raise a RuntimeError exception.
TESTS:
sage: gap.load_package("chevie")
...
RuntimeError: Error loading Gap package chevie
EXAMPLES:
sage: c = gap.trait_names()
sage: len(c) > 100
True
sage: 'Order' in c
True
Clear the variable named var.
EXAMPLES:
sage: gap.set('x', '2')
sage: gap.get('x')
'2'
sage: gap.unbind('x')
sage: gap.get('x')
...
RuntimeError: Gap produced error output
Variable: 'x' must have a value
...
Returns the version of GAP being used.
EXAMPLES:
sage: gap.version()
'4.4.12'
Spawn a new GAP command-line session.
EXAMPLES:
sage: gap.console() #not tested
GAP4, Version: 4.4.12 of 17-Dec-2008, powerpc-apple-darwin9.8.0-gcc
gap>
Call this to completely reset the GAP workspace, which is used by default when Sage first starts GAP.
The first time you start GAP from Sage, it saves the startup state of GAP in the file
$HOME/.sage/gap-workspace
This is useful, since then subsequent startup of GAP is at least 10 times as fast. Unfortunately, if you install any new code for GAP, it won’t be noticed unless you explicitly load it, e.g., with gap.load_package(“my_package”)
The packages sonata, guava, factint, gapdoc, grape, design, toric, and laguna are loaded in all cases before the workspace is saved, if they are available.
Returns the version of GAP being used.
EXAMPLES:
sage: gap_version()
'4.4.12'
INPUT:
OUTPUT: element of F
EXAMPLES:
sage: x = gap('Z(13)')
sage: F = GF(13, 'a')
sage: F(x)
2
sage: F(gap('0*Z(13)'))
0
sage: F = GF(13^2, 'a')
sage: x = gap('Z(13)')
sage: F(x)
2
sage: x = gap('Z(13^2)^3')
sage: F(x)
12*a + 11
sage: F.multiplicative_generator()^3
12*a + 11
AUTHOR:
Returns True if x is a GapElement.
EXAMPLES:
sage: from sage.interfaces.gap import is_GapElement
sage: is_GapElement(gap(2))
True
sage: is_GapElement(2)
False
Returns an invalid GAP element. Note that this is the object returned when a GAP element is unpickled.
EXAMPLES:
sage: from sage.interfaces.gap import reduce_load
sage: reduce_load()
...
ValueError: The session in which this object was defined is no longer running.
sage: loads(dumps(gap(2)))
...
ValueError: The session in which this object was defined is no longer running.
Returns the GAP interface object defined in sage.interfaces.gap.
EXAMPLES:
sage: from sage.interfaces.gap import reduce_load_GAP
sage: reduce_load_GAP()
Gap