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.
Files changed (203) hide show
  1. data/CHANGES +137 -0
  2. data/COPYING +17 -0
  3. data/LGPL-LICENSE +458 -0
  4. data/README +58 -0
  5. data/Rakefile +14 -0
  6. data/example/equation_system.rb +15 -0
  7. data/example/example_helper.rb +1 -0
  8. data/example/magic_sequence.rb +43 -0
  9. data/example/money.rb +36 -0
  10. data/example/queens.rb +42 -0
  11. data/example/send_more_money.rb +43 -0
  12. data/example/send_most_money.rb +58 -0
  13. data/example/square_tiling.rb +84 -0
  14. data/example/sudoku-set.rb +106 -0
  15. data/example/sudoku.rb +56 -0
  16. data/lib/gecode.dll +0 -0
  17. data/lib/gecoder.rb +5 -0
  18. data/lib/gecoder/bindings.rb +96 -0
  19. data/lib/gecoder/bindings/bindings.rb +2029 -0
  20. data/lib/gecoder/interface.rb +9 -0
  21. data/lib/gecoder/interface/binding_changes.rb +9 -0
  22. data/lib/gecoder/interface/branch.rb +163 -0
  23. data/lib/gecoder/interface/constraints.rb +471 -0
  24. data/lib/gecoder/interface/constraints/bool/boolean.rb +251 -0
  25. data/lib/gecoder/interface/constraints/bool/channel.rb +7 -0
  26. data/lib/gecoder/interface/constraints/bool/linear.rb +200 -0
  27. data/lib/gecoder/interface/constraints/bool_enum/channel.rb +68 -0
  28. data/lib/gecoder/interface/constraints/bool_enum/extensional.rb +106 -0
  29. data/lib/gecoder/interface/constraints/bool_enum/relation.rb +55 -0
  30. data/lib/gecoder/interface/constraints/bool_enum_constraints.rb +84 -0
  31. data/lib/gecoder/interface/constraints/bool_var_constraints.rb +155 -0
  32. data/lib/gecoder/interface/constraints/extensional_regexp.rb +101 -0
  33. data/lib/gecoder/interface/constraints/fixnum_enum/element.rb +63 -0
  34. data/lib/gecoder/interface/constraints/fixnum_enum/operation.rb +65 -0
  35. data/lib/gecoder/interface/constraints/fixnum_enum_constraints.rb +42 -0
  36. data/lib/gecoder/interface/constraints/int/arithmetic.rb +150 -0
  37. data/lib/gecoder/interface/constraints/int/channel.rb +51 -0
  38. data/lib/gecoder/interface/constraints/int/domain.rb +80 -0
  39. data/lib/gecoder/interface/constraints/int/linear.rb +143 -0
  40. data/lib/gecoder/interface/constraints/int/relation.rb +141 -0
  41. data/lib/gecoder/interface/constraints/int_enum/arithmetic.rb +63 -0
  42. data/lib/gecoder/interface/constraints/int_enum/channel.rb +86 -0
  43. data/lib/gecoder/interface/constraints/int_enum/count.rb +66 -0
  44. data/lib/gecoder/interface/constraints/int_enum/distinct.rb +64 -0
  45. data/lib/gecoder/interface/constraints/int_enum/element.rb +64 -0
  46. data/lib/gecoder/interface/constraints/int_enum/equality.rb +37 -0
  47. data/lib/gecoder/interface/constraints/int_enum/extensional.rb +187 -0
  48. data/lib/gecoder/interface/constraints/int_enum/sort.rb +135 -0
  49. data/lib/gecoder/interface/constraints/int_enum_constraints.rb +95 -0
  50. data/lib/gecoder/interface/constraints/int_var_constraints.rb +230 -0
  51. data/lib/gecoder/interface/constraints/reifiable_constraints.rb +78 -0
  52. data/lib/gecoder/interface/constraints/selected_set/select.rb +120 -0
  53. data/lib/gecoder/interface/constraints/selected_set_constraints.rb +75 -0
  54. data/lib/gecoder/interface/constraints/set/cardinality.rb +65 -0
  55. data/lib/gecoder/interface/constraints/set/channel.rb +51 -0
  56. data/lib/gecoder/interface/constraints/set/connection.rb +130 -0
  57. data/lib/gecoder/interface/constraints/set/domain.rb +156 -0
  58. data/lib/gecoder/interface/constraints/set/include.rb +36 -0
  59. data/lib/gecoder/interface/constraints/set/operation.rb +118 -0
  60. data/lib/gecoder/interface/constraints/set/relation.rb +155 -0
  61. data/lib/gecoder/interface/constraints/set_elements/relation.rb +116 -0
  62. data/lib/gecoder/interface/constraints/set_elements_constraints.rb +97 -0
  63. data/lib/gecoder/interface/constraints/set_enum/channel.rb +45 -0
  64. data/lib/gecoder/interface/constraints/set_enum/distinct.rb +43 -0
  65. data/lib/gecoder/interface/constraints/set_enum/operation.rb +69 -0
  66. data/lib/gecoder/interface/constraints/set_enum/select.rb +79 -0
  67. data/lib/gecoder/interface/constraints/set_enum_constraints.rb +84 -0
  68. data/lib/gecoder/interface/constraints/set_var_constraints.rb +243 -0
  69. data/lib/gecoder/interface/enum_matrix.rb +64 -0
  70. data/lib/gecoder/interface/enum_wrapper.rb +205 -0
  71. data/lib/gecoder/interface/model.rb +453 -0
  72. data/lib/gecoder/interface/model_sugar.rb +84 -0
  73. data/lib/gecoder/interface/search.rb +197 -0
  74. data/lib/gecoder/interface/variables.rb +306 -0
  75. data/lib/gecoder/version.rb +4 -0
  76. data/specs/bool_var.rb +81 -0
  77. data/specs/branch.rb +185 -0
  78. data/specs/constraints/bool/boolean.rb +317 -0
  79. data/specs/constraints/bool/boolean_properties.rb +51 -0
  80. data/specs/constraints/bool/linear.rb +213 -0
  81. data/specs/constraints/bool_enum/bool_enum_relation.rb +117 -0
  82. data/specs/constraints/bool_enum/channel.rb +102 -0
  83. data/specs/constraints/bool_enum/extensional.rb +225 -0
  84. data/specs/constraints/constraint_helper.rb +234 -0
  85. data/specs/constraints/constraint_receivers.rb +103 -0
  86. data/specs/constraints/constraints.rb +26 -0
  87. data/specs/constraints/fixnum_enum/element.rb +58 -0
  88. data/specs/constraints/fixnum_enum/operation.rb +67 -0
  89. data/specs/constraints/int/arithmetic.rb +149 -0
  90. data/specs/constraints/int/channel.rb +101 -0
  91. data/specs/constraints/int/domain.rb +106 -0
  92. data/specs/constraints/int/linear.rb +183 -0
  93. data/specs/constraints/int/linear_properties.rb +97 -0
  94. data/specs/constraints/int/relation.rb +84 -0
  95. data/specs/constraints/int_enum/arithmetic.rb +72 -0
  96. data/specs/constraints/int_enum/channel.rb +57 -0
  97. data/specs/constraints/int_enum/count.rb +72 -0
  98. data/specs/constraints/int_enum/distinct.rb +80 -0
  99. data/specs/constraints/int_enum/element.rb +61 -0
  100. data/specs/constraints/int_enum/equality.rb +29 -0
  101. data/specs/constraints/int_enum/extensional.rb +224 -0
  102. data/specs/constraints/int_enum/sort.rb +167 -0
  103. data/specs/constraints/operands.rb +264 -0
  104. data/specs/constraints/property_helper.rb +443 -0
  105. data/specs/constraints/reification_sugar.rb +69 -0
  106. data/specs/constraints/selected_set/select.rb +56 -0
  107. data/specs/constraints/selected_set/select_properties.rb +157 -0
  108. data/specs/constraints/set/cardinality.rb +58 -0
  109. data/specs/constraints/set/cardinality_properties.rb +46 -0
  110. data/specs/constraints/set/channel.rb +77 -0
  111. data/specs/constraints/set/connection.rb +176 -0
  112. data/specs/constraints/set/domain.rb +197 -0
  113. data/specs/constraints/set/include.rb +36 -0
  114. data/specs/constraints/set/operation.rb +132 -0
  115. data/specs/constraints/set/relation.rb +117 -0
  116. data/specs/constraints/set_elements/relation.rb +84 -0
  117. data/specs/constraints/set_enum/channel.rb +80 -0
  118. data/specs/constraints/set_enum/distinct.rb +59 -0
  119. data/specs/constraints/set_enum/operation.rb +111 -0
  120. data/specs/constraints/set_enum/select.rb +73 -0
  121. data/specs/distribution.rb +14 -0
  122. data/specs/enum_matrix.rb +43 -0
  123. data/specs/enum_wrapper.rb +179 -0
  124. data/specs/examples.rb +17 -0
  125. data/specs/int_var.rb +163 -0
  126. data/specs/logging.rb +24 -0
  127. data/specs/model.rb +325 -0
  128. data/specs/model_sugar.rb +30 -0
  129. data/specs/search.rb +383 -0
  130. data/specs/selected_set.rb +39 -0
  131. data/specs/set_elements.rb +34 -0
  132. data/specs/set_var.rb +82 -0
  133. data/specs/spec_helper.rb +265 -0
  134. data/tasks/all_tasks.rb +1 -0
  135. data/tasks/dependencies.txt +22 -0
  136. data/tasks/distribution.rake +194 -0
  137. data/tasks/rcov.rake +18 -0
  138. data/tasks/specs.rake +21 -0
  139. data/tasks/svn.rake +16 -0
  140. data/tasks/website.rake +51 -0
  141. data/vendor/gecode/win32/lib/libgecodeint.dll +0 -0
  142. data/vendor/gecode/win32/lib/libgecodekernel.dll +0 -0
  143. data/vendor/gecode/win32/lib/libgecodeminimodel.dll +0 -0
  144. data/vendor/gecode/win32/lib/libgecodesearch.dll +0 -0
  145. data/vendor/gecode/win32/lib/libgecodeset.dll +0 -0
  146. data/vendor/gecode/win32/lib/libgecodesupport.dll +0 -0
  147. data/vendor/rust/README +28 -0
  148. data/vendor/rust/bin/cxxgenerator.rb +93 -0
  149. data/vendor/rust/include/rust_checks.hh +116 -0
  150. data/vendor/rust/include/rust_conversions.hh +102 -0
  151. data/vendor/rust/rust.rb +67 -0
  152. data/vendor/rust/rust/attribute.rb +51 -0
  153. data/vendor/rust/rust/bindings.rb +172 -0
  154. data/vendor/rust/rust/class.rb +337 -0
  155. data/vendor/rust/rust/constants.rb +48 -0
  156. data/vendor/rust/rust/container.rb +110 -0
  157. data/vendor/rust/rust/cppifaceparser.rb +129 -0
  158. data/vendor/rust/rust/cwrapper.rb +72 -0
  159. data/vendor/rust/rust/cxxclass.rb +96 -0
  160. data/vendor/rust/rust/element.rb +81 -0
  161. data/vendor/rust/rust/enum.rb +63 -0
  162. data/vendor/rust/rust/function.rb +407 -0
  163. data/vendor/rust/rust/namespace.rb +61 -0
  164. data/vendor/rust/rust/templates/AttributeDefinition.rusttpl +17 -0
  165. data/vendor/rust/rust/templates/AttributeInitBinding.rusttpl +9 -0
  166. data/vendor/rust/rust/templates/BindingsHeader.rusttpl +24 -0
  167. data/vendor/rust/rust/templates/BindingsUnit.rusttpl +46 -0
  168. data/vendor/rust/rust/templates/CWrapperClassDefinitions.rusttpl +64 -0
  169. data/vendor/rust/rust/templates/ClassDeclarations.rusttpl +7 -0
  170. data/vendor/rust/rust/templates/ClassInitialize.rusttpl +6 -0
  171. data/vendor/rust/rust/templates/ConstructorStub.rusttpl +21 -0
  172. data/vendor/rust/rust/templates/CxxClassDefinitions.rusttpl +100 -0
  173. data/vendor/rust/rust/templates/CxxMethodStub.rusttpl +12 -0
  174. data/vendor/rust/rust/templates/CxxStandaloneClassDefinitions.rusttpl +26 -0
  175. data/vendor/rust/rust/templates/EnumDeclarations.rusttpl +3 -0
  176. data/vendor/rust/rust/templates/EnumDefinitions.rusttpl +29 -0
  177. data/vendor/rust/rust/templates/FunctionDefinition.rusttpl +9 -0
  178. data/vendor/rust/rust/templates/FunctionInitAlias.rusttpl +5 -0
  179. data/vendor/rust/rust/templates/FunctionInitBinding.rusttpl +9 -0
  180. data/vendor/rust/rust/templates/MethodInitBinding.rusttpl +9 -0
  181. data/vendor/rust/rust/templates/ModuleDeclarations.rusttpl +3 -0
  182. data/vendor/rust/rust/templates/ModuleDefinitions.rusttpl +3 -0
  183. data/vendor/rust/rust/templates/StandaloneClassDeclarations.rusttpl +7 -0
  184. data/vendor/rust/rust/templates/VariableFunctionCall.rusttpl +14 -0
  185. data/vendor/rust/rust/type.rb +98 -0
  186. data/vendor/rust/test/Makefile +4 -0
  187. data/vendor/rust/test/constants.rb +36 -0
  188. data/vendor/rust/test/cppclass.cc +45 -0
  189. data/vendor/rust/test/cppclass.hh +67 -0
  190. data/vendor/rust/test/cppclass.rb +59 -0
  191. data/vendor/rust/test/cwrapper.c +74 -0
  192. data/vendor/rust/test/cwrapper.h +41 -0
  193. data/vendor/rust/test/cwrapper.rb +56 -0
  194. data/vendor/rust/test/dummyclass.hh +31 -0
  195. data/vendor/rust/test/lib/extension-test.rb +98 -0
  196. data/vendor/rust/test/operators.cc +41 -0
  197. data/vendor/rust/test/operators.hh +39 -0
  198. data/vendor/rust/test/operators.rb +39 -0
  199. data/vendor/rust/test/test-constants.rb +43 -0
  200. data/vendor/rust/test/test-cppclass.rb +82 -0
  201. data/vendor/rust/test/test-cwrapper.rb +80 -0
  202. data/vendor/rust/test/test-operators.rb +42 -0
  203. 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
+