[Proposal] Mutable expressions in SymPy

60 views
Skip to first unread message

Francesco Bonazzi

unread,
Mar 24, 2018, 11:28:16 AM3/24/18
to sympy
I was considering the possibility of mutable expressions in SymPy.

Currently expressions such as Add and Mul are immutable once the class constructor has been called and modifying their content requires the object to be re-built.

I have tried to write a draft to implement the builder pattern, for example with an AddBuilder object:
https://github.com/Upabjojr/sympy/blob/f4e26d9a7314ad5093b97c7e84a581f523d38efb/sympy/core/dispatchers_add.py#L8

The builder class is mutable and would be added elements until it is passed to some method that builds the underlying class, Add in this case.

At this point construction of objects could be done through multiple dispatching an append method to the builder class. Unfortunately this makes everything much more complicated, as every object that potentially needs to subclass __add__ could potentially need its own builder object.

There have been other attempts at creating mutable corresponding objects, e.g.:
https://github.com/sympy/sympy/blob/master/sympy/unify/core.py#L24

Unfortunately once the SymPy expression is deconstructed, it remains unusable.

Proposal:what about allowing SymPy objects to exist in a mutable state? For example, introduce a mutable=False option to Basic, so that if mutable is set to True, there could be a way to edit the args.

There could be potential problems with the hashing. One possible solution could be not to allow immutable objects to contain mutable ones.

Aaron Meurer

unread,
Mar 24, 2018, 12:17:06 PM3/24/18
to sy...@googlegroups.com
Assumedly the point of this is for performance, so that something like
(x + y + z) + w doesn't require rebuilding x + y + z.

I've thought for some time that Add should save its coeff: term
dictionary, to make further additions faster. I'm not sure if this
requires mutability.

I believe mutability can work for builder classes, but it requires
very careful bookkeeping, to invalidate anything pointing to it once
it mutates. And as you noted, it can't be included in the hash of any
mutable object. So in general, the mutable builder should be
considered a cached preprocessing step. If it exists, and hasn't been
invalidated, it can be used. Otherwise, it should be rebuilt from
scratch.

Aaron Meurer
> --
> You received this message because you are subscribed to the Google Groups
> "sympy" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to sympy+un...@googlegroups.com.
> To post to this group, send email to sy...@googlegroups.com.
> Visit this group at https://groups.google.com/group/sympy.
> To view this discussion on the web visit
> https://groups.google.com/d/msgid/sympy/ecc4eaa9-28dc-44a4-9ed0-402adea432e5%40googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.

Francesco Bonazzi

unread,
Mar 24, 2018, 12:48:33 PM3/24/18
to sympy


On Saturday, 24 March 2018 17:17:06 UTC+1, Aaron Meurer wrote:
Assumedly the point of this is for performance, so that something like
(x + y + z) + w doesn't require rebuilding x + y + z.

Exactly.


I've thought for some time that Add should save its coeff: term
dictionary, to make further additions faster. I'm not sure if this
requires mutability.

Yes the term dictionary is actually a good representation.


I believe mutability can work for builder classes,

The builder classes will make the base code way too complicated. Suppose we get a new contributor/end-user in the future who wants to define some new algebraic group: he might give up if he has to go through builder classes.

but it requires very careful bookkeeping, to invalidate anything pointing to it once it mutates.

Wolfram Mathematica allows expressions to be mutated. They have a mechanism to update linked expressions automatically (I believe it's called reactive programming).

And as you noted, it can't be included in the hash of any
mutable object. So in general, the mutable builder should be
considered a cached preprocessing step.

I want to explore the possibility of not using the builder at all. Just use the same object in build mode. Example:

>>> a = Add(mutable=True)
>>> a.args
[]
>>> a.args.append(3)
>>> a.args.append(x)
3 + x
>>> a.args.extend([y, y])
>>> a
3 + x + y**2
>>> a.args
[3, x, y**2]
>>> a.as_immutable().args
(3, x, y**2)

That is, something similar to MutableMatrix and ImmutableMatrix, just with the same class.

Isuru Fernando

unread,
Mar 24, 2018, 12:54:27 PM3/24/18
to sy...@googlegroups.com
On Sat, Mar 24, 2018 at 11:16 AM, Aaron Meurer <asme...@gmail.com> wrote:
Assumedly the point of this is for performance, so that something like
(x + y + z) + w doesn't require rebuilding x + y + z.

I've thought for some time that Add should save its coeff: term
dictionary, to make further additions faster. I'm not sure if this
requires mutability.

That's exactly what symengine does. It keeps the internal dictionary structure and uses the dictionary. This makes .args a bit slower in symengine, but with caching that should go away. Note that you'd need a dictionary and a vector to keep the non-commutative and unevalauted objects.

Isuru


> To post to this group, send email to sy...@googlegroups.com.
> Visit this group at https://groups.google.com/group/sympy.
> To view this discussion on the web visit
> https://groups.google.com/d/msgid/sympy/ecc4eaa9-28dc-44a4-9ed0-402adea432e5%40googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.

--
You received this message because you are subscribed to the Google Groups "sympy" group.
To unsubscribe from this group and stop receiving emails from it, send an email to sympy+unsubscribe@googlegroups.com.

To post to this group, send email to sy...@googlegroups.com.
Visit this group at https://groups.google.com/group/sympy.

S.Y. Lee

unread,
Oct 5, 2021, 9:38:12 AM10/5/21
to sympy
I'm not sure if you have heard about, or familiar with term graph,
but I think that this can have the potential to generalize Basic object and make it to be a more efficient form, without 'mutability' trick to reduce the time and space complexity.


> To post to this group, send email to sy...@googlegroups.com.
> Visit this group at https://groups.google.com/group/sympy.
> To view this discussion on the web visit
> https://groups.google.com/d/msgid/sympy/ecc4eaa9-28dc-44a4-9ed0-402adea432e5%40googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.

--
You received this message because you are subscribed to the Google Groups "sympy" group.
To unsubscribe from this group and stop receiving emails from it, send an email to sympy+un...@googlegroups.com.
Reply all
Reply to author
Forward
0 new messages