gecoder 0.8.3 → 0.9.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.
- data/CHANGES +15 -0
- data/README +6 -2
- data/example/equation_system.rb +15 -0
- data/example/magic_sequence.rb +7 -7
- data/example/money.rb +36 -0
- data/example/queens.rb +7 -8
- data/example/send_most_money.rb +1 -1
- data/example/square_tiling.rb +2 -2
- data/example/sudoku-set.rb +11 -12
- data/example/sudoku.rb +40 -45
- data/ext/extconf.rb +0 -0
- data/lib/gecoder/bindings.rb +42 -0
- data/lib/gecoder/bindings/bindings.rb +16 -0
- data/lib/gecoder/interface.rb +2 -1
- data/lib/gecoder/interface/branch.rb +16 -9
- data/lib/gecoder/interface/constraints.rb +410 -451
- data/lib/gecoder/interface/constraints/bool/boolean.rb +205 -213
- data/lib/gecoder/interface/constraints/bool/channel.rb +4 -5
- data/lib/gecoder/interface/constraints/bool/linear.rb +192 -21
- data/lib/gecoder/interface/constraints/bool_enum/channel.rb +43 -39
- data/lib/gecoder/interface/constraints/bool_enum/extensional.rb +43 -49
- data/lib/gecoder/interface/constraints/bool_enum/relation.rb +38 -71
- data/lib/gecoder/interface/constraints/bool_enum_constraints.rb +73 -22
- data/lib/gecoder/interface/constraints/bool_var_constraints.rb +140 -61
- data/lib/gecoder/interface/constraints/extensional_regexp.rb +4 -4
- data/lib/gecoder/interface/constraints/fixnum_enum/element.rb +63 -0
- data/lib/gecoder/interface/constraints/fixnum_enum/operation.rb +65 -0
- data/lib/gecoder/interface/constraints/fixnum_enum_constraints.rb +42 -0
- data/lib/gecoder/interface/constraints/int/arithmetic.rb +131 -130
- data/lib/gecoder/interface/constraints/int/channel.rb +21 -31
- data/lib/gecoder/interface/constraints/int/domain.rb +45 -42
- data/lib/gecoder/interface/constraints/int/linear.rb +85 -239
- data/lib/gecoder/interface/constraints/int/relation.rb +141 -0
- data/lib/gecoder/interface/constraints/int_enum/arithmetic.rb +55 -64
- data/lib/gecoder/interface/constraints/int_enum/channel.rb +35 -37
- data/lib/gecoder/interface/constraints/int_enum/count.rb +53 -78
- data/lib/gecoder/interface/constraints/int_enum/distinct.rb +36 -46
- data/lib/gecoder/interface/constraints/int_enum/element.rb +39 -57
- data/lib/gecoder/interface/constraints/int_enum/equality.rb +15 -19
- data/lib/gecoder/interface/constraints/int_enum/extensional.rb +65 -72
- data/lib/gecoder/interface/constraints/int_enum/sort.rb +42 -45
- data/lib/gecoder/interface/constraints/int_enum_constraints.rb +79 -22
- data/lib/gecoder/interface/constraints/int_var_constraints.rb +215 -44
- data/lib/gecoder/interface/constraints/reifiable_constraints.rb +14 -14
- data/lib/gecoder/interface/constraints/selected_set/select.rb +120 -0
- data/lib/gecoder/interface/constraints/selected_set_constraints.rb +75 -0
- data/lib/gecoder/interface/constraints/set/cardinality.rb +43 -53
- data/lib/gecoder/interface/constraints/set/channel.rb +26 -29
- data/lib/gecoder/interface/constraints/set/connection.rb +89 -152
- data/lib/gecoder/interface/constraints/set/domain.rb +112 -65
- data/lib/gecoder/interface/constraints/set/include.rb +36 -0
- data/lib/gecoder/interface/constraints/set/operation.rb +96 -110
- data/lib/gecoder/interface/constraints/set/relation.rb +114 -137
- data/lib/gecoder/interface/constraints/set_elements/relation.rb +116 -0
- data/lib/gecoder/interface/constraints/set_elements_constraints.rb +97 -0
- data/lib/gecoder/interface/constraints/set_enum/channel.rb +23 -27
- data/lib/gecoder/interface/constraints/set_enum/distinct.rb +18 -19
- data/lib/gecoder/interface/constraints/set_enum/operation.rb +62 -53
- data/lib/gecoder/interface/constraints/set_enum/select.rb +79 -0
- data/lib/gecoder/interface/constraints/set_enum_constraints.rb +73 -23
- data/lib/gecoder/interface/constraints/set_var_constraints.rb +222 -57
- data/lib/gecoder/interface/enum_matrix.rb +4 -4
- data/lib/gecoder/interface/enum_wrapper.rb +71 -22
- data/lib/gecoder/interface/model.rb +167 -12
- data/lib/gecoder/interface/model_sugar.rb +84 -0
- data/lib/gecoder/interface/search.rb +30 -18
- data/lib/gecoder/interface/variables.rb +103 -33
- data/lib/gecoder/version.rb +2 -2
- data/specs/bool_var.rb +19 -12
- data/specs/constraints/{boolean.rb → bool/boolean.rb} +103 -28
- data/specs/constraints/bool/boolean_properties.rb +51 -0
- data/specs/constraints/bool/linear.rb +213 -0
- data/specs/constraints/bool_enum/bool_enum_relation.rb +117 -0
- data/specs/constraints/bool_enum/channel.rb +102 -0
- data/specs/constraints/{extensional.rb → bool_enum/extensional.rb} +32 -101
- data/specs/constraints/constraint_helper.rb +149 -179
- data/specs/constraints/constraint_receivers.rb +103 -0
- data/specs/constraints/constraints.rb +6 -63
- data/specs/constraints/fixnum_enum/element.rb +58 -0
- data/specs/constraints/fixnum_enum/operation.rb +67 -0
- data/specs/constraints/int/arithmetic.rb +149 -0
- data/specs/constraints/int/channel.rb +101 -0
- data/specs/constraints/int/domain.rb +106 -0
- data/specs/constraints/int/linear.rb +183 -0
- data/specs/constraints/int/linear_properties.rb +97 -0
- data/specs/constraints/int/relation.rb +84 -0
- data/specs/constraints/int_enum/arithmetic.rb +72 -0
- data/specs/constraints/int_enum/channel.rb +57 -0
- data/specs/constraints/int_enum/count.rb +72 -0
- data/specs/constraints/int_enum/distinct.rb +80 -0
- data/specs/constraints/int_enum/element.rb +61 -0
- data/specs/constraints/int_enum/equality.rb +29 -0
- data/specs/constraints/int_enum/extensional.rb +224 -0
- data/specs/constraints/int_enum/sort.rb +167 -0
- data/specs/constraints/operands.rb +264 -0
- data/specs/constraints/property_helper.rb +443 -0
- data/specs/constraints/reification_sugar.rb +4 -5
- data/specs/constraints/selected_set/select.rb +56 -0
- data/specs/constraints/selected_set/select_properties.rb +157 -0
- data/specs/constraints/set/cardinality.rb +58 -0
- data/specs/constraints/set/cardinality_properties.rb +46 -0
- data/specs/constraints/set/channel.rb +77 -0
- data/specs/constraints/set/connection.rb +176 -0
- data/specs/constraints/set/domain.rb +197 -0
- data/specs/constraints/set/include.rb +36 -0
- data/specs/constraints/set/operation.rb +132 -0
- data/specs/constraints/set/relation.rb +117 -0
- data/specs/constraints/set_elements/relation.rb +84 -0
- data/specs/constraints/set_enum/channel.rb +80 -0
- data/specs/constraints/set_enum/distinct.rb +59 -0
- data/specs/constraints/set_enum/operation.rb +111 -0
- data/specs/constraints/set_enum/select.rb +73 -0
- data/specs/enum_wrapper.rb +53 -3
- data/specs/int_var.rb +44 -25
- data/specs/model.rb +58 -1
- data/specs/model_sugar.rb +30 -0
- data/specs/search.rb +24 -5
- data/specs/selected_set.rb +39 -0
- data/specs/set_elements.rb +34 -0
- data/specs/set_var.rb +22 -8
- data/specs/spec_helper.rb +206 -6
- data/tasks/distribution.rake +22 -7
- data/tasks/svn.rake +3 -1
- metadata +218 -134
- data/lib/gecoder/interface/constraints/set_enum/selection.rb +0 -217
- data/specs/constraints/arithmetic.rb +0 -351
- data/specs/constraints/bool_enum_relation.rb +0 -160
- data/specs/constraints/cardinality.rb +0 -157
- data/specs/constraints/channel.rb +0 -454
- data/specs/constraints/connection.rb +0 -369
- data/specs/constraints/count.rb +0 -146
- data/specs/constraints/distinct.rb +0 -164
- data/specs/constraints/element.rb +0 -108
- data/specs/constraints/equality.rb +0 -31
- data/specs/constraints/int_domain.rb +0 -70
- data/specs/constraints/int_relation.rb +0 -82
- data/specs/constraints/linear.rb +0 -340
- data/specs/constraints/selection.rb +0 -292
- data/specs/constraints/set_domain.rb +0 -185
- data/specs/constraints/set_operation.rb +0 -285
- data/specs/constraints/set_relation.rb +0 -197
- data/specs/constraints/sort.rb +0 -179
data/specs/constraints/linear.rb
DELETED
@@ -1,340 +0,0 @@
|
|
1
|
-
require File.dirname(__FILE__) + '/../spec_helper'
|
2
|
-
require File.dirname(__FILE__) + '/constraint_helper'
|
3
|
-
|
4
|
-
class LinearSampleProblem < Gecode::Model
|
5
|
-
attr :x
|
6
|
-
attr :y
|
7
|
-
attr :z
|
8
|
-
|
9
|
-
def initialize(x_dom, y_dom, z_dom)
|
10
|
-
@x = self.int_var(x_dom)
|
11
|
-
@y = self.int_var(y_dom)
|
12
|
-
@z = self.int_var(z_dom)
|
13
|
-
branch_on wrap_enum([@x, @y, @z])
|
14
|
-
end
|
15
|
-
end
|
16
|
-
|
17
|
-
class BoolLinearSampleProblem < Gecode::Model
|
18
|
-
attr :x
|
19
|
-
attr :y
|
20
|
-
attr :z
|
21
|
-
|
22
|
-
def initialize
|
23
|
-
@x = self.bool_var
|
24
|
-
@y = self.bool_var
|
25
|
-
@z = self.bool_var
|
26
|
-
branch_on wrap_enum([@x, @y, @z])
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
|
-
class TrueClass
|
31
|
-
def to_i
|
32
|
-
1
|
33
|
-
end
|
34
|
-
end
|
35
|
-
|
36
|
-
class FalseClass
|
37
|
-
def to_i
|
38
|
-
0
|
39
|
-
end
|
40
|
-
end
|
41
|
-
|
42
|
-
describe Gecode::Constraints::Int::Linear do
|
43
|
-
before do
|
44
|
-
@x_dom = 0..2
|
45
|
-
@y_dom = -3..3
|
46
|
-
@z_dom = 0..10
|
47
|
-
@model = LinearSampleProblem.new(@x_dom, @y_dom, @z_dom)
|
48
|
-
@x = @model.x
|
49
|
-
@y = @model.y
|
50
|
-
@z = @model.z
|
51
|
-
|
52
|
-
# For constraint option spec.
|
53
|
-
@invoke_options = lambda do |hash|
|
54
|
-
(@x + @y).must_be.greater_than(@z, hash)
|
55
|
-
@model.solve!
|
56
|
-
end
|
57
|
-
@expect_options = option_expectation do |strength, kind, reif_var|
|
58
|
-
# TODO: this is hard to spec from this level.
|
59
|
-
end
|
60
|
-
end
|
61
|
-
|
62
|
-
it 'should handle addition with a variable' do
|
63
|
-
(@x + @y).must == 0
|
64
|
-
sol = @model.solve!
|
65
|
-
x = sol.x.value
|
66
|
-
y = sol.y.value
|
67
|
-
(x + y).should be_zero
|
68
|
-
end
|
69
|
-
|
70
|
-
it 'should handle addition with multiple variables' do
|
71
|
-
(@x + @y + @z).must == 0
|
72
|
-
sol = @model.solve!
|
73
|
-
x = sol.x.value
|
74
|
-
y = sol.y.value
|
75
|
-
z = sol.z.value
|
76
|
-
(x + y + z).should be_zero
|
77
|
-
end
|
78
|
-
|
79
|
-
it 'should handle subtraction with a variable' do
|
80
|
-
(@x - @y).must == 0
|
81
|
-
sol = @model.solve!
|
82
|
-
x = sol.x.value
|
83
|
-
y = sol.y.value
|
84
|
-
(x - y).should be_zero
|
85
|
-
end
|
86
|
-
|
87
|
-
it 'should handle non-zero constants as right hand side' do
|
88
|
-
(@x + @y).must == 1
|
89
|
-
sol = @model.solve!
|
90
|
-
x = sol.x.value
|
91
|
-
y = sol.y.value
|
92
|
-
(x + y).should equal(1)
|
93
|
-
end
|
94
|
-
|
95
|
-
it 'should handle variables as right hand side' do
|
96
|
-
(@x + @y).must == @z
|
97
|
-
sol = @model.solve!
|
98
|
-
x = sol.x.value
|
99
|
-
y = sol.y.value
|
100
|
-
z = sol.z.value
|
101
|
-
(x + y).should equal(z)
|
102
|
-
end
|
103
|
-
|
104
|
-
it 'should handle linear expressions as right hand side' do
|
105
|
-
(@x + @y).must == @z + @y
|
106
|
-
sol = @model.solve!
|
107
|
-
x = sol.x.value
|
108
|
-
y = sol.y.value
|
109
|
-
z = sol.z.value
|
110
|
-
(x + y).should equal(z + y)
|
111
|
-
end
|
112
|
-
|
113
|
-
it 'should raise error on invalid right hand sides' do
|
114
|
-
lambda{ ((@x + @y).must == 'z') }.should raise_error(TypeError)
|
115
|
-
end
|
116
|
-
|
117
|
-
it 'should handle coefficients other than 1' do
|
118
|
-
(@x * 2 + @y).must == 0
|
119
|
-
sol = @model.solve!
|
120
|
-
x = sol.x.value
|
121
|
-
y = sol.y.value
|
122
|
-
(2*x + y).should equal(0)
|
123
|
-
end
|
124
|
-
|
125
|
-
it 'should handle addition with constants' do
|
126
|
-
(@y + 2).must == 1
|
127
|
-
sol = @model.solve!
|
128
|
-
y = sol.y.value
|
129
|
-
(y + 2).should equal(1)
|
130
|
-
end
|
131
|
-
|
132
|
-
it 'should handle subtraction with a constant' do
|
133
|
-
(@x - 2).must == 0
|
134
|
-
sol = @model.solve!
|
135
|
-
x = sol.x.value
|
136
|
-
(x - 2).should be_zero
|
137
|
-
end
|
138
|
-
|
139
|
-
it 'should a single variable as left hande side' do
|
140
|
-
@x.must == @y + @z
|
141
|
-
sol = @model.solve!
|
142
|
-
x = sol.x.value
|
143
|
-
y = sol.y.value
|
144
|
-
z = sol.z.value
|
145
|
-
x.should equal(y + z)
|
146
|
-
end
|
147
|
-
|
148
|
-
it 'should handle parenthesis' do
|
149
|
-
(@x - (@y + @z)).must == 1
|
150
|
-
sol = @model.solve!
|
151
|
-
x = sol.x.value
|
152
|
-
y = sol.y.value
|
153
|
-
z = sol.z.value
|
154
|
-
(x - (y + z)).should equal(1)
|
155
|
-
end
|
156
|
-
|
157
|
-
it 'should handle multiplication of parenthesis' do
|
158
|
-
(((@x + @y*10)*10 + @z)*10).must == 0
|
159
|
-
sol = @model.solve!
|
160
|
-
x = sol.x.value
|
161
|
-
y = sol.y.value
|
162
|
-
z = sol.z.value
|
163
|
-
(((x + y*10)*10 + z)*10).should equal(0)
|
164
|
-
end
|
165
|
-
|
166
|
-
relations = ['>', '>=', '<', '<=', '==']
|
167
|
-
|
168
|
-
relations.each do |relation|
|
169
|
-
it "should handle #{relation} with constant integers" do
|
170
|
-
(@x + @y).must.send(relation, 1)
|
171
|
-
sol = @model.solve!
|
172
|
-
sol.should_not be_nil
|
173
|
-
(sol.x.value + sol.y.value).should.send(relation, 1)
|
174
|
-
end
|
175
|
-
end
|
176
|
-
|
177
|
-
relations.each do |relation|
|
178
|
-
it "should handle negated #{relation} with constant integers" do
|
179
|
-
(@x + @y).must_not.send(relation, 1)
|
180
|
-
sol = @model.solve!
|
181
|
-
sol.should_not be_nil
|
182
|
-
(sol.x.value + sol.y.value).should_not.send(relation, 1)
|
183
|
-
end
|
184
|
-
end
|
185
|
-
|
186
|
-
it 'should not interfere with other defined multiplication methods' do
|
187
|
-
(@x * :foo).should be_nil
|
188
|
-
end
|
189
|
-
|
190
|
-
it_should_behave_like 'reifiable constraint'
|
191
|
-
end
|
192
|
-
|
193
|
-
describe Gecode::Constraints::Int::Linear, '(with booleans)' do
|
194
|
-
before do
|
195
|
-
@model = BoolLinearSampleProblem.new
|
196
|
-
@x = @model.x
|
197
|
-
@y = @model.y
|
198
|
-
@z = @model.z
|
199
|
-
|
200
|
-
# For constraint option spec.
|
201
|
-
@invoke_options = lambda do |hash|
|
202
|
-
(@x + @y).must_be.greater_than(@z, hash)
|
203
|
-
@model.solve!
|
204
|
-
end
|
205
|
-
@expect_options = option_expectation do |strength, kind, reif_var|
|
206
|
-
# TODO: this is hard to spec from this level.
|
207
|
-
end
|
208
|
-
end
|
209
|
-
|
210
|
-
it 'should handle addition with a variable' do
|
211
|
-
(@x + @y).must == 0
|
212
|
-
sol = @model.solve!
|
213
|
-
x = sol.x.value.to_i
|
214
|
-
y = sol.y.value.to_i
|
215
|
-
(x + y).should be_zero
|
216
|
-
end
|
217
|
-
|
218
|
-
it 'should handle addition with multiple variables' do
|
219
|
-
(@x + @y + @z).must == 0
|
220
|
-
sol = @model.solve!
|
221
|
-
x = sol.x.value.to_i
|
222
|
-
y = sol.y.value.to_i
|
223
|
-
z = sol.z.value.to_i
|
224
|
-
(x + y + z).should be_zero
|
225
|
-
end
|
226
|
-
|
227
|
-
it 'should handle subtraction with a variable' do
|
228
|
-
(@x - @y).must == 0
|
229
|
-
sol = @model.solve!
|
230
|
-
x = sol.x.value.to_i
|
231
|
-
y = sol.y.value.to_i
|
232
|
-
(x - y).should be_zero
|
233
|
-
end
|
234
|
-
|
235
|
-
it 'should handle non-zero constants as right hand side' do
|
236
|
-
(@x + @y).must == 1
|
237
|
-
sol = @model.solve!
|
238
|
-
x = sol.x.value.to_i
|
239
|
-
y = sol.y.value.to_i
|
240
|
-
(x + y).should equal(1)
|
241
|
-
end
|
242
|
-
|
243
|
-
it 'should handle singe booleans as left hand side' do
|
244
|
-
@x.must == @y + 1
|
245
|
-
sol = @model.solve!
|
246
|
-
x = sol.x.value.to_i
|
247
|
-
y = sol.y.value.to_i
|
248
|
-
x.should equal(y + 1)
|
249
|
-
end
|
250
|
-
|
251
|
-
it 'should handle variables as right hand side' do
|
252
|
-
(@x + @y).must == @z
|
253
|
-
sol = @model.solve!
|
254
|
-
x = sol.x.value.to_i
|
255
|
-
y = sol.y.value.to_i
|
256
|
-
z = sol.z.value.to_i
|
257
|
-
(x + y).should equal(z)
|
258
|
-
end
|
259
|
-
|
260
|
-
it 'should handle linear expressions as right hand side' do
|
261
|
-
(@x + @y).must == @z + @y
|
262
|
-
sol = @model.solve!
|
263
|
-
x = sol.x.value.to_i
|
264
|
-
y = sol.y.value.to_i
|
265
|
-
z = sol.z.value.to_i
|
266
|
-
(x + y).should equal(z + y)
|
267
|
-
end
|
268
|
-
|
269
|
-
it 'should raise error on invalid right hand sides' do
|
270
|
-
lambda{ ((@x + @y).must == 'z') }.should raise_error(TypeError)
|
271
|
-
end
|
272
|
-
|
273
|
-
it 'should handle coefficients other than 1' do
|
274
|
-
(@x * 2 + @y).must == 0
|
275
|
-
sol = @model.solve!
|
276
|
-
x = sol.x.value.to_i
|
277
|
-
y = sol.y.value.to_i
|
278
|
-
(2*x + y).should equal(0)
|
279
|
-
end
|
280
|
-
|
281
|
-
it 'should handle addition with constants' do
|
282
|
-
(@y + 1).must == 1
|
283
|
-
sol = @model.solve!
|
284
|
-
y = sol.y.value.to_i
|
285
|
-
(y + 1).should equal(1)
|
286
|
-
end
|
287
|
-
|
288
|
-
it 'should handle subtraction with a constant' do
|
289
|
-
(@x - 1).must == 0
|
290
|
-
sol = @model.solve!
|
291
|
-
x = sol.x.value.to_i
|
292
|
-
(x - 1).should be_zero
|
293
|
-
end
|
294
|
-
|
295
|
-
it 'should handle parenthesis' do
|
296
|
-
(@x - (@y + @z)).must == 1
|
297
|
-
sol = @model.solve!
|
298
|
-
x = sol.x.value.to_i
|
299
|
-
y = sol.y.value.to_i
|
300
|
-
z = sol.z.value.to_i
|
301
|
-
(x - (y + z)).should equal(1)
|
302
|
-
end
|
303
|
-
|
304
|
-
it 'should handle multiplication of parenthesis' do
|
305
|
-
(((@x + @y*10)*10 + @z)*10).must == 0
|
306
|
-
sol = @model.solve!
|
307
|
-
x = sol.x.value.to_i
|
308
|
-
y = sol.y.value.to_i
|
309
|
-
z = sol.z.value.to_i
|
310
|
-
(((x + y*10)*10 + z)*10).should equal(0)
|
311
|
-
end
|
312
|
-
|
313
|
-
relations = ['>', '>=', '<', '<=', '==']
|
314
|
-
|
315
|
-
relations.each do |relation|
|
316
|
-
it "should handle #{relation} with constant integers" do
|
317
|
-
(@x + @y).must.send(relation, 1)
|
318
|
-
sol = @model.solve!
|
319
|
-
sol.should_not be_nil
|
320
|
-
(sol.x.value.to_i + sol.y.value.to_i).should.send(relation, 1)
|
321
|
-
end
|
322
|
-
end
|
323
|
-
|
324
|
-
relations.each do |relation|
|
325
|
-
it "should handle negated #{relation} with constant integers" do
|
326
|
-
(@x + @y).must_not.send(relation, 1)
|
327
|
-
sol = @model.solve!
|
328
|
-
sol.should_not be_nil
|
329
|
-
(sol.x.value.to_i + sol.y.value.to_i).should_not.send(relation, 1)
|
330
|
-
end
|
331
|
-
end
|
332
|
-
|
333
|
-
it 'should not interfere with other defined multiplication methods' do
|
334
|
-
(@x * :foo).should be_nil
|
335
|
-
end
|
336
|
-
|
337
|
-
it_should_behave_like 'reifiable constraint'
|
338
|
-
end
|
339
|
-
|
340
|
-
|
@@ -1,292 +0,0 @@
|
|
1
|
-
require File.dirname(__FILE__) + '/../spec_helper'
|
2
|
-
require File.dirname(__FILE__) + '/constraint_helper'
|
3
|
-
|
4
|
-
class SelectionSampleProblem < Gecode::Model
|
5
|
-
attr :sets
|
6
|
-
attr :set
|
7
|
-
attr :target
|
8
|
-
attr :index
|
9
|
-
|
10
|
-
def initialize
|
11
|
-
@sets = set_var_array(3, [], 0..20)
|
12
|
-
@set = set_var([], 0...3)
|
13
|
-
@target = set_var([], 0..20)
|
14
|
-
@index = int_var(0...3)
|
15
|
-
branch_on wrap_enum([@index])
|
16
|
-
branch_on @sets
|
17
|
-
end
|
18
|
-
end
|
19
|
-
|
20
|
-
# Requires everything that composite behaviour spec requires in addition to
|
21
|
-
# @stub and @expect_constrain_equal .
|
22
|
-
describe 'selection constraint', :shared => true do
|
23
|
-
before do
|
24
|
-
@expect = lambda do |index, relation, target, reif_var, negated|
|
25
|
-
@model.allow_space_access do
|
26
|
-
if target.respond_to? :bind
|
27
|
-
expected_target = [an_instance_of(Gecode::Raw::SetVar)]
|
28
|
-
relation_constraint = :rel
|
29
|
-
else
|
30
|
-
expected_target = expect_constant_set(target)
|
31
|
-
relation_constraint = :dom
|
32
|
-
end
|
33
|
-
if reif_var.nil?
|
34
|
-
if !negated and relation == Gecode::Raw::IRT_EQ and
|
35
|
-
!target.kind_of? Enumerable
|
36
|
-
@expect_constrain_equal.call
|
37
|
-
Gecode::Raw.should_receive(:rel).exactly(0).times
|
38
|
-
Gecode::Raw.should_receive(:dom).exactly(0).times
|
39
|
-
else
|
40
|
-
@expect_constrain_equal.call
|
41
|
-
if relation_constraint == :dom
|
42
|
-
# We can't seem to get any more specific than this with mocks.
|
43
|
-
Gecode::Raw.should_receive(relation_constraint).at_most(:twice)
|
44
|
-
else
|
45
|
-
Gecode::Raw.should_receive(relation_constraint).once.with(
|
46
|
-
an_instance_of(Gecode::Raw::Space),
|
47
|
-
an_instance_of(Gecode::Raw::SetVar), relation, *expected_target)
|
48
|
-
end
|
49
|
-
end
|
50
|
-
else
|
51
|
-
@expect_constrain_equal.call
|
52
|
-
if relation_constraint == :dom
|
53
|
-
Gecode::Raw.should_receive(relation_constraint).at_least(:twice)
|
54
|
-
else
|
55
|
-
expected_target << an_instance_of(Gecode::Raw::BoolVar)
|
56
|
-
Gecode::Raw.should_receive(relation_constraint).once.with(
|
57
|
-
an_instance_of(Gecode::Raw::Space),
|
58
|
-
an_instance_of(Gecode::Raw::SetVar), relation, *expected_target)
|
59
|
-
end
|
60
|
-
end
|
61
|
-
end
|
62
|
-
end
|
63
|
-
|
64
|
-
# For composite spec.
|
65
|
-
@invoke_relation = lambda do |relation, target, negated|
|
66
|
-
if negated
|
67
|
-
@stub.must_not.send(relation, target)
|
68
|
-
else
|
69
|
-
@stub.must.send(relation, target)
|
70
|
-
end
|
71
|
-
@model.solve!
|
72
|
-
end
|
73
|
-
@expect_relation = lambda do |relation, target, negated|
|
74
|
-
@expect.call(@index, relation, target, nil, negated)
|
75
|
-
end
|
76
|
-
|
77
|
-
# For options spec.
|
78
|
-
@invoke_options = lambda do |hash|
|
79
|
-
@stub.must_be.subset_of(@target, hash)
|
80
|
-
@model.solve!
|
81
|
-
end
|
82
|
-
@expect_options = option_expectation do |strength, kind, reif_var|
|
83
|
-
@expect.call(17, Gecode::Raw::SRT_SUB, @target, reif_var, false)
|
84
|
-
end
|
85
|
-
end
|
86
|
-
|
87
|
-
it 'should not disturb normal array access' do
|
88
|
-
@sets[0].should be_kind_of(Gecode::FreeSetVar)
|
89
|
-
end
|
90
|
-
|
91
|
-
it_should_behave_like 'reifiable set constraint'
|
92
|
-
it_should_behave_like 'composite set constraint'
|
93
|
-
end
|
94
|
-
|
95
|
-
describe Gecode::Constraints::SetEnum::Selection, ' (select)' do
|
96
|
-
include GecodeR::Specs::SetHelper
|
97
|
-
|
98
|
-
before do
|
99
|
-
@model = SelectionSampleProblem.new
|
100
|
-
@sets = @model.sets
|
101
|
-
@target = @set = @model.target
|
102
|
-
@index = @model.index
|
103
|
-
@model.branch_on @model.wrap_enum([@set])
|
104
|
-
@stub = @sets[@index]
|
105
|
-
|
106
|
-
@expect_constrain_equal = lambda do
|
107
|
-
Gecode::Raw.should_receive(:selectSet).once.with(
|
108
|
-
an_instance_of(Gecode::Raw::Space),
|
109
|
-
an_instance_of(Gecode::Raw::SetVarArray),
|
110
|
-
an_instance_of(Gecode::Raw::IntVar),
|
111
|
-
an_instance_of(Gecode::Raw::SetVar))
|
112
|
-
end
|
113
|
-
end
|
114
|
-
|
115
|
-
it 'should constrain the specified element of an enum of sets' do
|
116
|
-
@sets[@index].must_be.superset_of([5,7,9])
|
117
|
-
@model.solve!
|
118
|
-
@sets[@index.value].value.should include(5,7,9)
|
119
|
-
end
|
120
|
-
|
121
|
-
it_should_behave_like 'selection constraint'
|
122
|
-
end
|
123
|
-
|
124
|
-
describe Gecode::Constraints::SetEnum::Selection, ' (union)' do
|
125
|
-
include GecodeR::Specs::SetHelper
|
126
|
-
|
127
|
-
before do
|
128
|
-
@model = SelectionSampleProblem.new
|
129
|
-
@sets = @model.sets
|
130
|
-
@set = @model.set
|
131
|
-
@target = @model.target
|
132
|
-
@model.branch_on @model.wrap_enum([@target, @set])
|
133
|
-
@stub = @sets[@set].union
|
134
|
-
|
135
|
-
@expect_constrain_equal = lambda do
|
136
|
-
Gecode::Raw.should_receive(:selectUnion).once.with(
|
137
|
-
an_instance_of(Gecode::Raw::Space),
|
138
|
-
an_instance_of(Gecode::Raw::SetVarArray),
|
139
|
-
an_instance_of(Gecode::Raw::SetVar),
|
140
|
-
an_instance_of(Gecode::Raw::SetVar))
|
141
|
-
end
|
142
|
-
end
|
143
|
-
|
144
|
-
it 'should constrain the selected union of an enum of sets' do
|
145
|
-
@sets[@set].union.must_be.subset_of([5,7,9])
|
146
|
-
@sets[@set].union.must_be.superset_of([5])
|
147
|
-
@model.solve!
|
148
|
-
union = @set.value.inject([]) do |union, i|
|
149
|
-
union += @sets[i].value.to_a
|
150
|
-
end.uniq
|
151
|
-
union.should include(5)
|
152
|
-
(union - [5,7,9]).should be_empty
|
153
|
-
end
|
154
|
-
|
155
|
-
it_should_behave_like 'selection constraint'
|
156
|
-
end
|
157
|
-
|
158
|
-
describe Gecode::Constraints::SetEnum::Selection, ' (intersection)' do
|
159
|
-
include GecodeR::Specs::SetHelper
|
160
|
-
|
161
|
-
before do
|
162
|
-
@model = SelectionSampleProblem.new
|
163
|
-
@sets = @model.sets
|
164
|
-
@set = @model.set
|
165
|
-
@target = @model.target
|
166
|
-
@model.branch_on @model.wrap_enum([@target, @set])
|
167
|
-
@stub = @sets[@set].intersection
|
168
|
-
|
169
|
-
@expect_constrain_equal = lambda do
|
170
|
-
Gecode::Raw.should_receive(:selectInter).once.with(
|
171
|
-
an_instance_of(Gecode::Raw::Space),
|
172
|
-
an_instance_of(Gecode::Raw::SetVarArray),
|
173
|
-
an_instance_of(Gecode::Raw::SetVar),
|
174
|
-
an_instance_of(Gecode::Raw::SetVar))
|
175
|
-
end
|
176
|
-
end
|
177
|
-
|
178
|
-
it 'should constrain the selected intersection of an enum of sets' do
|
179
|
-
@sets[@set].intersection.must_be.subset_of([5,7,9])
|
180
|
-
@sets[@set].intersection.must_be.superset_of([5])
|
181
|
-
@model.solve!
|
182
|
-
intersection = @set.value.inject(nil) do |intersection, i|
|
183
|
-
elements = @sets[i].value.to_a
|
184
|
-
next elements if intersection.nil?
|
185
|
-
intersection &= elements
|
186
|
-
end.uniq
|
187
|
-
intersection.should include(5)
|
188
|
-
(intersection - [5,7,9]).should be_empty
|
189
|
-
end
|
190
|
-
|
191
|
-
it_should_behave_like 'selection constraint'
|
192
|
-
end
|
193
|
-
|
194
|
-
describe Gecode::Constraints::SetEnum::Selection, ' (intersection with universe)' do
|
195
|
-
include GecodeR::Specs::SetHelper
|
196
|
-
|
197
|
-
before do
|
198
|
-
@model = SelectionSampleProblem.new
|
199
|
-
@sets = @model.sets
|
200
|
-
@set = @model.set
|
201
|
-
@target = @model.target
|
202
|
-
@model.branch_on @model.wrap_enum([@target, @set])
|
203
|
-
@universe = [1,2]
|
204
|
-
@stub = @sets[@set].intersection(:with => @universe)
|
205
|
-
|
206
|
-
@expect_constrain_equal = lambda do
|
207
|
-
Gecode::Raw.should_receive(:selectInterIn).once.with(
|
208
|
-
an_instance_of(Gecode::Raw::Space),
|
209
|
-
an_instance_of(Gecode::Raw::SetVarArray),
|
210
|
-
an_instance_of(Gecode::Raw::SetVar),
|
211
|
-
an_instance_of(Gecode::Raw::SetVar),
|
212
|
-
an_instance_of(Gecode::Raw::IntSet))
|
213
|
-
end
|
214
|
-
end
|
215
|
-
|
216
|
-
it 'should constrain the selected intersection of an enum of sets in a universe' do
|
217
|
-
@sets[@set].intersection(:with => @universe).must_be.subset_of([2])
|
218
|
-
@model.solve!
|
219
|
-
intersection = @set.value.inject(@universe) do |intersection, i|
|
220
|
-
intersection &= @sets[i].value.to_a
|
221
|
-
end.uniq
|
222
|
-
intersection.should include(2)
|
223
|
-
(intersection - [1,2]).should be_empty
|
224
|
-
end
|
225
|
-
|
226
|
-
it 'should allow the universe to be specified as a range' do
|
227
|
-
@sets[@set].intersection(:with => 1..2).must_be.subset_of([2])
|
228
|
-
@model.solve!
|
229
|
-
intersection = @set.value.inject(@universe) do |intersection, i|
|
230
|
-
intersection &= @sets[i].value.to_a
|
231
|
-
end.uniq
|
232
|
-
intersection.should include(2)
|
233
|
-
(intersection - [1,2]).should be_empty
|
234
|
-
end
|
235
|
-
|
236
|
-
it 'should raise error if unknown options are specified' do
|
237
|
-
lambda do
|
238
|
-
@sets[@set].intersection(:does_not_exist => nil).must_be.subset_of([2])
|
239
|
-
end.should raise_error(ArgumentError)
|
240
|
-
end
|
241
|
-
|
242
|
-
it 'should raise error if the universe is of the wrong type' do
|
243
|
-
lambda do
|
244
|
-
@sets[@set].intersection(:with => 'foo').must_be.subset_of([2])
|
245
|
-
end.should raise_error(TypeError)
|
246
|
-
end
|
247
|
-
|
248
|
-
it_should_behave_like 'selection constraint'
|
249
|
-
end
|
250
|
-
|
251
|
-
describe Gecode::Constraints::SetEnum::Selection, ' (disjoint)' do
|
252
|
-
include GecodeR::Specs::SetHelper
|
253
|
-
|
254
|
-
before do
|
255
|
-
@model = SelectionSampleProblem.new
|
256
|
-
@sets = @model.sets
|
257
|
-
@set = @model.set
|
258
|
-
@target = @model.target
|
259
|
-
@model.branch_on @model.wrap_enum([@target, @set])
|
260
|
-
|
261
|
-
@expect = lambda do |index|
|
262
|
-
Gecode::Raw.should_receive(:selectDisjoint)
|
263
|
-
end
|
264
|
-
|
265
|
-
# For options spec.
|
266
|
-
@invoke_options = lambda do |hash|
|
267
|
-
@sets[@set].must_be.disjoint(hash)
|
268
|
-
@model.solve!
|
269
|
-
end
|
270
|
-
@expect_options = option_expectation do |strength, kind, reif_var|
|
271
|
-
@expect.call(@set)
|
272
|
-
end
|
273
|
-
end
|
274
|
-
|
275
|
-
it 'should constrain the selected sets to be disjoint' do
|
276
|
-
@sets[0].must_be.superset_of([7,8])
|
277
|
-
@sets[1].must_be.superset_of([5,7,9])
|
278
|
-
@sets[2].must_be.superset_of([6,8,10])
|
279
|
-
@sets[@set].must_be.disjoint
|
280
|
-
@set.size.must > 1
|
281
|
-
@model.solve!.should_not be_nil
|
282
|
-
|
283
|
-
@set.value.to_a.sort.should == [1,2]
|
284
|
-
end
|
285
|
-
|
286
|
-
it 'should not allow negation' do
|
287
|
-
lambda{ @sets[@set].must_not_be.disjoint }.should raise_error(
|
288
|
-
Gecode::MissingConstraintError)
|
289
|
-
end
|
290
|
-
|
291
|
-
it_should_behave_like 'non-reifiable set constraint'
|
292
|
-
end
|