I have a strange bug in this naive code for Gram-schmidt orthogonalization I wrote for numpy ( v1.21.2 ).
def gram_schmidt(basis):
"""
Compute orthogonal basis from given basis.
Parameters:
basis <- an mxn array-like of vectors in m-space
Returns:
orthogonalized basis as array of shape (m,n)
"""
m, n = basis.shape
orthobasis = np.zeros_like(basis)
quadrances = np.ones(n)
for i, b in enumerate(basis.T):
# initial iteration
if i == 0:
orthobasis[:, i] = b
quadrances[i] = b.T @ b
continue
# subsequent iterations
# get the orthogonal complement vector as the next basis vector in the set
# 1: project onto subspace generated by basis accumulated so far
P = orthobasis[:, :i]
proj_b = P @ ((P.T @ b) / quadrances[:i])
# 2: get the orthogonal vector to the projection
e = b - proj_b
# 3: add this orthogonal vector to the basis being constructed
orthobasis[:, i] = e
# 4: add the quadrance of the new vector
quadrances[i] = e.T @ e
print(f"**iteration {i}**\nb = {b}\nP = {P}\nproj_b = {proj_b}\ne = {e}\northobasis =\n{orthobasis}")
print("-" * 100)
return orthobasis
When I run this code with the following input:
basis = np.stack([ np.array(v) for v in
[[1,1,1,1],
[0,1,1,1],
[0,0,1,1]] ],
axis=1)
gram_schmidt(basis)
I get the output:
**iteration 1**
b = [0 1 1 1]
P = [[1]
[1]
[1]
[1]]
proj_b = [0.75 0.75 0.75 0.75]
e = [-0.75 0.25 0.25 0.25]
orthobasis =
[[1 0 0]
[1 0 0]
[1 0 0]
[1 0 0]]
----------------------------------------------------------------------------------------------------
**iteration 2**
b = [0 0 1 1]
P = [[1 0]
[1 0]
[1 0]
[1 0]]
proj_b = [0.5 0.5 0.5 0.5]
e = [-0.5 -0.5 0.5 0.5]
orthobasis =
[[1 0 0]
[1 0 0]
[1 0 0]
[1 0 0]]
So the unexpected behavior is that step 3 in the gram_schmidt
function does not assign the computed array e
to the i-th column of orthobasis
. You can ignore the correctness of gram_schmidt
as the problem is related to array assignment: the first iteration assigns successfully to the first column, yet the subsequent iterations silently fail. What is even more odd is that if I change e
in step 3 to a hard-coded array (of conforming shape with columns of orthobasis
), it assigns successfully, In the output you can see that starting from the second iteration (iteration 1), there is no change to the columns of orthobasis
; they are always 0!
I am so confused and have lost hours debugging this. I appreciate any assistance!
Each numpy array has a specified data type and can contain elements only of this type. In your example basis
is an array of integers. Then you are initializing orthobasis
using
orthobasis = np.zeros_like(basis)
This makes the data type of orthobasis
the same as basis
, ie it is an array of integers too. When you try to modify entries of this array by assigning to them floats values, these floats are first converted to integers by rounding them toward 0. Thus the array [-0.5 -0.5 0.5 0.5]
becomes an array of zeros.
To fix it, you can initialize orthobasis
as an array of floats:
orthobasis = np.zeros_like(basis, dtype=float)
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.