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,173 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../spec_helper'
|
2
|
+
require File.dirname(__FILE__) + '/constraint_helper'
|
3
|
+
|
4
|
+
class SortSampleProblem < Gecode::Model
|
5
|
+
attr :vars
|
6
|
+
attr :sorted
|
7
|
+
attr :indices
|
8
|
+
|
9
|
+
def initialize
|
10
|
+
@vars = int_var_array(4, 10..19)
|
11
|
+
@sorted = int_var_array(4, 10..19)
|
12
|
+
@indices = int_var_array(4, 0..9)
|
13
|
+
|
14
|
+
# To make it more interesting
|
15
|
+
@vars.must_be.distinct
|
16
|
+
|
17
|
+
branch_on @vars
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
describe Gecode::Constraints::IntEnum::Sort, ' (without :as and :order)' do
|
22
|
+
before do
|
23
|
+
@model = SortSampleProblem.new
|
24
|
+
@vars = @model.vars
|
25
|
+
@sorted = @model.sorted
|
26
|
+
|
27
|
+
@invoke_options = lambda do |hash|
|
28
|
+
@vars.must_be.sorted(hash)
|
29
|
+
@model.solve!
|
30
|
+
end
|
31
|
+
@expect_options = lambda do |strength, reif_var|
|
32
|
+
if reif_var.nil?
|
33
|
+
Gecode::Raw.should_receive(:rel).exactly(@vars.size - 1).times.with(
|
34
|
+
@model.active_space,
|
35
|
+
an_instance_of(Gecode::Raw::IntVar), Gecode::Raw::IRT_LQ,
|
36
|
+
an_instance_of(Gecode::Raw::IntVar), strength)
|
37
|
+
else
|
38
|
+
Gecode::Raw.should_receive(:rel).exactly(@vars.size - 1).times.with(
|
39
|
+
@model.active_space,
|
40
|
+
an_instance_of(Gecode::Raw::IntVar), Gecode::Raw::IRT_LQ,
|
41
|
+
an_instance_of(Gecode::Raw::IntVar),
|
42
|
+
an_instance_of(Gecode::Raw::BoolVar), strength)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
it 'should translate into n relation constraints' do
|
48
|
+
@expect_options.call(Gecode::Raw::ICL_DEF, nil)
|
49
|
+
@invoke_options.call({})
|
50
|
+
end
|
51
|
+
|
52
|
+
it 'should constraint variables to be sorted' do
|
53
|
+
@vars.must_be.sorted
|
54
|
+
values = @model.solve!.vars.map{ |x| x.val }
|
55
|
+
values.should == values.sort
|
56
|
+
end
|
57
|
+
|
58
|
+
it 'should allow negation' do
|
59
|
+
@vars.must_not_be.sorted
|
60
|
+
@model.solve!
|
61
|
+
values = @vars.map{ |x| x.val }
|
62
|
+
values.should_not == values.sort
|
63
|
+
end
|
64
|
+
|
65
|
+
it_should_behave_like 'constraint with options'
|
66
|
+
end
|
67
|
+
|
68
|
+
describe Gecode::Constraints::IntEnum::Sort, ' (with :as)' do
|
69
|
+
before do
|
70
|
+
@model = SortSampleProblem.new
|
71
|
+
@vars = @model.vars
|
72
|
+
@sorted = @model.sorted
|
73
|
+
|
74
|
+
# Make it a bit more interesting.
|
75
|
+
@vars[0].must > @vars[3] + 1
|
76
|
+
|
77
|
+
@invoke_options = lambda do |hash|
|
78
|
+
@vars.must_be.sorted hash.update(:as => @sorted)
|
79
|
+
@model.solve!
|
80
|
+
end
|
81
|
+
@expect_options = lambda do |strength, reif_var|
|
82
|
+
Gecode::Raw.should_receive(:sortedness).once.with(@model.active_space,
|
83
|
+
an_instance_of(Gecode::Raw::IntVarArray),
|
84
|
+
an_instance_of(Gecode::Raw::IntVarArray), strength)
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
it 'should translate into a sortedness constraints' do
|
89
|
+
@expect_options.call(Gecode::Raw::ICL_DEF, nil)
|
90
|
+
@invoke_options.call({})
|
91
|
+
end
|
92
|
+
|
93
|
+
it 'should constraint variables to be sorted' do
|
94
|
+
@vars.must_be.sorted(:as => @sorted)
|
95
|
+
@model.solve!
|
96
|
+
values = @sorted.map{ |x| x.val }
|
97
|
+
values.should == values.sort
|
98
|
+
end
|
99
|
+
|
100
|
+
it 'should not allow targets that are not int var enums' do
|
101
|
+
lambda{ @vars.must_be.sorted(:as => 'hello') }.should raise_error(TypeError)
|
102
|
+
end
|
103
|
+
|
104
|
+
it 'should not allow negation' do
|
105
|
+
lambda{ @vars.must_not_be.sorted(:as => @sorted) }.should raise_error(
|
106
|
+
Gecode::MissingConstraintError)
|
107
|
+
end
|
108
|
+
|
109
|
+
it_should_behave_like 'constraint with strength option'
|
110
|
+
end
|
111
|
+
|
112
|
+
describe Gecode::Constraints::IntEnum::Sort, ' (with :order)' do
|
113
|
+
before do
|
114
|
+
@model = SortSampleProblem.new
|
115
|
+
@vars = @model.vars
|
116
|
+
@sorted = @model.sorted
|
117
|
+
@indices = @model.indices
|
118
|
+
|
119
|
+
# Make it a bit more interesting.
|
120
|
+
@vars[0].must > @vars[3] + 1
|
121
|
+
|
122
|
+
@invoke_options = lambda do |hash|
|
123
|
+
@vars.must_be.sorted hash.update(:order => @indices, :as => @sorted)
|
124
|
+
@model.solve!
|
125
|
+
end
|
126
|
+
@expect_options = lambda do |strength, reif_var|
|
127
|
+
Gecode::Raw.should_receive(:sortedness).once.with(@model.active_space,
|
128
|
+
an_instance_of(Gecode::Raw::IntVarArray),
|
129
|
+
an_instance_of(Gecode::Raw::IntVarArray),
|
130
|
+
an_instance_of(Gecode::Raw::IntVarArray), strength)
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
it 'should translate into a sortedness constraints' do
|
135
|
+
@expect_options.call(Gecode::Raw::ICL_DEF, nil)
|
136
|
+
@invoke_options.call({})
|
137
|
+
end
|
138
|
+
|
139
|
+
it 'should translate into a sortedness constraints, even without a target' do
|
140
|
+
@expect_options.call(Gecode::Raw::ICL_DEF, nil)
|
141
|
+
@vars.must_be.sorted(:order => @indices)
|
142
|
+
@model.solve!
|
143
|
+
end
|
144
|
+
|
145
|
+
it 'should constraint variables to be sorted with the specified indices' do
|
146
|
+
@vars.must_be.sorted(:as => @sorted, :order => @indices)
|
147
|
+
@model.solve!
|
148
|
+
sorted_values = @sorted.map{ |x| x.val }
|
149
|
+
sorted_values.should == sorted_values.sort
|
150
|
+
expected_indices = @vars.map{ |v| sorted_values.index(v.val) }
|
151
|
+
@indices.map{ |i| i.val }.should == expected_indices
|
152
|
+
end
|
153
|
+
|
154
|
+
it 'should not allow targets that are not int var enums' do
|
155
|
+
lambda do
|
156
|
+
@vars.must_be.sorted(:as => 'hello', :order => @indices)
|
157
|
+
end.should raise_error(TypeError)
|
158
|
+
end
|
159
|
+
|
160
|
+
it 'should not allow order that are not int var enums' do
|
161
|
+
lambda do
|
162
|
+
@vars.must_be.sorted(:as => @sorted, :order => 'hello')
|
163
|
+
end.should raise_error(TypeError)
|
164
|
+
end
|
165
|
+
|
166
|
+
it 'should not allow negation' do
|
167
|
+
lambda do
|
168
|
+
@vars.must_not_be.sorted(:as => @sorted, :order => @indices)
|
169
|
+
end.should raise_error(Gecode::MissingConstraintError)
|
170
|
+
end
|
171
|
+
|
172
|
+
it_should_behave_like 'constraint with strength option'
|
173
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/spec_helper'
|
2
|
+
|
3
|
+
describe Gecode::Util::EnumMatrix do
|
4
|
+
before do
|
5
|
+
@matrix = Gecode::Util::EnumMatrix[[0, 1], [1, 0]]
|
6
|
+
end
|
7
|
+
|
8
|
+
it 'should be enumerable' do
|
9
|
+
@matrix.should be_kind_of(Enumerable)
|
10
|
+
end
|
11
|
+
|
12
|
+
it 'should produce rows that are enumerable' do
|
13
|
+
@matrix.row(0).should be_kind_of(Enumerable)
|
14
|
+
@matrix.row(0).inject([]){ |arr, e| arr << e }.should == [0, 1]
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'should produce columns that are enumerable' do
|
18
|
+
@matrix.column(0).should be_kind_of(Enumerable)
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'should produce submatrices that are enumerable' do
|
22
|
+
@matrix.minor(0,1,0,1).should be_kind_of(Enumerable)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
describe Gecode::Util::EnumMatrix, ' (when wrapped)' do
|
27
|
+
before do
|
28
|
+
@model = Gecode::Model.new
|
29
|
+
@matrix = @model.wrap_enum(Gecode::Util::EnumMatrix[[0, 1], [1, 0]])
|
30
|
+
end
|
31
|
+
|
32
|
+
it 'should produce rows that are wrapped' do
|
33
|
+
@matrix.row(0).should respond_to(:model)
|
34
|
+
end
|
35
|
+
|
36
|
+
it 'should produce columns that are enumerable' do
|
37
|
+
@matrix.column(0).should respond_to(:model)
|
38
|
+
end
|
39
|
+
|
40
|
+
it 'should produce submatrices that are enumerable' do
|
41
|
+
@matrix.minor(0,1,0,1).should respond_to(:model)
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,100 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/spec_helper'
|
2
|
+
|
3
|
+
describe Gecode::Model, ' (enum wrapping)' do
|
4
|
+
before do
|
5
|
+
@model = Gecode::Model.new
|
6
|
+
@bool = @model.bool_var
|
7
|
+
@int = @model.int_var(1..2)
|
8
|
+
end
|
9
|
+
|
10
|
+
it 'should only allow enumerables to be wrapped' do
|
11
|
+
lambda do
|
12
|
+
@model.wrap_enum(17)
|
13
|
+
end.should raise_error(TypeError)
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'should allow enumerables of bool variables to be wrapped' do
|
17
|
+
lambda do
|
18
|
+
enum = [@bool]
|
19
|
+
@model.wrap_enum(enum)
|
20
|
+
end.should_not raise_error
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'should allow enumerables of int variables to be wrapped' do
|
24
|
+
lambda do
|
25
|
+
enum = [@int]
|
26
|
+
@model.wrap_enum(enum)
|
27
|
+
end.should_not raise_error
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'should allow enumerables of fixnums to be wrapped' do
|
31
|
+
lambda do
|
32
|
+
enum = [17]
|
33
|
+
@model.wrap_enum(enum)
|
34
|
+
end.should_not raise_error
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'should not allow empty enumerables to be wrapped' do
|
38
|
+
lambda do
|
39
|
+
@model.wrap_enum([])
|
40
|
+
end.should raise_error(ArgumentError)
|
41
|
+
end
|
42
|
+
|
43
|
+
it 'should not allow enumerables without variables or fixnums to be wrapped' do
|
44
|
+
lambda do
|
45
|
+
@model.wrap_enum(['foo'])
|
46
|
+
end.should raise_error(TypeError)
|
47
|
+
end
|
48
|
+
|
49
|
+
it 'should not allow enumerables with only some variables to be wrapped' do
|
50
|
+
lambda do
|
51
|
+
enum = [@bool, 'foo']
|
52
|
+
@model.wrap_enum(enum)
|
53
|
+
end.should raise_error(TypeError)
|
54
|
+
end
|
55
|
+
|
56
|
+
it 'should not allow enumerables with mixed types of variables to be wrapped' do
|
57
|
+
lambda do
|
58
|
+
enum = [@bool, @int]
|
59
|
+
@model.wrap_enum(enum)
|
60
|
+
end.should raise_error(TypeError)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
describe Gecode::IntEnumMethods do
|
65
|
+
before do
|
66
|
+
@model = Gecode::Model.new
|
67
|
+
@int_enum = @model.int_var_array(3, 0..1)
|
68
|
+
end
|
69
|
+
|
70
|
+
it 'should convert to an int var array' do
|
71
|
+
@int_enum.to_int_var_array.should be_kind_of(Gecode::Raw::IntVarArray)
|
72
|
+
end
|
73
|
+
|
74
|
+
it 'should compute the smallest domain range' do
|
75
|
+
@int_enum.domain_range.should == (0..1)
|
76
|
+
(@int_enum << @model.int_var(-4..4)).domain_range.should == (-4..4)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
describe Gecode::BoolEnumMethods do
|
81
|
+
before do
|
82
|
+
@model = Gecode::Model.new
|
83
|
+
@int_enum = @model.bool_var_array(3)
|
84
|
+
end
|
85
|
+
|
86
|
+
it 'should convert to a bool var array' do
|
87
|
+
@int_enum.to_bool_var_array.should be_kind_of(Gecode::Raw::BoolVarArray)
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
describe Gecode::FixnumEnumMethods do
|
92
|
+
before do
|
93
|
+
@model = Gecode::Model.new
|
94
|
+
@enum = @model.instance_eval{ wrap_enum([7, 14, 17, 4711]) }
|
95
|
+
end
|
96
|
+
|
97
|
+
it 'should compute the smallest domain range' do
|
98
|
+
@enum.domain_range.should == (7..4711)
|
99
|
+
end
|
100
|
+
end
|
data/specs/int_var.rb
ADDED
@@ -0,0 +1,108 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/spec_helper'
|
2
|
+
|
3
|
+
describe 'non-empty int variable', :shared => true do
|
4
|
+
it 'should have min equal to the lower domain bound' do
|
5
|
+
@var.min.should equal(@domain.min)
|
6
|
+
end
|
7
|
+
|
8
|
+
it 'should have max equal to the upper domain bound' do
|
9
|
+
@var.max.should equal(@domain.max)
|
10
|
+
end
|
11
|
+
|
12
|
+
it 'should have size equal to the domain size' do
|
13
|
+
@var.size.should equal(@domain.size)
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'should contain every element in its domain' do
|
17
|
+
@domain.each do |i|
|
18
|
+
@var.should be_in(i)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
it 'should not contain elements outside its domain' do
|
23
|
+
@var.should_not be_in(@domain.min - 1)
|
24
|
+
@var.should_not be_in(@domain.max + 1)
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'should have a width equal to the domain width' do
|
28
|
+
@var.width.should equal(@domain.max - @domain.min + 1)
|
29
|
+
end
|
30
|
+
|
31
|
+
it 'should give a NoMethodError when calling a method that doesn\'t exist' do
|
32
|
+
lambda{ @var.this_method_does_not_exists }.should raise_error(NoMethodError)
|
33
|
+
end
|
34
|
+
|
35
|
+
it 'should have a zero degree' do
|
36
|
+
@var.degree.should be_zero
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
describe Gecode::FreeIntVar, ' (with range domain of size > 1)' do
|
41
|
+
before do
|
42
|
+
@range = -4..3
|
43
|
+
@domain = @range.to_a
|
44
|
+
model = Gecode::Model.new
|
45
|
+
@var = model.int_var(@range)
|
46
|
+
end
|
47
|
+
|
48
|
+
it_should_behave_like 'non-empty int variable'
|
49
|
+
|
50
|
+
it 'should not be assigned' do
|
51
|
+
@var.should_not be_assigned
|
52
|
+
end
|
53
|
+
|
54
|
+
it 'should have a range domain' do
|
55
|
+
@var.should be_range
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
describe Gecode::FreeIntVar, ' (defined with three-dot range)' do
|
60
|
+
before do
|
61
|
+
@range = -4...3
|
62
|
+
@domain = @range.to_a
|
63
|
+
model = Gecode::Model.new
|
64
|
+
@var = model.int_var(@range)
|
65
|
+
end
|
66
|
+
|
67
|
+
it_should_behave_like 'non-empty int variable'
|
68
|
+
end
|
69
|
+
|
70
|
+
describe Gecode::FreeIntVar, ' (with non-range domain of size > 1)' do
|
71
|
+
before do
|
72
|
+
@domain = [-3, -2, -1, 1]
|
73
|
+
model = Gecode::Model.new
|
74
|
+
@var = model.int_var(*@domain)
|
75
|
+
end
|
76
|
+
|
77
|
+
it_should_behave_like 'non-empty int variable'
|
78
|
+
|
79
|
+
it 'should not be assigned' do
|
80
|
+
@var.should_not be_assigned
|
81
|
+
end
|
82
|
+
|
83
|
+
it 'should not be a range domain' do
|
84
|
+
@var.should_not be_range
|
85
|
+
end
|
86
|
+
|
87
|
+
it 'should not contain the domain\'s holes' do
|
88
|
+
@var.should_not be_in(0)
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
describe Gecode::FreeIntVar, '(with a domain of size 1)' do
|
93
|
+
before do
|
94
|
+
@domain = [1]
|
95
|
+
model = Gecode::Model.new
|
96
|
+
@var = model.int_var(*@domain)
|
97
|
+
end
|
98
|
+
|
99
|
+
it_should_behave_like 'non-empty int variable'
|
100
|
+
|
101
|
+
it 'should be assigned' do
|
102
|
+
@var.should be_assigned
|
103
|
+
end
|
104
|
+
|
105
|
+
it 'should be a range domain' do
|
106
|
+
@var.should be_range
|
107
|
+
end
|
108
|
+
end
|
data/specs/model.rb
ADDED
@@ -0,0 +1,84 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/spec_helper'
|
2
|
+
|
3
|
+
describe Gecode::Model, ' (integer creation)' do
|
4
|
+
before do
|
5
|
+
@model = Gecode::Model.new
|
6
|
+
end
|
7
|
+
|
8
|
+
it 'should allow the creation of int variables with range' do
|
9
|
+
range = 0..3
|
10
|
+
@model.int_var(range).should have_domain(range)
|
11
|
+
end
|
12
|
+
|
13
|
+
# This currently fails, see specs/int_var for an explanation.
|
14
|
+
it 'should allow the creation of int variables with non-range domains' do
|
15
|
+
domain = [1, 3, 5]
|
16
|
+
@model.int_var(*domain).should have_domain(domain)
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'should allow the creation of int variables with single element domains' do
|
20
|
+
domain = 3
|
21
|
+
@model.int_var(domain).should have_domain([domain])
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'should not accept empty domains' do
|
25
|
+
lambda{ @model.int_var }.should raise_error(ArgumentError)
|
26
|
+
lambda{ @model.int_var_array(1) }.should raise_error(ArgumentError)
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'should allow the creation of int-var arrays with range domains' do
|
30
|
+
range = 0..3
|
31
|
+
count = 5
|
32
|
+
vars = @model.int_var_array(count, range)
|
33
|
+
vars.size.should equal(count)
|
34
|
+
vars.each{ |var| var.should have_domain(range) }
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'should allow the creation of int-var arrays with non-range domains' do
|
38
|
+
domain = [1,3,5]
|
39
|
+
count = 5
|
40
|
+
vars = @model.int_var_array(count, *domain)
|
41
|
+
vars.size.should equal(count)
|
42
|
+
vars.each{ |var| var.should have_domain(domain) }
|
43
|
+
end
|
44
|
+
|
45
|
+
it 'should allow the creation of int-var matrices with range domains' do
|
46
|
+
range = 0..3
|
47
|
+
rows = 5
|
48
|
+
columns = 4
|
49
|
+
vars = @model.int_var_matrix(rows, columns, range)
|
50
|
+
vars.row_size.should equal(rows)
|
51
|
+
vars.column_size.should equal(columns)
|
52
|
+
vars.each{ |var| var.should have_domain(range) }
|
53
|
+
end
|
54
|
+
|
55
|
+
it 'should allow the creation of int-var matrices with non-range domains' do
|
56
|
+
domain = [1,3,5]
|
57
|
+
rows = 5
|
58
|
+
columns = 4
|
59
|
+
vars = @model.int_var_matrix(rows, columns, *domain)
|
60
|
+
vars.row_size.should equal(rows)
|
61
|
+
vars.column_size.should equal(columns)
|
62
|
+
vars.each{ |var| var.should have_domain(domain) }
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
describe Gecode::Model, ' (bool creation)' do
|
67
|
+
before do
|
68
|
+
@model = Gecode::Model.new
|
69
|
+
end
|
70
|
+
|
71
|
+
it 'should allow the creation of boolean variables' do
|
72
|
+
@model.bool_var.should_not be_nil
|
73
|
+
end
|
74
|
+
|
75
|
+
it 'should allow the creation of arrays of boolean variables' do
|
76
|
+
@model.bool_var_array(3).size.should equal(3)
|
77
|
+
end
|
78
|
+
|
79
|
+
it 'should allow the creation of matrices of boolean variables' do
|
80
|
+
matrix = @model.bool_var_matrix(3, 4)
|
81
|
+
matrix.row_size.should equal(3)
|
82
|
+
matrix.column_size.should equal(4)
|
83
|
+
end
|
84
|
+
end
|
data/specs/search.rb
ADDED
@@ -0,0 +1,157 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/spec_helper'
|
2
|
+
require 'set'
|
3
|
+
|
4
|
+
class SampleProblem < Gecode::Model
|
5
|
+
attr :var
|
6
|
+
attr :array
|
7
|
+
attr :hash
|
8
|
+
attr :nested_enum
|
9
|
+
|
10
|
+
def initialize(domain)
|
11
|
+
vars = self.int_var_array(1,domain)
|
12
|
+
@var = vars.first
|
13
|
+
@var.must > 1
|
14
|
+
@array = [@var]
|
15
|
+
@hash = {:a => var}
|
16
|
+
@nested_enum = [1,2,[@var],[7, {:b => var}]]
|
17
|
+
|
18
|
+
branch_on vars, :variable => :smallest_size, :value => :min
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
describe Gecode::Model, ' (with multiple solutions)' do
|
23
|
+
before do
|
24
|
+
@domain = 0..3
|
25
|
+
@solved_domain = [2]
|
26
|
+
@model = SampleProblem.new(@domain)
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'should pass a solution to the block given in #solution' do
|
30
|
+
@model.solution do |s|
|
31
|
+
s.var.should have_domain(@solved_domain)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
it 'should only evaluate the block for one solution in #solution' do
|
36
|
+
i = 0
|
37
|
+
@model.solution{ |s| i += 1 }
|
38
|
+
i.should equal(1)
|
39
|
+
end
|
40
|
+
|
41
|
+
it 'should return the result of the block when calling #solution' do
|
42
|
+
@model.solution{ |s| 'test' }.should == 'test'
|
43
|
+
end
|
44
|
+
|
45
|
+
it 'should pass every solution to #each_solution' do
|
46
|
+
solutions = []
|
47
|
+
@model.each_solution do |s|
|
48
|
+
solutions << s.var.val
|
49
|
+
end
|
50
|
+
Set.new(solutions).should == Set.new([2,3])
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
describe Gecode::Model, ' (after #solve!)' do
|
55
|
+
before do
|
56
|
+
@domain = 0..3
|
57
|
+
@solved_domain = [2]
|
58
|
+
@model = SampleProblem.new(@domain)
|
59
|
+
@model.solve!
|
60
|
+
end
|
61
|
+
|
62
|
+
it 'should have updated the variables domains' do
|
63
|
+
@model.var.should have_domain(@solved_domain)
|
64
|
+
end
|
65
|
+
|
66
|
+
it 'should have updated variables in arrays' do
|
67
|
+
@model.array.first.should have_domain(@solved_domain)
|
68
|
+
end
|
69
|
+
|
70
|
+
it 'should have updated variables in hashes' do
|
71
|
+
@model.hash.values.first.should have_domain(@solved_domain)
|
72
|
+
end
|
73
|
+
|
74
|
+
it 'should have updated variables in nested enums' do
|
75
|
+
enum = @model.solve!.nested_enum
|
76
|
+
enum[2].first.should have_domain(@solved_domain)
|
77
|
+
enum[3][1][:b].should have_domain(@solved_domain)
|
78
|
+
|
79
|
+
enum = @model.nested_enum
|
80
|
+
enum[2].first.should have_domain(@solved_domain)
|
81
|
+
enum[3][1][:b].should have_domain(@solved_domain)
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
describe 'reset model', :shared => true do
|
86
|
+
it 'should have reset variables' do
|
87
|
+
@model.var.should have_domain(@reset_domain)
|
88
|
+
end
|
89
|
+
|
90
|
+
it 'should have reset variables in nested enums' do
|
91
|
+
enum = @model.nested_enum
|
92
|
+
enum[2].first.should have_domain(@reset_domain)
|
93
|
+
enum[3][1][:b].should have_domain(@reset_domain)
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
describe Gecode::Model, ' (after #reset!)' do
|
98
|
+
before do
|
99
|
+
@domain = 0..3
|
100
|
+
@reset_domain = 2..3
|
101
|
+
@model = SampleProblem.new(@domain)
|
102
|
+
@model.solve!
|
103
|
+
@model.reset!
|
104
|
+
end
|
105
|
+
|
106
|
+
it_should_behave_like 'reset model'
|
107
|
+
end
|
108
|
+
|
109
|
+
describe Gecode::Model, ' (after #solution)' do
|
110
|
+
before do
|
111
|
+
@domain = 0..3
|
112
|
+
@reset_domain = 2..3
|
113
|
+
@model = SampleProblem.new(@domain)
|
114
|
+
@model.solution{ |s| }
|
115
|
+
end
|
116
|
+
|
117
|
+
it_should_behave_like 'reset model'
|
118
|
+
end
|
119
|
+
|
120
|
+
describe Gecode::Model, ' (after #each_solution)' do
|
121
|
+
before do
|
122
|
+
@domain = 0..3
|
123
|
+
@reset_domain = 2..3
|
124
|
+
@model = SampleProblem.new(@domain)
|
125
|
+
@model.each_solution{ |s| }
|
126
|
+
end
|
127
|
+
|
128
|
+
it_should_behave_like 'reset model'
|
129
|
+
end
|
130
|
+
|
131
|
+
describe Gecode::Model, ' (without solution)' do
|
132
|
+
before do
|
133
|
+
@domain = 0..3
|
134
|
+
@model = SampleProblem.new(@domain)
|
135
|
+
@model.var.must < 0
|
136
|
+
end
|
137
|
+
|
138
|
+
it 'should return nil when calling #solution' do
|
139
|
+
@model.var.must < 0
|
140
|
+
@model.solution{ |s| 'test' }.should be_nil
|
141
|
+
end
|
142
|
+
|
143
|
+
it 'should return nil when calling #solve!' do
|
144
|
+
@model.solve!.should be_nil
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
describe Gecode::Model, ' (without constraints)' do
|
149
|
+
before do
|
150
|
+
@model = Gecode::Model.new
|
151
|
+
@x = @model.int_var(0..1)
|
152
|
+
end
|
153
|
+
|
154
|
+
it 'should produce a solution' do
|
155
|
+
@model.solve!.should_not be_nil
|
156
|
+
end
|
157
|
+
end
|