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.
- data/CHANGES +15 -0
- data/README +6 -2
- data/example/equation_system.rb +15 -0
- data/example/magic_sequence.rb +7 -7
- data/example/money.rb +36 -0
- data/example/queens.rb +7 -8
- data/example/send_most_money.rb +1 -1
- data/example/square_tiling.rb +2 -2
- data/example/sudoku-set.rb +11 -12
- data/example/sudoku.rb +40 -45
- data/ext/extconf.rb +0 -0
- data/lib/gecoder/bindings.rb +42 -0
- data/lib/gecoder/bindings/bindings.rb +16 -0
- data/lib/gecoder/interface.rb +2 -1
- data/lib/gecoder/interface/branch.rb +16 -9
- data/lib/gecoder/interface/constraints.rb +410 -451
- data/lib/gecoder/interface/constraints/bool/boolean.rb +205 -213
- data/lib/gecoder/interface/constraints/bool/channel.rb +4 -5
- data/lib/gecoder/interface/constraints/bool/linear.rb +192 -21
- data/lib/gecoder/interface/constraints/bool_enum/channel.rb +43 -39
- data/lib/gecoder/interface/constraints/bool_enum/extensional.rb +43 -49
- data/lib/gecoder/interface/constraints/bool_enum/relation.rb +38 -71
- data/lib/gecoder/interface/constraints/bool_enum_constraints.rb +73 -22
- data/lib/gecoder/interface/constraints/bool_var_constraints.rb +140 -61
- data/lib/gecoder/interface/constraints/extensional_regexp.rb +4 -4
- data/lib/gecoder/interface/constraints/fixnum_enum/element.rb +63 -0
- data/lib/gecoder/interface/constraints/fixnum_enum/operation.rb +65 -0
- data/lib/gecoder/interface/constraints/fixnum_enum_constraints.rb +42 -0
- data/lib/gecoder/interface/constraints/int/arithmetic.rb +131 -130
- data/lib/gecoder/interface/constraints/int/channel.rb +21 -31
- data/lib/gecoder/interface/constraints/int/domain.rb +45 -42
- data/lib/gecoder/interface/constraints/int/linear.rb +85 -239
- data/lib/gecoder/interface/constraints/int/relation.rb +141 -0
- data/lib/gecoder/interface/constraints/int_enum/arithmetic.rb +55 -64
- data/lib/gecoder/interface/constraints/int_enum/channel.rb +35 -37
- data/lib/gecoder/interface/constraints/int_enum/count.rb +53 -78
- data/lib/gecoder/interface/constraints/int_enum/distinct.rb +36 -46
- data/lib/gecoder/interface/constraints/int_enum/element.rb +39 -57
- data/lib/gecoder/interface/constraints/int_enum/equality.rb +15 -19
- data/lib/gecoder/interface/constraints/int_enum/extensional.rb +65 -72
- data/lib/gecoder/interface/constraints/int_enum/sort.rb +42 -45
- data/lib/gecoder/interface/constraints/int_enum_constraints.rb +79 -22
- data/lib/gecoder/interface/constraints/int_var_constraints.rb +215 -44
- data/lib/gecoder/interface/constraints/reifiable_constraints.rb +14 -14
- data/lib/gecoder/interface/constraints/selected_set/select.rb +120 -0
- data/lib/gecoder/interface/constraints/selected_set_constraints.rb +75 -0
- data/lib/gecoder/interface/constraints/set/cardinality.rb +43 -53
- data/lib/gecoder/interface/constraints/set/channel.rb +26 -29
- data/lib/gecoder/interface/constraints/set/connection.rb +89 -152
- data/lib/gecoder/interface/constraints/set/domain.rb +112 -65
- data/lib/gecoder/interface/constraints/set/include.rb +36 -0
- data/lib/gecoder/interface/constraints/set/operation.rb +96 -110
- data/lib/gecoder/interface/constraints/set/relation.rb +114 -137
- data/lib/gecoder/interface/constraints/set_elements/relation.rb +116 -0
- data/lib/gecoder/interface/constraints/set_elements_constraints.rb +97 -0
- data/lib/gecoder/interface/constraints/set_enum/channel.rb +23 -27
- data/lib/gecoder/interface/constraints/set_enum/distinct.rb +18 -19
- data/lib/gecoder/interface/constraints/set_enum/operation.rb +62 -53
- data/lib/gecoder/interface/constraints/set_enum/select.rb +79 -0
- data/lib/gecoder/interface/constraints/set_enum_constraints.rb +73 -23
- data/lib/gecoder/interface/constraints/set_var_constraints.rb +222 -57
- data/lib/gecoder/interface/enum_matrix.rb +4 -4
- data/lib/gecoder/interface/enum_wrapper.rb +71 -22
- data/lib/gecoder/interface/model.rb +167 -12
- data/lib/gecoder/interface/model_sugar.rb +84 -0
- data/lib/gecoder/interface/search.rb +30 -18
- data/lib/gecoder/interface/variables.rb +103 -33
- data/lib/gecoder/version.rb +2 -2
- data/specs/bool_var.rb +19 -12
- data/specs/constraints/{boolean.rb → bool/boolean.rb} +103 -28
- data/specs/constraints/bool/boolean_properties.rb +51 -0
- data/specs/constraints/bool/linear.rb +213 -0
- data/specs/constraints/bool_enum/bool_enum_relation.rb +117 -0
- data/specs/constraints/bool_enum/channel.rb +102 -0
- data/specs/constraints/{extensional.rb → bool_enum/extensional.rb} +32 -101
- data/specs/constraints/constraint_helper.rb +149 -179
- data/specs/constraints/constraint_receivers.rb +103 -0
- data/specs/constraints/constraints.rb +6 -63
- data/specs/constraints/fixnum_enum/element.rb +58 -0
- data/specs/constraints/fixnum_enum/operation.rb +67 -0
- data/specs/constraints/int/arithmetic.rb +149 -0
- data/specs/constraints/int/channel.rb +101 -0
- data/specs/constraints/int/domain.rb +106 -0
- data/specs/constraints/int/linear.rb +183 -0
- data/specs/constraints/int/linear_properties.rb +97 -0
- data/specs/constraints/int/relation.rb +84 -0
- data/specs/constraints/int_enum/arithmetic.rb +72 -0
- data/specs/constraints/int_enum/channel.rb +57 -0
- data/specs/constraints/int_enum/count.rb +72 -0
- data/specs/constraints/int_enum/distinct.rb +80 -0
- data/specs/constraints/int_enum/element.rb +61 -0
- data/specs/constraints/int_enum/equality.rb +29 -0
- data/specs/constraints/int_enum/extensional.rb +224 -0
- data/specs/constraints/int_enum/sort.rb +167 -0
- data/specs/constraints/operands.rb +264 -0
- data/specs/constraints/property_helper.rb +443 -0
- data/specs/constraints/reification_sugar.rb +4 -5
- data/specs/constraints/selected_set/select.rb +56 -0
- data/specs/constraints/selected_set/select_properties.rb +157 -0
- data/specs/constraints/set/cardinality.rb +58 -0
- data/specs/constraints/set/cardinality_properties.rb +46 -0
- data/specs/constraints/set/channel.rb +77 -0
- data/specs/constraints/set/connection.rb +176 -0
- data/specs/constraints/set/domain.rb +197 -0
- data/specs/constraints/set/include.rb +36 -0
- data/specs/constraints/set/operation.rb +132 -0
- data/specs/constraints/set/relation.rb +117 -0
- data/specs/constraints/set_elements/relation.rb +84 -0
- data/specs/constraints/set_enum/channel.rb +80 -0
- data/specs/constraints/set_enum/distinct.rb +59 -0
- data/specs/constraints/set_enum/operation.rb +111 -0
- data/specs/constraints/set_enum/select.rb +73 -0
- data/specs/enum_wrapper.rb +53 -3
- data/specs/int_var.rb +44 -25
- data/specs/model.rb +58 -1
- data/specs/model_sugar.rb +30 -0
- data/specs/search.rb +24 -5
- data/specs/selected_set.rb +39 -0
- data/specs/set_elements.rb +34 -0
- data/specs/set_var.rb +22 -8
- data/specs/spec_helper.rb +206 -6
- data/tasks/distribution.rake +22 -7
- data/tasks/svn.rake +3 -1
- metadata +218 -134
- data/lib/gecoder/interface/constraints/set_enum/selection.rb +0 -217
- data/specs/constraints/arithmetic.rb +0 -351
- data/specs/constraints/bool_enum_relation.rb +0 -160
- data/specs/constraints/cardinality.rb +0 -157
- data/specs/constraints/channel.rb +0 -454
- data/specs/constraints/connection.rb +0 -369
- data/specs/constraints/count.rb +0 -146
- data/specs/constraints/distinct.rb +0 -164
- data/specs/constraints/element.rb +0 -108
- data/specs/constraints/equality.rb +0 -31
- data/specs/constraints/int_domain.rb +0 -70
- data/specs/constraints/int_relation.rb +0 -82
- data/specs/constraints/linear.rb +0 -340
- data/specs/constraints/selection.rb +0 -292
- data/specs/constraints/set_domain.rb +0 -185
- data/specs/constraints/set_operation.rb +0 -285
- data/specs/constraints/set_relation.rb +0 -197
- data/specs/constraints/sort.rb +0 -179
@@ -0,0 +1,443 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../spec_helper'
|
2
|
+
|
3
|
+
# Every property should have a spec that specs the following:
|
4
|
+
#
|
5
|
+
# * An example where the property is used to constrain a sample problem.
|
6
|
+
# * should_behave_like foo operand
|
7
|
+
# * A test that the property is translated to the correct Gecode
|
8
|
+
# constraint if deemed necessary.
|
9
|
+
|
10
|
+
# Several of these shared specs requires one or more of the following instance
|
11
|
+
# variables to be used:
|
12
|
+
# [@operand] The operand that is being tested.
|
13
|
+
# [@model] The model that defines the context in which the test is
|
14
|
+
# conducted.
|
15
|
+
# [@property_types] An array of symbols signaling what types of
|
16
|
+
# arguments @select_property accepts. The symbols
|
17
|
+
# must be one of: :int, :bool, :set, :int_enum,
|
18
|
+
# :bool_enum, :set_enum, :fixnum_enum.
|
19
|
+
# [@select_property] A proc that selects the property under test. It
|
20
|
+
# should take at least one argument: the operand that
|
21
|
+
# the property should be selected from.
|
22
|
+
# [@selected_property] The resulting operand of the property. It should
|
23
|
+
# be constrained to the degree that it has a
|
24
|
+
# non-maximal domain.
|
25
|
+
# [@constraint_class] The class of the constraints that are expected to be
|
26
|
+
# produced when a constraint is short circuited.
|
27
|
+
#
|
28
|
+
|
29
|
+
|
30
|
+
# Requires @operand and @model.
|
31
|
+
describe 'int var operand', :shared => true do
|
32
|
+
it 'should implement #model' do
|
33
|
+
@operand.model.should be_kind_of(Gecode::Model)
|
34
|
+
end
|
35
|
+
|
36
|
+
it 'should implement #to_int_var' do
|
37
|
+
int_var = @operand.to_int_var
|
38
|
+
int_var.should be_kind_of(Gecode::IntVar)
|
39
|
+
@model.solve!
|
40
|
+
(int_var.min..int_var.max).should_not equal(Gecode::Model::LARGEST_INT_DOMAIN)
|
41
|
+
end
|
42
|
+
|
43
|
+
it 'should implement #must' do
|
44
|
+
receiver = @operand.must
|
45
|
+
receiver.should be_kind_of(
|
46
|
+
Gecode::Int::IntConstraintReceiver)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
# Requires @operand and @model.
|
51
|
+
describe 'bool var operand', :shared => true do
|
52
|
+
it 'should implement #model' do
|
53
|
+
@operand.model.should be_kind_of(Gecode::Model)
|
54
|
+
end
|
55
|
+
|
56
|
+
it 'should implement #to_bool_var' do
|
57
|
+
bool_var = @operand.to_bool_var
|
58
|
+
bool_var.should be_kind_of(Gecode::BoolVar)
|
59
|
+
end
|
60
|
+
|
61
|
+
it 'should implement #must' do
|
62
|
+
receiver = @operand.must
|
63
|
+
receiver.should be_kind_of(
|
64
|
+
Gecode::Bool::BoolConstraintReceiver)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
# Requires @operand and @model.
|
69
|
+
describe 'set var operand', :shared => true do
|
70
|
+
it 'should implement #model' do
|
71
|
+
@operand.model.should be_kind_of(Gecode::Model)
|
72
|
+
end
|
73
|
+
|
74
|
+
it 'should implement #to_set_var' do
|
75
|
+
set_var = @operand.to_set_var
|
76
|
+
set_var.should be_kind_of(Gecode::SetVar)
|
77
|
+
@model.solve!
|
78
|
+
((set_var.lower_bound == []) &&
|
79
|
+
(set_var.upper_bound == Gecode::Model::LARGEST_SET_BOUND)).should_not(
|
80
|
+
be_true)
|
81
|
+
end
|
82
|
+
|
83
|
+
it 'should implement #must' do
|
84
|
+
receiver = @operand.must
|
85
|
+
receiver.should be_kind_of(
|
86
|
+
Gecode::Set::SetConstraintReceiver)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
# Requires @model, @property_types and @select_property.
|
91
|
+
describe 'property that produces operand', :shared => true do
|
92
|
+
it 'should raise errors if parameters of the incorrect type are given' do
|
93
|
+
operands, variables = produce_general_arguments(@property_types)
|
94
|
+
(1...operands.size).each do |i|
|
95
|
+
bogus_operands = operands.clone
|
96
|
+
bogus_operands[i] = Object.new
|
97
|
+
lambda do
|
98
|
+
@select_property.call(*bogus_operands)
|
99
|
+
end.should raise_error(TypeError)
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
# Requires @model, @property_types and @select_property.
|
105
|
+
describe 'property that produces int operand', :shared => true do
|
106
|
+
it 'should produce int operand' do
|
107
|
+
operands, variables = produce_general_arguments(@property_types)
|
108
|
+
operand = @select_property.call(*operands)
|
109
|
+
|
110
|
+
# Test the same invariants as in the test for int var operands.
|
111
|
+
operand.model.should be_kind_of(Gecode::Model)
|
112
|
+
|
113
|
+
int_var = operand.to_int_var
|
114
|
+
int_var.should be_kind_of(Gecode::IntVar)
|
115
|
+
|
116
|
+
receiver = operand.must
|
117
|
+
receiver.should be_kind_of(
|
118
|
+
Gecode::Int::IntConstraintReceiver)
|
119
|
+
end
|
120
|
+
|
121
|
+
it_should_behave_like 'property that produces operand'
|
122
|
+
end
|
123
|
+
|
124
|
+
# Requires @model, @property_types and @select_property.
|
125
|
+
describe 'property that produces bool operand', :shared => true do
|
126
|
+
it 'should produce bool operand' do
|
127
|
+
operands, variables = produce_general_arguments(@property_types)
|
128
|
+
operand = @select_property.call(*operands)
|
129
|
+
|
130
|
+
# Test the same invariants as in the test for bool var operands.
|
131
|
+
operand.model.should be_kind_of(Gecode::Model)
|
132
|
+
|
133
|
+
bool_var = operand.to_bool_var
|
134
|
+
bool_var.should be_kind_of(Gecode::BoolVar)
|
135
|
+
|
136
|
+
receiver = operand.must
|
137
|
+
receiver.should be_kind_of(
|
138
|
+
Gecode::Bool::BoolConstraintReceiver)
|
139
|
+
end
|
140
|
+
|
141
|
+
it_should_behave_like 'property that produces operand'
|
142
|
+
end
|
143
|
+
|
144
|
+
# Requires @model, @property_types and @select_property.
|
145
|
+
describe 'property that produces set operand', :shared => true do
|
146
|
+
it 'should produce set operand' do
|
147
|
+
operands, variables = produce_general_arguments(@property_types)
|
148
|
+
operand = @select_property.call(*operands)
|
149
|
+
|
150
|
+
# Test the same invariants as in the test for int var operands.
|
151
|
+
operand.model.should be_kind_of(Gecode::Model)
|
152
|
+
|
153
|
+
set_var = operand.to_set_var
|
154
|
+
set_var.should be_kind_of(Gecode::SetVar)
|
155
|
+
|
156
|
+
receiver = operand.must
|
157
|
+
receiver.should be_kind_of(
|
158
|
+
Gecode::Set::SetConstraintReceiver)
|
159
|
+
end
|
160
|
+
|
161
|
+
it_should_behave_like 'property that produces operand'
|
162
|
+
end
|
163
|
+
|
164
|
+
# Requires @model, @constraint_class, @property_types, @select_property and
|
165
|
+
# @selected_property.
|
166
|
+
#
|
167
|
+
# These properties should only short circuit equality when there is no
|
168
|
+
# negation nor reification and the right hand side is an int operand.
|
169
|
+
describe 'property that produces int operand by short circuiting equality', :shared => true do
|
170
|
+
it 'should produce constraints when short circuited' do
|
171
|
+
@constraint_class.superclass.should == Gecode::Constraint
|
172
|
+
end
|
173
|
+
|
174
|
+
it 'should give the same solution regardless of whether short circuit was used' do
|
175
|
+
int_operand = @selected_property
|
176
|
+
direct_int_var = int_operand.to_int_var
|
177
|
+
indirect_int_op, _ = general_int_operand(@model)
|
178
|
+
@selected_property.must == indirect_int_op
|
179
|
+
@model.solve!
|
180
|
+
|
181
|
+
direct_int_var.should_not have_domain(Gecode::Model::LARGEST_INT_DOMAIN)
|
182
|
+
direct_int_var.should have_domain(indirect_int_op.domain)
|
183
|
+
end
|
184
|
+
|
185
|
+
it 'should short circuit equality' do
|
186
|
+
(@selected_property.must == @model.int_var).should(
|
187
|
+
be_kind_of(@constraint_class))
|
188
|
+
end
|
189
|
+
|
190
|
+
it 'should not short circuit when negation is used' do
|
191
|
+
(@selected_property.must_not == @model.int_var).should_not(
|
192
|
+
be_kind_of(@constraint_class))
|
193
|
+
end
|
194
|
+
|
195
|
+
it 'should not short circuit when reification is used' do
|
196
|
+
@selected_property.must.equal(@model.int_var,
|
197
|
+
:reify => @model.bool_var).should_not(be_kind_of(@constraint_class))
|
198
|
+
end
|
199
|
+
|
200
|
+
it 'should not short circuit when the right hand side is not a operand' do
|
201
|
+
@selected_property.must.equal(2).should_not(be_kind_of(@constraint_class))
|
202
|
+
end
|
203
|
+
|
204
|
+
it 'should not short circuit when equality is not used' do
|
205
|
+
(@selected_property.must > @model.int_var).should_not(
|
206
|
+
be_kind_of(@constraint_class))
|
207
|
+
end
|
208
|
+
|
209
|
+
it 'should raise error when the right hand side is of illegal type' do
|
210
|
+
lambda do
|
211
|
+
@selected_property.must == 'foo'
|
212
|
+
end.should raise_error(TypeError)
|
213
|
+
end
|
214
|
+
|
215
|
+
it_should_behave_like 'property that produces int operand'
|
216
|
+
end
|
217
|
+
|
218
|
+
# Requires @model, @constraint_class, @property_types, @select_property and
|
219
|
+
# @selected_property.
|
220
|
+
#
|
221
|
+
# These properties should only short circuit equality when there is no
|
222
|
+
# negation nor reification and the right hand side is a bool operand.
|
223
|
+
describe 'property that produces bool operand by short circuiting equality', :shared => true do
|
224
|
+
it 'should produce constraints when short circuited' do
|
225
|
+
@constraint_class.superclass.should == Gecode::Constraint
|
226
|
+
end
|
227
|
+
|
228
|
+
it 'should give the same solution regardless of whether short circuit was used' do
|
229
|
+
bool_operand = @selected_property
|
230
|
+
direct_bool_var = bool_operand.to_bool_var
|
231
|
+
indirect_bool_var = @model.bool_var
|
232
|
+
@selected_property.must == indirect_bool_var
|
233
|
+
@model.solve!
|
234
|
+
|
235
|
+
direct_bool_var.value.should == indirect_bool_var.value
|
236
|
+
end
|
237
|
+
|
238
|
+
it 'should short circuit equality' do
|
239
|
+
(@selected_property.must == @model.bool_var).should(
|
240
|
+
be_kind_of(@constraint_class))
|
241
|
+
end
|
242
|
+
|
243
|
+
it 'should not short circuit when negation is used' do
|
244
|
+
(@selected_property.must_not == @model.bool_var).should_not(
|
245
|
+
be_kind_of(@constraint_class))
|
246
|
+
end
|
247
|
+
|
248
|
+
it 'should not short circuit when reification is used' do
|
249
|
+
@selected_property.must.equal(@model.bool_var,
|
250
|
+
:reify => @model.bool_var).should_not(be_kind_of(@constraint_class))
|
251
|
+
end
|
252
|
+
|
253
|
+
it 'should not short circuit when equality is not used' do
|
254
|
+
(@selected_property.must.imply @model.bool_var).should_not(
|
255
|
+
be_kind_of(@constraint_class))
|
256
|
+
end
|
257
|
+
|
258
|
+
it 'should raise error when the right hand side is of illegal type' do
|
259
|
+
lambda do
|
260
|
+
@selected_property.must == 'foo'
|
261
|
+
end.should raise_error(TypeError)
|
262
|
+
end
|
263
|
+
|
264
|
+
it_should_behave_like 'property that produces bool operand'
|
265
|
+
end
|
266
|
+
|
267
|
+
# Requires @model, @constraint_class, @property_types and @select_property.
|
268
|
+
#
|
269
|
+
# These properties should short circuit all comparison relations
|
270
|
+
# even when negated and when fixnums are used as right hand side.
|
271
|
+
describe 'property that produces int operand by short circuiting relations', :shared => true do
|
272
|
+
it 'should produce reifiable constraints when short circuited' do
|
273
|
+
@constraint_class.superclass.should ==
|
274
|
+
Gecode::ReifiableConstraint
|
275
|
+
end
|
276
|
+
|
277
|
+
Gecode::Util::RELATION_TYPES.keys.each do |relation|
|
278
|
+
it "should give the same solution regardless of whether short circuit #{relation} was used" do
|
279
|
+
direct_int_var = @model.int_var
|
280
|
+
@selected_property.to_int_var.must.method(relation).call direct_int_var
|
281
|
+
indirect_int_var = @model.int_var
|
282
|
+
@selected_property.must.method(relation).call indirect_int_var
|
283
|
+
@model.solve!
|
284
|
+
|
285
|
+
direct_int_var.should_not have_domain(Gecode::Model::LARGEST_INT_DOMAIN)
|
286
|
+
direct_int_var.should have_domain(indirect_int_var.domain)
|
287
|
+
end
|
288
|
+
|
289
|
+
it "should short circuit #{relation}" do
|
290
|
+
(@selected_property.must.method(relation).call @model.int_var).should(
|
291
|
+
be_kind_of(@constraint_class))
|
292
|
+
end
|
293
|
+
|
294
|
+
it "should short circuit negated #{relation}" do
|
295
|
+
(@selected_property.must_not.method(relation).call @model.int_var).should(
|
296
|
+
be_kind_of(@constraint_class))
|
297
|
+
end
|
298
|
+
|
299
|
+
it "should short circuit #{relation} when reification is used" do
|
300
|
+
(@selected_property.must.method(relation).call(@model.int_var,
|
301
|
+
:reify => @model.bool_var)).should(be_kind_of(@constraint_class))
|
302
|
+
end
|
303
|
+
|
304
|
+
it "should short circuit #{relation} even when the right hand side is a fixnum" do
|
305
|
+
(@selected_property.must.method(relation).call 2).should(
|
306
|
+
be_kind_of(@constraint_class))
|
307
|
+
end
|
308
|
+
|
309
|
+
it "should raise error when the #{relation} right hand side is of illegal type" do
|
310
|
+
lambda do
|
311
|
+
@selected_property.must.method(relation).call('foo')
|
312
|
+
end.should raise_error(TypeError)
|
313
|
+
end
|
314
|
+
end
|
315
|
+
|
316
|
+
it_should_behave_like 'property that produces int operand'
|
317
|
+
end
|
318
|
+
|
319
|
+
# Requires @model, @constraint_class, @property_types, @select_property and
|
320
|
+
# @selected_property.
|
321
|
+
#
|
322
|
+
# These properties should only short circuit equality when there is no
|
323
|
+
# negation nor reification and the right hand side is a set operand.
|
324
|
+
describe 'property that produces set operand by short circuiting equality', :shared => true do
|
325
|
+
it 'should produce constraints when short circuited' do
|
326
|
+
@constraint_class.superclass.should == Gecode::Constraint
|
327
|
+
end
|
328
|
+
|
329
|
+
it 'should give the same solution regardless of whether short circuit was used' do
|
330
|
+
set_operand = @selected_property
|
331
|
+
direct_set_var = set_operand.to_set_var
|
332
|
+
indirect_set_var = @model.set_var
|
333
|
+
@selected_property.must == indirect_set_var
|
334
|
+
@model.solve!
|
335
|
+
|
336
|
+
direct_set_var.should have_bounds(indirect_set_var.lower_bound,
|
337
|
+
indirect_set_var.upper_bound)
|
338
|
+
end
|
339
|
+
|
340
|
+
it 'should short circuit equality' do
|
341
|
+
(@selected_property.must == @model.set_var).should(
|
342
|
+
be_kind_of(@constraint_class))
|
343
|
+
end
|
344
|
+
|
345
|
+
it 'should not short circuit when negation is used' do
|
346
|
+
(@selected_property.must_not == @model.set_var).should_not(
|
347
|
+
be_kind_of(@constraint_class))
|
348
|
+
end
|
349
|
+
|
350
|
+
it 'should not short circuit when reification is used' do
|
351
|
+
(@selected_property.must.equal(@model.set_var,
|
352
|
+
:reify => @model.bool_var)).should_not(be_kind_of(@constraint_class))
|
353
|
+
end
|
354
|
+
|
355
|
+
it 'should not short circuit when the right hand side is not a operand' do
|
356
|
+
(@selected_property.must == [1,3,5]).should_not(
|
357
|
+
be_kind_of(@constraint_class))
|
358
|
+
end
|
359
|
+
|
360
|
+
it 'should not short circuit when equality is not used' do
|
361
|
+
(@selected_property.must_be.subset_of(@model.set_var)).should_not(
|
362
|
+
be_kind_of(@constraint_class))
|
363
|
+
end
|
364
|
+
|
365
|
+
it 'should raise error when the right hand side is of illegal type' do
|
366
|
+
lambda do
|
367
|
+
@selected_property.must == 'foo'
|
368
|
+
end.should raise_error(TypeError)
|
369
|
+
end
|
370
|
+
|
371
|
+
it_should_behave_like 'property that produces set operand'
|
372
|
+
end
|
373
|
+
|
374
|
+
# Requires @model, @constraint_class, @property_types and @select_property.
|
375
|
+
#
|
376
|
+
# These properties should only short circuit set relations when neither
|
377
|
+
# negation nor reification is used (both for constant sets and set
|
378
|
+
# variables).
|
379
|
+
describe 'property that produces set operand by short circuiting set relations', :shared => true do
|
380
|
+
Gecode::Util::SET_RELATION_TYPES.keys.each do |relation|
|
381
|
+
it 'should produce constraints when short circuited' do
|
382
|
+
@constraint_class.superclass.should == Gecode::Constraint
|
383
|
+
end
|
384
|
+
|
385
|
+
it "should give the same solution regardless of whether short circuit #{relation} was used" do
|
386
|
+
if relation == :complement
|
387
|
+
direct_set_var, indirect_set_var = Array.new(2){ @model.set_var }
|
388
|
+
else
|
389
|
+
direct_set_var, indirect_set_var = Array.new(2) do
|
390
|
+
@model.set_var([], -1000..1000)
|
391
|
+
end
|
392
|
+
end
|
393
|
+
|
394
|
+
@selected_property.to_set_var.must.method(relation).call direct_set_var
|
395
|
+
@selected_property.must.method(relation).call indirect_set_var
|
396
|
+
@model.solve!
|
397
|
+
|
398
|
+
if relation == :complement
|
399
|
+
direct_set_var.upper_bound.min.should ==
|
400
|
+
indirect_set_var.upper_bound.min
|
401
|
+
direct_set_var.upper_bound.max.should ==
|
402
|
+
indirect_set_var.upper_bound.max
|
403
|
+
direct_set_var.lower_bound.min.should ==
|
404
|
+
indirect_set_var.lower_bound.min
|
405
|
+
direct_set_var.lower_bound.max.should ==
|
406
|
+
indirect_set_var.lower_bound.max
|
407
|
+
direct_set_var.lower_bound.size.should ==
|
408
|
+
indirect_set_var.lower_bound.size
|
409
|
+
else
|
410
|
+
direct_set_var.should have_bounds(indirect_set_var.lower_bound,
|
411
|
+
indirect_set_var.upper_bound)
|
412
|
+
end
|
413
|
+
end
|
414
|
+
|
415
|
+
it "should short circuit #{relation}" do
|
416
|
+
@selected_property.must.method(relation).call(@model.set_var).should(
|
417
|
+
be_kind_of(@constraint_class))
|
418
|
+
end
|
419
|
+
|
420
|
+
it "should not short circuit negated #{relation}" do
|
421
|
+
@selected_property.must_not.method(relation).call(
|
422
|
+
@model.set_var).should_not(be_kind_of(@constraint_class))
|
423
|
+
end
|
424
|
+
|
425
|
+
it "should not short circuit reified #{relation}" do
|
426
|
+
@selected_property.must.method(relation).call(@model.set_var,
|
427
|
+
:reify => @model.bool_var).should_not(be_kind_of(@constraint_class))
|
428
|
+
end
|
429
|
+
|
430
|
+
it "should short circuit #{relation} even when the right hand side is a constant set" do
|
431
|
+
@selected_property.must.method(relation).call([1, 2, 3]).should(
|
432
|
+
be_kind_of(@constraint_class))
|
433
|
+
end
|
434
|
+
|
435
|
+
it "should raise error when the #{relation} right hand side is of illegal type" do
|
436
|
+
lambda do
|
437
|
+
@selected_property.must.method(relation).call('foo')
|
438
|
+
end.should raise_error(TypeError)
|
439
|
+
end
|
440
|
+
end
|
441
|
+
|
442
|
+
it_should_behave_like 'property that produces set operand'
|
443
|
+
end
|
@@ -13,7 +13,7 @@ class ReifSugarSampleProblem < Gecode::Model
|
|
13
13
|
end
|
14
14
|
end
|
15
15
|
|
16
|
-
describe Gecode::
|
16
|
+
describe Gecode::ReifiableConstraint do
|
17
17
|
before do
|
18
18
|
@model = ReifSugarSampleProblem.new
|
19
19
|
@x = @model.x
|
@@ -23,7 +23,7 @@ describe Gecode::Constraints::ReifiableConstraint do
|
|
23
23
|
|
24
24
|
it 'should fail disjunctions if neither side can be satisfied' do
|
25
25
|
(@x.must == 3) | (@y.must == 3)
|
26
|
-
@model.solve
|
26
|
+
lambda{ @model.solve! }.should raise_error(Gecode::NoSolutionError)
|
27
27
|
end
|
28
28
|
|
29
29
|
it 'should solve disjunctions' do
|
@@ -35,7 +35,7 @@ describe Gecode::Constraints::ReifiableConstraint do
|
|
35
35
|
|
36
36
|
it 'should fail conjunctions if one side can\'t be satisfied' do
|
37
37
|
(@x.must > 3) & (@y.must == 3)
|
38
|
-
@model.solve
|
38
|
+
lambda{ @model.solve! }.should raise_error(Gecode::NoSolutionError)
|
39
39
|
end
|
40
40
|
|
41
41
|
it 'should solve conjunctions' do
|
@@ -64,7 +64,6 @@ describe Gecode::Constraints::ReifiableConstraint do
|
|
64
64
|
|
65
65
|
it 'should handle negations' do
|
66
66
|
(@z.must_not == 4) & (@z.must == 4)
|
67
|
-
|
68
|
-
sol.should be_nil
|
67
|
+
lambda{ @model.solve! }.should raise_error(Gecode::NoSolutionError)
|
69
68
|
end
|
70
69
|
end
|