rulp 0.0.24 → 0.0.25

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 9477cad891cf0cf2b700a5216742545d3fec329e
4
- data.tar.gz: 605645b0a0059d31c7f7c61cd07661422dcd297e
3
+ metadata.gz: 29755e45e91f606add5cc434cc9dd4a1cb6fd57a
4
+ data.tar.gz: e2b000cfe7ffec6160fcdb445eb5a79040bfdbb9
5
5
  SHA512:
6
- metadata.gz: 14a26446ed7a000c57514f2ab4e849820839f1f7a36ff077d90e67f2c6e12f015cbeea5d2f0ae1f24b435ab9c6f01c8db12a076851b45a7762aaa6a8ebb8dc65
7
- data.tar.gz: 3e603319eeeaaa034e1a9a4daddc61437f78187b5ba553bafb5f0c55c8fe342cb5f24a20f96cd711a125c1441028d42d0d4730085cb679b4d9655f67366f2869
6
+ metadata.gz: 5be883579ca22e2b86d5106204b4cc2213205bf7b0a49147f956522ebd550fa8670e5fa0671bf3ffe1982edaf5eb6a1f690155d21b2e2c5b1427260f508db93b
7
+ data.tar.gz: 31011b0958fe5c4a3b9109db4463099472b905e468afe00d5355c9666b71e4e06ee69091d46858aa46b99227704c572f4b178624cf684d96be96bdb02f785bc1
data/lib/rulp/rulp.rb CHANGED
@@ -21,7 +21,7 @@ module Rulp
21
21
  attr_accessor :expressions
22
22
  extend Rulp::Log
23
23
  self.print_solver_outputs = true
24
-
24
+ self.log_level = Logger::DEBUG
25
25
  MIN = "Minimize"
26
26
  MAX = "Maximize"
27
27
 
@@ -174,8 +174,19 @@ module Rulp
174
174
  Rulp.log(Logger::DEBUG, "Solver took #{time}")
175
175
 
176
176
  Rulp.log(Logger::INFO, "Parsing result")
177
+
178
+ unless solver.outfile
179
+ raise "No output file detected. Solver failed"
180
+ return
181
+ end
182
+
177
183
  solver.store_results(@variables)
178
184
 
185
+ if solver.unsuccessful
186
+ raise "Solve failed: solution infeasible" if IO.read(solver.outfile).downcase.include?("infeasible")
187
+ raise "Solve failed: all units undefined"
188
+ end
189
+
179
190
  solver.remove_lp_file if options[:remove_lp_file]
180
191
  solver.remove_sol_file if options[:remove_sol_file]
181
192
 
data/lib/solvers/cbc.rb CHANGED
@@ -19,7 +19,7 @@ class Cbc < Solver
19
19
 
20
20
  def store_results(variables)
21
21
  rows = IO.read(@outfile).split("\n")
22
- objective = rows[0].split(/\s+/)[-1].to_f
22
+ objective_str = rows[0].split(/\s+/)[-1]
23
23
  vars_by_name = {}
24
24
  rows[1..-1].each do |row|
25
25
  cols = row.strip.split(/\s+/)
@@ -28,6 +28,7 @@ class Cbc < Solver
28
28
  variables.each do |var|
29
29
  var.value = vars_by_name[var.to_s].to_f
30
30
  end
31
- return objective
31
+ self.unsuccessful = rows[0].start_with?('Infeasible')
32
+ return objective_str.to_f
32
33
  end
33
34
  end
data/lib/solvers/glpk.rb CHANGED
@@ -1,6 +1,6 @@
1
1
  class Glpk < Solver
2
2
  def solve
3
- command = "#{executable} --lp #{@filename} %s --cuts --write #{@outfile}"
3
+ command = "#{executable} --lp #{@filename} %s --cuts --output #{@outfile}"
4
4
  command %= options[:gap] ? "--mipgap #{options[:gap]}" : ""
5
5
  exec(command)
6
6
  end
@@ -11,10 +11,16 @@ class Glpk < Solver
11
11
 
12
12
  def store_results(variables)
13
13
  rows = IO.read(@outfile).split("\n")
14
- variables.zip(rows[-variables.count..-1]).each do |var, row|
15
- cols = row.split(" ")
16
- var.value = cols[[1, cols.count - 1].min].to_f
14
+ objective_str = rows[5].split(/\s+/)[-2]
15
+ vars_by_name = {}
16
+ rows[1..-1].each do |row|
17
+ cols = row.strip.split(/\s+/)
18
+ vars_by_name[cols[1].to_s] = cols[3].to_f
17
19
  end
18
- return rows[1].split(" ")[-1]
20
+ variables.each do |var|
21
+ var.value = vars_by_name[var.to_s].to_f
22
+ end
23
+ self.unsuccessful = rows[-3].downcase.include?('infeasible')
24
+ return objective_str.to_f
19
25
  end
20
26
  end
@@ -14,7 +14,7 @@ class Gurobi < Solver
14
14
 
15
15
  def store_results(variables)
16
16
  rows = IO.read(@outfile).split("\n")
17
- objective = rows[0].split(/\s+/)[-1].to_f
17
+ objective_str = rows[0].split(/\s+/)[-1]
18
18
  vars_by_name = {}
19
19
  rows[1..-1].each do |row|
20
20
  cols = row.strip.split(/\s+/)
@@ -23,6 +23,7 @@ class Gurobi < Solver
23
23
  variables.each do |var|
24
24
  var.value = vars_by_name[var.to_s].to_f
25
25
  end
26
- return objective
26
+ self.unsuccessful = rows.length.zero?
27
+ return objective_str.to_f
27
28
  end
28
29
  end
data/lib/solvers/scip.rb CHANGED
@@ -44,7 +44,7 @@ class Scip < Solver
44
44
  stripped = start.sub(/Statistics.+/m, "").strip
45
45
  rows = stripped.split("\n")
46
46
 
47
- objective = rows[0].split(/\s+/)[-1].to_f
47
+ objective_str = rows[0].split(/\s+/)[-1]
48
48
 
49
49
  vars_by_name = {}
50
50
  rows[1..-1].each do |row|
@@ -54,7 +54,7 @@ class Scip < Solver
54
54
  variables.each do |var|
55
55
  var.value = vars_by_name[var.to_s].to_f
56
56
  end
57
-
58
- return objective
57
+ self.unsuccessful = !(Float(objective_str) rescue false)
58
+ return objective_str.to_f
59
59
  end
60
60
  end
@@ -1,5 +1,6 @@
1
1
  class Solver
2
2
  attr_reader :options, :outfile
3
+ attr_accessor :unsuccessful
3
4
 
4
5
  def initialize(filename, options)
5
6
  @options = options
@@ -48,11 +48,11 @@ class BasicSuite < Minitest::Test
48
48
 
49
49
  # Integer variables respect integer bounds
50
50
  Rulp::Min(X_f).(solver)
51
- assert_equal X_f.value, -345.4321
51
+ assert_in_delta X_f.value, -345.4321, 0.001
52
52
 
53
53
  # Integer variables respect integer bounds
54
54
  Rulp::Max(X_f).(solver)
55
- assert_equal X_f.value, 345.4321
55
+ assert_in_delta X_f.value, 345.4321, 0.001
56
56
  end
57
57
  end
58
58
  end
@@ -0,0 +1,28 @@
1
+ require_relative 'test_helper'
2
+ ##
3
+ #
4
+ # Given 50 items of varying prices
5
+ # Get the minimal sum of 10 items that equals at least $15 dollars
6
+ #
7
+ ##
8
+ class InfeasibleTest < Minitest::Test
9
+ def setup
10
+ @items = 30.times.map(&Shop_Item_b)
11
+ items_count = @items.sum
12
+ @items_costs = @items.map{|item| item * Random.rand(1.0...5.0)}.sum
13
+
14
+ @problem =
15
+ Rulp::Min( @items_costs ) [
16
+ items_count >= 10,
17
+ @items_costs >= 150_000
18
+ ]
19
+ end
20
+
21
+ def test_simple
22
+ each_solver do |solver|
23
+ assert_raises RuntimeError do
24
+ @problem.send(solver)
25
+ end
26
+ end
27
+ end
28
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rulp
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.24
4
+ version: 0.0.25
5
5
  platform: ruby
6
6
  authors:
7
7
  - Wouter Coppieters
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-02-03 00:00:00.000000000 Z
11
+ date: 2016-02-29 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: A simple Ruby LP description DSL
14
14
  email: wc@pico.net.nz
@@ -40,6 +40,7 @@ files:
40
40
  - test/test_basic_suite.rb
41
41
  - test/test_boolean.rb
42
42
  - test/test_helper.rb
43
+ - test/test_infeasible.rb
43
44
  - test/test_save_to_file.rb
44
45
  - test/test_simple.rb
45
46
  homepage:
@@ -61,7 +62,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
61
62
  version: '0'
62
63
  requirements: []
63
64
  rubyforge_project:
64
- rubygems_version: 2.2.2
65
+ rubygems_version: 2.4.5
65
66
  signing_key:
66
67
  specification_version: 4
67
68
  summary: Ruby Linear Programming
@@ -69,6 +70,7 @@ test_files:
69
70
  - test/test_basic_suite.rb
70
71
  - test/test_boolean.rb
71
72
  - test/test_helper.rb
73
+ - test/test_infeasible.rb
72
74
  - test/test_save_to_file.rb
73
75
  - test/test_simple.rb
74
76
  has_rdoc: