# How do I define (and work with) a set of matrices?

Suppose $a,b,c$ are matrices, and I want to define the set $S=$ { $a,b,c$ }. What is the proper syntax for this? More generally, how do I define a set by specifying its elements (regardless of their nature). I am only finding documentation for sets of numbers.

I'm also interested in doing functions that take sets like $S$ as input. For instance, if I had a matrix $d$, I want to be able to define a set like $S'=$ { $da,db,dc$ }, but I want to be able to do this via the Sage equivalent of $f(S):=$ {$ms\mid s\in S$}.

edit retag close merge delete

Sort by » oldest newest most voted

First, let me explain how to deal with lists instead of sets, because there is a trick with sets:

You an create your matrices as follows:

sage: a = matrix(ZZ,[[1,2],[3,4]])
sage: b = matrix(ZZ,[[5,6],[7,8]])
sage: c = matrix(ZZ,[[1,2],[3,4]])
sage: d = matrix(ZZ,[[0,1],[1,0]])


Then, you can create the list of matrices as follows:

sage: L = [a,b,c]
sage: L
[
[1 2]  [5 6]  [1 2]
[3 4], [7 8], [3 4]
]


You can define the other list with list comprehension, which is a nice feature of Python:

sage: d = matrix(ZZ,[[0,1],[1,0]])
sage: [d*i for i in L]
[
[3 4]  [7 8]  [3 4]
[1 2], [5 6], [1 2]
]


Now, you noticed that c is equal to a and since you want a set, not a list, you would like Sage to keep only one occurence in the set.

You should be able to define a set as follows:

sage: S = {a,b,c}
TypeError: mutable matrices are unhashable


The error message tells you that the matrices must be immutable to enter a set. Indeed:

sage: a.is_mutable()
True


So, you can make your matrices immutable first as follows:

sage: a.set_immutable()
sage: b.set_immutable()
sage: c.set_immutable()
sage: d.set_immutable()


Then you can define your set:

sage: S = {a,b,c}
sage: S
{[1 2]
[3 4], [5 6]
[7 8]}


As you can see, there are only to elements in it:

sage: len(S)
2


Now, you shoud be able to define yous second set by comprehension as we did with lists:

sage: {d*i for i in S}
TypeError: mutable matrices are unhashable


You get the same error. Indeed, when we construct a new matrix, it is mutable by default, and there is no way to construct an immutable one from the beginning (at least this is not documented). So, even if a and d are immutable, d*a is mutable. I agree that this is not very handy.

A workaround is to define a immutabilize function that returns an immutable copy of a mutable matrix:

sage: def immutabilize(m):
....:     M = copy(m)
....:     M.set_immutable()
....:     return M


So, at the end you get:

sage: {immutabilize(d*i) for i in S}
{[3 4]
[1 2], [7 8]
[5 6]}

more

Great, I will give this a shot tomorrow and get back to you. Thanks for all the info.

( 2015-10-18 21:29:02 -0600 )edit

OK, two people come up with the same answer independently. This must be the right answer then!

( 2015-10-18 22:03:24 -0600 )edit

Well you've definitely answered my question. I now have another issue to get this to work for what I'm doing, which should perhaps be a separate conversation (so I'm check-marking the answer), but.. I'm interested in matrices over rings besides $\mathbb{Z}$. In particular I want to define my matrices over rings of integers of number fields. One solution is to just work over $\mathbb{C}$ but I don't like how I get decimal approximations as opposed to exact expressions in terms of the primitive element. Even the simplest case of $\mathbb{Z}[i]$ seems to not be straightforward. I may figure this out by searching/experimenting but if you happen to know how to do this and can answer easily, that'd be great!

( 2015-10-19 15:20:17 -0600 )edit

Okay I have an answer to the question from my previous comment. The best way define a matrix over the ring of integers of a number field seems to be the following (taking the Gaussian example).

K.<i> = NumberField(x^2+1)
R = K.order(i)
a = matrix(R,[[i+1,-i],[i,0]])


I can't just use $I$ as the imaginary number and get output as I want it because $I$ is understood as an element of $\mathbb{C}$. So we define a new algebraically independent element $i$ which happens to also satisfy $x^2+1=0$.

( 2015-10-19 15:38:36 -0600 )edit

The pythonic way of doing this with lists is to use "list comprehensions":

sage: S=[matrix(2,2,[1,i,0,1]) for i in [1..3]]
sage: S
[
[1 1]  [1 2]  [1 3]
[0 1], [0 1], [0 1]
]
sage: m=matrix(2,2,[0,-1,1,0])
sage: [m*s for s in S]
[
[ 0 -1]  [ 0 -1]  [ 0 -1]
[ 1  1], [ 1  2], [ 1  3]
]


This is probably what you should use, since it gives you a concise syntax and usually gives you the best performance in python. If you write "multiply by m" as a function you have some other syntax available:

sage: g=lambda s:m*s
sage: [g(s) for s in S]
[
[ 0 -1]  [ 0 -1]  [ 0 -1]
[ 1  1], [ 1  2], [ 1  3]
]
sage: map(g,S)
[
[ 0 -1]  [ 0 -1]  [ 0 -1]
[ 1  1], [ 1  2], [ 1  3]
]


Via the same idiom you can define a function that takes a list as its argument, but since list comprehension and the "map" functionality are so concise, you probably shouldn't unless you have a compelling mathematical reason for doing so.

sage: f= lambda S: [d*s for s in S]
sage: f(S)
[
[ 0 -1]  [ 0 -1]  [ 0 -1]
[ 1  1], [ 1  2], [ 1  3]
]


Note that I talked about lists here, not sets. There is a complication with sets and matrices: matrices are by default mutable and mutable elements don't want to be in a set (it'd be hard to find them if they mutate!):

sage: S={matrix(2,2,[1,i,0,1]) for i in [1..3]}
TypeError: mutable matrices are unhashable


You can jump through some hoops to make this work:

sage: def immutable_matrix(*args,**kwargs):
....:     m=matrix(*args,**kwargs)
....:     m.set_immutable()
....:     return m
....:
sage: S={immutable_matrix(2,2,[1,i,0,1]) for i in [1..3]}
sage: S
{[1 1]
[0 1], [1 2]
[0 1], [1 3]
[0 1]}


Everything we discussed before still works, except that new matrices will by default be mutable again:

sage: [d*s for s in S]
[
[ 0 -1]  [ 0 -1]  [ 0 -1]
[ 1  3], [ 1  2], [ 1  1]
]
sage: {d*s for s in S}
TypeError: mutable matrices are unhashable
sage: {immutable_matrix(d*s) for s in S}
{[ 0 -1]
[ 1  1], [ 0 -1]
[ 1  2], [ 0 -1]
[ 1  3]}


The map idiom still works, but will produce a list. You might try set(map(g,S)) but then you have to adjust g to produce immutable matrices. Mutatis mutandis, you can still wrap this into a function f that takes a set/list as input.

more