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,197 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../constraint_helper'
|
2
|
+
|
3
|
+
Gecode::Util::SET_RELATION_TYPES.each_pair do |relation, type|
|
4
|
+
next if relation == :==
|
5
|
+
|
6
|
+
describe Gecode::Set::Domain, " (#{relation})" do
|
7
|
+
include GecodeR::Specs::SetHelper
|
8
|
+
|
9
|
+
before do
|
10
|
+
@model = Gecode::Model.new
|
11
|
+
@glb = []
|
12
|
+
@lub = 0..3
|
13
|
+
@set = @model.set_var(@glb, @lub)
|
14
|
+
@model.branch_on @set
|
15
|
+
@range = 0..1
|
16
|
+
@non_range = [0, 2]
|
17
|
+
@singleton = 0
|
18
|
+
|
19
|
+
@types = [:set]
|
20
|
+
@invoke = lambda do |receiver, hash|
|
21
|
+
receiver.method(relation).call(@non_range, hash)
|
22
|
+
@model.solve!
|
23
|
+
end
|
24
|
+
@expect = lambda do |var, opts, reif_var|
|
25
|
+
@expect_with_rhs.call(var, opts, reif_var, @non_range)
|
26
|
+
end
|
27
|
+
@expect_with_rhs = lambda do |var, opts, reif_var, rhs|
|
28
|
+
if reif_var.nil?
|
29
|
+
Gecode::Raw.should_receive(:dom).once.with(
|
30
|
+
an_instance_of(Gecode::Raw::Space),
|
31
|
+
var, type,
|
32
|
+
*expect_constant_set(rhs))
|
33
|
+
else
|
34
|
+
params = [an_instance_of(Gecode::Raw::Space),
|
35
|
+
var, type]
|
36
|
+
params << expect_constant_set(rhs)
|
37
|
+
params << reif_var
|
38
|
+
Gecode::Raw.should_receive(:dom).once.with(*params.flatten)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
it "should translate #{relation} with constant range to domain constraint" do
|
44
|
+
@expect_with_rhs.call(@model.allow_space_access{ @set.bind },
|
45
|
+
nil, nil, @range)
|
46
|
+
@set.must.send(relation, @range)
|
47
|
+
@model.solve!
|
48
|
+
end
|
49
|
+
|
50
|
+
it "should translate #{relation} with constant non-range to domain constraint" do
|
51
|
+
@expect_with_rhs.call(@model.allow_space_access{ @set.bind },
|
52
|
+
nil, nil, @non_range)
|
53
|
+
@set.must.send(relation, @non_range)
|
54
|
+
@model.solve!
|
55
|
+
end
|
56
|
+
|
57
|
+
it "should translate #{relation} with constant singleton to domain constraint" do
|
58
|
+
@expect_with_rhs.call(@model.allow_space_access{ @set.bind },
|
59
|
+
nil, nil, @singleton)
|
60
|
+
@set.must.send(relation, @singleton)
|
61
|
+
@model.solve!
|
62
|
+
end
|
63
|
+
|
64
|
+
it 'should raise error if the right hand side is not a constant set' do
|
65
|
+
lambda do
|
66
|
+
@set.must.send(relation, 'not a constant set')
|
67
|
+
end.should raise_error(TypeError)
|
68
|
+
end
|
69
|
+
|
70
|
+
it "should constrain the domain when #{relation} is used" do
|
71
|
+
@set = @model.set_var if relation == :complement
|
72
|
+
@set.must.method(relation).call(@non_range)
|
73
|
+
@model.solve!
|
74
|
+
@set.should be_assigned
|
75
|
+
case relation
|
76
|
+
when :superset
|
77
|
+
(@non_range - @set.value.to_a).should be_empty
|
78
|
+
when :subset
|
79
|
+
(@set.value.to_a - @non_range).should be_empty
|
80
|
+
when :complement
|
81
|
+
val = @set.value
|
82
|
+
val.min.should == Gecode::Model::SET_MIN_INT
|
83
|
+
val.max.should == Gecode::Model::SET_MAX_INT
|
84
|
+
@non_range.each do |element|
|
85
|
+
@set.not_in_upper_bound?(element).should be_true
|
86
|
+
end
|
87
|
+
when :disjoint
|
88
|
+
(@non_range & @set.value.to_a).should be_empty
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
it "should constrain the domain when negated #{relation} is used" do
|
93
|
+
@set.must_not.method(relation).call(@non_range)
|
94
|
+
@model.solve!
|
95
|
+
@set.should be_assigned
|
96
|
+
case relation
|
97
|
+
when :superset
|
98
|
+
(@non_range - @set.value.to_a).should_not be_empty
|
99
|
+
when :subset
|
100
|
+
(@set.value.to_a - @non_range).should_not be_empty
|
101
|
+
when :complement
|
102
|
+
val = @set.value
|
103
|
+
((val.min != Gecode::Model::SET_MIN_INT) ||
|
104
|
+
(val.max != Gecode::Model::SET_MAX_INT) ||
|
105
|
+
@non_range.any?{ |element| @set.in_lower_bound?(element) }
|
106
|
+
).should be_true
|
107
|
+
when :disjoint
|
108
|
+
(@non_range & @set.value.to_a).should_not be_empty
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
it_should_behave_like 'reifiable set constraint'
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
describe Gecode::Set::Domain, ' (equality)' do
|
117
|
+
include GecodeR::Specs::SetHelper
|
118
|
+
|
119
|
+
before do
|
120
|
+
@model = Gecode::Model.new
|
121
|
+
@glb = [0]
|
122
|
+
@lub = 0..3
|
123
|
+
@set = @model.set_var(@glb, @lub)
|
124
|
+
@range = 0..1
|
125
|
+
@non_range = [0, 2]
|
126
|
+
@singleton = 0
|
127
|
+
@model.branch_on @model.wrap_enum([@set])
|
128
|
+
|
129
|
+
@types = [:set]
|
130
|
+
@invoke = lambda do |receiver, hash|
|
131
|
+
receiver.equal(@non_range, hash)
|
132
|
+
@model.solve!
|
133
|
+
end
|
134
|
+
@expect = lambda do |var, opts, reif_var|
|
135
|
+
@expect_with_rhs.call(var, opts, reif_var, @non_range)
|
136
|
+
end
|
137
|
+
@expect_with_rhs = lambda do |var, opts, reif_var, rhs|
|
138
|
+
if reif_var.nil?
|
139
|
+
Gecode::Raw.should_receive(:dom).once.with(
|
140
|
+
an_instance_of(Gecode::Raw::Space),
|
141
|
+
var, Gecode::Raw::SRT_EQ,
|
142
|
+
*expect_constant_set(rhs))
|
143
|
+
else
|
144
|
+
params = [an_instance_of(Gecode::Raw::Space),
|
145
|
+
var, Gecode::Raw::SRT_EQ]
|
146
|
+
params << expect_constant_set(rhs)
|
147
|
+
params << reif_var
|
148
|
+
Gecode::Raw.should_receive(:dom).once.with(*params.flatten)
|
149
|
+
end
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
it 'should translate equality with constant range to domain constraint' do
|
154
|
+
@expect_with_rhs.call(@model.allow_space_access{ @set.bind },
|
155
|
+
nil, nil, @range)
|
156
|
+
@set.must == @range
|
157
|
+
@model.solve!
|
158
|
+
end
|
159
|
+
|
160
|
+
it 'should translate equality with constant non-range to domain constraint' do
|
161
|
+
@expect_with_rhs.call(@model.allow_space_access{ @set.bind },
|
162
|
+
nil, nil, @non_range)
|
163
|
+
@set.must == @non_range
|
164
|
+
@model.solve!
|
165
|
+
end
|
166
|
+
|
167
|
+
it 'should translate equality with constant singleton to domain constraint' do
|
168
|
+
@expect_with_rhs.call(@model.allow_space_access{ @set.bind },
|
169
|
+
nil, nil, @singleton)
|
170
|
+
@set.must == @singleton
|
171
|
+
@model.solve!
|
172
|
+
end
|
173
|
+
|
174
|
+
it 'should constrain the domain with equality' do
|
175
|
+
@set.must == @singleton
|
176
|
+
@model.solve!
|
177
|
+
@set.should be_assigned
|
178
|
+
@set.value.should include(@singleton)
|
179
|
+
@set.value.size.should == 1
|
180
|
+
end
|
181
|
+
|
182
|
+
it 'should constrain the domain with inequality' do
|
183
|
+
@set.must_not == @singleton
|
184
|
+
@model.solve!
|
185
|
+
@set.should be_assigned
|
186
|
+
@set.value.should include(@singleton)
|
187
|
+
((@set.value.size > 1) || (@set.value != [@singleton])).should be_true
|
188
|
+
end
|
189
|
+
|
190
|
+
it 'should raise error if the right hand side is not a constant set' do
|
191
|
+
lambda do
|
192
|
+
@set.must == 'not a constant set'
|
193
|
+
end.should raise_error(TypeError)
|
194
|
+
end
|
195
|
+
|
196
|
+
it_should_behave_like 'reifiable set constraint'
|
197
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../constraint_helper'
|
2
|
+
|
3
|
+
describe Gecode::Set::Connection, ' (include)' do
|
4
|
+
before do
|
5
|
+
@model = Gecode::Model.new
|
6
|
+
@set = @model.set_var([], 2..5)
|
7
|
+
@array = @model.int_var_array(4, 0..9)
|
8
|
+
@array.must_be.distinct
|
9
|
+
@model.branch_on @array
|
10
|
+
#@model.branch_on @model.wrap_enum([@set])
|
11
|
+
|
12
|
+
@types = [:set, :int_enum]
|
13
|
+
@invoke = lambda do |receiver, int_enum, hash|
|
14
|
+
if hash.empty?
|
15
|
+
receiver.include(int_enum)
|
16
|
+
else
|
17
|
+
receiver.include(int_enum, hash)
|
18
|
+
end
|
19
|
+
@model.solve!
|
20
|
+
end
|
21
|
+
@expect = lambda do |var1, var2, opts, reif_var|
|
22
|
+
Gecode::Raw.should_receive(:match).once.with(
|
23
|
+
an_instance_of(Gecode::Raw::Space),
|
24
|
+
var1, var2)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
it 'should constrain the variables to be included in the set' do
|
29
|
+
@set.must.include @array
|
30
|
+
@model.solve!.should_not be_nil
|
31
|
+
@array.all?{ |x| @set.lower_bound.include? x.value }.should be_true
|
32
|
+
end
|
33
|
+
|
34
|
+
it_should_behave_like 'non-reifiable set constraint'
|
35
|
+
it_should_behave_like 'non-negatable constraint'
|
36
|
+
end
|
@@ -0,0 +1,132 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../property_helper'
|
2
|
+
|
3
|
+
Gecode::Util::SET_OPERATION_TYPES.each_pair do |operation, type|
|
4
|
+
describe Gecode::Set::Operation, " (#{operation} with set variable)" do
|
5
|
+
before do
|
6
|
+
@model = Gecode::Model.new
|
7
|
+
@set1 = @model.set_var([0], 0..20)
|
8
|
+
@set2 = @model.set_var([1], 0..20)
|
9
|
+
@constant_set = [2, 3, 5]
|
10
|
+
@rhs = @model.set_var([], 0..20)
|
11
|
+
@model.branch_on @model.wrap_enum([@set1, @set2, @rhs])
|
12
|
+
|
13
|
+
@property_types = [:set, :set]
|
14
|
+
@select_property = lambda do |set1, set2|
|
15
|
+
set1.method(operation).call(set2)
|
16
|
+
end
|
17
|
+
@selected_property = @set1.method(operation).call(@set2)
|
18
|
+
@constraint_class =
|
19
|
+
Gecode::Set::Operation::OperationConstraint
|
20
|
+
end
|
21
|
+
|
22
|
+
it "should translate #{operation} into an operation constraint" do
|
23
|
+
@model.allow_space_access do
|
24
|
+
Gecode::Raw.should_receive(:rel).once.with(
|
25
|
+
an_instance_of(Gecode::Raw::Space), @set1.bind, type, @set2.bind,
|
26
|
+
Gecode::Raw::SRT_EQ, @rhs.bind)
|
27
|
+
end
|
28
|
+
@set1.method(operation).call(@set2).must == @rhs
|
29
|
+
@model.solve!
|
30
|
+
end
|
31
|
+
|
32
|
+
it "should constrain the #{operation} of the sets with variable rhs" do
|
33
|
+
@set1.method(operation).call(@set2).must == @rhs
|
34
|
+
@model.solve!
|
35
|
+
|
36
|
+
s1 = @set1.value.to_a
|
37
|
+
s2 = @set2.value.to_a
|
38
|
+
rhs = @rhs.value.to_a
|
39
|
+
case operation
|
40
|
+
when :union
|
41
|
+
(s1 | s2).should == rhs
|
42
|
+
when :disjoint_union
|
43
|
+
(s1 | s2).sort.should == rhs.sort
|
44
|
+
when :intersection
|
45
|
+
(s1 & s2).should == rhs
|
46
|
+
when :minus
|
47
|
+
(s1 - s2).should == rhs
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
it "should constrain the #{operation} of the sets when used with constant rhs" do
|
52
|
+
if operation == :union || operation == :disjoint_union
|
53
|
+
@constant_set << 0 << 1 # Or there will not be any solution.
|
54
|
+
end
|
55
|
+
@set1.method(operation).call(@set2).must == @constant_set
|
56
|
+
@model.solve!
|
57
|
+
|
58
|
+
s1 = @set1.value.to_a
|
59
|
+
s2 = @set2.value.to_a
|
60
|
+
rhs = @constant_set
|
61
|
+
case operation
|
62
|
+
when :union
|
63
|
+
(s1 | s2).sort.should == rhs.sort
|
64
|
+
when :disjoint_union
|
65
|
+
(s1 | s2).sort.should == rhs.sort
|
66
|
+
when :intersection
|
67
|
+
(s1 & s2).should == rhs
|
68
|
+
when :minus
|
69
|
+
(s1 - s2).should == rhs
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
it_should_behave_like(
|
74
|
+
'property that produces set operand by short circuiting set relations')
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
Gecode::Util::SET_OPERATION_TYPES.each_pair do |operation, type|
|
79
|
+
describe Gecode::Set::Operation, " (#{operation} with constant set)" do
|
80
|
+
before do
|
81
|
+
@model = Gecode::Model.new
|
82
|
+
@set = @model.set_var([0], 0..20)
|
83
|
+
@constant_set = [1, 3, 5]
|
84
|
+
@rhs = @model.set_var([], 0..20)
|
85
|
+
@model.branch_on @model.wrap_enum([@set, @rhs])
|
86
|
+
|
87
|
+
@property_types = [:set, :set]
|
88
|
+
@select_property = lambda do |set1, set2|
|
89
|
+
set1.method(operation).call(set2)
|
90
|
+
end
|
91
|
+
@selected_property = @set.method(operation).call(@constant_set)
|
92
|
+
@constraint_class =
|
93
|
+
Gecode::Set::Operation::OperationConstraint
|
94
|
+
end
|
95
|
+
|
96
|
+
it "should translate #{operation} into an operation constraint" do
|
97
|
+
@model.allow_space_access do
|
98
|
+
Gecode::Raw.should_receive(:rel).once.with(
|
99
|
+
an_instance_of(Gecode::Raw::Space), @set.bind, type,
|
100
|
+
an_instance_of(Gecode::Raw::IntSet),
|
101
|
+
Gecode::Raw::SRT_EQ, @rhs.bind)
|
102
|
+
end
|
103
|
+
@set.method(operation).call(@constant_set).must == @rhs
|
104
|
+
@model.solve!
|
105
|
+
end
|
106
|
+
|
107
|
+
it "should constrain the #{operation} of the sets with a variable rhs" do
|
108
|
+
@set.method(operation).call(@constant_set).must == @rhs
|
109
|
+
@model.solve!
|
110
|
+
|
111
|
+
s1 = @set.value.to_a
|
112
|
+
s2 = @constant_set
|
113
|
+
rhs = @rhs.value.to_a
|
114
|
+
case operation
|
115
|
+
when :union
|
116
|
+
(s1 | s2).should == rhs
|
117
|
+
when :disjoint_union
|
118
|
+
(s1 | s2).sort.should == rhs.sort
|
119
|
+
when :intersection
|
120
|
+
(s1 & s2).should == rhs
|
121
|
+
when :minus
|
122
|
+
(s1 - s2).should == rhs
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
# We do not test with a constant rhs since we do not have enough
|
127
|
+
# degrees of freedom to always find a solution.
|
128
|
+
|
129
|
+
it_should_behave_like(
|
130
|
+
'property that produces set operand by short circuiting set relations')
|
131
|
+
end
|
132
|
+
end
|
@@ -0,0 +1,117 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../constraint_helper'
|
2
|
+
|
3
|
+
Gecode::Util::SET_RELATION_TYPES.each_pair do |relation, type|
|
4
|
+
next if relation == :==
|
5
|
+
|
6
|
+
describe Gecode::Set::Relation, " (#{relation})" do
|
7
|
+
before do
|
8
|
+
@model = Gecode::Model.new
|
9
|
+
@set = @model.set_var([0], 0..3)
|
10
|
+
@set2 = @model.set_var([1], 0..3)
|
11
|
+
@model.branch_on @model.wrap_enum([@set, @set2])
|
12
|
+
|
13
|
+
@types = [:set, :set]
|
14
|
+
@invoke = lambda do |receiver, set_op, hash|
|
15
|
+
receiver.method(relation).call(set_op, hash)
|
16
|
+
@model.solve!
|
17
|
+
end
|
18
|
+
@expect = lambda do |var1, var2, opts, reif_var|
|
19
|
+
if reif_var.nil?
|
20
|
+
Gecode::Raw.should_receive(:rel).once.with(
|
21
|
+
an_instance_of(Gecode::Raw::Space),
|
22
|
+
var1, type, var2)
|
23
|
+
else
|
24
|
+
Gecode::Raw.should_receive(:rel).once.with(
|
25
|
+
an_instance_of(Gecode::Raw::Space),
|
26
|
+
var1, type, var2, reif_var)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
it "should correctly constrain the set when #{relation} is used" do
|
32
|
+
@set = @model.set_var if relation == :complement
|
33
|
+
@set.must.method(relation).call(@set2)
|
34
|
+
@model.solve!
|
35
|
+
@set.should be_assigned
|
36
|
+
@set2.should be_assigned
|
37
|
+
case relation
|
38
|
+
when :superset
|
39
|
+
(@set2.value.to_a - @set.value.to_a).should be_empty
|
40
|
+
when :subset
|
41
|
+
(@set.value.to_a - @set2.value.to_a).should be_empty
|
42
|
+
when :complement
|
43
|
+
val = @set.value
|
44
|
+
val.min.should == Gecode::Model::SET_MIN_INT
|
45
|
+
val.max.should == Gecode::Model::SET_MAX_INT
|
46
|
+
@set2.value.each do |element|
|
47
|
+
@set.not_in_upper_bound?(element).should be_true
|
48
|
+
end
|
49
|
+
when :disjoint
|
50
|
+
(@set2.value.to_a & @set.value.to_a).should be_empty
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
it "should correctly constrain the set when negated #{relation} is used" do
|
55
|
+
@set.must_not.method(relation).call(@set2)
|
56
|
+
@model.solve!
|
57
|
+
@set.should be_assigned
|
58
|
+
@set2.should be_assigned
|
59
|
+
case relation
|
60
|
+
when :superset
|
61
|
+
(@set2.value.to_a - @set.value.to_a).should_not be_empty
|
62
|
+
when :subset
|
63
|
+
(@set.value.to_a - @set2.value.to_a).should_not be_empty
|
64
|
+
when :complement
|
65
|
+
val = @set.value
|
66
|
+
((val.min != Gecode::Model::SET_MIN_INT) ||
|
67
|
+
(val.max != Gecode::Model::SET_MAX_INT) ||
|
68
|
+
@set.value.to_a.any?{ |element| @set.in_lower_bound?(element) }
|
69
|
+
).should be_true
|
70
|
+
when :disjoint
|
71
|
+
(@set.value.to_a & @set.value.to_a).should_not be_empty
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
it_should_behave_like 'reifiable set constraint'
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
describe Gecode::Set::Relation, ' (equality)' do
|
80
|
+
before do
|
81
|
+
@model = Gecode::Model.new
|
82
|
+
@set = @model.set_var([0], 0..1)
|
83
|
+
@set2 = @model.set_var([1], 0..1)
|
84
|
+
@model.branch_on @model.wrap_enum([@set, @set2])
|
85
|
+
|
86
|
+
@types = [:set, :set]
|
87
|
+
@invoke = lambda do |receiver, set_op, hash|
|
88
|
+
receiver.equal(set_op, hash)
|
89
|
+
@model.solve!
|
90
|
+
end
|
91
|
+
@expect = lambda do |var1, var2, opts, reif_var|
|
92
|
+
if reif_var.nil?
|
93
|
+
Gecode::Raw.should_receive(:rel).once.with(
|
94
|
+
an_instance_of(Gecode::Raw::Space),
|
95
|
+
var1, Gecode::Raw::SRT_EQ, var2)
|
96
|
+
else
|
97
|
+
Gecode::Raw.should_receive(:rel).once.with(
|
98
|
+
an_instance_of(Gecode::Raw::Space),
|
99
|
+
var1, Gecode::Raw::SRT_EQ, var2, reif_var)
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
it 'should constrain sets to be equal' do
|
105
|
+
@set.must == @set2
|
106
|
+
@model.solve!
|
107
|
+
@set.value.to_a.should == @set2.value.to_a
|
108
|
+
end
|
109
|
+
|
110
|
+
it 'should constrain sets to not be equal when negated' do
|
111
|
+
@set.must_not == @set2
|
112
|
+
@model.solve!
|
113
|
+
@set.value.to_a.should_not == @set2.value.to_a
|
114
|
+
end
|
115
|
+
|
116
|
+
it_should_behave_like 'reifiable set constraint'
|
117
|
+
end
|