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.
Files changed (34) hide show
  1. data/CHANGES +14 -0
  2. data/lib/gecode.dll +0 -0
  3. data/lib/gecoder/bindings/bindings.rb +104 -46
  4. data/lib/gecoder/interface/binding_changes.rb +1 -301
  5. data/lib/gecoder/interface/branch.rb +15 -11
  6. data/lib/gecoder/interface/constraints.rb +38 -0
  7. data/lib/gecoder/interface/constraints/bool/boolean.rb +56 -52
  8. data/lib/gecoder/interface/constraints/bool/channel.rb +1 -16
  9. data/lib/gecoder/interface/constraints/bool_enum/channel.rb +13 -8
  10. data/lib/gecoder/interface/constraints/bool_enum/extensional.rb +48 -0
  11. data/lib/gecoder/interface/constraints/extensional_regexp.rb +101 -0
  12. data/lib/gecoder/interface/constraints/int/channel.rb +1 -13
  13. data/lib/gecoder/interface/constraints/int_enum/channel.rb +15 -35
  14. data/lib/gecoder/interface/constraints/int_enum/extensional.rb +130 -0
  15. data/lib/gecoder/interface/constraints/set/channel.rb +54 -0
  16. data/lib/gecoder/interface/constraints/set_enum/channel.rb +37 -6
  17. data/lib/gecoder/interface/constraints/set_var_constraints.rb +1 -0
  18. data/lib/gecoder/interface/model.rb +110 -85
  19. data/lib/gecoder/interface/variables.rb +3 -21
  20. data/lib/gecoder/version.rb +1 -1
  21. data/specs/branch.rb +16 -1
  22. data/specs/constraints/bool_enum_relation.rb +6 -6
  23. data/specs/constraints/boolean.rb +31 -25
  24. data/specs/constraints/channel.rb +102 -4
  25. data/specs/constraints/extensional.rb +185 -2
  26. data/specs/constraints/reification_sugar.rb +2 -46
  27. data/specs/model.rb +85 -7
  28. data/tasks/dependencies.txt +1 -0
  29. data/vendor/rust/rust/class.rb +33 -35
  30. data/vendor/rust/rust/templates/ClassDeclarations.rusttpl +1 -1
  31. data/vendor/rust/rust/templates/CxxClassDefinitions.rusttpl +10 -1
  32. metadata +186 -185
  33. data/example/raw_bindings.rb +0 -44
  34. 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
- space = active_space
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
@@ -1,4 +1,4 @@
1
1
  module GecodeR
2
2
  # A string representation of the Gecode/R version.
3
- VERSION = '0.8.2'
3
+ VERSION = '0.8.3'
4
4
  end
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 which
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.must_be.equal_to(true, hash)
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, 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.must_be.equal_to(true, hash)
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, 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.equal_to(true, hash)
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
- Gecode::Raw.should_receive(:rel).once.with(
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::BOT_EQV,
41
- an_instance_of(Gecode::Raw::BoolVar), 1, strength, kind)
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' do
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 the wrong type' do
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 wrap_enum([@int])
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::IntEnum::Channel, ' (one int enum and one set enum)' do
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