How can I solve an underdetermined linear system? #489
-
Suppose I have Here is an example, where we need a
|
Beta Was this translation helpful? Give feedback.
Replies: 3 comments 1 reply
-
Following these links, I did the following. I did this in
import numpy as np
import galois
GF = galois.GF(7)
A = GF([[3, 0, 5, 2], [4, 1, 3, 0]])
print(f"A = \n{A}")
b = GF([6, 1])
print(f"b = \n{b}")
Ab = np.hstack((A, np.atleast_2d(b).T))
print(f"Ab = \n{Ab}")
# Must be true for solutions to be consistent
print(np.linalg.matrix_rank(A) == np.linalg.matrix_rank(Ab))
Abrr = Ab.row_reduce()
print(f"Abrr = \n{Abrr}")
for _ in range(10):
x3 = GF.Random() # Independent variable
x4 = GF.Random() # Independent variable
x1 = -GF(4) * x3 - GF(3) * x4 + GF(2) # Dependent variable
x2 = -GF(1) * x3 - GF(2) * x4 + GF(0) # Dependent variable
x = GF([x1, x2, x3, x4])
print(f"x = {x}")
print(np.array_equal(A @ x, b)) From the row-reduced augmented
|
Beta Was this translation helpful? Give feedback.
-
Thank you for your quick answer. It gave me the necessary structure to be able to write a function to do the necessary. This seems to work. I would appreciate if you glance at this and see if there are any obvious mistakes. import numpy as np
import galois
def solve_underdetermined_system(A, b):
n_vars = A.shape[1]
A_rank = np.linalg.matrix_rank(A)
# create augmented matrix
Ab = np.hstack((A, np.atleast_2d(b).T))
# Must be true for solutions to be consistent
if A_rank != np.linalg.matrix_rank(Ab):
return False, None
# reduce the system
Abrr = Ab.row_reduce()
# additionally need reduced row echelon form (RREF)
swaps = []
for i in range(Abrr.shape[0]):
if Abrr[i,i] == 0:
for j in range(i+1,n_vars):
if Abrr[i,j] == 1:
Abrr[:, [i,j]] = Abrr[:, [j,i]]
swaps.append((i,j))
break
# randomly generate some independent variables
n_ind = n_vars - A_rank
ind_vars = A.Random(n_ind)
# compute dependent variables using reduced system and dep vars
dep_vars = -Abrr[:A_rank,A_rank:n_vars]@ind_vars + Abrr[:A_rank,-1]
# x is just concatenation of the two
x = np.hstack((dep_vars, ind_vars))
# Need to swap the variables according to column swaps for RREF
for s in reversed(swaps):
x[s[0]], x[s[1]] = x[s[1]], x[s[0]]
return True, x
p = 5
K = 3
n = 5
GF = galois.GF(p)
A = GF.Random((K,n))
b = GF.Random(K)
print(f"A = \n{A}")
print(f"b = \n{b}")
solved, x = solve_underdetermined_system(A, b)
if solved:
print(f"x = {x}")
print("Solution correct:", np.array_equal(A @ x, b))
else:
print("solution does not exist.")
### Now check lots of cases
noexist = 0
wrong = 0
GF = galois.GF(p)
for i in range(10000):
A = GF.Random((K,n))
b = GF.Random(K)
solved, x = solve_underdetermined_system(A, b)
if solved:
sol_check = np.array_equal(A @ x, b)
if not sol_check:
wrong += 1
else:
noexist += 1
print(f'{noexist=}')
print(f'{wrong=}')
|
Beta Was this translation helpful? Give feedback.
-
I seem to recall that RREF meant that the columns must be swapped as well to put the identity matrix on the left (or right). Wikipedia disagrees with me on these semantics. The P.S. It would be nice to have a cleaned up version of this in the library. |
Beta Was this translation helpful? Give feedback.
Thank you for your quick answer. It gave me the necessary structure to be able to write a function to do the necessary. This seems to work.
I would appreciate if you glance at this and see if there are any obvious mistakes.