gecoder 0.3.0 → 0.4.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 +17 -2
- data/README +7 -1
- data/Rakefile +4 -0
- data/lib/gecoder/interface/constraints/bool/boolean.rb +1 -4
- data/lib/gecoder/interface/constraints/int/arithmetic.rb +77 -0
- data/lib/gecoder/interface/constraints/int/domain.rb +50 -0
- data/lib/gecoder/interface/constraints/int/linear.rb +12 -44
- data/lib/gecoder/interface/constraints/int_enum/arithmetic.rb +72 -0
- data/lib/gecoder/interface/constraints/int_enum/channel.rb +32 -0
- data/lib/gecoder/interface/constraints/int_enum/count.rb +90 -0
- data/lib/gecoder/interface/constraints/int_enum/distinct.rb +3 -8
- data/lib/gecoder/interface/constraints/int_enum/element.rb +75 -0
- data/lib/gecoder/interface/constraints/int_enum/equality.rb +31 -0
- data/lib/gecoder/interface/constraints/int_enum/sort.rb +104 -0
- data/lib/gecoder/interface/constraints/int_enum_constraints.rb +6 -0
- data/lib/gecoder/interface/constraints/int_var_constraints.rb +2 -0
- data/lib/gecoder/interface/constraints/reifiable_constraints.rb +21 -0
- data/lib/gecoder/interface/constraints.rb +57 -6
- data/lib/gecoder/interface/enum_matrix.rb +64 -0
- data/lib/gecoder/interface/enum_wrapper.rb +33 -5
- data/lib/gecoder/interface/model.rb +36 -6
- data/lib/gecoder/interface.rb +1 -0
- data/lib/gecoder/version.rb +4 -0
- data/lib/gecoder.rb +1 -0
- data/specs/binding_changes.rb +72 -0
- data/specs/bool_var.rb +20 -0
- data/specs/branch.rb +104 -0
- data/specs/constraints/arithmetic.rb +227 -0
- data/specs/constraints/boolean.rb +132 -0
- data/specs/constraints/channel.rb +55 -0
- data/specs/constraints/constraint_helper.rb +48 -0
- data/specs/constraints/constraints.rb +28 -0
- data/specs/constraints/count.rb +99 -0
- data/specs/constraints/distinct.rb +99 -0
- data/specs/constraints/domain.rb +56 -0
- data/specs/constraints/element.rb +128 -0
- data/specs/constraints/equality.rb +30 -0
- data/specs/constraints/linear.rb +166 -0
- data/specs/constraints/reification_sugar.rb +92 -0
- data/specs/constraints/relation.rb +72 -0
- data/specs/constraints/sort.rb +173 -0
- data/specs/enum_matrix.rb +43 -0
- data/specs/enum_wrapper.rb +100 -0
- data/specs/int_var.rb +108 -0
- data/specs/model.rb +84 -0
- data/specs/search.rb +157 -0
- data/specs/spec_helper.rb +63 -0
- data/specs/tmp +135 -0
- data/tasks/all_tasks.rb +1 -0
- data/tasks/distribution.rake +64 -0
- data/tasks/rcov.rake +17 -0
- data/tasks/specs.rake +16 -0
- data/tasks/svn.rake +11 -0
- data/tasks/website.rake +58 -0
- data/vendor/rust/include/rust_conversions.hh +1 -2
- metadata +53 -2
@@ -0,0 +1,56 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../spec_helper'
|
2
|
+
require File.dirname(__FILE__) + '/constraint_helper'
|
3
|
+
|
4
|
+
describe Gecode::Constraints::Int::Domain do
|
5
|
+
before do
|
6
|
+
@model = Gecode::Model.new
|
7
|
+
@domain = 0..3
|
8
|
+
@x = @model.int_var(@domain)
|
9
|
+
@range_domain = 1..2
|
10
|
+
@three_dot_range_domain = 1...2
|
11
|
+
@non_range_domain = [1, 3]
|
12
|
+
|
13
|
+
@invoke_options = lambda do |hash|
|
14
|
+
@x.must_be.in(@non_range_domain, hash)
|
15
|
+
@model.solve!
|
16
|
+
end
|
17
|
+
@expect_options = lambda do |strength, reif_var|
|
18
|
+
if reif_var.nil?
|
19
|
+
Gecode::Raw.should_receive(:dom).once.with(@model.active_space,
|
20
|
+
@x.bind, an_instance_of(Gecode::Raw::IntSet), strength)
|
21
|
+
else
|
22
|
+
Gecode::Raw.should_receive(:dom).once.with(@model.active_space,
|
23
|
+
@x.bind, an_instance_of(Gecode::Raw::IntSet),
|
24
|
+
an_instance_of(Gecode::Raw::BoolVar), strength)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'should translate domain constraints with range domains' do
|
30
|
+
Gecode::Raw.should_receive(:dom).once.with(@model.active_space,
|
31
|
+
@x.bind, @range_domain.first, @range_domain.last, Gecode::Raw::ICL_DEF)
|
32
|
+
@x.must_be.in @range_domain
|
33
|
+
@model.solve!
|
34
|
+
end
|
35
|
+
|
36
|
+
it 'should translate domain constraints with three dot range domains' do
|
37
|
+
Gecode::Raw.should_receive(:dom).once.with(@model.active_space,
|
38
|
+
@x.bind, @three_dot_range_domain.first, @three_dot_range_domain.last,
|
39
|
+
Gecode::Raw::ICL_DEF)
|
40
|
+
@x.must_be.in @three_dot_range_domain
|
41
|
+
@model.solve!
|
42
|
+
end
|
43
|
+
|
44
|
+
it 'should translate domain constraints with non-range domains' do
|
45
|
+
@expect_options.call(Gecode::Raw::ICL_DEF, nil)
|
46
|
+
@invoke_options.call({})
|
47
|
+
end
|
48
|
+
|
49
|
+
it 'should handle negation' do
|
50
|
+
@x.must_not_be.in @range_domain
|
51
|
+
@model.solve!
|
52
|
+
@x.should have_domain(@domain.to_a - @range_domain.to_a)
|
53
|
+
end
|
54
|
+
|
55
|
+
it_should_behave_like 'constraint with options'
|
56
|
+
end
|
@@ -0,0 +1,128 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../spec_helper'
|
2
|
+
require File.dirname(__FILE__) + '/constraint_helper'
|
3
|
+
|
4
|
+
class ElementSampleProblem < Gecode::Model
|
5
|
+
attr :prices
|
6
|
+
attr :store
|
7
|
+
attr :price
|
8
|
+
attr :fixnum_prices
|
9
|
+
|
10
|
+
def initialize
|
11
|
+
prices = [17, 63, 45, 63]
|
12
|
+
@fixnum_prices = wrap_enum(prices)
|
13
|
+
@prices = int_var_array(4, *prices)
|
14
|
+
@store = int_var(0...prices.size)
|
15
|
+
@price = int_var(*prices)
|
16
|
+
branch_on wrap_enum([@store])
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
describe Gecode::Constraints::IntEnum::Element do
|
21
|
+
before do
|
22
|
+
@model = ElementSampleProblem.new
|
23
|
+
@prices = @model.prices
|
24
|
+
@price = @model.price
|
25
|
+
@store = @model.store
|
26
|
+
@fixnum_prices = @model.fixnum_prices
|
27
|
+
|
28
|
+
# For constraint option spec.
|
29
|
+
@invoke_options = lambda do |hash|
|
30
|
+
@prices[@store].must_be.greater_than(@price, hash)
|
31
|
+
@model.solve!
|
32
|
+
end
|
33
|
+
@expect_options = lambda do |strength, reif_var|
|
34
|
+
if reif_var.nil?
|
35
|
+
Gecode::Raw.should_receive(:element).once.with(@model.active_space,
|
36
|
+
an_instance_of(Gecode::Raw::IntVarArray),
|
37
|
+
an_instance_of(Gecode::Raw::IntVar),
|
38
|
+
an_instance_of(Gecode::Raw::IntVar), an_instance_of(Fixnum))
|
39
|
+
Gecode::Raw.should_receive(:rel).once.with(@model.active_space,
|
40
|
+
an_instance_of(Gecode::Raw::IntVar), Gecode::Raw::IRT_GR,
|
41
|
+
an_instance_of(Gecode::Raw::IntVar), strength)
|
42
|
+
else
|
43
|
+
Gecode::Raw.should_receive(:element).once.with(@model.active_space,
|
44
|
+
an_instance_of(Gecode::Raw::IntVarArray),
|
45
|
+
an_instance_of(Gecode::Raw::IntVar),
|
46
|
+
an_instance_of(Gecode::Raw::IntVar), an_instance_of(Fixnum))
|
47
|
+
Gecode::Raw.should_receive(:rel).once.with(@model.active_space,
|
48
|
+
an_instance_of(Gecode::Raw::IntVar), Gecode::Raw::IRT_GR,
|
49
|
+
an_instance_of(Gecode::Raw::IntVar),
|
50
|
+
an_instance_of(Gecode::Raw::BoolVar), strength)
|
51
|
+
end
|
52
|
+
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
|
+
|
71
|
+
Gecode::Constraints::Util::NEGATED_RELATION_TYPES.each_pair do |relation, type|
|
72
|
+
it "should translate negated #{relation} with variable right hand side" do
|
73
|
+
Gecode::Raw.should_receive(:element).once.with(@model.active_space,
|
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)
|
81
|
+
@model.solve!
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
Gecode::Constraints::Util::RELATION_TYPES.each_pair do |relation, type|
|
86
|
+
it "should translate #{relation} with constant right hand side" do
|
87
|
+
Gecode::Raw.should_receive(:element).once.with(@model.active_space,
|
88
|
+
an_instance_of(Gecode::Raw::IntVarArray),
|
89
|
+
an_instance_of(Gecode::Raw::IntVar),
|
90
|
+
an_instance_of(Gecode::Raw::IntVar), Gecode::Raw::ICL_DEF)
|
91
|
+
unless type == Gecode::Raw::IRT_EQ
|
92
|
+
Gecode::Raw.should_receive(:rel).once.with(@model.active_space,
|
93
|
+
an_instance_of(Gecode::Raw::IntVar), type, 5, an_instance_of(Fixnum))
|
94
|
+
end
|
95
|
+
@prices[@store].must.send(relation, 5)
|
96
|
+
@model.solve!
|
97
|
+
end
|
98
|
+
end
|
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!
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
it 'should not disturb normal array access' do
|
114
|
+
@fixnum_prices[2].should_not be_nil
|
115
|
+
@prices[2].should_not be_nil
|
116
|
+
end
|
117
|
+
|
118
|
+
it 'should handle fixnum enums as enumeration' do
|
119
|
+
@fixnum_prices[@store].must == @fixnum_prices[2]
|
120
|
+
@model.solve!.store.val.should equal(2)
|
121
|
+
end
|
122
|
+
|
123
|
+
it 'should raise error on right hand sides of the wrong type' do
|
124
|
+
lambda{ @prices[@store].must == 'hello' }.should raise_error(TypeError)
|
125
|
+
end
|
126
|
+
|
127
|
+
it_should_behave_like 'constraint with options'
|
128
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../spec_helper'
|
2
|
+
require File.dirname(__FILE__) + '/constraint_helper'
|
3
|
+
|
4
|
+
describe Gecode::Constraints::IntEnum::Equality do
|
5
|
+
before do
|
6
|
+
@model = Gecode::Model.new
|
7
|
+
@vars = @model.int_var_array(4, -2..2)
|
8
|
+
@invoke_options = lambda do |hash|
|
9
|
+
@vars.must_be.equal(hash)
|
10
|
+
@model.solve!
|
11
|
+
end
|
12
|
+
@expect_options = lambda do |strength, reif_var|
|
13
|
+
Gecode::Raw.should_receive(:eq).once.with(@model.active_space,
|
14
|
+
anything, strength)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
it 'should translate equality constraints' do
|
19
|
+
@expect_options.call(Gecode::Raw::ICL_DEF, nil)
|
20
|
+
@invoke_options.call({})
|
21
|
+
@vars.must_be.equal
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'should not allow negation' do
|
25
|
+
lambda{ @vars.must_not_be.equal }.should raise_error(
|
26
|
+
Gecode::MissingConstraintError)
|
27
|
+
end
|
28
|
+
|
29
|
+
it_should_behave_like 'constraint with strength option'
|
30
|
+
end
|
@@ -0,0 +1,166 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../spec_helper'
|
2
|
+
require File.dirname(__FILE__) + '/constraint_helper'
|
3
|
+
|
4
|
+
class LinearSampleProblem < Gecode::Model
|
5
|
+
attr :x
|
6
|
+
attr :y
|
7
|
+
attr :z
|
8
|
+
|
9
|
+
def initialize(x_dom, y_dom, z_dom)
|
10
|
+
@x = self.int_var(x_dom)
|
11
|
+
@y = self.int_var(y_dom)
|
12
|
+
@z = self.int_var(z_dom)
|
13
|
+
branch_on wrap_enum([@x, @y, @z])
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
describe Gecode::Constraints::Int::Linear do
|
18
|
+
before do
|
19
|
+
@x_dom = 0..2
|
20
|
+
@y_dom = -3..3
|
21
|
+
@z_dom = 0..10
|
22
|
+
@model = LinearSampleProblem.new(@x_dom, @y_dom, @z_dom)
|
23
|
+
@x = @model.x
|
24
|
+
@y = @model.y
|
25
|
+
@z = @model.z
|
26
|
+
|
27
|
+
# For constraint option spec.
|
28
|
+
@invoke_options = lambda do |hash|
|
29
|
+
(@x + @y).must_be.greater_than(@z, hash)
|
30
|
+
@model.solve!
|
31
|
+
end
|
32
|
+
@expect_options = lambda do |strength, reif_var|
|
33
|
+
# TODO: this is hard to spec from this level.
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'should handle addition with a variable' do
|
38
|
+
(@x + @y).must == 0
|
39
|
+
sol = @model.solve!
|
40
|
+
x = sol.x.val
|
41
|
+
y = sol.y.val
|
42
|
+
(x + y).should be_zero
|
43
|
+
end
|
44
|
+
|
45
|
+
it 'should handle addition with multiple variables' do
|
46
|
+
(@x + @y + @z).must == 0
|
47
|
+
sol = @model.solve!
|
48
|
+
x = sol.x.val
|
49
|
+
y = sol.y.val
|
50
|
+
z = sol.z.val
|
51
|
+
(x + y + z).should be_zero
|
52
|
+
end
|
53
|
+
|
54
|
+
it 'should handle subtraction with a variable' do
|
55
|
+
(@x - @y).must == 0
|
56
|
+
sol = @model.solve!
|
57
|
+
x = sol.x.val
|
58
|
+
y = sol.y.val
|
59
|
+
(x - y).should be_zero
|
60
|
+
end
|
61
|
+
|
62
|
+
it 'should handle non-zero constants as right hand side' do
|
63
|
+
(@x + @y).must == 1
|
64
|
+
sol = @model.solve!
|
65
|
+
x = sol.x.val
|
66
|
+
y = sol.y.val
|
67
|
+
(x + y).should equal(1)
|
68
|
+
end
|
69
|
+
|
70
|
+
it 'should handle variables as right hand side' do
|
71
|
+
(@x + @y).must == @z
|
72
|
+
sol = @model.solve!
|
73
|
+
x = sol.x.val
|
74
|
+
y = sol.y.val
|
75
|
+
z = sol.z.val
|
76
|
+
(x + y).should equal(z)
|
77
|
+
end
|
78
|
+
|
79
|
+
it 'should handle linear expressions as right hand side' do
|
80
|
+
(@x + @y).must == @z + @y
|
81
|
+
sol = @model.solve!
|
82
|
+
x = sol.x.val
|
83
|
+
y = sol.y.val
|
84
|
+
z = sol.z.val
|
85
|
+
(x + y).should equal(z + y)
|
86
|
+
end
|
87
|
+
|
88
|
+
it 'should raise error on invalid right hand sides' do
|
89
|
+
lambda{ ((@x + @y).must == 'z') }.should raise_error(TypeError)
|
90
|
+
end
|
91
|
+
|
92
|
+
it 'should handle coefficients other than 1' do
|
93
|
+
(@x * 2 + @y).must == 0
|
94
|
+
sol = @model.solve!
|
95
|
+
x = sol.x.val
|
96
|
+
y = sol.y.val
|
97
|
+
(2*x + y).should equal(0)
|
98
|
+
end
|
99
|
+
|
100
|
+
it 'should handle addition with constants' do
|
101
|
+
(@y + 2).must == 1
|
102
|
+
sol = @model.solve!
|
103
|
+
y = sol.y.val
|
104
|
+
(y + 2).should equal(1)
|
105
|
+
end
|
106
|
+
|
107
|
+
it 'should handle subtraction with a constant' do
|
108
|
+
(@x - 2).must == 0
|
109
|
+
sol = @model.solve!
|
110
|
+
x = sol.x.val
|
111
|
+
(x - 2).should be_zero
|
112
|
+
end
|
113
|
+
|
114
|
+
it 'should a single variable as left hande side' do
|
115
|
+
@x.must == @y + @z
|
116
|
+
sol = @model.solve!
|
117
|
+
x = sol.x.val
|
118
|
+
y = sol.y.val
|
119
|
+
z = sol.z.val
|
120
|
+
x.should equal(y + z)
|
121
|
+
end
|
122
|
+
|
123
|
+
it 'should handle parenthesis' do
|
124
|
+
(@x - (@y + @z)).must == 1
|
125
|
+
sol = @model.solve!
|
126
|
+
x = sol.x.val
|
127
|
+
y = sol.y.val
|
128
|
+
z = sol.z.val
|
129
|
+
(x - (y + z)).should equal(1)
|
130
|
+
end
|
131
|
+
|
132
|
+
it 'should handle multiplication of parenthesis' do
|
133
|
+
(((@x + @y*10)*10 + @z)*10).must == 0
|
134
|
+
sol = @model.solve!
|
135
|
+
x = sol.x.val
|
136
|
+
y = sol.y.val
|
137
|
+
z = sol.z.val
|
138
|
+
(((x + y*10)*10 + z)*10).should equal(0)
|
139
|
+
end
|
140
|
+
|
141
|
+
relations = ['>', '>=', '<', '<=', '==']
|
142
|
+
|
143
|
+
relations.each do |relation|
|
144
|
+
it "should handle #{relation} with constant integers" do
|
145
|
+
(@x + @y).must.send(relation, 1)
|
146
|
+
sol = @model.solve!
|
147
|
+
sol.should_not be_nil
|
148
|
+
(sol.x.val + sol.y.val).should.send(relation, 1)
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
relations.each do |relation|
|
153
|
+
it "should handle negated #{relation} with constant integers" do
|
154
|
+
(@x + @y).must_not.send(relation, 1)
|
155
|
+
sol = @model.solve!
|
156
|
+
sol.should_not be_nil
|
157
|
+
(sol.x.val + sol.y.val).should_not.send(relation, 1)
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
it 'should not interfere with other defined multiplication methods' do
|
162
|
+
(@x * :foo).should be_nil
|
163
|
+
end
|
164
|
+
|
165
|
+
it_should_behave_like 'constraint with options'
|
166
|
+
end
|
@@ -0,0 +1,92 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../spec_helper'
|
2
|
+
|
3
|
+
class ReifSugarSampleProblem < Gecode::Model
|
4
|
+
attr :x
|
5
|
+
attr :y
|
6
|
+
attr :z
|
7
|
+
|
8
|
+
def initialize
|
9
|
+
@x = int_var(0..1)
|
10
|
+
@y = int_var(1..2)
|
11
|
+
@z = int_var(3..4)
|
12
|
+
branch_on wrap_enum([@x, @y, @z])
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
describe Gecode::Constraints::ReifiableConstraint do
|
17
|
+
before do
|
18
|
+
@model = ReifSugarSampleProblem.new
|
19
|
+
@x = @model.x
|
20
|
+
@y = @model.y
|
21
|
+
@z = @model.z
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'should fail disjunctions if neither side can be satisfied' do
|
25
|
+
(@x.must == 3) | (@y.must == 3)
|
26
|
+
@model.solve!.should be_nil
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'should translate disjunctions' do
|
30
|
+
Gecode::Raw.should_receive(:rel).once.with(@model.active_space,
|
31
|
+
an_instance_of(Gecode::Raw::IntVar), Gecode::Raw::IRT_GR, 0,
|
32
|
+
an_instance_of(Gecode::Raw::BoolVar), Gecode::Raw::ICL_DEF)
|
33
|
+
Gecode::Raw.should_receive(:rel).once.with(@model.active_space,
|
34
|
+
an_instance_of(Gecode::Raw::IntVar), Gecode::Raw::IRT_EQ, 3,
|
35
|
+
an_instance_of(Gecode::Raw::BoolVar), Gecode::Raw::ICL_DEF)
|
36
|
+
(@x.must > 0) | (@y.must == 3)
|
37
|
+
sol = @model.solve!
|
38
|
+
end
|
39
|
+
|
40
|
+
it 'should solve disjunctions' do
|
41
|
+
(@x.must > 0) | (@y.must == 3)
|
42
|
+
sol = @model.solve!
|
43
|
+
sol.should_not be_nil
|
44
|
+
sol.x.should have_domain([1])
|
45
|
+
end
|
46
|
+
|
47
|
+
it 'should fail conjunctions if one side can\'t be satisfied' do
|
48
|
+
(@x.must > 3) & (@y.must == 3)
|
49
|
+
@model.solve!.should be_nil
|
50
|
+
end
|
51
|
+
|
52
|
+
it 'should translate conjunctions' do
|
53
|
+
Gecode::Raw.should_receive(:rel).once.with(@model.active_space,
|
54
|
+
an_instance_of(Gecode::Raw::IntVar), Gecode::Raw::IRT_GR, 0,
|
55
|
+
an_instance_of(Gecode::Raw::BoolVar), Gecode::Raw::ICL_DEF)
|
56
|
+
Gecode::Raw.should_receive(:rel).once.with(@model.active_space,
|
57
|
+
an_instance_of(Gecode::Raw::IntVar), Gecode::Raw::IRT_EQ, 2,
|
58
|
+
an_instance_of(Gecode::Raw::BoolVar), Gecode::Raw::ICL_DEF)
|
59
|
+
(@x.must > 0) & (@y.must == 2)
|
60
|
+
sol = @model.solve!
|
61
|
+
end
|
62
|
+
|
63
|
+
it 'should solve conjunctions' do
|
64
|
+
(@x.must > 0) & (@y.must == 2)
|
65
|
+
sol = @model.solve!
|
66
|
+
sol.should_not be_nil
|
67
|
+
sol.x.should have_domain([1])
|
68
|
+
sol.y.should have_domain([2])
|
69
|
+
end
|
70
|
+
|
71
|
+
it 'should handle the same variable being used multiple times' do
|
72
|
+
(@z.must == 4) | (@z.must == 4)
|
73
|
+
sol = @model.solve!
|
74
|
+
sol.should_not be_nil
|
75
|
+
sol.z.should have_domain([4])
|
76
|
+
end
|
77
|
+
|
78
|
+
it 'should handle nested operations' do
|
79
|
+
((@x.must > 3) & (@y.must == 2)) | (@z.must == 4) | (
|
80
|
+
(@x.must == 0) & (@z.must == 4))
|
81
|
+
sol = @model.solve!
|
82
|
+
sol.should_not be_nil
|
83
|
+
sol.x.should have_domain([0])
|
84
|
+
sol.z.should have_domain([4])
|
85
|
+
end
|
86
|
+
|
87
|
+
it 'should handle negations' do
|
88
|
+
(@z.must_not == 4) & (@z.must == 4)
|
89
|
+
sol = @model.solve!
|
90
|
+
sol.should be_nil
|
91
|
+
end
|
92
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../spec_helper'
|
2
|
+
require File.dirname(__FILE__) + '/constraint_helper'
|
3
|
+
|
4
|
+
describe Gecode::Constraints::Int::Linear, ' (simple ones)' do
|
5
|
+
before do
|
6
|
+
@model = Gecode::Model.new
|
7
|
+
@x = @model.int_var(1..2)
|
8
|
+
@int = 4
|
9
|
+
@y = @model.int_var(1..2)
|
10
|
+
|
11
|
+
# For constraint option spec.
|
12
|
+
@invoke_options = lambda do |hash|
|
13
|
+
@x.must_be.greater_than(3, hash)
|
14
|
+
@model.solve!
|
15
|
+
end
|
16
|
+
@expect_options = lambda do |strength, reif_var|
|
17
|
+
if reif_var.nil?
|
18
|
+
Gecode::Raw.should_receive(:rel).once.with(@model.active_space,
|
19
|
+
anything, Gecode::Raw::IRT_GR, anything,
|
20
|
+
strength)
|
21
|
+
else
|
22
|
+
Gecode::Raw.should_receive(:rel).once.with(@model.active_space,
|
23
|
+
an_instance_of(Gecode::Raw::IntVar), Gecode::Raw::IRT_GR, anything,
|
24
|
+
an_instance_of(Gecode::Raw::BoolVar), strength)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
Gecode::Constraints::Util::RELATION_TYPES.each_pair do |relation, type|
|
30
|
+
it "should translate #{relation} with constant to simple relation" do
|
31
|
+
Gecode::Raw.should_receive(:rel).once.with(@model.active_space,
|
32
|
+
an_instance_of(Gecode::Raw::IntVar), type, @int, Gecode::Raw::ICL_DEF)
|
33
|
+
@x.must.send(relation, @int)
|
34
|
+
@model.solve!
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
Gecode::Constraints::Util::NEGATED_RELATION_TYPES.each_pair do |relation, type|
|
39
|
+
it "should translate negated #{relation} with constant to simple relation" do
|
40
|
+
Gecode::Raw.should_receive(:rel).once.with(@model.active_space,
|
41
|
+
an_instance_of(Gecode::Raw::IntVar), type, @int, Gecode::Raw::ICL_DEF)
|
42
|
+
@x.must_not.send(relation, @int)
|
43
|
+
@model.solve!
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
Gecode::Constraints::Util::RELATION_TYPES.each_pair do |relation, type|
|
48
|
+
it "should translate #{relation} with variables to simple relation" do
|
49
|
+
Gecode::Raw.should_receive(:rel).once.with(@model.active_space,
|
50
|
+
an_instance_of(Gecode::Raw::IntVar), type,
|
51
|
+
an_instance_of(Gecode::Raw::IntVar), Gecode::Raw::ICL_DEF)
|
52
|
+
@x.must.send(relation, @y)
|
53
|
+
@model.solve!
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
Gecode::Constraints::Util::NEGATED_RELATION_TYPES.each_pair do |relation, type|
|
58
|
+
it "should translate negated #{relation} with variable to simple relation" do
|
59
|
+
Gecode::Raw.should_receive(:rel).once.with(@model.active_space,
|
60
|
+
an_instance_of(Gecode::Raw::IntVar), type,
|
61
|
+
an_instance_of(Gecode::Raw::IntVar), Gecode::Raw::ICL_DEF)
|
62
|
+
@x.must_not.send(relation, @y)
|
63
|
+
@model.solve!
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
it 'should raise error on arguments of the wrong type' do
|
68
|
+
lambda{ @x.must == 'hello' }.should raise_error(TypeError)
|
69
|
+
end
|
70
|
+
|
71
|
+
it_should_behave_like 'constraint with options'
|
72
|
+
end
|