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
@@ -1,160 +0,0 @@
|
|
1
|
-
require File.dirname(__FILE__) + '/../spec_helper'
|
2
|
-
require File.dirname(__FILE__) + '/constraint_helper'
|
3
|
-
|
4
|
-
class BoolEnumSampleProblem < Gecode::Model
|
5
|
-
attr :bools
|
6
|
-
attr :b1
|
7
|
-
attr :b2
|
8
|
-
|
9
|
-
def initialize
|
10
|
-
@bools = bool_var_array(4)
|
11
|
-
@b1 = bool_var
|
12
|
-
@b2 = bool_var
|
13
|
-
branch_on @bools
|
14
|
-
branch_on wrap_enum([@b1, @b2])
|
15
|
-
end
|
16
|
-
end
|
17
|
-
|
18
|
-
# Expects @stub, which contains the started constraint and @compute_result
|
19
|
-
# which computes whether the left hand side is true or not.
|
20
|
-
describe 'bool enum relation constraint', :shared => true do
|
21
|
-
it 'should handle being constrained to be true' do
|
22
|
-
@stub.must_be.true
|
23
|
-
@model.solve!
|
24
|
-
@compute_result.call.should be_true
|
25
|
-
end
|
26
|
-
|
27
|
-
it 'should handle being constrained to be negated true' do
|
28
|
-
@stub.must_not_be.true
|
29
|
-
@model.solve!
|
30
|
-
@compute_result.call.should_not be_true
|
31
|
-
end
|
32
|
-
|
33
|
-
it 'should handle being constrained to be false' do
|
34
|
-
@stub.must_be.false
|
35
|
-
@model.solve!
|
36
|
-
@compute_result.call.should_not be_true
|
37
|
-
end
|
38
|
-
|
39
|
-
it 'should handle being constrained to be negated false' do
|
40
|
-
@stub.must_not_be.false
|
41
|
-
@model.solve!
|
42
|
-
@compute_result.call.should be_true
|
43
|
-
end
|
44
|
-
|
45
|
-
it 'should handle being constrained to be equal to a variable' do
|
46
|
-
@stub.must_be == @b1
|
47
|
-
@model.solve!
|
48
|
-
@compute_result.call.should == @b1.value
|
49
|
-
end
|
50
|
-
|
51
|
-
it 'should handle being constrained to not be equal to a variable' do
|
52
|
-
@stub.must_not_be == @b1
|
53
|
-
@model.solve!
|
54
|
-
@compute_result.call.should_not == @b1.value
|
55
|
-
end
|
56
|
-
|
57
|
-
it 'should handle being constrained to be equal to be a nested expression' do
|
58
|
-
@stub.must_be == (@b1 | @b2) & @b1
|
59
|
-
@model.solve!
|
60
|
-
@compute_result.call.should == (@b1.value | @b2.value) & @b1.value
|
61
|
-
end
|
62
|
-
|
63
|
-
it 'should handle being constrained to not be equal to be a nested expression' do
|
64
|
-
@stub.must_not_be == (@b1 | @b2) & @b1
|
65
|
-
@model.solve!
|
66
|
-
@compute_result.call.should_not == (@b1.value | @b2.value) & @b1.value
|
67
|
-
end
|
68
|
-
end
|
69
|
-
|
70
|
-
describe Gecode::Constraints::BoolEnum::Relation, ' (conjunction)' do
|
71
|
-
before do
|
72
|
-
@model = BoolEnumSampleProblem.new
|
73
|
-
@bools = @model.bools
|
74
|
-
@b1 = @model.b1
|
75
|
-
@b2 = @model.b2
|
76
|
-
|
77
|
-
# For constraint option spec.
|
78
|
-
@invoke_options = lambda do |hash|
|
79
|
-
@bools.conjunction.must.equal(@b1, hash)
|
80
|
-
@model.solve!
|
81
|
-
end
|
82
|
-
@expect_options = option_expectation do |strength, kind, reif_var|
|
83
|
-
@model.allow_space_access do
|
84
|
-
if reif_var.nil?
|
85
|
-
Gecode::Raw.should_receive(:rel).once.with(
|
86
|
-
an_instance_of(Gecode::Raw::Space),
|
87
|
-
Gecode::Raw::BOT_AND,
|
88
|
-
an_instance_of(Gecode::Raw::BoolVarArray),
|
89
|
-
an_instance_of(Gecode::Raw::BoolVar),
|
90
|
-
strength, kind)
|
91
|
-
else
|
92
|
-
Gecode::Raw.should_receive(:rel).once.with(
|
93
|
-
an_instance_of(Gecode::Raw::Space),
|
94
|
-
an_instance_of(Gecode::Raw::BoolVar),
|
95
|
-
anything,
|
96
|
-
an_instance_of(Gecode::Raw::BoolVar),
|
97
|
-
anything, anything)
|
98
|
-
Gecode::Raw.should_receive(:rel).once.with(
|
99
|
-
an_instance_of(Gecode::Raw::Space),
|
100
|
-
Gecode::Raw::BOT_AND,
|
101
|
-
an_instance_of(Gecode::Raw::BoolVarArray),
|
102
|
-
reif_var, strength, kind)
|
103
|
-
end
|
104
|
-
end
|
105
|
-
end
|
106
|
-
|
107
|
-
# For bool enum spec.
|
108
|
-
@stub = @bools.conjunction
|
109
|
-
@compute_result = lambda{ @bools.all?{ |b| b.value } }
|
110
|
-
end
|
111
|
-
|
112
|
-
it_should_behave_like 'bool enum relation constraint'
|
113
|
-
it_should_behave_like 'reifiable constraint'
|
114
|
-
end
|
115
|
-
|
116
|
-
describe Gecode::Constraints::BoolEnum::Relation, ' (disjunction)' do
|
117
|
-
before do
|
118
|
-
@model = BoolEnumSampleProblem.new
|
119
|
-
@bools = @model.bools
|
120
|
-
@b1 = @model.b1
|
121
|
-
@b2 = @model.b2
|
122
|
-
|
123
|
-
# For constraint option spec.
|
124
|
-
@invoke_options = lambda do |hash|
|
125
|
-
@bools.disjunction.must.equal(@b1, hash)
|
126
|
-
@model.solve!
|
127
|
-
end
|
128
|
-
@expect_options = option_expectation do |strength, kind, reif_var|
|
129
|
-
@model.allow_space_access do
|
130
|
-
if reif_var.nil?
|
131
|
-
Gecode::Raw.should_receive(:rel).once.with(
|
132
|
-
an_instance_of(Gecode::Raw::Space),
|
133
|
-
Gecode::Raw::BOT_OR,
|
134
|
-
an_instance_of(Gecode::Raw::BoolVarArray),
|
135
|
-
an_instance_of(Gecode::Raw::BoolVar),
|
136
|
-
strength, kind)
|
137
|
-
else
|
138
|
-
Gecode::Raw.should_receive(:rel).once.with(
|
139
|
-
an_instance_of(Gecode::Raw::Space),
|
140
|
-
an_instance_of(Gecode::Raw::BoolVar),
|
141
|
-
anything,
|
142
|
-
an_instance_of(Gecode::Raw::BoolVar),
|
143
|
-
anything, anything)
|
144
|
-
Gecode::Raw.should_receive(:rel).once.with(
|
145
|
-
an_instance_of(Gecode::Raw::Space),
|
146
|
-
Gecode::Raw::BOT_OR,
|
147
|
-
an_instance_of(Gecode::Raw::BoolVarArray),
|
148
|
-
reif_var, strength, kind)
|
149
|
-
end
|
150
|
-
end
|
151
|
-
end
|
152
|
-
|
153
|
-
# For bool enum spec.
|
154
|
-
@stub = @bools.disjunction
|
155
|
-
@compute_result = lambda{ @bools.any?{ |b| b.value } }
|
156
|
-
end
|
157
|
-
|
158
|
-
it_should_behave_like 'bool enum relation constraint'
|
159
|
-
it_should_behave_like 'reifiable constraint'
|
160
|
-
end
|
@@ -1,157 +0,0 @@
|
|
1
|
-
require File.dirname(__FILE__) + '/../spec_helper'
|
2
|
-
require File.dirname(__FILE__) + '/constraint_helper'
|
3
|
-
|
4
|
-
describe Gecode::Constraints::Set::Cardinality, ' (range)' do
|
5
|
-
before do
|
6
|
-
@model = Gecode::Model.new
|
7
|
-
@set = @model.set_var([], 0..10)
|
8
|
-
@model.branch_on @model.wrap_enum([@set])
|
9
|
-
@range = 1..2
|
10
|
-
@three_dot_range = 1...2
|
11
|
-
|
12
|
-
@invoke_options = lambda do |hash|
|
13
|
-
@set.size.must_be.in(@range, hash)
|
14
|
-
end
|
15
|
-
|
16
|
-
@invoke = lambda do |rhs|
|
17
|
-
@set.size.must_be.in(rhs)
|
18
|
-
@model.solve!
|
19
|
-
end
|
20
|
-
@expect = lambda do |rhs|
|
21
|
-
@model.allow_space_access do
|
22
|
-
Gecode::Raw.should_receive(:cardinality).once.with(
|
23
|
-
an_instance_of(Gecode::Raw::Space),
|
24
|
-
an_instance_of(Gecode::Raw::SetVar), rhs.first, rhs.last)
|
25
|
-
end
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
it 'should translate cardinality constraints with ranges' do
|
30
|
-
@expect.call(@range)
|
31
|
-
@invoke.call(@range)
|
32
|
-
end
|
33
|
-
|
34
|
-
it 'should translate cardinality constraints with three dot range domains' do
|
35
|
-
@expect.call(@three_dot_range)
|
36
|
-
@invoke.call(@three_dot_range)
|
37
|
-
end
|
38
|
-
|
39
|
-
it 'should constrain the cardinality of a set' do
|
40
|
-
@set.size.must_be.in @range
|
41
|
-
@model.solve!
|
42
|
-
@range.should include(@set.value.size)
|
43
|
-
end
|
44
|
-
|
45
|
-
it 'should raise error if the right hand side is not a range' do
|
46
|
-
lambda{ @set.size.must_be.in 'hello' }.should raise_error(TypeError)
|
47
|
-
end
|
48
|
-
|
49
|
-
it 'should not shadow the integer variable domain constrain' do
|
50
|
-
Gecode::Raw.should_receive(:dom).with(
|
51
|
-
an_instance_of(Gecode::Raw::Space),
|
52
|
-
an_instance_of(Gecode::Raw::IntVar), 0, 11, Gecode::Raw::ICL_DEF,
|
53
|
-
Gecode::Raw::PK_DEF)
|
54
|
-
Gecode::Raw.should_receive(:dom).with(
|
55
|
-
an_instance_of(Gecode::Raw::Space),
|
56
|
-
an_instance_of(Gecode::Raw::IntVar), an_instance_of(Gecode::Raw::IntSet),
|
57
|
-
an_instance_of(Gecode::Raw::BoolVar), Gecode::Raw::ICL_DEF,
|
58
|
-
Gecode::Raw::PK_DEF)
|
59
|
-
@set.size.must_not_be.in [1,3]
|
60
|
-
@model.solve!
|
61
|
-
end
|
62
|
-
|
63
|
-
it_should_behave_like 'non-reifiable set constraint'
|
64
|
-
end
|
65
|
-
|
66
|
-
describe Gecode::Constraints::Set::Cardinality, ' (composite)' do
|
67
|
-
before do
|
68
|
-
@model = Gecode::Model.new
|
69
|
-
@set = @model.set_var([], 0..10)
|
70
|
-
@target = @var = @model.int_var(0..11)
|
71
|
-
@model.branch_on @model.wrap_enum([@set])
|
72
|
-
@model.branch_on @model.wrap_enum([@var])
|
73
|
-
|
74
|
-
@invoke = lambda do |rhs|
|
75
|
-
@set.size.must == rhs
|
76
|
-
@model.solve!
|
77
|
-
end
|
78
|
-
@expect = lambda do |relation, rhs, strength, kind, reif_var, negated|
|
79
|
-
@model.allow_space_access do
|
80
|
-
rhs = an_instance_of(Gecode::Raw::IntVar) if rhs.respond_to? :bind
|
81
|
-
if reif_var.nil?
|
82
|
-
if !negated and relation == Gecode::Raw::IRT_EQ and
|
83
|
-
!rhs.kind_of? Fixnum
|
84
|
-
Gecode::Raw.should_receive(:cardinality).once.with(
|
85
|
-
an_instance_of(Gecode::Raw::Space),
|
86
|
-
an_instance_of(Gecode::Raw::SetVar), rhs)
|
87
|
-
Gecode::Raw.should_receive(:rel).exactly(0).times
|
88
|
-
else
|
89
|
-
Gecode::Raw.should_receive(:cardinality).once.with(
|
90
|
-
an_instance_of(Gecode::Raw::Space),
|
91
|
-
an_instance_of(Gecode::Raw::SetVar),
|
92
|
-
an_instance_of(Gecode::Raw::IntVar))
|
93
|
-
Gecode::Raw.should_receive(:rel).once.with(
|
94
|
-
an_instance_of(Gecode::Raw::Space),
|
95
|
-
an_instance_of(Gecode::Raw::IntVar), relation, rhs,
|
96
|
-
strength, kind)
|
97
|
-
end
|
98
|
-
else
|
99
|
-
Gecode::Raw.should_receive(:cardinality).once.with(
|
100
|
-
an_instance_of(Gecode::Raw::Space),
|
101
|
-
an_instance_of(Gecode::Raw::SetVar),
|
102
|
-
an_instance_of(Gecode::Raw::IntVar))
|
103
|
-
Gecode::Raw.should_receive(:rel).once.with(
|
104
|
-
an_instance_of(Gecode::Raw::Space),
|
105
|
-
an_instance_of(Gecode::Raw::IntVar), relation, rhs,
|
106
|
-
an_instance_of(Gecode::Raw::BoolVar),
|
107
|
-
strength, kind)
|
108
|
-
end
|
109
|
-
end
|
110
|
-
end
|
111
|
-
|
112
|
-
# For composite spec.
|
113
|
-
@invoke_relation = lambda do |relation, target, negated|
|
114
|
-
if negated
|
115
|
-
@set.size.must_not.send(relation, target)
|
116
|
-
else
|
117
|
-
@set.size.must.send(relation, target)
|
118
|
-
end
|
119
|
-
@model.solve!
|
120
|
-
end
|
121
|
-
@expect_relation = lambda do |relation, target, negated|
|
122
|
-
@expect.call(relation, target, Gecode::Raw::ICL_DEF, Gecode::Raw::PK_DEF,
|
123
|
-
nil, negated)
|
124
|
-
end
|
125
|
-
|
126
|
-
# For options spec.
|
127
|
-
@invoke_options = lambda do |hash|
|
128
|
-
@set.size.must_be.less_than_or_equal_to(17, hash)
|
129
|
-
@model.solve!
|
130
|
-
end
|
131
|
-
@expect_options = option_expectation do |strength, kind, reif_var|
|
132
|
-
@expect.call(Gecode::Raw::IRT_LQ, 17, strength, kind, reif_var, false)
|
133
|
-
end
|
134
|
-
end
|
135
|
-
|
136
|
-
it 'should constrain the cardinality of a set' do
|
137
|
-
@set.size.must == @var
|
138
|
-
@model.solve!
|
139
|
-
@set.value.size.should == @var.value
|
140
|
-
end
|
141
|
-
|
142
|
-
it 'should constrain the cardinality of a set (2)' do
|
143
|
-
@set.size.must == 2
|
144
|
-
@model.solve!.should_not be_nil
|
145
|
-
@set.value.size.should == 2
|
146
|
-
end
|
147
|
-
|
148
|
-
it 'should constrain the cardinality of a set (3)' do
|
149
|
-
@set.size.must == @var
|
150
|
-
@var.must == 2
|
151
|
-
@model.solve!
|
152
|
-
@set.value.size.should == 2
|
153
|
-
end
|
154
|
-
|
155
|
-
it_should_behave_like 'reifiable constraint'
|
156
|
-
it_should_behave_like 'composite constraint'
|
157
|
-
end
|
@@ -1,454 +0,0 @@
|
|
1
|
-
require File.dirname(__FILE__) + '/../spec_helper'
|
2
|
-
require File.dirname(__FILE__) + '/constraint_helper'
|
3
|
-
|
4
|
-
class ChannelSampleProblem < Gecode::Model
|
5
|
-
attr :elements
|
6
|
-
attr :positions
|
7
|
-
attr :sets
|
8
|
-
|
9
|
-
def initialize
|
10
|
-
@elements = int_var_array(4, 0..3)
|
11
|
-
@elements.must_be.distinct
|
12
|
-
@positions = int_var_array(4, 0..3)
|
13
|
-
@positions.must_be.distinct
|
14
|
-
@sets = set_var_array(4, [], 0..3)
|
15
|
-
branch_on @positions
|
16
|
-
end
|
17
|
-
end
|
18
|
-
|
19
|
-
class BoolChannelSampleProblem < Gecode::Model
|
20
|
-
attr :bool_enum
|
21
|
-
attr :bool
|
22
|
-
attr :int
|
23
|
-
|
24
|
-
def initialize
|
25
|
-
@bool_enum = bool_var_array(4)
|
26
|
-
@int = int_var(0..3)
|
27
|
-
@bool = bool_var
|
28
|
-
|
29
|
-
branch_on @int
|
30
|
-
end
|
31
|
-
end
|
32
|
-
|
33
|
-
class SetChannelSampleProblem < Gecode::Model
|
34
|
-
attr :bool_enum
|
35
|
-
attr :set
|
36
|
-
|
37
|
-
def initialize
|
38
|
-
@bool_enum = bool_var_array(4)
|
39
|
-
@set = set_var([], 0..3)
|
40
|
-
|
41
|
-
branch_on @bool_enum
|
42
|
-
end
|
43
|
-
end
|
44
|
-
|
45
|
-
|
46
|
-
describe Gecode::Constraints::IntEnum::Channel, ' (two int enums)' do
|
47
|
-
before do
|
48
|
-
@model = ChannelSampleProblem.new
|
49
|
-
@positions = @model.positions
|
50
|
-
@elements = @model.elements
|
51
|
-
@invoke_options = lambda do |hash|
|
52
|
-
@positions.must.channel @elements, hash
|
53
|
-
@model.solve!
|
54
|
-
end
|
55
|
-
@expect_options = option_expectation do |strength, kind, reif_var|
|
56
|
-
Gecode::Raw.should_receive(:channel).once.with(
|
57
|
-
an_instance_of(Gecode::Raw::Space),
|
58
|
-
an_instance_of(Gecode::Raw::IntVarArray),
|
59
|
-
an_instance_of(Gecode::Raw::IntVarArray), strength, kind)
|
60
|
-
end
|
61
|
-
end
|
62
|
-
|
63
|
-
it 'should translate into a channel constraint' do
|
64
|
-
Gecode::Raw.should_receive(:channel).once.with(
|
65
|
-
an_instance_of(Gecode::Raw::Space),
|
66
|
-
anything, anything, Gecode::Raw::ICL_DEF, Gecode::Raw::PK_DEF)
|
67
|
-
@invoke_options.call({})
|
68
|
-
end
|
69
|
-
|
70
|
-
it 'should constrain variables to be channelled' do
|
71
|
-
@elements.must.channel @positions
|
72
|
-
@model.solve!
|
73
|
-
elements = @model.elements.values
|
74
|
-
positions = @model.elements.values
|
75
|
-
elements.each_with_index do |element, i|
|
76
|
-
element.should equal(positions.index(i))
|
77
|
-
end
|
78
|
-
end
|
79
|
-
|
80
|
-
it 'should not allow negation' do
|
81
|
-
lambda{ @elements.must_not.channel @positions }.should raise_error(
|
82
|
-
Gecode::MissingConstraintError)
|
83
|
-
end
|
84
|
-
|
85
|
-
it 'should raise error for unsupported right hand sides' do
|
86
|
-
lambda{ @elements.must.channel 'hello' }.should raise_error(TypeError)
|
87
|
-
end
|
88
|
-
|
89
|
-
it_should_behave_like 'non-reifiable constraint'
|
90
|
-
end
|
91
|
-
|
92
|
-
describe Gecode::Constraints::SetEnum::Channel::IntChannelConstraint, ' (channel with set as right 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
|
-
@positions.must.channel @sets, hash
|
100
|
-
@model.solve!
|
101
|
-
end
|
102
|
-
@expect_options = option_expectation do |strength, kind, 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({})
|
112
|
-
@positions.must.channel @sets
|
113
|
-
@model.solve!
|
114
|
-
end
|
115
|
-
|
116
|
-
it 'should constrain variables to be channelled' do
|
117
|
-
@positions.must.channel @sets
|
118
|
-
@model.solve!
|
119
|
-
sets = @model.sets
|
120
|
-
positions = @model.positions.values
|
121
|
-
positions.each_with_index do |position, i|
|
122
|
-
sets[position].value.should include(i)
|
123
|
-
end
|
124
|
-
end
|
125
|
-
|
126
|
-
it_should_behave_like 'non-reifiable set constraint'
|
127
|
-
end
|
128
|
-
|
129
|
-
describe Gecode::Constraints::SetEnum::Channel::IntChannelConstraint, ' (channel with set as left hand side)' do
|
130
|
-
before do
|
131
|
-
@model = ChannelSampleProblem.new
|
132
|
-
@positions = @model.positions
|
133
|
-
@sets = @model.sets
|
134
|
-
|
135
|
-
@invoke_options = lambda do |hash|
|
136
|
-
@sets.must.channel @positions, hash
|
137
|
-
@model.solve!
|
138
|
-
end
|
139
|
-
@expect_options = option_expectation do |strength, kind, reif_var|
|
140
|
-
Gecode::Raw.should_receive(:channel).once.with(
|
141
|
-
an_instance_of(Gecode::Raw::Space),
|
142
|
-
an_instance_of(Gecode::Raw::IntVarArray),
|
143
|
-
an_instance_of(Gecode::Raw::SetVarArray))
|
144
|
-
end
|
145
|
-
end
|
146
|
-
|
147
|
-
it 'should translate into a channel constraint' do
|
148
|
-
@expect_options.call({})
|
149
|
-
@sets.must.channel @positions
|
150
|
-
@model.solve!
|
151
|
-
end
|
152
|
-
|
153
|
-
it 'should not allow negation' do
|
154
|
-
lambda{ @sets.must_not.channel @positions }.should raise_error(
|
155
|
-
Gecode::MissingConstraintError)
|
156
|
-
end
|
157
|
-
|
158
|
-
it 'should raise error for unsupported right hand sides' do
|
159
|
-
lambda{ @sets.must.channel 'hello' }.should raise_error(TypeError)
|
160
|
-
end
|
161
|
-
|
162
|
-
it_should_behave_like 'non-reifiable set constraint'
|
163
|
-
end
|
164
|
-
|
165
|
-
# Requires @model, @bool and @int. Also requires @place_constraint which is a
|
166
|
-
# method that takes five variables: a boolean variable, an integer variable,
|
167
|
-
# the name of the equality method to use, whether or not the constraint should
|
168
|
-
# be negated and a hash of options, and places the channel constraint on them.
|
169
|
-
describe 'channel constraint between one int and one bool variable', :shared => true do
|
170
|
-
before do
|
171
|
-
@invoke_options = lambda do |hash|
|
172
|
-
@place_constraint.call(@bool, @int, :==, false, hash)
|
173
|
-
@model.solve!
|
174
|
-
end
|
175
|
-
@expect_options = option_expectation do |strength, kind, reif_var|
|
176
|
-
Gecode::Raw.should_receive(:channel).once.with(
|
177
|
-
an_instance_of(Gecode::Raw::Space),
|
178
|
-
an_instance_of(Gecode::Raw::IntVar),
|
179
|
-
an_instance_of(Gecode::Raw::BoolVar),
|
180
|
-
strength, kind)
|
181
|
-
end
|
182
|
-
end
|
183
|
-
|
184
|
-
([:==] + Gecode::Constraints::Util::COMPARISON_ALIASES[:==]).each do |ali|
|
185
|
-
it "should translate #{ali} into a channel constraint" do
|
186
|
-
@expect_options.call({})
|
187
|
-
@place_constraint.call(@bool, @int, ali, false, {})
|
188
|
-
@model.solve!
|
189
|
-
end
|
190
|
-
end
|
191
|
-
|
192
|
-
it 'should constrain the int variable to be 1 when the boolean variable is true' do
|
193
|
-
@bool.must_be.true
|
194
|
-
@place_constraint.call(@bool, @int, :==, false, {})
|
195
|
-
@model.solve!
|
196
|
-
@int.value.should == 1
|
197
|
-
end
|
198
|
-
|
199
|
-
it 'should constrain the int variable to be 0 when the boolean variable is false' do
|
200
|
-
@bool.must_be.false
|
201
|
-
@place_constraint.call(@bool, @int, :==, false, {})
|
202
|
-
@model.solve!
|
203
|
-
@int.value.should == 0
|
204
|
-
end
|
205
|
-
|
206
|
-
it 'should not allow negation' do
|
207
|
-
lambda do
|
208
|
-
@place_constraint.call(@bool, @int, :==, true, {})
|
209
|
-
end.should raise_error(Gecode::MissingConstraintError)
|
210
|
-
end
|
211
|
-
|
212
|
-
it_should_behave_like 'non-reifiable constraint'
|
213
|
-
end
|
214
|
-
|
215
|
-
describe Gecode::Constraints::Int::Channel, ' (one int and one bool variable)' do
|
216
|
-
before do
|
217
|
-
@model = BoolChannelSampleProblem.new
|
218
|
-
@bool = @model.bool_var
|
219
|
-
@int = @model.int_var
|
220
|
-
|
221
|
-
@place_constraint = lambda do |bool, int, equals_method_name, negate, options|
|
222
|
-
if negate
|
223
|
-
int.must_not.method(equals_method_name).call(bool, options)
|
224
|
-
else
|
225
|
-
int.must.method(equals_method_name).call(bool, options)
|
226
|
-
end
|
227
|
-
end
|
228
|
-
end
|
229
|
-
|
230
|
-
it 'should not shadow linear boolean constraints' do
|
231
|
-
lambda do
|
232
|
-
(@bool + @bool).must == @bool
|
233
|
-
@model.solve!
|
234
|
-
end.should_not raise_error
|
235
|
-
end
|
236
|
-
|
237
|
-
it 'should raise error for unsupported right hand sides' do
|
238
|
-
lambda{ @int.must == 'hello' }.should raise_error(TypeError)
|
239
|
-
end
|
240
|
-
|
241
|
-
it_should_behave_like 'channel constraint between one int and one bool variable'
|
242
|
-
end
|
243
|
-
|
244
|
-
describe Gecode::Constraints::Int::Channel, ' (one bool and one int variable)' do
|
245
|
-
before do
|
246
|
-
@model = BoolChannelSampleProblem.new
|
247
|
-
@bool = @model.bool_var
|
248
|
-
@int = @model.int_var
|
249
|
-
|
250
|
-
@place_constraint = lambda do |bool, int, equals_method_name, negate, options|
|
251
|
-
if negate
|
252
|
-
bool.must_not.method(equals_method_name).call(int, options)
|
253
|
-
else
|
254
|
-
bool.must.method(equals_method_name).call(int, options)
|
255
|
-
end
|
256
|
-
end
|
257
|
-
end
|
258
|
-
|
259
|
-
it 'should not shadow linear boolean constraints' do
|
260
|
-
lambda do
|
261
|
-
@bool.must == @bool + @bool
|
262
|
-
@model.solve!
|
263
|
-
end.should_not raise_error
|
264
|
-
end
|
265
|
-
|
266
|
-
it 'should raise error for unsupported right hand sides' do
|
267
|
-
lambda{ @bool.must == 'hello' }.should raise_error(TypeError)
|
268
|
-
end
|
269
|
-
|
270
|
-
it_should_behave_like 'channel constraint between one int and one bool variable'
|
271
|
-
end
|
272
|
-
|
273
|
-
# Requires @model, @bool_enum and @int. Also requires @place_constraint which
|
274
|
-
# is a method that takes four variables: a boolean enum, an integer variable,
|
275
|
-
# whether or not the constraint should be negated and a hash of options, and
|
276
|
-
# places the channel constraint on them.
|
277
|
-
describe 'channel constraint between bool enum and int variable', :shared => true do
|
278
|
-
before do
|
279
|
-
@invoke_options = lambda do |hash|
|
280
|
-
@place_constraint.call(@bools, @int, false, hash)
|
281
|
-
@model.solve!
|
282
|
-
end
|
283
|
-
@expect_options = option_expectation do |strength, kind, reif_var|
|
284
|
-
Gecode::Raw.should_receive(:channel).once.with(
|
285
|
-
an_instance_of(Gecode::Raw::Space),
|
286
|
-
an_instance_of(Gecode::Raw::BoolVarArray),
|
287
|
-
an_instance_of(Gecode::Raw::IntVar), 0,
|
288
|
-
strength, kind)
|
289
|
-
end
|
290
|
-
end
|
291
|
-
|
292
|
-
it 'should channel the bool enum with the integer variable' do
|
293
|
-
@int.must > 2
|
294
|
-
@place_constraint.call(@bools, @int, false, {})
|
295
|
-
@model.solve!.should_not be_nil
|
296
|
-
int_val = @int.value
|
297
|
-
@bools.values.each_with_index do |bool, index|
|
298
|
-
bool.should == (index == int_val)
|
299
|
-
end
|
300
|
-
end
|
301
|
-
|
302
|
-
it 'should take the offset into account when channeling' do
|
303
|
-
@int.must > 2
|
304
|
-
offset = 1
|
305
|
-
@place_constraint.call(@bools, @int, false, :offset => offset)
|
306
|
-
@model.solve!.should_not be_nil
|
307
|
-
int_val = @int.value
|
308
|
-
@bools.values.each_with_index do |bool, index|
|
309
|
-
bool.should == (index + offset == int_val)
|
310
|
-
end
|
311
|
-
end
|
312
|
-
|
313
|
-
it 'should not allow negation' do
|
314
|
-
lambda do
|
315
|
-
@place_constraint.call(@bools, @int, true, {})
|
316
|
-
end.should raise_error(Gecode::MissingConstraintError)
|
317
|
-
end
|
318
|
-
|
319
|
-
it_should_behave_like 'non-reifiable constraint'
|
320
|
-
end
|
321
|
-
|
322
|
-
describe Gecode::Constraints::BoolEnum::Channel, ' (bool enum as lhs with int variable)' do
|
323
|
-
before do
|
324
|
-
@model = BoolChannelSampleProblem.new
|
325
|
-
@bools = @model.bool_enum
|
326
|
-
@int = @model.int
|
327
|
-
|
328
|
-
@place_constraint = lambda do |bools, int, negate, options|
|
329
|
-
unless negate
|
330
|
-
bools.must.channel(int, options)
|
331
|
-
else
|
332
|
-
bools.must_not.channel(int, options)
|
333
|
-
end
|
334
|
-
end
|
335
|
-
end
|
336
|
-
|
337
|
-
it 'should raise error if an integer variable is not given as right hand side' do
|
338
|
-
lambda do
|
339
|
-
@bools.must.channel 'hello'
|
340
|
-
end.should raise_error(TypeError)
|
341
|
-
end
|
342
|
-
|
343
|
-
it_should_behave_like 'channel constraint between bool enum and int variable'
|
344
|
-
end
|
345
|
-
|
346
|
-
|
347
|
-
describe Gecode::Constraints::BoolEnum::Channel, ' (int variable as lhs with bool enum)' do
|
348
|
-
before do
|
349
|
-
@model = BoolChannelSampleProblem.new
|
350
|
-
@bools = @model.bool_enum
|
351
|
-
@int = @model.int
|
352
|
-
|
353
|
-
@place_constraint = lambda do |bools, int, negate, options|
|
354
|
-
unless negate
|
355
|
-
int.must.channel(bools, options)
|
356
|
-
else
|
357
|
-
int.must_not.channel(bools, options)
|
358
|
-
end
|
359
|
-
end
|
360
|
-
end
|
361
|
-
|
362
|
-
it 'should raise error if a boolean enum is not given as right hand side' do
|
363
|
-
lambda do
|
364
|
-
@int.must.channel 'hello'
|
365
|
-
end.should raise_error(TypeError)
|
366
|
-
end
|
367
|
-
|
368
|
-
it_should_behave_like 'channel constraint between bool enum and int variable'
|
369
|
-
end
|
370
|
-
|
371
|
-
# Requires @model, @bool_enum and @set. Also requires @place_constraint which
|
372
|
-
# is a method that takes four variables: a boolean enum, a set variable,
|
373
|
-
# whether or not the constraint should be negated and a hash of options, and
|
374
|
-
# places the channel constraint on them.
|
375
|
-
describe 'channel constraint between set variable and bool enum', :shared => true do
|
376
|
-
before do
|
377
|
-
@invoke_options = lambda do |hash|
|
378
|
-
@place_constraint.call(@bools, @set, false, hash)
|
379
|
-
@model.solve!
|
380
|
-
end
|
381
|
-
@expect_options = option_expectation do |strength, kind, reif_var|
|
382
|
-
Gecode::Raw.should_receive(:channel).once.with(
|
383
|
-
an_instance_of(Gecode::Raw::Space),
|
384
|
-
an_instance_of(Gecode::Raw::BoolVarArray),
|
385
|
-
an_instance_of(Gecode::Raw::SetVar))
|
386
|
-
end
|
387
|
-
end
|
388
|
-
|
389
|
-
it 'should channel the bool enum with the set variable' do
|
390
|
-
@set.must_be.superset_of [0, 2]
|
391
|
-
@place_constraint.call(@bools, @set, false, {})
|
392
|
-
@model.solve!.should_not be_nil
|
393
|
-
set_values = @set.value
|
394
|
-
@bools.values.each_with_index do |bool, index|
|
395
|
-
bool.should == set_values.include?(index)
|
396
|
-
end
|
397
|
-
end
|
398
|
-
|
399
|
-
it 'should not allow negation' do
|
400
|
-
lambda do
|
401
|
-
@place_constraint.call(@bools, @set, true, {})
|
402
|
-
end.should raise_error(Gecode::MissingConstraintError)
|
403
|
-
end
|
404
|
-
|
405
|
-
it_should_behave_like 'non-reifiable set constraint'
|
406
|
-
end
|
407
|
-
|
408
|
-
describe Gecode::Constraints::Set::Channel, ' (set variable as lhs with bool enum)' do
|
409
|
-
before do
|
410
|
-
@model = SetChannelSampleProblem.new
|
411
|
-
@bools = @model.bool_enum
|
412
|
-
@set = @model.set
|
413
|
-
|
414
|
-
@place_constraint = lambda do |bools, set, negate, options|
|
415
|
-
unless negate
|
416
|
-
set.must.channel(bools, options)
|
417
|
-
else
|
418
|
-
set.must_not.channel(bools, options)
|
419
|
-
end
|
420
|
-
end
|
421
|
-
end
|
422
|
-
|
423
|
-
it 'should raise error if a boolean enum is not given as right hand side' do
|
424
|
-
lambda do
|
425
|
-
@set.must.channel 'hello'
|
426
|
-
end.should raise_error(TypeError)
|
427
|
-
end
|
428
|
-
|
429
|
-
it_should_behave_like 'channel constraint between set variable and bool enum'
|
430
|
-
end
|
431
|
-
|
432
|
-
describe Gecode::Constraints::Set::Channel, ' (bool enum as lhs with set variable)' do
|
433
|
-
before do
|
434
|
-
@model = SetChannelSampleProblem.new
|
435
|
-
@bools = @model.bool_enum
|
436
|
-
@set = @model.set
|
437
|
-
|
438
|
-
@place_constraint = lambda do |bools, set, negate, options|
|
439
|
-
unless negate
|
440
|
-
bools.must.channel(set, options)
|
441
|
-
else
|
442
|
-
bools.must_not.channel(set, options)
|
443
|
-
end
|
444
|
-
end
|
445
|
-
end
|
446
|
-
|
447
|
-
it 'should raise error if an integer variable is not given as right hand side' do
|
448
|
-
lambda do
|
449
|
-
@bools.must.channel 'hello'
|
450
|
-
end.should raise_error(TypeError)
|
451
|
-
end
|
452
|
-
|
453
|
-
it_should_behave_like 'channel constraint between set variable and bool enum'
|
454
|
-
end
|