gecoder 0.4.0 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGES +11 -0
- data/README +12 -1
- data/example/example_helper.rb +1 -0
- data/example/magic_sequence.rb +43 -0
- data/example/queens.rb +43 -0
- data/example/raw_bindings.rb +42 -0
- data/example/send_more_money.rb +43 -0
- data/example/sudoku.rb +65 -0
- data/ext/missing.cpp +15 -21
- data/ext/missing.h +14 -20
- data/ext/vararray.cpp +14 -20
- data/ext/vararray.h +18 -22
- data/lib/gecoder/bindings/bindings.rb +1979 -1969
- data/lib/gecoder/interface/binding_changes.rb +123 -2
- data/lib/gecoder/interface/constraints/bool/boolean.rb +80 -65
- data/lib/gecoder/interface/constraints/bool_enum/boolean.rb +59 -0
- data/lib/gecoder/interface/constraints/bool_enum_constraints.rb +8 -0
- data/lib/gecoder/interface/constraints/bool_var_constraints.rb +42 -0
- data/lib/gecoder/interface/constraints/int/arithmetic.rb +21 -44
- data/lib/gecoder/interface/constraints/int/domain.rb +6 -4
- data/lib/gecoder/interface/constraints/int_enum/arithmetic.rb +18 -44
- data/lib/gecoder/interface/constraints/int_enum/count.rb +3 -18
- data/lib/gecoder/interface/constraints/int_enum/distinct.rb +4 -16
- data/lib/gecoder/interface/constraints/int_enum/element.rb +9 -20
- data/lib/gecoder/interface/constraints/int_var_constraints.rb +28 -0
- data/lib/gecoder/interface/constraints/set/cardinality.rb +56 -0
- data/lib/gecoder/interface/constraints/set/domain.rb +66 -0
- data/lib/gecoder/interface/constraints/set/relation.rb +125 -0
- data/lib/gecoder/interface/constraints/set_var_constraints.rb +37 -0
- data/lib/gecoder/interface/constraints.rb +229 -65
- data/lib/gecoder/interface/enum_wrapper.rb +42 -11
- data/lib/gecoder/interface/model.rb +75 -0
- data/lib/gecoder/interface/search.rb +4 -9
- data/lib/gecoder/interface/variables.rb +36 -2
- data/lib/gecoder/version.rb +1 -1
- data/specs/bool_var.rb +58 -0
- data/specs/constraints/arithmetic.rb +91 -90
- data/specs/constraints/bool_enum.rb +130 -0
- data/specs/constraints/boolean.rb +95 -2
- data/specs/constraints/cardinality.rb +127 -0
- data/specs/constraints/constraint_helper.rb +91 -0
- data/specs/constraints/constraints.rb +31 -0
- data/specs/constraints/element.rb +43 -72
- data/specs/constraints/{domain.rb → int_domain.rb} +4 -0
- data/specs/constraints/{relation.rb → int_relation.rb} +0 -0
- data/specs/constraints/set_domain.rb +165 -0
- data/specs/constraints/set_relation.rb +181 -0
- data/specs/enum_wrapper.rb +13 -2
- data/specs/int_var.rb +33 -1
- data/specs/model.rb +80 -0
- data/specs/set_var.rb +39 -0
- data/specs/spec_helper.rb +35 -0
- data/specs/tmp +11 -124
- data/tasks/distribution.rake +1 -1
- data/vendor/rust/rust/class.rb +10 -10
- data/vendor/rust/rust/constants.rb +1 -1
- data/vendor/rust/rust/function.rb +5 -5
- data/vendor/rust/rust/type.rb +1 -1
- data/vendor/rust/test/constants.rb +1 -0
- data/vendor/rust/test/cppclass.cc +5 -0
- data/vendor/rust/test/cppclass.hh +4 -0
- data/vendor/rust/test/lib/extension-test.rb +1 -1
- data/vendor/rust/test/operators.cc +41 -0
- data/vendor/rust/test/operators.hh +39 -0
- data/vendor/rust/test/operators.rb +39 -0
- data/vendor/rust/test/test-cwrapper.rb +3 -0
- data/vendor/rust/test/test-operators.rb +42 -0
- metadata +31 -4
@@ -45,4 +45,95 @@ describe 'constraint with options', :shared => true do
|
|
45
45
|
end
|
46
46
|
|
47
47
|
it_should_behave_like 'constraint with strength option'
|
48
|
+
end
|
49
|
+
|
50
|
+
# This requires that the constraint spec has the instance variable
|
51
|
+
# @expect_relation which takes a relation and right hand side as arguments and
|
52
|
+
# sets up the corresponding expectations. It also requires @invoke_relation and
|
53
|
+
# @invoke_negated_relation with the same arguments. The spec is also required to
|
54
|
+
# provide an int var @target.
|
55
|
+
describe 'composite constraint', :shared => true do
|
56
|
+
Gecode::Constraints::Util::RELATION_TYPES.each_pair do |relation, type|
|
57
|
+
it "should translate #{relation} with constant target" do
|
58
|
+
@expect_relation.call(type, 1, false)
|
59
|
+
@invoke_relation.call(relation, 1, false)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
Gecode::Constraints::Util::RELATION_TYPES.each_pair do |relation, type|
|
64
|
+
it "should translate #{relation} with variable target" do
|
65
|
+
@expect_relation.call(type, @target, false)
|
66
|
+
@invoke_relation.call(relation, @target, false)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
Gecode::Constraints::Util::NEGATED_RELATION_TYPES.each_pair do |relation, type|
|
71
|
+
it "should translate negated #{relation} with constant target" do
|
72
|
+
@expect_relation.call(type, 1, true)
|
73
|
+
@invoke_relation.call(relation, 1, true)
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
Gecode::Constraints::Util::NEGATED_RELATION_TYPES.each_pair do |relation, type|
|
78
|
+
it "should translate negated #{relation} with variable target" do
|
79
|
+
@expect_relation.call(type, @target, true)
|
80
|
+
@invoke_relation.call(relation, @target, true)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
it 'should raise error if the target is of the wrong type' do
|
85
|
+
lambda do
|
86
|
+
@invoke_relation.call(:==, 'hello', false)
|
87
|
+
end.should raise_error(TypeError)
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
# Requires @invoke_options and @model.
|
92
|
+
describe 'non-reifiable set constraint', :shared => true do
|
93
|
+
it 'should not accept strength option' do
|
94
|
+
lambda do
|
95
|
+
@invoke_options.call(:strength => :default)
|
96
|
+
end.should raise_error(ArgumentError)
|
97
|
+
end
|
98
|
+
|
99
|
+
it 'should not accept reification option' do
|
100
|
+
bool = @model.bool_var
|
101
|
+
lambda do
|
102
|
+
@invoke_options.call(:reify => bool)
|
103
|
+
end.should raise_error(ArgumentError)
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
# Requires @invoke_options, @expect_options and @model.
|
108
|
+
describe 'reifiable set constraint', :shared => true do
|
109
|
+
it 'should not accept strength option' do
|
110
|
+
lambda do
|
111
|
+
@invoke_options.call(:strength => :default)
|
112
|
+
end.should raise_error(ArgumentError)
|
113
|
+
end
|
114
|
+
|
115
|
+
it 'should accept reification option' do
|
116
|
+
bool = @model.bool_var
|
117
|
+
@expect_options.call(nil, bool)
|
118
|
+
@invoke_options.call(:reify => bool)
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
# Help methods for the GecodeR specs.
|
123
|
+
module GecodeR::Specs
|
124
|
+
module SetHelper
|
125
|
+
module_function
|
126
|
+
|
127
|
+
# Returns the arguments that should be used in a partial mock to expect the
|
128
|
+
# specified constant set (possibly an array of arguments).
|
129
|
+
def expect_constant_set(constant_set)
|
130
|
+
if constant_set.kind_of? Range
|
131
|
+
return constant_set.first, constant_set.last
|
132
|
+
elsif constant_set.kind_of? Fixnum
|
133
|
+
constant_set
|
134
|
+
else
|
135
|
+
an_instance_of(Gecode::Raw::IntSet)
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
48
139
|
end
|
@@ -17,6 +17,18 @@ describe Gecode::Constraints::IntEnum::Expression do
|
|
17
17
|
end
|
18
18
|
end
|
19
19
|
|
20
|
+
describe Gecode::Constraints::Int::CompositeStub, ' (not subclassed)' do
|
21
|
+
before do
|
22
|
+
@con = Gecode::Constraints::Int::CompositeStub.new(Gecode::Model.new, {})
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'should raise error when calling #constrain_equal' do
|
26
|
+
lambda do
|
27
|
+
@con.instance_eval{ constrain_equal(nil, {}) }
|
28
|
+
end.should raise_error(NoMethodError)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
20
32
|
describe Gecode::Constraints::Constraint, ' (not subclassed)' do
|
21
33
|
before do
|
22
34
|
@con = Gecode::Constraints::Constraint.new(Gecode::Model.new, {})
|
@@ -25,4 +37,23 @@ describe Gecode::Constraints::Constraint, ' (not subclassed)' do
|
|
25
37
|
it 'should raise error when calling #post because it\'s not overridden' do
|
26
38
|
lambda{ @con.post }.should raise_error(NoMethodError)
|
27
39
|
end
|
40
|
+
end
|
41
|
+
|
42
|
+
describe Gecode::Constraints::Util do
|
43
|
+
it 'should raise error when giving incorrect set to #constant_set_to_params' do
|
44
|
+
lambda do
|
45
|
+
Gecode::Constraints::Util.constant_set_to_params('hello')
|
46
|
+
end.should raise_error(TypeError)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
describe Gecode::Constraints::CompositeExpression do
|
51
|
+
it 'should raise error if a method doesn\'t exist' do
|
52
|
+
expression = Gecode::Constraints::CompositeExpression.new(
|
53
|
+
Gecode::Constraints::Int::Expression, Gecode::FreeIntVar,
|
54
|
+
Gecode::Model.new, {:lhs => nil, :negate => false}){}
|
55
|
+
lambda do
|
56
|
+
expression.this_method_does_not_exist
|
57
|
+
end.should raise_error(NoMethodError)
|
58
|
+
end
|
28
59
|
end
|
@@ -21,92 +21,58 @@ describe Gecode::Constraints::IntEnum::Element do
|
|
21
21
|
before do
|
22
22
|
@model = ElementSampleProblem.new
|
23
23
|
@prices = @model.prices
|
24
|
-
@price = @model.price
|
24
|
+
@target = @price = @model.price
|
25
25
|
@store = @model.store
|
26
26
|
@fixnum_prices = @model.fixnum_prices
|
27
27
|
|
28
|
-
#
|
29
|
-
@
|
30
|
-
|
31
|
-
|
32
|
-
end
|
33
|
-
@expect_options = lambda do |strength, reif_var|
|
28
|
+
# Creates an expectation corresponding to the specified input.
|
29
|
+
@expect = lambda do |element, relation, target, strength, reif_var, negated|
|
30
|
+
target = target.bind if target.respond_to? :bind
|
31
|
+
element = element.bind if element.respond_to? :bind
|
34
32
|
if reif_var.nil?
|
35
|
-
Gecode::Raw
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
33
|
+
if !negated and relation == Gecode::Raw::IRT_EQ and
|
34
|
+
target.kind_of? Gecode::Raw::IntVar
|
35
|
+
Gecode::Raw.should_receive(:element).once.with(@model.active_space,
|
36
|
+
an_instance_of(Gecode::Raw::IntVarArray),
|
37
|
+
element, target, strength)
|
38
|
+
else
|
39
|
+
Gecode::Raw.should_receive(:element).once.with(@model.active_space,
|
40
|
+
an_instance_of(Gecode::Raw::IntVarArray),
|
41
|
+
element, an_instance_of(Gecode::Raw::IntVar), strength)
|
42
|
+
Gecode::Raw.should_receive(:rel).once.with(@model.active_space,
|
43
|
+
an_instance_of(Gecode::Raw::IntVar), relation, target, strength)
|
44
|
+
end
|
42
45
|
else
|
43
46
|
Gecode::Raw.should_receive(:element).once.with(@model.active_space,
|
44
47
|
an_instance_of(Gecode::Raw::IntVarArray),
|
45
|
-
an_instance_of(Gecode::Raw::IntVar),
|
46
|
-
an_instance_of(Gecode::Raw::IntVar), an_instance_of(Fixnum))
|
48
|
+
element, an_instance_of(Gecode::Raw::IntVar), strength)
|
47
49
|
Gecode::Raw.should_receive(:rel).once.with(@model.active_space,
|
48
|
-
an_instance_of(Gecode::Raw::IntVar),
|
49
|
-
an_instance_of(Gecode::Raw::IntVar),
|
50
|
+
an_instance_of(Gecode::Raw::IntVar), relation, target,
|
50
51
|
an_instance_of(Gecode::Raw::BoolVar), strength)
|
51
52
|
end
|
52
53
|
end
|
53
|
-
end
|
54
|
-
|
55
|
-
Gecode::Constraints::Util::RELATION_TYPES.each_pair do |relation, type|
|
56
|
-
it "should translate #{relation} with variable right hand side" do
|
57
|
-
Gecode::Raw.should_receive(:element).once.with(@model.active_space,
|
58
|
-
an_instance_of(Gecode::Raw::IntVarArray),
|
59
|
-
an_instance_of(Gecode::Raw::IntVar),
|
60
|
-
an_instance_of(Gecode::Raw::IntVar), Gecode::Raw::ICL_DEF)
|
61
|
-
unless type == Gecode::Raw::IRT_EQ
|
62
|
-
Gecode::Raw.should_receive(:rel).once.with(@model.active_space,
|
63
|
-
an_instance_of(Gecode::Raw::IntVar), type,
|
64
|
-
an_instance_of(Gecode::Raw::IntVar), an_instance_of(Fixnum))
|
65
|
-
end
|
66
|
-
@prices[@store].must.send(relation, @price)
|
67
|
-
@model.solve!
|
68
|
-
end
|
69
|
-
end
|
70
54
|
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
an_instance_of(Gecode::Raw::IntVarArray),
|
75
|
-
an_instance_of(Gecode::Raw::IntVar),
|
76
|
-
an_instance_of(Gecode::Raw::IntVar), Gecode::Raw::ICL_DEF)
|
77
|
-
Gecode::Raw.should_receive(:rel).once.with(@model.active_space,
|
78
|
-
an_instance_of(Gecode::Raw::IntVar), type,
|
79
|
-
an_instance_of(Gecode::Raw::IntVar), an_instance_of(Fixnum))
|
80
|
-
@prices[@store].must_not.send(relation, @price)
|
55
|
+
# For constraint option spec.
|
56
|
+
@invoke_options = lambda do |hash|
|
57
|
+
@prices[@store].must_be.greater_than(@price, hash)
|
81
58
|
@model.solve!
|
82
59
|
end
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
60
|
+
@expect_options = lambda do |strength, reif_var|
|
61
|
+
@expect.call(@store, Gecode::Raw::IRT_GR, @price, strength, reif_var,
|
62
|
+
false)
|
63
|
+
end
|
64
|
+
|
65
|
+
# For composite spec.
|
66
|
+
@invoke_relation = lambda do |relation, target, negated|
|
67
|
+
if negated
|
68
|
+
@prices[@store].must_not.send(relation, target)
|
69
|
+
else
|
70
|
+
@prices[@store].must.send(relation, target)
|
94
71
|
end
|
95
|
-
@prices[@store].must.send(relation, 5)
|
96
72
|
@model.solve!
|
97
73
|
end
|
98
|
-
|
99
|
-
|
100
|
-
Gecode::Constraints::Util::NEGATED_RELATION_TYPES.each_pair do |relation, type|
|
101
|
-
it "should translate negated #{relation} with constant right hand side" do
|
102
|
-
Gecode::Raw.should_receive(:element).once.with(@model.active_space,
|
103
|
-
an_instance_of(Gecode::Raw::IntVarArray),
|
104
|
-
an_instance_of(Gecode::Raw::IntVar),
|
105
|
-
an_instance_of(Gecode::Raw::IntVar), Gecode::Raw::ICL_DEF)
|
106
|
-
Gecode::Raw.should_receive(:rel).once.with(@model.active_space,
|
107
|
-
an_instance_of(Gecode::Raw::IntVar), type, 5, an_instance_of(Fixnum))
|
108
|
-
@prices[@store].must_not.send(relation, 5)
|
109
|
-
@model.solve!
|
74
|
+
@expect_relation = lambda do |relation, target, negated|
|
75
|
+
@expect.call(@store, relation, target, Gecode::Raw::ICL_DEF, nil, negated)
|
110
76
|
end
|
111
77
|
end
|
112
78
|
|
@@ -119,10 +85,15 @@ describe Gecode::Constraints::IntEnum::Element do
|
|
119
85
|
@fixnum_prices[@store].must == @fixnum_prices[2]
|
120
86
|
@model.solve!.store.val.should equal(2)
|
121
87
|
end
|
122
|
-
|
123
|
-
it 'should
|
124
|
-
|
88
|
+
|
89
|
+
it 'should translate reification when using equality' do
|
90
|
+
bool_var = @model.bool_var
|
91
|
+
@expect.call(@store, Gecode::Raw::IRT_EQ, @target, Gecode::Raw::ICL_DEF,
|
92
|
+
bool_var, false)
|
93
|
+
@prices[@store].must_be.equal_to(@target, :reify => bool_var)
|
94
|
+
@model.solve!
|
125
95
|
end
|
126
96
|
|
97
|
+
it_should_behave_like 'composite constraint'
|
127
98
|
it_should_behave_like 'constraint with options'
|
128
99
|
end
|
@@ -52,5 +52,9 @@ describe Gecode::Constraints::Int::Domain do
|
|
52
52
|
@x.should have_domain(@domain.to_a - @range_domain.to_a)
|
53
53
|
end
|
54
54
|
|
55
|
+
it 'should raise error if the right hand side is not an enumeration' do
|
56
|
+
lambda{ @x.must_be.in 'hello' }.should raise_error(TypeError)
|
57
|
+
end
|
58
|
+
|
55
59
|
it_should_behave_like 'constraint with options'
|
56
60
|
end
|
File without changes
|
@@ -0,0 +1,165 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../spec_helper'
|
2
|
+
require File.dirname(__FILE__) + '/constraint_helper'
|
3
|
+
|
4
|
+
describe Gecode::Constraints::Set::Domain do
|
5
|
+
include GecodeR::Specs::SetHelper
|
6
|
+
|
7
|
+
before do
|
8
|
+
@model = Gecode::Model.new
|
9
|
+
@glb = [0]
|
10
|
+
@lub = 0..3
|
11
|
+
@set = @model.set_var(@glb, @lub)
|
12
|
+
@range = 0..1
|
13
|
+
@non_range = [0, 2]
|
14
|
+
@singleton = 0
|
15
|
+
|
16
|
+
@expect = lambda do |relation_type, rhs, reif_var, negated|
|
17
|
+
if reif_var.nil? and !negated
|
18
|
+
Gecode::Raw.should_receive(:dom).once.with(@model.active_space,
|
19
|
+
@set.bind, relation_type, *expect_constant_set(rhs))
|
20
|
+
else
|
21
|
+
params = [@model.active_space, @set.bind, relation_type]
|
22
|
+
params << expect_constant_set(rhs)
|
23
|
+
params << an_instance_of(Gecode::Raw::BoolVar)
|
24
|
+
Gecode::Raw.should_receive(:dom).once.with(*params.flatten)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
# For options spec.
|
29
|
+
@invoke_options = lambda do |hash|
|
30
|
+
@set.must_be.superset_of(@non_range, hash)
|
31
|
+
@model.solve!
|
32
|
+
end
|
33
|
+
@expect_options = lambda do |strength, reif_var|
|
34
|
+
@expect.call(Gecode::Raw::SRT_SUP, @non_range, reif_var, false)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
Gecode::Constraints::Util::SET_RELATION_TYPES.each_pair do |relation, type|
|
39
|
+
next if relation == :==
|
40
|
+
|
41
|
+
it "should translate #{relation} with constant range to domain constraint" do
|
42
|
+
@expect.call(type, @range, nil, false)
|
43
|
+
@set.must.send(relation, @range)
|
44
|
+
@model.solve!
|
45
|
+
end
|
46
|
+
|
47
|
+
it "should translate #{relation} with constant non-range to domain constraint" do
|
48
|
+
@expect.call(type, @non_range, nil, false)
|
49
|
+
@set.must.send(relation, @non_range)
|
50
|
+
@model.solve!
|
51
|
+
end
|
52
|
+
|
53
|
+
it "should translate #{relation} with constant singleton to domain constraint" do
|
54
|
+
@expect.call(type, @singleton, nil, false)
|
55
|
+
@set.must.send(relation, @singleton)
|
56
|
+
@model.solve!
|
57
|
+
end
|
58
|
+
|
59
|
+
it "should translate negated #{relation} with constant range to domain constraint" do
|
60
|
+
@expect.call(type, @range, nil, true)
|
61
|
+
@set.must_not.send(relation, @range)
|
62
|
+
@model.solve!
|
63
|
+
end
|
64
|
+
|
65
|
+
it "should translate negated #{relation} with constant non-range to domain constraint" do
|
66
|
+
@expect.call(type, @non_range, nil, true)
|
67
|
+
@set.must_not.send(relation, @non_range)
|
68
|
+
@model.solve!
|
69
|
+
end
|
70
|
+
|
71
|
+
it "should translate negated #{relation} with constant singleton to domain constraint" do
|
72
|
+
@expect.call(type, @singleton, nil, true)
|
73
|
+
@set.must_not.send(relation, @singleton)
|
74
|
+
@model.solve!
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
it_should_behave_like 'reifiable set constraint'
|
79
|
+
end
|
80
|
+
|
81
|
+
describe Gecode::Constraints::Set::Domain, ' (equality)' do
|
82
|
+
include GecodeR::Specs::SetHelper
|
83
|
+
|
84
|
+
before do
|
85
|
+
@model = Gecode::Model.new
|
86
|
+
@glb = [0]
|
87
|
+
@lub = 0..3
|
88
|
+
@set = @model.set_var(@glb, @lub)
|
89
|
+
@range = 0..1
|
90
|
+
@non_range = [0, 2]
|
91
|
+
@singleton = 0
|
92
|
+
|
93
|
+
@expect = lambda do |relation_type, rhs, reif_var|
|
94
|
+
if reif_var.nil?
|
95
|
+
Gecode::Raw.should_receive(:dom).once.with(@model.active_space,
|
96
|
+
@set.bind, relation_type, *expect_constant_set(rhs))
|
97
|
+
else
|
98
|
+
params = [@model.active_space, @set.bind, relation_type]
|
99
|
+
params << expect_constant_set(rhs)
|
100
|
+
params << an_instance_of(Gecode::Raw::BoolVar)
|
101
|
+
Gecode::Raw.should_receive(:dom).once.with(*params.flatten)
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
# For options spec.
|
106
|
+
@invoke_options = lambda do |hash|
|
107
|
+
@set.must_be.equal_to(@non_range, hash)
|
108
|
+
@model.solve!
|
109
|
+
end
|
110
|
+
@expect_options = lambda do |strength, reif_var|
|
111
|
+
@expect.call(Gecode::Raw::SRT_EQ, @non_range, reif_var)
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
it 'should translate equality with constant range to domain constraint' do
|
116
|
+
@expect.call(Gecode::Raw::SRT_EQ, @range, nil)
|
117
|
+
@set.must == @range
|
118
|
+
@model.solve!
|
119
|
+
end
|
120
|
+
|
121
|
+
it 'should translate equality with constant non-range to domain constraint' do
|
122
|
+
@expect.call(Gecode::Raw::SRT_EQ, @non_range, nil)
|
123
|
+
@set.must == @non_range
|
124
|
+
@model.solve!
|
125
|
+
end
|
126
|
+
|
127
|
+
it 'should translate equality with constant singleton to domain constraint' do
|
128
|
+
@expect.call(Gecode::Raw::SRT_EQ, @singleton, nil)
|
129
|
+
@set.must == @singleton
|
130
|
+
@model.solve!
|
131
|
+
end
|
132
|
+
|
133
|
+
it 'should translate negated equality with constant range to domain constraint' do
|
134
|
+
@expect.call(Gecode::Raw::SRT_NQ, @range, nil)
|
135
|
+
@set.must_not == @range
|
136
|
+
@model.solve!
|
137
|
+
end
|
138
|
+
|
139
|
+
it 'should translate negated equality with constant non-range to domain constraint' do
|
140
|
+
@expect.call(Gecode::Raw::SRT_NQ, @non_range, nil)
|
141
|
+
@set.must_not == @non_range
|
142
|
+
@model.solve!
|
143
|
+
end
|
144
|
+
|
145
|
+
it 'should translate negated equality with constant singleton to domain constraint' do
|
146
|
+
@expect.call(Gecode::Raw::SRT_NQ, @singleton, nil)
|
147
|
+
@set.must_not == @singleton
|
148
|
+
@model.solve!
|
149
|
+
end
|
150
|
+
|
151
|
+
it 'should constrain the domain with equality' do
|
152
|
+
@set.must == @singleton
|
153
|
+
@model.solve!
|
154
|
+
@set.should be_assigned
|
155
|
+
@set.should include(@singleton)
|
156
|
+
@set.val_size.should == 1
|
157
|
+
end
|
158
|
+
|
159
|
+
it 'should constrain the domain with inequality' do
|
160
|
+
@set.must_not == @singleton
|
161
|
+
@model.solve!.should be_nil
|
162
|
+
end
|
163
|
+
|
164
|
+
it_should_behave_like 'reifiable set constraint'
|
165
|
+
end
|
@@ -0,0 +1,181 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../spec_helper'
|
2
|
+
require File.dirname(__FILE__) + '/constraint_helper'
|
3
|
+
|
4
|
+
describe Gecode::Constraints::Set::Relation do
|
5
|
+
include GecodeR::Specs::SetHelper
|
6
|
+
|
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
|
+
|
12
|
+
@expect = lambda do |relation_type, rhs, reif_var, negated|
|
13
|
+
if reif_var.nil? and !negated
|
14
|
+
Gecode::Raw.should_receive(:rel).once.with(@model.active_space,
|
15
|
+
@set.bind, relation_type, @set2.bind)
|
16
|
+
else
|
17
|
+
Gecode::Raw.should_receive(:rel).once.with(@model.active_space,
|
18
|
+
@set.bind, relation_type, @set2.bind,
|
19
|
+
an_instance_of(Gecode::Raw::BoolVar))
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
# For options spec.
|
24
|
+
@invoke_options = lambda do |hash|
|
25
|
+
@set.must_be.superset_of(@set2, hash)
|
26
|
+
@model.solve!
|
27
|
+
end
|
28
|
+
@expect_options = lambda do |strength, reif_var|
|
29
|
+
@expect.call(Gecode::Raw::SRT_SUP, @set2, reif_var, false)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
Gecode::Constraints::Util::SET_RELATION_TYPES.each_pair do |relation, type|
|
34
|
+
next if relation == :==
|
35
|
+
|
36
|
+
it "should translate #{relation} with set to relation constraint" do
|
37
|
+
@expect.call(type, @set2, nil, false)
|
38
|
+
@set.must.send(relation, @set2)
|
39
|
+
@model.solve!
|
40
|
+
end
|
41
|
+
|
42
|
+
it "should translate negated #{relation} with set to relation constraint" do
|
43
|
+
@expect.call(type, @set2, nil, true)
|
44
|
+
@set.must_not.send(relation, @set2)
|
45
|
+
@model.solve!
|
46
|
+
end
|
47
|
+
end
|
48
|
+
it_should_behave_like 'reifiable set constraint'
|
49
|
+
end
|
50
|
+
|
51
|
+
describe Gecode::Constraints::Set::Relation, ' (equality)' do
|
52
|
+
include GecodeR::Specs::SetHelper
|
53
|
+
|
54
|
+
before do
|
55
|
+
@model = Gecode::Model.new
|
56
|
+
@set = @model.set_var([0], 0..1)
|
57
|
+
@set2 = @model.set_var([1], 0..1)
|
58
|
+
|
59
|
+
@expect = lambda do |relation_type, rhs, reif_var|
|
60
|
+
if reif_var.nil?
|
61
|
+
Gecode::Raw.should_receive(:rel).once.with(@model.active_space,
|
62
|
+
@set.bind, relation_type, @set2.bind)
|
63
|
+
else
|
64
|
+
Gecode::Raw.should_receive(:rel).once.with(@model.active_space,
|
65
|
+
@set.bind, relation_type, @set2.bind,
|
66
|
+
an_instance_of(Gecode::Raw::BoolVar))
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
# For options spec.
|
71
|
+
@invoke_options = lambda do |hash|
|
72
|
+
@set.must_be.equal_to(@set2, hash)
|
73
|
+
@model.solve!
|
74
|
+
end
|
75
|
+
@expect_options = lambda do |strength, reif_var|
|
76
|
+
@expect.call(Gecode::Raw::SRT_EQ, @set2, reif_var)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
it 'should translate equality with set to relation constraint' do
|
81
|
+
@expect.call(Gecode::Raw::SRT_EQ, @set2, nil)
|
82
|
+
@set.must == @set2
|
83
|
+
@model.solve!
|
84
|
+
end
|
85
|
+
|
86
|
+
it 'should translate negated equality with set to domain constraint' do
|
87
|
+
@expect.call(Gecode::Raw::SRT_NQ, @set2, nil)
|
88
|
+
@set.must_not == @set2
|
89
|
+
@model.solve!
|
90
|
+
end
|
91
|
+
|
92
|
+
it 'should constrain sets to be equality when not negated' do
|
93
|
+
@set.must == @set2
|
94
|
+
@model.solve!
|
95
|
+
@set.should have_bounds(0..1, 0..1)
|
96
|
+
@set2.should have_bounds(0..1, 0..1)
|
97
|
+
end
|
98
|
+
|
99
|
+
it 'should constrain sets to not be equal when negated' do
|
100
|
+
@set.must_not == @set2
|
101
|
+
union = @model.set_var([0, 1], [0, 1])
|
102
|
+
@set.must_not == union
|
103
|
+
@set2.must_not == union
|
104
|
+
@model.solve!
|
105
|
+
@set.should have_bounds([0], [0])
|
106
|
+
@set2.should have_bounds([1], [1])
|
107
|
+
end
|
108
|
+
|
109
|
+
it_should_behave_like 'reifiable set constraint'
|
110
|
+
end
|
111
|
+
|
112
|
+
describe Gecode::Constraints::Set::Relation, ' (elements)' do
|
113
|
+
include GecodeR::Specs::SetHelper
|
114
|
+
|
115
|
+
before do
|
116
|
+
@model = Gecode::Model.new
|
117
|
+
@set = @model.set_var([0], 0..2)
|
118
|
+
@int_var = @model.int_var(0..2)
|
119
|
+
@int_constant = 2
|
120
|
+
@model.branch_on @model.wrap_enum([@set])
|
121
|
+
@expect = lambda do |relation_type, rhs|
|
122
|
+
if rhs.kind_of? Fixnum
|
123
|
+
rhs = an_instance_of(Gecode::Raw::IntVar)
|
124
|
+
end
|
125
|
+
rhs = rhs.bind if rhs.respond_to? :bind
|
126
|
+
Gecode::Raw.should_receive(:rel).once.with(@model.active_space,
|
127
|
+
@set.bind, relation_type, rhs)
|
128
|
+
end
|
129
|
+
|
130
|
+
@invoke_options = lambda do |hash|
|
131
|
+
@set.elements.must_be.equal_to(@int_var, hash)
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
Gecode::Constraints::Util::RELATION_TYPES.each_pair do |relation, type|
|
136
|
+
it "should translate #{relation} with variable to relation constraint" do
|
137
|
+
@expect.call(type, @int_var)
|
138
|
+
@set.elements.must.send(relation, @int_var)
|
139
|
+
@model.solve!
|
140
|
+
end
|
141
|
+
|
142
|
+
it "should translate #{relation} with constant to relation constraint" do
|
143
|
+
@expect.call(type, @int_constant)
|
144
|
+
@set.elements.must.send(relation, @int_constant)
|
145
|
+
@model.solve!
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
Gecode::Constraints::Util::NEGATED_RELATION_TYPES.each_pair do |relation, type|
|
150
|
+
it "should translate negated #{relation} with variable to relation constraint" do
|
151
|
+
@expect.call(type, @int_var)
|
152
|
+
@set.elements.must_not.send(relation, @int_var)
|
153
|
+
@model.solve!
|
154
|
+
end
|
155
|
+
|
156
|
+
it "should translate negated #{relation} with constant to relation constraint" do
|
157
|
+
@expect.call(type, @int_constant)
|
158
|
+
@set.elements.must_not.send(relation, @int_constant)
|
159
|
+
@model.solve!
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
it 'should constrain the elements of the set' do
|
164
|
+
@set.elements.must <= @int_var
|
165
|
+
@int_var.must == 0
|
166
|
+
@model.solve!
|
167
|
+
@set.should be_assigned
|
168
|
+
@set.should include(0)
|
169
|
+
@set.should_not include(1,2)
|
170
|
+
end
|
171
|
+
|
172
|
+
it 'should constrain the elements of the set (constant parameter)' do
|
173
|
+
@set.elements.must <= 0
|
174
|
+
@model.solve!
|
175
|
+
@set.should be_assigned
|
176
|
+
@set.should include(0)
|
177
|
+
@set.should_not include(1,2)
|
178
|
+
end
|
179
|
+
|
180
|
+
it_should_behave_like 'non-reifiable set constraint'
|
181
|
+
end
|
data/specs/enum_wrapper.rb
CHANGED
@@ -80,11 +80,22 @@ end
|
|
80
80
|
describe Gecode::BoolEnumMethods do
|
81
81
|
before do
|
82
82
|
@model = Gecode::Model.new
|
83
|
-
@
|
83
|
+
@bool_enum = @model.bool_var_array(3)
|
84
84
|
end
|
85
85
|
|
86
86
|
it 'should convert to a bool var array' do
|
87
|
-
@
|
87
|
+
@bool_enum.to_bool_var_array.should be_kind_of(Gecode::Raw::BoolVarArray)
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
describe Gecode::SetEnumMethods do
|
92
|
+
before do
|
93
|
+
@model = Gecode::Model.new
|
94
|
+
@set_enum = @model.set_var_array(3, [0], 0..1)
|
95
|
+
end
|
96
|
+
|
97
|
+
it 'should convert to a set var array' do
|
98
|
+
@set_enum.to_set_var_array.should be_kind_of(Gecode::Raw::SetVarArray)
|
88
99
|
end
|
89
100
|
end
|
90
101
|
|