gecoder-with-gecode 0.9.0-x86-mswin32-60
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 +137 -0
- data/COPYING +17 -0
- data/LGPL-LICENSE +458 -0
- data/README +58 -0
- data/Rakefile +14 -0
- data/example/equation_system.rb +15 -0
- data/example/example_helper.rb +1 -0
- data/example/magic_sequence.rb +43 -0
- data/example/money.rb +36 -0
- data/example/queens.rb +42 -0
- data/example/send_more_money.rb +43 -0
- data/example/send_most_money.rb +58 -0
- data/example/square_tiling.rb +84 -0
- data/example/sudoku-set.rb +106 -0
- data/example/sudoku.rb +56 -0
- data/lib/gecode.dll +0 -0
- data/lib/gecoder.rb +5 -0
- data/lib/gecoder/bindings.rb +96 -0
- data/lib/gecoder/bindings/bindings.rb +2029 -0
- data/lib/gecoder/interface.rb +9 -0
- data/lib/gecoder/interface/binding_changes.rb +9 -0
- data/lib/gecoder/interface/branch.rb +163 -0
- data/lib/gecoder/interface/constraints.rb +471 -0
- data/lib/gecoder/interface/constraints/bool/boolean.rb +251 -0
- data/lib/gecoder/interface/constraints/bool/channel.rb +7 -0
- data/lib/gecoder/interface/constraints/bool/linear.rb +200 -0
- data/lib/gecoder/interface/constraints/bool_enum/channel.rb +68 -0
- data/lib/gecoder/interface/constraints/bool_enum/extensional.rb +106 -0
- data/lib/gecoder/interface/constraints/bool_enum/relation.rb +55 -0
- data/lib/gecoder/interface/constraints/bool_enum_constraints.rb +84 -0
- data/lib/gecoder/interface/constraints/bool_var_constraints.rb +155 -0
- data/lib/gecoder/interface/constraints/extensional_regexp.rb +101 -0
- 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 +150 -0
- data/lib/gecoder/interface/constraints/int/channel.rb +51 -0
- data/lib/gecoder/interface/constraints/int/domain.rb +80 -0
- data/lib/gecoder/interface/constraints/int/linear.rb +143 -0
- data/lib/gecoder/interface/constraints/int/relation.rb +141 -0
- data/lib/gecoder/interface/constraints/int_enum/arithmetic.rb +63 -0
- data/lib/gecoder/interface/constraints/int_enum/channel.rb +86 -0
- data/lib/gecoder/interface/constraints/int_enum/count.rb +66 -0
- data/lib/gecoder/interface/constraints/int_enum/distinct.rb +64 -0
- data/lib/gecoder/interface/constraints/int_enum/element.rb +64 -0
- data/lib/gecoder/interface/constraints/int_enum/equality.rb +37 -0
- data/lib/gecoder/interface/constraints/int_enum/extensional.rb +187 -0
- data/lib/gecoder/interface/constraints/int_enum/sort.rb +135 -0
- data/lib/gecoder/interface/constraints/int_enum_constraints.rb +95 -0
- data/lib/gecoder/interface/constraints/int_var_constraints.rb +230 -0
- data/lib/gecoder/interface/constraints/reifiable_constraints.rb +78 -0
- 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 +65 -0
- data/lib/gecoder/interface/constraints/set/channel.rb +51 -0
- data/lib/gecoder/interface/constraints/set/connection.rb +130 -0
- data/lib/gecoder/interface/constraints/set/domain.rb +156 -0
- data/lib/gecoder/interface/constraints/set/include.rb +36 -0
- data/lib/gecoder/interface/constraints/set/operation.rb +118 -0
- data/lib/gecoder/interface/constraints/set/relation.rb +155 -0
- 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 +45 -0
- data/lib/gecoder/interface/constraints/set_enum/distinct.rb +43 -0
- data/lib/gecoder/interface/constraints/set_enum/operation.rb +69 -0
- data/lib/gecoder/interface/constraints/set_enum/select.rb +79 -0
- data/lib/gecoder/interface/constraints/set_enum_constraints.rb +84 -0
- data/lib/gecoder/interface/constraints/set_var_constraints.rb +243 -0
- data/lib/gecoder/interface/enum_matrix.rb +64 -0
- data/lib/gecoder/interface/enum_wrapper.rb +205 -0
- data/lib/gecoder/interface/model.rb +453 -0
- data/lib/gecoder/interface/model_sugar.rb +84 -0
- data/lib/gecoder/interface/search.rb +197 -0
- data/lib/gecoder/interface/variables.rb +306 -0
- data/lib/gecoder/version.rb +4 -0
- data/specs/bool_var.rb +81 -0
- data/specs/branch.rb +185 -0
- data/specs/constraints/bool/boolean.rb +317 -0
- 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/bool_enum/extensional.rb +225 -0
- data/specs/constraints/constraint_helper.rb +234 -0
- data/specs/constraints/constraint_receivers.rb +103 -0
- data/specs/constraints/constraints.rb +26 -0
- 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 +69 -0
- 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/distribution.rb +14 -0
- data/specs/enum_matrix.rb +43 -0
- data/specs/enum_wrapper.rb +179 -0
- data/specs/examples.rb +17 -0
- data/specs/int_var.rb +163 -0
- data/specs/logging.rb +24 -0
- data/specs/model.rb +325 -0
- data/specs/model_sugar.rb +30 -0
- data/specs/search.rb +383 -0
- data/specs/selected_set.rb +39 -0
- data/specs/set_elements.rb +34 -0
- data/specs/set_var.rb +82 -0
- data/specs/spec_helper.rb +265 -0
- data/tasks/all_tasks.rb +1 -0
- data/tasks/dependencies.txt +22 -0
- data/tasks/distribution.rake +194 -0
- data/tasks/rcov.rake +18 -0
- data/tasks/specs.rake +21 -0
- data/tasks/svn.rake +16 -0
- data/tasks/website.rake +51 -0
- data/vendor/gecode/win32/lib/libgecodeint.dll +0 -0
- data/vendor/gecode/win32/lib/libgecodekernel.dll +0 -0
- data/vendor/gecode/win32/lib/libgecodeminimodel.dll +0 -0
- data/vendor/gecode/win32/lib/libgecodesearch.dll +0 -0
- data/vendor/gecode/win32/lib/libgecodeset.dll +0 -0
- data/vendor/gecode/win32/lib/libgecodesupport.dll +0 -0
- data/vendor/rust/README +28 -0
- data/vendor/rust/bin/cxxgenerator.rb +93 -0
- data/vendor/rust/include/rust_checks.hh +116 -0
- data/vendor/rust/include/rust_conversions.hh +102 -0
- data/vendor/rust/rust.rb +67 -0
- data/vendor/rust/rust/attribute.rb +51 -0
- data/vendor/rust/rust/bindings.rb +172 -0
- data/vendor/rust/rust/class.rb +337 -0
- data/vendor/rust/rust/constants.rb +48 -0
- data/vendor/rust/rust/container.rb +110 -0
- data/vendor/rust/rust/cppifaceparser.rb +129 -0
- data/vendor/rust/rust/cwrapper.rb +72 -0
- data/vendor/rust/rust/cxxclass.rb +96 -0
- data/vendor/rust/rust/element.rb +81 -0
- data/vendor/rust/rust/enum.rb +63 -0
- data/vendor/rust/rust/function.rb +407 -0
- data/vendor/rust/rust/namespace.rb +61 -0
- data/vendor/rust/rust/templates/AttributeDefinition.rusttpl +17 -0
- data/vendor/rust/rust/templates/AttributeInitBinding.rusttpl +9 -0
- data/vendor/rust/rust/templates/BindingsHeader.rusttpl +24 -0
- data/vendor/rust/rust/templates/BindingsUnit.rusttpl +46 -0
- data/vendor/rust/rust/templates/CWrapperClassDefinitions.rusttpl +64 -0
- data/vendor/rust/rust/templates/ClassDeclarations.rusttpl +7 -0
- data/vendor/rust/rust/templates/ClassInitialize.rusttpl +6 -0
- data/vendor/rust/rust/templates/ConstructorStub.rusttpl +21 -0
- data/vendor/rust/rust/templates/CxxClassDefinitions.rusttpl +100 -0
- data/vendor/rust/rust/templates/CxxMethodStub.rusttpl +12 -0
- data/vendor/rust/rust/templates/CxxStandaloneClassDefinitions.rusttpl +26 -0
- data/vendor/rust/rust/templates/EnumDeclarations.rusttpl +3 -0
- data/vendor/rust/rust/templates/EnumDefinitions.rusttpl +29 -0
- data/vendor/rust/rust/templates/FunctionDefinition.rusttpl +9 -0
- data/vendor/rust/rust/templates/FunctionInitAlias.rusttpl +5 -0
- data/vendor/rust/rust/templates/FunctionInitBinding.rusttpl +9 -0
- data/vendor/rust/rust/templates/MethodInitBinding.rusttpl +9 -0
- data/vendor/rust/rust/templates/ModuleDeclarations.rusttpl +3 -0
- data/vendor/rust/rust/templates/ModuleDefinitions.rusttpl +3 -0
- data/vendor/rust/rust/templates/StandaloneClassDeclarations.rusttpl +7 -0
- data/vendor/rust/rust/templates/VariableFunctionCall.rusttpl +14 -0
- data/vendor/rust/rust/type.rb +98 -0
- data/vendor/rust/test/Makefile +4 -0
- data/vendor/rust/test/constants.rb +36 -0
- data/vendor/rust/test/cppclass.cc +45 -0
- data/vendor/rust/test/cppclass.hh +67 -0
- data/vendor/rust/test/cppclass.rb +59 -0
- data/vendor/rust/test/cwrapper.c +74 -0
- data/vendor/rust/test/cwrapper.h +41 -0
- data/vendor/rust/test/cwrapper.rb +56 -0
- data/vendor/rust/test/dummyclass.hh +31 -0
- data/vendor/rust/test/lib/extension-test.rb +98 -0
- 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-constants.rb +43 -0
- data/vendor/rust/test/test-cppclass.rb +82 -0
- data/vendor/rust/test/test-cwrapper.rb +80 -0
- data/vendor/rust/test/test-operators.rb +42 -0
- metadata +393 -0
data/specs/logging.rb
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/spec_helper'
|
2
|
+
|
3
|
+
describe Gecode::LoggingLayer do
|
4
|
+
before do
|
5
|
+
# Enable logging.
|
6
|
+
Gecode.instance_eval{ remove_const(:Raw) }
|
7
|
+
Gecode.const_set(:Raw, Gecode::LoggingLayer)
|
8
|
+
end
|
9
|
+
|
10
|
+
after do
|
11
|
+
# Disable logging.
|
12
|
+
Gecode.instance_eval{ remove_const(:Raw) }
|
13
|
+
Gecode.const_set(:Raw, GecodeRaw)
|
14
|
+
end
|
15
|
+
|
16
|
+
it "shouldn't interfere with calls through Gecode::Raw" do
|
17
|
+
lambda do
|
18
|
+
model = Gecode::Model.new
|
19
|
+
int_var = model.int_var(0..9)
|
20
|
+
int_var.must >= 5
|
21
|
+
model.solve!
|
22
|
+
end.should_not raise_error
|
23
|
+
end
|
24
|
+
end
|
data/specs/model.rb
ADDED
@@ -0,0 +1,325 @@
|
|
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
|
+
it 'should allow the creation of int variables without specified domain' do
|
14
|
+
var = @model.int_var
|
15
|
+
var.should be_range
|
16
|
+
var.min.should == Gecode::Raw::IntLimits::MIN
|
17
|
+
var.max.should == Gecode::Raw::IntLimits::MAX
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'should allow the creation of int variables with non-range domains' do
|
21
|
+
domain = [1, 3, 5]
|
22
|
+
@model.int_var(domain).should have_domain(domain)
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'should allow the creation of int variables with single element domains' do
|
26
|
+
domain = 3
|
27
|
+
@model.int_var(domain).should have_domain([domain])
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'should allow the creation of int-var arrays with range domains' do
|
31
|
+
range = 0..3
|
32
|
+
count = 5
|
33
|
+
vars = @model.int_var_array(count, range)
|
34
|
+
vars.size.should equal(count)
|
35
|
+
vars.each{ |var| var.should have_domain(range) }
|
36
|
+
end
|
37
|
+
|
38
|
+
it 'should allow the creation of int-var arrays with non-range domains' do
|
39
|
+
domain = [1,3,5]
|
40
|
+
count = 5
|
41
|
+
vars = @model.int_var_array(count, domain)
|
42
|
+
vars.size.should equal(count)
|
43
|
+
vars.each{ |var| var.should have_domain(domain) }
|
44
|
+
end
|
45
|
+
|
46
|
+
it 'should allow the creation of int-var arrays without specified domain' do
|
47
|
+
count = 5
|
48
|
+
vars = @model.int_var_array(count)
|
49
|
+
vars.size.should equal(count)
|
50
|
+
vars.each do |var|
|
51
|
+
var.should be_range
|
52
|
+
var.min.should == Gecode::Raw::IntLimits::MIN
|
53
|
+
var.max.should == Gecode::Raw::IntLimits::MAX
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
it 'should allow the creation of int-var matrices with range domains' do
|
58
|
+
range = 0..3
|
59
|
+
rows = 5
|
60
|
+
columns = 4
|
61
|
+
vars = @model.int_var_matrix(rows, columns, range)
|
62
|
+
vars.row_size.should equal(rows)
|
63
|
+
vars.column_size.should equal(columns)
|
64
|
+
vars.each{ |var| var.should have_domain(range) }
|
65
|
+
end
|
66
|
+
|
67
|
+
it 'should allow the creation of int-var matrices with non-range domains' do
|
68
|
+
domain = [1,3,5]
|
69
|
+
rows = 5
|
70
|
+
columns = 4
|
71
|
+
vars = @model.int_var_matrix(rows, columns, domain)
|
72
|
+
vars.row_size.should equal(rows)
|
73
|
+
vars.column_size.should equal(columns)
|
74
|
+
vars.each{ |var| var.should have_domain(domain) }
|
75
|
+
end
|
76
|
+
|
77
|
+
it 'should allow the creation of int-var matrices without specified domain' do
|
78
|
+
rows = 5
|
79
|
+
columns = 4
|
80
|
+
vars = @model.int_var_matrix(rows, columns)
|
81
|
+
vars.row_size.should equal(rows)
|
82
|
+
vars.column_size.should equal(columns)
|
83
|
+
vars.each do |var|
|
84
|
+
var.should be_range
|
85
|
+
var.min.should == Gecode::Raw::IntLimits::MIN
|
86
|
+
var.max.should == Gecode::Raw::IntLimits::MAX
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
it 'should raise error if the domain is of incorrect type' do
|
91
|
+
lambda do
|
92
|
+
@model.int_var(nil)
|
93
|
+
end.should raise_error(TypeError)
|
94
|
+
end
|
95
|
+
|
96
|
+
it 'should gracefully GC a variable that was never accessed' do
|
97
|
+
lambda do
|
98
|
+
@model.int_var 0
|
99
|
+
GC.start
|
100
|
+
end.should_not raise_error
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
describe Gecode::Model, ' (bool creation)' do
|
105
|
+
before do
|
106
|
+
@model = Gecode::Model.new
|
107
|
+
end
|
108
|
+
|
109
|
+
it 'should allow the creation of boolean variables' do
|
110
|
+
@model.bool_var.should_not be_nil
|
111
|
+
end
|
112
|
+
|
113
|
+
it 'should allow the creation of arrays of boolean variables' do
|
114
|
+
@model.bool_var_array(3).size.should equal(3)
|
115
|
+
end
|
116
|
+
|
117
|
+
it 'should allow the creation of matrices of boolean variables' do
|
118
|
+
matrix = @model.bool_var_matrix(3, 4)
|
119
|
+
matrix.row_size.should equal(3)
|
120
|
+
matrix.column_size.should equal(4)
|
121
|
+
end
|
122
|
+
|
123
|
+
it 'should gracefully GC a variable that was never accessed' do
|
124
|
+
lambda do
|
125
|
+
@model.bool_var
|
126
|
+
GC.start
|
127
|
+
end.should_not raise_error
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
describe Gecode::Model, ' (set creation)' do
|
132
|
+
before do
|
133
|
+
@model = Gecode::Model.new
|
134
|
+
@glb_range = 0..3
|
135
|
+
@lub_range = 0..5
|
136
|
+
@glb_enum = [0, 3]
|
137
|
+
@lub_enum = [0, 1, 2, 3, 5]
|
138
|
+
@lower_card = 1
|
139
|
+
@upper_card = 3
|
140
|
+
end
|
141
|
+
|
142
|
+
it 'should allow the creation of set variables without specified bounds' do
|
143
|
+
var = @model.set_var
|
144
|
+
var.lower_bound.size.should == 0
|
145
|
+
var.upper_bound.min.should == Gecode::Raw::SetLimits::MIN
|
146
|
+
var.upper_bound.max.should == Gecode::Raw::SetLimits::MAX
|
147
|
+
end
|
148
|
+
|
149
|
+
it 'should allow the creation of set variables with glb range and lub range' do
|
150
|
+
@model.set_var(@glb_range, @lub_range).should have_bounds(@glb_range,
|
151
|
+
@lub_range)
|
152
|
+
end
|
153
|
+
|
154
|
+
it 'should allow the creation of set variables with glb enum and lub range' do
|
155
|
+
@model.set_var(@glb_enum, @lub_range).should have_bounds(@glb_enum,
|
156
|
+
@lub_range)
|
157
|
+
end
|
158
|
+
|
159
|
+
it 'should allow the creation of set variables with glb range and lub enum' do
|
160
|
+
@model.set_var(@glb_range, @lub_enum).should have_bounds(@glb_range,
|
161
|
+
@lub_enum)
|
162
|
+
end
|
163
|
+
|
164
|
+
it 'should allow the creation of set variables with glb enum and lub enum' do
|
165
|
+
@model.set_var(@glb_enum, @lub_enum).should have_bounds(@glb_enum,
|
166
|
+
@lub_enum)
|
167
|
+
end
|
168
|
+
|
169
|
+
it 'should allow the creation of set variables with specified lower cardinality bound' do
|
170
|
+
@model.set_var(@glb_range, @lub_range,
|
171
|
+
@lower_card).cardinality.begin.should >= @lower_card
|
172
|
+
end
|
173
|
+
|
174
|
+
it 'should allow the creation of set variables with specified cardinality range' do
|
175
|
+
var = @model.set_var(@glb_range, @lub_range, @lower_card..@upper_card)
|
176
|
+
var.cardinality.end.should <= @upper_card
|
177
|
+
var.cardinality.begin.should >= @lower_card
|
178
|
+
end
|
179
|
+
|
180
|
+
it 'should allow the creation of arrays of set variables' do
|
181
|
+
arr = @model.set_var_array(3, @glb_enum, @lub_enum, @lower_card..@upper_card)
|
182
|
+
arr.size.should == 3
|
183
|
+
arr.each do |var|
|
184
|
+
var.should have_bounds(@glb_enum, @lub_enum)
|
185
|
+
var.cardinality.end.should <= @upper_card
|
186
|
+
var.cardinality.begin.should >= @lower_card
|
187
|
+
end
|
188
|
+
end
|
189
|
+
|
190
|
+
it 'should allow the creation of arrays of set variables without specified bounds' do
|
191
|
+
vars = @model.set_var_array(3)
|
192
|
+
vars.each do |var|
|
193
|
+
var.lower_bound.size.should == 0
|
194
|
+
var.upper_bound.min.should == Gecode::Raw::SetLimits::MIN
|
195
|
+
var.upper_bound.max.should == Gecode::Raw::SetLimits::MAX
|
196
|
+
end
|
197
|
+
end
|
198
|
+
|
199
|
+
it 'should allow the creation of matrices of set variables' do
|
200
|
+
matrix = @model.set_var_matrix(4, 5, @glb_enum, @lub_enum,
|
201
|
+
@lower_card..@upper_card)
|
202
|
+
matrix.row_size.should == 4
|
203
|
+
matrix.column_size.should == 5
|
204
|
+
matrix.each do |var|
|
205
|
+
var.should have_bounds(@glb_enum, @lub_enum)
|
206
|
+
var.cardinality.end.should <= @upper_card
|
207
|
+
var.cardinality.begin.should >= @lower_card
|
208
|
+
end
|
209
|
+
end
|
210
|
+
|
211
|
+
it 'should allow the creation of matrices of set variables without specified bounds' do
|
212
|
+
matrix = @model.set_var_matrix(4, 5)
|
213
|
+
matrix.each do |var|
|
214
|
+
var.lower_bound.size.should == 0
|
215
|
+
var.upper_bound.min.should == Gecode::Raw::SetLimits::MIN
|
216
|
+
var.upper_bound.max.should == Gecode::Raw::SetLimits::MAX
|
217
|
+
end
|
218
|
+
end
|
219
|
+
|
220
|
+
it 'should raise error if glb and lub are not valid when they are given as range' do
|
221
|
+
lambda do
|
222
|
+
@model.set_var(@lub_range, @glb_range)
|
223
|
+
end.should raise_error(ArgumentError)
|
224
|
+
end
|
225
|
+
|
226
|
+
it 'should raise error if glb and lub are not valid when one is given as enum' do
|
227
|
+
lambda do
|
228
|
+
@model.set_var(@lub_range, @glb_enum)
|
229
|
+
end.should raise_error(ArgumentError)
|
230
|
+
end
|
231
|
+
|
232
|
+
it 'should raise error if glb and lub are not valid when both are given as enums' do
|
233
|
+
lambda do
|
234
|
+
@model.set_var(@lub_enum, @glb_enum)
|
235
|
+
end.should raise_error(ArgumentError)
|
236
|
+
end
|
237
|
+
|
238
|
+
it 'should raise error if the glb and lub are of incorrect type' do
|
239
|
+
lambda do
|
240
|
+
@model.set_var("foo\n", "foo\ns")
|
241
|
+
end.should raise_error(TypeError)
|
242
|
+
end
|
243
|
+
|
244
|
+
it 'should gracefully GC a variable that was never accessed' do
|
245
|
+
lambda do
|
246
|
+
@model.set_var(@glb_range, @lub_range)
|
247
|
+
GC.start
|
248
|
+
end.should_not raise_error
|
249
|
+
end
|
250
|
+
end
|
251
|
+
|
252
|
+
describe Gecode::Model, ' (space access restriction)' do
|
253
|
+
before do
|
254
|
+
@model = Gecode::Model.new
|
255
|
+
end
|
256
|
+
|
257
|
+
it 'should raise error if not allowed to access space' do
|
258
|
+
lambda{ @model.active_space }.should raise_error(RuntimeError)
|
259
|
+
end
|
260
|
+
|
261
|
+
it 'should not raise error because of space restriction if allowed to access space' do
|
262
|
+
lambda do
|
263
|
+
@model.allow_space_access do
|
264
|
+
@model.active_space
|
265
|
+
end
|
266
|
+
end.should_not raise_error(RuntimeError)
|
267
|
+
end
|
268
|
+
end
|
269
|
+
|
270
|
+
describe Gecode::Model, ' (accessible variable creation)' do
|
271
|
+
before do
|
272
|
+
@model = Class.new(Gecode::Model).new
|
273
|
+
end
|
274
|
+
|
275
|
+
it 'should allow creation of named variable using #foo_is_a' do
|
276
|
+
var = @model.int_var(17)
|
277
|
+
lambda{ @model.foo }.should raise_error(NoMethodError)
|
278
|
+
@model.instance_eval{ foo_is_a var }
|
279
|
+
lambda{ @model.foo }.should_not raise_error
|
280
|
+
@model.foo.should == var
|
281
|
+
end
|
282
|
+
|
283
|
+
it 'should allow creation of named variable using #foo_is_an' do
|
284
|
+
var = @model.int_var(17)
|
285
|
+
lambda{ @model.foo }.should raise_error(NoMethodError)
|
286
|
+
@model.instance_eval{ foo_is_an var }
|
287
|
+
lambda{ @model.foo }.should_not raise_error
|
288
|
+
@model.foo.should == var
|
289
|
+
end
|
290
|
+
|
291
|
+
it 'should only allow one argument to be given to #foo_is_a' do
|
292
|
+
lambda do
|
293
|
+
@model.instance_eval{ foo_is_a }
|
294
|
+
end.should raise_error(ArgumentError)
|
295
|
+
lambda do
|
296
|
+
@model.instance_eval{ foo_is_a bool_var, bool_var }
|
297
|
+
end.should raise_error(ArgumentError)
|
298
|
+
end
|
299
|
+
|
300
|
+
it 'should only define the variable in the current instance' do
|
301
|
+
klass = Class.new Gecode::Model
|
302
|
+
model_a = klass.new
|
303
|
+
model_b = klass.new
|
304
|
+
|
305
|
+
model_a.instance_eval{ bar_is_a bool_var }
|
306
|
+
lambda{ model_a.bar }.should_not raise_error
|
307
|
+
lambda{ model_b.bar }.should raise_error(NoMethodError)
|
308
|
+
end
|
309
|
+
|
310
|
+
it 'should raise error if a method would be overwritten' do
|
311
|
+
var = @model.int_var(17)
|
312
|
+
lambda{ @model.class }.should_not raise_error
|
313
|
+
lambda do
|
314
|
+
@model.instance_eval{ class_is_an var }
|
315
|
+
end.should raise_error(ArgumentError)
|
316
|
+
end
|
317
|
+
|
318
|
+
it 'should raise error if an instance variable would be overwritten' do
|
319
|
+
@model.instance_eval{ @foo = 17 }
|
320
|
+
var = @model.int_var(17)
|
321
|
+
lambda do
|
322
|
+
@model.instance_eval{ foo_is_a var }
|
323
|
+
end.should raise_error(ArgumentError)
|
324
|
+
end
|
325
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/spec_helper'
|
2
|
+
|
3
|
+
describe Gecode, ' (Model sugar)' do
|
4
|
+
it 'should provide #solve as sugar for constructing a model and running solve!' do
|
5
|
+
Gecode.solve do
|
6
|
+
numbers_is_an int_var_array(2, 0..5)
|
7
|
+
x, y = numbers
|
8
|
+
(x * y).must == 25
|
9
|
+
branch_on numbers
|
10
|
+
end.numbers.values.should == [5,5]
|
11
|
+
end
|
12
|
+
|
13
|
+
it 'should provide #maximize as sugar for constructing a model and running maximize!' do
|
14
|
+
Gecode.maximize :z do
|
15
|
+
z_is_an int_var
|
16
|
+
x, y = vars = int_var_array(2, 0..5)
|
17
|
+
(x*2 - y).must == z
|
18
|
+
branch_on vars
|
19
|
+
end.z.value.should equal(10)
|
20
|
+
end
|
21
|
+
|
22
|
+
it 'should provide #minimize as sugar for constructing a model and running minimize!' do
|
23
|
+
Gecode.minimize :z do
|
24
|
+
z_is_an int_var
|
25
|
+
x, y = vars = int_var_array(2, 0..5)
|
26
|
+
(x*2 - y).must == z
|
27
|
+
branch_on vars
|
28
|
+
end.z.value.should equal(-5)
|
29
|
+
end
|
30
|
+
end
|
data/specs/search.rb
ADDED
@@ -0,0 +1,383 @@
|
|
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
|
+
class SampleOptimizationProblem < Gecode::Model
|
23
|
+
attr :x
|
24
|
+
attr :y
|
25
|
+
attr :z
|
26
|
+
|
27
|
+
def initialize
|
28
|
+
@x,@y = int_var_array(2, 0..5)
|
29
|
+
@z = int_var(0..25)
|
30
|
+
(@x * @y).must == @z
|
31
|
+
|
32
|
+
branch_on wrap_enum([@x, @y]), :variable => :smallest_size, :value => :min
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
class SampleOptimizationProblem2 < Gecode::Model
|
37
|
+
attr :money
|
38
|
+
|
39
|
+
def initialize
|
40
|
+
@money = int_var_array(3, 0..9)
|
41
|
+
@money.must_be.distinct
|
42
|
+
@money.to_number.must < 500 # Otherwise it takes some time.
|
43
|
+
|
44
|
+
branch_on @money, :variable => :smallest_size, :value => :min
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
class Array
|
49
|
+
# Computes a number of the specified base using the array's elements as
|
50
|
+
# digits.
|
51
|
+
def to_number(base = 10)
|
52
|
+
inject{ |result, variable| variable + result * base }
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
describe Gecode::Model, ' (with multiple solutions)' do
|
57
|
+
before do
|
58
|
+
@domain = 0..3
|
59
|
+
@solved_domain = [2]
|
60
|
+
@model = SampleProblem.new(@domain)
|
61
|
+
end
|
62
|
+
|
63
|
+
it 'should pass a solution to the block given in #solution' do
|
64
|
+
@model.solution do |s|
|
65
|
+
s.var.should have_domain(@solved_domain)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
it 'should update the search statistics before yielding to #solution' do
|
70
|
+
@model.solution do |s|
|
71
|
+
@model.search_stats.should_not be_nil
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
it 'should only evaluate the block for one solution in #solution' do
|
76
|
+
i = 0
|
77
|
+
@model.solution{ |s| i += 1 }
|
78
|
+
i.should equal(1)
|
79
|
+
end
|
80
|
+
|
81
|
+
it 'should return the result of the block when calling #solution' do
|
82
|
+
@model.solution{ |s| 'test' }.should == 'test'
|
83
|
+
end
|
84
|
+
|
85
|
+
it 'should pass every solution to #each_solution' do
|
86
|
+
solutions = []
|
87
|
+
@model.each_solution do |s|
|
88
|
+
solutions << s.var.value
|
89
|
+
end
|
90
|
+
Set.new(solutions).should == Set.new([2,3])
|
91
|
+
end
|
92
|
+
|
93
|
+
it 'should update the search statistics before yielding to #each_solution' do
|
94
|
+
solutions = []
|
95
|
+
old_stats = @model.search_stats
|
96
|
+
old_stats.should be_nil
|
97
|
+
@model.each_solution do |s|
|
98
|
+
solutions << s.var.value
|
99
|
+
@model.search_stats.should_not == old_stats
|
100
|
+
@model.search_stats.should_not be_nil
|
101
|
+
old_stats = @model.search_stats
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
describe Gecode::Model, ' (after #solve!)' do
|
107
|
+
before do
|
108
|
+
@domain = 0..3
|
109
|
+
@solved_domain = [2]
|
110
|
+
@model = SampleProblem.new(@domain)
|
111
|
+
@model.solve!
|
112
|
+
end
|
113
|
+
|
114
|
+
it 'should have updated the variables domains' do
|
115
|
+
@model.var.should have_domain(@solved_domain)
|
116
|
+
end
|
117
|
+
|
118
|
+
it 'should have updated variables in arrays' do
|
119
|
+
@model.array.first.should have_domain(@solved_domain)
|
120
|
+
end
|
121
|
+
|
122
|
+
it 'should have updated variables in hashes' do
|
123
|
+
@model.hash.values.first.should have_domain(@solved_domain)
|
124
|
+
end
|
125
|
+
|
126
|
+
it 'should have updated variables in nested enums' do
|
127
|
+
enum = @model.solve!.nested_enum
|
128
|
+
enum[2].first.should have_domain(@solved_domain)
|
129
|
+
enum[3][1][:b].should have_domain(@solved_domain)
|
130
|
+
|
131
|
+
enum = @model.nested_enum
|
132
|
+
enum[2].first.should have_domain(@solved_domain)
|
133
|
+
enum[3][1][:b].should have_domain(@solved_domain)
|
134
|
+
end
|
135
|
+
|
136
|
+
it 'should have updated the search statistics' do
|
137
|
+
stats = @model.search_stats
|
138
|
+
stats[:propagations].should == 0
|
139
|
+
stats[:failures].should == 0
|
140
|
+
stats[:clones].should_not be_nil
|
141
|
+
stats[:commits].should_not be_nil
|
142
|
+
stats[:memory].should > 0
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
describe 'reset model', :shared => true do
|
147
|
+
it 'should have reset variables' do
|
148
|
+
@model.var.should have_domain(@reset_domain)
|
149
|
+
end
|
150
|
+
|
151
|
+
it 'should have reset variables in nested enums' do
|
152
|
+
enum = @model.nested_enum
|
153
|
+
enum[2].first.should have_domain(@reset_domain)
|
154
|
+
enum[3][1][:b].should have_domain(@reset_domain)
|
155
|
+
end
|
156
|
+
|
157
|
+
it 'should have cleared the search statistics' do
|
158
|
+
@model.search_stats.should be_nil
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
describe Gecode::Model, ' (after #reset!)' do
|
163
|
+
before do
|
164
|
+
@domain = 0..3
|
165
|
+
@reset_domain = 2..3
|
166
|
+
@model = SampleProblem.new(@domain)
|
167
|
+
@model.solve!
|
168
|
+
@model.reset!
|
169
|
+
end
|
170
|
+
|
171
|
+
it_should_behave_like 'reset model'
|
172
|
+
end
|
173
|
+
|
174
|
+
describe Gecode::Model, ' (after #solution)' do
|
175
|
+
before do
|
176
|
+
@domain = 0..3
|
177
|
+
@reset_domain = 2..3
|
178
|
+
@model = SampleProblem.new(@domain)
|
179
|
+
@model.solution{ |s| }
|
180
|
+
end
|
181
|
+
|
182
|
+
it_should_behave_like 'reset model'
|
183
|
+
end
|
184
|
+
|
185
|
+
describe Gecode::Model, ' (after #each_solution)' do
|
186
|
+
before do
|
187
|
+
@domain = 0..3
|
188
|
+
@reset_domain = 2..3
|
189
|
+
@model = SampleProblem.new(@domain)
|
190
|
+
@model.each_solution{ |s| }
|
191
|
+
end
|
192
|
+
|
193
|
+
it_should_behave_like 'reset model'
|
194
|
+
end
|
195
|
+
|
196
|
+
describe Gecode::Model, ' (without solution)' do
|
197
|
+
before do
|
198
|
+
@domain = 0..3
|
199
|
+
@model = SampleProblem.new(@domain)
|
200
|
+
@model.var.must < 0
|
201
|
+
end
|
202
|
+
|
203
|
+
it 'should return nil when calling #solution' do
|
204
|
+
@model.solution{ |s| 'test' }.should be_nil
|
205
|
+
end
|
206
|
+
|
207
|
+
it 'should not yield anything to #each_solution' do
|
208
|
+
@model.each_solution{ |s| violated }
|
209
|
+
end
|
210
|
+
|
211
|
+
it 'should raise NoSolutionError when calling #solve!' do
|
212
|
+
lambda do
|
213
|
+
@model.solve!
|
214
|
+
end.should raise_error(Gecode::NoSolutionError)
|
215
|
+
end
|
216
|
+
|
217
|
+
it 'should raise NoSolutionError when calling #optimize!' do
|
218
|
+
lambda do
|
219
|
+
@model.optimize!{}
|
220
|
+
end.should raise_error(Gecode::NoSolutionError)
|
221
|
+
end
|
222
|
+
|
223
|
+
it 'should raise NoSolutionError when calling #minimize!' do
|
224
|
+
lambda do
|
225
|
+
@model.optimize!{}
|
226
|
+
end.should raise_error(Gecode::NoSolutionError)
|
227
|
+
end
|
228
|
+
|
229
|
+
it 'should raise NoSolutionError when calling #maximize!' do
|
230
|
+
lambda do
|
231
|
+
@model.maximize!(:var)
|
232
|
+
end.should raise_error(Gecode::NoSolutionError)
|
233
|
+
end
|
234
|
+
end
|
235
|
+
|
236
|
+
describe Gecode::Model, ' (without constraints)' do
|
237
|
+
before do
|
238
|
+
@model = Gecode::Model.new
|
239
|
+
@x = @model.int_var(0..1)
|
240
|
+
end
|
241
|
+
|
242
|
+
it 'should produce a solution' do
|
243
|
+
@model.solve!.should_not be_nil
|
244
|
+
end
|
245
|
+
end
|
246
|
+
|
247
|
+
describe Gecode::Model, '(optimization search)' do
|
248
|
+
it 'should optimize the solution' do
|
249
|
+
solution = SampleOptimizationProblem.new.optimize! do |model, best_so_far|
|
250
|
+
model.z.must > best_so_far.z.value
|
251
|
+
end
|
252
|
+
solution.should_not be_nil
|
253
|
+
solution.x.value.should == 5
|
254
|
+
solution.y.value.should == 5
|
255
|
+
solution.z.value.should == 25
|
256
|
+
end
|
257
|
+
|
258
|
+
it 'should not be bothered by garbage collecting' do
|
259
|
+
# This goes through 400+ spaces.
|
260
|
+
solution = SampleOptimizationProblem2.new.optimize! do |model, best_so_far|
|
261
|
+
model.money.to_number.must > best_so_far.money.values.to_number
|
262
|
+
end
|
263
|
+
solution.should_not be_nil
|
264
|
+
solution.money.values.to_number.should == 498
|
265
|
+
end
|
266
|
+
|
267
|
+
it 'should raise error if no constrain proc has been defined' do
|
268
|
+
lambda do
|
269
|
+
Gecode::Model.constrain(nil, nil)
|
270
|
+
end.should raise_error(NotImplementedError)
|
271
|
+
end
|
272
|
+
|
273
|
+
it 'should not have problems with variables being created in the optimization block' do
|
274
|
+
solution = SampleOptimizationProblem.new.optimize! do |model, best_so_far|
|
275
|
+
tmp = model.int_var(0..25)
|
276
|
+
tmp.must == model.z
|
277
|
+
tmp.must > best_so_far.z.value
|
278
|
+
end
|
279
|
+
solution.should_not be_nil
|
280
|
+
solution.x.value.should == 5
|
281
|
+
solution.y.value.should == 5
|
282
|
+
solution.z.value.should == 25
|
283
|
+
end
|
284
|
+
|
285
|
+
it 'should not have problems with variables being created in the optimization block (2)' do
|
286
|
+
solution = SampleOptimizationProblem.new.optimize! do |model, best_so_far|
|
287
|
+
tmp = model.int_var(0..25)
|
288
|
+
tmp.must == model.z
|
289
|
+
(tmp + tmp).must > best_so_far.z.value*2
|
290
|
+
end
|
291
|
+
solution.should_not be_nil
|
292
|
+
solution.x.value.should == 5
|
293
|
+
solution.y.value.should == 5
|
294
|
+
solution.z.value.should == 25
|
295
|
+
end
|
296
|
+
|
297
|
+
it 'should update the search statistics' do
|
298
|
+
model = SampleOptimizationProblem.new
|
299
|
+
solution = model.maximize! :z
|
300
|
+
|
301
|
+
stats = model.search_stats
|
302
|
+
stats.should_not be_nil
|
303
|
+
stats[:propagations].should be_between(1, 100)
|
304
|
+
stats[:failures].should be_between(1, 100)
|
305
|
+
stats[:clones].should_not be_nil
|
306
|
+
stats[:commits].should_not be_nil
|
307
|
+
stats[:memory].should > 0
|
308
|
+
end
|
309
|
+
end
|
310
|
+
|
311
|
+
describe 'single variable optimization', :shared => true do
|
312
|
+
it "should support #{@method_name} having the variable given as a symbol" do
|
313
|
+
solution = @model.method(@method_name).call(@variable_name.to_sym)
|
314
|
+
@expect_to_be_correct.call(solution)
|
315
|
+
end
|
316
|
+
|
317
|
+
it "should support #{@method_name} having the variable given as a string" do
|
318
|
+
solution = @model.method(@method_name).call(@variable_name.to_s)
|
319
|
+
@expect_to_be_correct.call(solution)
|
320
|
+
end
|
321
|
+
|
322
|
+
it "should raise error if #{@method_name} is given a non-existing method" do
|
323
|
+
lambda do
|
324
|
+
SampleOptimizationProblem.new.method(@method_name).call(:does_not_exist)
|
325
|
+
end.should raise_error(NameError)
|
326
|
+
end
|
327
|
+
|
328
|
+
it "should raise error if #{@method_name} is given a method that does not return an integer variable" do
|
329
|
+
lambda do
|
330
|
+
SampleOptimizationProblem.new.method(@method_name).call(:object_id)
|
331
|
+
end.should raise_error(ArgumentError)
|
332
|
+
end
|
333
|
+
|
334
|
+
it 'should update the search statistics' do
|
335
|
+
@model.method(@method_name).call(@variable_name.to_sym)
|
336
|
+
|
337
|
+
stats = @model.search_stats
|
338
|
+
stats.should_not be_nil
|
339
|
+
stats[:propagations].should be_between(1, 100)
|
340
|
+
stats[:failures].should be_between(1, 100)
|
341
|
+
stats[:clones].should_not be_nil
|
342
|
+
stats[:commits].should_not be_nil
|
343
|
+
stats[:memory].should > 0
|
344
|
+
end
|
345
|
+
end
|
346
|
+
|
347
|
+
describe Gecode::Model, '(single variable minimization)' do
|
348
|
+
before do
|
349
|
+
@method_name = 'minimize!'
|
350
|
+
@variable_name = 'x'
|
351
|
+
|
352
|
+
@model = SampleOptimizationProblem.new
|
353
|
+
@model.z.must > 2
|
354
|
+
|
355
|
+
@expect_to_be_correct = lambda do |solution|
|
356
|
+
solution.should_not be_nil
|
357
|
+
solution.x.value.should == 1
|
358
|
+
solution.y.value.should == 3
|
359
|
+
solution.z.value.should == 3
|
360
|
+
end
|
361
|
+
end
|
362
|
+
|
363
|
+
it_should_behave_like 'single variable optimization'
|
364
|
+
end
|
365
|
+
|
366
|
+
describe Gecode::Model, '(single variable maximization)' do
|
367
|
+
before do
|
368
|
+
@method_name = 'maximize!'
|
369
|
+
@variable_name = 'z'
|
370
|
+
|
371
|
+
@model = SampleOptimizationProblem.new
|
372
|
+
|
373
|
+
@expect_to_be_correct = lambda do |solution|
|
374
|
+
solution.should_not be_nil
|
375
|
+
solution.x.value.should == 5
|
376
|
+
solution.y.value.should == 5
|
377
|
+
solution.z.value.should == 25
|
378
|
+
end
|
379
|
+
end
|
380
|
+
|
381
|
+
it_should_behave_like 'single variable optimization'
|
382
|
+
end
|
383
|
+
|