Open GoogleCodeExporter opened 9 years ago
Inspired by the latest post to sympylist. :)
I, as the user, I don't see why I would need this feature and why I should care
about
the internal representation. Why do you think it's useful?
Original comment by ondrej.c...@gmail.com
on 30 Oct 2007 at 10:08
Indeed, this issue is raised from users feedback. The last one is from
sympylist.
The first one comes from Simula where people typically use pyginac and
deal with huge but simple expression trees that can easily take all
the memory that computer has. Say, adding two huge trees would create
a third huge tree.
a = 2 + ...
b = 3 + ...
a + b -> 5 + ... + ...
A typical task with these expressions is to
generate C/C++ code with minimal number of operations.
Therefore, it is sometimes preferable not to carry out
elementary simplifications but keep original expressions in
an Add instance:
a + b -> (2 + ...) + (3 + ...)
and that takes almost no memory.
Original comment by pearu.peterson
on 30 Oct 2007 at 10:27
So is it a question of memory intensive Add.canonize()?
Because simplifying the expression usually reduces the number of terms.
Original comment by ondrej.c...@gmail.com
on 30 Oct 2007 at 10:44
No. Consider
s1 = 2 + a + b
s2 = 3 + c + d
s1 + s2 -> 5 + a + b + c + d
Original comment by pearu.peterson
on 30 Oct 2007 at 10:48
Compared to:
s1 = 2 + a + b
s2 = 3 + c + d
s1 + s2 -> 2 + 3 + a + b + c + d
?
I am missing the point.
Original comment by ondrej.c...@gmail.com
on 30 Oct 2007 at 10:59
This should be compared to unevaluated sum:
s1 + s2 -> s = (2 + a + b) + (3 + c + d)
where the following properties hold:
len(s)==2
s[0]==s1
s[1]==s2
Original comment by pearu.peterson
on 30 Oct 2007 at 11:02
ok. So the properties of
s1 = 2 + a + b
s2 = 3 + c + d
s1 + s2 -> s3=5 + a + b + c + d
are:
len(s3) = 5
s3[0] = 5
s3[1] = a
...
It seems to me that s3 consumes less memory than s.
Original comment by ondrej.c...@gmail.com
on 30 Oct 2007 at 11:16
Ah, you mean the memory of "s1+s2+s" as compared to "s1+s2+s3"? Yeah, the sum
of all
those are indeed better for the s1+s2+s case, since it's reusing the memory of
s1,
s2. Is this the point?
Original comment by ondrej.c...@gmail.com
on 30 Oct 2007 at 11:18
Yes, the point is not to create no additional huge
expressions but to reuse the pointers of these huge expressions
to form a sum.
Original comment by pearu.peterson
on 30 Oct 2007 at 12:17
One one hand, I think this feature should somehow be supported in SymPy. On the
other
hand, symbolic arithmetic without simplifications is trivial to implement
Lisp-style
in Python:
class sym(tuple):
def __add__(self, other): return sym((self, '+', other))
def __radd__(self, other): return sym((other, '+', self))
def __mul__(self, other): return sym((self, '*', other))
def __rmul__(self, other): return sym((other, '*', self))
def __repr__(self):
if len(self) == 1:
return str(self[0])
return "(%r %s %r)" % self[:]
x = sym('x')
y = sym('y')
x + 3*(x+y) + 5*y
(You might want to switch to a prefix representation to support more complicated
operations.)
It could easily be implemented in a stand-alone module.
Original comment by fredrik....@gmail.com
on 30 Oct 2007 at 12:53
Another idea would be to introduce parametric symbols (I think ginac has
something similar):
class ParametricSymbol(Symbol):
def __new__(cls, name, parameter):
obj = Symbol.__new__(cls, name)
obj.parameter = parameter
return obj
def expand(self):
return self.parameter.expand()
s1 = Symbol('s1',2+a+b)
s2 = Symbol('s2',3+c+d)
s = s1 + s2
Original comment by pearu.peterson
on 30 Oct 2007 at 1:01
For me, unevaluated lisp-style symbolic trees could be useful, when preparing
lecture materials, slides, etc.
e.g. if I want to show the simplification process itsel like:
1 + 2 = 3
4 + 9 = 13
1 + 6 = 7
...
or
first_term + second_term = (first+second evaluated)
then I'll use something like constructing an expression via usual syntax like
Basic.canonize_push(False) # XXX ugly
e = e1 + e2
print e, '=', e.canonize()
Original comment by kirill.s...@gmail.com
on 30 Oct 2007 at 5:42
If I've misunderstood the purpose of unevalulated instances as Pearu proposed,
please do ignore this comment. But....
In Maple, I could do:
a:= b+c;
b:= 1;
c:= 2;
and then evaluate a to find it's equal to 3. *Then*, I could type:
b:= x;
c:= y;
and evaluate a to find it's now equal to (x+y).
Do you consider this feature of Maple, Mathematica, YACCAs etc to be related to
these 'unevaluated instances'?
This is a feature I would like to have: the ability to express a mathematical
relationship which persists as other values change, *without* the need to
define a
function each time (i.e. without having to replace 'a' in my example with a
function) into a function each time.
I'm used to this from other computer algebra systems and it would certainly be
useful for my work.
- Has this been considered for Sympy at all?
- Is it too unPythonic?
- If unevaluated instances are implemented, would / could this be supported by
them?
Many thanks for any reply.
Best regards,
andy
Original comment by and...@hotmail.com
on 31 Oct 2007 at 12:56
Python itself does not support idioms like Maple above.
Also, in sympy all symbolic objects has to be immutable objects.
So, the answer to this proposal is pretty much just 'not-possible'.
Original comment by pearu.peterson
on 31 Oct 2007 at 1:20
Pearu,
Thanks for your reply....
Having thought about it, I can probably obtain what I want by using functions
with
zero arguments. It's much simpler than a full function with an argument for
each of
the variables in the equation :-). Also, the up-to-date values of the variables
within the expression will get pulled in through Python's scoping rules.
There's an example below for simple addition.
(I haven't had time to see if this works with sympy functions and sympy Lambdas
yet -
as I don't have access to a machine I can load sympy on today.....)
Best regards,
andy
Python 2.2.3 (#1, Aug 8 2003, 08:44:27)
[GCC 3.2.3 20030502 (Red Hat Linux 3.2.3-13)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>>
>>> def a():
... return c + b
...
>>> b=2
>>> c=4
>>> a()
6
>>> b=5
>>> a()
9
>>> c='f'
>>> b='g'
>>> a()
'fg'
Original comment by and...@hotmail.com
on 2 Nov 2007 at 1:24
Nice idea. Here is an extension of it (this requires sympycore):
>>> from sympy import *
>>> def a(locals=locals()): return sympify('c+d',locals=locals)
...
>>> a()
c + d
>>> c=4
>>> a()
4 + d
>>> c=5
>>> a()
5 + d
>>> c='c'
>>> a()
c + d
Original comment by pearu.peterson
on 2 Nov 2007 at 1:31
See also releated thread in sympy mailing list:
http://groups.google.com/group/sympy/t/454584a2bea22672
The question of having noun and verb forms of operations
seems relevant. Currently we have only classes of verb kind.
To have also noun forms, there seems two options: (i) add
a flag `canonize=True` to operation constructors or (ii) derive
verb type of classes from noun type of classes by overwriting
their canonize() methods (that simply return None) with canonize()
methods that performs expression canonization operations.
Here follows a proposed naming convention (in case noun kind
of classes will be implemented):
<VerbClass> - <NounClass>
Add - Addition
Mul - Multiplication
Pow - Exponentation
Sin - Sine
Cos - Cosine
Tan - Tangent
Union - ??
Intersection - ??
etc.
The options (i) could be useful in algorithms that produce input
to operation classes in canonical form and using canonize=False
would avoid unnecessary computation. However, other codes may
assume that an operation instance is in a canonical form and
take an advantage of it - this might introduce incorrect results
when this assumptions turns out to be invalid. So, (ii) option
seems more robust.
Original comment by pearu.peterson
on 15 Nov 2007 at 6:09
Original issue reported on code.google.com by
pearu.peterson
on 30 Oct 2007 at 9:08