问题描述:

I have lots of matrices (as result of rotations, etc.), but I would be sure to store them only once. I thought about *using a set* :

`print set([np.matrix([[0, 0],[0, 1],[1, 1],[2, 1]]),`

np.matrix([[0, 0],[1, 0],[1, -1],[1, -2]])])

Unfortunately, I get :

TypeError: unhashable type: 'matrix'

It's sad because a set would be exactly the right data type to avoid repetitions, and be able to use union, intersection, etc.

**How to work with sets of matrices in Python?**

```
In [299]: m1
Out[299]:
matrix([[0, 0],
[0, 1],
[1, 1],
[2, 1]])
In [300]: m2
Out[300]:
matrix([[ 0, 0],
[ 1, 0],
[ 1, -1],
[ 1, -2]])
In [297]: set([tuple(m1.A1),tuple(m2.A1)])
Out[297]: {(0, 0, 0, 1, 1, 1, 2, 1), (0, 0, 1, 0, 1, -1, 1, -2)}
```

`m1.A1`

converts the matrix to a 1d array, which displays as a simple list. Wrap that in `tuple`

makes an object that is hashable.

A `set`

is like a dictionary with keys but no values. Both provide quick access (and `in`

testing) by converting each key to a 'hash'. Part of why it requires a tuple, as opposed to a list is that it must be immutable. The hash would change if you changed one of the values of the matrix.

Without the `A1`

(or other ravel) it does not work - look at `tuple(m1)`

.

```
In [302]: set([tuple(m1),tuple(m2)])
...
TypeError: unhashable type: 'matrix'
In [303]: tuple(m1)
Out[303]: (matrix([[0, 0]]), matrix([[0, 1]]), matrix([[1, 1]]), matrix([[2, 1]]))
```

We could also convert the matrix to some string representation, and store that. Note that these conversions don't save you space, and all incur a conversion cost.

We may need to explore how these matrices are compared. What makes one different from another?

Equality of matching elements:

```
In [306]: m1==m2
Out[306]:
matrix([[ True, True],
[False, False],
[ True, False],
[False, False]], dtype=bool)
In [307]: (m1==m2).all()
Out[307]: False
In [308]: (m1==m1).all()
Out[308]: True
```

Of course that requires that they all be the same shape.

If the shapes differ it can't do element by element comparisons, so it returns a boolean scalar.

```
In [309]: m1==m1.T
Out[309]: False
```

You could compare the object ids

```
In [314]: set([id(m1),id(m2),id(m2[:])])
Out[314]: {3029619684, 3036025828, 3036825892}
```

but it doesn't capture the equality of views (`m2[:]`

has the same values, but is a different object).

Also if I change a value, e.g. `m2[2,1]=1`

, it does not change the `id`

, but would change the `tuple(m2.A1)`

hash, and equality tests.