rams 0.1.2 → 0.1.3
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/rams/model.rb +3 -1
- data/lib/rams/solvers/cbc.rb +4 -4
- data/lib/rams/solvers/clp.rb +4 -4
- data/lib/rams/solvers/cplex.rb +3 -3
- data/lib/rams/solvers/glpk.rb +4 -4
- data/lib/rams/solvers/scip.rb +63 -0
- data/lib/rams/solvers/solver.rb +1 -0
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6ef086c84ca5a0a24442527f9cfea81b147d521d
|
4
|
+
data.tar.gz: 36dc61c090667e648edc3c17cd1339093899cf92
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: fe7659717c3e04f74b0ab2e624e0b23cb83f8592d6cabfbf09162c87dafe57ebab179c1af2a1107497c78e6a3ed9ec5ea3b55132c26c33cc1151f7a46032b907
|
7
|
+
data.tar.gz: 008681815a50ec96d8d85120a2863977b535e338871b624d49b9c8fb800e9aedcd444dbc764d24de3a4047ae90ab153ea274fd55fe6fd019b37de37f95c4a63e
|
data/lib/rams/model.rb
CHANGED
@@ -4,6 +4,7 @@ require_relative 'solvers/cbc'
|
|
4
4
|
require_relative 'solvers/clp'
|
5
5
|
require_relative 'solvers/cplex'
|
6
6
|
require_relative 'solvers/glpk'
|
7
|
+
require_relative 'solvers/scip'
|
7
8
|
|
8
9
|
module RAMS
|
9
10
|
# A Model is a collection of:
|
@@ -35,7 +36,8 @@ module RAMS
|
|
35
36
|
cbc: RAMS::Solvers::CBC.new,
|
36
37
|
clp: RAMS::Solvers::CLP.new,
|
37
38
|
cplex: RAMS::Solvers::CPLEX.new,
|
38
|
-
glpk: RAMS::Solvers::GLPK.new
|
39
|
+
glpk: RAMS::Solvers::GLPK.new,
|
40
|
+
scip: RAMS::Solvers::SCIP.new
|
39
41
|
}.freeze
|
40
42
|
|
41
43
|
def initialize
|
data/lib/rams/solvers/cbc.rb
CHANGED
@@ -13,10 +13,10 @@ module RAMS
|
|
13
13
|
def parse_status(_model, lines)
|
14
14
|
return :undefined if lines.count < 1
|
15
15
|
status = lines.first
|
16
|
-
return :optimal if status =~ /
|
17
|
-
return :feasible if status =~ /
|
18
|
-
return :infeasible if status =~ /
|
19
|
-
return :unbounded if status =~ /
|
16
|
+
return :optimal if status =~ /optimal/i
|
17
|
+
return :feasible if status =~ /stopped/i
|
18
|
+
return :infeasible if status =~ /infeasible/i
|
19
|
+
return :unbounded if status =~ /unbounded/i
|
20
20
|
:undefined
|
21
21
|
end
|
22
22
|
|
data/lib/rams/solvers/clp.rb
CHANGED
@@ -13,10 +13,10 @@ module RAMS
|
|
13
13
|
def parse_status(_model, lines)
|
14
14
|
return :undefined if lines.count < 1
|
15
15
|
status = lines.first
|
16
|
-
return :optimal if status =~ /optimal/
|
17
|
-
return :feasible if status =~ /stopped/
|
18
|
-
return :infeasible if status =~ /infeasible/
|
19
|
-
return :unbounded if status =~ /unbounded/
|
16
|
+
return :optimal if status =~ /optimal/i
|
17
|
+
return :feasible if status =~ /stopped/i
|
18
|
+
return :infeasible if status =~ /infeasible/i
|
19
|
+
return :unbounded if status =~ /unbounded/i
|
20
20
|
:undefined
|
21
21
|
end
|
22
22
|
|
data/lib/rams/solvers/cplex.rb
CHANGED
@@ -29,9 +29,9 @@ module RAMS
|
|
29
29
|
|
30
30
|
def parse_status(_model, xml_doc)
|
31
31
|
status = xml_doc.css('CPLEXSolution').css('header').first['solutionStatusString']
|
32
|
-
return :optimal if status =~ /optimal/
|
33
|
-
return :feasible if status =~ /feasible/
|
34
|
-
return :unbounded if status =~ /unbounded/
|
32
|
+
return :optimal if status =~ /optimal/i
|
33
|
+
return :feasible if status =~ /feasible/i
|
34
|
+
return :unbounded if status =~ /unbounded/i
|
35
35
|
:unknown
|
36
36
|
end
|
37
37
|
|
data/lib/rams/solvers/glpk.rb
CHANGED
@@ -12,10 +12,10 @@ module RAMS
|
|
12
12
|
|
13
13
|
def parse_status(_model, lines)
|
14
14
|
status = lines.select { |l| l =~ /^Status/ }.first
|
15
|
-
return :optimal if status =~ /
|
16
|
-
return :feasible if status =~ /
|
17
|
-
return :infeasible if status =~ /
|
18
|
-
return :unbounded if status =~ /
|
15
|
+
return :optimal if status =~ /optimal/i
|
16
|
+
return :feasible if status =~ /feasibe/i
|
17
|
+
return :infeasible if status =~ /empty/i
|
18
|
+
return :unbounded if status =~ /unbounded/i
|
19
19
|
:undefined
|
20
20
|
end
|
21
21
|
|
@@ -0,0 +1,63 @@
|
|
1
|
+
require 'open3'
|
2
|
+
require_relative 'solver'
|
3
|
+
|
4
|
+
module RAMS
|
5
|
+
module Solvers
|
6
|
+
# Interface to SCIP
|
7
|
+
class SCIP < Solver
|
8
|
+
def solve_and_parse(model, model_path, solution_path)
|
9
|
+
output = call_solver model, model_path, solution_path
|
10
|
+
parse_solution model, output
|
11
|
+
end
|
12
|
+
|
13
|
+
def solver_command(model_path, _solution_path, args)
|
14
|
+
['scip', '-c', "read #{model_path}"] + args +
|
15
|
+
['-c', 'optimize', '-c', 'display solution', '-c', 'display dualsolution', '-c', 'quit']
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
def parse_status(_model, lines)
|
21
|
+
return :undefined if lines.count < 1
|
22
|
+
status = lines.select { |l| l =~ /^SCIP Status/ }.first
|
23
|
+
return :optimal if status =~ /optimal/i
|
24
|
+
return :unknown if status =~ /(unknown|infeasible or unbounded)/i
|
25
|
+
return :infeasible if status =~ /infeasible/i
|
26
|
+
return :unbounded if status =~ /unbounded/i
|
27
|
+
:feasible
|
28
|
+
end
|
29
|
+
|
30
|
+
def parse_objective(_model, lines)
|
31
|
+
status = (lines.select { |l| l =~ /^objective value:/ }.first || '').split
|
32
|
+
return nil if status.size < 3
|
33
|
+
status[2].to_f
|
34
|
+
end
|
35
|
+
|
36
|
+
def parse_primal(model, lines)
|
37
|
+
primal = model.variables.values.map { |v| [v, 0.0] }.to_h
|
38
|
+
primal.merge(solution_lines(lines).map do |l|
|
39
|
+
comps = l.split
|
40
|
+
model.variables[comps[0]].nil? ? [] : [model.variables[comps.first], comps[1].to_f]
|
41
|
+
end.reject(&:empty?).to_h)
|
42
|
+
end
|
43
|
+
|
44
|
+
def parse_dual(model, lines)
|
45
|
+
dual = model.constraints.values.map { |c| [c, 0.0] }.to_h
|
46
|
+
dual.merge(solution_lines(lines).map do |l|
|
47
|
+
comps = l.split
|
48
|
+
model.constraints[comps[0]].nil? ? [] : [model.constraints[comps[0]], dual_value(model, comps[1].to_f)]
|
49
|
+
end.reject(&:empty?).to_h)
|
50
|
+
end
|
51
|
+
|
52
|
+
def solution_lines(lines)
|
53
|
+
start_idx = lines.index { |l| l =~ /^objective value:/ }
|
54
|
+
return [] unless start_idx
|
55
|
+
lines[start_idx, lines.count]
|
56
|
+
end
|
57
|
+
|
58
|
+
def dual_value(model, dual)
|
59
|
+
model.sense == :max ? -dual : dual
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
data/lib/rams/solvers/solver.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rams
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ryan J. O'Neil
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-01-
|
11
|
+
date: 2017-01-16 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: A library for solving MILPs in Ruby.
|
14
14
|
email:
|
@@ -27,6 +27,7 @@ files:
|
|
27
27
|
- lib/rams/solvers/clp.rb
|
28
28
|
- lib/rams/solvers/cplex.rb
|
29
29
|
- lib/rams/solvers/glpk.rb
|
30
|
+
- lib/rams/solvers/scip.rb
|
30
31
|
- lib/rams/solvers/solver.rb
|
31
32
|
- lib/rams/variable.rb
|
32
33
|
homepage: https://github.com/ryanjoneil/rams
|