gecoder-with-gecode 0.8.1-mswin32 → 0.8.2-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.
@@ -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
@@ -65,6 +65,12 @@ describe Gecode::Model, ' (with multiple solutions)' do
65
65
  s.var.should have_domain(@solved_domain)
66
66
  end
67
67
  end
68
+
69
+ it 'should update the search statistics before yielding to #solution' do
70
+ @model.solution do |s|
71
+ @model.search_stats.should_not be_nil
72
+ end
73
+ end
68
74
 
69
75
  it 'should only evaluate the block for one solution in #solution' do
70
76
  i = 0
@@ -83,6 +89,18 @@ describe Gecode::Model, ' (with multiple solutions)' do
83
89
  end
84
90
  Set.new(solutions).should == Set.new([2,3])
85
91
  end
92
+
93
+ it 'should update the search statistics before yielding to #each_solution' do
94
+ solutions = []
95
+ old_stats = @model.search_stats
96
+ old_stats.should be_nil
97
+ @model.each_solution do |s|
98
+ solutions << s.var.value
99
+ @model.search_stats.should_not == old_stats
100
+ @model.search_stats.should_not be_nil
101
+ old_stats = @model.search_stats
102
+ end
103
+ end
86
104
  end
87
105
 
88
106
  describe Gecode::Model, ' (after #solve!)' do
@@ -114,6 +132,15 @@ describe Gecode::Model, ' (after #solve!)' do
114
132
  enum[2].first.should have_domain(@solved_domain)
115
133
  enum[3][1][:b].should have_domain(@solved_domain)
116
134
  end
135
+
136
+ it 'should have updated the search statistics' do
137
+ stats = @model.search_stats
138
+ stats[:propagations].should == 0
139
+ stats[:failures].should == 0
140
+ stats[:clones].should_not be_nil
141
+ stats[:commits].should_not be_nil
142
+ stats[:memory].should > 0
143
+ end
117
144
  end
118
145
 
119
146
  describe 'reset model', :shared => true do
@@ -126,6 +153,10 @@ describe 'reset model', :shared => true do
126
153
  enum[2].first.should have_domain(@reset_domain)
127
154
  enum[3][1][:b].should have_domain(@reset_domain)
128
155
  end
156
+
157
+ it 'should have cleared the search statistics' do
158
+ @model.search_stats.should be_nil
159
+ end
129
160
  end
130
161
 
131
162
  describe Gecode::Model, ' (after #reset!)' do
@@ -205,66 +236,6 @@ describe Gecode::Model, '(optimization search)' do
205
236
  solution.z.value.should == 25
206
237
  end
207
238
 
208
- it 'should support maximizing singe variables given as symbols' do
209
- solution = SampleOptimizationProblem.new.maximize! :z
210
- solution.should_not be_nil
211
- solution.x.value.should == 5
212
- solution.y.value.should == 5
213
- solution.z.value.should == 25
214
- end
215
-
216
- it 'should support maximizing singe variables given as strings' do
217
- solution = SampleOptimizationProblem.new.maximize! 'z'
218
- solution.should_not be_nil
219
- solution.x.value.should == 5
220
- solution.y.value.should == 5
221
- solution.z.value.should == 25
222
- end
223
-
224
- it 'should raise error if maximize! is given a non-existing method' do
225
- lambda do
226
- SampleOptimizationProblem.new.maximize! :does_not_exist
227
- end.should raise_error(NameError)
228
- end
229
-
230
- it 'should raise error if maximize! is given a method that does not return an integer variable' do
231
- lambda do
232
- SampleOptimizationProblem.new.maximize! :object_id
233
- end.should raise_error(ArgumentError)
234
- end
235
-
236
- it 'should support minimizing singe variables given as symbols' do
237
- problem = SampleOptimizationProblem.new
238
- problem.z.must > 2
239
- solution = problem.minimize! :x
240
- solution.should_not be_nil
241
- solution.x.value.should == 1
242
- solution.y.value.should == 3
243
- solution.z.value.should == 3
244
- end
245
-
246
- it 'should support minimizing singe variables given as strings' do
247
- problem = SampleOptimizationProblem.new
248
- problem.z.must > 2
249
- solution = problem.minimize! 'x'
250
- solution.should_not be_nil
251
- solution.x.value.should == 1
252
- solution.y.value.should == 3
253
- solution.z.value.should == 3
254
- end
255
-
256
- it 'should raise error if minimize! is given a non-existing method' do
257
- lambda do
258
- SampleOptimizationProblem.new.minimize! :does_not_exist
259
- end.should raise_error(NameError)
260
- end
261
-
262
- it 'should raise error if minimize! is given a method that does not return an integer variable' do
263
- lambda do
264
- SampleOptimizationProblem.new.minimize! :object_id
265
- end.should raise_error(ArgumentError)
266
- end
267
-
268
239
  it 'should not be bothered by garbage collecting' do
269
240
  # This goes through 400+ spaces.
270
241
  solution = SampleOptimizationProblem2.new.optimize! do |model, best_so_far|
@@ -303,4 +274,91 @@ describe Gecode::Model, '(optimization search)' do
303
274
  solution.y.value.should == 5
304
275
  solution.z.value.should == 25
305
276
  end
306
- end
277
+
278
+ it 'should update the search statistics' do
279
+ model = SampleOptimizationProblem.new
280
+ solution = model.maximize! :z
281
+
282
+ stats = model.search_stats
283
+ stats.should_not be_nil
284
+ stats[:propagations].should be_between(1, 100)
285
+ stats[:failures].should be_between(1, 100)
286
+ stats[:clones].should_not be_nil
287
+ stats[:commits].should_not be_nil
288
+ stats[:memory].should > 0
289
+ end
290
+ end
291
+
292
+ describe 'single variable optimization', :shared => true do
293
+ it "should support #{@method_name} having the variable given as a symbol" do
294
+ solution = @model.method(@method_name).call(@variable_name.to_sym)
295
+ @expect_to_be_correct.call(solution)
296
+ end
297
+
298
+ it "should support #{@method_name} having the variable given as a string" do
299
+ solution = @model.method(@method_name).call(@variable_name.to_s)
300
+ @expect_to_be_correct.call(solution)
301
+ end
302
+
303
+ it "should raise error if #{@method_name} is given a non-existing method" do
304
+ lambda do
305
+ SampleOptimizationProblem.new.method(@method_name).call(:does_not_exist)
306
+ end.should raise_error(NameError)
307
+ end
308
+
309
+ it "should raise error if #{@method_name} is given a method that does not return an integer variable" do
310
+ lambda do
311
+ SampleOptimizationProblem.new.method(@method_name).call(:object_id)
312
+ end.should raise_error(ArgumentError)
313
+ end
314
+
315
+ it 'should update the search statistics' do
316
+ @model.method(@method_name).call(@variable_name.to_sym)
317
+
318
+ stats = @model.search_stats
319
+ stats.should_not be_nil
320
+ stats[:propagations].should be_between(1, 100)
321
+ stats[:failures].should be_between(1, 100)
322
+ stats[:clones].should_not be_nil
323
+ stats[:commits].should_not be_nil
324
+ stats[:memory].should > 0
325
+ end
326
+ end
327
+
328
+ describe Gecode::Model, '(single variable minimization)' do
329
+ before do
330
+ @method_name = 'minimize!'
331
+ @variable_name = 'x'
332
+
333
+ @model = SampleOptimizationProblem.new
334
+ @model.z.must > 2
335
+
336
+ @expect_to_be_correct = lambda do |solution|
337
+ solution.should_not be_nil
338
+ solution.x.value.should == 1
339
+ solution.y.value.should == 3
340
+ solution.z.value.should == 3
341
+ end
342
+ end
343
+
344
+ it_should_behave_like 'single variable optimization'
345
+ end
346
+
347
+ describe Gecode::Model, '(single variable maximization)' do
348
+ before do
349
+ @method_name = 'maximize!'
350
+ @variable_name = 'z'
351
+
352
+ @model = SampleOptimizationProblem.new
353
+
354
+ @expect_to_be_correct = lambda do |solution|
355
+ solution.should_not be_nil
356
+ solution.x.value.should == 5
357
+ solution.y.value.should == 5
358
+ solution.z.value.should == 25
359
+ end
360
+ end
361
+
362
+ it_should_behave_like 'single variable optimization'
363
+ end
364
+
@@ -58,34 +58,6 @@ module CustomVarMatchers
58
58
  def have_bounds(expected_glb, expected_lub)
59
59
  HaveBounds.new(expected_glb, expected_lub)
60
60
  end
61
-
62
- class IsAlias
63
- def initialize(expected)
64
- @expected = expected.to_a
65
- end
66
-
67
- def matches?(target)
68
- @target = target
69
- return false unless @target.size == @expected.size
70
- @expected.each do |element|
71
- return false unless @target.in(element)
72
- end
73
- return true
74
- end
75
-
76
- def failure_message
77
- "expected #{@target.inspect} to be an alias of #{@expected.inspect}"
78
- end
79
-
80
- def negative_failure_message
81
- "expected #{@target.inspect} not to be an alias of #{@expected.inspect}"
82
- end
83
- end
84
-
85
- # Tests whether a method with a specified name is the alias of another.
86
- def is_alias_of(expected)
87
- HaveDomain.new(expected)
88
- end
89
61
  end
90
62
 
91
63
  Spec::Runner.configure do |config|
@@ -54,7 +54,7 @@ spec = Gem::Specification.new do |s|
54
54
  s.files = FileList[
55
55
  '[A-Z]*',
56
56
  'lib/**/*.rb',
57
- 'example/**/*',
57
+ 'example/**/*.rb',
58
58
  'src/**/*',
59
59
  'vendor/rust/**/*',
60
60
  'tasks/**/*',
@@ -136,8 +136,7 @@ end
136
136
 
137
137
  desc 'Publish packages on RubyForge'
138
138
  task :publish_packages => [:publish_gecoder_packages,
139
- :publish_gecoder_with_gecode_packages,
140
- :publish_gecoder_with_gecode_mswin32_packages]
139
+ :publish_gecoder_with_gecode_packages]
141
140
 
142
141
  # Files included in the vanilla Gecode/R release.
143
142
  vanilla_release_files = [