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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 8340e74253257a2e32d343f0c1c9a17e50ddeb47
4
- data.tar.gz: 62eb080153e76cfa116a34c0afcb326e023484f6
3
+ metadata.gz: 6ef086c84ca5a0a24442527f9cfea81b147d521d
4
+ data.tar.gz: 36dc61c090667e648edc3c17cd1339093899cf92
5
5
  SHA512:
6
- metadata.gz: c4cf8db5cc61366fcf80cdabde0ba1f87d93a837f2cff11ca62de37088f4afb02d12df01d4fa2899d3cf35fbe18f9747da7b1ba0bdfea44e116ec319abc494b9
7
- data.tar.gz: d7ea6f0faf629e241cb205fc6e28057b6639d51b1ce2bff4fc654594e0d84bce5fd87c7901c2ac57a6eb1dcc0c8275f239f1df61c03bec0a9d9c009db4d4c68d
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
@@ -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
 
@@ -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
 
@@ -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
 
@@ -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 =~ /OPTIMAL/
16
- return :feasible if status =~ /FEASIBLE/
17
- return :infeasible if status =~ /EMPTY/
18
- return :unbounded if status =~ /UNBOUNDED/
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
@@ -48,6 +48,7 @@ module RAMS
48
48
  error = output + (stderr.gets(nil) || '')
49
49
  puts output if model.verbose && output != ''
50
50
  raise error unless exit_code.value == 0
51
+ return output
51
52
  ensure
52
53
  stdout.close
53
54
  stderr.close
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.2
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-10 00:00:00.000000000 Z
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