wh0
wh0

Reputation: 510

sympy.Matrix hash value difference

I am currently using Python 2.7.3, sympy 0.7.1.rc1 I am constructing two matrices like this:

import sympy as sp

A = sp.Matrix([[0,0,1],[0,1,0],[1,0,0]])
B = sp.Matrix([[0,0,1],[0,1,0],[1,0,0]])

print A
print B
print A==B
print hash(A)
print hash(B)

and the result is...

[0, 0, 1]
[0, 1, 0]
[1, 0, 0]
[0, 0, 1]
[0, 1, 0]
[1, 0, 0]
True
3144597
3144601

The hash value of A,B are different. I need to put these two matrix into a set(), but the hash value are different and then I am unable to do what I intended for. Is it a bug of sympy or I should do it another way?

Upvotes: 1

Views: 544

Answers (2)

Jake Levi
Jake Levi

Reputation: 1742

A practical solution to the problem of hashing a sympy matrix is to pass the matrix to sp.simplify() (which returns an ImmutableDenseMatrix), call the evalf method, and hash the result:

import sympy as sp

A = sp.Matrix([[0,0,1],[0,1,0],[1,0,0]])
B = sp.Matrix([[0,0,1],[0,1,0],[1,0,0]])

print(hash(sp.simplify(A).evalf())) # >>> 4987893712874514770
print(hash(sp.simplify(B).evalf())) # >>> 4987893712874514770
print(type(A))                      # >>> <class 'sympy.matrices.dense.MutableDenseMatrix'>
print(type(sp.simplify(A)))         # >>> <class 'sympy.matrices.immutable.ImmutableDenseMatrix'>
print(type(sp.simplify(A).evalf())) # >>> <class 'sympy.matrices.immutable.ImmutableDenseMatrix'>

As an example of when evalf is necessary, consider a = sqrt(2) + sqrt(3). Calculating a^2 and simplifying gives a^2 = 5 = 2*sqrt(6), so taking the square root again gives a = sqrt(5 + 2*sqrt(6)). Evaluating the difference between these 2 expressions shows that sympy knows these numbers are equal, but the hash values are different unless .evalf() is used:

a = sp.sqrt(2) + sp.sqrt(3)
b = sp.sqrt(5 + 2*sp.sqrt(6))

print(sp.simplify(a - b))           # >>> 0
print(hash(sp.simplify(a)))         # >>> 5078824210580610210
print(hash(sp.simplify(b)))         # >>> 1941379121012922090
print(hash(sp.simplify(a).evalf())) # >>> -6599331494183888331
print(hash(sp.simplify(b).evalf())) # >>> -6599331494183888331

Upvotes: 0

asmeurer
asmeurer

Reputation: 91620

As the commenters noted, you need to update to a newer version of SymPy. In older versions, mutable matrices were hashable, which was incorrect. Now, hash(Matrix([[0,0,1],[0,1,0],[1,0,0]])) raises TypeError as it should. If you want a hashable matrix, use ImmutableMatrix.

Upvotes: 2

Related Questions