ASKSAGE: Sage Q&A Forum - Individual question feedhttp://ask.sagemath.org/questions/Q&A Forum for SageenCopyright Sage, 2010. Some rights reserved under creative commons license.Mon, 19 Oct 2015 15:38:36 -0500How do I define (and work with) a set of matrices?http://ask.sagemath.org/question/30102/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 $}.Sun, 18 Oct 2015 19:25:38 -0500http://ask.sagemath.org/question/30102/how-do-i-define-and-work-with-a-set-of-matrices/Answer by tmonteil for <p>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.</p>
<p>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 $}.</p>
http://ask.sagemath.org/question/30102/how-do-i-define-and-work-with-a-set-of-matrices/?answer=30106#post-id-30106First, 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]}
Sun, 18 Oct 2015 21:08:54 -0500http://ask.sagemath.org/question/30102/how-do-i-define-and-work-with-a-set-of-matrices/?answer=30106#post-id-30106Comment by j0equ1nn for <p>First, let me explain how to deal with lists instead of sets, because there is a trick with sets:</p>
<p>You an create your matrices as follows:</p>
<pre><code>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]])
</code></pre>
<p>Then, you can create the list of matrices as follows:</p>
<pre><code>sage: L = [a,b,c]
sage: L
[
[1 2] [5 6] [1 2]
[3 4], [7 8], [3 4]
]
</code></pre>
<p>You can define the other list with <em>list comprehension</em>, which is a nice feature of Python:</p>
<pre><code>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]
]
</code></pre>
<p>Now, you noticed that <code>c</code> is equal to <code>a</code> and since you want a set, not a list, you would like Sage to keep only one occurence in the set.</p>
<p>You should be able to define a set as follows:</p>
<pre><code>sage: S = {a,b,c}
TypeError: mutable matrices are unhashable
</code></pre>
<p>The error message tells you that the matrices must be immutable to enter a set. Indeed:</p>
<pre><code>sage: a.is_mutable()
True
</code></pre>
<p>So, you can make your matrices immutable first as follows:</p>
<pre><code>sage: a.set_immutable()
sage: b.set_immutable()
sage: c.set_immutable()
sage: d.set_immutable()
</code></pre>
<p>Then you can define your set:</p>
<pre><code>sage: S = {a,b,c}
sage: S
{[1 2]
[3 4], [5 6]
[7 8]}
</code></pre>
<p>As you can see, there are only to elements in it:</p>
<pre><code>sage: len(S)
2
</code></pre>
<p>Now, you shoud be able to define yous second set by comprehension as we did with lists:</p>
<pre><code>sage: {d*i for i in S}
TypeError: mutable matrices are unhashable
</code></pre>
<p>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 <code>a</code> and <code>d</code> are immutable, <code>d*a</code> is mutable. I agree that this is not very handy.</p>
<p>A workaround is to define a <code>immutabilize</code> function that returns an immutable copy of a mutable matrix:</p>
<pre><code>sage: def immutabilize(m):
....: M = copy(m)
....: M.set_immutable()
....: return M
</code></pre>
<p>So, at the end you get:</p>
<pre><code>sage: {immutabilize(d*i) for i in S}
{[3 4]
[1 2], [7 8]
[5 6]}
</code></pre>
http://ask.sagemath.org/question/30102/how-do-i-define-and-work-with-a-set-of-matrices/?comment=30123#post-id-30123Okay 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$.Mon, 19 Oct 2015 15:38:36 -0500http://ask.sagemath.org/question/30102/how-do-i-define-and-work-with-a-set-of-matrices/?comment=30123#post-id-30123Comment by j0equ1nn for <p>First, let me explain how to deal with lists instead of sets, because there is a trick with sets:</p>
<p>You an create your matrices as follows:</p>
<pre><code>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]])
</code></pre>
<p>Then, you can create the list of matrices as follows:</p>
<pre><code>sage: L = [a,b,c]
sage: L
[
[1 2] [5 6] [1 2]
[3 4], [7 8], [3 4]
]
</code></pre>
<p>You can define the other list with <em>list comprehension</em>, which is a nice feature of Python:</p>
<pre><code>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]
]
</code></pre>
<p>Now, you noticed that <code>c</code> is equal to <code>a</code> and since you want a set, not a list, you would like Sage to keep only one occurence in the set.</p>
<p>You should be able to define a set as follows:</p>
<pre><code>sage: S = {a,b,c}
TypeError: mutable matrices are unhashable
</code></pre>
<p>The error message tells you that the matrices must be immutable to enter a set. Indeed:</p>
<pre><code>sage: a.is_mutable()
True
</code></pre>
<p>So, you can make your matrices immutable first as follows:</p>
<pre><code>sage: a.set_immutable()
sage: b.set_immutable()
sage: c.set_immutable()
sage: d.set_immutable()
</code></pre>
<p>Then you can define your set:</p>
<pre><code>sage: S = {a,b,c}
sage: S
{[1 2]
[3 4], [5 6]
[7 8]}
</code></pre>
<p>As you can see, there are only to elements in it:</p>
<pre><code>sage: len(S)
2
</code></pre>
<p>Now, you shoud be able to define yous second set by comprehension as we did with lists:</p>
<pre><code>sage: {d*i for i in S}
TypeError: mutable matrices are unhashable
</code></pre>
<p>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 <code>a</code> and <code>d</code> are immutable, <code>d*a</code> is mutable. I agree that this is not very handy.</p>
<p>A workaround is to define a <code>immutabilize</code> function that returns an immutable copy of a mutable matrix:</p>
<pre><code>sage: def immutabilize(m):
....: M = copy(m)
....: M.set_immutable()
....: return M
</code></pre>
<p>So, at the end you get:</p>
<pre><code>sage: {immutabilize(d*i) for i in S}
{[3 4]
[1 2], [7 8]
[5 6]}
</code></pre>
http://ask.sagemath.org/question/30102/how-do-i-define-and-work-with-a-set-of-matrices/?comment=30122#post-id-30122Well 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!Mon, 19 Oct 2015 15:20:17 -0500http://ask.sagemath.org/question/30102/how-do-i-define-and-work-with-a-set-of-matrices/?comment=30122#post-id-30122Comment by nbruin for <p>First, let me explain how to deal with lists instead of sets, because there is a trick with sets:</p>
<p>You an create your matrices as follows:</p>
<pre><code>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]])
</code></pre>
<p>Then, you can create the list of matrices as follows:</p>
<pre><code>sage: L = [a,b,c]
sage: L
[
[1 2] [5 6] [1 2]
[3 4], [7 8], [3 4]
]
</code></pre>
<p>You can define the other list with <em>list comprehension</em>, which is a nice feature of Python:</p>
<pre><code>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]
]
</code></pre>
<p>Now, you noticed that <code>c</code> is equal to <code>a</code> and since you want a set, not a list, you would like Sage to keep only one occurence in the set.</p>
<p>You should be able to define a set as follows:</p>
<pre><code>sage: S = {a,b,c}
TypeError: mutable matrices are unhashable
</code></pre>
<p>The error message tells you that the matrices must be immutable to enter a set. Indeed:</p>
<pre><code>sage: a.is_mutable()
True
</code></pre>
<p>So, you can make your matrices immutable first as follows:</p>
<pre><code>sage: a.set_immutable()
sage: b.set_immutable()
sage: c.set_immutable()
sage: d.set_immutable()
</code></pre>
<p>Then you can define your set:</p>
<pre><code>sage: S = {a,b,c}
sage: S
{[1 2]
[3 4], [5 6]
[7 8]}
</code></pre>
<p>As you can see, there are only to elements in it:</p>
<pre><code>sage: len(S)
2
</code></pre>
<p>Now, you shoud be able to define yous second set by comprehension as we did with lists:</p>
<pre><code>sage: {d*i for i in S}
TypeError: mutable matrices are unhashable
</code></pre>
<p>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 <code>a</code> and <code>d</code> are immutable, <code>d*a</code> is mutable. I agree that this is not very handy.</p>
<p>A workaround is to define a <code>immutabilize</code> function that returns an immutable copy of a mutable matrix:</p>
<pre><code>sage: def immutabilize(m):
....: M = copy(m)
....: M.set_immutable()
....: return M
</code></pre>
<p>So, at the end you get:</p>
<pre><code>sage: {immutabilize(d*i) for i in S}
{[3 4]
[1 2], [7 8]
[5 6]}
</code></pre>
http://ask.sagemath.org/question/30102/how-do-i-define-and-work-with-a-set-of-matrices/?comment=30111#post-id-30111OK, two people come up with the same answer independently. This must be the right answer then!Sun, 18 Oct 2015 22:03:24 -0500http://ask.sagemath.org/question/30102/how-do-i-define-and-work-with-a-set-of-matrices/?comment=30111#post-id-30111Comment by j0equ1nn for <p>First, let me explain how to deal with lists instead of sets, because there is a trick with sets:</p>
<p>You an create your matrices as follows:</p>
<pre><code>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]])
</code></pre>
<p>Then, you can create the list of matrices as follows:</p>
<pre><code>sage: L = [a,b,c]
sage: L
[
[1 2] [5 6] [1 2]
[3 4], [7 8], [3 4]
]
</code></pre>
<p>You can define the other list with <em>list comprehension</em>, which is a nice feature of Python:</p>
<pre><code>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]
]
</code></pre>
<p>Now, you noticed that <code>c</code> is equal to <code>a</code> and since you want a set, not a list, you would like Sage to keep only one occurence in the set.</p>
<p>You should be able to define a set as follows:</p>
<pre><code>sage: S = {a,b,c}
TypeError: mutable matrices are unhashable
</code></pre>
<p>The error message tells you that the matrices must be immutable to enter a set. Indeed:</p>
<pre><code>sage: a.is_mutable()
True
</code></pre>
<p>So, you can make your matrices immutable first as follows:</p>
<pre><code>sage: a.set_immutable()
sage: b.set_immutable()
sage: c.set_immutable()
sage: d.set_immutable()
</code></pre>
<p>Then you can define your set:</p>
<pre><code>sage: S = {a,b,c}
sage: S
{[1 2]
[3 4], [5 6]
[7 8]}
</code></pre>
<p>As you can see, there are only to elements in it:</p>
<pre><code>sage: len(S)
2
</code></pre>
<p>Now, you shoud be able to define yous second set by comprehension as we did with lists:</p>
<pre><code>sage: {d*i for i in S}
TypeError: mutable matrices are unhashable
</code></pre>
<p>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 <code>a</code> and <code>d</code> are immutable, <code>d*a</code> is mutable. I agree that this is not very handy.</p>
<p>A workaround is to define a <code>immutabilize</code> function that returns an immutable copy of a mutable matrix:</p>
<pre><code>sage: def immutabilize(m):
....: M = copy(m)
....: M.set_immutable()
....: return M
</code></pre>
<p>So, at the end you get:</p>
<pre><code>sage: {immutabilize(d*i) for i in S}
{[3 4]
[1 2], [7 8]
[5 6]}
</code></pre>
http://ask.sagemath.org/question/30102/how-do-i-define-and-work-with-a-set-of-matrices/?comment=30108#post-id-30108Great, I will give this a shot tomorrow and get back to you. Thanks for all the info.Sun, 18 Oct 2015 21:29:02 -0500http://ask.sagemath.org/question/30102/how-do-i-define-and-work-with-a-set-of-matrices/?comment=30108#post-id-30108Answer by nbruin for <p>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.</p>
<p>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 $}.</p>
http://ask.sagemath.org/question/30102/how-do-i-define-and-work-with-a-set-of-matrices/?answer=30110#post-id-30110The 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.Sun, 18 Oct 2015 22:00:42 -0500http://ask.sagemath.org/question/30102/how-do-i-define-and-work-with-a-set-of-matrices/?answer=30110#post-id-30110