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,84 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../constraint_helper'
|
2
|
+
|
3
|
+
Gecode::Util::RELATION_TYPES.each_pair do |relation, rel_value|
|
4
|
+
describe Gecode::SetElements::Relation, " (#{relation} with int op)" do
|
5
|
+
before do
|
6
|
+
@model = Gecode::Model.new
|
7
|
+
@set = @model.set_var([0], 0..2)
|
8
|
+
@int = @model.int_var(-1..2)
|
9
|
+
@model.branch_on @set
|
10
|
+
@model.branch_on @int
|
11
|
+
|
12
|
+
# For constraint spec.
|
13
|
+
@types = [:set_elements, :int]
|
14
|
+
@invoke = lambda do |receiver, op, hash|
|
15
|
+
receiver.method(relation).call(op, hash)
|
16
|
+
@model.solve!
|
17
|
+
end
|
18
|
+
@expect = lambda do |var1, var2, opts, reif_var|
|
19
|
+
Gecode::Raw.should_receive(:rel).once.with(
|
20
|
+
an_instance_of(Gecode::Raw::Space),
|
21
|
+
var1, rel_value, var2)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
it "should constrain the elements of the set when #{relation} is used" do
|
26
|
+
@set.elements.must.method(relation).call(@int)
|
27
|
+
@model.solve!
|
28
|
+
@set.value.each do |i|
|
29
|
+
i.should.method(relation).call(@int.value)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
it "should constrain the elements of the set when negated #{relation} is used" do
|
34
|
+
@set.elements.must_not.method(relation).call(@int)
|
35
|
+
@model.solve!
|
36
|
+
@set.value.each do |i|
|
37
|
+
i.should_not.method(relation).call(@int.value)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
it_should_behave_like 'non-reifiable set constraint'
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
Gecode::Util::RELATION_TYPES.each_pair do |relation, rel_value|
|
46
|
+
describe Gecode::SetElements::Relation, " (#{relation} with fixnum)" do
|
47
|
+
before do
|
48
|
+
@model = Gecode::Model.new
|
49
|
+
@set = @model.set_var([], 0..2)
|
50
|
+
@int_constant = 1
|
51
|
+
@model.branch_on @set
|
52
|
+
|
53
|
+
# For constraint spec.
|
54
|
+
@types = [:set_elements]
|
55
|
+
@invoke = lambda do |receiver, hash|
|
56
|
+
receiver.method(relation).call(@int_constant, hash)
|
57
|
+
@model.solve!
|
58
|
+
end
|
59
|
+
@expect = lambda do |var1, var2, opts, reif_var|
|
60
|
+
Gecode::Raw.should_receive(:rel).once.with(
|
61
|
+
an_instance_of(Gecode::Raw::Space),
|
62
|
+
var1, rel_value, an_instance_of(Gecode::Raw::IntVar))
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
it "should constrain the elements of the set when #{relation} is used" do
|
67
|
+
@set.elements.must.method(relation).call(@int_constant)
|
68
|
+
@model.solve!
|
69
|
+
@set.value.each do |i|
|
70
|
+
i.should.method(relation).call(@int_constant)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
it "should constrain the elements of the set when negated #{relation} is used" do
|
75
|
+
@set.elements.must_not.method(relation).call(@int_constant)
|
76
|
+
@model.solve!
|
77
|
+
@set.value.each do |i|
|
78
|
+
i.should_not.method(relation).call(@int_constant)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
it_should_behave_like 'non-reifiable set constraint'
|
83
|
+
end
|
84
|
+
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../constraint_helper'
|
2
|
+
|
3
|
+
class ChannelSampleProblem < Gecode::Model
|
4
|
+
attr :elements
|
5
|
+
attr :positions
|
6
|
+
attr :sets
|
7
|
+
|
8
|
+
def initialize
|
9
|
+
@elements = int_var_array(4, 0..3)
|
10
|
+
@elements.must_be.distinct
|
11
|
+
@positions = int_var_array(4, 0..3)
|
12
|
+
@positions.must_be.distinct
|
13
|
+
@sets = set_var_array(4, [], 0..3)
|
14
|
+
branch_on @positions
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
describe Gecode::SetEnum::Channel::IntEnumChannelConstraint, ' (channel with set as right hand side)' do
|
19
|
+
before do
|
20
|
+
@model = ChannelSampleProblem.new
|
21
|
+
@positions = @model.positions
|
22
|
+
@sets = @model.sets
|
23
|
+
|
24
|
+
@types = [:int_enum, :set_enum]
|
25
|
+
@invoke = lambda do |receiver, set_enum, hash|
|
26
|
+
receiver.channel(set_enum, hash)
|
27
|
+
@model.solve!
|
28
|
+
end
|
29
|
+
@expect = lambda do |var1, var2, opts, reif_var|
|
30
|
+
Gecode::Raw.should_receive(:channel).once.with(
|
31
|
+
an_instance_of(Gecode::Raw::Space),
|
32
|
+
var1, var2)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
it 'should constrain variables to be channelled' do
|
37
|
+
@positions.must.channel @sets
|
38
|
+
@model.solve!
|
39
|
+
sets = @model.sets
|
40
|
+
positions = @model.positions.values
|
41
|
+
positions.each_with_index do |position, i|
|
42
|
+
sets[position].value.should include(i)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
it_should_behave_like 'non-reifiable set constraint'
|
47
|
+
it_should_behave_like 'non-negatable constraint'
|
48
|
+
end
|
49
|
+
|
50
|
+
describe Gecode::SetEnum::Channel::IntEnumChannelConstraint, ' (channel with set as left hand side)' do
|
51
|
+
before do
|
52
|
+
@model = ChannelSampleProblem.new
|
53
|
+
@positions = @model.positions
|
54
|
+
@sets = @model.sets
|
55
|
+
|
56
|
+
@types = [:set_enum, :int_enum]
|
57
|
+
@invoke = lambda do |receiver, int_enum, hash|
|
58
|
+
receiver.channel(int_enum, hash)
|
59
|
+
@model.solve!
|
60
|
+
end
|
61
|
+
@expect = lambda do |var1, var2, opts, reif_var|
|
62
|
+
Gecode::Raw.should_receive(:channel).once.with(
|
63
|
+
an_instance_of(Gecode::Raw::Space),
|
64
|
+
var2, var1)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
it 'should constrain variables to be channelled' do
|
69
|
+
@sets.must.channel @positions
|
70
|
+
@model.solve!
|
71
|
+
sets = @model.sets
|
72
|
+
positions = @model.positions.values
|
73
|
+
positions.each_with_index do |position, i|
|
74
|
+
sets[position].value.should include(i)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
it_should_behave_like 'non-reifiable set constraint'
|
79
|
+
it_should_behave_like 'non-negatable constraint'
|
80
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../constraint_helper'
|
2
|
+
|
3
|
+
class SetEnumDistinctSampleProblem < Gecode::Model
|
4
|
+
attr :vars
|
5
|
+
attr :sets
|
6
|
+
|
7
|
+
def initialize
|
8
|
+
@vars = int_var_array(2, 1)
|
9
|
+
@sets = set_var_array(2, [], 0..2)
|
10
|
+
branch_on @sets
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
describe Gecode::SetEnum::Distinct, ' (at most one)' do
|
15
|
+
before do
|
16
|
+
@model = SetEnumDistinctSampleProblem.new
|
17
|
+
@sets = @model.sets
|
18
|
+
@size = 2
|
19
|
+
|
20
|
+
@types = [:set_enum]
|
21
|
+
@invoke = lambda do |receiver, hash|
|
22
|
+
receiver.at_most_share_one_element hash.update(:size => @size)
|
23
|
+
@model.solve!
|
24
|
+
end
|
25
|
+
@expect = lambda do |var, opts, reif_var|
|
26
|
+
Gecode::Raw.should_receive(:atmostOne).once.with(
|
27
|
+
an_instance_of(Gecode::Raw::Space),
|
28
|
+
var, @size)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
it 'should translate into a atmostOne constraint' do
|
33
|
+
Gecode::Raw.should_receive(:atmostOne).once.with(
|
34
|
+
an_instance_of(Gecode::Raw::Space),
|
35
|
+
an_instance_of(Gecode::Raw::SetVarArray), @size)
|
36
|
+
@sets.must.at_most_share_one_element(:size => @size)
|
37
|
+
@model.solve!
|
38
|
+
end
|
39
|
+
|
40
|
+
it 'should constrain sets to have at most one element in common' do
|
41
|
+
@sets.must.at_most_share_one_element(:size => @size)
|
42
|
+
@sets[0].must_not_be.superset_of 0
|
43
|
+
solution = @model.solve!
|
44
|
+
solution.should_not be_nil
|
45
|
+
set1, set2 = solution.sets
|
46
|
+
set1.value.size.should == @size
|
47
|
+
set2.value.size.should == @size
|
48
|
+
(set1.value.to_a & set2.value.to_a).size.should <= 1
|
49
|
+
end
|
50
|
+
|
51
|
+
it 'should raise error if :size is not specified' do
|
52
|
+
lambda do
|
53
|
+
@sets.must.at_most_share_one_element
|
54
|
+
end.should raise_error(ArgumentError)
|
55
|
+
end
|
56
|
+
|
57
|
+
it_should_behave_like 'non-reifiable set constraint'
|
58
|
+
it_should_behave_like 'non-negatable constraint'
|
59
|
+
end
|
@@ -0,0 +1,111 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../property_helper'
|
2
|
+
|
3
|
+
# Assumes that @operation, @set and @set_enum are defined.
|
4
|
+
describe 'set enum operation property', :shared => true do
|
5
|
+
before do
|
6
|
+
@property_types = [:set_enum]
|
7
|
+
@select_property = lambda do |set_enum|
|
8
|
+
set_enum.method(@operation).call
|
9
|
+
end
|
10
|
+
@selected_property = @set_enum.method(@operation).call
|
11
|
+
|
12
|
+
@constraint_class = Gecode::BlockConstraint
|
13
|
+
end
|
14
|
+
|
15
|
+
it "should translate #{@operation} into an operand constraint" do
|
16
|
+
operation_type = Gecode::Util::SET_OPERATION_TYPES[@operation]
|
17
|
+
@model.allow_space_access do
|
18
|
+
Gecode::Raw.should_receive(:rel).with(
|
19
|
+
an_instance_of(Gecode::Raw::Space), operation_type,
|
20
|
+
@set_enum.bind_array, @set.bind)
|
21
|
+
end
|
22
|
+
@set_enum.method(@operation).call.must == @set
|
23
|
+
@model.solve!
|
24
|
+
end
|
25
|
+
|
26
|
+
it_should_behave_like(
|
27
|
+
'property that produces set operand by short circuiting equality')
|
28
|
+
end
|
29
|
+
|
30
|
+
describe Gecode::SetEnum::Operation, ' (union)' do
|
31
|
+
before do
|
32
|
+
@model = Gecode::Model.new
|
33
|
+
@set_enum = @sets = @model.set_var_array(10, [], 0..20)
|
34
|
+
@set = @model.set_var([], 0..20)
|
35
|
+
@model.branch_on @sets
|
36
|
+
|
37
|
+
@operation = :union
|
38
|
+
end
|
39
|
+
|
40
|
+
it 'should constrain the union of the sets' do
|
41
|
+
@sets.union.must_be.subset_of [1,4,17]
|
42
|
+
@sets.union.must_be.superset_of 1
|
43
|
+
@model.solve!.should_not be_nil
|
44
|
+
union = @sets.values.inject([]){ |union, set| union += set.to_a }.uniq
|
45
|
+
union.should include(1)
|
46
|
+
(union - [1,4,17]).should be_empty
|
47
|
+
end
|
48
|
+
|
49
|
+
it_should_behave_like 'set enum operation property'
|
50
|
+
end
|
51
|
+
|
52
|
+
describe Gecode::SetEnum::Operation, ' (intersection)' do
|
53
|
+
before do
|
54
|
+
@model = Gecode::Model.new
|
55
|
+
@set_enum = @sets = @model.set_var_array(10, [], 0..20)
|
56
|
+
@set = @model.set_var([], 0..20)
|
57
|
+
@model.branch_on @sets
|
58
|
+
|
59
|
+
@operation = :intersection
|
60
|
+
end
|
61
|
+
|
62
|
+
it 'should constrain the intersection of the sets' do
|
63
|
+
@sets.intersection.must_be.subset_of [1,4,17]
|
64
|
+
@sets.intersection.must_be.superset_of [1]
|
65
|
+
@model.solve!.should_not be_nil
|
66
|
+
intersection = @sets.values.inject(nil) do |intersection, set|
|
67
|
+
next set.to_a if intersection.nil?
|
68
|
+
intersection &= set.to_a
|
69
|
+
end.uniq
|
70
|
+
intersection.should include(1)
|
71
|
+
(intersection - [1,4,17]).should be_empty
|
72
|
+
end
|
73
|
+
|
74
|
+
it_should_behave_like 'set enum operation property'
|
75
|
+
end
|
76
|
+
|
77
|
+
describe Gecode::SetEnum::Operation, ' (disjoint union)' do
|
78
|
+
before do
|
79
|
+
@model = Gecode::Model.new
|
80
|
+
@set_enum = @sets = @model.set_var_array(10, [], 0..20)
|
81
|
+
@set = @model.set_var([], 0..20)
|
82
|
+
@model.branch_on @sets
|
83
|
+
|
84
|
+
@operation = :disjoint_union
|
85
|
+
end
|
86
|
+
|
87
|
+
it 'should constrain the disjoint union of the sets' do
|
88
|
+
@sets.disjoint_union.must_be.subset_of [1,4,17]
|
89
|
+
@sets.disjoint_union.must_be.superset_of [1]
|
90
|
+
@model.solve!.should_not be_nil
|
91
|
+
disjoint_union = @sets.values.inject([]) do |union, set|
|
92
|
+
unless union.any?{ |x| set.to_a.include? x }
|
93
|
+
union += set.to_a
|
94
|
+
end
|
95
|
+
end.uniq
|
96
|
+
disjoint_union.should include(1)
|
97
|
+
(disjoint_union - [1,4,17]).should be_empty
|
98
|
+
end
|
99
|
+
|
100
|
+
it 'should constrain the disjoint union of the sets (2)' do
|
101
|
+
@sets.disjoint_union.must_be.subset_of [1,4,17]
|
102
|
+
@sets.disjoint_union.must_be.superset_of [1]
|
103
|
+
@sets[0].must_be.superset_of [1]
|
104
|
+
@sets[1].must_be.superset_of [1]
|
105
|
+
lambda do
|
106
|
+
@model.solve!
|
107
|
+
end.should raise_error(Gecode::NoSolutionError)
|
108
|
+
end
|
109
|
+
|
110
|
+
it_should_behave_like 'set enum operation property'
|
111
|
+
end
|
@@ -0,0 +1,73 @@
|
|
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
|
+
# Requires everything that composite behaviour spec requires in addition to
|
20
|
+
# @stub and @expect_constrain_equal .
|
21
|
+
describe 'selection constraint', :shared => true do
|
22
|
+
it 'should not disturb normal array access' do
|
23
|
+
@sets[0].should be_kind_of(Gecode::SetVar)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
describe Gecode::SetEnum::Select, ' (int operand)' do
|
28
|
+
include GecodeR::Specs::SetHelper
|
29
|
+
|
30
|
+
before do
|
31
|
+
@model = SelectionSampleProblem.new
|
32
|
+
@sets = @model.sets
|
33
|
+
@target = @set = @model.target
|
34
|
+
@index = @model.index
|
35
|
+
@model.branch_on @model.wrap_enum([@set])
|
36
|
+
@stub = @sets[@index]
|
37
|
+
|
38
|
+
@property_types = [:set_enum, :int]
|
39
|
+
@select_property = lambda do |set_enum, int|
|
40
|
+
set_enum[int]
|
41
|
+
end
|
42
|
+
@selected_property = @sets[@index]
|
43
|
+
@constraint_class = Gecode::BlockConstraint
|
44
|
+
end
|
45
|
+
|
46
|
+
it 'should constrain the specified element of an enum of sets' do
|
47
|
+
@sets[@index].must_be.superset_of([5,7,9])
|
48
|
+
@model.solve!
|
49
|
+
@sets[@index.value].value.should include(5,7,9)
|
50
|
+
end
|
51
|
+
|
52
|
+
it 'should translate into a select constraint' do
|
53
|
+
Gecode::Raw.should_receive(:selectSet)
|
54
|
+
@sets[@index].must_be.superset_of([5,7,9])
|
55
|
+
@model.solve!
|
56
|
+
end
|
57
|
+
|
58
|
+
it_should_behave_like 'selection constraint'
|
59
|
+
it_should_behave_like(
|
60
|
+
'property that produces set operand by short circuiting equality')
|
61
|
+
end
|
62
|
+
|
63
|
+
describe Gecode::SetEnum::Select, ' (set operand)' do
|
64
|
+
before do
|
65
|
+
@model = SelectionSampleProblem.new
|
66
|
+
@sets = @model.sets
|
67
|
+
@set = @model.set
|
68
|
+
end
|
69
|
+
|
70
|
+
it 'should produce a selected set operand' do
|
71
|
+
@sets[@set].should be_respond_to(:to_selected_set)
|
72
|
+
end
|
73
|
+
end
|
data/specs/enum_wrapper.rb
CHANGED
@@ -5,6 +5,7 @@ describe Gecode::Model, ' (enum wrapping)' do
|
|
5
5
|
@model = Gecode::Model.new
|
6
6
|
@bool = @model.bool_var
|
7
7
|
@int = @model.int_var(1..2)
|
8
|
+
@set = @model.set_var([], 1..2)
|
8
9
|
end
|
9
10
|
|
10
11
|
it 'should only allow enumerables to be wrapped' do
|
@@ -19,6 +20,13 @@ describe Gecode::Model, ' (enum wrapping)' do
|
|
19
20
|
@model.wrap_enum(enum)
|
20
21
|
end.should_not raise_error
|
21
22
|
end
|
23
|
+
|
24
|
+
it 'should allow enumerables of bool operands to be wrapped' do
|
25
|
+
lambda do
|
26
|
+
enum = [@bool & @bool]
|
27
|
+
@model.wrap_enum(enum)
|
28
|
+
end.should_not raise_error
|
29
|
+
end
|
22
30
|
|
23
31
|
it 'should allow enumerables of int variables to be wrapped' do
|
24
32
|
lambda do
|
@@ -26,6 +34,28 @@ describe Gecode::Model, ' (enum wrapping)' do
|
|
26
34
|
@model.wrap_enum(enum)
|
27
35
|
end.should_not raise_error
|
28
36
|
end
|
37
|
+
|
38
|
+
it 'should allow enumerables of int operands to be wrapped' do
|
39
|
+
lambda do
|
40
|
+
enum = [@int + @int]
|
41
|
+
@model.wrap_enum(enum)
|
42
|
+
end.should_not raise_error
|
43
|
+
end
|
44
|
+
|
45
|
+
it 'should allow enumerables of set variables to be wrapped' do
|
46
|
+
lambda do
|
47
|
+
enum = [@set]
|
48
|
+
@model.wrap_enum(enum)
|
49
|
+
end.should_not raise_error
|
50
|
+
end
|
51
|
+
|
52
|
+
it 'should allow enumerables of set operands to be wrapped' do
|
53
|
+
lambda do
|
54
|
+
enum = [@set.union(@set)]
|
55
|
+
@model.wrap_enum(enum)
|
56
|
+
end.should_not raise_error
|
57
|
+
end
|
58
|
+
|
29
59
|
|
30
60
|
it 'should allow enumerables of fixnums to be wrapped' do
|
31
61
|
lambda do
|
@@ -76,7 +106,7 @@ describe Gecode::IntEnumMethods do
|
|
76
106
|
|
77
107
|
it 'should convert to an int var array' do
|
78
108
|
@model.allow_space_access do
|
79
|
-
@int_enum.
|
109
|
+
@int_enum.bind_array.should be_kind_of(Gecode::Raw::IntVarArray)
|
80
110
|
end
|
81
111
|
end
|
82
112
|
|
@@ -84,6 +114,11 @@ describe Gecode::IntEnumMethods do
|
|
84
114
|
@int_enum.domain_range.should == (0..1)
|
85
115
|
(@int_enum << @model.int_var(-4..4)).domain_range.should == (-4..4)
|
86
116
|
end
|
117
|
+
|
118
|
+
it 'should define #to_int_enum' do
|
119
|
+
@int_enum.to_int_enum.should be_kind_of(
|
120
|
+
Gecode::IntEnum::IntEnumOperand)
|
121
|
+
end
|
87
122
|
end
|
88
123
|
|
89
124
|
describe Gecode::BoolEnumMethods do
|
@@ -94,9 +129,14 @@ describe Gecode::BoolEnumMethods do
|
|
94
129
|
|
95
130
|
it 'should convert to a bool var array' do
|
96
131
|
@model.allow_space_access do
|
97
|
-
@bool_enum.
|
132
|
+
@bool_enum.bind_array.should be_kind_of(Gecode::Raw::BoolVarArray)
|
98
133
|
end
|
99
134
|
end
|
135
|
+
|
136
|
+
it 'should define #to_bool_enum' do
|
137
|
+
@bool_enum.to_bool_enum.should be_kind_of(
|
138
|
+
Gecode::BoolEnum::BoolEnumOperand)
|
139
|
+
end
|
100
140
|
end
|
101
141
|
|
102
142
|
describe Gecode::SetEnumMethods do
|
@@ -107,7 +147,7 @@ describe Gecode::SetEnumMethods do
|
|
107
147
|
|
108
148
|
it 'should convert to a set var array' do
|
109
149
|
@model.allow_space_access do
|
110
|
-
@set_enum.
|
150
|
+
@set_enum.bind_array.should be_kind_of(Gecode::Raw::SetVarArray)
|
111
151
|
end
|
112
152
|
end
|
113
153
|
|
@@ -115,6 +155,11 @@ describe Gecode::SetEnumMethods do
|
|
115
155
|
@set_enum.upper_bound_range.should == (0..1)
|
116
156
|
(@set_enum << @model.set_var([], -4..4)).upper_bound_range.should == (-4..4)
|
117
157
|
end
|
158
|
+
|
159
|
+
it 'should define #to_set_enum' do
|
160
|
+
@set_enum.to_set_enum.should be_kind_of(
|
161
|
+
Gecode::SetEnum::SetEnumOperand)
|
162
|
+
end
|
118
163
|
end
|
119
164
|
|
120
165
|
describe Gecode::FixnumEnumMethods do
|
@@ -126,4 +171,9 @@ describe Gecode::FixnumEnumMethods do
|
|
126
171
|
it 'should compute the smallest domain range' do
|
127
172
|
@enum.domain_range.should == (7..4711)
|
128
173
|
end
|
174
|
+
|
175
|
+
it 'should define #to_fixnum_enum' do
|
176
|
+
@enum.to_fixnum_enum.should be_kind_of(
|
177
|
+
Gecode::FixnumEnum::FixnumEnumOperand)
|
178
|
+
end
|
129
179
|
end
|