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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: be4a36c1220ddba30d7a7da9efdcac266659d34e
4
- data.tar.gz: a23d432c3ae635ab871e731b636242dfe5ba07f5
3
+ metadata.gz: d1bb406b225c6e4d0a2ebb85d7fd718bbf7def0a
4
+ data.tar.gz: 4edcbad008f26a175221e69934af3c39a5a013cb
5
5
  SHA512:
6
- metadata.gz: 1d25d5afca198d57ddb31daa26b8b2306851d28169d296ac8015cfdd38d8bfa557459ed6a7e25a9c99bd3ce8523ba379601c6f2f3b2a6527cf6bf035c23ddc60
7
- data.tar.gz: aa0b5a56bc7b9649d4add0046f04ca67f367048e89f99bb3ff5ebbb52a409fa86b1d2f21d01ae77d9ea4b8888034c95e00fef85385d8f6e7d18ef5f98f0319ca
6
+ metadata.gz: bf69bc70073a7e185b4273237e87474a4f4179599b356488cc2c6b6106bdc18a092723198c6afa087c5e2cd9e3b15e012bc5e348d76db81852d343a7fd36f242
7
+ data.tar.gz: 81a28f541725580981f6a5e4121edc8d75a4fe290802e2d0a83745c673ba863a8404b2523769a8823172cd6f70cef4ab0b57bce49393c81cca2340874d8e0173
@@ -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
@@ -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 'variable'
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 :objective, :args, :verbose
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
- # rubocop:disable AbcSize
79
- def to_s
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
@@ -18,7 +18,7 @@ module RAMS
18
18
 
19
19
  def write_model_file(model)
20
20
  model_file = Tempfile.new ['', '.lp']
21
- model_file.write model.to_s
21
+ model_file.write model.to_lp
22
22
  model_file.close
23
23
  model_file
24
24
  end
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
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-17 00:00:00.000000000 Z
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