gecoder-with-gecode 0.8.2-mswin32 → 0.8.3-mswin32
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 +14 -0
- data/lib/gecode.dll +0 -0
- data/lib/gecoder/bindings/bindings.rb +104 -46
- data/lib/gecoder/interface/binding_changes.rb +1 -301
- data/lib/gecoder/interface/branch.rb +15 -11
- data/lib/gecoder/interface/constraints.rb +38 -0
- data/lib/gecoder/interface/constraints/bool/boolean.rb +56 -52
- data/lib/gecoder/interface/constraints/bool/channel.rb +1 -16
- data/lib/gecoder/interface/constraints/bool_enum/channel.rb +13 -8
- data/lib/gecoder/interface/constraints/bool_enum/extensional.rb +48 -0
- data/lib/gecoder/interface/constraints/extensional_regexp.rb +101 -0
- data/lib/gecoder/interface/constraints/int/channel.rb +1 -13
- data/lib/gecoder/interface/constraints/int_enum/channel.rb +15 -35
- data/lib/gecoder/interface/constraints/int_enum/extensional.rb +130 -0
- data/lib/gecoder/interface/constraints/set/channel.rb +54 -0
- data/lib/gecoder/interface/constraints/set_enum/channel.rb +37 -6
- data/lib/gecoder/interface/constraints/set_var_constraints.rb +1 -0
- data/lib/gecoder/interface/model.rb +110 -85
- data/lib/gecoder/interface/variables.rb +3 -21
- data/lib/gecoder/version.rb +1 -1
- data/specs/branch.rb +16 -1
- data/specs/constraints/bool_enum_relation.rb +6 -6
- data/specs/constraints/boolean.rb +31 -25
- data/specs/constraints/channel.rb +102 -4
- data/specs/constraints/extensional.rb +185 -2
- data/specs/constraints/reification_sugar.rb +2 -46
- data/specs/model.rb +85 -7
- data/tasks/dependencies.txt +1 -0
- data/vendor/rust/rust/class.rb +33 -35
- data/vendor/rust/rust/templates/ClassDeclarations.rusttpl +1 -1
- data/vendor/rust/rust/templates/CxxClassDefinitions.rusttpl +10 -1
- metadata +186 -185
- data/example/raw_bindings.rb +0 -44
- data/specs/binding_changes.rb +0 -76
@@ -8,21 +8,9 @@ module Gecode
|
|
8
8
|
def initialize(model, index)
|
9
9
|
@model = model
|
10
10
|
@index = index
|
11
|
-
@bound_space = @bound_var = nil
|
12
11
|
model.track_variable(self)
|
13
12
|
end
|
14
|
-
|
15
|
-
# Checks whether the variable is cached, i.e. whether it needs to be
|
16
|
-
# rebound after changes to a space.
|
17
|
-
def cached?
|
18
|
-
not @bound_space.nil?
|
19
|
-
end
|
20
|
-
|
21
|
-
# Forces the variable to refresh itself.
|
22
|
-
def refresh
|
23
|
-
@bound_space = nil
|
24
|
-
end
|
25
|
-
|
13
|
+
|
26
14
|
def inspect
|
27
15
|
if assigned?
|
28
16
|
"#<#{self.class} #{domain}>"
|
@@ -54,13 +42,7 @@ module Gecode
|
|
54
42
|
# Binds the int variable to the currently active space of the model,
|
55
43
|
# returning the bound int variable.
|
56
44
|
def bind
|
57
|
-
|
58
|
-
unless @bound_space == space
|
59
|
-
# We have not bound the variable to this space, so we do it now.
|
60
|
-
@bound = space.method(:#{space_bind_method}).call(@index)
|
61
|
-
@bound_space = space
|
62
|
-
end
|
63
|
-
return @bound
|
45
|
+
active_space.method(:#{space_bind_method}).call(@index)
|
64
46
|
end
|
65
47
|
|
66
48
|
private
|
@@ -251,4 +233,4 @@ module Gecode
|
|
251
233
|
end
|
252
234
|
end
|
253
235
|
end
|
254
|
-
end
|
236
|
+
end
|
data/lib/gecoder/version.rb
CHANGED
data/specs/branch.rb
CHANGED
@@ -37,6 +37,16 @@ describe Gecode::Model, ' (integer branch)' do
|
|
37
37
|
@model.solve!.bools.each{ |var| var.should be_assigned }
|
38
38
|
end
|
39
39
|
|
40
|
+
it 'should allow branching on a single integer variable' do
|
41
|
+
@model.branch_on @vars.first
|
42
|
+
@model.solve!.vars.first.should be_assigned
|
43
|
+
end
|
44
|
+
|
45
|
+
it 'should allow branching on a single boolean variable' do
|
46
|
+
@model.branch_on @bools.first
|
47
|
+
@model.solve!.bools.first.should be_assigned
|
48
|
+
end
|
49
|
+
|
40
50
|
supported_var_selectors = {
|
41
51
|
:none => Gecode::Raw::INT_VAR_NONE,
|
42
52
|
:smallest_min => Gecode::Raw::INT_VAR_MIN_MIN,
|
@@ -120,6 +130,11 @@ describe Gecode::Model, ' (set branch)' do
|
|
120
130
|
@model.branch_on @sets
|
121
131
|
@model.solve!.sets.each{ |var| var.should be_assigned }
|
122
132
|
end
|
133
|
+
|
134
|
+
it 'should allow branching on a single set variable' do
|
135
|
+
@model.branch_on @sets.first
|
136
|
+
@model.solve!.sets.first.should be_assigned
|
137
|
+
end
|
123
138
|
|
124
139
|
supported_var_selectors = {
|
125
140
|
:none => Gecode::Raw::SET_VAR_NONE,
|
@@ -167,4 +182,4 @@ describe Gecode::Model, ' (set branch)' do
|
|
167
182
|
@model.branch_on @sets, :foo => 5
|
168
183
|
end.should raise_error(ArgumentError)
|
169
184
|
end
|
170
|
-
end
|
185
|
+
end
|
@@ -15,8 +15,8 @@ class BoolEnumSampleProblem < Gecode::Model
|
|
15
15
|
end
|
16
16
|
end
|
17
17
|
|
18
|
-
# Expects @stub, which contains the started constraint and @compute_result
|
19
|
-
# computes whether the left hand side is true or not.
|
18
|
+
# Expects @stub, which contains the started constraint and @compute_result
|
19
|
+
# which computes whether the left hand side is true or not.
|
20
20
|
describe 'bool enum relation constraint', :shared => true do
|
21
21
|
it 'should handle being constrained to be true' do
|
22
22
|
@stub.must_be.true
|
@@ -76,7 +76,7 @@ describe Gecode::Constraints::BoolEnum::Relation, ' (conjunction)' do
|
|
76
76
|
|
77
77
|
# For constraint option spec.
|
78
78
|
@invoke_options = lambda do |hash|
|
79
|
-
@bools.conjunction.
|
79
|
+
@bools.conjunction.must.equal(@b1, hash)
|
80
80
|
@model.solve!
|
81
81
|
end
|
82
82
|
@expect_options = option_expectation do |strength, kind, reif_var|
|
@@ -94,7 +94,7 @@ describe Gecode::Constraints::BoolEnum::Relation, ' (conjunction)' do
|
|
94
94
|
an_instance_of(Gecode::Raw::BoolVar),
|
95
95
|
anything,
|
96
96
|
an_instance_of(Gecode::Raw::BoolVar),
|
97
|
-
anything, anything
|
97
|
+
anything, anything)
|
98
98
|
Gecode::Raw.should_receive(:rel).once.with(
|
99
99
|
an_instance_of(Gecode::Raw::Space),
|
100
100
|
Gecode::Raw::BOT_AND,
|
@@ -122,7 +122,7 @@ describe Gecode::Constraints::BoolEnum::Relation, ' (disjunction)' do
|
|
122
122
|
|
123
123
|
# For constraint option spec.
|
124
124
|
@invoke_options = lambda do |hash|
|
125
|
-
@bools.disjunction.
|
125
|
+
@bools.disjunction.must.equal(@b1, hash)
|
126
126
|
@model.solve!
|
127
127
|
end
|
128
128
|
@expect_options = option_expectation do |strength, kind, reif_var|
|
@@ -140,7 +140,7 @@ describe Gecode::Constraints::BoolEnum::Relation, ' (disjunction)' do
|
|
140
140
|
an_instance_of(Gecode::Raw::BoolVar),
|
141
141
|
anything,
|
142
142
|
an_instance_of(Gecode::Raw::BoolVar),
|
143
|
-
anything, anything
|
143
|
+
anything, anything)
|
144
144
|
Gecode::Raw.should_receive(:rel).once.with(
|
145
145
|
an_instance_of(Gecode::Raw::Space),
|
146
146
|
Gecode::Raw::BOT_OR,
|
@@ -22,28 +22,22 @@ describe Gecode::Constraints::Bool do
|
|
22
22
|
|
23
23
|
# For constraint option spec.
|
24
24
|
@invoke_options = lambda do |hash|
|
25
|
-
(@b1 | @b2).must_be.
|
25
|
+
(@b1 | @b2).must_be.true(hash)
|
26
26
|
@model.solve!
|
27
27
|
end
|
28
28
|
@expect_options = option_expectation do |strength, kind, reif_var|
|
29
29
|
@model.allow_space_access do
|
30
|
-
|
31
|
-
an_instance_of(Gecode::Raw::Space),
|
32
|
-
an_instance_of(Gecode::Raw::BoolVar),
|
33
|
-
Gecode::Raw::BOT_OR,
|
34
|
-
an_instance_of(Gecode::Raw::BoolVar),
|
35
|
-
an_instance_of(Gecode::Raw::BoolVar),
|
36
|
-
Gecode::Raw::ICL_DEF, Gecode::Raw::PK_DEF)
|
30
|
+
# We only test the non-MiniModel parts.
|
37
31
|
unless reif_var.nil?
|
38
32
|
Gecode::Raw.should_receive(:rel).once.with(
|
39
33
|
an_instance_of(Gecode::Raw::Space),
|
40
|
-
an_instance_of(Gecode::Raw::BoolVar), Gecode::Raw::
|
41
|
-
an_instance_of(Gecode::Raw::BoolVar),
|
34
|
+
an_instance_of(Gecode::Raw::BoolVar), Gecode::Raw::IRT_EQ,
|
35
|
+
an_instance_of(Gecode::Raw::BoolVar), strength, kind)
|
42
36
|
end
|
43
37
|
end
|
44
38
|
end
|
45
39
|
end
|
46
|
-
|
40
|
+
|
47
41
|
it 'should handle single variables constrainted to be true' do
|
48
42
|
@b1.must_be.true
|
49
43
|
b1 = @model.solve!.b1
|
@@ -79,7 +73,7 @@ describe Gecode::Constraints::Bool do
|
|
79
73
|
sol.b1.value.should_not be_true
|
80
74
|
sol.b2.value.should be_true
|
81
75
|
end
|
82
|
-
|
76
|
+
|
83
77
|
it 'should handle negated disjunction' do
|
84
78
|
@b1.must_be.false
|
85
79
|
(@b1 | @b2).must_not_be.true
|
@@ -87,7 +81,7 @@ describe Gecode::Constraints::Bool do
|
|
87
81
|
sol.b1.value.should_not be_true
|
88
82
|
sol.b2.value.should_not be_true
|
89
83
|
end
|
90
|
-
|
84
|
+
|
91
85
|
it 'should handle conjunction' do
|
92
86
|
(@b1 & @b2).must_be.true
|
93
87
|
sol = @model.solve!
|
@@ -142,7 +136,7 @@ describe Gecode::Constraints::Bool do
|
|
142
136
|
sol.b1.value.should_not be_true
|
143
137
|
sol.b2.value.should_not be_true
|
144
138
|
end
|
145
|
-
|
139
|
+
|
146
140
|
it 'should handle imply after must_not' do
|
147
141
|
@b1.must_be.true
|
148
142
|
@b1.must_not.imply @b2
|
@@ -166,7 +160,7 @@ describe Gecode::Constraints::Bool do
|
|
166
160
|
sol.b1.value.should be_true
|
167
161
|
sol.b2.value.should_not be_true
|
168
162
|
end
|
169
|
-
|
163
|
+
|
170
164
|
it 'should handle expressions as right hand side' do
|
171
165
|
@b1.must == (@b2 | @b3)
|
172
166
|
@b2.must_be.true
|
@@ -174,7 +168,7 @@ describe Gecode::Constraints::Bool do
|
|
174
168
|
sol.b1.value.should be_true
|
175
169
|
sol.b2.value.should be_true
|
176
170
|
end
|
177
|
-
|
171
|
+
|
178
172
|
it 'should handle nested expressions as left hand side' do
|
179
173
|
((@b1 & @b2) | @b3 | (@b1 & @b3)).must_be.true
|
180
174
|
@b1.must_be.false
|
@@ -182,7 +176,7 @@ describe Gecode::Constraints::Bool do
|
|
182
176
|
sol.b1.value.should_not be_true
|
183
177
|
sol.b3.value.should be_true
|
184
178
|
end
|
185
|
-
|
179
|
+
|
186
180
|
it 'should handle nested expressions on both side' do
|
187
181
|
((@b1 & @b1) | @b3).must == ((@b1 & @b3) & @b2)
|
188
182
|
@b1.must_be.true
|
@@ -191,7 +185,15 @@ describe Gecode::Constraints::Bool do
|
|
191
185
|
sol.b2.value.should be_true
|
192
186
|
sol.b3.value.should be_true
|
193
187
|
end
|
194
|
-
|
188
|
+
|
189
|
+
it 'should handle nested expressions with implication' do
|
190
|
+
((@b1 & @b1) | @b3).must.imply(@b1 ^ @b2)
|
191
|
+
@b1.must_be.true
|
192
|
+
sol = @model.solve!
|
193
|
+
sol.b1.value.should be_true
|
194
|
+
sol.b2.value.should be_false
|
195
|
+
end
|
196
|
+
|
195
197
|
it 'should handle nested expressions containing exclusive or' do
|
196
198
|
((@b1 ^ @b1) & @b3).must == ((@b2 | @b3) ^ @b2)
|
197
199
|
@b1.must_be.true
|
@@ -201,7 +203,7 @@ describe Gecode::Constraints::Bool do
|
|
201
203
|
sol.b2.value.should_not be_true
|
202
204
|
sol.b3.value.should_not be_true
|
203
205
|
end
|
204
|
-
|
206
|
+
|
205
207
|
it 'should handle nested expressions on both sides with negation' do
|
206
208
|
((@b1 & @b1) | @b3).must_not == ((@b1 | @b3) & @b2)
|
207
209
|
@b1.must_be.true
|
@@ -211,7 +213,7 @@ describe Gecode::Constraints::Bool do
|
|
211
213
|
sol.b2.value.should_not be_true
|
212
214
|
sol.b3.value.should be_true
|
213
215
|
end
|
214
|
-
|
216
|
+
|
215
217
|
it 'should translate reification with a variable right hand side' do
|
216
218
|
@b1.must_be.equal_to(@b2, :reify => @b3)
|
217
219
|
@b1.must_be.true
|
@@ -219,8 +221,8 @@ describe Gecode::Constraints::Bool do
|
|
219
221
|
sol = @model.solve!
|
220
222
|
sol.b3.value.should_not be_true
|
221
223
|
end
|
222
|
-
|
223
|
-
it 'should translate reification with a variable right hand side and negation'
|
224
|
+
|
225
|
+
it 'should translate reification with a variable right hand side and negation' do
|
224
226
|
@b1.must_not_be.equal_to(@b2, :reify => @b3)
|
225
227
|
@b1.must_be.true
|
226
228
|
@b2.must_be.false
|
@@ -228,9 +230,13 @@ describe Gecode::Constraints::Bool do
|
|
228
230
|
sol.b3.value.should be_true
|
229
231
|
end
|
230
232
|
|
231
|
-
it 'should raise error on right hand sides of
|
233
|
+
it 'should raise error on right hand sides of incorrect type given to #==' do
|
232
234
|
lambda{ @b1.must == 'hello' }.should raise_error(TypeError)
|
233
235
|
end
|
234
|
-
|
236
|
+
|
237
|
+
it 'should raise error on right hand sides of incorrect type given to #imply' do
|
238
|
+
lambda{ @b1.must.imply 'hello' }.should raise_error(TypeError)
|
239
|
+
end
|
240
|
+
|
235
241
|
it_should_behave_like 'reifiable constraint'
|
236
|
-
end
|
242
|
+
end
|
@@ -26,10 +26,23 @@ class BoolChannelSampleProblem < Gecode::Model
|
|
26
26
|
@int = int_var(0..3)
|
27
27
|
@bool = bool_var
|
28
28
|
|
29
|
-
branch_on
|
29
|
+
branch_on @int
|
30
30
|
end
|
31
31
|
end
|
32
32
|
|
33
|
+
class SetChannelSampleProblem < Gecode::Model
|
34
|
+
attr :bool_enum
|
35
|
+
attr :set
|
36
|
+
|
37
|
+
def initialize
|
38
|
+
@bool_enum = bool_var_array(4)
|
39
|
+
@set = set_var([], 0..3)
|
40
|
+
|
41
|
+
branch_on @bool_enum
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
|
33
46
|
describe Gecode::Constraints::IntEnum::Channel, ' (two int enums)' do
|
34
47
|
before do
|
35
48
|
@model = ChannelSampleProblem.new
|
@@ -73,10 +86,10 @@ describe Gecode::Constraints::IntEnum::Channel, ' (two int enums)' do
|
|
73
86
|
lambda{ @elements.must.channel 'hello' }.should raise_error(TypeError)
|
74
87
|
end
|
75
88
|
|
76
|
-
it_should_behave_like 'reifiable constraint'
|
89
|
+
it_should_behave_like 'non-reifiable constraint'
|
77
90
|
end
|
78
91
|
|
79
|
-
describe Gecode::Constraints::
|
92
|
+
describe Gecode::Constraints::SetEnum::Channel::IntChannelConstraint, ' (channel with set as right hand side)' do
|
80
93
|
before do
|
81
94
|
@model = ChannelSampleProblem.new
|
82
95
|
@positions = @model.positions
|
@@ -113,7 +126,7 @@ describe Gecode::Constraints::IntEnum::Channel, ' (one int enum and one set enum
|
|
113
126
|
it_should_behave_like 'non-reifiable set constraint'
|
114
127
|
end
|
115
128
|
|
116
|
-
describe Gecode::Constraints::SetEnum, ' (channel with set as left hand side)' do
|
129
|
+
describe Gecode::Constraints::SetEnum::Channel::IntChannelConstraint, ' (channel with set as left hand side)' do
|
117
130
|
before do
|
118
131
|
@model = ChannelSampleProblem.new
|
119
132
|
@positions = @model.positions
|
@@ -354,3 +367,88 @@ describe Gecode::Constraints::BoolEnum::Channel, ' (int variable as lhs with boo
|
|
354
367
|
|
355
368
|
it_should_behave_like 'channel constraint between bool enum and int variable'
|
356
369
|
end
|
370
|
+
|
371
|
+
# Requires @model, @bool_enum and @set. Also requires @place_constraint which
|
372
|
+
# is a method that takes four variables: a boolean enum, a set variable,
|
373
|
+
# whether or not the constraint should be negated and a hash of options, and
|
374
|
+
# places the channel constraint on them.
|
375
|
+
describe 'channel constraint between set variable and bool enum', :shared => true do
|
376
|
+
before do
|
377
|
+
@invoke_options = lambda do |hash|
|
378
|
+
@place_constraint.call(@bools, @set, false, hash)
|
379
|
+
@model.solve!
|
380
|
+
end
|
381
|
+
@expect_options = option_expectation do |strength, kind, reif_var|
|
382
|
+
Gecode::Raw.should_receive(:channel).once.with(
|
383
|
+
an_instance_of(Gecode::Raw::Space),
|
384
|
+
an_instance_of(Gecode::Raw::BoolVarArray),
|
385
|
+
an_instance_of(Gecode::Raw::SetVar))
|
386
|
+
end
|
387
|
+
end
|
388
|
+
|
389
|
+
it 'should channel the bool enum with the set variable' do
|
390
|
+
@set.must_be.superset_of [0, 2]
|
391
|
+
@place_constraint.call(@bools, @set, false, {})
|
392
|
+
@model.solve!.should_not be_nil
|
393
|
+
set_values = @set.value
|
394
|
+
@bools.values.each_with_index do |bool, index|
|
395
|
+
bool.should == set_values.include?(index)
|
396
|
+
end
|
397
|
+
end
|
398
|
+
|
399
|
+
it 'should not allow negation' do
|
400
|
+
lambda do
|
401
|
+
@place_constraint.call(@bools, @set, true, {})
|
402
|
+
end.should raise_error(Gecode::MissingConstraintError)
|
403
|
+
end
|
404
|
+
|
405
|
+
it_should_behave_like 'non-reifiable set constraint'
|
406
|
+
end
|
407
|
+
|
408
|
+
describe Gecode::Constraints::Set::Channel, ' (set variable as lhs with bool enum)' do
|
409
|
+
before do
|
410
|
+
@model = SetChannelSampleProblem.new
|
411
|
+
@bools = @model.bool_enum
|
412
|
+
@set = @model.set
|
413
|
+
|
414
|
+
@place_constraint = lambda do |bools, set, negate, options|
|
415
|
+
unless negate
|
416
|
+
set.must.channel(bools, options)
|
417
|
+
else
|
418
|
+
set.must_not.channel(bools, options)
|
419
|
+
end
|
420
|
+
end
|
421
|
+
end
|
422
|
+
|
423
|
+
it 'should raise error if a boolean enum is not given as right hand side' do
|
424
|
+
lambda do
|
425
|
+
@set.must.channel 'hello'
|
426
|
+
end.should raise_error(TypeError)
|
427
|
+
end
|
428
|
+
|
429
|
+
it_should_behave_like 'channel constraint between set variable and bool enum'
|
430
|
+
end
|
431
|
+
|
432
|
+
describe Gecode::Constraints::Set::Channel, ' (bool enum as lhs with set variable)' do
|
433
|
+
before do
|
434
|
+
@model = SetChannelSampleProblem.new
|
435
|
+
@bools = @model.bool_enum
|
436
|
+
@set = @model.set
|
437
|
+
|
438
|
+
@place_constraint = lambda do |bools, set, negate, options|
|
439
|
+
unless negate
|
440
|
+
bools.must.channel(set, options)
|
441
|
+
else
|
442
|
+
bools.must_not.channel(set, options)
|
443
|
+
end
|
444
|
+
end
|
445
|
+
end
|
446
|
+
|
447
|
+
it 'should raise error if an integer variable is not given as right hand side' do
|
448
|
+
lambda do
|
449
|
+
@bools.must.channel 'hello'
|
450
|
+
end.should raise_error(TypeError)
|
451
|
+
end
|
452
|
+
|
453
|
+
it_should_behave_like 'channel constraint between set variable and bool enum'
|
454
|
+
end
|
@@ -44,7 +44,7 @@ describe 'tuple constraint', :shared => true do
|
|
44
44
|
it_should_behave_like 'non-reifiable constraint'
|
45
45
|
end
|
46
46
|
|
47
|
-
describe Gecode::Constraints::IntEnum::Extensional do
|
47
|
+
describe Gecode::Constraints::IntEnum::Extensional, ' (tuple constraint)' do
|
48
48
|
before do
|
49
49
|
@model = Gecode::Model.new
|
50
50
|
@tuples = [[1,7], [5,1]]
|
@@ -77,7 +77,7 @@ describe Gecode::Constraints::IntEnum::Extensional do
|
|
77
77
|
it_should_behave_like 'tuple constraint'
|
78
78
|
end
|
79
79
|
|
80
|
-
describe Gecode::Constraints::BoolEnum::Extensional do
|
80
|
+
describe Gecode::Constraints::BoolEnum::Extensional, ' (tuple constraint)' do
|
81
81
|
before do
|
82
82
|
@model = Gecode::Model.new
|
83
83
|
@tuples = [[true, false, true], [false, false, true]]
|
@@ -109,3 +109,186 @@ describe Gecode::Constraints::BoolEnum::Extensional do
|
|
109
109
|
|
110
110
|
it_should_behave_like 'tuple constraint'
|
111
111
|
end
|
112
|
+
|
113
|
+
# Assumes that @variables, @expected_array, @value1, @value2 (must not
|
114
|
+
# equal @value1) and @regexp are defined.
|
115
|
+
describe 'regular expression constraint', :shared => true do
|
116
|
+
before do
|
117
|
+
@invoke_options = lambda do |hash|
|
118
|
+
@variables.must.match(@regexp, hash)
|
119
|
+
@model.solve!
|
120
|
+
end
|
121
|
+
@expect_options = option_expectation do |strength, kind, reif_var|
|
122
|
+
Gecode::Raw.should_receive(:extensional).once.with(
|
123
|
+
an_instance_of(Gecode::Raw::Space),
|
124
|
+
@expected_array,
|
125
|
+
an_instance_of(Gecode::Raw::REG), strength, kind)
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
it 'should handle values grouped in a single array' do
|
130
|
+
@variables.must.match [@value1, @value2, @value1]
|
131
|
+
@model.solve!.should_not be_nil
|
132
|
+
@variables.values.should == [@value1, @value2, @value1]
|
133
|
+
end
|
134
|
+
|
135
|
+
it 'should allow nested groups of values' do
|
136
|
+
@variables.must.match [@value1, [@value2, [@value1]]]
|
137
|
+
@model.solve!.should_not be_nil
|
138
|
+
@variables.values.should == [@value1, @value2, @value1]
|
139
|
+
end
|
140
|
+
|
141
|
+
it 'should handle the repeat operation' do
|
142
|
+
@variables.must.match [@value1, @model.repeat([@value2], 1, 2)]
|
143
|
+
@model.solve!.should_not be_nil
|
144
|
+
@variables.values.should == [@value1, @value2, @value2]
|
145
|
+
end
|
146
|
+
|
147
|
+
it 'should handle repeat operations that do not encase constant values in arrays' do
|
148
|
+
@variables.must.match [@value1, @model.repeat(@value2, 1, 2)]
|
149
|
+
@model.solve!.should_not be_nil
|
150
|
+
@variables.values.should == [@value1, @value2, @value2]
|
151
|
+
end
|
152
|
+
|
153
|
+
it 'should handle nested repeat operations' do
|
154
|
+
@variables.must.match [[@model.repeat(@model.repeat([@value2], 1, 3), 1, 2)]]
|
155
|
+
@model.solve!.should_not be_nil
|
156
|
+
@variables.values.should == [@value2, @value2, @value2]
|
157
|
+
end
|
158
|
+
|
159
|
+
it 'should handle nested repeat operations (2)' do
|
160
|
+
@variables.must.match [[@model.repeat([@model.repeat(@value2, 1, 3)], 1, 2)]]
|
161
|
+
@model.solve!.should_not be_nil
|
162
|
+
@variables.values.should == [@value2, @value2, @value2]
|
163
|
+
end
|
164
|
+
|
165
|
+
it 'should interpret the repeat operation with the last argument omitted as only giving a lower bound' do
|
166
|
+
@variables.must.match [@value1, @model.repeat([@value2], 1)]
|
167
|
+
@model.solve!.should_not be_nil
|
168
|
+
@variables.values.should == [@value1, @value2, @value2]
|
169
|
+
end
|
170
|
+
|
171
|
+
it 'should interpret the repeat operation with all but the first argument omitted as not giving any bound' do
|
172
|
+
@variables.must.match [@model.repeat(@value2), @value1, @value1, @value1]
|
173
|
+
@model.solve!.should_not be_nil
|
174
|
+
@variables.values.should == [@value1, @value1, @value1]
|
175
|
+
end
|
176
|
+
|
177
|
+
it 'should interpret the repeat operation with all but the first argument omitted as not giving any bound (2)' do
|
178
|
+
@variables.must.match [@model.repeat(@value2)]
|
179
|
+
@model.solve!.should_not be_nil
|
180
|
+
@variables.values.should == [@value2, @value2, @value2]
|
181
|
+
end
|
182
|
+
|
183
|
+
it 'should translate at_most_once(reg) to repeat(reg, 0, 1)' do
|
184
|
+
@model.should_receive(:repeat).once.with([@value1], 0, 1)
|
185
|
+
@model.at_most_once [@value1]
|
186
|
+
end
|
187
|
+
|
188
|
+
it 'should translate at_least_once(reg) to repeat(reg, 1)' do
|
189
|
+
@model.should_receive(:repeat).once.with([@value1], 1)
|
190
|
+
@model.at_least_once [@value1]
|
191
|
+
end
|
192
|
+
|
193
|
+
it 'should raise error if the right hand side is not an enumeration' do
|
194
|
+
lambda do
|
195
|
+
@variables.must.match Object.new
|
196
|
+
end.should raise_error(TypeError)
|
197
|
+
end
|
198
|
+
|
199
|
+
it 'should raise error if the right hand side does not a regexp of the right type' do
|
200
|
+
lambda do
|
201
|
+
@variables.must.match [@value1, 'foo']
|
202
|
+
end.should raise_error(TypeError)
|
203
|
+
end
|
204
|
+
|
205
|
+
it 'should raise error if the right hand side contains a nested element of an incorrect type' do
|
206
|
+
lambda do
|
207
|
+
@variables.must.match [@value1, [@value2, 'foo']]
|
208
|
+
end.should raise_error(TypeError)
|
209
|
+
end
|
210
|
+
|
211
|
+
it 'should raise error if the repeat operation is given arguments of incorrect type (2)' do
|
212
|
+
lambda do
|
213
|
+
@variables.must.match @model.repeat(@value1, [0], 1)
|
214
|
+
end.should raise_error(TypeError)
|
215
|
+
end
|
216
|
+
|
217
|
+
it 'should raise error if the repeat operation is given arguments of incorrect type (3)' do
|
218
|
+
lambda do
|
219
|
+
@variables.must.match @model.repeat(@value1, 0, [1])
|
220
|
+
end.should raise_error(TypeError)
|
221
|
+
end
|
222
|
+
|
223
|
+
it 'should raise error if the repeat operation is given arguments of incorrect type' do
|
224
|
+
lambda do
|
225
|
+
@variables.must.match @model.repeat('foo', 0, 1)
|
226
|
+
end.should raise_error(TypeError)
|
227
|
+
end
|
228
|
+
|
229
|
+
it 'should not allow negation' do
|
230
|
+
lambda do
|
231
|
+
@variables.must_not.match @regexp
|
232
|
+
end.should raise_error(Gecode::MissingConstraintError)
|
233
|
+
end
|
234
|
+
|
235
|
+
it_should_behave_like 'non-reifiable constraint'
|
236
|
+
end
|
237
|
+
|
238
|
+
describe Gecode::Constraints::IntEnum::Extensional, ' (regexp constraint)' do
|
239
|
+
before do
|
240
|
+
@model = Gecode::Model.new
|
241
|
+
@variables = @digits = @model.int_var_array(3, 0..9)
|
242
|
+
@model.branch_on @digits
|
243
|
+
@expected_array = an_instance_of Gecode::Raw::IntVarArray
|
244
|
+
@value1 = 3
|
245
|
+
@value2 = 5
|
246
|
+
@regexp = [1, @model.any(3, 4), @model.at_most_once(5)]
|
247
|
+
end
|
248
|
+
|
249
|
+
it 'should handle the any operation' do
|
250
|
+
@digits.must.match [1, @model.any(1, 2, 3), 3]
|
251
|
+
@model.solve!.should_not be_nil
|
252
|
+
values = @digits.values
|
253
|
+
values.size.should == 3
|
254
|
+
values.should == values.sort
|
255
|
+
end
|
256
|
+
|
257
|
+
it 'should handle the any operator with nested expressions' do
|
258
|
+
@digits.must.match [1, @model.any(@model.at_least_once(2), [3, 5])]
|
259
|
+
@digits[2].must < 4
|
260
|
+
@model.solve!.should_not be_nil
|
261
|
+
@digits.values.should == [1,2,2]
|
262
|
+
end
|
263
|
+
|
264
|
+
it_should_behave_like 'regular expression constraint'
|
265
|
+
end
|
266
|
+
|
267
|
+
describe Gecode::Constraints::BoolEnum::Extensional, ' (regexp constraint)' do
|
268
|
+
before do
|
269
|
+
@model = Gecode::Model.new
|
270
|
+
@variables = @bools = @model.bool_var_array(3)
|
271
|
+
@model.branch_on @bools
|
272
|
+
@expected_array = an_instance_of Gecode::Raw::BoolVarArray
|
273
|
+
@value1 = true
|
274
|
+
@value2 = false
|
275
|
+
@regexp = [true, @model.any(true, false), @model.at_most_once(true)]
|
276
|
+
end
|
277
|
+
|
278
|
+
it 'should handle the any operation' do
|
279
|
+
@bools.must.match [@model.repeat(@model.any(true, false))]
|
280
|
+
@bools[0].must_be.true
|
281
|
+
@bools[1].must_be.false
|
282
|
+
@model.solve!.should_not be_nil
|
283
|
+
@bools[0].value.should be_true
|
284
|
+
@bools[1].value.should be_false
|
285
|
+
end
|
286
|
+
|
287
|
+
it 'should handle the any operator with nested expressions' do
|
288
|
+
@bools.must.match [@model.any(@model.at_least_once(true), [false])]
|
289
|
+
@model.solve!.should_not be_nil
|
290
|
+
@bools.values.should == [true, true, true]
|
291
|
+
end
|
292
|
+
|
293
|
+
it_should_behave_like 'regular expression constraint'
|
294
|
+
end
|