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 }