lib/compsci/simplex.rb in compsci-0.3.1.1 vs lib/compsci/simplex.rb in compsci-0.3.2.1
- old
+ new
@@ -24,39 +24,40 @@
raise(ArgumentError, "a doesn't match c") unless a.first.size == num_vars
@max_pivots = DEFAULT_MAX_PIVOTS
# Problem dimensions; these never change
- @num_non_slack_vars = num_vars
- @num_constraints = num_inequalities
- @num_vars = @num_non_slack_vars + @num_constraints
+ @num_free_vars = num_vars
+ @num_basic_vars = num_inequalities
+ @total_vars = @num_free_vars + @num_basic_vars
# Set up initial matrix A and vectors b, c
- @c = c.map { |flt| -1 * flt } + Array.new(@num_constraints, 0)
+ # store all input values as Rational (via #rationalize)
+ @c = c.map { |flt| -1 * flt.rationalize } + Array.new(@num_basic_vars, 0)
@a = a.map.with_index { |ary, i|
- if ary.size != @num_non_slack_vars
+ if ary.size != @num_free_vars
raise ArgumentError, "a is inconsistent"
end
- # set diagonal to 1 (identity matrix?)
- ary + Array.new(@num_constraints) { |ci| ci == i ? 1 : 0 }
+ # add identity matrix
+ ary.map { |flt| flt.rationalize } +
+ Array.new(@num_basic_vars) { |ci| ci == i ? 1 : 0 }
}
- @b = b
+ @b = b.map { |flt| flt.rationalize }
- # set initial solution: all non-slack variables = 0
- @basic_vars = (@num_non_slack_vars...@num_vars).to_a
+ @basic_vars = (@num_free_vars...@total_vars).to_a
self.update_solution
end
# does not modify vector / matrix
def update_solution
- @x = Array.new(@num_vars, 0)
+ @x = Array.new(@total_vars, 0)
@basic_vars.each { |basic_var|
idx = nil
- @num_constraints.times { |i|
+ @num_basic_vars.times { |i|
if @a[i][basic_var] == 1
- idx =i
+ idx = i
break
end
}
raise(SanityCheck, "no idx for basic_var #{basic_var} in a") unless idx
@x[basic_var] = @b[idx]
@@ -76,11 +77,11 @@
self.pivot
end
end
def current_solution
- @x[0...@num_non_slack_vars]
+ @x[0...@num_free_vars]
end
def can_improve?
!self.entering_variable.nil?
end
@@ -119,11 +120,11 @@
@c = @c.map.with_index { |val, i|
val - @c[pivot_column] * @a[pivot_row][i]
}
# update A and B
- @num_constraints.times { |i|
+ @num_basic_vars.times { |i|
next if i == pivot_row
r = @a[i][pivot_column]
@a[i] = @a[i].map.with_index { |val, j| val - r * @a[pivot_row][j] }
@b[i] = @b[i] - r * @b[pivot_row]
}
@@ -132,10 +133,10 @@
end
def pivot_row(column_ix)
min_ratio = nil
idx = nil
- @num_constraints.times { |i|
+ @num_basic_vars.times { |i|
a, b = @a[i][column_ix], @b[i]
next if a == 0 or (b < 0) ^ (a < 0)
ratio = Rational(b, a)
idx, min_ratio = i, ratio if min_ratio.nil? or ratio <= min_ratio
}