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 +4 -4
- data/lib/rulp/rulp.rb +12 -1
- data/lib/solvers/cbc.rb +3 -2
- data/lib/solvers/glpk.rb +11 -5
- data/lib/solvers/gurobi.rb +3 -2
- data/lib/solvers/scip.rb +3 -3
- data/lib/solvers/solver.rb +1 -0
- data/test/test_basic_suite.rb +2 -2
- data/test/test_infeasible.rb +28 -0
- metadata +5 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 29755e45e91f606add5cc434cc9dd4a1cb6fd57a
|
4
|
+
data.tar.gz: e2b000cfe7ffec6160fcdb445eb5a79040bfdbb9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
-
|
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
|
-
|
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 --
|
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
|
-
|
15
|
-
|
16
|
-
|
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
|
-
|
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
|
data/lib/solvers/gurobi.rb
CHANGED
@@ -14,7 +14,7 @@ class Gurobi < Solver
|
|
14
14
|
|
15
15
|
def store_results(variables)
|
16
16
|
rows = IO.read(@outfile).split("\n")
|
17
|
-
|
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
|
-
|
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
|
-
|
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
|
57
|
+
self.unsuccessful = !(Float(objective_str) rescue false)
|
58
|
+
return objective_str.to_f
|
59
59
|
end
|
60
60
|
end
|
data/lib/solvers/solver.rb
CHANGED
data/test/test_basic_suite.rb
CHANGED
@@ -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
|
-
|
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
|
-
|
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.
|
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-
|
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.
|
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:
|