I am creating symmetric matrices/arrays in Python with NumPy, using a standard method:
x = rand(500,500)
x = (x+x.T)
all(x==x.T)
> True
The implementation detail mentioned by others is called buffering. You can read more about it in the docs on array iteration.
If you look at your failing example in a little more detail:
>>> a = np.random.rand(91, 91)
>>> a += a.T
>>> a[:5, -1]
array([ 0.83818399, 1.06489316, 1.23675312, 0.00379798, 1.08967428])
>>> a[-1, :5]
array([ 0.83818399, 1.06489316, 1.75091827, 0.00416305, 1.76315071])
So the first wrong value is 90*91 + 2 = 8192
, which, unsurprisingly, is what we get from:
>>> np.getbufsize()
8192
And we can also set it higher, and then:
>>> np.setbufsize(16384) # Must be a multiple of 16
8192 # returns the previous buffer size
>>> a = np.random.rand(91, 91)
>>> a += a.T
>>> np.all(a == a.T)
True
Although now:
>>> a = np.random.rand(129, 129)
>>> a += a.T
>>> np.all(a == a.T)
False
This is of course a dangerous thing to rely on for correctness, as it is indeed an implementation detail subject to change.