amor 0.2.0 → 0.3.0
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/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
|