gecoder-with-gecode 0.9.0-x86-mswin32-60

Sign up to get free protection for your applications and to get access to all the features.
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