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 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