# Revision history [back]

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

sage: S=[matrix(2,2,[1,i,0,1],mutable=False) 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],mutable=False) 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],mutable=False) 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.

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

sage: S=[matrix(2,2,[1,i,0,1],mutable=False) 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],mutable=False) 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],mutable=False) 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.