amor 0.2.0 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 31492f2a4a6321ec6ad50a028c7e0a072c32131b
4
- data.tar.gz: 2d11c7147c51de95267d0ae69ddefcd858fab2c3
3
+ metadata.gz: 1ec00e3d5906aa7d712edca9dec76af8e9abb836
4
+ data.tar.gz: 0cbe07d9db38b005d5d99d970cd13825f73fc82f
5
5
  SHA512:
6
- metadata.gz: 8b6a4b028958ab03e30430cd6c75b5df531944eaffe99628c2df3d8600f98c98f8fbb2eeda4280e17a58317c112a9fe540204004d2dfe6663e72fdf8d6b70ef4
7
- data.tar.gz: 5efcbc2c466fac5623951a281753b1a3f995cc2cd85b20a6dfe6ec24dd54288ad2e17c64bdd336795f12c1b1e090cf1741d586187d87565b46be6d2b7fad5db0
6
+ metadata.gz: af840f1e2654c95b22fe84de7b15560b802f116f024cd4d709f4d7026307b2220ad2c50aed3a326ab09c3b7cbf6e234fe686eb97464091a524a77ae1de60e6cb
7
+ data.tar.gz: 5ed46fe705dbb87ff6a6201e043205709c7cafd9f420686edf7c85e356b6b87dca2b4ed406f40405f6b5dd2e600172f5b18dd733e25a5964d2ed3987d0755aaf
data/lib/amor/block.rb ADDED
@@ -0,0 +1,24 @@
1
+ module Amor
2
+ class Block
3
+ attr_reader :constraints
4
+
5
+ def initialize
6
+ @constraints = Array.new
7
+ end
8
+
9
+ def add_constraint constraint
10
+ @constraints << constraint
11
+ end
12
+
13
+ # Returns a representation for .dec file format of this block
14
+ # It assumes the block has the specified index
15
+ def dec_string index
16
+ result = ["BLOCK #{index}"]
17
+ @constraints.each do | constraint |
18
+ result << constraint.lp_name
19
+ end
20
+
21
+ result.join("\n")
22
+ end
23
+ end
24
+ end
@@ -1,6 +1,7 @@
1
1
  module Amor
2
2
  class Constraint
3
3
  attr_reader :lhs, :rhs, :relation
4
+ attr_accessor :index
4
5
 
5
6
  def initialize(lhs, relation, rhs)
6
7
  @lhs = Expression.new(lhs)
@@ -19,7 +20,11 @@ module Amor
19
20
  "="
20
21
  end
21
22
 
22
- "#{temp_lhs.remove_constants.lp_string} #{relation_string} #{-temp_lhs.constant_factor}"
23
+ "#{lp_name}: #{temp_lhs.remove_constants.lp_string} #{relation_string} #{-temp_lhs.constant_factor}"
24
+ end
25
+
26
+ def lp_name
27
+ "c#{index+1}"
23
28
  end
24
29
 
25
30
  def to_s
data/lib/amor/model.rb CHANGED
@@ -3,7 +3,7 @@ require 'amor/objective'
3
3
  module Amor
4
4
  class Model
5
5
 
6
- attr_reader :constraints, :solved, :bounded
6
+ attr_reader :constraints, :solved, :bounded, :blocks
7
7
 
8
8
  def initialize
9
9
  @variables = Array.new
@@ -46,7 +46,9 @@ module Amor
46
46
 
47
47
  # Add a constraint
48
48
  def st(constraint)
49
+ constraint.index = @constraints.size
49
50
  @constraints << constraint
51
+ @in_block.add_constraint(constraint) if @in_block
50
52
  return constraint
51
53
  end
52
54
  alias :subject_to :st
@@ -71,7 +73,7 @@ module Amor
71
73
  result = @objective.lp_string
72
74
  result << "\nSubject To\n"
73
75
  result << @constraints.each_with_index.map do |constraint, i|
74
- " c#{i+1}: #{constraint.lp_string}"
76
+ " #{constraint.lp_string}"
75
77
  end.join("\n")
76
78
 
77
79
  # Bounds section
@@ -133,8 +135,17 @@ module Amor
133
135
  def scip
134
136
  self.save_lp('__temp.lp')
135
137
  scip_result = `scip -f __temp.lp`
138
+ File.open('scip.log', 'w') {|file| file.puts scip_result}
136
139
  File.delete('__temp.lp')
137
140
 
141
+ parse_scip_output scip_result
142
+
143
+ rescue Errno::ENOENT => e
144
+ puts "Could not find SCIP. Please make sure that SCIP is installed and you can execute 'scip'."
145
+ raise e
146
+ end
147
+
148
+ def parse_scip_output(scip_result)
138
149
  solution_section = false
139
150
  scip_result.each_line do |line|
140
151
  if line =~ /problem is solved \[([\w\s]*)\]/
@@ -158,9 +169,48 @@ module Amor
158
169
  end
159
170
  end
160
171
  end
172
+ end
173
+
174
+ # Creates a new block and makes sure that constraints added in yield are added to block
175
+ def block
176
+ (@blocks ||= Array.new) << Block.new
177
+ @in_block = @blocks.last
178
+ yield
179
+ @in_block = nil
180
+ end
181
+
182
+ def dec_string
183
+ result = ["PRESOLVED 0", "NBLOCKS #{@blocks.size}"]
184
+
185
+ @blocks.each_with_index do |block, i|
186
+ result << block.dec_string(i + 1)
187
+ end
188
+
189
+ result << "MASTERCONSS"
190
+ # Remaining constraints
191
+ @blocks.inject(@constraints) {|mem, block| mem - block.constraints}.each do |constraint|
192
+ result << constraint.lp_name
193
+ end
194
+
195
+ result.join("\n")
196
+ end
197
+
198
+ def save_dec(filename)
199
+ File.open(filename, 'w') {|file| file.puts self.dec_string}
200
+ end
201
+
202
+ def gcg
203
+ self.save_lp('__temp.lp')
204
+ self.save_dec('__temp.dec')
205
+ gcg_result = `gcg -f __temp.lp -d __temp.dec`
206
+ File.open('gcg.log', 'w') {|file| file.puts gcg_result}
207
+ File.delete('__temp.lp')
208
+ File.delete('__temp.dec')
209
+
210
+ parse_scip_output gcg_result
161
211
 
162
212
  rescue Errno::ENOENT => e
163
- puts "Could not find SCIP. Please make sure that SCIP is installed and you can execute 'scip'."
213
+ puts "Could not find GCG. Please make sure that GCG is installed and you can execute 'gcg'."
164
214
  raise e
165
215
  end
166
216
  end
data/lib/amor/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Amor
2
- VERSION = "0.2.0"
2
+ VERSION = "0.3.0"
3
3
  end
data/lib/amor.rb CHANGED
@@ -6,3 +6,4 @@ require 'amor/model'
6
6
  require 'amor/numeric_extensions'
7
7
  require 'amor/objective'
8
8
  require 'amor/variable'
9
+ require 'amor/block'
@@ -0,0 +1,27 @@
1
+ require 'amor/block'
2
+
3
+ module Amor
4
+ describe Block do
5
+ describe '#add_contraint' do
6
+ it 'adds a constraint' do
7
+ block = Block.new
8
+ constraint = double('Constraint')
9
+ block.add_constraint(constraint)
10
+ expect(block.constraints[0]).to eq(constraint)
11
+ end
12
+ end
13
+
14
+ describe '#dec_string' do
15
+ it 'returns a representation of the block for the .dec file format' do
16
+ constraint1 = double('Constraint')
17
+ allow(constraint1).to receive(:lp_name).and_return('c1')
18
+ constraint2 = double('Constraint')
19
+ allow(constraint2).to receive(:lp_name).and_return('c2')
20
+ block = Block.new
21
+ block.add_constraint(constraint1)
22
+ block.add_constraint(constraint2)
23
+ expect(block.dec_string(1)).to eq("BLOCK 1\nc1\nc2")
24
+ end
25
+ end
26
+ end
27
+ end
@@ -27,7 +27,19 @@ module Amor
27
27
  v1 = model.x(1)
28
28
  v2 = model.x(2)
29
29
  v3 = model.x(3)
30
- expect(Constraint.new(Expression.new([[3, v1], [-2.0, v2], [2, :constant], [2.5, v3]]), :lesser_equal, Expression.new(5)).lp_string).to eq('3 x1 - 2.0 x2 + 2.5 x3 <= 3')
30
+ constraint = model.st(Constraint.new(Expression.new([[3, v1], [-2.0, v2], [2, :constant], [2.5, v3]]), :lesser_equal, Expression.new(5)))
31
+ expect(constraint.lp_string).to eq('c1: 3 x1 - 2.0 x2 + 2.5 x3 <= 3')
32
+ end
33
+ end
34
+
35
+ describe '#lp_name' do
36
+ it 'returns the indexed contraint name' do
37
+ model = Model.new
38
+ v1 = model.x(1)
39
+ v2 = model.x(2)
40
+ v3 = model.x(3)
41
+ constraint = model.st(Constraint.new(Expression.new([[3, v1], [-2.0, v2], [2, :constant], [2.5, v3]]), :lesser_equal, Expression.new(5)))
42
+ expect(constraint.lp_name).to eq("c1")
31
43
  end
32
44
  end
33
45
 
@@ -87,6 +87,18 @@ module Amor
87
87
  @model.st(@constraint)
88
88
  expect(@model.constraints).to include(@constraint)
89
89
  end
90
+
91
+ it 'stores the index, which the constraint has in the model' do
92
+ @model.st(@constraint)
93
+ expect(@model.constraints[0].index).to eq(0)
94
+ end
95
+
96
+ it 'adds constraint to block if a block is given' do
97
+ @model.block do
98
+ @model.st(@constraint)
99
+ end
100
+ expect(@model.blocks.last.constraints).to include(@constraint)
101
+ end
90
102
  end
91
103
 
92
104
 
@@ -180,5 +192,43 @@ module Amor
180
192
  expect(@model.x(1).lb).to eq(0)
181
193
  end
182
194
  end
195
+
196
+ describe '#block' do
197
+ it 'yields' do
198
+ expect { |b| @model.block(&b) }.to yield_control
199
+ end
200
+
201
+ it 'sets @in_block to current block within yield' do
202
+ @model.block do
203
+ expect(@model.instance_variable_get('@in_block').class).to eq(Block)
204
+ end
205
+ end
206
+
207
+ it 'sets @in_block to nil before leaving' do
208
+ @model.block do
209
+ end
210
+ expect(@model.instance_variable_get('@in_block')).to eq(nil)
211
+ end
212
+
213
+ it 'adds a new block to the model' do
214
+ @model.block { }
215
+ expect(@model.blocks.size).to eq(1)
216
+ end
217
+ end
218
+
219
+ describe '#dec_string' do
220
+ it 'returns a string representation of specified decomposition in .dec file format' do
221
+ @model.st(@model.x(1) + @model.x(2) >= 3)
222
+ @model.block do
223
+ @model.st(@model.x(1) + @model.x(3) <= 1)
224
+ @model.st(@model.x(2) - @model.x(4) <= 2)
225
+ end
226
+ @model.block do
227
+ @model.st(@model.x(1) - @model.x(5) >= 1)
228
+ end
229
+ @model.st(@model.x(3) + @model.x(4) == 2)
230
+ expect(@model.dec_string).to eq("PRESOLVED 0\nNBLOCKS 2\nBLOCK 1\nc2\nc3\nBLOCK 2\nc4\nMASTERCONSS\nc1\nc5")
231
+ end
232
+ end
183
233
  end
184
234
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: amor
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Florian Dahms
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-10-24 00:00:00.000000000 Z
11
+ date: 2014-11-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -86,6 +86,7 @@ files:
86
86
  - amor.sublime-project
87
87
  - bin/amor
88
88
  - lib/amor.rb
89
+ - lib/amor/block.rb
89
90
  - lib/amor/constraint.rb
90
91
  - lib/amor/expression.rb
91
92
  - lib/amor/model.rb
@@ -93,6 +94,7 @@ files:
93
94
  - lib/amor/objective.rb
94
95
  - lib/amor/variable.rb
95
96
  - lib/amor/version.rb
97
+ - spec/amor/block_spec.rb
96
98
  - spec/amor/constraint_spec.rb
97
99
  - spec/amor/expression_spec.rb
98
100
  - spec/amor/model_spec.rb
@@ -120,11 +122,12 @@ required_rubygems_version: !ruby/object:Gem::Requirement
120
122
  version: '0'
121
123
  requirements: []
122
124
  rubyforge_project:
123
- rubygems_version: 2.2.2
125
+ rubygems_version: 2.2.1
124
126
  signing_key:
125
127
  specification_version: 4
126
128
  summary: A versatile, yet simple modelling language for mathematical programming
127
129
  test_files:
130
+ - spec/amor/block_spec.rb
128
131
  - spec/amor/constraint_spec.rb
129
132
  - spec/amor/expression_spec.rb
130
133
  - spec/amor/model_spec.rb