rams 0.1.4 → 0.1.5
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/constraint.rb +0 -6
- data/lib/rams/expression.rb +0 -7
- data/lib/rams/formatters/lp.rb +59 -0
- data/lib/rams/model.rb +11 -24
- data/lib/rams/solvers/solver.rb +1 -1
- data/lib/rams/variable.rb +0 -13
- 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: d1bb406b225c6e4d0a2ebb85d7fd718bbf7def0a
|
4
|
+
data.tar.gz: 4edcbad008f26a175221e69934af3c39a5a013cb
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: bf69bc70073a7e185b4273237e87474a4f4179599b356488cc2c6b6106bdc18a092723198c6afa087c5e2cd9e3b15e012bc5e348d76db81852d343a7fd36f242
|
7
|
+
data.tar.gz: 81a28f541725580981f6a5e4121edc8d75a4fe290802e2d0a83745c673ba863a8404b2523769a8823172cd6f70cef4ab0b57bce49393c81cca2340874d8e0173
|
data/lib/rams/constraint.rb
CHANGED
@@ -23,12 +23,6 @@ module RAMS
|
|
23
23
|
"c#{id}"
|
24
24
|
end
|
25
25
|
|
26
|
-
def to_s
|
27
|
-
lhs_s = lhs.map { |v, c| "#{c >= 0 ? '+ ' : ''}#{c} #{v.name} " }.join
|
28
|
-
sense_s = sense == :== ? '=' : sense.to_s
|
29
|
-
"#{name}: #{lhs_s}#{sense_s} #{rhs}"
|
30
|
-
end
|
31
|
-
|
32
26
|
@next_id = 0
|
33
27
|
|
34
28
|
def self.next_id
|
data/lib/rams/expression.rb
CHANGED
@@ -67,13 +67,6 @@ module RAMS
|
|
67
67
|
RAMS::Constraint.new(lhs(other), :>=, rhs(other))
|
68
68
|
end
|
69
69
|
|
70
|
-
def to_s
|
71
|
-
vars_s = coefficients.map { |v, c| "#{c >= 0 ? '+ ' : ''}#{c} #{v.name} " }.join
|
72
|
-
sign_s = constant >= 0 ? '+ ' : ''
|
73
|
-
const_s = constant == 0 ? '' : "#{sign_s}#{constant}"
|
74
|
-
vars_s + const_s
|
75
|
-
end
|
76
|
-
|
77
70
|
private
|
78
71
|
|
79
72
|
def merge_variables(other)
|
@@ -0,0 +1,59 @@
|
|
1
|
+
module RAMS
|
2
|
+
module Formatters
|
3
|
+
# LP formatter
|
4
|
+
class LP
|
5
|
+
# rubocop:disable AbcSize
|
6
|
+
def self.format(model)
|
7
|
+
<<-LP
|
8
|
+
#{model.sense}
|
9
|
+
obj: #{expression model.objective}
|
10
|
+
st
|
11
|
+
#{model.constraints.values.map { |c| constraint c }.join "\n "}
|
12
|
+
bounds
|
13
|
+
#{model.variables.values.map { |v| bounds v }.join "\n "}
|
14
|
+
general
|
15
|
+
#{model.variables.values.select { |v| v.type == :integer }.map(&:name).join "\n "}
|
16
|
+
binary
|
17
|
+
#{model.variables.values.select { |v| v.type == :binary }.map(&:name).join "\n "}
|
18
|
+
end
|
19
|
+
LP
|
20
|
+
end
|
21
|
+
# rubocop:enable AbcSize
|
22
|
+
|
23
|
+
def self.expression(expr)
|
24
|
+
expr_terms = terms(expr.coefficients)
|
25
|
+
expr_terms << constant(expr.constant) unless expr.constant.zero?
|
26
|
+
expr_terms.join(' ').sub(/^\+\s*/, '')
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.constraint(cons)
|
30
|
+
sense_s = cons.sense == :== ? '=' : cons.sense.to_s
|
31
|
+
"#{cons.name}: #{terms(cons.lhs).join(' ').sub(/^\+\s*/, '')} #{sense_s} " +
|
32
|
+
constant(cons.rhs).sub(/^\+\s*/, '')
|
33
|
+
end
|
34
|
+
|
35
|
+
def self.terms(coef)
|
36
|
+
coef.map { |v, c| variable(v, c) }
|
37
|
+
end
|
38
|
+
|
39
|
+
def self.variable(var, coeff)
|
40
|
+
"#{constant(coeff)} #{var.name}"
|
41
|
+
end
|
42
|
+
|
43
|
+
def self.constant(const)
|
44
|
+
"#{const >= 0 ? '+' : '-'} #{const.abs}"
|
45
|
+
end
|
46
|
+
|
47
|
+
def self.bounds(var)
|
48
|
+
return bounds_binary(var) if var.type == :binary
|
49
|
+
"#{var.low.nil? ? '-inf' : var.low} <= #{var.name} <= #{var.high.nil? ? '+inf' : var.high}"
|
50
|
+
end
|
51
|
+
|
52
|
+
def self.bounds_binary(var)
|
53
|
+
low_s = var.low.nil? ? 0.0 : [0.0, var.low].max
|
54
|
+
high_s = var.high.nil? ? 1.0 : [1.0, var.high].min
|
55
|
+
"#{low_s} <= #{var.name} <= #{high_s}"
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
data/lib/rams/model.rb
CHANGED
@@ -1,10 +1,12 @@
|
|
1
1
|
require 'tempfile'
|
2
|
-
require_relative '
|
2
|
+
require_relative 'expression'
|
3
|
+
require_relative 'formatters/lp'
|
3
4
|
require_relative 'solvers/cbc'
|
4
5
|
require_relative 'solvers/clp'
|
5
6
|
require_relative 'solvers/cplex'
|
6
7
|
require_relative 'solvers/glpk'
|
7
8
|
require_relative 'solvers/scip'
|
9
|
+
require_relative 'variable'
|
8
10
|
|
9
11
|
module RAMS
|
10
12
|
# A Model is a collection of:
|
@@ -29,8 +31,9 @@ module RAMS
|
|
29
31
|
# m.solve
|
30
32
|
#
|
31
33
|
class Model
|
32
|
-
attr_accessor :
|
34
|
+
attr_accessor :args, :verbose
|
33
35
|
attr_reader :solver, :sense, :variables, :constraints
|
36
|
+
attr_writer :objective
|
34
37
|
|
35
38
|
SOLVERS = {
|
36
39
|
cbc: RAMS::Solvers::CBC.new,
|
@@ -69,34 +72,18 @@ module RAMS
|
|
69
72
|
constraints[constraint.name] = constraint
|
70
73
|
end
|
71
74
|
|
75
|
+
def objective
|
76
|
+
@objective || Expression.new(variables.values.first => 0)
|
77
|
+
end
|
78
|
+
|
72
79
|
def solve
|
73
80
|
raise(ArgumentError, 'model has no variables') if variables.empty?
|
74
81
|
raise(ArgumentError, 'model has no constraints') if constraints.empty?
|
75
82
|
SOLVERS[solver].solve self
|
76
83
|
end
|
77
84
|
|
78
|
-
|
79
|
-
|
80
|
-
<<-LP
|
81
|
-
#{sense}
|
82
|
-
obj: #{feasible_objective.is_a?(Variable) ? feasible_objective.name : feasible_objective}
|
83
|
-
st
|
84
|
-
#{constraints.values.map(&:to_s).join("\n ")}
|
85
|
-
bounds
|
86
|
-
#{variables.values.map(&:to_s).join("\n ")}
|
87
|
-
general
|
88
|
-
#{variables.values.select { |v| v.type == :integer }.map(&:name).join("\n ")}
|
89
|
-
binary
|
90
|
-
#{variables.values.select { |v| v.type == :binary }.map(&:name).join("\n ")}
|
91
|
-
end
|
92
|
-
LP
|
93
|
-
end
|
94
|
-
# rubocop:enable AbcSize
|
95
|
-
|
96
|
-
private
|
97
|
-
|
98
|
-
def feasible_objective
|
99
|
-
objective || variables.values.first
|
85
|
+
def to_lp
|
86
|
+
RAMS::Formatters::LP.format self
|
100
87
|
end
|
101
88
|
end
|
102
89
|
end
|
data/lib/rams/solvers/solver.rb
CHANGED
data/lib/rams/variable.rb
CHANGED
@@ -26,23 +26,10 @@ module RAMS
|
|
26
26
|
"v#{id}"
|
27
27
|
end
|
28
28
|
|
29
|
-
def to_s
|
30
|
-
return to_s_binary if type == :binary
|
31
|
-
"#{low.nil? ? '-inf' : low} <= #{name} <= #{high.nil? ? '+inf' : high}"
|
32
|
-
end
|
33
|
-
|
34
29
|
@next_id = 0
|
35
30
|
|
36
31
|
def self.next_id
|
37
32
|
@next_id += 1
|
38
33
|
end
|
39
|
-
|
40
|
-
private
|
41
|
-
|
42
|
-
def to_s_binary
|
43
|
-
low_s = low.nil? ? 0.0 : [0.0, low].max
|
44
|
-
high_s = high.nil? ? 1.0 : [1.0, high].min
|
45
|
-
"#{low_s} <= #{name} <= #{high_s}"
|
46
|
-
end
|
47
34
|
end
|
48
35
|
end
|
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.5
|
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-26 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: A library for solving MILPs in Ruby.
|
14
14
|
email:
|
@@ -20,6 +20,7 @@ files:
|
|
20
20
|
- lib/rams.rb
|
21
21
|
- lib/rams/constraint.rb
|
22
22
|
- lib/rams/expression.rb
|
23
|
+
- lib/rams/formatters/lp.rb
|
23
24
|
- lib/rams/model.rb
|
24
25
|
- lib/rams/numeric.rb
|
25
26
|
- lib/rams/solution.rb
|