1

I tried to make a random symmetric matrix to test my program. I don't care about the data at all as long as it is symmetric (sufficient randomness is no concern at all).

My first attempt was this:

x=np.random.random((100,100))
x+=x.T

However, np.all(x==x.T) returns False. print x==x.T yields

array([[ True,  True,  True, ..., False, False, False],
   [ True,  True,  True, ..., False, False, False],
   [ True,  True,  True, ..., False, False, False],
   ..., 
   [False, False, False, ...,  True,  True,  True],
   [False, False, False, ...,  True,  True,  True],
   [False, False, False, ...,  True,  True,  True]], dtype=bool)

I tried to run a small test example with n=10 to see what was going on, but that example works just as you would expect it to.

If I do it like this instead:

x=np.random.random((100,100))
x=x+x.T

then it works just fine.

What's going on here? Aren't these statements semantically equivalent? What's the difference?

aestrivex
  • 5,170
  • 2
  • 27
  • 44

1 Answers1

2

Those statements aren't semantically equivalent. x.T returns a view of the original array. in the += case, you're actually changing the values of x as you iterate over it (which changes the values of x.T).

Think of it this way ... When your algorithm gets to index (3,4), it looks something like this in pseudocode:

x[3,4] = x[3,4] + x[4,3]

now, when your iteration gets to (4,3), you do

x[4,3] = x[4,3] + x[3,4]

but, x[3,4] is not what it was when you started iterating.


In the second case, you actually create a new (empty) array and change the elements in the empty array (never writing to x). So the pseudocode looks something like:

y[3,4] = x[3,4] + x[4,3]

and

y[4,3] = x[4,3] + x[3,4]

which obviously will give you a symmetric matrix (y.

mgilson
  • 300,191
  • 65
  • 633
  • 696
  • That makes sense. But it seems like a poor choice of semantics that `x+=` would ever be different than `x=x+`. – aestrivex Jun 13 '13 at 15:55
  • @aestrivex, `x += ` would work as long as `exp` did not read the memory location that was being written to by `x +=` part. It is the same reason why `memmove()` exists in C (and `memcpy()` has undefined behavior when memory regions overlap). If you still want to use `+=`, you can do `x += x.T.copy()`. – Alok Singhal Jun 13 '13 at 16:19
  • 1
    @aestrivex -- Actually, my [highest upvoted question of all time](http://stackoverflow.com/questions/15376509/when-is-i-x-different-from-i-i-x-in-python/15376520#15376520) is explaining the difference between `x += something` and `x = x + something`. – mgilson Jun 13 '13 at 17:12
  • Huh, interesting. I had never heard of `__iadd__` before. Thanks! – aestrivex Jun 13 '13 at 19:11