gecoder 0.8.1 → 0.8.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -17,6 +17,55 @@ class ArithmeticSampleProblem < Gecode::Model
17
17
  end
18
18
  end
19
19
 
20
+ # Construct a method placing expectations for an arithmetic constraint with the
21
+ # specified arity (number of variables before must) and the specified name in
22
+ # Gecode.
23
+ def arithmetic_expectation(gecode_name, arity)
24
+ lambda do |relation, rhs, strength, kind, reif_var, negated|
25
+ # Construct the arguments expected to be passed to the Gecode variant of
26
+ # the constraint.
27
+ rhs = an_instance_of(Gecode::Raw::IntVar) if rhs.respond_to? :bind
28
+ expected_gecode_arguments = [an_instance_of(Gecode::Raw::Space)]
29
+ arity.times do
30
+ expected_gecode_arguments << an_instance_of(Gecode::Raw::IntVar)
31
+ end
32
+ can_use_single_gecode_constraint = reif_var.nil? && !negated &&
33
+ relation == Gecode::Raw::IRT_EQ && !rhs.kind_of?(Fixnum)
34
+ if can_use_single_gecode_constraint
35
+ expected_gecode_arguments << rhs
36
+ else
37
+ expected_gecode_arguments << an_instance_of(Gecode::Raw::IntVar)
38
+ end
39
+ expected_gecode_arguments.concat([strength, kind])
40
+
41
+ # Create the actual method producing the expectation.
42
+ @model.allow_space_access do
43
+ if reif_var.nil?
44
+ if can_use_single_gecode_constraint
45
+ Gecode::Raw.should_receive(gecode_name).once.with(
46
+ *expected_gecode_arguments)
47
+ Gecode::Raw.should_receive(:rel).exactly(0).times
48
+ else
49
+ Gecode::Raw.should_receive(gecode_name).once.with(
50
+ *expected_gecode_arguments)
51
+ Gecode::Raw.should_receive(:rel).once.with(
52
+ an_instance_of(Gecode::Raw::Space),
53
+ an_instance_of(Gecode::Raw::IntVar),
54
+ relation, rhs, strength, kind)
55
+ end
56
+ else
57
+ Gecode::Raw.should_receive(gecode_name).once.with(
58
+ *expected_gecode_arguments)
59
+ Gecode::Raw.should_receive(:rel).once.with(
60
+ an_instance_of(Gecode::Raw::Space),
61
+ an_instance_of(Gecode::Raw::IntVar), relation, rhs,
62
+ an_instance_of(Gecode::Raw::BoolVar),
63
+ strength, kind)
64
+ end
65
+ end
66
+ end
67
+ end
68
+
20
69
  # Requires @stub, @target, @model and @expect.
21
70
  describe 'arithmetic constraint', :shared => true do
22
71
  before do
@@ -228,46 +277,7 @@ describe Gecode::Constraints::Int::Arithmetic, ' (multiplication)' do
228
277
  @stub = @var * @var2
229
278
  @target = @model.var3
230
279
 
231
- # Creates an expectation corresponding to the specified input.
232
- @expect = lambda do |relation, rhs, strength, kind, reif_var, negated|
233
- @model.allow_space_access do
234
- rhs = an_instance_of(Gecode::Raw::IntVar) if rhs.respond_to? :bind
235
- if reif_var.nil?
236
- if !negated and relation == Gecode::Raw::IRT_EQ and
237
- !rhs.kind_of? Fixnum
238
- Gecode::Raw.should_receive(:mult).once.with(
239
- an_instance_of(Gecode::Raw::Space),
240
- an_instance_of(Gecode::Raw::IntVar),
241
- an_instance_of(Gecode::Raw::IntVar),
242
- rhs, strength, kind)
243
- Gecode::Raw.should_receive(:rel).exactly(0).times
244
- else
245
- Gecode::Raw.should_receive(:mult).once.with(
246
- an_instance_of(Gecode::Raw::Space),
247
- an_instance_of(Gecode::Raw::IntVar),
248
- an_instance_of(Gecode::Raw::IntVar),
249
- an_instance_of(Gecode::Raw::IntVar),
250
- strength, kind)
251
- Gecode::Raw.should_receive(:rel).once.with(
252
- an_instance_of(Gecode::Raw::Space),
253
- an_instance_of(Gecode::Raw::IntVar),
254
- relation, rhs, strength, kind)
255
- end
256
- else
257
- Gecode::Raw.should_receive(:mult).once.with(
258
- an_instance_of(Gecode::Raw::Space),
259
- an_instance_of(Gecode::Raw::IntVar),
260
- an_instance_of(Gecode::Raw::IntVar),
261
- an_instance_of(Gecode::Raw::IntVar),
262
- strength, kind)
263
- Gecode::Raw.should_receive(:rel).once.with(
264
- an_instance_of(Gecode::Raw::Space),
265
- an_instance_of(Gecode::Raw::IntVar), relation, rhs,
266
- an_instance_of(Gecode::Raw::BoolVar),
267
- strength, kind)
268
- end
269
- end
270
- end
280
+ @expect = arithmetic_expectation(:mult, 2)
271
281
  end
272
282
 
273
283
  it 'should constrain the value of the multiplication' do
@@ -281,4 +291,61 @@ describe Gecode::Constraints::Int::Arithmetic, ' (multiplication)' do
281
291
  end
282
292
 
283
293
  it_should_behave_like 'arithmetic constraint'
284
- end
294
+ end
295
+
296
+ describe Gecode::Constraints::Int::Arithmetic, ' (squared)' do
297
+ before do
298
+ @model = ArithmeticSampleProblem.new
299
+ @var = @model.var
300
+ @stub = @var.squared
301
+ @target = @model.var2
302
+
303
+ @expect = arithmetic_expectation(:sqr, 1)
304
+ end
305
+
306
+ it 'should constrain the value of the variable squared' do
307
+ @var.squared.must == 9
308
+ sol = @model.solve!
309
+ sol.var.value.abs.should == 3
310
+ end
311
+
312
+ it_should_behave_like 'arithmetic constraint'
313
+ end
314
+
315
+ describe Gecode::Constraints::Int::Arithmetic, ' (square root)' do
316
+ before do
317
+ @model = ArithmeticSampleProblem.new
318
+ @var = @model.var
319
+ @stub = @var.square_root
320
+ @target = @model.var2
321
+
322
+ @expect = arithmetic_expectation(:sqrt, 1)
323
+ end
324
+
325
+ it 'should constrain the square root of the variable' do
326
+ @var.square_root.must == 3
327
+ sol = @model.solve!
328
+ Math.sqrt(sol.var.value).floor.should == 3
329
+ end
330
+
331
+ it 'should constrain the square root of the variable (2)' do
332
+ @var.square_root.must == 0
333
+ sol = @model.solve!
334
+ Math.sqrt(sol.var.value).floor.should == 0
335
+ end
336
+
337
+ it 'should constrain the square root of the variable (3)' do
338
+ @var.must < 0
339
+ @var.square_root.must == 0
340
+ @model.solve!.should be_nil
341
+ end
342
+
343
+ it 'should round down the square root' do
344
+ @var.must > 4
345
+ @var.square_root.must == 2
346
+ sol = @model.solve!
347
+ sol.var.value.should be_between(5,8)
348
+ end
349
+
350
+ it_should_behave_like 'arithmetic constraint'
351
+ end
@@ -228,5 +228,9 @@ describe Gecode::Constraints::Bool do
228
228
  sol.b3.value.should be_true
229
229
  end
230
230
 
231
+ it 'should raise error on right hand sides of the wrong type' do
232
+ lambda{ @b1.must == 'hello' }.should raise_error(TypeError)
233
+ end
234
+
231
235
  it_should_behave_like 'reifiable constraint'
232
236
  end
@@ -16,6 +16,20 @@ class ChannelSampleProblem < Gecode::Model
16
16
  end
17
17
  end
18
18
 
19
+ class BoolChannelSampleProblem < Gecode::Model
20
+ attr :bool_enum
21
+ attr :bool
22
+ attr :int
23
+
24
+ def initialize
25
+ @bool_enum = bool_var_array(4)
26
+ @int = int_var(0..3)
27
+ @bool = bool_var
28
+
29
+ branch_on wrap_enum([@int])
30
+ end
31
+ end
32
+
19
33
  describe Gecode::Constraints::IntEnum::Channel, ' (two int enums)' do
20
34
  before do
21
35
  @model = ChannelSampleProblem.new
@@ -67,13 +81,21 @@ describe Gecode::Constraints::IntEnum::Channel, ' (one int enum and one set enum
67
81
  @model = ChannelSampleProblem.new
68
82
  @positions = @model.positions
69
83
  @sets = @model.sets
84
+
85
+ @invoke_options = lambda do |hash|
86
+ @positions.must.channel @sets, hash
87
+ @model.solve!
88
+ end
89
+ @expect_options = option_expectation do |strength, kind, reif_var|
90
+ Gecode::Raw.should_receive(:channel).once.with(
91
+ an_instance_of(Gecode::Raw::Space),
92
+ an_instance_of(Gecode::Raw::IntVarArray),
93
+ an_instance_of(Gecode::Raw::SetVarArray))
94
+ end
70
95
  end
71
96
 
72
97
  it 'should translate into a channel constraint' do
73
- Gecode::Raw.should_receive(:channel).once.with(
74
- an_instance_of(Gecode::Raw::Space),
75
- an_instance_of(Gecode::Raw::IntVarArray),
76
- an_instance_of(Gecode::Raw::SetVarArray))
98
+ @expect_options.call({})
77
99
  @positions.must.channel @sets
78
100
  @model.solve!
79
101
  end
@@ -87,6 +109,8 @@ describe Gecode::Constraints::IntEnum::Channel, ' (one int enum and one set enum
87
109
  sets[position].value.should include(i)
88
110
  end
89
111
  end
112
+
113
+ it_should_behave_like 'non-reifiable set constraint'
90
114
  end
91
115
 
92
116
  describe Gecode::Constraints::SetEnum, ' (channel with set as left hand side)' do
@@ -123,4 +147,210 @@ describe Gecode::Constraints::SetEnum, ' (channel with set as left hand side)' d
123
147
  end
124
148
 
125
149
  it_should_behave_like 'non-reifiable set constraint'
126
- end
150
+ end
151
+
152
+ # Requires @model, @bool and @int. Also requires @place_constraint which is a
153
+ # method that takes five variables: a boolean variable, an integer variable,
154
+ # the name of the equality method to use, whether or not the constraint should
155
+ # be negated and a hash of options, and places the channel constraint on them.
156
+ describe 'channel constraint between one int and one bool variable', :shared => true do
157
+ before do
158
+ @invoke_options = lambda do |hash|
159
+ @place_constraint.call(@bool, @int, :==, false, hash)
160
+ @model.solve!
161
+ end
162
+ @expect_options = option_expectation do |strength, kind, reif_var|
163
+ Gecode::Raw.should_receive(:channel).once.with(
164
+ an_instance_of(Gecode::Raw::Space),
165
+ an_instance_of(Gecode::Raw::IntVar),
166
+ an_instance_of(Gecode::Raw::BoolVar),
167
+ strength, kind)
168
+ end
169
+ end
170
+
171
+ ([:==] + Gecode::Constraints::Util::COMPARISON_ALIASES[:==]).each do |ali|
172
+ it "should translate #{ali} into a channel constraint" do
173
+ @expect_options.call({})
174
+ @place_constraint.call(@bool, @int, ali, false, {})
175
+ @model.solve!
176
+ end
177
+ end
178
+
179
+ it 'should constrain the int variable to be 1 when the boolean variable is true' do
180
+ @bool.must_be.true
181
+ @place_constraint.call(@bool, @int, :==, false, {})
182
+ @model.solve!
183
+ @int.value.should == 1
184
+ end
185
+
186
+ it 'should constrain the int variable to be 0 when the boolean variable is false' do
187
+ @bool.must_be.false
188
+ @place_constraint.call(@bool, @int, :==, false, {})
189
+ @model.solve!
190
+ @int.value.should == 0
191
+ end
192
+
193
+ it 'should not allow negation' do
194
+ lambda do
195
+ @place_constraint.call(@bool, @int, :==, true, {})
196
+ end.should raise_error(Gecode::MissingConstraintError)
197
+ end
198
+
199
+ it_should_behave_like 'non-reifiable constraint'
200
+ end
201
+
202
+ describe Gecode::Constraints::Int::Channel, ' (one int and one bool variable)' do
203
+ before do
204
+ @model = BoolChannelSampleProblem.new
205
+ @bool = @model.bool_var
206
+ @int = @model.int_var
207
+
208
+ @place_constraint = lambda do |bool, int, equals_method_name, negate, options|
209
+ if negate
210
+ int.must_not.method(equals_method_name).call(bool, options)
211
+ else
212
+ int.must.method(equals_method_name).call(bool, options)
213
+ end
214
+ end
215
+ end
216
+
217
+ it 'should not shadow linear boolean constraints' do
218
+ lambda do
219
+ (@bool + @bool).must == @bool
220
+ @model.solve!
221
+ end.should_not raise_error
222
+ end
223
+
224
+ it 'should raise error for unsupported right hand sides' do
225
+ lambda{ @int.must == 'hello' }.should raise_error(TypeError)
226
+ end
227
+
228
+ it_should_behave_like 'channel constraint between one int and one bool variable'
229
+ end
230
+
231
+ describe Gecode::Constraints::Int::Channel, ' (one bool and one int variable)' do
232
+ before do
233
+ @model = BoolChannelSampleProblem.new
234
+ @bool = @model.bool_var
235
+ @int = @model.int_var
236
+
237
+ @place_constraint = lambda do |bool, int, equals_method_name, negate, options|
238
+ if negate
239
+ bool.must_not.method(equals_method_name).call(int, options)
240
+ else
241
+ bool.must.method(equals_method_name).call(int, options)
242
+ end
243
+ end
244
+ end
245
+
246
+ it 'should not shadow linear boolean constraints' do
247
+ lambda do
248
+ @bool.must == @bool + @bool
249
+ @model.solve!
250
+ end.should_not raise_error
251
+ end
252
+
253
+ it 'should raise error for unsupported right hand sides' do
254
+ lambda{ @bool.must == 'hello' }.should raise_error(TypeError)
255
+ end
256
+
257
+ it_should_behave_like 'channel constraint between one int and one bool variable'
258
+ end
259
+
260
+ # Requires @model, @bool_enum and @int. Also requires @place_constraint which
261
+ # is a method that takes four variables: a boolean enum, an integer variable,
262
+ # whether or not the constraint should be negated and a hash of options, and
263
+ # places the channel constraint on them.
264
+ describe 'channel constraint between bool enum and int variable', :shared => true do
265
+ before do
266
+ @invoke_options = lambda do |hash|
267
+ @place_constraint.call(@bools, @int, false, hash)
268
+ @model.solve!
269
+ end
270
+ @expect_options = option_expectation do |strength, kind, reif_var|
271
+ Gecode::Raw.should_receive(:channel).once.with(
272
+ an_instance_of(Gecode::Raw::Space),
273
+ an_instance_of(Gecode::Raw::BoolVarArray),
274
+ an_instance_of(Gecode::Raw::IntVar), 0,
275
+ strength, kind)
276
+ end
277
+ end
278
+
279
+ it 'should channel the bool enum with the integer variable' do
280
+ @int.must > 2
281
+ @place_constraint.call(@bools, @int, false, {})
282
+ @model.solve!.should_not be_nil
283
+ int_val = @int.value
284
+ @bools.values.each_with_index do |bool, index|
285
+ bool.should == (index == int_val)
286
+ end
287
+ end
288
+
289
+ it 'should take the offset into account when channeling' do
290
+ @int.must > 2
291
+ offset = 1
292
+ @place_constraint.call(@bools, @int, false, :offset => offset)
293
+ @model.solve!.should_not be_nil
294
+ int_val = @int.value
295
+ @bools.values.each_with_index do |bool, index|
296
+ bool.should == (index + offset == int_val)
297
+ end
298
+ end
299
+
300
+ it 'should not allow negation' do
301
+ lambda do
302
+ @place_constraint.call(@bools, @int, true, {})
303
+ end.should raise_error(Gecode::MissingConstraintError)
304
+ end
305
+
306
+ it_should_behave_like 'non-reifiable constraint'
307
+ end
308
+
309
+ describe Gecode::Constraints::BoolEnum::Channel, ' (bool enum as lhs with int variable)' do
310
+ before do
311
+ @model = BoolChannelSampleProblem.new
312
+ @bools = @model.bool_enum
313
+ @int = @model.int
314
+
315
+ @place_constraint = lambda do |bools, int, negate, options|
316
+ unless negate
317
+ bools.must.channel(int, options)
318
+ else
319
+ bools.must_not.channel(int, options)
320
+ end
321
+ end
322
+ end
323
+
324
+ it 'should raise error if an integer variable is not given as right hand side' do
325
+ lambda do
326
+ @bools.must.channel 'hello'
327
+ end.should raise_error(TypeError)
328
+ end
329
+
330
+ it_should_behave_like 'channel constraint between bool enum and int variable'
331
+ end
332
+
333
+
334
+ describe Gecode::Constraints::BoolEnum::Channel, ' (int variable as lhs with bool enum)' do
335
+ before do
336
+ @model = BoolChannelSampleProblem.new
337
+ @bools = @model.bool_enum
338
+ @int = @model.int
339
+
340
+ @place_constraint = lambda do |bools, int, negate, options|
341
+ unless negate
342
+ int.must.channel(bools, options)
343
+ else
344
+ int.must_not.channel(bools, options)
345
+ end
346
+ end
347
+ end
348
+
349
+ it 'should raise error if a boolean enum is not given as right hand side' do
350
+ lambda do
351
+ @int.must.channel 'hello'
352
+ end.should raise_error(TypeError)
353
+ end
354
+
355
+ it_should_behave_like 'channel constraint between bool enum and int variable'
356
+ end
@@ -8,7 +8,7 @@ class DistinctSampleProblem < Gecode::Model
8
8
  def initialize
9
9
  @vars = int_var_array(2, 1)
10
10
  @sets = set_var_array(2, [], 0..2)
11
- branch_on wrap_enum(@sets)
11
+ branch_on @sets
12
12
  end
13
13
  end
14
14
 
@@ -1,25 +1,59 @@
1
1
  require File.dirname(__FILE__) + '/../spec_helper'
2
2
  require File.dirname(__FILE__) + '/constraint_helper'
3
3
 
4
- describe Gecode::Constraints::IntEnum::Extensional do
4
+ # Assumes that @variables, @expected_array and @tuples are defined.
5
+ describe 'tuple constraint', :shared => true do
5
6
  before do
6
- @model = Gecode::Model.new
7
- @tuples = [[1,7], [5,1]]
8
- @digits = @model.int_var_array(2, 0..9)
9
- @model.branch_on @digits
10
-
11
7
  @invoke_options = lambda do |hash|
12
- @digits.must_be.in(@tuples, hash)
8
+ @variables.must_be.in(@tuples, hash)
13
9
  @model.solve!
14
10
  end
15
11
  @expect_options = option_expectation do |strength, kind, reif_var|
16
12
  Gecode::Raw.should_receive(:extensional).once.with(
17
13
  an_instance_of(Gecode::Raw::Space),
18
- an_instance_of(Gecode::Raw::IntVarArray),
14
+ @expected_array,
19
15
  an_instance_of(Gecode::Raw::TupleSet), strength, kind)
20
16
  end
21
17
  end
22
18
 
19
+ it 'should not allow negation' do
20
+ lambda do
21
+ @variables.must_not_be.in @tuples
22
+ end.should raise_error(Gecode::MissingConstraintError)
23
+ end
24
+
25
+ it 'should not allow empty tuples' do
26
+ lambda do
27
+ @variables.must_be.in []
28
+ end.should raise_error(ArgumentError)
29
+ end
30
+
31
+ it 'should not allow tuples of sizes other than the number of variables' do
32
+ lambda do
33
+ @variables.must_be.in([@tuples.first * 2])
34
+ end.should raise_error(ArgumentError)
35
+ end
36
+
37
+ it 'should raise error if the right hand side does not contain tuples of correct type' do
38
+ lambda do
39
+ size = @variables.size
40
+ @variables.must_be.in ['h'*size, 'i'*size]
41
+ end.should raise_error(TypeError)
42
+ end
43
+
44
+ it_should_behave_like 'non-reifiable constraint'
45
+ end
46
+
47
+ describe Gecode::Constraints::IntEnum::Extensional do
48
+ before do
49
+ @model = Gecode::Model.new
50
+ @tuples = [[1,7], [5,1]]
51
+ @variables = @digits = @model.int_var_array(2, 0..9)
52
+ @model.branch_on @digits
53
+
54
+ @expected_array = an_instance_of Gecode::Raw::IntVarArray
55
+ end
56
+
23
57
  it 'should constrain the domain of all variables' do
24
58
  @digits.must_be.in @tuples
25
59
 
@@ -32,12 +66,6 @@ describe Gecode::Constraints::IntEnum::Extensional do
32
66
  (found_solutions - @tuples).should be_empty
33
67
  end
34
68
 
35
- it 'should not allow negation' do
36
- lambda do
37
- @digits.must_not_be.in @tuples
38
- end.should raise_error(Gecode::MissingConstraintError)
39
- end
40
-
41
69
  it 'should raise error if the right hand side is not an enumeration' do
42
70
  lambda{ @digits.must_be.in 4711 }.should raise_error(TypeError)
43
71
  end
@@ -46,30 +74,17 @@ describe Gecode::Constraints::IntEnum::Extensional do
46
74
  lambda{ @digits.must_be.in [17, 4711] }.should raise_error(TypeError)
47
75
  end
48
76
 
49
- it 'should raise error if the right hand side does not contain integer tuples' do
50
- lambda{ @digits.must_be.in ['hello'] }.should raise_error(TypeError)
51
- end
52
-
53
- it_should_behave_like 'non-reifiable constraint'
77
+ it_should_behave_like 'tuple constraint'
54
78
  end
55
79
 
56
80
  describe Gecode::Constraints::BoolEnum::Extensional do
57
81
  before do
58
82
  @model = Gecode::Model.new
59
83
  @tuples = [[true, false, true], [false, false, true]]
60
- @bools = @model.bool_var_array(3)
84
+ @variables = @bools = @model.bool_var_array(3)
61
85
  @model.branch_on @bools
62
86
 
63
- @invoke_options = lambda do |hash|
64
- @bools.must_be.in(@tuples, hash)
65
- @model.solve!
66
- end
67
- @expect_options = option_expectation do |strength, kind, reif_var|
68
- Gecode::Raw.should_receive(:extensional).once.with(
69
- an_instance_of(Gecode::Raw::Space),
70
- an_instance_of(Gecode::Raw::BoolVarArray),
71
- an_instance_of(Gecode::Raw::TupleSet), strength, kind)
72
- end
87
+ @expected_array = an_instance_of Gecode::Raw::BoolVarArray
73
88
  end
74
89
 
75
90
  it 'should constrain the domain of all variables' do
@@ -84,12 +99,6 @@ describe Gecode::Constraints::BoolEnum::Extensional do
84
99
  (found_solutions - @tuples).should be_empty
85
100
  end
86
101
 
87
- it 'should not allow negation' do
88
- lambda do
89
- @bools.must_not_be.in @tuples
90
- end.should raise_error(Gecode::MissingConstraintError)
91
- end
92
-
93
102
  it 'should raise error if the right hand side is not an enumeration' do
94
103
  lambda{ @bools.must_be.in true }.should raise_error(TypeError)
95
104
  end
@@ -98,9 +107,5 @@ describe Gecode::Constraints::BoolEnum::Extensional do
98
107
  lambda{ @bools.must_be.in [true, false] }.should raise_error(TypeError)
99
108
  end
100
109
 
101
- it 'should raise error if the right hand side does not contain boolean tuples' do
102
- lambda{ @bools.must_be.in ['hello'] }.should raise_error(TypeError)
103
- end
104
-
105
- it_should_behave_like 'non-reifiable constraint'
110
+ it_should_behave_like 'tuple constraint'
106
111
  end
@@ -240,6 +240,14 @@ describe Gecode::Constraints::Int::Linear, '(with booleans)' do
240
240
  (x + y).should equal(1)
241
241
  end
242
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
+
243
251
  it 'should handle variables as right hand side' do
244
252
  (@x + @y).must == @z
245
253
  sol = @model.solve!
@@ -40,6 +40,13 @@ describe Gecode::Model, ' (enum wrapping)' do
40
40
  end.should raise_error(ArgumentError)
41
41
  end
42
42
 
43
+ it 'should not allow wrapping a wrapped enumerable' do
44
+ lambda do
45
+ enum = [@bool]
46
+ @model.wrap_enum(@model.wrap_enum(enum))
47
+ end.should raise_error(ArgumentError)
48
+ end
49
+
43
50
  it 'should not allow enumerables without variables or fixnums to be wrapped' do
44
51
  lambda do
45
52
  @model.wrap_enum(['foo'])
@@ -119,4 +126,4 @@ describe Gecode::FixnumEnumMethods do
119
126
  it 'should compute the smallest domain range' do
120
127
  @enum.domain_range.should == (7..4711)
121
128
  end
122
- end
129
+ end