当前位置: 动力学知识库 > 问答 > 编程问答 >

python - Set of matrices

问题描述:

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.

分享给朋友:
您可能感兴趣的文章:
随机阅读: