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

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

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!

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

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