extending the Expression class

40 views
Skip to first unread message

Steven Pollack

unread,
Jul 20, 2011, 8:02:49 PM7/20/11
to sage-support
Hi everyone,

I noticed that a thread was developed for this sort of thing (http://
groups.google.com/group/sage-support/browse_thread/thread/
d50dc3bc2bdbeab0/34798c0585fc034f?lnk=gst&q=nicolas&fwc=1#), but I'm a
newbie, and a lot of it went over my head.

Is there a simple to create a subclass of
sage.symbolic.expression.Expression?

Better yet, is there any documentation out there for building classes
inside Sage? I'm new to OOP, in general, and would love to see how
people have gone about working the OOP aspects of python into their
Sage workflow.

Thanks,

Steven

Burcin Erocal

unread,
Jul 21, 2011, 6:37:37 AM7/21/11
to sage-s...@googlegroups.com
Hi,

On Wed, 20 Jul 2011 17:02:49 -0700 (PDT)
Steven Pollack <stevenlawr...@gmail.com> wrote:

> I noticed that a thread was developed for this sort of thing (http://
> groups.google.com/group/sage-support/browse_thread/thread/
> d50dc3bc2bdbeab0/34798c0585fc034f?lnk=gst&q=nicolas&fwc=1#), but I'm a
> newbie, and a lot of it went over my head.
>
> Is there a simple to create a subclass of
> sage.symbolic.expression.Expression?

The main problem with subclassing Expression is that the result
returned from arithmetic is hardcoded to be an Expression again.

I quickly did a search and replace in the sage/symbolics directory to
pass the new class as an argument to the fast expression constructor
new_Expression_from_GEx. Here is the patch:

http://sage.math.washington.edu/home/burcin/subclass_expression.patch

After applying the patch the following works:

sage: class new_exp(Expression):
....: pass
....:
sage: t = new_exp(SR, x)
sage: t
x
sage: type(t)
<class '__main__.new_exp'>
sage: u = t*t
sage: type(u)
<class '__main__.new_exp'>
sage: u
x^2


Hope this helps.

Burcin

Steven Pollack

unread,
Jul 25, 2011, 11:03:04 AM7/25/11
to sage-support
Is the syntax for this class

t = new_exp(SR, symbolic_expression)?

So that sage: t returns symbolic_expression?

Second, I'm not entirely sure I understand how this patch was made,
let alone how to install it. I skimmed over
http://www.sagemath.org/doc/developer/patching_spkgs.html and
http://www.sagemath.org/doc/developer/producing_spkgs.html#chapter-spkg
but found the whole thing to be a bit over my head (I'm a newbie,
sorry).

Is there a series of instructions you could provide me for the
installation of your patch? I'm sure you're very busy, so I really do
appreciate the effort.

Thanks,

Steven


On Jul 21, 6:37 am, Burcin Erocal <bur...@erocal.org> wrote:
> Hi,
>
> On Wed, 20 Jul 2011 17:02:49 -0700 (PDT)
>

Robert Bradshaw

unread,
Jul 26, 2011, 3:03:41 AM7/26/11
to sage-s...@googlegroups.com
On Thu, Jul 21, 2011 at 3:37 AM, Burcin Erocal <bur...@erocal.org> wrote:
> Hi,
>
> On Wed, 20 Jul 2011 17:02:49 -0700 (PDT)
> Steven Pollack <stevenlawr...@gmail.com> wrote:
>
>> I noticed that a thread was developed for this sort of thing (http://
>> groups.google.com/group/sage-support/browse_thread/thread/
>> d50dc3bc2bdbeab0/34798c0585fc034f?lnk=gst&q=nicolas&fwc=1#), but I'm a
>> newbie, and a lot of it went over my head.
>>
>> Is there a simple to create a subclass of
>> sage.symbolic.expression.Expression?

Note that many of the low-level classes, such as Integers and perhaps
Expressions, were not designed with sublcassing in mind. YMMV, but
this is often a problem of OOP in general.

> The main problem with subclassing Expression is that the result
> returned from arithmetic is hardcoded to be an Expression again.
>
> I quickly did a search and replace in the sage/symbolics directory to
> pass the new class as an argument to the fast expression constructor
> new_Expression_from_GEx. Here is the patch:
>
> http://sage.math.washington.edu/home/burcin/subclass_expression.patch
>
> After applying the patch the following works:
>
> sage: class new_exp(Expression):
> ....:     pass
> ....:
> sage: t = new_exp(SR, x)
> sage: t
> x
> sage: type(t)
> <class '__main__.new_exp'>
> sage: u = t*t
> sage: type(u)
> <class '__main__.new_exp'>
> sage: u
> x^2

Any performance cost?

- Robert

Jason Grout

unread,
Jul 26, 2011, 10:57:52 AM7/26/11
to sage-s...@googlegroups.com
On 7/26/11 12:03 AM, Robert Bradshaw wrote:
> Note that many of the low-level classes, such as Integers and perhaps
> Expressions, were not designed with sublcassing in mind. YMMV, but
> this is often a problem of OOP in general.

I'm curious; could you write a sentence or two more about why this is
often a problem of OOP in general? I would have thought it would be a
strength of OOP in general.

Jason


Burcin Erocal

unread,
Jul 26, 2011, 2:54:43 PM7/26/11
to sage-s...@googlegroups.com

Without the patch:

sage: %timeit v = [-pi,-pi+1/100000..,pi]
5 loops, best of 3: 1.4 s per loop

With the patch:

sage: %timeit v = [-pi,-pi+1/100000..,pi]
5 loops, best of 3: 1.62 s per loop


Cheers,
Burcin

Burcin Erocal

unread,
Jul 26, 2011, 3:15:54 PM7/26/11
to sage-s...@googlegroups.com
On Mon, 25 Jul 2011 08:03:04 -0700 (PDT)
Steven Pollack <stevenlawr...@gmail.com> wrote:

> Is the syntax for this class
>
> t = new_exp(SR, symbolic_expression)?
>
> So that sage: t returns symbolic_expression?

t is an instance of new_exp, which inherits from Expression. The value
of the internal GiNaC object stored in both is determined by the second
argument.

You could define other member functions or store attributes in your
class. Though you need to take care what happens to the attributes
when you do any arithmetic.

sage: class new_exp(Expression):
def __init__(self, parent, value, attribute):
self.attr = attribute
super(self.__class__, self).__init__(parent, value)
....:
sage: t = new_exp(SR, x, 2)
sage: t
x
sage: t.attr
2
sage: t.new_method(5)
x - 5
sage: u = t+t
sage: u.new_method(5)
2*x - 5
sage: u.attr
<snip>
AttributeError: 'new_exp' object has no attribute 'attr'


sage: type(u)
<class '__main__.new_exp'>
sage: u

2*x
sage: v = u/2
sage: v.new_method(5)
x - 5
sage: v.attr
<snip>
AttributeError: 'new_exp' object has no attribute 'attr'

> Second, I'm not entirely sure I understand how this patch was made,
> let alone how to install it. I skimmed over
> http://www.sagemath.org/doc/developer/patching_spkgs.html and
> http://www.sagemath.org/doc/developer/producing_spkgs.html#chapter-spkg
> but found the whole thing to be a bit over my head (I'm a newbie,
> sorry).
>
> Is there a series of instructions you could provide me for the
> installation of your patch? I'm sure you're very busy, so I really do
> appreciate the effort.

You need to look at a different section of the guide:

http://sagemath.org/doc/developer/walk_through.html

Here is a quick summary:

- Go to your SAGE_ROOT, the base directory of your sage installation
- Go to the directory with the sage library sources
cd devel/sage
- import the patch into a patch queue
hg qimport <URL_of_patch>
- apply the patch
hg qpush
- go back to SAGE_ROOT
cd ../..
- build the library with changes
./sage -b
- start Sage and enjoy
./sage


Cheers,
Burcin

Steven Pollack

unread,
Jul 29, 2011, 11:43:18 AM7/29/11
to sage-support
Thanks for the explanation! I haven't had a chance to try installing
the patch (I got caught up taking care of some other side-projects),
however I can't thank you enough for the help.

I now have a new question (@Robert): if the Expression class wasn't
made with subclassing in mind, how did the makers of sage envision
users to build their own classes (while still utilizing expressions)?

I'm new to OOP, but the impression I'm (now) under is that without
Burcin's patch, we have to do something like:

class newObject():
def __init___(self, expression, *variables, **attributes):
[var('{0}'.format(variable)) for variable in
variables]
self.exp = expression
for options in attributes.items():
self.attr[option] = attributes(option)
?

Thanks,

Steven

On Jul 26, 3:15 pm, Burcin Erocal <bur...@erocal.org> wrote:
> On Mon, 25 Jul 2011 08:03:04 -0700 (PDT)
>

kcrisman

unread,
Jul 29, 2011, 3:07:40 PM7/29/11
to sage-support
Incidentally, if you and Burcin think this is worthwhile in general,
please feel free to make a Trac ticket so that it's easier for others
to test these ideas out. Thank you - looking forward to it!

- kcrisman

On Jul 29, 11:43 am, Steven Pollack <stevenlawrencepoll...@gmail.com>
wrote:

Steven Pollack

unread,
Aug 2, 2011, 3:23:17 PM8/2/11
to sage-s...@googlegroups.com
Weirdly enough, I'm not sure if this is so important, after all. It might be cleaner to just define a more basic Class, which takes expressions as attributes.

Doing arithmetic on these objects might get a little weird, but I'm sure the purpose of the object and the context of its creation will determine how that kind of situation will get handled. 

Thanks for all the help, everyone!

-Steven

Reply all
Reply to author
Forward
0 new messages