Sage's Axiom/FriCAS Interface

5 views
Skip to first unread message

Mike Hansen

unread,
Aug 31, 2008, 11:11:48 PM8/31/08
to fricas...@googlegroups.com, sage-...@googlegroups.com
Hello Bill,

> There is very a little documentation available in Sage about how the
> conversion from Sage internal format to some external format (such as
> used when calling Axiom). This happens automatically when you write
> something like
>
> sage: axiom(x^2+1)
>
> without including the 'quotes'. In this case Sage parses the expression
>
> x^2+1
>
> and creates a native polynomial object. Then the 'axiom' function must
> now recursively process this Sage expression until it finds objects
> and operations near the bottom of the tree that it knows how to
> interpret as Axiom objects and operations. Most of the coding that
> accomplishes this is outside of the 'axiom.py' interface itself,
> distributed over several other Python classes. As far as I know
> William Stein is still the best source for how this conversion works.
> He has said that "really it is very simple" and I guess I do
> understand parts of it, but you should expect to spend some time to
> re-discover how it works sufficiently well in order to improve it.

I don't think the interfaces are as much "magic" as you make them out
to be. If you're interested in converting object from Sage to
Axiom/FriCAS, then there are really only two methods you need to worry
about -- _axiom_ and _axiom_init_. _axiom_init_ method just returns a
string used to construct self in Axiom. For example, say we have

class Foo(SageObject):
def __init__(self, n):
self.n = int(n)
def _axiom_init_(self):
return str(self.n)

Then I can do

sage: a = Foo(2); a
<class '__main__.Foo'>
sage: axiom(a)
2
sage: axiom(a).type()
PositiveInteger

For more compilcated things, the _axiom_ method takes in an Axiom
interface object and returns self constructed in Axiom.

class Foo(SageObject):
def __init__(self, n):
self.n = int(n)
def _axiom_(self, axiom):
return axiom(str(self.n))

This behaves the same as above.

The Macualay2 interface in sage/interfaces/macaulay2.py has some good
examples of moving objects back and forth between systems.

Anyway, I did some work on the Axiom interface today such as
doctesting it, removing broken code, adding tab completion, etc. You
can see my changes at http://trac.sagemath.org/sage_trac/ticket/4028 .
Things like the online help didn't work with either the fricas spkg
or just on a local copy, but I'd be more than happy to help adding
that functionality (as well as anything else).

--Mike

Bill Page

unread,
Sep 1, 2008, 2:37:07 PM9/1/08
to fricas...@googlegroups.com, sage-...@googlegroups.com
Mike,

Before I reply to your email, let me ask a simple question about sage
as installed on sage.math. When I try the axiom interface there I get:

page@sage:~$ sage
----------------------------------------------------------------------
| SAGE Version 3.1, Release Date: 2008-08-16 |
| Type notebook() for the GUI, and license() for information. |
----------------------------------------------------------------------

sage: axiom('1+1')

sage: axiom('1+1')

sage: axiom('1+1')

Type: PositiveInteger
sage: exit
Exiting SAGE (CPU time 0m0.06s, Wall time 0m33.20s).
Exiting spawned Axiom process.
page@sage:~$ which sage
/usr/local/bin/sage

--------

This result is typical of the failure due to readline/clisp
synchronization problems on some platforms. The only solution I have
for this involves calling FriCAS in such a way as to defeat readline
in './devel/sage-main/sage/interfaces/axiom.py' as follows:

Expect.__init__(self,
name = 'axiom',
prompt = '\([0-9]+\) -> ',
command = "sh -c 'axiom -nox -noclef | cat'",

Although it generates more processes than should be required to do the
job, perhaps this change should be included in the next release?

On Sun, Aug 31, 2008 at 11:11 PM, Mike Hansen wrote:
> ...


> I don't think the interfaces are as much "magic" as you make them
> out to be.

Magic is only science that we don't understand, right? :-) I did not
mean to give the impression that I thought it was magic - only that I
felt some basic documentation in this area was missing. To this end
your comments below are very helpful.

> If you're interested in converting object from Sage to Axiom/FriCAS,
> then there are really only two methods you need to worry about --
> _axiom_ and _axiom_init_. _axiom_init_ method just returns a
> string used to construct self in Axiom. For example, say we have
>
> class Foo(SageObject):
> def __init__(self, n):
> self.n = int(n)
> def _axiom_init_(self):
> return str(self.n)
>
> Then I can do
>
> sage: a = Foo(2); a
> <class '__main__.Foo'>
> sage: axiom(a)
> 2
> sage: axiom(a).type()
> PositiveInteger
>

Thanks! So the point is that we can obtain the string representation
of some Sage object by calling 'str' and often this string can be
passed directly to the Axiom interpreter. I think that is a good
thing, but of course whether or not this works will depend on the type
inferences done by the interpreter. For example:

sage: K = FiniteField(2)
sage: k=K(1)
sage: k.parent()
Finite Field of size 2
sage: k+1
0
sage: k_ax = axiom(k)
sage: k_ax.type()
PositiveInteger
sage: k_ax+1
2

Something is wrong here! In Axiom we do have an appropriate type:

sage: k_ax2=axiom('1$FiniteField(2,1)')
sage: k_ax2.type()
FiniteField(2,1)
sage: k+1
0

Obviously the default conversion from a string is not correct. How can
we make the conversion from Sage to Axiom smarter in this case? Does
it mean that we need to override the _axiom_init_ method with
something more appropriate in some more specific class in Sage? I see
that:

sage: k?
Type: IntegerMod_int
Base Class: <type 'sage.rings.integer_mod.IntegerMod_int'>
String Form: 1
Namespace: Interactive
Docstring:

Elements of Z/nZ for n small enough to be operated on in 32 bits

AUTHORS:
-- Robert Bradshaw (2006-08-24)

So should we add _axiom_init_ to IntegerMod_int class? Something like this?

def _axiom_init_(self):
return str(self.n)+'::FiniteField(%d,1)'%n

where do I get a value for n?

But I notice that:

sage: k=IntegerModRing(2)(1)
sage: k.parent()
Ring of integers modulo 2
sage: k?
Type: IntegerMod_int
Base Class: <type 'sage.rings.integer_mod.IntegerMod_int'>
String Form: 1
Namespace: Interactive
Docstring:

Elements of Z/nZ for n small enough to be operated on in 32 bits

AUTHORS:
-- Robert Bradshaw (2006-08-24)

and also that in Axiom we have 'IntegerMod(2)' as distinct from
"FiniteField(2,1)'. Both Sage and Axiom distinguish between the ring
and the field, so maybe IntegerMod_int is not the right place for
_axiom_init_ since that would make it a field in all cases.

Maybe _axiom_init_ has to come from the Sage parent? How do I do that?

This is the kind of thing that still seems a little mysterious to me ...

> For more complicated things, the _axiom_ method takes in an Axiom


> interface object and returns self constructed in Axiom.
>
> class Foo(SageObject):
> def __init__(self, n):
> self.n = int(n)
> def _axiom_(self, axiom):
> return axiom(str(self.n))
>
> This behaves the same as above.
>

This form seems obscure to me. What is an "Axiom interface object"?
Why/How does this code behave the same way as the first example?

> The Macualay2 interface in sage/interfaces/macaulay2.py has some
> good examples of moving objects back and forth between systems.
>
> Anyway, I did some work on the Axiom interface today such as
> doctesting it, removing broken code, adding tab completion, etc.
> You can see my changes at
> http://trac.sagemath.org/sage_trac/ticket/4028

Great. I have applied these changes to my test version of axiom interface.

> Things like the online help didn't work with either the fricas spkg
> or just on a local copy, but I'd be more than happy to help adding
> that functionality (as well as anything else).
>

Thanks for your work! I hope it will attract more developers
interested in the Axiom interface in Sage.

Regards,
Bill Page.

Mike Hansen

unread,
Sep 1, 2008, 8:11:28 PM9/1/08
to fricas...@googlegroups.com
Hello,

> Although it generates more processes than should be required to do the
> job, perhaps this change should be included in the next release?

I think the issue on sage.math is just due to the installation of
Axiom installed in "system installation" of Sage. Michael Abshoff is
going to install the FriCAS 1.0.3 spkg there so it shouldn't be an
issue in the near future.

> Thanks! So the point is that we can obtain the string representation
> of some Sage object by calling 'str' and often this string can be
> passed directly to the Axiom interpreter. I think that is a good
> thing, but of course whether or not this works will depend on the type
> inferences done by the interpreter. For example:

If neither _axiom_ or _axiom_init_ are defined for the object (in its
class or superclasses), then it falls back to just trying to send the
string representation of the Sage object to see if that works. For
example, if you do

sage: axiom(QQ)
Traceback (most recent call last):
...
TypeError: sage0 := Rational Field
...

After adding an _axiom_init_ to sage/rings/rational_field.py, we get

sage: axiom(QQ)
Fraction Integer


> Obviously the default conversion from a string is not correct. How can
> we make the conversion from Sage to Axiom smarter in this case? Does
> it mean that we need to override the _axiom_init_ method with
> something more appropriate in some more specific class in Sage?

Yep. It's just a matter of putting it in the right place on the class
hierarchy.

> So should we add _axiom_init_ to IntegerMod_int class? Something like this?

...


> Maybe _axiom_init_ has to come from the Sage parent? How do I do that?
> This is the kind of thing that still seems a little mysterious to me ...


For IntegersMod in Sage, the right place was in the
IntegerMod_abstract class. I put a patch up with these at
http://trac.sagemath.org/sage_trac/ticket/4036 .


>
>> For more complicated things, the _axiom_ method takes in an Axiom
>> interface object and returns self constructed in Axiom.
>>
>> class Foo(SageObject):
>> def __init__(self, n):
>> self.n = int(n)
>> def _axiom_(self, axiom):
>> return axiom(str(self.n))
>>
>> This behaves the same as above.
>>
>

> This form seems obscure to me. What is an "Axiom interface object"?

By "Axiom interface object", I mean the same type of object as the
"axiom" you use at the command line.

sage: type(axiom)
<class 'sage.interfaces.axiom.Axiom'>

Each of these object corresponds to a different Axiom session. For example,


sage: a1 = Axiom()
sage: a2 = Axiom()
sage: a1.set('x', '2')
sage: a1.get('x')
'2'
sage: a2.get('x')
'x'
sage: a2.get('x')
'3'
sage: a1.get('x')
'2'


> Why/How does this code behave the same way as the first example?

When you call axiom(a), it finds the _axiom_ method and calls it. All
the function has to do is construct and return the appropriate object
in the Axiom session that is passed in. Since you have the actual
object, you have a lot more flexibility than if you just had to return
a string. (Think defining functions, etc.)

--Mike

Bill Page

unread,
Sep 1, 2008, 10:21:36 PM9/1/08
to fricas...@googlegroups.com
On Mon, Sep 1, 2008 at 8:11 PM, Mike Hansen wrote:

>
> Bill Page wrote:
>> Although it generates more processes than should be required to
>> do the job, perhaps this change should be included in the next
>> release?
>
> I think the issue on sage.math is just due to the installation of
> Axiom installed in "system installation" of Sage. Michael Abshoff is
> going to install the FriCAS 1.0.3 spkg there so it shouldn't be an
> issue in the near future.
>

I just tested this with sage-3.1.1 on sage.math and it works without
the readline hack. Great! :-)

Was there a specific fix to expect, axiom.py or clisp that corrected
the problem? What versions of Sage are known to work with FriCAS 1.0.3
without this problem?

Regards,
Bill Page.

Mike Hansen

unread,
Sep 2, 2008, 12:15:37 AM9/2/08
to fricas...@googlegroups.com
> Was there a specific fix to expect, axiom.py or clisp that corrected
> the problem? What versions of Sage are known to work with FriCAS 1.0.3
> without this problem?

No, it was just that FriCAS wasn't installed and that installation of
Sage was using an old version of Axiom.

--Mike

mabshoff

unread,
Sep 2, 2008, 12:26:52 AM9/2/08
to FriCAS - computer algebra system


On Sep 1, 9:15 pm, "Mike Hansen" <mhan...@gmail.com> wrote:
> > Was there a specific fix to expect, axiom.py or clisp that corrected
> > the problem? What versions of Sage are known to work with FriCAS 1.0.3
> > without this problem?

Yes, it seems. We will likely always test with the current FriCAS spkg
when running the Axiom doctests since that fork is the one we usually
have a current spkg for. OpenAxiom as well as the original Axiom could
also be tested if we had an spkg - but since they don't seem to be
easily installable in parallel at least I will stick to FriCAS for
now.

> No, it was just that FriCAS wasn't installed and that installation of
> Sage was using an old version of Axiom.
>
> --Mike

Well, it was a 2007 release.

Cheers,

Michael

Bill Page

unread,
Sep 2, 2008, 9:34:32 AM9/2/08
to fricas...@googlegroups.com

???

But previously I and several other people on this list reported that
the axiom interface in Sage **using fricas-1.0.3** failed without the
hack. It seemed to work on some versions of linux/architecture and not
on others.

Regards,
Bill Page.

Bill Page

unread,
Sep 2, 2008, 9:41:08 AM9/2/08
to fricas...@googlegroups.com
On Tue, Sep 2, 2008 at 12:26 AM, mabshoff wrote:
>
> On Sep 1, 9:15 pm, Mike Hansen wrote:
>...

>> No, it was just that FriCAS wasn't installed and that installation of
>> Sage was using an old version of Axiom.
>>
>> --Mike
>
> Well, it was a 2007 release.
>

Then it probably wasn't compiled using clisp. GCL has an option to
build without readline support. There is also the issue of whether
only the main Axiom program (AXIOMsys) or the sman "shell" program
(axiom) is started. These behave different initial prompt sequences
which affect the pexpect configuration. The problem that I reported
earlier occurs using FriCAS compiled using clisp in which readline
cannot be easily disabled.

Anyway, I agree that we only should be testing with the fricas package
installed and not any pre-existing Axiom installation.

Regards,
Bill Page.

Reply all
Reply to author
Forward
0 new messages