rulp 0.0.24 → 0.0.25

Sign up to get free protection for your applications and to get access to all the features.
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: