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,56 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../constraint_helper'
|
2
|
+
|
3
|
+
class SelectionSampleProblem < Gecode::Model
|
4
|
+
attr :sets
|
5
|
+
attr :set
|
6
|
+
attr :target
|
7
|
+
attr :index
|
8
|
+
|
9
|
+
def initialize
|
10
|
+
@sets = set_var_array(3, [], 0..20)
|
11
|
+
@set = set_var([], 0...3)
|
12
|
+
@target = set_var([], 0..20)
|
13
|
+
@index = int_var(0...3)
|
14
|
+
branch_on wrap_enum([@index])
|
15
|
+
branch_on @sets
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
describe Gecode::SetEnum::Select, ' (disjoint)' do
|
20
|
+
include GecodeR::Specs::SetHelper
|
21
|
+
|
22
|
+
before do
|
23
|
+
@model = SelectionSampleProblem.new
|
24
|
+
@sets = @model.sets
|
25
|
+
@set = @model.set
|
26
|
+
@target = @model.target
|
27
|
+
@model.branch_on @model.wrap_enum([@target, @set])
|
28
|
+
|
29
|
+
@types = [:selected_set]
|
30
|
+
@invoke = lambda do |receiver, hash|
|
31
|
+
receiver.disjoint(hash)
|
32
|
+
@model.solve!
|
33
|
+
end
|
34
|
+
@expect = lambda do |var, opts, reif_var|
|
35
|
+
set_enum, set = var
|
36
|
+
Gecode::Raw.should_receive(:selectDisjoint).once.with(
|
37
|
+
an_instance_of(Gecode::Raw::Space),
|
38
|
+
set_enum, set)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
it 'should constrain the selected sets to be disjoint' do
|
43
|
+
@sets[0].must_be.superset_of([7,8])
|
44
|
+
@sets[1].must_be.superset_of([5,7,9])
|
45
|
+
@sets[2].must_be.superset_of([6,8,10])
|
46
|
+
@sets[@set].must_be.disjoint
|
47
|
+
@set.size.must > 1
|
48
|
+
@model.solve!.should_not be_nil
|
49
|
+
|
50
|
+
@set.value.to_a.sort.should == [1,2]
|
51
|
+
end
|
52
|
+
|
53
|
+
it_should_behave_like 'non-reifiable set constraint'
|
54
|
+
it_should_behave_like 'non-negatable constraint'
|
55
|
+
end
|
56
|
+
|
@@ -0,0 +1,157 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../property_helper'
|
2
|
+
|
3
|
+
class SelectionSampleProblem < Gecode::Model
|
4
|
+
attr :sets
|
5
|
+
attr :set
|
6
|
+
attr :target
|
7
|
+
attr :index
|
8
|
+
|
9
|
+
def initialize
|
10
|
+
@sets = set_var_array(3, [], 0..20)
|
11
|
+
@set = set_var([], 0...3)
|
12
|
+
@target = set_var([], 0..20)
|
13
|
+
@index = int_var(0...3)
|
14
|
+
branch_on wrap_enum([@index])
|
15
|
+
branch_on @sets
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
describe Gecode::SelectedSet::Select, ' (union)' do
|
20
|
+
include GecodeR::Specs::SetHelper
|
21
|
+
|
22
|
+
before do
|
23
|
+
@model = SelectionSampleProblem.new
|
24
|
+
@sets = @model.sets
|
25
|
+
@set = @model.set
|
26
|
+
@model.branch_on @set
|
27
|
+
|
28
|
+
@property_types = [:selected_set]
|
29
|
+
@select_property = lambda do |selected_set|
|
30
|
+
selected_set.union
|
31
|
+
end
|
32
|
+
@selected_property = @sets[@set].union
|
33
|
+
@constraint_class = Gecode::BlockConstraint
|
34
|
+
end
|
35
|
+
|
36
|
+
it 'should constrain the selected union of an enum of sets' do
|
37
|
+
@sets[@set].union.must_be.subset_of([5,7,9])
|
38
|
+
@sets[@set].union.must_be.superset_of([5])
|
39
|
+
@model.solve!
|
40
|
+
union = @set.value.inject([]) do |union, i|
|
41
|
+
union += @sets[i].value.to_a
|
42
|
+
end.uniq
|
43
|
+
union.should include(5)
|
44
|
+
(union - [5,7,9]).should be_empty
|
45
|
+
end
|
46
|
+
|
47
|
+
it 'should translate into a select union constraint' do
|
48
|
+
Gecode::Raw.should_receive(:selectUnion)
|
49
|
+
@sets[@set].union.must_be.subset_of([5,7,9])
|
50
|
+
@model.solve!
|
51
|
+
end
|
52
|
+
|
53
|
+
it_should_behave_like(
|
54
|
+
'property that produces set operand by short circuiting equality')
|
55
|
+
end
|
56
|
+
|
57
|
+
describe Gecode::SetEnum::Select, ' (intersection)' do
|
58
|
+
include GecodeR::Specs::SetHelper
|
59
|
+
|
60
|
+
before do
|
61
|
+
@model = SelectionSampleProblem.new
|
62
|
+
@sets = @model.sets
|
63
|
+
@set = @model.set
|
64
|
+
@model.branch_on @set
|
65
|
+
|
66
|
+
@property_types = [:selected_set]
|
67
|
+
@select_property = lambda do |selected_set|
|
68
|
+
selected_set.intersection
|
69
|
+
end
|
70
|
+
@selected_property = @sets[@set].intersection
|
71
|
+
@constraint_class = Gecode::BlockConstraint
|
72
|
+
end
|
73
|
+
|
74
|
+
it 'should constrain the selected intersection of an enum of sets' do
|
75
|
+
@sets[@set].intersection.must_be.subset_of([5,7,9])
|
76
|
+
@sets[@set].intersection.must_be.superset_of([5])
|
77
|
+
@model.solve!
|
78
|
+
intersection = @set.value.inject(nil) do |intersection, i|
|
79
|
+
elements = @sets[i].value.to_a
|
80
|
+
next elements if intersection.nil?
|
81
|
+
intersection &= elements
|
82
|
+
end.uniq
|
83
|
+
intersection.should include(5)
|
84
|
+
(intersection - [5,7,9]).should be_empty
|
85
|
+
end
|
86
|
+
|
87
|
+
it 'should translate into a select intersection constraint' do
|
88
|
+
Gecode::Raw.should_receive(:selectInter)
|
89
|
+
@sets[@set].intersection.must_be.subset_of([5,7,9])
|
90
|
+
@model.solve!
|
91
|
+
end
|
92
|
+
|
93
|
+
it_should_behave_like(
|
94
|
+
'property that produces set operand by short circuiting equality')
|
95
|
+
end
|
96
|
+
|
97
|
+
describe Gecode::SelectedSet::Select, ' (intersection with universe)' do
|
98
|
+
include GecodeR::Specs::SetHelper
|
99
|
+
|
100
|
+
before do
|
101
|
+
@model = SelectionSampleProblem.new
|
102
|
+
@sets = @model.sets
|
103
|
+
@set = @model.set
|
104
|
+
@model.branch_on @set
|
105
|
+
@universe = [1,2]
|
106
|
+
|
107
|
+
@property_types = [:selected_set]
|
108
|
+
@select_property = lambda do |selected_set|
|
109
|
+
selected_set.intersection(:with => @universe)
|
110
|
+
end
|
111
|
+
@selected_property = @sets[@set].intersection(:with => @universe)
|
112
|
+
@constraint_class = Gecode::BlockConstraint
|
113
|
+
end
|
114
|
+
|
115
|
+
it 'should constrain the selected intersection of an enum of sets in a universe' do
|
116
|
+
@sets[@set].intersection(:with => @universe).must_be.subset_of([2])
|
117
|
+
@model.solve!
|
118
|
+
intersection = @set.value.inject(@universe) do |intersection, i|
|
119
|
+
intersection &= @sets[i].value.to_a
|
120
|
+
end.uniq
|
121
|
+
intersection.should include(2)
|
122
|
+
(intersection - [1,2]).should be_empty
|
123
|
+
end
|
124
|
+
|
125
|
+
it 'should allow the universe to be specified as a range' do
|
126
|
+
@sets[@set].intersection(:with => 1..2).must_be.subset_of([2])
|
127
|
+
@model.solve!
|
128
|
+
intersection = @set.value.inject(@universe) do |intersection, i|
|
129
|
+
intersection &= @sets[i].value.to_a
|
130
|
+
end.uniq
|
131
|
+
intersection.should include(2)
|
132
|
+
(intersection - [1,2]).should be_empty
|
133
|
+
end
|
134
|
+
|
135
|
+
it 'should translate into a select intersection constraint' do
|
136
|
+
Gecode::Raw.should_receive(:selectInterIn)
|
137
|
+
@sets[@set].intersection(:with => 1..2).must_be.subset_of([5,7,9])
|
138
|
+
@model.solve!
|
139
|
+
end
|
140
|
+
|
141
|
+
it 'should raise error if unknown options are specified' do
|
142
|
+
lambda do
|
143
|
+
@sets[@set].intersection(:does_not_exist => nil).must_be.subset_of([2])
|
144
|
+
end.should raise_error(ArgumentError)
|
145
|
+
end
|
146
|
+
|
147
|
+
it 'should raise error if the universe is of the wrong type' do
|
148
|
+
lambda do
|
149
|
+
@sets[@set].intersection(:with => 'foo').must_be.subset_of([2])
|
150
|
+
end.should raise_error(TypeError)
|
151
|
+
end
|
152
|
+
|
153
|
+
it_should_behave_like(
|
154
|
+
'property that produces set operand by short circuiting equality')
|
155
|
+
end
|
156
|
+
|
157
|
+
|
@@ -0,0 +1,58 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../constraint_helper'
|
2
|
+
|
3
|
+
describe Gecode::Set::Cardinality, ' (constraint)' do
|
4
|
+
before do
|
5
|
+
@model = Gecode::Model.new
|
6
|
+
@set = @model.set_var([], 0..10)
|
7
|
+
@model.branch_on @model.wrap_enum([@set])
|
8
|
+
@range = 1..2
|
9
|
+
@three_dot_range = 1...2
|
10
|
+
|
11
|
+
@invoke = lambda do |rhs|
|
12
|
+
@set.size.must_be.in(rhs)
|
13
|
+
@model.solve!
|
14
|
+
end
|
15
|
+
@expect = lambda do |rhs|
|
16
|
+
@model.allow_space_access do
|
17
|
+
Gecode::Raw.should_receive(:cardinality).once.with(
|
18
|
+
an_instance_of(Gecode::Raw::Space),
|
19
|
+
an_instance_of(Gecode::Raw::SetVar), rhs.first, rhs.last)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'should translate cardinality constraints with ranges' do
|
25
|
+
@expect.call(@range)
|
26
|
+
@invoke.call(@range)
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'should translate cardinality constraints with three dot range domains' do
|
30
|
+
@expect.call(@three_dot_range)
|
31
|
+
@invoke.call(@three_dot_range)
|
32
|
+
end
|
33
|
+
|
34
|
+
it 'should constrain the cardinality of a set' do
|
35
|
+
@set.size.must_be.in @range
|
36
|
+
@model.solve!
|
37
|
+
@range.should include(@set.value.size)
|
38
|
+
end
|
39
|
+
|
40
|
+
it 'should raise error if the right hand side is not a range' do
|
41
|
+
lambda{ @set.size.must_be.in 'hello' }.should raise_error(TypeError)
|
42
|
+
end
|
43
|
+
|
44
|
+
it 'should not shadow the integer variable domain constrain' do
|
45
|
+
Gecode::Raw.should_receive(:dom).with(
|
46
|
+
an_instance_of(Gecode::Raw::Space),
|
47
|
+
an_instance_of(Gecode::Raw::IntVar), 0, 11, Gecode::Raw::ICL_DEF,
|
48
|
+
Gecode::Raw::PK_DEF)
|
49
|
+
Gecode::Raw.should_receive(:dom).with(
|
50
|
+
an_instance_of(Gecode::Raw::Space),
|
51
|
+
an_instance_of(Gecode::Raw::IntVar), an_instance_of(Gecode::Raw::IntSet),
|
52
|
+
an_instance_of(Gecode::Raw::BoolVar), Gecode::Raw::ICL_DEF,
|
53
|
+
Gecode::Raw::PK_DEF)
|
54
|
+
@set.size.must_not_be.in [1,3]
|
55
|
+
@model.solve!
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
@@ -0,0 +1,46 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../property_helper'
|
2
|
+
|
3
|
+
describe Gecode::Set::Cardinality, ' (property)' do
|
4
|
+
before do
|
5
|
+
@model = Gecode::Model.new
|
6
|
+
@set = @model.set_var([], 0..10)
|
7
|
+
@var = @model.int_var(0..11)
|
8
|
+
@model.branch_on @set
|
9
|
+
@model.branch_on @var
|
10
|
+
|
11
|
+
@property_types = [:set]
|
12
|
+
@select_property = lambda do |set|
|
13
|
+
set.size
|
14
|
+
end
|
15
|
+
@selected_property = @set.size
|
16
|
+
@constraint_class = Gecode::BlockConstraint
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'should constrain the cardinality of a set' do
|
20
|
+
@set.size.must == @var
|
21
|
+
@model.solve!
|
22
|
+
@set.value.size.should == @var.value
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'should constrain the cardinality of a set (2)' do
|
26
|
+
@set.size.must == 2
|
27
|
+
@model.solve!.should_not be_nil
|
28
|
+
@set.value.size.should == 2
|
29
|
+
end
|
30
|
+
|
31
|
+
it 'should constrain the cardinality of a set (3)' do
|
32
|
+
@set.size.must == @var
|
33
|
+
@var.must == 2
|
34
|
+
@model.solve!
|
35
|
+
@set.value.size.should == 2
|
36
|
+
end
|
37
|
+
|
38
|
+
it 'should translate into a cardinality constraint' do
|
39
|
+
Gecode::Raw.should_receive(:cardinality)
|
40
|
+
@set.size.must == @var
|
41
|
+
@model.solve!
|
42
|
+
end
|
43
|
+
|
44
|
+
it_should_behave_like(
|
45
|
+
'property that produces int operand by short circuiting equality')
|
46
|
+
end
|
@@ -0,0 +1,77 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../constraint_helper'
|
2
|
+
|
3
|
+
class SetChannelSampleProblem < Gecode::Model
|
4
|
+
attr :bool_enum
|
5
|
+
attr :set
|
6
|
+
|
7
|
+
def initialize
|
8
|
+
@bool_enum = bool_var_array(4)
|
9
|
+
@set = set_var([], 0..3)
|
10
|
+
|
11
|
+
branch_on @bool_enum
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
describe Gecode::Set::Channel, ' (set variable as lhs with bool enum)' do
|
16
|
+
before do
|
17
|
+
@model = SetChannelSampleProblem.new
|
18
|
+
@bools = @model.bool_enum
|
19
|
+
@set = @model.set
|
20
|
+
|
21
|
+
@types = [:set, :bool_enum]
|
22
|
+
@invoke = lambda do |receiver, bool_enum, hash|
|
23
|
+
receiver.channel(bool_enum, hash)
|
24
|
+
@model.solve!
|
25
|
+
end
|
26
|
+
@expect = lambda do |var1, var2, opts, reif_var|
|
27
|
+
Gecode::Raw.should_receive(:channel).once.with(
|
28
|
+
an_instance_of(Gecode::Raw::Space),
|
29
|
+
var1, var2)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
it 'should channel the bool enum with the set variable' do
|
34
|
+
@set.must_be.superset_of [0, 2]
|
35
|
+
@set.must.channel @bools
|
36
|
+
@model.solve!.should_not be_nil
|
37
|
+
set_values = @set.value
|
38
|
+
@bools.values.each_with_index do |bool, index|
|
39
|
+
bool.should == set_values.include?(index)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
it_should_behave_like 'non-reifiable set constraint'
|
44
|
+
it_should_behave_like 'non-negatable constraint'
|
45
|
+
end
|
46
|
+
|
47
|
+
describe Gecode::Set::Channel, ' (bool enum as lhs with set variable)' do
|
48
|
+
before do
|
49
|
+
@model = SetChannelSampleProblem.new
|
50
|
+
@bools = @model.bool_enum
|
51
|
+
@set = @model.set
|
52
|
+
|
53
|
+
@types = [:bool_enum, :set]
|
54
|
+
@invoke = lambda do |receiver, set, hash|
|
55
|
+
receiver.channel(set, hash)
|
56
|
+
@model.solve!
|
57
|
+
end
|
58
|
+
@expect = lambda do |var1, var2, opts, reif_var|
|
59
|
+
Gecode::Raw.should_receive(:channel).once.with(
|
60
|
+
an_instance_of(Gecode::Raw::Space),
|
61
|
+
var1, var2)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
it 'should channel the bool enum with the set variable' do
|
66
|
+
@set.must_be.superset_of [0, 2]
|
67
|
+
@bools.must.channel @set
|
68
|
+
@model.solve!.should_not be_nil
|
69
|
+
set_values = @set.value
|
70
|
+
@bools.values.each_with_index do |bool, index|
|
71
|
+
bool.should == set_values.include?(index)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
it_should_behave_like 'non-reifiable set constraint'
|
76
|
+
it_should_behave_like 'non-negatable constraint'
|
77
|
+
end
|
@@ -0,0 +1,176 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../property_helper'
|
2
|
+
|
3
|
+
describe Gecode::Set::Connection, ' (min)' do
|
4
|
+
before do
|
5
|
+
@model = Gecode::Model.new
|
6
|
+
@set = @model.set_var([], 0..9)
|
7
|
+
@var = @model.int_var(0..10)
|
8
|
+
@model.branch_on @model.wrap_enum([@set])
|
9
|
+
|
10
|
+
@property_types = [:set]
|
11
|
+
@select_property = lambda do |set|
|
12
|
+
set.min
|
13
|
+
end
|
14
|
+
@selected_property = @set.min
|
15
|
+
@constraint_class = Gecode::BlockConstraint
|
16
|
+
end
|
17
|
+
|
18
|
+
it 'should constrain the min of a set' do
|
19
|
+
@set.min.must == 3
|
20
|
+
@model.solve!
|
21
|
+
@set.lower_bound.min.should == 3
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'should translate into a min constraint' do
|
25
|
+
Gecode::Raw.should_receive(:min)
|
26
|
+
@set.min.must == 5
|
27
|
+
@model.solve!
|
28
|
+
end
|
29
|
+
|
30
|
+
it_should_behave_like(
|
31
|
+
'property that produces int operand by short circuiting equality')
|
32
|
+
end
|
33
|
+
|
34
|
+
describe Gecode::Set::Connection, ' (max)' do
|
35
|
+
before do
|
36
|
+
@model = Gecode::Model.new
|
37
|
+
@set = @model.set_var([], 0..9)
|
38
|
+
@var = @model.int_var(0..10)
|
39
|
+
@model.branch_on @model.wrap_enum([@set])
|
40
|
+
|
41
|
+
@property_types = [:set]
|
42
|
+
@select_property = lambda do |set|
|
43
|
+
set.max
|
44
|
+
end
|
45
|
+
@selected_property = @set.max
|
46
|
+
@constraint_class = Gecode::BlockConstraint
|
47
|
+
end
|
48
|
+
|
49
|
+
it 'should constrain the max of a set' do
|
50
|
+
@set.max.must == 3
|
51
|
+
@model.solve!
|
52
|
+
@set.lower_bound.max.should == 3
|
53
|
+
end
|
54
|
+
|
55
|
+
it 'should translate into a max constraint' do
|
56
|
+
Gecode::Raw.should_receive(:max)
|
57
|
+
@set.max.must == 5
|
58
|
+
@model.solve!
|
59
|
+
end
|
60
|
+
|
61
|
+
it_should_behave_like(
|
62
|
+
'property that produces int operand by short circuiting equality')
|
63
|
+
end
|
64
|
+
|
65
|
+
describe Gecode::Set::Connection, ' (sum)' do
|
66
|
+
before do
|
67
|
+
@model = Gecode::Model.new
|
68
|
+
@set = @model.set_var([], 0..9)
|
69
|
+
@target = @var = @model.int_var(0..20)
|
70
|
+
@model.branch_on @model.wrap_enum([@set])
|
71
|
+
|
72
|
+
@property_types = [:set]
|
73
|
+
@select_property = lambda do |set|
|
74
|
+
set.sum
|
75
|
+
end
|
76
|
+
@selected_property = @set.sum
|
77
|
+
@constraint_class = Gecode::BlockConstraint
|
78
|
+
end
|
79
|
+
|
80
|
+
it 'should constrain the sum of a set' do
|
81
|
+
@set.sum.must == 7
|
82
|
+
@model.solve!.should_not be_nil
|
83
|
+
@set.value.inject(0){ |x, y| x + y }.should == 7
|
84
|
+
end
|
85
|
+
|
86
|
+
it 'should translate into a weights constraint' do
|
87
|
+
Gecode::Raw.should_receive(:weights)
|
88
|
+
@set.sum.must == 5
|
89
|
+
@model.solve!
|
90
|
+
end
|
91
|
+
|
92
|
+
it 'should raise error if unsupported options is given' do
|
93
|
+
lambda do
|
94
|
+
@set.sum(:does_not_exist => :foo).must == @var
|
95
|
+
end.should raise_error(ArgumentError)
|
96
|
+
end
|
97
|
+
|
98
|
+
it 'should raise error if multiple options are given' do
|
99
|
+
lambda do
|
100
|
+
@set.sum(:weights => {}, :substitutions => {}).must == @var
|
101
|
+
end.should raise_error(ArgumentError)
|
102
|
+
end
|
103
|
+
|
104
|
+
it_should_behave_like(
|
105
|
+
'property that produces int operand by short circuiting equality')
|
106
|
+
end
|
107
|
+
|
108
|
+
describe Gecode::Set::Connection, ' (sum with weights)' do
|
109
|
+
before do
|
110
|
+
@model = Gecode::Model.new
|
111
|
+
@set = @model.set_var([], 0..9)
|
112
|
+
@target = @var = @model.int_var(-20..20)
|
113
|
+
@model.branch_on @model.wrap_enum([@set])
|
114
|
+
@weights = Hash[*(0..9).zip((-9..-0).to_a.reverse).flatten]
|
115
|
+
|
116
|
+
@property_types = [:set]
|
117
|
+
@select_property = lambda do |set|
|
118
|
+
set.sum(:weights => @weights)
|
119
|
+
end
|
120
|
+
@selected_property = @set.sum(:weights => @weights)
|
121
|
+
@constraint_class = Gecode::BlockConstraint
|
122
|
+
end
|
123
|
+
|
124
|
+
it 'should constrain the sum of a set' do
|
125
|
+
@set.sum(:weights => @weights).must_be.in(-10..-1)
|
126
|
+
@model.solve!.should_not be_nil
|
127
|
+
weighted_sum = @set.value.inject(0){ |sum, x| sum - x**2 }
|
128
|
+
weighted_sum.should >= -10
|
129
|
+
weighted_sum.should <= -1
|
130
|
+
end
|
131
|
+
|
132
|
+
it 'should remove any elements not in the weight hash' do
|
133
|
+
@set.must_be.superset_of 0
|
134
|
+
@set.sum(:weights => {}).must_be == 0
|
135
|
+
lambda do
|
136
|
+
@model.solve!
|
137
|
+
end.should raise_error(Gecode::NoSolutionError)
|
138
|
+
end
|
139
|
+
|
140
|
+
it_should_behave_like(
|
141
|
+
'property that produces int operand by short circuiting equality')
|
142
|
+
end
|
143
|
+
|
144
|
+
describe Gecode::Set::Connection, ' (sum with substitutions)' do
|
145
|
+
before do
|
146
|
+
@model = Gecode::Model.new
|
147
|
+
@set = @model.set_var([], 0..9)
|
148
|
+
@target = @var = @model.int_var(-20..20)
|
149
|
+
@model.branch_on @model.wrap_enum([@set])
|
150
|
+
@subs = Hash[*(0..9).zip((-9..-0).to_a.reverse).flatten]
|
151
|
+
|
152
|
+
@property_types = [:set]
|
153
|
+
@select_property = lambda do |set|
|
154
|
+
set.sum(:substitutions => @subs)
|
155
|
+
end
|
156
|
+
@selected_property = @set.sum(:substitutions => @subs)
|
157
|
+
@constraint_class = Gecode::BlockConstraint
|
158
|
+
end
|
159
|
+
|
160
|
+
it 'should constrain the sum of a set' do
|
161
|
+
@set.sum(:substitutions => @subs).must_be.in(-10..-1)
|
162
|
+
@model.solve!.should_not be_nil
|
163
|
+
substituted_sum = @set.value.inject{ |sum, x| sum + @subs[x] }
|
164
|
+
substituted_sum.should >= -10
|
165
|
+
substituted_sum.should <= -1
|
166
|
+
end
|
167
|
+
|
168
|
+
it 'should not be allowed together with :weights option' do
|
169
|
+
lambda do
|
170
|
+
@set.sum(:substitutions => @subs, :weights => [1]*20).must_be.in(-10..-1)
|
171
|
+
end.should raise_error(ArgumentError)
|
172
|
+
end
|
173
|
+
|
174
|
+
it_should_behave_like(
|
175
|
+
'property that produces int operand by short circuiting equality')
|
176
|
+
end
|