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,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'