gecoder 0.8.3 → 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (142) hide show
  1. data/CHANGES +15 -0
  2. data/README +6 -2
  3. data/example/equation_system.rb +15 -0
  4. data/example/magic_sequence.rb +7 -7
  5. data/example/money.rb +36 -0
  6. data/example/queens.rb +7 -8
  7. data/example/send_most_money.rb +1 -1
  8. data/example/square_tiling.rb +2 -2
  9. data/example/sudoku-set.rb +11 -12
  10. data/example/sudoku.rb +40 -45
  11. data/ext/extconf.rb +0 -0
  12. data/lib/gecoder/bindings.rb +42 -0
  13. data/lib/gecoder/bindings/bindings.rb +16 -0
  14. data/lib/gecoder/interface.rb +2 -1
  15. data/lib/gecoder/interface/branch.rb +16 -9
  16. data/lib/gecoder/interface/constraints.rb +410 -451
  17. data/lib/gecoder/interface/constraints/bool/boolean.rb +205 -213
  18. data/lib/gecoder/interface/constraints/bool/channel.rb +4 -5
  19. data/lib/gecoder/interface/constraints/bool/linear.rb +192 -21
  20. data/lib/gecoder/interface/constraints/bool_enum/channel.rb +43 -39
  21. data/lib/gecoder/interface/constraints/bool_enum/extensional.rb +43 -49
  22. data/lib/gecoder/interface/constraints/bool_enum/relation.rb +38 -71
  23. data/lib/gecoder/interface/constraints/bool_enum_constraints.rb +73 -22
  24. data/lib/gecoder/interface/constraints/bool_var_constraints.rb +140 -61
  25. data/lib/gecoder/interface/constraints/extensional_regexp.rb +4 -4
  26. data/lib/gecoder/interface/constraints/fixnum_enum/element.rb +63 -0
  27. data/lib/gecoder/interface/constraints/fixnum_enum/operation.rb +65 -0
  28. data/lib/gecoder/interface/constraints/fixnum_enum_constraints.rb +42 -0
  29. data/lib/gecoder/interface/constraints/int/arithmetic.rb +131 -130
  30. data/lib/gecoder/interface/constraints/int/channel.rb +21 -31
  31. data/lib/gecoder/interface/constraints/int/domain.rb +45 -42
  32. data/lib/gecoder/interface/constraints/int/linear.rb +85 -239
  33. data/lib/gecoder/interface/constraints/int/relation.rb +141 -0
  34. data/lib/gecoder/interface/constraints/int_enum/arithmetic.rb +55 -64
  35. data/lib/gecoder/interface/constraints/int_enum/channel.rb +35 -37
  36. data/lib/gecoder/interface/constraints/int_enum/count.rb +53 -78
  37. data/lib/gecoder/interface/constraints/int_enum/distinct.rb +36 -46
  38. data/lib/gecoder/interface/constraints/int_enum/element.rb +39 -57
  39. data/lib/gecoder/interface/constraints/int_enum/equality.rb +15 -19
  40. data/lib/gecoder/interface/constraints/int_enum/extensional.rb +65 -72
  41. data/lib/gecoder/interface/constraints/int_enum/sort.rb +42 -45
  42. data/lib/gecoder/interface/constraints/int_enum_constraints.rb +79 -22
  43. data/lib/gecoder/interface/constraints/int_var_constraints.rb +215 -44
  44. data/lib/gecoder/interface/constraints/reifiable_constraints.rb +14 -14
  45. data/lib/gecoder/interface/constraints/selected_set/select.rb +120 -0
  46. data/lib/gecoder/interface/constraints/selected_set_constraints.rb +75 -0
  47. data/lib/gecoder/interface/constraints/set/cardinality.rb +43 -53
  48. data/lib/gecoder/interface/constraints/set/channel.rb +26 -29
  49. data/lib/gecoder/interface/constraints/set/connection.rb +89 -152
  50. data/lib/gecoder/interface/constraints/set/domain.rb +112 -65
  51. data/lib/gecoder/interface/constraints/set/include.rb +36 -0
  52. data/lib/gecoder/interface/constraints/set/operation.rb +96 -110
  53. data/lib/gecoder/interface/constraints/set/relation.rb +114 -137
  54. data/lib/gecoder/interface/constraints/set_elements/relation.rb +116 -0
  55. data/lib/gecoder/interface/constraints/set_elements_constraints.rb +97 -0
  56. data/lib/gecoder/interface/constraints/set_enum/channel.rb +23 -27
  57. data/lib/gecoder/interface/constraints/set_enum/distinct.rb +18 -19
  58. data/lib/gecoder/interface/constraints/set_enum/operation.rb +62 -53
  59. data/lib/gecoder/interface/constraints/set_enum/select.rb +79 -0
  60. data/lib/gecoder/interface/constraints/set_enum_constraints.rb +73 -23
  61. data/lib/gecoder/interface/constraints/set_var_constraints.rb +222 -57
  62. data/lib/gecoder/interface/enum_matrix.rb +4 -4
  63. data/lib/gecoder/interface/enum_wrapper.rb +71 -22
  64. data/lib/gecoder/interface/model.rb +167 -12
  65. data/lib/gecoder/interface/model_sugar.rb +84 -0
  66. data/lib/gecoder/interface/search.rb +30 -18
  67. data/lib/gecoder/interface/variables.rb +103 -33
  68. data/lib/gecoder/version.rb +2 -2
  69. data/specs/bool_var.rb +19 -12
  70. data/specs/constraints/{boolean.rb → bool/boolean.rb} +103 -28
  71. data/specs/constraints/bool/boolean_properties.rb +51 -0
  72. data/specs/constraints/bool/linear.rb +213 -0
  73. data/specs/constraints/bool_enum/bool_enum_relation.rb +117 -0
  74. data/specs/constraints/bool_enum/channel.rb +102 -0
  75. data/specs/constraints/{extensional.rb → bool_enum/extensional.rb} +32 -101
  76. data/specs/constraints/constraint_helper.rb +149 -179
  77. data/specs/constraints/constraint_receivers.rb +103 -0
  78. data/specs/constraints/constraints.rb +6 -63
  79. data/specs/constraints/fixnum_enum/element.rb +58 -0
  80. data/specs/constraints/fixnum_enum/operation.rb +67 -0
  81. data/specs/constraints/int/arithmetic.rb +149 -0
  82. data/specs/constraints/int/channel.rb +101 -0
  83. data/specs/constraints/int/domain.rb +106 -0
  84. data/specs/constraints/int/linear.rb +183 -0
  85. data/specs/constraints/int/linear_properties.rb +97 -0
  86. data/specs/constraints/int/relation.rb +84 -0
  87. data/specs/constraints/int_enum/arithmetic.rb +72 -0
  88. data/specs/constraints/int_enum/channel.rb +57 -0
  89. data/specs/constraints/int_enum/count.rb +72 -0
  90. data/specs/constraints/int_enum/distinct.rb +80 -0
  91. data/specs/constraints/int_enum/element.rb +61 -0
  92. data/specs/constraints/int_enum/equality.rb +29 -0
  93. data/specs/constraints/int_enum/extensional.rb +224 -0
  94. data/specs/constraints/int_enum/sort.rb +167 -0
  95. data/specs/constraints/operands.rb +264 -0
  96. data/specs/constraints/property_helper.rb +443 -0
  97. data/specs/constraints/reification_sugar.rb +4 -5
  98. data/specs/constraints/selected_set/select.rb +56 -0
  99. data/specs/constraints/selected_set/select_properties.rb +157 -0
  100. data/specs/constraints/set/cardinality.rb +58 -0
  101. data/specs/constraints/set/cardinality_properties.rb +46 -0
  102. data/specs/constraints/set/channel.rb +77 -0
  103. data/specs/constraints/set/connection.rb +176 -0
  104. data/specs/constraints/set/domain.rb +197 -0
  105. data/specs/constraints/set/include.rb +36 -0
  106. data/specs/constraints/set/operation.rb +132 -0
  107. data/specs/constraints/set/relation.rb +117 -0
  108. data/specs/constraints/set_elements/relation.rb +84 -0
  109. data/specs/constraints/set_enum/channel.rb +80 -0
  110. data/specs/constraints/set_enum/distinct.rb +59 -0
  111. data/specs/constraints/set_enum/operation.rb +111 -0
  112. data/specs/constraints/set_enum/select.rb +73 -0
  113. data/specs/enum_wrapper.rb +53 -3
  114. data/specs/int_var.rb +44 -25
  115. data/specs/model.rb +58 -1
  116. data/specs/model_sugar.rb +30 -0
  117. data/specs/search.rb +24 -5
  118. data/specs/selected_set.rb +39 -0
  119. data/specs/set_elements.rb +34 -0
  120. data/specs/set_var.rb +22 -8
  121. data/specs/spec_helper.rb +206 -6
  122. data/tasks/distribution.rake +22 -7
  123. data/tasks/svn.rake +3 -1
  124. metadata +218 -134
  125. data/lib/gecoder/interface/constraints/set_enum/selection.rb +0 -217
  126. data/specs/constraints/arithmetic.rb +0 -351
  127. data/specs/constraints/bool_enum_relation.rb +0 -160
  128. data/specs/constraints/cardinality.rb +0 -157
  129. data/specs/constraints/channel.rb +0 -454
  130. data/specs/constraints/connection.rb +0 -369
  131. data/specs/constraints/count.rb +0 -146
  132. data/specs/constraints/distinct.rb +0 -164
  133. data/specs/constraints/element.rb +0 -108
  134. data/specs/constraints/equality.rb +0 -31
  135. data/specs/constraints/int_domain.rb +0 -70
  136. data/specs/constraints/int_relation.rb +0 -82
  137. data/specs/constraints/linear.rb +0 -340
  138. data/specs/constraints/selection.rb +0 -292
  139. data/specs/constraints/set_domain.rb +0 -185
  140. data/specs/constraints/set_operation.rb +0 -285
  141. data/specs/constraints/set_relation.rb +0 -197
  142. data/specs/constraints/sort.rb +0 -179
@@ -1,7 +1,7 @@
1
1
  module Gecode
2
2
  class Model
3
3
  # Specifies which variables that should be branched on (given as an
4
- # enum of variables or as a single variable). One can optionally
4
+ # enum of operands or as a single operand). One can optionally
5
5
  # also select which of the variables that should be used first with
6
6
  # the :variable option and which value in that variable's domain
7
7
  # that should be used with the :value option. If nothing is
@@ -62,16 +62,23 @@ module Gecode
62
62
  # [:min] Selects the smallest value in the unknown part of the set.
63
63
  # [:max] Selects the largest value in the unknown part of the set.
64
64
  def branch_on(variables, options = {})
65
- if variables.respond_to? :bind
65
+ if variables.respond_to?(:to_int_var) or
66
+ variables.respond_to?(:to_bool_var) or
67
+ variables.respond_to?(:to_set_var)
66
68
  variables = wrap_enum [variables]
67
69
  end
68
70
 
69
- if variables.respond_to? :to_int_var_array or
70
- variables.respond_to? :to_bool_var_array
71
- add_branch(variables, options, Constants::BRANCH_INT_VAR_CONSTANTS,
71
+ if variables.respond_to? :to_int_enum
72
+ add_branch(variables.to_int_enum, options,
73
+ Constants::BRANCH_INT_VAR_CONSTANTS,
72
74
  Constants::BRANCH_INT_VALUE_CONSTANTS)
73
- elsif variables.respond_to? :to_set_var_array
74
- add_branch(variables, options, Constants::BRANCH_SET_VAR_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,
75
82
  Constants::BRANCH_SET_VALUE_CONSTANTS)
76
83
  else
77
84
  raise TypeError, "Unknown type of variable enum #{variables.class}."
@@ -126,7 +133,7 @@ module Gecode
126
133
  }
127
134
  end
128
135
 
129
- # Adds a branching selection for the specified variable with the specified
136
+ # Adds a branching selection for the specified variables with the specified
130
137
  # options. The hashes are used to decode the options into Gecode's
131
138
  # constants.
132
139
  def add_branch(variables, options, branch_var_hash, branch_value_hash)
@@ -148,7 +155,7 @@ module Gecode
148
155
 
149
156
  # Add the branching as a gecode interaction.
150
157
  add_interaction do
151
- Gecode::Raw.branch(active_space, variables.to_var_array,
158
+ Gecode::Raw.branch(active_space, variables.bind_array,
152
159
  branch_var_hash[var_strat], branch_value_hash[val_strat])
153
160
  end
154
161
  end
@@ -4,499 +4,455 @@ module Gecode
4
4
  class MissingConstraintError < StandardError
5
5
  end
6
6
 
7
- # A module containing all the constraints.
8
- module Constraints
9
- # A module that should be mixed in to class of objects that should be usable
10
- # as left hand sides (i.e. the part before must*) when specifying
11
- # constraints. Assumes that a method #expression is defined which produces
12
- # a new expression given the current constraint parameters.
13
- module LeftHandSideMethods #:nodoc:
14
- # Specifies that a constraint must hold for the keft hand side.
15
- def must
16
- expression update_params(:negate => false)
17
- end
18
- alias_method :must_be, :must
19
-
20
- # Specifies that the negation of a constraint must hold for the left hand
21
- # side.
22
- def must_not
23
- expression update_params(:negate => true)
24
- end
25
- alias_method :must_not_be, :must_not
26
-
27
- private
28
-
29
- # Updates the parameters with the specified new parameters.
30
- def update_params(params_to_add)
31
- @constraint_params ||= {}
32
- @constraint_params.update(params_to_add)
33
- end
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
34
32
  end
33
+ alias_method :must_be, :must
35
34
 
36
- # A module that provides some utility-methods for constraints.
37
- module Util #:nodoc:
38
- # Maps the name used in options to the value used in Gecode for
39
- # propagation strengths.
40
- PROPAGATION_STRENGTHS = {
41
- :default => Gecode::Raw::ICL_DEF,
42
- :value => Gecode::Raw::ICL_VAL,
43
- :bounds => Gecode::Raw::ICL_BND,
44
- :domain => Gecode::Raw::ICL_DOM
45
- }
46
-
47
- # Maps the name used in options to the value used in Gecode for
48
- # propagation kinds.
49
- PROPAGATION_KINDS = {
50
- :default => Gecode::Raw::PK_DEF,
51
- :speed => Gecode::Raw::PK_SPEED,
52
- :memory => Gecode::Raw::PK_MEMORY,
53
- }
54
-
55
- # Maps the names of the methods to the corresponding integer relation
56
- # type in Gecode.
57
- RELATION_TYPES = {
58
- :== => Gecode::Raw::IRT_EQ,
59
- :<= => Gecode::Raw::IRT_LQ,
60
- :< => Gecode::Raw::IRT_LE,
61
- :>= => Gecode::Raw::IRT_GQ,
62
- :> => Gecode::Raw::IRT_GR
63
- }
64
- # The same as above, but negated.
65
- NEGATED_RELATION_TYPES = {
66
- :== => Gecode::Raw::IRT_NQ,
67
- :<= => Gecode::Raw::IRT_GR,
68
- :< => Gecode::Raw::IRT_GQ,
69
- :>= => Gecode::Raw::IRT_LE,
70
- :> => Gecode::Raw::IRT_LQ
71
- }
72
-
73
- # Maps the names of the methods to the corresponding set relation type in
74
- # Gecode.
75
- SET_RELATION_TYPES = {
76
- :== => Gecode::Raw::SRT_EQ,
77
- :superset => Gecode::Raw::SRT_SUP,
78
- :subset => Gecode::Raw::SRT_SUB,
79
- :disjoint => Gecode::Raw::SRT_DISJ,
80
- :complement => Gecode::Raw::SRT_CMPL
81
- }
82
- # The same as above, but negated.
83
- NEGATED_SET_RELATION_TYPES = {
84
- :== => Gecode::Raw::SRT_NQ
85
- }
86
- # Maps the names of the methods to the corresponding set operation type in
87
- # Gecode.
88
- SET_OPERATION_TYPES = {
89
- :union => Gecode::Raw::SOT_UNION,
90
- :disjoint_union => Gecode::Raw::SOT_DUNION,
91
- :intersection => Gecode::Raw::SOT_INTER,
92
- :minus => Gecode::Raw::SOT_MINUS
93
- }
94
-
95
- # Various method aliases for comparison methods. Maps the original
96
- # (symbol) name to an array of aliases.
97
- COMPARISON_ALIASES = {
98
- :== => [:equal, :equal_to],
99
- :> => [:greater, :greater_than],
100
- :>= => [:greater_or_equal, :greater_than_or_equal_to],
101
- :< => [:less, :less_than],
102
- :<= => [:less_or_equal, :less_than_or_equal_to]
103
- }
104
- SET_ALIASES = {
105
- :== => [:equal, :equal_to],
106
- :superset => [:superset_of],
107
- :subset => [:subset_of],
108
- :disjoint => [:disjoint_with],
109
- :complement => [:complement_of]
110
- }
111
-
112
- module_function
113
-
114
- # Decodes the common options to constraints: strength, kind and
115
- # reification. Returns a hash with up to three values. :strength is the
116
- # strength that should be used for the constraint, :kind is the
117
- # propagation kind that should be used, and :reif is the (bound) boolean
118
- # variable that should be used for reification. The decoded options are
119
- # removed from the hash (so in general the hash will be consumed in the
120
- # process).
121
- #
122
- # Raises ArgumentError if an unrecognized option is found in the specified
123
- # hash. Or if an unrecognized strength is given. Raises TypeError if the
124
- # reification variable is not a boolean variable.
125
- def decode_options(options)
126
- # Propagation strength.
127
- strength = options.delete(:strength) || :default
128
- unless PROPAGATION_STRENGTHS.include? strength
129
- raise ArgumentError, "Unrecognized propagation strength #{strength}."
130
- end
131
-
132
- # Propagation kind.
133
- kind = options.delete(:kind) || :default
134
- unless PROPAGATION_KINDS.include? kind
135
- raise ArgumentError, "Unrecognized propagation kind #{kind}."
136
- end
137
-
138
- # Reification.
139
- reif_var = options.delete(:reify)
140
- unless reif_var.nil? or reif_var.kind_of? FreeBoolVar
141
- raise TypeError, 'Only boolean variables may be used for reification.'
142
- end
143
-
144
- # Check for unrecognized options.
145
- unless options.empty?
146
- raise ArgumentError, 'Unrecognized constraint option: ' +
147
- options.keys.first.to_s
148
- end
149
- return {
150
- :strength => PROPAGATION_STRENGTHS[strength],
151
- :kind => PROPAGATION_KINDS[kind],
152
- :reif => reif_var
153
- }
154
- end
155
-
156
- # Converts the different ways to specify constant sets in the interface
157
- # to the form that the set should be represented in Gecode (possibly
158
- # multiple paramters. The different forms accepted are:
159
- # * Single instance of Fixnum (singleton set).
160
- # * Range (set containing all numbers in range), treated differently from
161
- # other enumerations.
162
- # * Enumeration of integers (set contaning all numbers in set).
163
- def constant_set_to_params(constant_set)
164
- unless constant_set?(constant_set)
165
- raise TypeError, "Expected a constant set, got: #{constant_set}."
166
- end
167
-
168
- if constant_set.kind_of? Range
169
- return constant_set.first, constant_set.last
170
- elsif constant_set.kind_of? Fixnum
171
- return constant_set
172
- else
173
- constant_set = constant_set.to_a
174
- return Gecode::Raw::IntSet.new(constant_set, constant_set.size)
175
- end
176
- end
177
-
178
- # Converts the different ways to specify constant sets in the interface
179
- # to an instance of Gecode::Raw::IntSet. The different forms accepted are:
180
- # * Single instance of Fixnum (singleton set).
181
- # * Range (set containing all numbers in range), treated differently from
182
- # other enumerations.
183
- # * Enumeration of integers (set contaning all numbers in set).
184
- def constant_set_to_int_set(constant_set)
185
- unless constant_set?(constant_set)
186
- raise TypeError, "Expected a constant set, got: #{constant_set}."
187
- end
188
-
189
- if constant_set.kind_of? Range
190
- return Gecode::Raw::IntSet.new(constant_set.first, constant_set.last)
191
- elsif constant_set.kind_of? Fixnum
192
- return Gecode::Raw::IntSet.new([constant_set], 1)
193
- else
194
- constant_set = constant_set.to_a
195
- return Gecode::Raw::IntSet.new(constant_set, constant_set.size)
196
- end
197
- end
198
-
199
- # Checks whether the specified expression is regarded as a constant set.
200
- # Returns true if it is, false otherwise.
201
- def constant_set?(expression)
202
- return (
203
- expression.kind_of?(Range) && # It's a range.
204
- expression.first.kind_of?(Fixnum) &&
205
- expression.last.kind_of?(Fixnum)) ||
206
- expression.kind_of?(Fixnum) || # It's a single fixnum.
207
- (expression.kind_of?(Enumerable) && # It's an enum of fixnums.
208
- expression.all?{ |e| e.kind_of? Fixnum })
209
- end
210
-
211
- # Extracts an array of the values selected for the standard propagation
212
- # options (propagation strength and propagation kind) from the hash of
213
- # parameters given. The options are returned in the order that they are
214
- # given when posting constraints to Gecode.
215
- def extract_propagation_options(params)
216
- params.values_at(:strength, :kind)
217
- end
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
218
39
  end
219
-
220
- # A module that contains utility-methods for extensional constraints.
221
- module Util::Extensional #:nodoc:
222
- module_function
223
-
224
- # Checks that the specified enumeration is an enumeration containing
225
- # one or more tuples of the specified size. It also allows the caller
226
- # to define additional tests by providing a block, which is given each
227
- # tuple. If a test fails then an appropriate error is raised.
228
- def perform_tuple_checks(tuples, expected_size, &additional_test)
229
- unless tuples.respond_to?(:each)
230
- raise TypeError, 'Expected an enumeration with tuples, got ' +
231
- "#{tuples.class}."
232
- end
233
-
234
- if tuples.empty?
235
- raise ArgumentError, 'One or more tuples must be specified.'
236
- end
237
-
238
- tuples.each do |tuple|
239
- unless tuple.respond_to?(:each)
240
- raise TypeError, 'Expected an enumeration containing enumeraions, ' +
241
- "got #{tuple.class}."
242
- end
243
-
244
- unless tuple.size == expected_size
245
- raise ArgumentError, 'All tuples must be of the same size as the ' +
246
- 'number of variables in the array.'
247
- end
248
-
249
- yield tuple
250
- end
251
- 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.'
252
45
  end
253
46
 
254
- # Describes a constraint expressions. An expression is produced by calling
255
- # some form of must on a left hand side. The expression waits for a right
256
- # hand side so that it can post the corresponding constraint.
257
- class Expression #:nodoc:
258
- # Constructs a new expression with the specified parameters. The
259
- # parameters shoud at least contain the keys :lhs, and :negate.
260
- #
261
- # Raises ArgumentError if any of those keys are missing.
262
- def initialize(model, params)
263
- unless params.has_key?(:lhs) and params.has_key?(:negate)
264
- raise ArgumentError, 'Expression requires at least :lhs, ' +
265
- "and :negate as parameter keys, got #{params.keys.join(', ')}."
266
- end
267
-
268
- @model = model
269
- @params = params
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(', ')}."
270
132
  end
271
-
272
- private
273
-
274
- # Provides commutivity for the constraint with the specified method name.
275
- # If the method with the specified method name is called with something
276
- # that, when given to the block, evaluates to true, then the constraint
277
- # will be called on the right hand side with the left hand side as
278
- # argument.
279
- #
280
- # The original constraint method is assumed to take two arguments: a
281
- # right hand side and a hash of options.
282
- def self.provide_commutivity(constraint_name, &block)
283
- unique_id = constraint_name.to_sym.to_i
284
- pre_alias_method_name = 'pre_commutivity_' << unique_id.to_s
285
- if method_defined? constraint_name
286
- alias_method pre_alias_method_name, constraint_name
287
- end
288
-
289
- module_eval <<-end_code
290
- @@commutivity_check_#{unique_id} = block
291
- def #{constraint_name}(rhs, options = {})
292
- if @@commutivity_check_#{unique_id}.call(rhs, options)
293
- if @params[:negate]
294
- rhs.must_not.method(:#{constraint_name}).call(
295
- @params[:lhs], options)
296
- else
297
- rhs.must.method(:#{constraint_name}).call(
298
- @params[:lhs], options)
299
- end
300
- else
301
- if self.class.method_defined? :#{pre_alias_method_name}
302
- #{pre_alias_method_name}(rhs, options)
303
- else
304
- raise TypeError, \"Unexpected argument type \#{rhs.class}.\"
305
- end
306
- end
307
- end
308
- end_code
133
+ unless params[:lhs].kind_of? Operand
134
+ raise ArgumentError, 'Expected :lhs to be an operand, received ' +
135
+ "#{params[:lhs].class}."
309
136
  end
310
137
 
311
- # Creates aliases for any defined comparison methods.
312
- def self.alias_comparison_methods
313
- Gecode::Constraints::Util::COMPARISON_ALIASES.each_pair do |orig, aliases|
314
- if instance_methods.include?(orig.to_s)
315
- aliases.each do |name|
316
- alias_method(name, orig)
317
- end
318
- end
319
- end
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
320
157
  end
321
158
 
322
- # Creates aliases for any defined set methods.
323
- def self.alias_set_methods
324
- Gecode::Constraints::Util::SET_ALIASES.each_pair do |orig, aliases|
325
- if instance_methods.include?(orig.to_s)
326
- aliases.each do |name|
327
- alias_method(name, orig)
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}.\"
328
175
  end
329
176
  end
330
177
  end
331
- end
178
+ end_code
332
179
  end
333
180
 
334
- # A composite expression which is a expression with a left hand side
335
- # resulting from a previous constraint.
336
- class CompositeExpression < Gecode::Constraints::Expression #:nodoc:
337
- # The expression class should be the class of the expression delegated to,
338
- # the variable class the kind of single variable used in the expression.
339
- # The new var proc should produce a new variable (of the appropriate type)
340
- # which has an unconstricted domain. The block given should take three
341
- # parameters. The first is the variable that should be the left hand side.
342
- # The second is the hash of parameters. The third is a boolean, it it's
343
- # true then the block should try to constrain the first variable's domain
344
- # as much as possible.
345
- def initialize(expression_class, variable_class, new_var_proc, model,
346
- params, &block)
347
- super(model, params)
348
- @expression_class = expression_class
349
- @variable_class = variable_class
350
- @new_var_proc = new_var_proc
351
- @constrain_equal_proc = block
352
- end
353
-
354
- # Delegate to an instance of the expression class when we get something
355
- # that we can't handle.
356
- def method_missing(name, *args)
357
- if @expression_class.instance_methods.include? name.to_s
358
- options = {}
359
- if args.size >= 2 and args[1].kind_of? Hash
360
- options = args[1]
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)
361
187
  end
362
-
363
- # Link a variable to the composite constraint.
364
- @params.update Gecode::Constraints::Util.decode_options(options.clone)
365
- variable = @new_var_proc.call
366
- @model.add_interaction do
367
- @constrain_equal_proc.call(variable, @params, true)
368
- end
369
-
370
- # Perform the operation on the linked variable.
371
- int_var_params = @params.clone.update(:lhs => variable)
372
- @expression_class.new(@model, int_var_params).send(name, *args)
373
- else
374
- super
375
188
  end
376
189
  end
377
-
378
- def ==(expression, options = {})
379
- if !@params[:negate] and options[:reify].nil? and
380
- expression.kind_of? @variable_class
381
- # We don't need any additional constraints.
382
- @params.update Gecode::Constraints::Util.decode_options(options)
383
- @model.add_interaction do
384
- @constrain_equal_proc.call(expression, @params, false)
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)
385
198
  end
386
- else
387
- method_missing(:==, expression, options)
388
199
  end
389
200
  end
390
- alias_comparison_methods
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
391
211
  end
392
212
 
393
- # Describes a constraint expression that has yet to be completed. I.e. a
394
- # form of must has not yet been called, but some method has been called to
395
- # initiate the expression. An example is distinct with offsets:
396
- #
397
- # enum.with_offsets(0..n).must_be.distinct
398
- #
399
- # The call of with_offsets initiates the constraint as a stub, even though
400
- # must has not yet been called.
401
- class ExpressionStub #:nodoc:
402
- # Constructs a new expression with the specified parameters.
403
- def initialize(model, params)
404
- @model = model
405
- @params = params
406
- end
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.'
407
217
  end
408
218
 
409
- # Describes an expression stub which includes left hand side methods and
410
- # just sends models and parameters through a supplied block to construct the
411
- # resulting expression.
412
- class SimpleExpressionStub < ExpressionStub #:nodoc:
413
- include Gecode::Constraints::LeftHandSideMethods
219
+ private
414
220
 
415
- # The block provided is executed when the expression demanded by the left
416
- # hand side methods is to be constructed. The block should take two
417
- # parameters: model and params (which have been updated with negate and
418
- # so on). The block should return an expression.
419
- def initialize(model, params, &block)
420
- super(model, params)
421
- @proc = block
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}."
422
336
  end
423
337
 
424
- private
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
425
349
 
426
- # Produces an expression with offsets for the lhs module.
427
- def expression(params)
428
- @params.update(params)
429
- @proc.call(@model, @params)
350
+ # Check for unrecognized options.
351
+ unless options.empty?
352
+ raise ArgumentError, 'Unrecognized constraint option: ' +
353
+ options.keys.first.to_s
430
354
  end
355
+ return {
356
+ :strength => PROPAGATION_STRENGTHS[strength],
357
+ :kind => PROPAGATION_KINDS[kind],
358
+ :reif => reif_var
359
+ }
431
360
  end
432
361
 
433
- # Describes a stub that produces a variable, which can then be used with
434
- # that variable's normalconstraints. An example with int variables would be
435
- # the element constraint.
436
- #
437
- # int_enum[int_var].must > rhs
438
- #
439
- # The int_enum[int_var] part produces an int variable which the constraint
440
- # ".must > rhs" is then applied to. In the above case two constraints (and
441
- # one temporary variable) are required, but in the case of equality only
442
- # one constraint is required.
443
- class CompositeStub < Gecode::Constraints::ExpressionStub #:nodoc:
444
- include Gecode::Constraints::LeftHandSideMethods
445
-
446
- # The composite expression class should be the class that the stub uses
447
- # when creating its expressions.
448
- def initialize(composite_expression_class, model, params)
449
- super(model, params)
450
- @composite_class = composite_expression_class
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}."
451
372
  end
452
-
453
- private
454
-
455
- # Constrains the result of the stub to be equal to the specified variable
456
- # with the specified parameters. If constrain is true then the variable's
457
- # domain should additionally be constrained as much as possible.
458
- def constrain_equal(variable, params, constrain)
459
- raise NoMethodError, 'Abstract method has not been implemented.'
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)
460
381
  end
461
-
462
- # Produces an expression with position for the lhs module.
463
- def expression(params)
464
- @params.update params
465
- @composite_class.new(@model, @params) do |var, params, constrain|
466
- constrain_equal(var, params, constrain)
467
- 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}."
468
393
  end
469
394
 
470
- # Gives an array of the values selected for the standard propagation
471
- # options (propagation strength and propagation kind) in the order that
472
- # they are given when posting constraints to Gecode.
473
- def propagation_options
474
- Gecode::Constraints::Util::extract_propagation_options(@params)
475
- end
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
476
403
  end
477
404
 
478
- # Base class for all constraints.
479
- class Constraint
480
- # Creates a constraint with the specified parameters, bound to the
481
- # specified model.
482
- def initialize(model, params)
483
- @model = model
484
- @params = params.clone
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}."
485
438
  end
486
439
 
487
- # Posts the constraint, adding it to the model. This is an abstract
488
- # method and should be overridden by all sub-classes.
489
- def post
490
- raise NoMethodError, 'Abstract method has not been implemented.'
440
+ if tuples.empty?
441
+ raise ArgumentError, 'One or more tuples must be specified.'
491
442
  end
492
443
 
493
- private
494
-
495
- # Gives an array of the values selected for the standard propagation
496
- # options (propagation strength and propagation kind) in the order that
497
- # they are given when posting constraints to Gecode.
498
- def propagation_options
499
- Gecode::Constraints::Util::extract_propagation_options(@params)
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
500
456
  end
501
457
  end
502
458
  end
@@ -509,4 +465,7 @@ require 'gecoder/interface/constraints/bool_var_constraints'
509
465
  require 'gecoder/interface/constraints/bool_enum_constraints'
510
466
  require 'gecoder/interface/constraints/set_var_constraints'
511
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'
512
471
  require 'gecoder/interface/constraints/extensional_regexp'