gecoder 0.8.3 → 0.9.0

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 (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