Page 2 of 2
Re: Linear equation matrix solver
Posted: Sun Feb 23, 2014 5:32 pm
by KG_is_back
The solver actually calculates the matrix size from the "no. of equations" input, So the code will ignore values if you input too long array. Internally the max buffer size is set to 200 (so 13equations max) but you can easily increase the maximum within the code by simply setting all the float arrays bigger.
Re: Linear equation matrix solver
Posted: Sun Feb 23, 2014 9:28 pm
by digitalwhitebyte
Pure Ruby Gaussian elimination
Code: Select all
# Performs an in-place Gaussian elimination on an NxN matrix 'matrix' (2D array
# of Numeric objects) and an N-element vector 'vector.' (array of N Numerics).
def gaussianElimination(matrix, vector)
0.upto(matrix.length - 2) do |pivotIdx|
# Find the best pivot. This is the one who has the largest absolute value
# relative to his row (scaled partial pivoting). This step can be omitted
# to improve speed at the cost of increased error.
maxRelVal = 0
maxIdx = pivotIdx
(pivotIdx).upto(matrix.length - 1) do |row|
relVal = matrix[row][pivotIdx] / matrix[row].map{ |x| x.abs }.max
if relVal >= maxRelVal
maxRelVal = relVal
maxIdx = row
end
end
# Swap the best pivot row into place.
matrix[pivotIdx], matrix[maxIdx] = matrix[maxIdx], matrix[pivotIdx]
vector[pivotIdx], vector[maxIdx] = vector[maxIdx], vector[pivotIdx]
pivot = matrix[pivotIdx][pivotIdx]
# Loop over each row below the pivot row.
(pivotIdx+1).upto(matrix.length - 1) do |row|
# Find factor so that [this row] = [this row] - factor*[pivot row]
# leaves 0 in the pivot column.
factor = matrix[row][pivotIdx]/pivot
# We know it will be zero.
matrix[row][pivotIdx] = 0.0
# Compute [this row] = [this row] - factor*[pivot row] for the other cols.
(pivotIdx+1).upto(matrix[row].length - 1) do |col|
matrix[row][col] -= factor*matrix[pivotIdx][col]
end
vector[row] -= factor*vector[pivotIdx]
end
end
return [matrix,vector]
end
# Assumes 'matrix' is in row echelon form.
def backSubstitution(matrix, vector)
(matrix.length - 1).downto( 0 ) do |row|
tail = vector[row]
(row+1).upto(matrix.length - 1) do |col|
tail -= matrix[row][col] * vector[col]
matrix[row][col] = 0.0
end
vector[row] = tail / matrix[row][row]
matrix[row][row] = 1.0
end
end
# Example usage:
# A system of equations: matrix * X = vector
matrix =
[
[1.0, 1.0, 1.0, 1.0],
[0.0, 1.0, 2.0, 3.0],
[1.0, 2.0, 4.0, 8.0],
[0.0, 1.0, 4.0, 12.0],
]
vector = [1.0, 0.0, 2.0, 0.0]
# Create a backup for verification.
matrix_backup = Marshal.load(Marshal.dump(matrix))
vector_backup= vector.dup
# Gaussian elemination to put the system in row echelon form.
gaussianElimination(matrix, vector)
watch 'gaussian matrix', matrix
watch 'gaussian vector', vector
# Back-substitution to solve the system.
backSubstitution(matrix, vector)
watch 'back matrix', matrix
watch 'back vector', vector
# Verify the result.
pass = true
0.upto(matrix_backup.length - 1) do |eqn|
sum = 0
0.upto(matrix_backup[eqn].length - 1) do |term|
sum += matrix_backup[eqn][term] * vector[term]
end
if (sum - vector_backup[eqn]).abs > 0.0000000001
pass = false
break
end
end
if pass
watch "PASSED?", "Verification PASSED."
else
watch "PASSED?", "Verification FAILED."
end
Re: Linear equation matrix solver
Posted: Sun Feb 23, 2014 9:54 pm
by MegaHurtz
Came back to a solved problem

Find it easy to apply, hard to understand. Was wondering if one can find X, couldn't X then be solved by integrating it on a loop. Or..?