ImmutableMatrix

15 views
Skip to first unread message

Matthew Rocklin

unread,
Jan 21, 2012, 7:32:28 PM1/21/12
to sy...@googlegroups.com
Hi Everyone, 

So a question on this thread got me thinking about matrices again. 

There has been a lot of conversation in the past about the Matrix object not being Basic. The problem is as follows:

Most SymPy objects inherit from Basic and most SymPy functions only work on Basics. Basic objects can not change, they must be immutable. Matrices should be able to change, otherwise every time you say X[1,2] = 5 you need to create a new large object and this would be slow. Thus, matrices are placed outside of the normal SymPy family of expressions and functions. It is a challenge to incorporate them into the rest of the work that we do. 

A possible solution to this problem is to have two Matrix types, Matrix and ImmutableMatrix. An ImmutableMatrix is just like Matrix but its values can not be changed, i.e. X[1,2] = 5 raises an exception. There are many questions about how we should organize matrices to minimize code reuse, allow for other general types of matrices, etc.... This is a complex problem with many potential solutions. 

I've written a small example showing what I think is the minimum work solution. I don't think this is the best solution overall but I think this is the most likely to get into SymPy in the near future. How do people feel about a sub-optimal near-term solution?

My code is here

The example isn't complete but it shows the route I'm proposing. 

-matt

Aaron Meurer

unread,
Jan 21, 2012, 10:10:10 PM1/21/12
to sy...@googlegroups.com
Hi.

I think we should do it. It shouldn't be hard. I think a lot of the
discussion got bogged down on discussions about rewriting internal
data structures, but these should probably be separate considerations.
We should just create an immutable object based on what we currently
have, and then if we work on new internal structures, build them to
work with both.

Regarding your branch, I think the class hierarchy should probably be
done differently. It doesn't make sense to me to make ImmutableMatrix
derive from (mutable) Matrix. Then the immutable subclass has to make
sure that it correctly makes all mutable implementations from the
superclass immutable. What I would do is create a MatrixBase class
that has all the algorithms that are independent of mutability. The
subclasses Matrix and ImmutableMatrix should then contain only those
things that are different between the two, like __new__ or
__setitem__. That's just the first thing that comes to my mind when
thinking about how I would do the class structure. Maybe others can
suggest even better ways to do it.

I also am wondering why you derive it from MatrixExpr. What exactly
did you plan to do with that?

Aaron Meurer

> --
> 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.

Matthew

unread,
Jan 22, 2012, 9:25:54 AM1/22/12
to sympy
Inheriting from MatrixExpr rather than Expr doesn't demand much more
from a class other than that it implements things like .shape, and .T
(transpose). The biggest point of contention would be that it
overloads __add__, __mul__, etc... to use the MatAdd and MatMul
objects. These objects are more suited towards matrices (they do
things like check shape, replace zeros with ZeroMatrix objects,
replace I*X with X, etc...) and in general fix many matrix-specific
problems. MatAdd/MatMul though are also far more buggy than Add/Mul
and it's easy to create odd syntax trees that should simplify but
don't. They can only rely on certain parts of the pretty robust Add/
Mul logic.

It also makes using the existing Inverse, Transpose, BlockMatrix,
etc... classes more clean.

Matthew

unread,
Jan 22, 2012, 12:03:45 PM1/22/12
to sympy
I've refactored into
MatrixBase(object):
MutableMatrix(MatrixBase)
ImmutableMatrix(MatrixExpr, MatrixBase)

Matrix = MutableMatrix in the standard namespace. There isn't any
backwards incompatability. All old tests still pass without revision.

I've started an issue here
http://code.google.com/p/sympy/issues/detail?id=3021
and again my branch is here
https://github.com/mrocklin/sympy/tree/immutable_matrix

-Matt

Aaron Meurer

unread,
Jan 22, 2012, 3:18:40 PM1/22/12
to sy...@googlegroups.com
I actually would have expected to use Basic instead of Expr.

Will deriving from MatrixExpr let you combine ImmutableMatrix objects
seamlessly with MatrixExpr objects? I suppose this could be a good
thing. If x is a MatrixSymbol and M is an ImmutableMatrix, then x*M
would return a MatrixMul (or raise ShapeError). But if x is just
Symbol('x'), or some other Expr, x*M should distribute x across the
elements of M.

Aaron Meurer

Aaron Meurer

unread,
Jan 22, 2012, 3:27:42 PM1/22/12
to sy...@googlegroups.com
On Sun, Jan 22, 2012 at 10:03 AM, Matthew <mroc...@gmail.com> wrote:
> I've refactored into
> MatrixBase(object):
>    MutableMatrix(MatrixBase)
>    ImmutableMatrix(MatrixExpr, MatrixBase)
>
> Matrix = MutableMatrix in the standard namespace. There isn't any
> backwards incompatability. All old tests still pass without revision.
>
> I've started an issue here
> http://code.google.com/p/sympy/issues/detail?id=3021
> and again my branch is here
> https://github.com/mrocklin/sympy/tree/immutable_matrix
>
> -Matt

You can go ahead and start a pull request for discussion on this.
That will make it easier to talk about your changes specifically.

Aaron Meurer

Matthew Rocklin

unread,
Jan 23, 2012, 11:25:30 AM1/23/12
to sy...@googlegroups.com
Pull request for further discussion is here
Reply all
Reply to author
Forward
0 new messages