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 +4 -4
- data/lib/amor/block.rb +24 -0
- data/lib/amor/constraint.rb +6 -1
- data/lib/amor/model.rb +53 -3
- data/lib/amor/version.rb +1 -1
- data/lib/amor.rb +1 -0
- data/spec/amor/block_spec.rb +27 -0
- data/spec/amor/constraint_spec.rb +13 -1
- data/spec/amor/model_spec.rb +50 -0
- metadata +6 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1ec00e3d5906aa7d712edca9dec76af8e9abb836
|
4
|
+
data.tar.gz: 0cbe07d9db38b005d5d99d970cd13825f73fc82f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
data/lib/amor/constraint.rb
CHANGED
@@ -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
|
-
"
|
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
|
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
data/lib/amor.rb
CHANGED
@@ -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
|
-
|
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
|
|
data/spec/amor/model_spec.rb
CHANGED
@@ -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.
|
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-
|
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.
|
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
|