Matthew,

On Wed, Jul 13, 2011 at 6:39 AM, Matthew Rocklin <mrock...@gmail.com> wrote:
> I have op_priority set to 11 so that basic arithmetic operations do use
> MatMuls and MatAdds. MatMul and MatAdd check shape, then call regular
> Mul/Add __new__ methods to take advantage of the already built flattening
> functions. After that's done they go through and change classes back to
> MatMul/MatAdd in case a normal Mul/Add was called within the __new__. So far
> this has worked very well. All of the associativity cases 1-6 throw the
> correct error. The more complex expressions that I've tried have also worked
> fine.
> Calling Mul or Add explicitly does break things. There's no entry point for
> me to insert clever logic as I don't want to edit core functions. My
> solution here is simply to say "Use MatMul or MatAdd instead, or, if you
> must use Mul/Add, call matrixify on the expression afterwards". Matrixify
> will be guaranteed to return a Matrix expression if MatrixSymbols exist
> within a normal Expression. I plan to put it in a few key functions like
> simplify and expand.
>
> Is this matrixify solution too much of a hack? Hopefully I can hide it away
> within a few key functions so that the user never needs to know about it
> unless they explicitly use Add or Mul. If they're using Add or Mul then I
> expect them to be clever enough to handle matrixify.
> I'm working on this branch .

As I understand it Matrixify goes through an expression and makes sure
that your Mul/Add/Pow subclasses are used.  If that is the case, I
advise against it because the second a user starts to do things with
the expression they will have to call Matrixify again.  Again, I would
just use the default Mul/Add/Pow and provide standalone functions like
check_shape that perform a specific type of action on an expression.

Cheers,

Brian

> On Wed, Jul 13, 2011 at 12:25 AM, Aaron Meurer <asmeu...@gmail.com> wrote:
>>
>> One thing that I have noticed with regard to overriding __mul__ and
>> __rmul__ (for example) is that you can never completely control what
>> happens to your class because of association.  For example, suppose
>> that A and B are MatrixExprs and x is some Expr object (say, a
>> Symbol).  Suppose that A*B should give a ShapeError, and that x is a
>> scalar, which does not matter where it is in the expression.  Then you
>> have to program it so that all of the following give ShapeError:
>>
>> 1. x*(A*B)
>> 2. (x*A)*B
>> 3. (A*x)*B
>> 4. A*(x*B)
>> 5. (A*B)*x
>> 6. A*(B*x)
>>
>> Let us look at these.  Obviously, 1 and 5 will work, since you have
>> complete control over A.__mul__(B).  Similarly, in 4 and 6, you will
>> end up with A.__mul__(Mul(x, B)), but this is not a problem, since you
>> can make A.__mul__ check for the left-most noncommutative in a Mul.
>>
>> But what about 2 and 3?  Here, we have __mul__ being called by a Expr
>> type, namely, Mul(x, A).  You want to get B.__rmul__(Mul(x, A)), since
>> you have implemented shape checking logic in MatrixExpr.__(r)mul__.
>> But b.__rmul__(a) is called with a*b only if a.__mul__(b) returns
>> NotImplemented.  So, basically, we need Mul.__mul__(MatrixExpr) to
>> return NotImplemented.  Well, let us look at the code for Mul.__mul__
>> (actually Expr.__mul__):
>>
>> @_sympifyit('other', NotImplemented)
>> @call_highest_priority('__rmul__')
>> def __mul__(self, other):
>>    return Mul(self, other)
>>
>> Well, this is not very helpful, because the logic is buried in some
>> decorators.  So let us look at the code for those decorators.  I will
>> not bore you by pasting the entire code here (you can see it in
>> sympy/core/decorators.py), but basically, _sympifyit makes tries to
>> sympify other, and makes __mul__ return NotImplemented if it fails.  I
>> am not delving into this, because sympify would not fail for
>> MatrixExpr (otherwise, we would actually have a problem doing any form
>> of x*A*B).
>>
>> So call_highest_priority seems to be a better bet.  This decorator I
>> will also not paste here, but it basically lets you define
>> ._op_priority on your object, and if it is greater than Expr's (which
>> is quite arbitrarily set to 10.0), then it will call
>> other.__rmul__(self).
>>
>> But wait, there's more.  _op_priority can make the above cases work,
>> but * is not the only way that SymPy multiplies things.  You will also
>> have to deal with variations on Mul(x, A, B).  Mul completely ignores
>> _op_priority.  Unfortunately, even if this may seem like a more
>> esoteric way to multiply things that you can just recommend users
>> avoid, it is used internally a lot, because Mul(*args) is more
>> efficient than reduce(operator.mul, args).
>>
>> Thus, you see that it is quite impossible to make things work 100% of
>> the time without modifying the core. And actually, because of the Mul
>> thing that would not work at all and that is called by so many core
>> functions and methods, you will not even get something like things
>> working 90% of the time, but instead things will break when used a
>> certain way, and you will have hard to track bugs.
>>
>> Aaron Meurer
>>
>> On Tue, Jul 12, 2011 at 3:08 PM, Matthew Rocklin <mrock...@gmail.com>
>> wrote:
>> > Subclassing Expr has some issues as well. This is what Brian was
>> > referring
>> > to. Within all of our code we use Add and Mul and don't check if instead
>> > we
>> > should use some subclass of Add or subclass of Mul. If I feed a matrix
>> > expression into these objects then the special matrix structure is lost.
>> > This happens if, for example, you call simplify on a matrix expression.
>> > I think I can get around this though with a few well placed "matrixify"
>> > functions. Matrixify is a function which goes through the expression
>> > tree
>> > and makes appropriate fixes. I've had good success so far with a very
>> > very
>> > basic Matrixify function.
>> > Brian, did you have particular horror stories trying to subclass Expr?
>> > I'm
>> > enthusiastic about my approach but you seemed to have a bad experience.
>> > Can
>> > you suggest difficult test cases that I should think about?
>> >
>> >
>> > On Fri, Jul 8, 2011 at 3:22 PM, Aaron Meurer <asmeu...@gmail.com> wrote:
>> >>
>> >> On Fri, Jul 8, 2011 at 4:00 AM, SherjilOzair <sherjiloz...@gmail.com>
>> >> wrote:
>> >> > There is something I'm doing as part of my project which maybe be
>> >> > useful. I'm implementing a Matrix_ wrapper class which will wrap over
>> >> > low-level matrices. Its being written to replace the current Matrix
>> >> > class. Algorithmic code and user-level code is being separated into
>> >> > different classes. Currently, we have three internal matrices, the
>> >> > DenseMatrix( a modified form of the current Matrix class), DOKMatrix
>> >> > and LILMatrix. These three are essentially Data internal matrices.
>> >> > The MatrixSymbol can be another object that Matrix_ (later Matrix)
>> >> > would use as internal.
>> >> >
>> >> > Of what I understand from this discussion about the Matrix Symbol, we
>> >> > need to have an object that will be treated like a Matrix everywhere,
>> >> > but without the internal data. Space is being made in the Matrix
>> >> > module for such an object, but for it work nicely it needs to
>> >> > interact
>> >> > nicely with Expr objects. If its a problem subclassing Expr and
>> >> > friends, I'm +1 about making a separate codebase for matrix
>> >> > expressions. It is, after all, a different algebra.
>> >> >
>> >> > I'm not very familiar with Expr, Add, etc. but I think a separate
>> >> > algebra MatrixExpr, MatrixAdd, etc. could be developed by
>> >> > copy-pasting
>> >> > some code from Expr, Add, and modifying according to need. I say
>> >> > 'copy-
>> >> > paste' and not subclassing as the code would be need to be modified
>> >> > much before it can work on matrices.
>> >>
>> >> As has been discussed before, this is a bad idea. Just subclass Expr.
>> >>
>> >> Aaron Meurer
>> >>
>> >> >
>> >> > Presently, I'm quite busy with this new encapsulation class Matrix_
>> >> > and can only think of working fulltime on MatrixSymbol after I've
>> >> > merged in my work on DOKMatrix, LILMatrix and the ongoing work on
>> >> > Matrix_.
>> >> >
>> >> > Matthew, you could set up a wiki page on 'matrix expressions' with
>> >> > some example code in it. 'symbolic matrices' can mean a few number of
>> >> > things, and is somewhat vague. It would be good if everyone could see
>> >> > what sort of concrete things are expected from matrix expressions.
>> >> > Approaches to implement Matrix Algebra, with pros and cons listed,
>> >> > could be added there for discussion, suggestion and improvement.
>> >> >
>> >> > Regards,
>> >> > Sherjil Ozair
>> >> >
>> >> > --
>> >> > You received this message because you are subscribed to the Google
>> >> > Groups "sympy" group.
>> >> > To post to this group, send email to sympy@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.
>> >> >
>> >> >
>> >>
>> >> --
>> >> You received this message because you are subscribed to the Google
>> >> Groups
>> >> "sympy" group.
>> >> To post to this group, send email to sympy@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.
>> >>
>> >
>> > --
>> > You received this message because you are subscribed to the Google
>> > Groups
>> > "sympy" group.
>> > To post to this group, send email to sympy@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.
>> >
>>
>> --
>> You received this message because you are subscribed to the Google Groups
>> "sympy" group.
>> To post to this group, send email to sympy@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.
>>
>
> --
> You received this message because you are subscribed to the Google Groups
> "sympy" group.
> To post to this group, send email to sympy@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.
>



-- 
Brian E. Granger
Cal Poly State University, San Luis Obispo
bgran...@calpoly.edu and elliso...@gmail.com

-- 
You received this message because you are subscribed to the Google Groups 
"sympy" group.
To post to this group, send email to sympy@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