pmoreira
pmoreira

Reputation: 175

Indexing inside a double `for` loop wrongly

I am posting below a simplified code version which reproduces my issue:

import numpy as np

a1 = np.array([[0., (2/3)**(1/2), (1/3)**(1/2)],
           [-(1/2)**(1/2), -(1/6)**(1/2), (1/3)**(1/2)],
           [-(1/2)**(1/2), (1/6)**(1/2), -(1/3)**(1/2)],
           [(1/2)**(1/2), -(1/6)**(1/2), (1/3)**(1/2)],
           [(1/2)**(1/2), (1/6)**(1/2), -(1/3)**(1/2)],
           [0., -(2/3)**(1/2), -(1/3)**(1/2)]])

b1 = np.array([[-1. , 0., 0.],
           [-1/2, (3/4)**(1/2), 0.],
           [1/2, -(1/12)**(1/2), -(2/3)**(1/2)],
           [-1/2, -(3/4)**(1/2), 0.],
           [-1/2, -(1/12)**(1/2), -(2/3)**(1/2)],
           [0., (1/3)**(1/2), -(2/3)**(1/2)]])

a2 = np.array([[(1/2)**(1/2), (1/6)**(1/2), -(1/3)**(1/2)],
           [0., -(2/3)**(1/2), -(1/3)**(1/2)],
           [(1/2)**(1/2), -(1/6)**(1/2), (1/3)**(1/2)],
           [-(1/2)**(1/2), (1/6)**(1/2), -(1/3)**(1/2)],
           [0., (2/3)**(1/2), (1/3)**(1/2)],
           [-(1/2)**(1/2), -(1/6)**(1/2), (1/3)**(1/2)]])

b2 = np.array([[1/2 , -(3/4)**(1/2), 0.],
           [-1., 0., 0.],
           [-1/2, (1/12)**(1/2), (2/3)**(1/2)],
           [-1/2, -(3/4)**(1/2), 0.],
           [0., -(1/3)**(1/2), (2/3)**(1/2)],
           [1/2, (1/12)**(1/2), (2/3)**(1/2)]])


avector = [a1, a2]
bvector = [b1, b2]

cvector = [np.zeros([6, 3])]*2

for i in range(2):
    for j in range(6):
        cvector[i][j] = np.cross(avector[i][j], bvector[i][j])
        print(i, j, cvector[i][j])

print(cvector)

The output would be:

0 0 [ 0.         -0.57735027  0.81649658]
0 1 [-0.5        -0.28867513 -0.81649658]
0 2 [-0.5       -0.8660254  0.       ]
0 3 [ 0.5        -0.28867513 -0.81649658]
0 4 [-0.5        0.8660254  0.       ]
0 5 [ 1.  0.  0.] 
1 0 [-0.5        -0.28867513 -0.81649658]
1 1 [ 0.          0.57735027 -0.81649658]
1 2 [-0.5       -0.8660254  0.       ]
1 3 [-0.5         0.28867513  0.81649658]
1 4 [ 1.  0. -0.]
1 5 [-0.5        0.8660254  0.       ]

[array([[-0.5       , -0.28867513, -0.81649658],
       [ 0.        ,  0.57735027, -0.81649658],
       [-0.5       , -0.8660254 ,  0.        ],
       [-0.5       ,  0.28867513,  0.81649658],
       [ 1.        ,  0.        , -0.        ],
       [-0.5       ,  0.8660254 ,  0.        ]]),
array([[-0.5       , -0.28867513, -0.81649658],
       [ 0.        ,  0.57735027, -0.81649658],
       [-0.5       , -0.8660254 ,  0.        ],
       [-0.5       ,  0.28867513,  0.81649658],
       [ 1.        ,  0.        , -0.        ],
       [-0.5       ,  0.8660254 ,  0.        ]])]

One can note that the first line 0 0 calculated inside the for loop does not match with the matrix cvector[0][0]. I would hope they matched. The same happens with the sixth line 0 5 and the matrix cvector[0][0].

If you change the range(2) to range(1) in the first for loop, you will not see the same behavior and, in my opinion, the correct one.

Does anyone know why it is happening?

Upvotes: 0

Views: 40

Answers (1)

tmdavison
tmdavison

Reputation: 69116

When you create cvector using [np.zeros([6, 3])]*2, you are not creating 2 np.array's. The second instance is simply a view of the first. So, cvector[0] = cvector[1]. Thus, in the loop, you overwrite the i=0 calculations when you do it again for i=1.

Instead, you can create two independent arrays, like so:

cvector = [np.zeros([6, 3]), np.zeros([6, 3])]

and it works as expected:

(0, 0, array([ 0.        , -0.57735027,  0.81649658]))
(0, 1, array([-0.5       , -0.28867513, -0.81649658]))
(0, 2, array([-0.5      , -0.8660254,  0.       ]))
(0, 3, array([ 0.5       , -0.28867513, -0.81649658]))
(0, 4, array([-0.5      ,  0.8660254,  0.       ]))
(0, 5, array([1., 0., 0.]))
(1, 0, array([-0.5       , -0.28867513, -0.81649658]))
(1, 1, array([ 0.        ,  0.57735027, -0.81649658]))
(1, 2, array([-0.5      , -0.8660254,  0.       ]))
(1, 3, array([-0.5       ,  0.28867513,  0.81649658]))
(1, 4, array([ 1.,  0., -0.]))
(1, 5, array([-0.5      ,  0.8660254,  0.       ]))

[array([[ 0.        , -0.57735027,  0.81649658],
       [-0.5       , -0.28867513, -0.81649658],
       [-0.5       , -0.8660254 ,  0.        ],
       [ 0.5       , -0.28867513, -0.81649658],
       [-0.5       ,  0.8660254 ,  0.        ],
       [ 1.        ,  0.        ,  0.        ]]),
 array([[-0.5       , -0.28867513, -0.81649658], 
       [ 0.        ,  0.57735027, -0.81649658],
       [-0.5       , -0.8660254 ,  0.        ],
       [-0.5       ,  0.28867513,  0.81649658],
       [ 1.        ,  0.        , -0.        ],
       [-0.5       ,  0.8660254 ,  0.        ]])]

Consider this example to show why the first array is being overwritten:

In [1]: import numpy as np

In [2]: cvector = [np.zeros([6, 3])]*2

In [3]: cvector
Out[3]: 
[array([[0., 0., 0.],
        [0., 0., 0.],
        [0., 0., 0.],
        [0., 0., 0.],
        [0., 0., 0.],
        [0., 0., 0.]]), 
 array([[0., 0., 0.],
        [0., 0., 0.],
        [0., 0., 0.],
        [0., 0., 0.],
        [0., 0., 0.],
        [0., 0., 0.]])]

In [4]: cvector[0][0] = (1, 2, 3)

In [5]: cvector
Out[5]: 
[array([[1., 2., 3.],
        [0., 0., 0.],
        [0., 0., 0.],
        [0., 0., 0.],
        [0., 0., 0.],
        [0., 0., 0.]]), 
 array([[1., 2., 3.],
        [0., 0., 0.],
        [0., 0., 0.],
        [0., 0., 0.],
        [0., 0., 0.],
        [0., 0., 0.]])]

Note how the first element is overwritten in both cases.

Upvotes: 2

Related Questions