What is the difference between Tuple and ImmutableMatrix?

14 views
Skip to first unread message

krastano...@gmail.com

unread,
May 11, 2012, 7:51:20 PM5/11/12
to sy...@googlegroups.com
Can we merge them? It will be useful for my gsoc project (I wont have
to make special cases for Tuple).

Chris Smith

unread,
May 11, 2012, 8:12:59 PM5/11/12
to sy...@googlegroups.com
What do you have in mind for the merge? (IM has 2 shape parameters and
Tuple does not.)

Matthew Rocklin

unread,
May 11, 2012, 8:22:30 PM5/11/12
to sy...@googlegroups.com
You're right in that they both redundantly serve as immutable storage classes. I can envision a system where they're merged. 

On the other hand one can think about them quite differently. Tuples contain Basics, IMs contain Exprs (not sure this is actually enforced.) Most importantly IMs have all the matrix computation stuff attached to them, Tuples are simpler. Were you thinking of subclassing IM from Tuple, subclassing Tuple from IM? Creating NDArray?

What is the situation? Why does Tuple/IM require a special case?

There has also been talk of removing Tuple entirely. You could pursue that as a solution. 


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


krastano...@gmail.com

unread,
May 11, 2012, 8:37:39 PM5/11/12
to sy...@googlegroups.com
On 12 May 2012 02:22, Matthew Rocklin <mroc...@gmail.com> wrote:
> You're right in that they both redundantly serve as immutable storage
> classes. I can envision a system where they're merged.
>
> On the other hand one can think about them quite differently. Tuples contain
> Basics, IMs contain Exprs (not sure this is actually enforced.) Most
> importantly IMs have all the matrix computation stuff attached to them,
> Tuples are simpler. Were you thinking of subclassing IM from Tuple,
> subclassing Tuple from IM? Creating NDArray?
>
> What is the situation? Why does Tuple/IM require a special case?
>

I do not see a meaningful difference between a column vector and a
tuple, If someone needs to input coordinates in a function at the
moment he can use list, tuple, Tuple and Matrix. That does not seem
right.

More generally I do not see why iterables are not sympified into
column matrices. This will make so many special cases in the code go
away.

And I am not speaking about some kind of Arrays. Matrices are arrays
and that seems good enough to me. For something more fancy one can
always use numpy arrays with dtype=object.

I will try to remove Tuple from the code base.

Chris Smith

unread,
May 11, 2012, 8:39:09 PM5/11/12
to sy...@googlegroups.com
On Sat, May 12, 2012 at 6:07 AM, Matthew Rocklin <mroc...@gmail.com> wrote:
> You're right in that they both redundantly serve as immutable storage
> classes. I can envision a system where they're merged.
>
> On the other hand one can think about them quite differently. Tuples contain
> Basics, IMs contain Exprs (not sure this is actually enforced.) Most

And Basic can contain anything (e.g. Basic(*range(3)) contains 3 ints,
not Integers). But Basic is not slicable.

Tuple could subclass from IM with 1xN shape; perhaps it needs to print
differently

>>> ImmutableMatrix(1,6,range(6))
[0, 1, 2, 3, 4, 5]
>>> Tuple(*range(6))
(0, 1, 2, 3, 4, 5)

It already slices the same:

>>> Tuple(*range(6))[3:5]
(3, 4)
>>> ImmutableMatrix(1,6,range(6))[3:5]
(3, 4)

Chris Smith

unread,
May 11, 2012, 8:44:55 PM5/11/12
to sy...@googlegroups.com
> More generally I do not see why iterables are not sympified into
> column matrices. This will make so many special cases in the code go
> away.

It's going to look super ugle to print things that have column
matrices (cf rref) so perhaps a row vector would be better.

krastano...@gmail.com

unread,
May 11, 2012, 8:54:46 PM5/11/12
to sy...@googlegroups.com
You are right. But on the other hand vectors are usually presented as
columns and not rows. This should be discussed I suppose.


And I am not proposing subclassing from ImmutableMatrix, rather
complete removal of Tuple and adding needed functionality (like
`to_mpmath`) to Matrix.

Joachim Durchholz

unread,
May 12, 2012, 3:16:41 AM5/12/12
to sy...@googlegroups.com
Am 12.05.2012 02:54, schrieb krastano...@gmail.com:
> On 12 May 2012 02:44, Chris Smith<smi...@gmail.com> wrote:
>>> More generally I do not see why iterables are not sympified into
>>> column matrices. This will make so many special cases in the code go
>>> away.
>>
>> It's going to look super ugle to print things that have column
>> matrices (cf rref) so perhaps a row vector would be better.
>>
> You are right. But on the other hand vectors are usually presented as
> columns and not rows. This should be discussed I suppose.

I'd expect column vectors as columns in prettyprinting.
String output should probably display them like row vectors, with just
enough visual feedback that one can distinguish row and column vectors
but otherwise the same.

> And I am not proposing subclassing from ImmutableMatrix, rather
> complete removal of Tuple and adding needed functionality (like
> `to_mpmath`) to Matrix.

There are two possible justifications for having two classes: software
and mathematics.

The software justification would be if there's code that can work with
Tuple but not with a row vector.
That would be a representational difference.

Mathematically, while all vectors can be seen as tuples, not all tuples
are row vectors. For example, a tuple of categories isn't.
That would be a semantic difference.

Disclaimer: I do not know whether either of these justifications
actually holds for Matrix and Tuple in SymPy.
I'm just not sure whether these aspects have been considered.

krastano...@gmail.com

unread,
May 12, 2012, 6:30:59 AM5/12/12
to sy...@googlegroups.com
>
>> And I am not proposing subclassing from ImmutableMatrix, rather
>> complete removal of Tuple and adding needed functionality (like
>> `to_mpmath`) to Matrix.
>
>
> There are two possible justifications for having two classes: software and
> mathematics.
>
> The software justification would be if there's code that can work with Tuple
> but not with a row vector.
> That would be a representational difference.
>
> Mathematically, while all vectors can be seen as tuples, not all tuples are
> row vectors. For example, a tuple of categories isn't.
> That would be a semantic difference.
>
> Disclaimer: I do not know whether either of these justifications actually
> holds for Matrix and Tuple in SymPy.
> I'm just not sure whether these aspects have been considered.
>
>
Pythonic code should be based on interfaces. All that Tuple provides
is an iterator. Matrix can do that. The other minor differences make
sense to be added to Matrix. That is why I think we should not have
two classes.

Besides, in mathematica you have just lists, and build you matrices
out of lists. It is beautifully simple.

Tom Bachmann

unread,
May 12, 2012, 6:41:30 AM5/12/12
to sy...@googlegroups.com
On 12.05.2012 11:30, krastano...@gmail.com wrote:
> Pythonic code should be based on interfaces.

As understand it, pythonic *use* of objects means only using interfaces,
not checking actual types. I think there can very well be legitimate
reasons for having several implementations of the same interface. In
fact it would seem to me that printing them differently (tuples with
'()' and matrices with '[]') is quite a legitimate reason to have two.

They should probably share some code, though..

krastano...@gmail.com

unread,
May 12, 2012, 7:17:25 AM5/12/12
to sy...@googlegroups.com
@Tom, your comment makes sense. Now it seems less urgent to remove the
duplicate code between them. I will file an issue about all this.

krastano...@gmail.com

unread,
May 12, 2012, 7:21:28 AM5/12/12
to sy...@googlegroups.com

Aaron Meurer

unread,
May 12, 2012, 9:10:12 AM5/12/12
to sy...@googlegroups.com
I agree that they should be separate. A Tuple represents a generic
container object, whereas a Matrix is a specific kind of object with
certain algebraic properties. The fact that Tuple is only Basic
whereas ImmutableMatrix is also Expr showcases this fact (I know this
brings us back to the "meaning of Expr" discussion).

A Tuple might be thought of mathematically as an element of a
cartesian product set. As Joachim noted, it could contain anything:
mathematical expressions, boolean expressions, sets, other tuples,
etc. A Matrix has properties like a*(x, y, z) = (a*x, a*y, a*z).
This doesn't make sense if x, y, and z are all booleans, for example.

Another thing: if we define a nxm matrix by ((x11, x12, ..., x1m),
..., (xn1, xn2, ..., xnm)), then this could be seen as a column of row
vectors. So we see that depending on the context, we must consider a
tuple to be a row matrix or a column matrix.

If anything, ImmutableMatrix should subclass from Tuple, not the other
way around, since the latter is a more generic class.

What specific special cases are there in the code by the way?

Aaron Meurer

On Sat, May 12, 2012 at 5:21 AM, krastano...@gmail.com
<krastano...@gmail.com> wrote:
> Here is the issue http://code.google.com/p/sympy/issues/detail?id=3263
>

Matthew Rocklin

unread,
May 12, 2012, 9:20:04 AM5/12/12
to sy...@googlegroups.com
We could create a generic NDArray storage class. Matrix could contain such a class rather than inherit from it. 

krastano...@gmail.com

unread,
May 12, 2012, 10:49:41 AM5/12/12
to sy...@googlegroups.com
>
> What specific special cases are there in the code by the way?
>
Things like nsolve working when guesses are inserted as a tuple but
not if they are inserted as a matrix (or something like that.)

More importantly, places where coordinates will have to be used - a
coordinate vector makes sense as a tuple and as a matrix.

Vinzent Steinberg

unread,
May 14, 2012, 1:08:51 PM5/14/12
to sy...@googlegroups.com
On Saturday, May 12, 2012 4:49:41 PM UTC+2, Stefan Krastanov wrote:
>
> What specific special cases are there in the code by the way?
>
Things like nsolve working when guesses are inserted as a tuple but
not if they are inserted as a matrix (or something like that.) 

If this is the case, it should be fixed.
 

More importantly, places where coordinates will have to be used - a
coordinate vector makes sense as a tuple and as a matrix.

I think we should keep the interfaces different. You have addition and multiplication with scalars for a vector/matrix, but in general not for a tuple. Also, you have for example transposition, which does not make sense for tuples.

Maybe the implementations should share more code in order to be less redundant though. I agree with Aaron, it might make sense for ImmutableMatrix to subclass Tuple.

Vinzent 

Ronan Lamy

unread,
May 15, 2012, 4:33:50 PM5/15/12
to sy...@googlegroups.com
Le lundi 14 mai 2012 à 10:08 -0700, Vinzent Steinberg a écrit :

>
> I think we should keep the interfaces different. You have addition and
> multiplication with scalars for a vector/matrix, but in general not
> for a tuple. Also, you have for example transposition, which does not
> make sense for tuples.
>
>
> Maybe the implementations should share more code in order to be less
> redundant though. I agree with Aaron, it might make sense for
> ImmutableMatrix to subclass Tuple.
>
I disagree. An ImmutableMatrix is clearly not Liskov-substitutable for a
Tuple. For Tuples, "+" means concatenation, not addition, and matrices
are 2-D while tuples are 1-D, so indexing works differently.


Aaron Meurer

unread,
May 15, 2012, 5:00:56 PM5/15/12
to sy...@googlegroups.com
I agree. The constructors are different too. In fact, looking at the code, I'm doubtful whether any code is shared between the two classes at all, except for trivial boilerplate shared by most classes. 

The only concept shared between the two classes is that they are both iterables, and this concept should be indicated by subclassing, but rather by the definition of the __iter__ method.  Actually, even in this concept they differ if you consider a matrix to be a column vector of row vectors, because iteration goes through the elements, not through the row vectors as naive iteration would do (and as iteration of a similarly constructed Tuple would do). 

So nsolve and other functions that try to apply heuristics to Tuple vs. Matrix should treat the matrices separately if it makes sense, and otherwise just use the duck typing to determine that the object is a container type, or alternately not support container types at all and just require the user to do the iteration with a list comprehension or something similar.

Aaron Meurer  


--
Sent from my iPad.

krastano...@gmail.com

unread,
May 15, 2012, 5:14:20 PM5/15/12
to sy...@googlegroups.com
OK, I suppose that I am just too used to the idea that "everything is a list".

I do not see the reason not to have vector of Sets/Manifolds/Whatever
instead of a Tuple of sets/whatever (which I think was the only strong
argument in favor of keeping Tuples). And I also do not see the
problem with "Tuple and Matrix not being Liskov-substitutable" - they
do not need to be, one will simply not use + to denote concatenation
when Tuple is removed and gone.

However, as the majority has another view I will not proceed on this.
(on the other hand, any arguments explaining why Liskov-substitutable
is important *in this single case* will be appreciated)

Aaron Meurer

unread,
May 15, 2012, 5:17:23 PM5/15/12
to sy...@googlegroups.com
I gave two other examples where they differ: the constructors and
iteration. Actually, it seems to me now that there's very little that
they actually do share in exactly the same way.

Aaron Meurer

On May 15, 2012, at 3:14 PM, "krastano...@gmail.com"

krastano...@gmail.com

unread,
May 15, 2012, 5:21:24 PM5/15/12
to sy...@googlegroups.com
> I gave two other examples where they differ: the constructors and
> iteration. Actually, it seems to me now that there's very little that
> they actually do share in exactly the same way.
>
Yes, but these examples are about their interface, not whether they
serve similar functions. It is argument in favor of no common
subclassing, but it is not in favor of not removing one of them.

Aaron Meurer

unread,
May 15, 2012, 5:27:42 PM5/15/12
to sy...@googlegroups.com
Well, if you remove one, you loose the ability to do what it does.
Iteration is a good example of this. `for i in ((1, 2, 3), (4, 5, 6))`
iterating as `1, 2, 3, 4, 5, 6` and `(1, 2, 3), (4, 5, 6)` are both
useful.

As another argument, it doesn't make sense to force constructs like
shape and matrix multiplication on to arbitrary container types.

Aaron Meurer

On May 15, 2012, at 3:21 PM, "krastano...@gmail.com"
Reply all
Reply to author
Forward
0 new messages