First off, pragmatically speaking, is there a reason why you need to use the 
core Mul instead of writing your own custom Mul for the quantum stuff?  I am 
just saying this because even though I agree that we need this change, changing 
anything in the core is very difficult and time consuming, because the code is 
so fragile, and you also have to pay close attention to speed concerns.  

Also, Mul is optimized for commutative arguments, with non-commutatives special 
cased (read "hacked in").  I am thinking it might be smarter to have separate 
NCMul for general non-commutatives anyway.  

So basically, these suggestions are on how to fix issue 1941, because as I see 
it, validating whether two objects can be multiplied together is just a special 
case of objects that combine with each other specially. 

On Jul 21, 2010, at 1:34 PM, Brian Granger wrote:

> Hi,
> 
> We are running into some issues with Mul in the quantum stuff.  There
> are two main things:
> 
> 1.  How Mul combines adjacent args.

This one may prove to be the more difficult of the two to solve, because of the 
way Python evaluates expressions like a*b*c.  Also, you have to consider that 
no matter how you try to make things work with __mul__ and __rmul__, it can 
always be thrown off with something like a*(b*c).  Option 1 alone might not 
work for this reason.  

> 2.  How Mul decides if two adjacent args can be multiplied.
> 
> For now, let's focus on the second of these.  The difficulty right now
> is that Mul allow any two Exprs to be multiplied.  But in quantum
> mechanics, certain things can't be multiplied.  For example, the
> following don't make sense:
> 
> Ket('a')*Operator('O)
> Operator('O')*Bra('a')
> 
> We would like to add logic to check for these cases into the
> __mul__/__rmul__ methods of Operator and State.  But, this logic will
> never be triggered in situations like this:
> 
> Bra('a')*Ket('a')*Operator('O) = Mul(Bra('a'), Ket('a'))*Operator('O')
> 
> Because the Mul*Operator triggers Mul.__mul__ (which has no validation
> for Operators or States) rather than Operator.__rmul__.
> 
> I see two ways out of this:
> 
> 1.  Handle this like numpy arrays that have an __array_priority__
> attribute.  The idea is that the array having the highest numeric
> value of the __array_priority__ attribute would have its __mul__ or
> __rmul__ method called.  This would make it possible for:
> 
> Mul(Bra('a'), Ket('a'))*Operator('O') to trigger Operator.__rmul__
> 
> This solution would not required changes to Mul, only to the __mul__
> and __rmul__ methods of Expr.  It would also require going through
> sympy and adding the priority atttributes to relevant classes.
> 
> 2.  To add a new set of methods to Expr that are used by Mul to
> validate if two things could be multiplied.  This is more flexible.  I
> propose methods like:
> 
> _validate_mul(self, other)
> _validate_rmul(self, other)
> 

It seems to me like you would have to have both options.  The _validate_mul (or 
combine_mul, as Ondrej called it in 
http://github.com/certik/sympyx/commits/handler) would have to be there to 
handle the special multiplication behaviors.  But I think you also need some 
kind of priority system to break ties of more than one object in the Mul has 
such a method.  If you just do validation (no combining), then maybe you could 
do without option 1, except you will have to accept the fact that _validate_mul 
will always be called before _validate_rmul. 

By the way, it is more general to send to the combination method the whole list 
of objects that have been gathered together already.  This is for things that 
combine into each other, such as infinities and Order, so they can pull 
everything into themselves. 

> The end of Mul.flatten would check for these attributes and then
> validate adjacent objects to make sure they could really be
> multiplied.  This would help us with symbolic Matrices and Tensors for
> example, because these methods could do shape compatibility tests.
> 
> This issue is also related to how combines are done in Mul.flatten,
> but I think we might be able to resolve this by itself.  Thoughts?

Maybe for now you could do validation separate from combination, if it's easier 
to handle.  Ultimately, I would like to see both separated out into the 
objects. The validation is a trivial special case of the combination, but not 
the other way around, because combination requires handling all args, not just 
adjacent ones.  On the other hand, the issue #1 you name above could cause 
efficiency problems for the combination, so might need to be solved 
concurrently.

Aaron Meurer
> 
> Cheers,
> 
> Brian
> 

-- 
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+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/sympy?hl=en.

Reply via email to