axiom-developer
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Axiom-developer] CAS for the masses


From: Ondrej Certik
Subject: Re: [Axiom-developer] CAS for the masses
Date: Thu, 29 Mar 2007 14:32:04 +0200

Thanks for your explanation - I didn't know there is a distinction
between symbolic manipulation (computation) and computer algebra
system.  But it makes sense.

I also think what can be done in Aldor can be pretty much done in
Python and vice versa. Ralf sent me a code that he thinks cannot be
easily rewritten in Python, but I still didn't have time to get
through it. But as you know Python - what exactly can be done in Aldor
that cannot be done in Python?

Ondrej

On 3/29/07, Bill Page <address@hidden> wrote:
On March 28, 2007 7:42 AM Ondrej Certik wrote:
> ...
> Expression tree (Add, Mul,...) are very low level types, and
> you have many algorithms, that work with high level types like
> Polynomial, Fraction, ODE, DAE, PDE, etc. I understand that.
>

I think that there may be two problems with this discussion so
far.

I think the first problem is that Axiom developers and Python
programmers may not appreciate just how similar SPAD (or Aldor)
and Python really is. Although Python is dynamically typed
while Axiom is statically typed, both Python classes and Axiom
domains support object-oriented programming in similar ways.

I have been promising myself for some time now to take the time
to write a more accessible introduction. So here is at least a
start at this.

A draft containing the examples below is available on the Axiom
wiki as:

http://wiki.axiom-developer.org/SandBoxSPADForPython

For example, in Python we might define a simple class implementing
complex numbers something like the following:

### file: complex.py
class Complex:
    "Example to demonstrate SPAD equivalent of Python Classes"
    def __init__(self, realpart, imagpart):
        self.r = realpart
        self.i = imagpart
    def real(self):
      return self.r
    def imag(self):
      return self.i
    def __str__(self):
      if self.i<0:
        return "%g - i %g"%(self.real(),-self.imag())
      else:
        return "%g + i %g"%(self.real(),self.imag())
    def __coerce__(self,b):
      if isinstance(b,Complex):
         return(self,b)
      else:
         return(self,Complex(b,0))
    def __add__(self,b):
      return Complex(self.real()+b.real(), self.imag()+b.imag())
    def __mul__(self,b):
      return Complex(self.real()*b.real() - self.imag()*b.imag(),
                     self.real()*b.imag() + self.imag()*b.real())
###

>>> x = Complex(3.0, -4.5)
>>> y = Complex(-2.0, 5.4)
>>> print x
  3.0 - i 4.5
>>> print x+y
  1 + i 0.9
>>> print x*y
  18.3 + i 25.2
>>> print x+1.0
  4 - i 4.5

------

You can find details of how operator overloading in Python is done
by using special names like __op__ explained here:

http://docs.python.org/ref/customization.html

In SPAD a domain equivalent to this Python class would be:

--- file: complex.spad
)abbrev domain CMPLXS ComplexSpad
+++ Example of SPAD equivalent of Python Class
ComplexSpad(): with
    new: (Float,Float) -> %     ++ __init__   in Python
    coerce: Float -> %          ++ __coerce__ in Python
    real: % -> Float            ++ real       in Python
    imag: % -> Float            ++ imag       in Python
    _+: (%,%) -> %              ++ __add__    in Python
    _*: (%,%) -> %              ++ __mul__    in Python
    coerce: % -> OutputForm     ++ __str__    in Python
  == add
    Rep ==> Record(r:Float,i:Float)
    import Rep, OutputForm, Symbol

    new(realpart:Float,imagpart:Float):% == [realpart,imagpart] pretend %
    coerce(x:Float):% == new(x,0)
    real(x:%):Float == (x pretend Rep).r
    imag(x:%):Float == (x pretend Rep).i
    _+(x:%, y:%):% ==
      new(real(x)+real(y), imag(x)+imag(y))
    _*(x:%, y:%):% ==
       new(real(x)*real(y) - imag(x)*imag(y),
           real(x)*imag(y) + imag(x)*real(y))
    coerce(x:%):OutputForm ==
      if imag(x)<0 then
        real(x)::OutputForm - outputForm("i"::Symbol) *
(-imag(x))::OutputForm
      else
        real(x)::OutputForm + outputForm("i"::Symbol) * imag(x)::OutputForm
---

I have indicated the equivalent Python function by the ++
comment in each export.

This would be compiled in Axiom using the command:

(1) -> )compile complex.spad
   Compiling AXIOM source code from file
      C:/Documents and Settings/Administrator.ASUS/My Documents/complex.spad
      using old system compiler.
   CMPLXS abbreviates domain ComplexSpad
   ...

Then we may use this new domain like this:

(1) -> x := new(3.0, -4.5)$ComplexSpad

   (1)  3.0 - i 4.5
                                                Type: ComplexSpad
(2) -> y := new(-2.0, 5.4)$ComplexSpad

   (2)  - 2.0 + i 5.4
                                                Type: ComplexSpad
(3) -> x+y

   (3)  1.0 + i 0.9
                                                Type: ComplexSpad
(4) -> x*y

   (4)  18.3 + i 25.2
                                                Type: ComplexSpad
(5) -> x+1.0

   (5)  4.0 - i 4.5
                                                Type: ComplexSpad

There are a lot of good references to Python classes on the web
and in numerous books. Although the emphasis is on numerical
applications of Python I think a good introduction for Axiom
developers might be the following book:

  Python Scripting for Computational Science
  by Langtangen, Hans Petter
  2nd ed., 2006, XXIV, 736 p., 33 illus., Hardcover
  ISBN: 978-3-540-29415-3

http://www.springer.com/sgw/cda/frontpage/0,11855,1-40109-22-83511316-0,00.h
tml

See especially section 8.6 on Classes.

Or for a more detailed and technical description of Python
classes with a C++ flavour you could try:

http://docs.python.org/tut/node11.html

For Python programmers the best introduction to domains and
categories in Axiom is probably the Axiom book:

http://wiki.axiom-developer.org/public/book2.pdf#page=940

You might want to consult the Aldor user's guide:

http://www.aldor.org/docs/HTML/index.html

Most of what is written here about Aldor also applies to the SPAD
programming language in Axiom. See especially chapter 7 on Types:

http://www.aldor.org/docs/HTML/chap7.html

Unfortunately this document might be overly technical as an
introduction and uses terms that might not be very familiar to
Python programmers.

> The question is - how the Axiom converts from the low level
> representation to the high level?
>

Now this question suggests to me the second problem. What we are
missing here is the distinction between symbolic computation and
computer algebra that has been discussed by Steven Watt (the
developer of Aldor) in several recent papers. See especially his
paper:

Making Computer Algebra More Symbolic

http://www.csd.uwo.ca/~watt/pub/reprints/2006-tc-sympoly.pdf

Abstract

This paper is a step to bring closer together two views of computing
with mathematical objects: the view of "symbolic computation" and
the view of "computer algebra". Symbolic computation may be seen as
working with expression trees representing mathematical formulae
and applying various rules to transform them. Computer algebra may
be seen as developing constructive algorithms to compute algebraic
quantities in various arithmetic domains, possibly involving
indeterminates. Symbolic computation allows a wider range of
expression, while computer algebra admits greater algorithmic
precision. ...

-----

So what Axiom does is basically "computer algebra" in the above
sense while what many other so called computer algebra systems
are doing is really better described at "symbolic computation".
What makes things a little fuzzy here is that Axiom also has an
algebraic domain called Expression which has many (but not all!)
of the characteristics as symbolic computation in these other
systems.

But from this point of view what Axiom is doing is fundamentally
different than what I think SymPy is doing. SymPy is doing
symbolic computation using a set of Python domains that implement
an Expression tree structure. But what Axiom is doing with it's
Expression domain is trying to define a mathematical object
starting with rational functions (Fraction Polynomial) and adding
a large number of special functions.

> A place that occurs to me to do it is just right after the
> evaluation to the canonical form:
>
> like Add(x,x) automatically converts to Mul(2,x)  and here, at
> this place, the CAS would check the expression and says: hey -
> the Mul(2,x) is a polynomial, let's return a Polynomial class
> instead.
>
> This would make sense to me, and we could do it in SymPy as well.
>

I think what Axiom is doing is very different.

Regards,
Bill Page.







reply via email to

[Prev in Thread] Current Thread [Next in Thread]