Details:
The reason I want automatic evaluation is that I am working on some
hackish implementation of <some math object> and I have a ton of
```ImmutableMatrix(Matrix(instance_of_MatrixExpr))``` snippets. I need
ImmutableMatrix because of the implementation of __hash__. In another
thread I have posed a related question.
<some math object> in my case is quantum field theory tensors in Dirac
x Lorentz space
--
You received this message because you are subscribed to the Google Groups "sympy" group.
To post to this group, send email to sy...@googlegroups.com.
To unsubscribe from this group, send email to sympy+un...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/sympy?hl=en.
> Also, you should be able to
> turn ImmutableMatrix(Matrix(instance_of_MatrixExpr)) into
> just ImmutableMatrix(instance_of_MatrixExpr).
Thanks for that. I was fairly sure I tried it but obviously I am mistaken.
Also, sympify now works with ImmutableMatrices but it still fails on
MutableMatrices. Is there a fundamental reason behind that?
Something like this seems good enough:
In [9]: Add(1,2,evaluate=False)
Out[9]: 1 + 2
On a related note. At the moment mutability is contagious. I would
rather have it other way. Have I missed any discussions on this topic?
Also, sympify now works with ImmutableMatrices but it still fails on
MutableMatrices. Is there a fundamental reason behind that?
Couldn't we have contagious immutability for matrix*matrix, contagious
mutability for symbol*matrix / matrix*symbol and sympification towards
immutable?
It does not sound good. Basic*Mutable and Mutable*Basic should always
behave in the same way independently of what subclass of Basic we
have.
Aaron Meurer
Agreed.
> We should
> have separate subclasses to do each (UnevaluatedImmutableMatrix is
> probably better than ImmutableMatrix(evaluate=False)).
That will create a proliferation of classes. Mutable/Immutable and
Evaluated/Unevaluated is already four combinations; any additional
property would double the number of classes needed.
Yeah, I was thinking about that too. I guess we should determine what
should be a separate class and what can just be a property of the
class. I think immutability should definitely be a separate class,
because this is a fundamental property in Python. I'm not sure about
evaluation. Ronan's pointed out some of the issues that can come from
making it a property.
Also, as Matthew noted, I guess evaluation should really be a property
of the container object, not the object itself. So we wouldn't really
need an UnevaluatedImmutibleMatrix, just an UnevaluatedMatrixMul.
By the way, I think that an unevaluated Matrix would have to be
immutable, because that's how Mul (and hence MatrixMul) works. So
there are really only three types of classes.
Aaron Meurer
"Fundamental" is in the eye of the beholder.
There's a better litmus test: Do they have the same list of operations?
Require the operations the same preconditions, ensure the same
postconditions?
If yes, it's the same class. If no, it's a different class.
Of course, since we're *defining* the operations, we have considerable
leeway in making classes the same.
However, for (im)mutability, making the class interfaces the same does
not make any sense.
> I'm not sure about
> evaluation. Ronan's pointed out some of the issues that can come from
> making it a property.
>
> Also, as Matthew noted, I guess evaluation should really be a property
> of the container object, not the object itself. So we wouldn't really
> need an UnevaluatedImmutibleMatrix, just an UnevaluatedMatrixMul.
I'm not sure what exactly distinguishes an evaluated from an unevaluated
matrix, so I can't comment.
> By the way, I think that an unevaluated Matrix would have to be
> immutable, because that's how Mul (and hence MatrixMul) works. So
> there are really only three types of classes.
Sure, but the class proliferation will come soon enough.
Of course, sometimes the proliferation is worth the gains. Just make
sure it's really worth something.
I don't understand what you mean here.
Aaron Meurer
As I understand the main target to evaluate ImmutableMatrix by default
is to show the result of expression.
I agreed that it is better to see the result with in more convinient
form and key details.
Meanwhile at [1] was formulated arguments contra, and pro unevaluation
variant. I am warry why they are ignored.
Nevertheless, may be it is possible to join advantages of both variants
(non-evaluated by default and evaluated by default).
When I learn the sequences ans series I meet the similar problem, and
here are my suggestions:
For this we can just separate the task of showing of and the task
manipulation with expressions.
When I construct the expression (mul or add), I keep them in unevualeted
form as an expression, but every expression has `__getitem__` index,
which runs the calculation of desirable element (and, cache it).
If we work with such expressions in interactive mode, then printer
method form matrix used and it calls `__getitem__`, so we obtain the
readable answer.
Consider example (on example of ImmutableMatrix):
>>> a = ImmutableMatrix(3*eye(3))
# a <-- 3*ImmutableMatrix(...)
# here automatic simplification on the
# fly, which carring out common coeff.
# The "..." is written, because I don't know internal structure of the
# created object .
>>> b = 2*ImmutableMatrix(diag(1, 5, 6))
# b <-- 2*ImmutableMatrix(...)
>>> c = a*b
# c <-- 6*MatMul(ImmutableMatrix(...), ImmutableMatrix(...)
Note, so far we have not done any calculations with matrices.
No reasons for it.
We just construct the expression, simplify trivial things, if needed.
But if what to know (to show, or use in further calculations) then
result in readable form then we'll see:
>>> c[1:2]
30
>>> c
[6, 0, 0]
[0, 30, 0]
[0, 0, 36]
When we input "c[1:2]" then the
* `__getitem__ calls`
* the process of calculation of this element runs
(it is well-defined), which use only necessary calculations,
* then the result is cached,
* then it is returned and printed by printing system.
When we run "c", then (ordinary) printer for matrices is runs, which
also use __getitem__.
So, we can tune the printer system, and the expression behavior
independently during manipulation.
[1] http://code.google.com/p/sympy/issues/detail?id=3180
--
Alexey Gudchenko