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
@@ -0,0 +1,64 @@
1
+ require 'matrix'
2
+
3
+ module Gecode::Util #:nodoc:
4
+ # Methods that make a matrix an enumerable.
5
+ module MatrixEnumMethods #:nodoc:
6
+ include Enumerable
7
+
8
+ # Iterates over every element in the matrix.
9
+ def each(&block)
10
+ row_size.times do |i|
11
+ column_size.times do |j|
12
+ yield self[i,j]
13
+ end
14
+ end
15
+ end
16
+ end
17
+
18
+ # Extends Matrix so that it's an enumerable.
19
+ class EnumMatrix < Matrix #:nodoc:
20
+ include MatrixEnumMethods
21
+
22
+ def row(i)
23
+ wrap_if_wrapped make_vector_enumerable(super)
24
+ end
25
+
26
+ def column(i)
27
+ wrap_if_wrapped make_vector_enumerable(super)
28
+ end
29
+
30
+ def minor(*args)
31
+ matrix = super
32
+ class <<matrix
33
+ include MatrixEnumMethods
34
+ end
35
+ return wrap_if_wrapped(matrix)
36
+ end
37
+
38
+ private
39
+
40
+ # Makes the specified vector enumerable.
41
+ def make_vector_enumerable(vector)
42
+ class <<vector
43
+ include Enumerable
44
+
45
+ # Iterates over every element in the matrix.
46
+ def each(&block)
47
+ size.times do |i|
48
+ yield self[i]
49
+ end
50
+ end
51
+ end
52
+ return vector
53
+ end
54
+
55
+ # Wraps the specified enumerable if the matrix itself is already wrapped.
56
+ def wrap_if_wrapped(enum)
57
+ if respond_to? :model
58
+ model.wrap_enum(enum)
59
+ else
60
+ enum
61
+ end
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,205 @@
1
+ module Gecode
2
+ class Model
3
+ # Wraps a custom enumerable so that constraints can be specified using it.
4
+ # The argument is altered and returned.
5
+ def wrap_enum(enum)
6
+ unless enum.kind_of? Enumerable
7
+ raise TypeError, 'Only enumerables can be wrapped.'
8
+ end
9
+ if enum.kind_of? Gecode::EnumMethods
10
+ raise ArgumentError, 'The enumration is already wrapped.'
11
+ end
12
+ elements = enum.to_a
13
+ if elements.empty?
14
+ raise ArgumentError, 'Enumerable must not be empty.'
15
+ end
16
+
17
+ if elements.all?{ |var| var.respond_to? :to_int_var }
18
+ elements.map!{ |var| var.to_int_var }
19
+ class <<enum
20
+ include Gecode::IntEnumMethods
21
+ end
22
+ elsif elements.all?{ |var| var.respond_to? :to_bool_var }
23
+ elements.map!{ |var| var.to_bool_var }
24
+ class <<enum
25
+ include Gecode::BoolEnumMethods
26
+ end
27
+ elsif elements.all?{ |var| var.respond_to? :to_set_var }
28
+ elements.map!{ |var| var.to_set_var }
29
+ class <<enum
30
+ include Gecode::SetEnumMethods
31
+ end
32
+ elsif elements.all?{ |var| var.kind_of? Fixnum }
33
+ class <<enum
34
+ include Gecode::FixnumEnumMethods
35
+ end
36
+ else
37
+ raise TypeError, "Enumerable doesn't contain operands #{enum.inspect}."
38
+ end
39
+
40
+ enum.model = self
41
+ return enum
42
+ end
43
+ end
44
+
45
+ # A module containing the methods needed by enumerations containing
46
+ # operands.
47
+ module EnumMethods #:nodoc:
48
+ attr_accessor :model
49
+ # Gets the current space of the model the array is connected to.
50
+ def active_space
51
+ @model.active_space
52
+ end
53
+ end
54
+
55
+ module VariableEnumMethods #:nodoc:
56
+ include EnumMethods
57
+
58
+ # Gets the values of all the operands in the enum.
59
+ def values
60
+ map{ |var| var.value }
61
+ end
62
+ end
63
+
64
+ # A module containing the methods needed by enumerations containing int
65
+ # operands. Requires that it's included in an enumerable.
66
+ module IntEnumMethods #:nodoc:
67
+ include IntEnum::IntEnumOperand
68
+ include VariableEnumMethods
69
+
70
+ # Returns an int variable array with all the bound variables.
71
+ def bind_array
72
+ space = @model.active_space
73
+ unless @bound_space == space
74
+ elements = to_a
75
+ @bound_arr = Gecode::Raw::IntVarArray.new(active_space, elements.size)
76
+ elements.each_with_index{ |var, index| @bound_arr[index] = var.bind }
77
+ @bound_space = space
78
+ end
79
+ return @bound_arr
80
+ end
81
+
82
+ # Returns the receiver.
83
+ def to_int_enum
84
+ self
85
+ end
86
+
87
+ # Returns the smallest range that contains the domains of all integer
88
+ # variables involved.
89
+ def domain_range
90
+ inject(nil) do |range, var|
91
+ min = var.min
92
+ max = var.max
93
+ next min..max if range.nil?
94
+
95
+ range = min..range.last if min < range.first
96
+ range = range.first..max if max > range.last
97
+ range
98
+ end
99
+ end
100
+ end
101
+
102
+ # A dummy class that just shows what methods an int enum responds to.
103
+ class IntEnum::Dummy < Array #:nodoc:
104
+ include IntEnum::IntEnumOperand
105
+ include VariableEnumMethods
106
+ end
107
+
108
+ # A module containing the methods needed by enumerations containing boolean
109
+ # operands. Requires that it's included in an enumerable.
110
+ module BoolEnumMethods #:nodoc:
111
+ include BoolEnum::BoolEnumOperand
112
+ include VariableEnumMethods
113
+
114
+ # Returns a bool variable array with all the bound variables.
115
+ def bind_array
116
+ space = @model.active_space
117
+ unless @bound_space == space
118
+ elements = to_a
119
+ @bound_arr = Gecode::Raw::BoolVarArray.new(active_space, elements.size)
120
+ elements.each_with_index{ |var, index| @bound_arr[index] = var.bind }
121
+ @bound_space = space
122
+ end
123
+ return @bound_arr
124
+ end
125
+
126
+ # Returns the receiver.
127
+ def to_bool_enum
128
+ self
129
+ end
130
+ end
131
+
132
+ # A dummy class that just shows what methods a bool enum responds to.
133
+ class BoolEnum::Dummy < Array #:nodoc:
134
+ include BoolEnum::BoolEnumOperand
135
+ include VariableEnumMethods
136
+ end
137
+
138
+ # A module containing the methods needed by enumerations containing set
139
+ # operands. Requires that it's included in an enumerable.
140
+ module SetEnumMethods #:nodoc:
141
+ include SetEnum::SetEnumOperand
142
+ include VariableEnumMethods
143
+
144
+ # Returns a set variable array with all the bound variables.
145
+ def bind_array
146
+ space = @model.active_space
147
+ unless @bound_space == space
148
+ elements = to_a
149
+ @bound_arr = Gecode::Raw::SetVarArray.new(active_space, elements.size)
150
+ elements.each_with_index{ |var, index| @bound_arr[index] = var.bind }
151
+ @bound_space = space
152
+ end
153
+ return @bound_arr
154
+ end
155
+
156
+ # Returns the receiver.
157
+ def to_set_enum
158
+ self
159
+ end
160
+
161
+ # Returns the range of the union of the contained sets' upper bounds.
162
+ def upper_bound_range
163
+ inject(nil) do |range, var|
164
+ upper_bound = var.upper_bound
165
+ min = upper_bound.min
166
+ max = upper_bound.max
167
+ next min..max if range.nil?
168
+
169
+ range = min..range.last if min < range.first
170
+ range = range.first..max if max > range.last
171
+ range
172
+ end
173
+ end
174
+ end
175
+
176
+ # A dummy class that just shows what methods a set enum responds to.
177
+ class SetEnum::Dummy < Array #:nodoc:
178
+ include SetEnum::SetEnumOperand
179
+ include VariableEnumMethods
180
+ end
181
+
182
+ # A module containing the methods needed by enumerations containing fixnums.
183
+ # Requires that it's included in an enumerable.
184
+ module FixnumEnumMethods #:nodoc:
185
+ include FixnumEnum::FixnumEnumOperand
186
+ include EnumMethods
187
+
188
+ # Returns the receiver.
189
+ def to_fixnum_enum
190
+ self
191
+ end
192
+
193
+ # Returns the smallest range that contains the domains of all integer
194
+ # variables involved.
195
+ def domain_range
196
+ min..max
197
+ end
198
+ end
199
+
200
+ # A dummy class that just shows what methods a fixnum enum responds to.
201
+ class FixnumEnum::Dummy < Array #:nodoc:
202
+ include FixnumEnum::FixnumEnumOperand
203
+ include VariableEnumMethods
204
+ end
205
+ end
@@ -0,0 +1,453 @@
1
+ module Gecode
2
+ # Model is the base class that all models must inherit from.
3
+ #
4
+ # == Formulating problems
5
+ #
6
+ # Models are used to formulate the problems that Gecode should solve.
7
+ # Below is an example of a model that formulates the problem of finding
8
+ # a solution to the following equation system.
9
+ #
10
+ # Equation system:
11
+ # x + y = z
12
+ # x = y - 3
13
+ # 0 <= x,y,z <= 9
14
+ #
15
+ # Model:
16
+ # class EquationProblem < Gecode::Model
17
+ # attr :vars
18
+ #
19
+ # def initialize
20
+ # x, y, z = @vars = int_var_array(3, 0..9)
21
+ #
22
+ # (x + y).must == z
23
+ # x.must == y - 3
24
+ #
25
+ # branch_on @vars
26
+ # end
27
+ # end
28
+ #
29
+ # A model typically consists of three main parts:
30
+ # [Variables] Variables specify how to view the problem. A solution is an
31
+ # assignment of the variables. In the example above we created
32
+ # an array of three integer variables with domains 0..9 and gave
33
+ # it the name +variables+.
34
+ #
35
+ # There are three types of variables: integer variables
36
+ # (Gecode::IntVar, can be assigned one of many
37
+ # possible integer values), boolean variables
38
+ # (Gecode::BoolVar, can be assigned either true or
39
+ # false) and set variables (Gecode::SetVar, can be
40
+ # assigned a set of integers). Variables of the different
41
+ # types are constructed using #int_var, #int_var_array,
42
+ # #int_var_matrix, #bool_var, #bool_var_array,
43
+ # #bool_var_matrix, #set_var, #set_var_array and
44
+ # #set_var_matrix .
45
+ #
46
+ # The various variables all have the functionality of Operand
47
+ # and have many properties depending on their type. For
48
+ # instance integer variables have the properties defined
49
+ # in Gecode::Int::IntOperand and
50
+ # enumerations of integer variables (such as the array
51
+ # +variables+ we used) have the properties defined in
52
+ # Gecode::IntEnum::IntEnumOperand .
53
+ #
54
+ # [Constraints] Constraints are placed on the variables to ensure that a
55
+ # valid assignment of the variables must also be a solution.
56
+ # In the example above we constrained the variables so
57
+ # that all equations were satisfied (which is exactly when
58
+ # we have found a solution).
59
+ #
60
+ # The various constraints that can be placed on the various
61
+ # kinds of operands are found in the respective
62
+ # constraint receivers. For instance, the constraints
63
+ # that can be placed on integer operands are found in
64
+ # Gecode::Int::IntConstraintReceiver and
65
+ # the constraints that can be placed on enumerations of
66
+ # integer operands are found in
67
+ # Gecode::IntEnum::IntEnumConstraintReceiver .
68
+ #
69
+ # [Branching] "branch_on variables" in the example tells Gecode that
70
+ # it should explore the search space until it has assigned
71
+ # +variables+ (or exhausted the search space). It also
72
+ # tells Gecode in what order the search space should be
73
+ # explore, which can have a big effect on the search
74
+ # performance. See #branch_on for details.
75
+ #
76
+ # == Finding solutions
77
+ #
78
+ # Solutions to a formulated problem are found are found by using
79
+ # methods such as #solve!, #solution, #each_solution . If one wants to
80
+ # find a solution that optimizes a certain quantity (i.e. maximizes a
81
+ # certain variable) then one should have a look at #maximize!,
82
+ # #minimize! and #optimize! .
83
+ #
84
+ # The first solution to the example above could for instance be found
85
+ # using
86
+ #
87
+ # puts EquationProblem.new.solve!.vars.values.join(', ')
88
+ #
89
+ # which would find the first solution to the problem, access the
90
+ # assigned values of +variables+ and print them (in order x, y, z).
91
+ #
92
+ # == Shorter ways of formulating problems
93
+ #
94
+ # Problems can also be formulated without defining a new class by
95
+ # using Gecode#solve et al.
96
+ #
97
+ # Additionally one can use "foo_is_an ..." to create an accessor of
98
+ # name foo, without having to use instance variables. The above
99
+ # problem becomes
100
+ # class EquationProblem < Gecode::Model
101
+ # def initialize
102
+ # x, y, z = vars_is_an int_var_array(3, 0..9)
103
+ #
104
+ # (x + y).must == z
105
+ # x.must == y - 3
106
+ #
107
+ # branch_on vars
108
+ # end
109
+ # end
110
+ #
111
+ class Model
112
+ # The largest integer allowed in the domain of an integer variable.
113
+ MAX_INT = Gecode::Raw::IntLimits::MAX
114
+ # The smallest integer allowed in the domain of an integer variable.
115
+ MIN_INT = Gecode::Raw::IntLimits::MIN
116
+
117
+ # The largest integer allowed in the domain of a set variable.
118
+ SET_MAX_INT = Gecode::Raw::SetLimits::MAX
119
+ # The smallest integer allowed in the domain of a set variable.
120
+ SET_MIN_INT = Gecode::Raw::SetLimits::MIN
121
+
122
+ # The largest possible domain for an integer variable.
123
+ LARGEST_INT_DOMAIN = MIN_INT..MAX_INT
124
+ # The largest possible domain, without negative integers, for an
125
+ # integer variable.
126
+ NON_NEGATIVE_INT_DOMAIN = 0..MAX_INT
127
+
128
+ # The largest possible bound for a set variable.
129
+ LARGEST_SET_BOUND = SET_MIN_INT..SET_MAX_INT
130
+
131
+ # Creates a new integer variable with the specified domain. The domain can
132
+ # either be a range, a single element, or an enumeration of elements. If no
133
+ # domain is specified then the largest possible domain is used.
134
+ def int_var(domain = LARGEST_INT_DOMAIN)
135
+ args = domain_arguments(domain)
136
+ IntVar.new(self, variable_creation_space.new_int_var(*args))
137
+ end
138
+
139
+ # Creates an array containing the specified number of integer variables
140
+ # with the specified domain. The domain can either be a range, a single
141
+ # element, or an enumeration of elements. If no domain is specified then
142
+ # the largest possible domain is used.
143
+ def int_var_array(count, domain = LARGEST_INT_DOMAIN)
144
+ args = domain_arguments(domain)
145
+ build_var_array(count) do
146
+ IntVar.new(self, variable_creation_space.new_int_var(*args))
147
+ end
148
+ end
149
+
150
+ # Creates a matrix containing the specified number rows and columns of
151
+ # integer variables with the specified domain. The domain can either be a
152
+ # range, a single element, or an enumeration of elements. If no domain
153
+ # is specified then the largest possible domain is used.
154
+ def int_var_matrix(row_count, col_count, domain = LARGEST_INT_DOMAIN)
155
+ args = domain_arguments(domain)
156
+ build_var_matrix(row_count, col_count) do
157
+ IntVar.new(self, variable_creation_space.new_int_var(*args))
158
+ end
159
+ end
160
+
161
+ # Creates a new boolean variable.
162
+ def bool_var
163
+ BoolVar.new(self, variable_creation_space.new_bool_var)
164
+ end
165
+
166
+ # Creates an array containing the specified number of boolean variables.
167
+ def bool_var_array(count)
168
+ build_var_array(count) do
169
+ BoolVar.new(self, variable_creation_space.new_bool_var)
170
+ end
171
+ end
172
+
173
+ # Creates a matrix containing the specified number rows and columns of
174
+ # boolean variables.
175
+ def bool_var_matrix(row_count, col_count)
176
+ build_var_matrix(row_count, col_count) do
177
+ BoolVar.new(self, variable_creation_space.new_bool_var)
178
+ end
179
+ end
180
+
181
+ # Creates a set variable with the specified domain for greatest lower bound
182
+ # and least upper bound (specified as either a fixnum, range or enum). If
183
+ # no bounds are specified then the empty set is used as greatest lower
184
+ # bound and the largest possible set as least upper bound.
185
+ #
186
+ # A range for the allowed cardinality of the set can also be
187
+ # specified, if none is specified, or nil is given, then the default
188
+ # range (anything) will be used. If only a single Fixnum is
189
+ # specified as cardinality_range then it's used as lower bound.
190
+ def set_var(glb_domain = [], lub_domain = LARGEST_SET_BOUND,
191
+ cardinality_range = nil)
192
+ args = set_bounds_to_parameters(glb_domain, lub_domain, cardinality_range)
193
+ SetVar.new(self, variable_creation_space.new_set_var(*args))
194
+ end
195
+
196
+ # Creates an array containing the specified number of set variables. The
197
+ # parameters beyond count are the same as for #set_var .
198
+ def set_var_array(count, glb_domain = [], lub_domain = LARGEST_SET_BOUND,
199
+ cardinality_range = nil)
200
+ args = set_bounds_to_parameters(glb_domain, lub_domain, cardinality_range)
201
+ build_var_array(count) do
202
+ SetVar.new(self, variable_creation_space.new_set_var(*args))
203
+ end
204
+ end
205
+
206
+ # Creates a matrix containing the specified number of rows and columns
207
+ # filled with set variables. The parameters beyond row and column counts are
208
+ # the same as for #set_var .
209
+ def set_var_matrix(row_count, col_count, glb_domain = [],
210
+ lub_domain = LARGEST_SET_BOUND, cardinality_range = nil)
211
+ args = set_bounds_to_parameters(glb_domain, lub_domain, cardinality_range)
212
+ build_var_matrix(row_count, col_count) do
213
+ SetVar.new(self, variable_creation_space.new_set_var(*args))
214
+ end
215
+ end
216
+
217
+ # Retrieves the currently used space. Calling this method is only allowed
218
+ # when sanctioned by the model beforehand, e.g. when the model asks a
219
+ # constraint to post itself. Otherwise an RuntimeError is raised.
220
+ #
221
+ # The space returned by this method should never be stored, it should be
222
+ # rerequested from the model every time that it's needed.
223
+ def active_space #:nodoc:
224
+ unless @allow_space_access
225
+ raise 'Space access is restricted and the permission to access the ' +
226
+ 'space has not been given.'
227
+ end
228
+ selected_space
229
+ end
230
+
231
+ # Adds the specified constraint to the model. Returns the newly added
232
+ # constraint.
233
+ def add_constraint(constraint) #:nodoc:
234
+ add_interaction do
235
+ constraint.post
236
+ end
237
+ return constraint
238
+ end
239
+
240
+ # Adds a block containing something that interacts with Gecode to a queue
241
+ # where it is potentially executed.
242
+ def add_interaction(&block) #:nodoc:
243
+ gecode_interaction_queue << block
244
+ end
245
+
246
+ # Allows the model's active space to be accessed while the block is
247
+ # executed. Don't use this unless you know what you're doing. Anything that
248
+ # the space is used for (such as bound variables) must be released before
249
+ # the block ends.
250
+ #
251
+ # Returns the result of the block.
252
+ def allow_space_access(&block) #:nodoc:
253
+ # We store the old value so that nested calls don't become a problem, i.e.
254
+ # access is allowed as long as one call to this method is still on the
255
+ # stack.
256
+ old = @allow_space_access
257
+ @allow_space_access = true
258
+ res = yield
259
+ @allow_space_access = old
260
+ return res
261
+ end
262
+
263
+ # Starts tracking a variable that depends on the space. All variables
264
+ # created should call this method for their respective models.
265
+ def track_variable(variable) #:nodoc:
266
+ (@variables ||= []) << variable
267
+ end
268
+
269
+ # Wraps method missing to handle #foo_is_a and #foo_is_an .
270
+ #
271
+ # "<variable_name>_is_a <variable>" or "<variable_name>_is_an <variable>",
272
+ # replacing "<variable_name>" with the variable's name and
273
+ # "<variable>" with the variable, adds an instance variable and
274
+ # accessor with the specified name.
275
+ #
276
+ # The method also returns the variable given.
277
+ #
278
+ # ==== Example
279
+ #
280
+ # # Add an instance variable and accessor named "foo" that return
281
+ # # the integer variable.
282
+ # foo_is_an int_var(0..9)
283
+ #
284
+ # # Add an instance variable and accessor named "bar" that return
285
+ # # the boolean variable array.
286
+ # bar_is_a bool_var_array(2)
287
+ def method_missing(name_symbol, *args)
288
+ name = name_symbol.to_s
289
+ if name =~ /._is_an?$/
290
+ name.sub!(/_is_an?$/, '')
291
+ unless args.size == 1
292
+ raise ArgumentError, "Wrong number of argmuments (#{args.size} for 1)."
293
+ end
294
+ if respond_to? name
295
+ raise ArgumentError, "Method with name #{name} already exists."
296
+ end
297
+ if instance_variable_defined? "@#{name}"
298
+ raise ArgumentError,
299
+ "Instance variable with name @#{name} already exists."
300
+ end
301
+
302
+ # We use the meta class to avoid defining the variable in all
303
+ # other instances of the class.
304
+ eval <<-"end_eval"
305
+ @#{name} = args.first
306
+ class <<self
307
+ attr :#{name}
308
+ end
309
+ end_eval
310
+ return args.first
311
+ else
312
+ super
313
+ end
314
+ end
315
+
316
+ protected
317
+
318
+ # Gets a queue of objects that can be posted to the model's active_space
319
+ # (by calling their post method).
320
+ def gecode_interaction_queue #:nodoc:
321
+ @gecode_interaction_queue ||= []
322
+ end
323
+
324
+ private
325
+
326
+ # Creates an array containing the specified number of variables, all
327
+ # constructed using the provided block..
328
+ def build_var_array(count, &block)
329
+ variables = []
330
+ count.times do
331
+ variables << yield
332
+ end
333
+ return wrap_enum(variables)
334
+ end
335
+
336
+ # Creates a matrix containing the specified number rows and columns of
337
+ # variables, all constructed using the provided block.
338
+ def build_var_matrix(row_count, col_count, &block)
339
+ rows = []
340
+ row_count.times do |i|
341
+ row = []
342
+ col_count.times do |j|
343
+ row << yield
344
+ end
345
+ rows << row
346
+ end
347
+ return wrap_enum(Util::EnumMatrix.rows(rows, false))
348
+ end
349
+
350
+ # Returns the array of arguments that correspond to the specified
351
+ # domain when given to Gecode. The domain can be given as a range,
352
+ # a single number, or an enumerable of elements.
353
+ def domain_arguments(domain)
354
+ if domain.respond_to?(:first) and domain.respond_to?(:last) and
355
+ domain.respond_to?(:exclude_end?)
356
+ if domain.exclude_end?
357
+ return [domain.first, (domain.last - 1)]
358
+ else
359
+ return [domain.first, domain.last]
360
+ end
361
+ elsif domain.kind_of? Enumerable
362
+ array = domain.to_a
363
+ return [Gecode::Raw::IntSet.new(array, array.size)]
364
+ elsif domain.kind_of? Fixnum
365
+ return [domain, domain]
366
+ else
367
+ raise TypeError, 'The domain must be given as an instance of ' +
368
+ "Enumerable or Fixnum, but #{domain.class} was given."
369
+ end
370
+ end
371
+
372
+ # Transforms the argument to a set cardinality range, returns nil if the
373
+ # default range should be used. If arg is a range then that's used,
374
+ # otherwise if the argument is a fixnum it's used as lower bound.
375
+ def to_set_cardinality_range(arg)
376
+ if arg.kind_of? Fixnum
377
+ arg..Gecode::Raw::SetLimits::MAX
378
+ else
379
+ arg
380
+ end
381
+ end
382
+
383
+ # Converts the specified set var domain to parameters accepted by
384
+ # Gecode. The bounds can be specified as a fixnum, range or # enum.
385
+ # The parameters are returned as an array.
386
+ def set_bounds_to_parameters(glb_domain, lub_domain, cardinality_range)
387
+ check_set_bounds(glb_domain, lub_domain)
388
+ args = []
389
+ args << Gecode::Util.constant_set_to_int_set(glb_domain)
390
+ args << Gecode::Util.constant_set_to_int_set(lub_domain)
391
+ card_range = to_set_cardinality_range(cardinality_range)
392
+ if card_range.nil?
393
+ card_range = 0..Gecode::Raw::SetLimits::CARD
394
+ end
395
+ args << card_range.first << card_range.last
396
+ end
397
+
398
+ # Checks whether the specified greatest lower bound is a subset of least
399
+ # upper bound. Raises ArgumentError if that is not the case.
400
+ def check_set_bounds(glb, lub)
401
+ unless valid_set_bounds?(glb, lub)
402
+ raise ArgumentError,
403
+ "Invalid set bounds: #{glb} is not a subset of #{lub}."
404
+ end
405
+ end
406
+
407
+ # Returns whether the greatest lower bound is a subset of least upper
408
+ # bound.
409
+ def valid_set_bounds?(glb, lub)
410
+ return true if glb.respond_to?(:empty?) and glb.empty?
411
+ if glb.kind_of?(Range) and lub.kind_of?(Range)
412
+ glb.first >= lub.first and glb.last <= lub.last
413
+ else
414
+ glb = [glb] if glb.kind_of?(Fixnum)
415
+ lub = [lub] if lub.kind_of?(Fixnum)
416
+ (glb.to_a - lub.to_a).empty?
417
+ end
418
+ end
419
+
420
+ # Retrieves the base from which searches are made.
421
+ def base_space
422
+ @base_space ||= Gecode::Raw::Space.new
423
+ end
424
+
425
+ # Retrieves the currently selected space, the one which constraints and
426
+ # variables should be bound to.
427
+ def selected_space
428
+ return @active_space unless @active_space.nil?
429
+ self.active_space = base_space
430
+ end
431
+
432
+ # Retrieves the space that should be used for variable creation.
433
+ def variable_creation_space
434
+ @variable_creation_space || selected_space
435
+ end
436
+
437
+ # Executes any interactions with Gecode still waiting in the queue
438
+ # (emptying the queue) in the process.
439
+ def perform_queued_gecode_interactions
440
+ allow_space_access do
441
+ gecode_interaction_queue.each{ |con| con.call }
442
+ gecode_interaction_queue.clear # Empty the queue.
443
+ end
444
+ end
445
+
446
+ # Switches the active space used (the space from which variables are read
447
+ # and to which constraints are posted). @active_space should never be
448
+ # assigned directly.
449
+ def active_space=(new_space)
450
+ @active_space = new_space
451
+ end
452
+ end
453
+ end