gecoder 0.5.0 → 0.6.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.
- data/CHANGES +16 -3
- data/example/magic_sequence.rb +1 -1
- data/example/queens.rb +1 -1
- data/example/send_more_money.rb +1 -1
- data/example/sudoku.rb +1 -1
- data/ext/missing.cpp +18 -4
- data/ext/missing.h +8 -0
- data/lib/gecoder/bindings.rb +30 -3
- data/lib/gecoder/bindings/bindings.rb +22 -0
- data/lib/gecoder/interface/binding_changes.rb +81 -107
- data/lib/gecoder/interface/branch.rb +65 -14
- data/lib/gecoder/interface/constraints.rb +1 -0
- data/lib/gecoder/interface/constraints/bool_enum/boolean.rb +16 -12
- data/lib/gecoder/interface/constraints/int/arithmetic.rb +7 -3
- data/lib/gecoder/interface/constraints/int/linear.rb +19 -16
- data/lib/gecoder/interface/constraints/int_enum/arithmetic.rb +8 -4
- data/lib/gecoder/interface/constraints/int_enum/channel.rb +14 -6
- data/lib/gecoder/interface/constraints/int_enum/element.rb +7 -5
- data/lib/gecoder/interface/constraints/int_enum/sort.rb +1 -4
- data/lib/gecoder/interface/constraints/set/cardinality.rb +6 -3
- data/lib/gecoder/interface/constraints/set/connection.rb +136 -0
- data/lib/gecoder/interface/constraints/set_enum/channel.rb +18 -0
- data/lib/gecoder/interface/constraints/set_enum/distinct.rb +61 -0
- data/lib/gecoder/interface/constraints/set_enum_constraints.rb +32 -0
- data/lib/gecoder/interface/constraints/set_var_constraints.rb +1 -0
- data/lib/gecoder/interface/enum_wrapper.rb +12 -3
- data/lib/gecoder/interface/model.rb +77 -56
- data/lib/gecoder/interface/search.rb +74 -5
- data/lib/gecoder/interface/variables.rb +117 -15
- data/lib/gecoder/version.rb +1 -1
- data/specs/binding_changes.rb +9 -5
- data/specs/bool_var.rb +8 -12
- data/specs/branch.rb +85 -19
- data/specs/constraints/arithmetic.rb +99 -71
- data/specs/constraints/bool_enum.rb +26 -18
- data/specs/constraints/boolean.rb +53 -49
- data/specs/constraints/cardinality.rb +33 -26
- data/specs/constraints/channel.rb +77 -6
- data/specs/constraints/connection.rb +352 -0
- data/specs/constraints/constraints.rb +10 -1
- data/specs/constraints/count.rb +79 -39
- data/specs/constraints/distinct.rb +128 -9
- data/specs/constraints/element.rb +26 -19
- data/specs/constraints/equality.rb +2 -1
- data/specs/constraints/int_domain.rb +19 -12
- data/specs/constraints/int_relation.rb +12 -6
- data/specs/constraints/linear.rb +30 -30
- data/specs/constraints/reification_sugar.rb +8 -4
- data/specs/constraints/set_domain.rb +24 -18
- data/specs/constraints/set_relation.rb +38 -23
- data/specs/constraints/sort.rb +12 -10
- data/specs/enum_wrapper.rb +9 -3
- data/specs/int_var.rb +8 -4
- data/specs/logging.rb +24 -0
- data/specs/model.rb +25 -7
- data/specs/search.rb +41 -1
- data/specs/set_var.rb +36 -7
- data/specs/spec_helper.rb +3 -10
- data/vendor/rust/rust/templates/FunctionDefinition.rusttpl +1 -1
- metadata +12 -3
- data/specs/tmp +0 -22
@@ -45,25 +45,25 @@ describe 'bool enum constraint', :shared => true do
|
|
45
45
|
it 'should handle being constrained to be equal to a variable' do
|
46
46
|
@stub.must_be == @b1
|
47
47
|
@model.solve!
|
48
|
-
@compute_result.call.should == @b1.
|
48
|
+
@compute_result.call.should == @b1.value
|
49
49
|
end
|
50
50
|
|
51
51
|
it 'should handle being constrained to not be equal to a variable' do
|
52
52
|
@stub.must_not_be == @b1
|
53
53
|
@model.solve!
|
54
|
-
@compute_result.call.should_not == @b1.
|
54
|
+
@compute_result.call.should_not == @b1.value
|
55
55
|
end
|
56
56
|
|
57
57
|
it 'should handle being constrained to be equal to be a nested expression' do
|
58
58
|
@stub.must_be == (@b1 | @b2) & @b1
|
59
59
|
@model.solve!
|
60
|
-
@compute_result.call.should == (@b1.
|
60
|
+
@compute_result.call.should == (@b1.value | @b2.value) & @b1.value
|
61
61
|
end
|
62
62
|
|
63
63
|
it 'should handle being constrained to not be equal to be a nested expression' do
|
64
64
|
@stub.must_not_be == (@b1 | @b2) & @b1
|
65
65
|
@model.solve!
|
66
|
-
@compute_result.call.should_not == (@b1.
|
66
|
+
@compute_result.call.should_not == (@b1.value | @b2.value) & @b1.value
|
67
67
|
end
|
68
68
|
end
|
69
69
|
|
@@ -80,18 +80,22 @@ describe Gecode::Constraints::BoolEnum, ' (conjunction)' do
|
|
80
80
|
@model.solve!
|
81
81
|
end
|
82
82
|
@expect_options = lambda do |strength, reif_var|
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
83
|
+
@model.allow_space_access do
|
84
|
+
Gecode::Raw.should_receive(:bool_and).once.with(
|
85
|
+
an_instance_of(Gecode::Raw::Space),
|
86
|
+
an_instance_of(Gecode::Raw::BoolVarArray),
|
87
|
+
an_instance_of(Gecode::Raw::BoolVar), strength)
|
88
|
+
unless reif_var.nil?
|
89
|
+
Gecode::Raw.should_receive(:bool_eqv).once.with(
|
90
|
+
an_instance_of(Gecode::Raw::Space),
|
91
|
+
an_instance_of(Gecode::Raw::BoolVar), reif_var.bind, true, strength)
|
92
|
+
end
|
89
93
|
end
|
90
94
|
end
|
91
95
|
|
92
96
|
# For bool enum spec.
|
93
97
|
@stub = @bools.conjunction
|
94
|
-
@compute_result = lambda{ @bools.all?{ |b| b.
|
98
|
+
@compute_result = lambda{ @bools.all?{ |b| b.value } }
|
95
99
|
end
|
96
100
|
|
97
101
|
it_should_behave_like 'bool enum constraint'
|
@@ -111,18 +115,22 @@ describe Gecode::Constraints::BoolEnum, ' (disjunction)' do
|
|
111
115
|
@model.solve!
|
112
116
|
end
|
113
117
|
@expect_options = lambda do |strength, reif_var|
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
118
|
+
@model.allow_space_access do
|
119
|
+
Gecode::Raw.should_receive(:bool_or).once.with(
|
120
|
+
an_instance_of(Gecode::Raw::Space),
|
121
|
+
an_instance_of(Gecode::Raw::BoolVarArray),
|
122
|
+
an_instance_of(Gecode::Raw::BoolVar), strength)
|
123
|
+
unless reif_var.nil?
|
124
|
+
Gecode::Raw.should_receive(:bool_eqv).once.with(
|
125
|
+
an_instance_of(Gecode::Raw::Space),
|
126
|
+
an_instance_of(Gecode::Raw::BoolVar), reif_var.bind, true, strength)
|
127
|
+
end
|
120
128
|
end
|
121
129
|
end
|
122
130
|
|
123
131
|
# For bool enum spec.
|
124
132
|
@stub = @bools.disjunction
|
125
|
-
@compute_result = lambda{ @bools.any?{ |b| b.
|
133
|
+
@compute_result = lambda{ @bools.any?{ |b| b.value } }
|
126
134
|
end
|
127
135
|
|
128
136
|
it_should_behave_like 'bool enum constraint'
|
@@ -26,12 +26,16 @@ describe Gecode::Constraints::Bool do
|
|
26
26
|
@model.solve!
|
27
27
|
end
|
28
28
|
@expect_options = lambda do |strength, reif_var|
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
29
|
+
@model.allow_space_access do
|
30
|
+
Gecode::Raw.should_receive(:bool_or).once.with(
|
31
|
+
an_instance_of(Gecode::Raw::Space),
|
32
|
+
@b1.bind, @b2.bind, an_instance_of(Gecode::Raw::BoolVar),
|
33
|
+
Gecode::Raw::ICL_DEF)
|
34
|
+
unless reif_var.nil?
|
35
|
+
Gecode::Raw.should_receive(:bool_eqv).once.with(
|
36
|
+
an_instance_of(Gecode::Raw::Space),
|
37
|
+
an_instance_of(Gecode::Raw::BoolVar), reif_var.bind, true, strength)
|
38
|
+
end
|
35
39
|
end
|
36
40
|
end
|
37
41
|
end
|
@@ -40,148 +44,148 @@ describe Gecode::Constraints::Bool do
|
|
40
44
|
@b1.must_be.true
|
41
45
|
b1 = @model.solve!.b1
|
42
46
|
b1.should be_assigned
|
43
|
-
b1.
|
47
|
+
b1.value.should be_true
|
44
48
|
end
|
45
49
|
|
46
50
|
it 'should handle single variables constrainted to be false' do
|
47
51
|
@b1.must_be.false
|
48
52
|
b1 = @model.solve!.b1
|
49
53
|
b1.should be_assigned
|
50
|
-
b1.
|
54
|
+
b1.value.should_not be_true
|
51
55
|
end
|
52
56
|
|
53
57
|
it 'should handle single variables constrainted not to be false' do
|
54
58
|
@b1.must_not_be.false
|
55
59
|
b1 = @model.solve!.b1
|
56
60
|
b1.should be_assigned
|
57
|
-
b1.
|
61
|
+
b1.value.should be_true
|
58
62
|
end
|
59
63
|
|
60
64
|
it 'should handle single variables constrainted not to be true' do
|
61
65
|
@b1.must_not_be.true
|
62
66
|
b1 = @model.solve!.b1
|
63
67
|
b1.should be_assigned
|
64
|
-
b1.
|
68
|
+
b1.value.should_not be_true
|
65
69
|
end
|
66
70
|
|
67
71
|
it 'should handle disjunction' do
|
68
72
|
@b1.must_be.false
|
69
73
|
(@b1 | @b2).must_be.true
|
70
74
|
sol = @model.solve!
|
71
|
-
sol.b1.
|
72
|
-
sol.b2.
|
75
|
+
sol.b1.value.should_not be_true
|
76
|
+
sol.b2.value.should be_true
|
73
77
|
end
|
74
78
|
|
75
79
|
it 'should handle negated disjunction' do
|
76
80
|
@b1.must_be.false
|
77
81
|
(@b1 | @b2).must_not_be.true
|
78
82
|
sol = @model.solve!
|
79
|
-
sol.b1.
|
80
|
-
sol.b2.
|
83
|
+
sol.b1.value.should_not be_true
|
84
|
+
sol.b2.value.should_not be_true
|
81
85
|
end
|
82
86
|
|
83
87
|
it 'should handle conjunction' do
|
84
88
|
(@b1 & @b2).must_be.true
|
85
89
|
sol = @model.solve!
|
86
|
-
sol.b1.
|
87
|
-
sol.b2.
|
90
|
+
sol.b1.value.should be_true
|
91
|
+
sol.b2.value.should be_true
|
88
92
|
end
|
89
93
|
|
90
94
|
it 'should handle negated conjunction' do
|
91
95
|
@b1.must_be.true
|
92
96
|
(@b1 & @b2).must_not_be.true
|
93
97
|
sol = @model.solve!
|
94
|
-
sol.b1.
|
95
|
-
sol.b2.
|
98
|
+
sol.b1.value.should be_true
|
99
|
+
sol.b2.value.should_not be_true
|
96
100
|
end
|
97
101
|
|
98
102
|
it 'should handle exclusive or' do
|
99
103
|
@b1.must_be.false
|
100
104
|
(@b1 ^ @b2).must_be.true
|
101
105
|
sol = @model.solve!
|
102
|
-
sol.b1.
|
103
|
-
sol.b2.
|
106
|
+
sol.b1.value.should_not be_true
|
107
|
+
sol.b2.value.should be_true
|
104
108
|
end
|
105
109
|
|
106
110
|
it 'should handle negated exclusive or' do
|
107
111
|
@b1.must_be.true
|
108
112
|
(@b1 ^ @b2).must_not_be.true
|
109
113
|
sol = @model.solve!
|
110
|
-
sol.b1.
|
111
|
-
sol.b2.
|
114
|
+
sol.b1.value.should be_true
|
115
|
+
sol.b2.value.should be_true
|
112
116
|
end
|
113
117
|
|
114
118
|
it 'should handle implication' do
|
115
119
|
@b2.must_be.false
|
116
120
|
(@b1.implies @b2).must_be.true
|
117
121
|
sol = @model.solve!
|
118
|
-
sol.b1.
|
119
|
-
sol.b2.
|
122
|
+
sol.b1.value.should_not be_true
|
123
|
+
sol.b2.value.should_not be_true
|
120
124
|
end
|
121
125
|
|
122
126
|
it 'should handle negated implication' do
|
123
127
|
@b1.must_be.true
|
124
128
|
((@b1 | @b2).implies @b2).must_not_be.true
|
125
129
|
sol = @model.solve!
|
126
|
-
sol.b1.
|
127
|
-
sol.b2.
|
130
|
+
sol.b1.value.should be_true
|
131
|
+
sol.b2.value.should_not be_true
|
128
132
|
end
|
129
133
|
|
130
134
|
it 'should handle imply after must' do
|
131
135
|
@b2.must_be.false
|
132
136
|
@b1.must.imply @b2
|
133
137
|
sol = @model.solve!
|
134
|
-
sol.b1.
|
135
|
-
sol.b2.
|
138
|
+
sol.b1.value.should_not be_true
|
139
|
+
sol.b2.value.should_not be_true
|
136
140
|
end
|
137
141
|
|
138
142
|
it 'should handle imply after must_not' do
|
139
143
|
@b1.must_be.true
|
140
144
|
@b1.must_not.imply @b2
|
141
145
|
sol = @model.solve!
|
142
|
-
sol.b1.
|
143
|
-
sol.b2.
|
146
|
+
sol.b1.value.should be_true
|
147
|
+
sol.b2.value.should_not be_true
|
144
148
|
end
|
145
149
|
|
146
150
|
it 'should handle single variables as right hand side' do
|
147
151
|
@b1.must == @b2
|
148
152
|
@b2.must_be.false
|
149
153
|
sol = @model.solve!
|
150
|
-
sol.b1.
|
151
|
-
sol.b2.
|
154
|
+
sol.b1.value.should_not be_true
|
155
|
+
sol.b2.value.should_not be_true
|
152
156
|
end
|
153
157
|
|
154
158
|
it 'should handle single variables with negation as right hand side' do
|
155
159
|
@b1.must_not == @b2
|
156
160
|
@b2.must_be.false
|
157
161
|
sol = @model.solve!
|
158
|
-
sol.b1.
|
159
|
-
sol.b2.
|
162
|
+
sol.b1.value.should be_true
|
163
|
+
sol.b2.value.should_not be_true
|
160
164
|
end
|
161
165
|
|
162
166
|
it 'should handle expressions as right hand side' do
|
163
167
|
@b1.must == (@b2 | @b3)
|
164
168
|
@b2.must_be.true
|
165
169
|
sol = @model.solve!
|
166
|
-
sol.b1.
|
167
|
-
sol.b2.
|
170
|
+
sol.b1.value.should be_true
|
171
|
+
sol.b2.value.should be_true
|
168
172
|
end
|
169
173
|
|
170
174
|
it 'should handle nested expressions as left hand side' do
|
171
175
|
((@b1 & @b2) | @b3 | (@b1 & @b3)).must_be.true
|
172
176
|
@b1.must_be.false
|
173
177
|
sol = @model.solve!
|
174
|
-
sol.b1.
|
175
|
-
sol.b3.
|
178
|
+
sol.b1.value.should_not be_true
|
179
|
+
sol.b3.value.should be_true
|
176
180
|
end
|
177
181
|
|
178
182
|
it 'should handle nested expressions on both side' do
|
179
183
|
((@b1 & @b1) | @b3).must == ((@b1 & @b3) & @b2)
|
180
184
|
@b1.must_be.true
|
181
185
|
sol = @model.solve!
|
182
|
-
sol.b1.
|
183
|
-
sol.b2.
|
184
|
-
sol.b3.
|
186
|
+
sol.b1.value.should be_true
|
187
|
+
sol.b2.value.should be_true
|
188
|
+
sol.b3.value.should be_true
|
185
189
|
end
|
186
190
|
|
187
191
|
it 'should handle nested expressions containing exclusive or' do
|
@@ -189,9 +193,9 @@ describe Gecode::Constraints::Bool do
|
|
189
193
|
@b1.must_be.true
|
190
194
|
@b2.must_be.false
|
191
195
|
sol = @model.solve!
|
192
|
-
sol.b1.
|
193
|
-
sol.b2.
|
194
|
-
sol.b3.
|
196
|
+
sol.b1.value.should be_true
|
197
|
+
sol.b2.value.should_not be_true
|
198
|
+
sol.b3.value.should_not be_true
|
195
199
|
end
|
196
200
|
|
197
201
|
it 'should handle nested expressions on both sides with negation' do
|
@@ -199,9 +203,9 @@ describe Gecode::Constraints::Bool do
|
|
199
203
|
@b1.must_be.true
|
200
204
|
@b3.must_be.true
|
201
205
|
sol = @model.solve!
|
202
|
-
sol.b1.
|
203
|
-
sol.b2.
|
204
|
-
sol.b3.
|
206
|
+
sol.b1.value.should be_true
|
207
|
+
sol.b2.value.should_not be_true
|
208
|
+
sol.b3.value.should be_true
|
205
209
|
end
|
206
210
|
|
207
211
|
it 'should translate reification with a variable right hand side' do
|
@@ -209,7 +213,7 @@ describe Gecode::Constraints::Bool do
|
|
209
213
|
@b1.must_be.true
|
210
214
|
@b2.must_be.false
|
211
215
|
sol = @model.solve!
|
212
|
-
sol.b3.
|
216
|
+
sol.b3.value.should_not be_true
|
213
217
|
end
|
214
218
|
|
215
219
|
it 'should translate reification with a variable right hand side and negation' do
|
@@ -217,7 +221,7 @@ describe Gecode::Constraints::Bool do
|
|
217
221
|
@b1.must_be.true
|
218
222
|
@b2.must_be.false
|
219
223
|
sol = @model.solve!
|
220
|
-
sol.b3.
|
224
|
+
sol.b3.value.should be_true
|
221
225
|
end
|
222
226
|
|
223
227
|
|
@@ -18,8 +18,11 @@ describe Gecode::Constraints::Set::Cardinality, ' (range)' do
|
|
18
18
|
@model.solve!
|
19
19
|
end
|
20
20
|
@expect = lambda do |rhs|
|
21
|
-
|
22
|
-
|
21
|
+
@model.allow_space_access do
|
22
|
+
Gecode::Raw.should_receive(:cardinality).once.with(
|
23
|
+
an_instance_of(Gecode::Raw::Space),
|
24
|
+
@set.bind, rhs.first, rhs.last)
|
25
|
+
end
|
23
26
|
end
|
24
27
|
end
|
25
28
|
|
@@ -36,7 +39,7 @@ describe Gecode::Constraints::Set::Cardinality, ' (range)' do
|
|
36
39
|
it 'should constrain the cardinality of a set' do
|
37
40
|
@set.size.must_be.in @range
|
38
41
|
@model.solve!
|
39
|
-
@range.should include(@set.
|
42
|
+
@range.should include(@set.value.size)
|
40
43
|
end
|
41
44
|
|
42
45
|
it 'should raise error if the right hand side is not a range' do
|
@@ -44,10 +47,12 @@ describe Gecode::Constraints::Set::Cardinality, ' (range)' do
|
|
44
47
|
end
|
45
48
|
|
46
49
|
it 'should not shadow the integer variable domain constrain' do
|
47
|
-
Gecode::Raw.should_receive(:dom).once.with(
|
50
|
+
Gecode::Raw.should_receive(:dom).once.with(
|
51
|
+
an_instance_of(Gecode::Raw::Space),
|
48
52
|
an_instance_of(Gecode::Raw::IntVar), an_instance_of(Gecode::Raw::IntSet),
|
49
|
-
Gecode::Raw::ICL_DEF)
|
53
|
+
an_instance_of(Gecode::Raw::BoolVar), Gecode::Raw::ICL_DEF)
|
50
54
|
@set.size.must_not_be.in [1,3]
|
55
|
+
@model.solve!
|
51
56
|
end
|
52
57
|
|
53
58
|
it_should_behave_like 'non-reifiable set constraint'
|
@@ -61,35 +66,37 @@ describe Gecode::Constraints::Set::Cardinality, ' (composite)' do
|
|
61
66
|
@model.branch_on @model.wrap_enum([@set])
|
62
67
|
@model.branch_on @model.wrap_enum([@var])
|
63
68
|
|
64
|
-
@invoke_options = lambda do |hash|
|
65
|
-
@set.size.must_be.equal_to(@var, hash)
|
66
|
-
end
|
67
|
-
|
68
69
|
@invoke = lambda do |rhs|
|
69
70
|
@set.size.must == rhs
|
70
71
|
@model.solve!
|
71
72
|
end
|
72
73
|
@expect = lambda do |relation, rhs, strength, reif_var, negated|
|
73
|
-
|
74
|
-
|
75
|
-
if
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
74
|
+
@model.allow_space_access do
|
75
|
+
rhs = rhs.bind if rhs.respond_to? :bind
|
76
|
+
if reif_var.nil?
|
77
|
+
if !negated and relation == Gecode::Raw::IRT_EQ and
|
78
|
+
rhs.kind_of? Gecode::Raw::IntVar
|
79
|
+
Gecode::Raw.should_receive(:cardinality).once.with(
|
80
|
+
an_instance_of(Gecode::Raw::Space), @set.bind, rhs)
|
81
|
+
Gecode::Raw.should_receive(:rel).exactly(0).times
|
82
|
+
else
|
83
|
+
Gecode::Raw.should_receive(:cardinality).once.with(
|
84
|
+
an_instance_of(Gecode::Raw::Space), @set.bind,
|
85
|
+
an_instance_of(Gecode::Raw::IntVar))
|
86
|
+
Gecode::Raw.should_receive(:rel).once.with(
|
87
|
+
an_instance_of(Gecode::Raw::Space),
|
88
|
+
an_instance_of(Gecode::Raw::IntVar), relation, rhs,
|
89
|
+
strength)
|
90
|
+
end
|
80
91
|
else
|
81
92
|
Gecode::Raw.should_receive(:cardinality).once.with(
|
82
|
-
|
83
|
-
|
84
|
-
|
93
|
+
an_instance_of(Gecode::Raw::Space),
|
94
|
+
@set.bind, an_instance_of(Gecode::Raw::IntVar))
|
95
|
+
Gecode::Raw.should_receive(:rel).once.with(
|
96
|
+
an_instance_of(Gecode::Raw::Space),
|
97
|
+
an_instance_of(Gecode::Raw::IntVar), relation, rhs, reif_var.bind,
|
85
98
|
strength)
|
86
99
|
end
|
87
|
-
else
|
88
|
-
Gecode::Raw.should_receive(:cardinality).once.with(@model.active_space,
|
89
|
-
@set.bind, an_instance_of(Gecode::Raw::IntVar))
|
90
|
-
Gecode::Raw.should_receive(:rel).once.with(@model.active_space,
|
91
|
-
an_instance_of(Gecode::Raw::IntVar), relation, rhs, reif_var.bind,
|
92
|
-
strength)
|
93
100
|
end
|
94
101
|
end
|
95
102
|
|
@@ -119,7 +126,7 @@ describe Gecode::Constraints::Set::Cardinality, ' (composite)' do
|
|
119
126
|
it 'should constrain the cardinality of a set' do
|
120
127
|
@set.size.must == @var
|
121
128
|
@model.solve!
|
122
|
-
@set.
|
129
|
+
@set.value.size.should == @var.value
|
123
130
|
end
|
124
131
|
|
125
132
|
it_should_behave_like 'constraint with options'
|
@@ -4,17 +4,19 @@ require File.dirname(__FILE__) + '/constraint_helper'
|
|
4
4
|
class ChannelSampleProblem < Gecode::Model
|
5
5
|
attr :elements
|
6
6
|
attr :positions
|
7
|
+
attr :sets
|
7
8
|
|
8
9
|
def initialize
|
9
10
|
@elements = int_var_array(4, 0..3)
|
10
11
|
@elements.must_be.distinct
|
11
12
|
@positions = int_var_array(4, 0..3)
|
12
13
|
@positions.must_be.distinct
|
13
|
-
|
14
|
+
@sets = set_var_array(4, [], 0..3)
|
15
|
+
branch_on @positions
|
14
16
|
end
|
15
17
|
end
|
16
18
|
|
17
|
-
describe Gecode::Constraints::IntEnum::Channel do
|
19
|
+
describe Gecode::Constraints::IntEnum::Channel, ' (two int enums)' do
|
18
20
|
before do
|
19
21
|
@model = ChannelSampleProblem.new
|
20
22
|
@positions = @model.positions
|
@@ -24,14 +26,16 @@ describe Gecode::Constraints::IntEnum::Channel do
|
|
24
26
|
@model.solve!
|
25
27
|
end
|
26
28
|
@expect_options = lambda do |strength, reif_var|
|
27
|
-
Gecode::Raw.should_receive(:channel).once.with(
|
29
|
+
Gecode::Raw.should_receive(:channel).once.with(
|
30
|
+
an_instance_of(Gecode::Raw::Space),
|
28
31
|
an_instance_of(Gecode::Raw::IntVarArray),
|
29
32
|
an_instance_of(Gecode::Raw::IntVarArray), strength)
|
30
33
|
end
|
31
34
|
end
|
32
35
|
|
33
36
|
it 'should translate into a channel constraint' do
|
34
|
-
Gecode::Raw.should_receive(:channel).once.with(
|
37
|
+
Gecode::Raw.should_receive(:channel).once.with(
|
38
|
+
an_instance_of(Gecode::Raw::Space),
|
35
39
|
anything, anything, Gecode::Raw::ICL_DEF)
|
36
40
|
@invoke_options.call({})
|
37
41
|
end
|
@@ -39,8 +43,8 @@ describe Gecode::Constraints::IntEnum::Channel do
|
|
39
43
|
it 'should constrain variables to be channelled' do
|
40
44
|
@elements.must.channel @positions
|
41
45
|
@model.solve!
|
42
|
-
elements = @model.elements.
|
43
|
-
positions = @model.elements.
|
46
|
+
elements = @model.elements.values
|
47
|
+
positions = @model.elements.values
|
44
48
|
elements.each_with_index do |element, i|
|
45
49
|
element.should equal(positions.index(i))
|
46
50
|
end
|
@@ -51,5 +55,72 @@ describe Gecode::Constraints::IntEnum::Channel do
|
|
51
55
|
Gecode::MissingConstraintError)
|
52
56
|
end
|
53
57
|
|
58
|
+
it 'should raise error for unsupported right hand sides' do
|
59
|
+
lambda{ @elements.must.channel 'hello' }.should raise_error(TypeError)
|
60
|
+
end
|
61
|
+
|
54
62
|
it_should_behave_like 'constraint with strength option'
|
55
63
|
end
|
64
|
+
|
65
|
+
describe Gecode::Constraints::IntEnum::Channel, ' (one int enum and one set enum)' do
|
66
|
+
before do
|
67
|
+
@model = ChannelSampleProblem.new
|
68
|
+
@positions = @model.positions
|
69
|
+
@sets = @model.sets
|
70
|
+
end
|
71
|
+
|
72
|
+
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))
|
77
|
+
@positions.must.channel @sets
|
78
|
+
@model.solve!
|
79
|
+
end
|
80
|
+
|
81
|
+
it 'should constrain variables to be channelled' do
|
82
|
+
@positions.must.channel @sets
|
83
|
+
@model.solve!
|
84
|
+
sets = @model.sets
|
85
|
+
positions = @model.positions.values
|
86
|
+
positions.each_with_index do |position, i|
|
87
|
+
sets[position].value.should include(i)
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
describe Gecode::Constraints::SetEnum, ' (channel with set as left hand side)' do
|
93
|
+
before do
|
94
|
+
@model = ChannelSampleProblem.new
|
95
|
+
@positions = @model.positions
|
96
|
+
@sets = @model.sets
|
97
|
+
|
98
|
+
@invoke_options = lambda do |hash|
|
99
|
+
@sets.must.channel @positions, hash
|
100
|
+
@model.solve!
|
101
|
+
end
|
102
|
+
@expect_options = lambda do |strength, reif_var|
|
103
|
+
Gecode::Raw.should_receive(:channel).once.with(
|
104
|
+
an_instance_of(Gecode::Raw::Space),
|
105
|
+
an_instance_of(Gecode::Raw::IntVarArray),
|
106
|
+
an_instance_of(Gecode::Raw::SetVarArray))
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
it 'should translate into a channel constraint' do
|
111
|
+
@expect_options.call(Gecode::Raw::ICL_DEF, nil)
|
112
|
+
@sets.must.channel @positions
|
113
|
+
@model.solve!
|
114
|
+
end
|
115
|
+
|
116
|
+
it 'should not allow negation' do
|
117
|
+
lambda{ @sets.must_not.channel @positions }.should raise_error(
|
118
|
+
Gecode::MissingConstraintError)
|
119
|
+
end
|
120
|
+
|
121
|
+
it 'should raise error for unsupported right hand sides' do
|
122
|
+
lambda{ @sets.must.channel 'hello' }.should raise_error(TypeError)
|
123
|
+
end
|
124
|
+
|
125
|
+
it_should_behave_like 'non-reifiable set constraint'
|
126
|
+
end
|