Skip to content

Instantly share code, notes, and snippets.

@sudeeptarlekar
Created June 11, 2021 08:08
Show Gist options
  • Save sudeeptarlekar/8a60f2981597d1a5fb81b34160ead019 to your computer and use it in GitHub Desktop.
Save sudeeptarlekar/8a60f2981597d1a5fb81b34160ead019 to your computer and use it in GitHub Desktop.
class GaussJordanElimination
attr_reader :max_elements, :matrix, :solution, :sorted_columns
def initialize(max_elements)
@max_elements = max_elements
@matrix = []
@solution = []
@sorted_columns = []
end
def take_input
@matrix = []
@sorted_columns = []
@solution = []
puts "Enter the values of equation comma separated"
max_elements.times do |_n|
temp = gets.chomp.split(',').map(&:to_i)
while temp.count != max_elements + 1 do
puts 'Not valid matrix, give input again'
temp = gets.chomp.split(',').map(&:to_i)
end
matrix << temp
end
end
def print_matrix
matrix.each { |row| puts row.join(' ') }
end
def forward_elimination
for column in 0...@max_elements do
for row in column...@max_elements do
# sort first column in the matrix
sort column(column)
# go to next row if element is 0
next if matrix[row][column] == 0
# if element is diagonal element
# then multiply same by inverse of element to get 1
if column == row
# get inverse of current element
multiplier = 1.0 / matrix[row][column]
#multiply current row with inverse
matrix[row] = multiply_row(row, multiplier)
# if this is first row in matrix
# then go to next iterations
next if row == 0
# else eliminate column elemetns in all above rows
(0...row).each { |i| perform_operation(i, column) }
else
# if element is not diagonal element then eliminatio other column elements
perform_operation(row, column)
end
end
end
solve_system
end
def print_solution
if solution.include? nil
puts "No solution possible"
return
elsif solution.include? 'arbitary'
puts "Infinitely many solutions possible"
return
end
solution.each_with_index { |sol, index| puts "x#{index + 1} = #{sol}" }
end
private
def solve_system
# Each diagonal element contains the 1
(0...@max_elements).reduce(solution) do |arr, i|
# If diagonal element is 0 and RHS is not 0 then x/0 is infinity and hence
# infinitely many solutions possible for system
if matrix[i][i] == 0 && matrix[i][max_elements] != 0
arr << nil
# If both LHS and RHS are 0 then variable can be arbitary
elsif matrix[i][i] == 0 && matrix[i][max_elements] == 0
arr << 'arbitary'
else
arr << matrix[i][max_elements] / matrix[i][i]
end
arr
end
end
def perform_operation(row, column)
multiplied_row = multiply_row(column, matrix[row][column])
if subtract_rows?(multiplied_row[column], matrix[row][column])
matrix[row] = subtract_rows(matrix[row], multiplied_row)
else
matrix[row] = add_rows(matrix[row], multiplied_row)
end
end
def multiply_row(row_number, multiplier)
matrix[row_number].map { |element| element * multiplier }
end
def subtract_rows?(element_1, element_2)
(element_1.negative? && element_2.negative?) || !(element_1.negative? || element_2.negative? )
end
def sort(column)
return if sorted_columns.include? column
sorted_columns << column
for row in column...@max_elements - 1 do
swap_rows(row + 1, row) if matrix[row + 1][column] < matrix[row][column]
end
end
def swap_rows(row_1, row_2)
return if row_2 >= @max_elements
temp = matrix[row_1]
matrix[row_1] = matrix[row_2]
matrix[row_2] = temp
end
def add_rows(row_1, row_2)
(0..max_elements).reduce([]) { |arr, column| arr << row_1[column] + row_2[column] }
end
def subtract_rows(row_1, row_2)
(0..max_elements).reduce([]) { |arr, column| arr << row_1[column] - row_2[column] }
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment