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,9 @@
1
+ require 'gecoder/interface/binding_changes'
2
+ require 'gecoder/interface/enum_matrix'
3
+ require 'gecoder/interface/model'
4
+ require 'gecoder/interface/search'
5
+ require 'gecoder/interface/constraints'
6
+ require 'gecoder/interface/variables'
7
+ require 'gecoder/interface/enum_wrapper'
8
+ require 'gecoder/interface/branch'
9
+ require 'gecoder/interface/model_sugar'
@@ -0,0 +1,9 @@
1
+ # This file adds a small layer on top of the bindings.
2
+ module GecodeRaw #:nodoc: all
3
+ class Space
4
+ # Used by Gecode during BAB-search.
5
+ def constrain(best_so_far_space)
6
+ Gecode::Model.constrain(self, best_so_far_space)
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,163 @@
1
+ module Gecode
2
+ class Model
3
+ # Specifies which variables that should be branched on (given as an
4
+ # enum of operands or as a single operand). One can optionally
5
+ # also select which of the variables that should be used first with
6
+ # the :variable option and which value in that variable's domain
7
+ # that should be used with the :value option. If nothing is
8
+ # specified then :variable uses :none and value uses :min.
9
+ #
10
+ # The following values can be used with :variable for integer and
11
+ # boolean enums:
12
+ # [:none] The first unassigned variable.
13
+ # [:smallest_min] The one with the smallest minimum.
14
+ # [:largest_min] The one with the largest minimum.
15
+ # [:smallest_max] The one with the smallest maximum.
16
+ # [:largest_max] The one with the largest maximum.
17
+ # [:smallest_size] The one with the smallest size.
18
+ # [:largest_size] The one with the larges size.
19
+ # [:smallest_degree] The one with the smallest degree. The degree of a
20
+ # variable is defined as the number of dependant
21
+ # propagators. In case of ties, choose the variable
22
+ # with smallest domain.
23
+ # [:largest_degree] The one with the largest degree. The degree of a
24
+ # variable is defined as the number of dependant
25
+ # propagators. In case of ties, choose the variable
26
+ # with smallest domain.
27
+ # [:smallest_min_regret] The one with the smallest min-regret. The
28
+ # min-regret of a variable is the difference between
29
+ # the smallest and second-smallest value still in
30
+ # the domain.
31
+ # [:largest_min_regret] The one with the largest min-regret. The
32
+ # min-regret of a variable is the difference between
33
+ # the smallest and second-smallest value still in
34
+ # the domain.
35
+ # [:smallest_max_regret] The one with the smallest max-regret The
36
+ # max-regret of a variable is the difference between
37
+ # the largest and second-largest value still in
38
+ # the domain.
39
+ # [:largest_max_regret] The one with the largest max-regret. The
40
+ # max-regret of a variable is the difference between
41
+ # the largest and second-largest value still in
42
+ # the domain.
43
+ #
44
+ # The following values can be used with :value for integer and boolean
45
+ # enums:
46
+ # [:min] Selects the smallest value.
47
+ # [:med] Select the median value.
48
+ # [:max] Selects the largest vale
49
+ # [:split_min] Selects the lower half of the domain.
50
+ # [:split_max] Selects the upper half of the domain.
51
+ #
52
+ # The following values can be used with :variable for set enums:
53
+ # [:none] The first unassigned set.
54
+ # [:smallest_cardinality] The one with the smallest cardinality.
55
+ # [:largest_cardinality] The one with the largest cardinality.
56
+ # [:smallest_unknown] The one with the smallest number of unknown
57
+ # elements
58
+ # [:largest_unknown] The one with the largest number of unknown
59
+ # elements
60
+ #
61
+ # The following values can be used with :value set enums:
62
+ # [:min] Selects the smallest value in the unknown part of the set.
63
+ # [:max] Selects the largest value in the unknown part of the set.
64
+ def branch_on(variables, options = {})
65
+ if variables.respond_to?(:to_int_var) or
66
+ variables.respond_to?(:to_bool_var) or
67
+ variables.respond_to?(:to_set_var)
68
+ variables = wrap_enum [variables]
69
+ end
70
+
71
+ if variables.respond_to? :to_int_enum
72
+ add_branch(variables.to_int_enum, options,
73
+ Constants::BRANCH_INT_VAR_CONSTANTS,
74
+ Constants::BRANCH_INT_VALUE_CONSTANTS)
75
+ elsif variables.respond_to? :to_bool_enum
76
+ add_branch(variables.to_bool_enum, options,
77
+ Constants::BRANCH_INT_VAR_CONSTANTS,
78
+ Constants::BRANCH_INT_VALUE_CONSTANTS)
79
+ elsif variables.respond_to? :to_set_enum
80
+ add_branch(variables.to_set_enum, options,
81
+ Constants::BRANCH_SET_VAR_CONSTANTS,
82
+ Constants::BRANCH_SET_VALUE_CONSTANTS)
83
+ else
84
+ raise TypeError, "Unknown type of variable enum #{variables.class}."
85
+ end
86
+ end
87
+
88
+ private
89
+
90
+ # This is a hack to get RDoc to ignore the constants.
91
+ module Constants #:nodoc:
92
+ # Maps the names of the supported variable branch strategies for
93
+ # integer and booleans to the corresponding constant in Gecode.
94
+ BRANCH_INT_VAR_CONSTANTS = {
95
+ :none => Gecode::Raw::INT_VAR_NONE,
96
+ :smallest_min => Gecode::Raw::INT_VAR_MIN_MIN,
97
+ :largest_min => Gecode::Raw::INT_VAR_MIN_MAX,
98
+ :smallest_max => Gecode::Raw::INT_VAR_MAX_MIN,
99
+ :largest_max => Gecode::Raw::INT_VAR_MAX_MAX,
100
+ :smallest_size => Gecode::Raw::INT_VAR_SIZE_MIN,
101
+ :largest_size => Gecode::Raw::INT_VAR_SIZE_MAX,
102
+ :smallest_degree => Gecode::Raw::INT_VAR_DEGREE_MIN,
103
+ :largest_degree => Gecode::Raw::INT_VAR_DEGREE_MAX,
104
+ :smallest_min_regret => Gecode::Raw::INT_VAR_REGRET_MIN_MIN,
105
+ :largest_min_regret => Gecode::Raw::INT_VAR_REGRET_MIN_MAX,
106
+ :smallest_max_regret => Gecode::Raw::INT_VAR_REGRET_MAX_MIN,
107
+ :largest_max_regret => Gecode::Raw::INT_VAR_REGRET_MAX_MAX
108
+ }
109
+ # Maps the names of the supported variable branch strategies for sets to
110
+ # the corresponding constant in Gecode.
111
+ BRANCH_SET_VAR_CONSTANTS = { #:nodoc:
112
+ :none => Gecode::Raw::SET_VAR_NONE,
113
+ :smallest_cardinality => Gecode::Raw::SET_VAR_MIN_CARD,
114
+ :largest_cardinality => Gecode::Raw::SET_VAR_MAX_CARD,
115
+ :smallest_unknown => Gecode::Raw::SET_VAR_MIN_UNKNOWN_ELEM,
116
+ :largest_unknown => Gecode::Raw::SET_VAR_MAX_UNKNOWN_ELEM
117
+ }
118
+
119
+ # Maps the names of the supported value branch strategies for integers and
120
+ # booleans to the corresponding constant in Gecode.
121
+ BRANCH_INT_VALUE_CONSTANTS = { #:nodoc:
122
+ :min => Gecode::Raw::INT_VAL_MIN,
123
+ :med => Gecode::Raw::INT_VAL_MED,
124
+ :max => Gecode::Raw::INT_VAL_MAX,
125
+ :split_min => Gecode::Raw::INT_VAL_SPLIT_MIN,
126
+ :split_max => Gecode::Raw::INT_VAL_SPLIT_MAX
127
+ }
128
+ # Maps the names of the supported value branch strategies for sets to the
129
+ # corresponding constant in Gecode.
130
+ BRANCH_SET_VALUE_CONSTANTS = { #:nodoc:
131
+ :min => Gecode::Raw::SET_VAL_MIN,
132
+ :max => Gecode::Raw::SET_VAL_MAX
133
+ }
134
+ end
135
+
136
+ # Adds a branching selection for the specified variables with the specified
137
+ # options. The hashes are used to decode the options into Gecode's
138
+ # constants.
139
+ def add_branch(variables, options, branch_var_hash, branch_value_hash)
140
+ # Extract optional arguments.
141
+ var_strat = options.delete(:variable) || :none
142
+ val_strat = options.delete(:value) || :min
143
+
144
+ # Check that the options are correct.
145
+ unless options.empty?
146
+ raise ArgumentError, 'Unknown branching option given: ' +
147
+ options.keys.join(', ')
148
+ end
149
+ unless branch_var_hash.include? var_strat
150
+ raise ArgumentError, "Unknown variable selection strategy: #{var_strat}"
151
+ end
152
+ unless branch_value_hash.include? val_strat
153
+ raise ArgumentError, "Unknown value selection strategy: #{val_strat}"
154
+ end
155
+
156
+ # Add the branching as a gecode interaction.
157
+ add_interaction do
158
+ Gecode::Raw.branch(active_space, variables.bind_array,
159
+ branch_var_hash[var_strat], branch_value_hash[val_strat])
160
+ end
161
+ end
162
+ end
163
+ end
@@ -0,0 +1,471 @@
1
+ module Gecode
2
+ # An error signaling that the constraint specified is missing (e.g. one tried
3
+ # to negate a constraint, but no negated form is implemented).
4
+ class MissingConstraintError < StandardError
5
+ end
6
+
7
+ # Describes an operand, something that a constraint can be placed
8
+ # on. Constraints are placed by calling #must or #must_not (the
9
+ # latter negates the constraint). This produces a
10
+ # ConstraintReceiver, which defines methods that places constraints
11
+ # on the operand.
12
+ #
13
+ # In general this produces something like the following.
14
+ #
15
+ # operand.must.constraint_method(params)
16
+ #
17
+ # See e.g. Gecode::Int::IntOperand for concrete examples.
18
+ #
19
+ # Classes that mix in Operand must define the methods #model
20
+ # and #construct_receiver. They should also define a method that converts
21
+ # the operand into a variable of the operand's type (e.g. int var
22
+ # operands should define a method #to_int_var that returns an
23
+ # instance of Gecode::IntVar that represents the operand). The
24
+ # latter method should be used by constraints to fetch variables
25
+ # needed when posting constraints. The presence of the method should
26
+ # also be used for type checking (rather than e.g. checking whether
27
+ # a parameter is of type IntOperand).
28
+ module Operand
29
+ # Specifies that a constraint must hold for the left hand side.
30
+ def must
31
+ construct_receiver :lhs => self, :negate => false
32
+ end
33
+ alias_method :must_be, :must
34
+
35
+ # Specifies that the negation of a constraint must hold for the left hand
36
+ # side.
37
+ def must_not
38
+ construct_receiver :lhs => self, :negate => true
39
+ end
40
+ alias_method :must_not_be, :must_not
41
+
42
+ # Fetches the model that the operand belongs to.
43
+ def model
44
+ raise NotImplementedError, 'Abstract method has not been implemented.'
45
+ end
46
+
47
+ private
48
+
49
+ # Constructs the appropriate constraint receiver given the
50
+ # specified parameters.
51
+ def construct_receiver(params)
52
+ raise NotImplementedError, 'Abstract method has not been implemented.'
53
+ end
54
+ end
55
+
56
+ # Describes a constraint receiver, something that receives and
57
+ # places constraints on various Operand. Constraint receivers
58
+ # are created by calling #must or #must_not (the latter negates
59
+ # the constraint) on something that mixes in Operand.
60
+ #
61
+ # A constraint is placed on an Operand +operand+ as follows:
62
+ #
63
+ # operand.must.constraint_method(params)
64
+ #
65
+ # The constraint receiver is created by the call to #must and the
66
+ # constraint is then placed by the call to #constraint_method.
67
+ # See e.g. Gecode::Int::IntConstraintReceiver for
68
+ # concrete examples.
69
+ #
70
+ # The following options can be specified in a hash with symbols as
71
+ # keys when placing a constraint:
72
+ #
73
+ # [:strength] The propagation strength suggests how much effort the
74
+ # solver should put into trying to prune the domains of
75
+ # variables using the constraint.
76
+ #
77
+ # The allowed values are:
78
+ # [:value] Value consistency (naive).
79
+ # [:bounds] Bounds consistency. The bounds of the operand
80
+ # will always be constrained as much as possible
81
+ # (but pruning may not be done inside the
82
+ # bounds, even though it may be possible).
83
+ # [:domain] Domain consistency. All values that can be pruned
84
+ # away, given the current amount of information,
85
+ # are pruned away.
86
+ # [:default] Uses the default consistency of the constraint.
87
+ #
88
+ # The strength generally progresses as
89
+ # :value < :bounds < :domain (:value being the weakest,
90
+ # :domain being the strongest). A higher strength can
91
+ # reduce the search space quicker, but at the cost of
92
+ # making each propagation more costly.
93
+ #
94
+ # [:kind] The propagation kind option suggests the implementation
95
+ # that should be preferred if there are multiple
96
+ # implementations of a constraint.
97
+ #
98
+ # The different kinds are:
99
+ # [:speed] Prefer speed over memory consumption.
100
+ # [:memory] Prefer low memory consumption over speed.
101
+ # [:default] Uses the constraint's default propagation kind.
102
+ #
103
+ # [:reify] Reification is used to link a constraint to a boolean
104
+ # operand in such a way that the variable is true if and
105
+ # only if the constraint is satisfied. The propagation
106
+ # goes both ways, so if the variable is constrained to be
107
+ # false then the constraint is not allowed to be
108
+ # satisfied.
109
+ #
110
+ # Reification can be thought of as a last resort glue which
111
+ # can be used to combine constraints so that e.g. exactly
112
+ # 3 out of 17 constraints must be satisfied.
113
+ #
114
+ # Not all constraints accept all options. Constraints that have sets
115
+ # as operands (e.g. SetConstraintReceiver and
116
+ # SetEnumConstraintReceiver) do not accept the :strength and :kind
117
+ # options, all other do. Some constraints do not accept the :reify
118
+ # option.
119
+ #
120
+ # See e.g. Gecode::Int::IntConstraintReceiver for
121
+ # concrete examples of options being specified.
122
+ class ConstraintReceiver
123
+ # Constructs a new expression with the specified parameters. The
124
+ # parameters should at least contain the keys :lhs, and :negate.
125
+ #
126
+ # Raises ArgumentError if any of those keys are missing or if :lhs
127
+ # is not an operand.
128
+ def initialize(model, params)
129
+ unless params.has_key?(:lhs) and params.has_key?(:negate)
130
+ raise ArgumentError, 'Expression requires at least :lhs, ' +
131
+ "and :negate as parameter keys, got #{params.keys.join(', ')}."
132
+ end
133
+ unless params[:lhs].kind_of? Operand
134
+ raise ArgumentError, 'Expected :lhs to be an operand, received ' +
135
+ "#{params[:lhs].class}."
136
+ end
137
+
138
+ @model = model
139
+ @params = params
140
+ end
141
+
142
+ private
143
+
144
+ # Provides commutativity for the constraint with the specified
145
+ # method name. If the method with the specified method name is
146
+ # called with something that, when given to the block, evaluates
147
+ # to true, then the constraint will be called on the right hand
148
+ # side with the left hand side as argument.
149
+ #
150
+ # The original constraint method is assumed to take two arguments:
151
+ # a right hand side and a hash of options.
152
+ def self.provide_commutativity(constraint_name, &block)
153
+ unique_id = constraint_name.to_sym.to_i
154
+ pre_alias_method_name = 'pre_commutivity_' << unique_id.to_s
155
+ if method_defined? constraint_name
156
+ alias_method pre_alias_method_name, constraint_name
157
+ end
158
+
159
+ module_eval <<-end_code
160
+ @@commutivity_check_#{unique_id} = block
161
+ def #{constraint_name}(rhs, options = {})
162
+ if @@commutivity_check_#{unique_id}.call(rhs, options)
163
+ if @params[:negate]
164
+ rhs.must_not.method(:#{constraint_name}).call(
165
+ @params[:lhs], options)
166
+ else
167
+ rhs.must.method(:#{constraint_name}).call(
168
+ @params[:lhs], options)
169
+ end
170
+ else
171
+ if self.class.method_defined? :#{pre_alias_method_name}
172
+ #{pre_alias_method_name}(rhs, options)
173
+ else
174
+ raise TypeError, \"Unexpected argument type \#{rhs.class}.\"
175
+ end
176
+ end
177
+ end
178
+ end_code
179
+ end
180
+
181
+ # Creates aliases for any defined comparison methods.
182
+ def self.alias_comparison_methods
183
+ Gecode::Util::COMPARISON_ALIASES.each_pair do |orig, aliases|
184
+ if instance_methods.include?(orig.to_s)
185
+ aliases.each do |name|
186
+ alias_method(name, orig)
187
+ end
188
+ end
189
+ end
190
+ end
191
+
192
+ # Creates aliases for any defined set methods.
193
+ def self.alias_set_methods
194
+ Gecode::Util::SET_ALIASES.each_pair do |orig, aliases|
195
+ if instance_methods.include?(orig.to_s)
196
+ aliases.each do |name|
197
+ alias_method(name, orig)
198
+ end
199
+ end
200
+ end
201
+ end
202
+ end
203
+
204
+ # Base class for all constraints.
205
+ class Constraint #:nodoc:
206
+ # Creates a constraint with the specified parameters, bound to the
207
+ # specified model.
208
+ def initialize(model, params)
209
+ @model = model
210
+ @params = params.clone
211
+ end
212
+
213
+ # Posts the constraint, adding it to the model. This is an abstract
214
+ # method and should be overridden by all sub-classes.
215
+ def post
216
+ raise NotImplementedError, 'Abstract method has not been implemented.'
217
+ end
218
+
219
+ private
220
+
221
+ # Gives an array of the values selected for the standard propagation
222
+ # options (propagation strength and propagation kind) in the order that
223
+ # they are given when posting constraints to Gecode.
224
+ def propagation_options
225
+ Gecode::Util::extract_propagation_options(@params)
226
+ end
227
+ end
228
+
229
+ # A constraint that can be specified by providing a block containing the
230
+ # post method.
231
+ class BlockConstraint < Constraint #:nodoc:
232
+ def initialize(model, params, &block)
233
+ super(model, params)
234
+ @proc = block
235
+ end
236
+
237
+ def post
238
+ @proc.call
239
+ end
240
+ end
241
+
242
+ # A module that provides some utility-methods for constraints.
243
+ module Util #:nodoc:
244
+ # Maps the name used in options to the value used in Gecode for
245
+ # propagation strengths.
246
+ PROPAGATION_STRENGTHS = {
247
+ :default => Gecode::Raw::ICL_DEF,
248
+ :value => Gecode::Raw::ICL_VAL,
249
+ :bounds => Gecode::Raw::ICL_BND,
250
+ :domain => Gecode::Raw::ICL_DOM
251
+ }
252
+
253
+ # Maps the name used in options to the value used in Gecode for
254
+ # propagation kinds.
255
+ PROPAGATION_KINDS = {
256
+ :default => Gecode::Raw::PK_DEF,
257
+ :speed => Gecode::Raw::PK_SPEED,
258
+ :memory => Gecode::Raw::PK_MEMORY,
259
+ }
260
+
261
+ # Maps the names of the methods to the corresponding integer relation
262
+ # type in Gecode.
263
+ RELATION_TYPES = {
264
+ :== => Gecode::Raw::IRT_EQ,
265
+ :<= => Gecode::Raw::IRT_LQ,
266
+ :< => Gecode::Raw::IRT_LE,
267
+ :>= => Gecode::Raw::IRT_GQ,
268
+ :> => Gecode::Raw::IRT_GR
269
+ }
270
+ # The same as above, but negated.
271
+ NEGATED_RELATION_TYPES = {
272
+ :== => Gecode::Raw::IRT_NQ,
273
+ :<= => Gecode::Raw::IRT_GR,
274
+ :< => Gecode::Raw::IRT_GQ,
275
+ :>= => Gecode::Raw::IRT_LE,
276
+ :> => Gecode::Raw::IRT_LQ
277
+ }
278
+
279
+ # Maps the names of the methods to the corresponding set relation type in
280
+ # Gecode.
281
+ SET_RELATION_TYPES = {
282
+ :== => Gecode::Raw::SRT_EQ,
283
+ :superset => Gecode::Raw::SRT_SUP,
284
+ :subset => Gecode::Raw::SRT_SUB,
285
+ :disjoint => Gecode::Raw::SRT_DISJ,
286
+ :complement => Gecode::Raw::SRT_CMPL
287
+ }
288
+ # The same as above, but negated.
289
+ NEGATED_SET_RELATION_TYPES = {
290
+ :== => Gecode::Raw::SRT_NQ
291
+ }
292
+ # Maps the names of the methods to the corresponding set operation type in
293
+ # Gecode.
294
+ SET_OPERATION_TYPES = {
295
+ :union => Gecode::Raw::SOT_UNION,
296
+ :disjoint_union => Gecode::Raw::SOT_DUNION,
297
+ :intersection => Gecode::Raw::SOT_INTER,
298
+ :minus => Gecode::Raw::SOT_MINUS
299
+ }
300
+
301
+ # Various method aliases for comparison methods. Maps the original
302
+ # (symbol) name to an array of aliases.
303
+ COMPARISON_ALIASES = {
304
+ :== => [:equal, :equal_to],
305
+ :> => [:greater, :greater_than],
306
+ :>= => [:greater_or_equal, :greater_than_or_equal_to],
307
+ :< => [:less, :less_than],
308
+ :<= => [:less_or_equal, :less_than_or_equal_to]
309
+ }
310
+ SET_ALIASES = {
311
+ :== => [:equal, :equal_to],
312
+ :superset => [:superset_of],
313
+ :subset => [:subset_of],
314
+ :disjoint => [:disjoint_with],
315
+ :complement => [:complement_of]
316
+ }
317
+
318
+ module_function
319
+
320
+ # Decodes the common options to constraints: strength, kind and
321
+ # reification. Returns a hash with up to three values. :strength is the
322
+ # strength that should be used for the constraint, :kind is the
323
+ # propagation kind that should be used, and :reif is the (bound) boolean
324
+ # operand that should be used for reification. The decoded options are
325
+ # removed from the hash (so in general the hash will be consumed in the
326
+ # process).
327
+ #
328
+ # Raises ArgumentError if an unrecognized option is found in the specified
329
+ # hash. Or if an unrecognized strength is given. Raises TypeError if the
330
+ # reification operand is not a boolean operand.
331
+ def decode_options(options)
332
+ # Propagation strength.
333
+ strength = options.delete(:strength) || :default
334
+ unless PROPAGATION_STRENGTHS.include? strength
335
+ raise ArgumentError, "Unrecognized propagation strength #{strength}."
336
+ end
337
+
338
+ # Propagation kind.
339
+ kind = options.delete(:kind) || :default
340
+ unless PROPAGATION_KINDS.include? kind
341
+ raise ArgumentError, "Unrecognized propagation kind #{kind}."
342
+ end
343
+
344
+ # Reification.
345
+ reif_var = options.delete(:reify)
346
+ unless reif_var.nil? or reif_var.respond_to? :to_bool_var
347
+ raise TypeError, 'Only boolean operands may be used for reification.'
348
+ end
349
+
350
+ # Check for unrecognized options.
351
+ unless options.empty?
352
+ raise ArgumentError, 'Unrecognized constraint option: ' +
353
+ options.keys.first.to_s
354
+ end
355
+ return {
356
+ :strength => PROPAGATION_STRENGTHS[strength],
357
+ :kind => PROPAGATION_KINDS[kind],
358
+ :reif => reif_var
359
+ }
360
+ end
361
+
362
+ # Converts the different ways to specify constant sets in the interface
363
+ # to the form that the set should be represented in Gecode (possibly
364
+ # multiple paramters. The different forms accepted are:
365
+ # * Single instance of Fixnum (singleton set).
366
+ # * Range (set containing all numbers in range), treated differently from
367
+ # other enumerations.
368
+ # * Enumeration of integers (set contaning all numbers in set).
369
+ def constant_set_to_params(constant_set)
370
+ unless constant_set?(constant_set)
371
+ raise TypeError, "Expected a constant set, got: #{constant_set}."
372
+ end
373
+
374
+ if constant_set.kind_of? Range
375
+ return constant_set.first, constant_set.last
376
+ elsif constant_set.kind_of? Fixnum
377
+ return constant_set
378
+ else
379
+ constant_set = constant_set.to_a
380
+ return Gecode::Raw::IntSet.new(constant_set, constant_set.size)
381
+ end
382
+ end
383
+
384
+ # Converts the different ways to specify constant sets in the interface
385
+ # to an instance of Gecode::Raw::IntSet. The different forms accepted are:
386
+ # * Single instance of Fixnum (singleton set).
387
+ # * Range (set containing all numbers in range), treated differently from
388
+ # other enumerations.
389
+ # * Enumeration of integers (set contaning all numbers in set).
390
+ def constant_set_to_int_set(constant_set)
391
+ unless constant_set?(constant_set)
392
+ raise TypeError, "Expected a constant set, got: #{constant_set}."
393
+ end
394
+
395
+ if constant_set.kind_of? Range
396
+ return Gecode::Raw::IntSet.new(constant_set.first, constant_set.last)
397
+ elsif constant_set.kind_of? Fixnum
398
+ return Gecode::Raw::IntSet.new([constant_set], 1)
399
+ else
400
+ constant_set = constant_set.to_a
401
+ return Gecode::Raw::IntSet.new(constant_set, constant_set.size)
402
+ end
403
+ end
404
+
405
+ # Checks whether the specified expression is regarded as a constant set.
406
+ # Returns true if it is, false otherwise.
407
+ def constant_set?(expression)
408
+ return (
409
+ expression.kind_of?(Range) && # It's a range.
410
+ expression.first.kind_of?(Fixnum) &&
411
+ expression.last.kind_of?(Fixnum)) ||
412
+ expression.kind_of?(Fixnum) || # It's a single fixnum.
413
+ (expression.kind_of?(Enumerable) && # It's an enum of fixnums.
414
+ expression.all?{ |e| e.kind_of? Fixnum })
415
+ end
416
+
417
+ # Extracts an array of the values selected for the standard propagation
418
+ # options (propagation strength and propagation kind) from the hash of
419
+ # parameters given. The options are returned in the order that they are
420
+ # given when posting constraints to Gecode.
421
+ def extract_propagation_options(params)
422
+ params.values_at(:strength, :kind)
423
+ end
424
+ end
425
+
426
+ # A module that contains utility-methods for extensional constraints.
427
+ module Util::Extensional #:nodoc:
428
+ module_function
429
+
430
+ # Checks that the specified enumeration is an enumeration containing
431
+ # one or more tuples of the specified size. It also allows the caller
432
+ # to define additional tests by providing a block, which is given each
433
+ # tuple. If a test fails then an appropriate error is raised.
434
+ def perform_tuple_checks(tuples, expected_size, &additional_test)
435
+ unless tuples.respond_to?(:each)
436
+ raise TypeError, 'Expected an enumeration with tuples, got ' +
437
+ "#{tuples.class}."
438
+ end
439
+
440
+ if tuples.empty?
441
+ raise ArgumentError, 'One or more tuples must be specified.'
442
+ end
443
+
444
+ tuples.each do |tuple|
445
+ unless tuple.respond_to?(:each)
446
+ raise TypeError, 'Expected an enumeration containing enumeraions, ' +
447
+ "got #{tuple.class}."
448
+ end
449
+
450
+ unless tuple.size == expected_size
451
+ raise ArgumentError, 'All tuples must be of the same size as the ' +
452
+ 'number of operands in the array.'
453
+ end
454
+
455
+ yield tuple
456
+ end
457
+ end
458
+ end
459
+ end
460
+
461
+ require 'gecoder/interface/constraints/reifiable_constraints'
462
+ require 'gecoder/interface/constraints/int_var_constraints'
463
+ require 'gecoder/interface/constraints/int_enum_constraints'
464
+ require 'gecoder/interface/constraints/bool_var_constraints'
465
+ require 'gecoder/interface/constraints/bool_enum_constraints'
466
+ require 'gecoder/interface/constraints/set_var_constraints'
467
+ require 'gecoder/interface/constraints/set_enum_constraints'
468
+ require 'gecoder/interface/constraints/selected_set_constraints'
469
+ require 'gecoder/interface/constraints/set_elements_constraints'
470
+ require 'gecoder/interface/constraints/fixnum_enum_constraints'
471
+ require 'gecoder/interface/constraints/extensional_regexp'