gecoder 0.8.3 → 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (142) hide show
  1. data/CHANGES +15 -0
  2. data/README +6 -2
  3. data/example/equation_system.rb +15 -0
  4. data/example/magic_sequence.rb +7 -7
  5. data/example/money.rb +36 -0
  6. data/example/queens.rb +7 -8
  7. data/example/send_most_money.rb +1 -1
  8. data/example/square_tiling.rb +2 -2
  9. data/example/sudoku-set.rb +11 -12
  10. data/example/sudoku.rb +40 -45
  11. data/ext/extconf.rb +0 -0
  12. data/lib/gecoder/bindings.rb +42 -0
  13. data/lib/gecoder/bindings/bindings.rb +16 -0
  14. data/lib/gecoder/interface.rb +2 -1
  15. data/lib/gecoder/interface/branch.rb +16 -9
  16. data/lib/gecoder/interface/constraints.rb +410 -451
  17. data/lib/gecoder/interface/constraints/bool/boolean.rb +205 -213
  18. data/lib/gecoder/interface/constraints/bool/channel.rb +4 -5
  19. data/lib/gecoder/interface/constraints/bool/linear.rb +192 -21
  20. data/lib/gecoder/interface/constraints/bool_enum/channel.rb +43 -39
  21. data/lib/gecoder/interface/constraints/bool_enum/extensional.rb +43 -49
  22. data/lib/gecoder/interface/constraints/bool_enum/relation.rb +38 -71
  23. data/lib/gecoder/interface/constraints/bool_enum_constraints.rb +73 -22
  24. data/lib/gecoder/interface/constraints/bool_var_constraints.rb +140 -61
  25. data/lib/gecoder/interface/constraints/extensional_regexp.rb +4 -4
  26. data/lib/gecoder/interface/constraints/fixnum_enum/element.rb +63 -0
  27. data/lib/gecoder/interface/constraints/fixnum_enum/operation.rb +65 -0
  28. data/lib/gecoder/interface/constraints/fixnum_enum_constraints.rb +42 -0
  29. data/lib/gecoder/interface/constraints/int/arithmetic.rb +131 -130
  30. data/lib/gecoder/interface/constraints/int/channel.rb +21 -31
  31. data/lib/gecoder/interface/constraints/int/domain.rb +45 -42
  32. data/lib/gecoder/interface/constraints/int/linear.rb +85 -239
  33. data/lib/gecoder/interface/constraints/int/relation.rb +141 -0
  34. data/lib/gecoder/interface/constraints/int_enum/arithmetic.rb +55 -64
  35. data/lib/gecoder/interface/constraints/int_enum/channel.rb +35 -37
  36. data/lib/gecoder/interface/constraints/int_enum/count.rb +53 -78
  37. data/lib/gecoder/interface/constraints/int_enum/distinct.rb +36 -46
  38. data/lib/gecoder/interface/constraints/int_enum/element.rb +39 -57
  39. data/lib/gecoder/interface/constraints/int_enum/equality.rb +15 -19
  40. data/lib/gecoder/interface/constraints/int_enum/extensional.rb +65 -72
  41. data/lib/gecoder/interface/constraints/int_enum/sort.rb +42 -45
  42. data/lib/gecoder/interface/constraints/int_enum_constraints.rb +79 -22
  43. data/lib/gecoder/interface/constraints/int_var_constraints.rb +215 -44
  44. data/lib/gecoder/interface/constraints/reifiable_constraints.rb +14 -14
  45. data/lib/gecoder/interface/constraints/selected_set/select.rb +120 -0
  46. data/lib/gecoder/interface/constraints/selected_set_constraints.rb +75 -0
  47. data/lib/gecoder/interface/constraints/set/cardinality.rb +43 -53
  48. data/lib/gecoder/interface/constraints/set/channel.rb +26 -29
  49. data/lib/gecoder/interface/constraints/set/connection.rb +89 -152
  50. data/lib/gecoder/interface/constraints/set/domain.rb +112 -65
  51. data/lib/gecoder/interface/constraints/set/include.rb +36 -0
  52. data/lib/gecoder/interface/constraints/set/operation.rb +96 -110
  53. data/lib/gecoder/interface/constraints/set/relation.rb +114 -137
  54. data/lib/gecoder/interface/constraints/set_elements/relation.rb +116 -0
  55. data/lib/gecoder/interface/constraints/set_elements_constraints.rb +97 -0
  56. data/lib/gecoder/interface/constraints/set_enum/channel.rb +23 -27
  57. data/lib/gecoder/interface/constraints/set_enum/distinct.rb +18 -19
  58. data/lib/gecoder/interface/constraints/set_enum/operation.rb +62 -53
  59. data/lib/gecoder/interface/constraints/set_enum/select.rb +79 -0
  60. data/lib/gecoder/interface/constraints/set_enum_constraints.rb +73 -23
  61. data/lib/gecoder/interface/constraints/set_var_constraints.rb +222 -57
  62. data/lib/gecoder/interface/enum_matrix.rb +4 -4
  63. data/lib/gecoder/interface/enum_wrapper.rb +71 -22
  64. data/lib/gecoder/interface/model.rb +167 -12
  65. data/lib/gecoder/interface/model_sugar.rb +84 -0
  66. data/lib/gecoder/interface/search.rb +30 -18
  67. data/lib/gecoder/interface/variables.rb +103 -33
  68. data/lib/gecoder/version.rb +2 -2
  69. data/specs/bool_var.rb +19 -12
  70. data/specs/constraints/{boolean.rb → bool/boolean.rb} +103 -28
  71. data/specs/constraints/bool/boolean_properties.rb +51 -0
  72. data/specs/constraints/bool/linear.rb +213 -0
  73. data/specs/constraints/bool_enum/bool_enum_relation.rb +117 -0
  74. data/specs/constraints/bool_enum/channel.rb +102 -0
  75. data/specs/constraints/{extensional.rb → bool_enum/extensional.rb} +32 -101
  76. data/specs/constraints/constraint_helper.rb +149 -179
  77. data/specs/constraints/constraint_receivers.rb +103 -0
  78. data/specs/constraints/constraints.rb +6 -63
  79. data/specs/constraints/fixnum_enum/element.rb +58 -0
  80. data/specs/constraints/fixnum_enum/operation.rb +67 -0
  81. data/specs/constraints/int/arithmetic.rb +149 -0
  82. data/specs/constraints/int/channel.rb +101 -0
  83. data/specs/constraints/int/domain.rb +106 -0
  84. data/specs/constraints/int/linear.rb +183 -0
  85. data/specs/constraints/int/linear_properties.rb +97 -0
  86. data/specs/constraints/int/relation.rb +84 -0
  87. data/specs/constraints/int_enum/arithmetic.rb +72 -0
  88. data/specs/constraints/int_enum/channel.rb +57 -0
  89. data/specs/constraints/int_enum/count.rb +72 -0
  90. data/specs/constraints/int_enum/distinct.rb +80 -0
  91. data/specs/constraints/int_enum/element.rb +61 -0
  92. data/specs/constraints/int_enum/equality.rb +29 -0
  93. data/specs/constraints/int_enum/extensional.rb +224 -0
  94. data/specs/constraints/int_enum/sort.rb +167 -0
  95. data/specs/constraints/operands.rb +264 -0
  96. data/specs/constraints/property_helper.rb +443 -0
  97. data/specs/constraints/reification_sugar.rb +4 -5
  98. data/specs/constraints/selected_set/select.rb +56 -0
  99. data/specs/constraints/selected_set/select_properties.rb +157 -0
  100. data/specs/constraints/set/cardinality.rb +58 -0
  101. data/specs/constraints/set/cardinality_properties.rb +46 -0
  102. data/specs/constraints/set/channel.rb +77 -0
  103. data/specs/constraints/set/connection.rb +176 -0
  104. data/specs/constraints/set/domain.rb +197 -0
  105. data/specs/constraints/set/include.rb +36 -0
  106. data/specs/constraints/set/operation.rb +132 -0
  107. data/specs/constraints/set/relation.rb +117 -0
  108. data/specs/constraints/set_elements/relation.rb +84 -0
  109. data/specs/constraints/set_enum/channel.rb +80 -0
  110. data/specs/constraints/set_enum/distinct.rb +59 -0
  111. data/specs/constraints/set_enum/operation.rb +111 -0
  112. data/specs/constraints/set_enum/select.rb +73 -0
  113. data/specs/enum_wrapper.rb +53 -3
  114. data/specs/int_var.rb +44 -25
  115. data/specs/model.rb +58 -1
  116. data/specs/model_sugar.rb +30 -0
  117. data/specs/search.rb +24 -5
  118. data/specs/selected_set.rb +39 -0
  119. data/specs/set_elements.rb +34 -0
  120. data/specs/set_var.rb +22 -8
  121. data/specs/spec_helper.rb +206 -6
  122. data/tasks/distribution.rake +22 -7
  123. data/tasks/svn.rake +3 -1
  124. metadata +218 -134
  125. data/lib/gecoder/interface/constraints/set_enum/selection.rb +0 -217
  126. data/specs/constraints/arithmetic.rb +0 -351
  127. data/specs/constraints/bool_enum_relation.rb +0 -160
  128. data/specs/constraints/cardinality.rb +0 -157
  129. data/specs/constraints/channel.rb +0 -454
  130. data/specs/constraints/connection.rb +0 -369
  131. data/specs/constraints/count.rb +0 -146
  132. data/specs/constraints/distinct.rb +0 -164
  133. data/specs/constraints/element.rb +0 -108
  134. data/specs/constraints/equality.rb +0 -31
  135. data/specs/constraints/int_domain.rb +0 -70
  136. data/specs/constraints/int_relation.rb +0 -82
  137. data/specs/constraints/linear.rb +0 -340
  138. data/specs/constraints/selection.rb +0 -292
  139. data/specs/constraints/set_domain.rb +0 -185
  140. data/specs/constraints/set_operation.rb +0 -285
  141. data/specs/constraints/set_relation.rb +0 -197
  142. data/specs/constraints/sort.rb +0 -179
@@ -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