Skip to main content

lu_caching_solver

🧮 Efficient Batch Solving with LU Caching

When you need to solve multiple systems Ax = b with the same coefficient matrix, decomposing A each time is wasteful. Use Matrix#lu to decompose once into L, U and a permutation vector, then implement simple forward/backward substitution for each new right‐hand side.

require 'matrix'

class LUCacheSolver
def initialize(a)
@l, @u, @perm, _ = a.lu
end

def solve(b)
# Apply row permutations
bp = Vector.elements(@perm.map { |i| b[i] })
# Forward substitution Ly = bp
y = forward_substitution(@l, bp)
# Backward substitution Ux = y
backward_substitution(@u, y)
end

private

def forward_substitution(l, b)
n = b.size
y = Array.new(n)
(0...n).each do |i|
sum = (0...i).inject(0) { |s, j| s + l[i, j] * y[j] }
y[i] = (b[i] - sum) / l[i, i]
end
Vector[*y]
end

def backward_substitution(u, y)
n = y.size
x = Array.new(n)
(n-1).downto(0) do |i|
sum = ((i+1)...n).inject(0) { |s, j| s + u[i, j] * x[j] }
x[i] = (y[i] - sum) / u[i, i]
end
Vector[*x]
end
end

# Usage example
a = Matrix[[4.0, 2.0, 0.0], [2.0, 4.0, 2.0], [0.0, 2.0, 4.0]]
solver = LUCacheSolver.new(a)
b1 = Vector[2.0, 4.0, 6.0]
b2 = Vector[1.0, 0.0, 1.0]

puts solver.solve(b1) # => solution for first RHS
puts solver.solve(b2) # => solution for second RHS