On 5/28/07, Nathan Dunfield <[EMAIL PROTECTED]> wrote:
> I'm trying to hack up a quick finitely presented group class, and am
> trying to write the _gap_init_ method.   In simple cases, _gap_init_
> returns a string, but I can't come up with one that works; e.g. the
> following fails
>
> sage: gap.new("F := FreeGroup(2); F/[F.1*F.2*F.1^-1*F.2^-1]")
> $sage21:=F := FreeGroup(2); F/[F.1*F.2*F.1^-1*F.2^-1];;
>             ^
>
>    executing $sage21:=F := FreeGroup(2); F/[F.1*F.2*F.1^-1*F.2^-1];;
>
> Now, I could have _gap_init_ return a GAP object created in several
> steps, e.g.
>
> sage: gap.eval("F := FreeGroup(2)")
> '<free group on the generators [ f1, f2 ]>'
> sage: G = gap.new("F/[F.1*F.2*F.1^-1*F.2^-1]");
> sage: G
> <fp group of size infinity on the generators [ f1, f2 ]>
>
> but this has the disadvantage of littering the GAP interpreter with a
> bunch of useless variables

I think the only variable you introduced was F, which
you would have introduced anyways.

> (or worse, over-writing something from my interactive session).

Fortunately, SAGE can use multiple copies of interfaces to GAP.
Probably the SAGE group theory package used its
own copy of the GAP interpreter, which is different from the interactive
session GAP.  This is what is done with maxima in the calculus package.
E.g.,

Set x to be 5 in maxima:
sage: maxima('x: 5')
5
sage: maxima('x + x + %pi')
%pi+10

This simplification is done using maxima (behind the scenes):
sage: x + x + pi
2*x + pi

Note that x is still x, since the maxima used by the calculus package
is different than the one in the interactive interpreter.

sage: quit
Exiting SAGE (CPU time 0m0.26s, Wall time 6m7.56s).
Exiting spawned Maxima process.
Exiting spawned Maxima process.
[EMAIL PROTECTED]:~$

----

Likewise, for group theory one should define the group package's
copy of GAP in some file:

from sage.interfaces.gap import Gap
gap = Gap()  # the group theory gap

Then if you use that gap you won't mess up anything else.

You should also define

  _gap_init_(self)

for your FP group to raise a NotImplementedError, so it isn't
unintentionally used, and you should define a method

   def _gap_(self, system=gap):
         ...

which creates your FP group in the given copy of gap (the one
that is the system argument).  If it's the local group-theory gap,
then you're in a controlled copy of the interpreter, and don't have
to worry much about variables you define (since you are carefully
not to do anything stupid).  If another copy of the gap
interpreter is passed in, you should be sure to be much more
careful about variables names, e.g., call it _sage_F instead of F.

Making a new copy of the GAP interpreter is very cheap, since
the workspace is cached.  You can do it about 5 times a second
in Linux:

sage: time g=Gap()('2+2')
CPU times: user 0.00 s, sys: 0.01 s, total: 0.01 s
Wall time: 0.19      <---- this is what matters

Note also that it takes not time to just make an instance of Gap
without doing a computation (since GAP isn't actually started until
a computation is done):
sage: time g=Gap()
CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s
Wall time: 0.00


William

--~--~---------~--~----~------------~-------~--~----~
To post to this group, send email to sage-devel@googlegroups.com
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at http://groups.google.com/group/sage-devel
URLs: http://sage.scipy.org/sage/ and http://modular.math.washington.edu/sage/
-~----------~----~----~----~------~----~------~--~---

Reply via email to