gecoder-with-gecode 0.7.1-mswin32

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 (159) hide show
  1. data/CHANGES +81 -0
  2. data/COPYING +17 -0
  3. data/LGPL-LICENSE +458 -0
  4. data/README +45 -0
  5. data/Rakefile +13 -0
  6. data/example/example_helper.rb +1 -0
  7. data/example/magic_sequence.rb +43 -0
  8. data/example/queens.rb +43 -0
  9. data/example/raw_bindings.rb +42 -0
  10. data/example/send_more_money.rb +43 -0
  11. data/example/send_most_money.rb +58 -0
  12. data/example/square_tiling.rb +84 -0
  13. data/example/sudoku-set.rb +110 -0
  14. data/example/sudoku.rb +61 -0
  15. data/lib/gecode.dll +0 -0
  16. data/lib/gecoder.rb +5 -0
  17. data/lib/gecoder/bindings.rb +54 -0
  18. data/lib/gecoder/bindings/bindings.rb +2210 -0
  19. data/lib/gecoder/interface.rb +8 -0
  20. data/lib/gecoder/interface/binding_changes.rb +313 -0
  21. data/lib/gecoder/interface/branch.rb +152 -0
  22. data/lib/gecoder/interface/constraints.rb +397 -0
  23. data/lib/gecoder/interface/constraints/bool/boolean.rb +246 -0
  24. data/lib/gecoder/interface/constraints/bool/linear.rb +29 -0
  25. data/lib/gecoder/interface/constraints/bool_enum/boolean.rb +84 -0
  26. data/lib/gecoder/interface/constraints/bool_enum_constraints.rb +8 -0
  27. data/lib/gecoder/interface/constraints/bool_var_constraints.rb +75 -0
  28. data/lib/gecoder/interface/constraints/int/arithmetic.rb +71 -0
  29. data/lib/gecoder/interface/constraints/int/domain.rb +78 -0
  30. data/lib/gecoder/interface/constraints/int/linear.rb +295 -0
  31. data/lib/gecoder/interface/constraints/int_enum/arithmetic.rb +72 -0
  32. data/lib/gecoder/interface/constraints/int_enum/channel.rb +100 -0
  33. data/lib/gecoder/interface/constraints/int_enum/count.rb +92 -0
  34. data/lib/gecoder/interface/constraints/int_enum/distinct.rb +69 -0
  35. data/lib/gecoder/interface/constraints/int_enum/element.rb +82 -0
  36. data/lib/gecoder/interface/constraints/int_enum/equality.rb +38 -0
  37. data/lib/gecoder/interface/constraints/int_enum/sort.rb +126 -0
  38. data/lib/gecoder/interface/constraints/int_enum_constraints.rb +37 -0
  39. data/lib/gecoder/interface/constraints/int_var_constraints.rb +58 -0
  40. data/lib/gecoder/interface/constraints/reifiable_constraints.rb +78 -0
  41. data/lib/gecoder/interface/constraints/set/cardinality.rb +75 -0
  42. data/lib/gecoder/interface/constraints/set/connection.rb +193 -0
  43. data/lib/gecoder/interface/constraints/set/domain.rb +109 -0
  44. data/lib/gecoder/interface/constraints/set/operation.rb +132 -0
  45. data/lib/gecoder/interface/constraints/set/relation.rb +178 -0
  46. data/lib/gecoder/interface/constraints/set_enum/channel.rb +18 -0
  47. data/lib/gecoder/interface/constraints/set_enum/distinct.rb +80 -0
  48. data/lib/gecoder/interface/constraints/set_enum/operation.rb +60 -0
  49. data/lib/gecoder/interface/constraints/set_enum/selection.rb +217 -0
  50. data/lib/gecoder/interface/constraints/set_enum_constraints.rb +34 -0
  51. data/lib/gecoder/interface/constraints/set_var_constraints.rb +72 -0
  52. data/lib/gecoder/interface/enum_matrix.rb +64 -0
  53. data/lib/gecoder/interface/enum_wrapper.rb +153 -0
  54. data/lib/gecoder/interface/model.rb +251 -0
  55. data/lib/gecoder/interface/search.rb +123 -0
  56. data/lib/gecoder/interface/variables.rb +254 -0
  57. data/lib/gecoder/version.rb +4 -0
  58. data/specs/binding_changes.rb +76 -0
  59. data/specs/bool_var.rb +74 -0
  60. data/specs/branch.rb +170 -0
  61. data/specs/constraints/arithmetic.rb +266 -0
  62. data/specs/constraints/bool_enum.rb +140 -0
  63. data/specs/constraints/boolean.rb +232 -0
  64. data/specs/constraints/cardinality.rb +154 -0
  65. data/specs/constraints/channel.rb +126 -0
  66. data/specs/constraints/connection.rb +373 -0
  67. data/specs/constraints/constraint_helper.rb +180 -0
  68. data/specs/constraints/constraints.rb +74 -0
  69. data/specs/constraints/count.rb +139 -0
  70. data/specs/constraints/distinct.rb +218 -0
  71. data/specs/constraints/element.rb +106 -0
  72. data/specs/constraints/equality.rb +31 -0
  73. data/specs/constraints/int_domain.rb +69 -0
  74. data/specs/constraints/int_relation.rb +78 -0
  75. data/specs/constraints/linear.rb +332 -0
  76. data/specs/constraints/reification_sugar.rb +96 -0
  77. data/specs/constraints/selection.rb +292 -0
  78. data/specs/constraints/set_domain.rb +181 -0
  79. data/specs/constraints/set_operation.rb +285 -0
  80. data/specs/constraints/set_relation.rb +201 -0
  81. data/specs/constraints/sort.rb +175 -0
  82. data/specs/distribution.rb +14 -0
  83. data/specs/enum_matrix.rb +43 -0
  84. data/specs/enum_wrapper.rb +122 -0
  85. data/specs/int_var.rb +144 -0
  86. data/specs/logging.rb +24 -0
  87. data/specs/model.rb +190 -0
  88. data/specs/search.rb +246 -0
  89. data/specs/set_var.rb +68 -0
  90. data/specs/spec_helper.rb +93 -0
  91. data/tasks/all_tasks.rb +1 -0
  92. data/tasks/building.howto +65 -0
  93. data/tasks/distribution.rake +156 -0
  94. data/tasks/rcov.rake +17 -0
  95. data/tasks/specs.rake +15 -0
  96. data/tasks/svn.rake +11 -0
  97. data/tasks/website.rake +51 -0
  98. data/vendor/gecode/win32/lib/libgecodeint.dll +0 -0
  99. data/vendor/gecode/win32/lib/libgecodekernel.dll +0 -0
  100. data/vendor/gecode/win32/lib/libgecodeminimodel.dll +0 -0
  101. data/vendor/gecode/win32/lib/libgecodesearch.dll +0 -0
  102. data/vendor/gecode/win32/lib/libgecodeset.dll +0 -0
  103. data/vendor/rust/README +28 -0
  104. data/vendor/rust/bin/cxxgenerator.rb +93 -0
  105. data/vendor/rust/include/rust_checks.hh +115 -0
  106. data/vendor/rust/include/rust_conversions.hh +102 -0
  107. data/vendor/rust/rust.rb +67 -0
  108. data/vendor/rust/rust/attribute.rb +51 -0
  109. data/vendor/rust/rust/bindings.rb +172 -0
  110. data/vendor/rust/rust/class.rb +339 -0
  111. data/vendor/rust/rust/constants.rb +48 -0
  112. data/vendor/rust/rust/container.rb +110 -0
  113. data/vendor/rust/rust/cppifaceparser.rb +129 -0
  114. data/vendor/rust/rust/cwrapper.rb +72 -0
  115. data/vendor/rust/rust/cxxclass.rb +98 -0
  116. data/vendor/rust/rust/element.rb +81 -0
  117. data/vendor/rust/rust/enum.rb +63 -0
  118. data/vendor/rust/rust/function.rb +407 -0
  119. data/vendor/rust/rust/namespace.rb +61 -0
  120. data/vendor/rust/rust/templates/AttributeDefinition.rusttpl +17 -0
  121. data/vendor/rust/rust/templates/AttributeInitBinding.rusttpl +9 -0
  122. data/vendor/rust/rust/templates/BindingsHeader.rusttpl +24 -0
  123. data/vendor/rust/rust/templates/BindingsUnit.rusttpl +46 -0
  124. data/vendor/rust/rust/templates/CWrapperClassDefinitions.rusttpl +64 -0
  125. data/vendor/rust/rust/templates/ClassDeclarations.rusttpl +7 -0
  126. data/vendor/rust/rust/templates/ClassInitialize.rusttpl +6 -0
  127. data/vendor/rust/rust/templates/ConstructorStub.rusttpl +21 -0
  128. data/vendor/rust/rust/templates/CxxClassDefinitions.rusttpl +91 -0
  129. data/vendor/rust/rust/templates/CxxMethodStub.rusttpl +12 -0
  130. data/vendor/rust/rust/templates/CxxStandaloneClassDefinitions.rusttpl +26 -0
  131. data/vendor/rust/rust/templates/EnumDeclarations.rusttpl +3 -0
  132. data/vendor/rust/rust/templates/EnumDefinitions.rusttpl +29 -0
  133. data/vendor/rust/rust/templates/FunctionDefinition.rusttpl +9 -0
  134. data/vendor/rust/rust/templates/FunctionInitAlias.rusttpl +5 -0
  135. data/vendor/rust/rust/templates/FunctionInitBinding.rusttpl +9 -0
  136. data/vendor/rust/rust/templates/MethodInitBinding.rusttpl +9 -0
  137. data/vendor/rust/rust/templates/ModuleDeclarations.rusttpl +3 -0
  138. data/vendor/rust/rust/templates/ModuleDefinitions.rusttpl +3 -0
  139. data/vendor/rust/rust/templates/StandaloneClassDeclarations.rusttpl +7 -0
  140. data/vendor/rust/rust/templates/VariableFunctionCall.rusttpl +14 -0
  141. data/vendor/rust/rust/type.rb +98 -0
  142. data/vendor/rust/test/Makefile +4 -0
  143. data/vendor/rust/test/constants.rb +36 -0
  144. data/vendor/rust/test/cppclass.cc +45 -0
  145. data/vendor/rust/test/cppclass.hh +67 -0
  146. data/vendor/rust/test/cppclass.rb +59 -0
  147. data/vendor/rust/test/cwrapper.c +74 -0
  148. data/vendor/rust/test/cwrapper.h +41 -0
  149. data/vendor/rust/test/cwrapper.rb +56 -0
  150. data/vendor/rust/test/dummyclass.hh +31 -0
  151. data/vendor/rust/test/lib/extension-test.rb +98 -0
  152. data/vendor/rust/test/operators.cc +41 -0
  153. data/vendor/rust/test/operators.hh +39 -0
  154. data/vendor/rust/test/operators.rb +39 -0
  155. data/vendor/rust/test/test-constants.rb +43 -0
  156. data/vendor/rust/test/test-cppclass.rb +82 -0
  157. data/vendor/rust/test/test-cwrapper.rb +80 -0
  158. data/vendor/rust/test/test-operators.rb +42 -0
  159. metadata +293 -0
@@ -0,0 +1,397 @@
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
+ # 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
34
+ end
35
+
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 names of the methods to the corresponding integer relation
48
+ # type in Gecode.
49
+ RELATION_TYPES = {
50
+ :== => Gecode::Raw::IRT_EQ,
51
+ :<= => Gecode::Raw::IRT_LQ,
52
+ :< => Gecode::Raw::IRT_LE,
53
+ :>= => Gecode::Raw::IRT_GQ,
54
+ :> => Gecode::Raw::IRT_GR
55
+ }
56
+ # The same as above, but negated.
57
+ NEGATED_RELATION_TYPES = {
58
+ :== => Gecode::Raw::IRT_NQ,
59
+ :<= => Gecode::Raw::IRT_GR,
60
+ :< => Gecode::Raw::IRT_GQ,
61
+ :>= => Gecode::Raw::IRT_LE,
62
+ :> => Gecode::Raw::IRT_LQ
63
+ }
64
+
65
+ # Maps the names of the methods to the corresponding set relation type in
66
+ # Gecode.
67
+ SET_RELATION_TYPES = {
68
+ :== => Gecode::Raw::SRT_EQ,
69
+ :superset => Gecode::Raw::SRT_SUP,
70
+ :subset => Gecode::Raw::SRT_SUB,
71
+ :disjoint => Gecode::Raw::SRT_DISJ,
72
+ :complement => Gecode::Raw::SRT_CMPL
73
+ }
74
+ # The same as above, but negated.
75
+ NEGATED_SET_RELATION_TYPES = {
76
+ :== => Gecode::Raw::SRT_NQ
77
+ }
78
+ # Maps the names of the methods to the corresponding set operation type in
79
+ # Gecode.
80
+ SET_OPERATION_TYPES = {
81
+ :union => Gecode::Raw::SOT_UNION,
82
+ :disjoint_union => Gecode::Raw::SOT_DUNION,
83
+ :intersection => Gecode::Raw::SOT_INTER,
84
+ :minus => Gecode::Raw::SOT_MINUS
85
+ }
86
+
87
+ # Various method aliases for comparison methods. Maps the original
88
+ # (symbol) name to an array of aliases.
89
+ COMPARISON_ALIASES = {
90
+ :== => [:equal, :equal_to],
91
+ :> => [:greater, :greater_than],
92
+ :>= => [:greater_or_equal, :greater_than_or_equal_to],
93
+ :< => [:less, :less_than],
94
+ :<= => [:less_or_equal, :less_than_or_equal_to]
95
+ }
96
+ SET_ALIASES = {
97
+ :== => [:equal, :equal_to],
98
+ :superset => [:superset_of],
99
+ :subset => [:subset_of],
100
+ :disjoint => [:disjoint_with],
101
+ :complement => [:complement_of]
102
+ }
103
+
104
+ module_function
105
+
106
+ # Decodes the common options to constraints: strength and reification.
107
+ # Returns a hash with up to two values. :strength is the strength that
108
+ # should be used for the constraint and :reif is the (bound) boolean
109
+ # variable that should be used for reification. The decoded options are
110
+ # removed from the hash (so in general the hash will be consumed in the
111
+ # process).
112
+ #
113
+ # Raises ArgumentError if an unrecognized option is found in the specified
114
+ # hash. Or if an unrecognized strength is given. Raises TypeError if the
115
+ # reification variable is not a boolean variable.
116
+ def decode_options(options)
117
+ # Propagation strength.
118
+ strength = options.delete(:strength) || :default
119
+ unless PROPAGATION_STRENGTHS.include? strength
120
+ raise ArgumentError, "Unrecognized propagation strength #{strength}."
121
+ end
122
+
123
+ # Reification.
124
+ reif_var = options.delete(:reify)
125
+ unless reif_var.nil? or reif_var.kind_of? FreeBoolVar
126
+ raise TypeError, 'Only boolean variables may be used for reification.'
127
+ end
128
+
129
+ # Check for unrecognized options.
130
+ unless options.empty?
131
+ raise ArgumentError, 'Unrecognized constraint option: ' +
132
+ options.keys.first.to_s
133
+ end
134
+ return {:strength => PROPAGATION_STRENGTHS[strength], :reif => reif_var}
135
+ end
136
+
137
+ # Converts the different ways to specify constant sets in the interface
138
+ # to the form that the set should be represented in Gecode (possibly
139
+ # multiple paramters. The different forms accepted are:
140
+ # * Single instance of Fixnum (singleton set).
141
+ # * Range (set containing all numbers in range), treated differently from
142
+ # other enumerations.
143
+ # * Enumeration of integers (set contaning all numbers in set).
144
+ def constant_set_to_params(constant_set)
145
+ unless constant_set?(constant_set)
146
+ raise TypeError, "Expected a constant set, got: #{constant_set}."
147
+ end
148
+
149
+ if constant_set.kind_of? Range
150
+ return constant_set.first, constant_set.last
151
+ elsif constant_set.kind_of? Fixnum
152
+ return constant_set
153
+ else
154
+ constant_set = constant_set.to_a
155
+ return Gecode::Raw::IntSet.new(constant_set, constant_set.size)
156
+ end
157
+ end
158
+
159
+ # Converts the different ways to specify constant sets in the interface
160
+ # to an instance of Gecode::Raw::IntSet. The different forms accepted are:
161
+ # * Single instance of Fixnum (singleton set).
162
+ # * Range (set containing all numbers in range), treated differently from
163
+ # other enumerations.
164
+ # * Enumeration of integers (set contaning all numbers in set).
165
+ def constant_set_to_int_set(constant_set)
166
+ unless constant_set?(constant_set)
167
+ raise TypeError, "Expected a constant set, got: #{constant_set}."
168
+ end
169
+
170
+ if constant_set.kind_of? Range
171
+ return Gecode::Raw::IntSet.new(constant_set.first, constant_set.last)
172
+ elsif constant_set.kind_of? Fixnum
173
+ return Gecode::Raw::IntSet.new([constant_set], 1)
174
+ else
175
+ constant_set = constant_set.to_a
176
+ return Gecode::Raw::IntSet.new(constant_set, constant_set.size)
177
+ end
178
+ end
179
+
180
+ # Checks whether the specified expression is regarded as a constant set.
181
+ # Returns true if it is, false otherwise.
182
+ def constant_set?(expression)
183
+ return (
184
+ expression.kind_of?(Range) && # It's a range.
185
+ expression.first.kind_of?(Fixnum) &&
186
+ expression.last.kind_of?(Fixnum)) ||
187
+ expression.kind_of?(Fixnum) || # It's a single fixnum.
188
+ (expression.kind_of?(Enumerable) && # It's an enum of fixnums.
189
+ expression.all?{ |e| e.kind_of? Fixnum })
190
+ end
191
+ end
192
+
193
+ # Describes a constraint expressions. An expression is produced by calling
194
+ # some form of must on a left hand side. The expression waits for a right
195
+ # hand side so that it can post the corresponding constraint.
196
+ class Expression #:nodoc:
197
+ # Constructs a new expression with the specified parameters. The
198
+ # parameters shoud at least contain the keys :lhs, and :negate.
199
+ #
200
+ # Raises ArgumentError if any of those keys are missing.
201
+ def initialize(model, params)
202
+ unless params.has_key?(:lhs) and params.has_key?(:negate)
203
+ raise ArgumentError, 'Expression requires at least :lhs, ' +
204
+ "and :negate as parameter keys, got #{params.keys.join(', ')}."
205
+ end
206
+
207
+ @model = model
208
+ @params = params
209
+ end
210
+
211
+ private
212
+
213
+ # Creates aliases for any defined comparison methods.
214
+ def self.alias_comparison_methods
215
+ Gecode::Constraints::Util::COMPARISON_ALIASES.each_pair do |orig, aliases|
216
+ if instance_methods.include?(orig.to_s)
217
+ aliases.each do |name|
218
+ alias_method(name, orig)
219
+ end
220
+ end
221
+ end
222
+ end
223
+
224
+ # Creates aliases for any defined set methods.
225
+ def self.alias_set_methods
226
+ Gecode::Constraints::Util::SET_ALIASES.each_pair do |orig, aliases|
227
+ if instance_methods.include?(orig.to_s)
228
+ aliases.each do |name|
229
+ alias_method(name, orig)
230
+ end
231
+ end
232
+ end
233
+ end
234
+ end
235
+
236
+ # A composite expression which is a expression with a left hand side
237
+ # resulting from a previous constraint.
238
+ class CompositeExpression < Gecode::Constraints::Expression #:nodoc:
239
+ # The expression class should be the class of the expression delegated to,
240
+ # the variable class the kind of single variable used in the expression.
241
+ # The new var proc should produce a new variable (of the appropriate type)
242
+ # which has an unconstricted domain. The block given should take three
243
+ # parameters. The first is the variable that should be the left hand side.
244
+ # The second is the hash of parameters. The third is a boolean, it it's
245
+ # true then the block should try to constrain the first variable's domain
246
+ # as much as possible.
247
+ def initialize(expression_class, variable_class, new_var_proc, model,
248
+ params, &block)
249
+ super(model, params)
250
+ @expression_class = expression_class
251
+ @variable_class = variable_class
252
+ @new_var_proc = new_var_proc
253
+ @constrain_equal_proc = block
254
+ end
255
+
256
+ # Delegate to an instance of the expression class when we get something
257
+ # that we can't handle.
258
+ def method_missing(name, *args)
259
+ if @expression_class.instance_methods.include? name.to_s
260
+ options = {}
261
+ if args.size >= 2 and args[1].kind_of? Hash
262
+ options = args[1]
263
+ end
264
+
265
+ # Link a variable to the composite constraint.
266
+ @params.update Gecode::Constraints::Util.decode_options(options.clone)
267
+ variable = @new_var_proc.call
268
+ @model.add_interaction do
269
+ @constrain_equal_proc.call(variable, @params, true)
270
+ end
271
+
272
+ # Perform the operation on the linked variable.
273
+ int_var_params = @params.clone.update(:lhs => variable)
274
+ @expression_class.new(@model, int_var_params).send(name, *args)
275
+ else
276
+ super
277
+ end
278
+ end
279
+
280
+ def ==(expression, options = {})
281
+ if !@params[:negate] and options[:reify].nil? and
282
+ expression.kind_of? @variable_class
283
+ # We don't need any additional constraints.
284
+ @params.update Gecode::Constraints::Util.decode_options(options)
285
+ @model.add_interaction do
286
+ @constrain_equal_proc.call(expression, @params, false)
287
+ end
288
+ else
289
+ method_missing(:==, expression, options)
290
+ end
291
+ end
292
+ alias_comparison_methods
293
+ end
294
+
295
+ # Describes a constraint expression that has yet to be completed. I.e. a
296
+ # form of must has not yet been called, but some method has been called to
297
+ # initiate the expression. An example is distinct with offsets:
298
+ #
299
+ # enum.with_offsets(0..n).must_be.distinct
300
+ #
301
+ # The call of with_offsets initiates the constraint as a stub, even though
302
+ # must has not yet been called.
303
+ class ExpressionStub #:nodoc:
304
+ # Constructs a new expression with the specified parameters.
305
+ def initialize(model, params)
306
+ @model = model
307
+ @params = params
308
+ end
309
+ end
310
+
311
+ # Describes an expression stub which includes left hand side methods and
312
+ # just sends models and parameters through a supplied block to construct the
313
+ # resulting expression.
314
+ class SimpleExpressionStub < ExpressionStub #:nodoc:
315
+ include Gecode::Constraints::LeftHandSideMethods
316
+
317
+ # The block provided is executed when the expression demanded by the left
318
+ # hand side methods is to be constructed. The block should take two
319
+ # parameters: model and params (which have been updated with negate and
320
+ # so on). The block should return an expression.
321
+ def initialize(model, params, &block)
322
+ super(model, params)
323
+ @proc = block
324
+ end
325
+
326
+ private
327
+
328
+ # Produces an expression with offsets for the lhs module.
329
+ def expression(params)
330
+ @params.update(params)
331
+ @proc.call(@model, @params)
332
+ end
333
+ end
334
+
335
+ # Describes a stub that produces a variable, which can then be used with
336
+ # that variable's normalconstraints. An example with int variables would be
337
+ # the element constraint.
338
+ #
339
+ # int_enum[int_var].must > rhs
340
+ #
341
+ # The int_enum[int_var] part produces an int variable which the constraint
342
+ # ".must > rhs" is then applied to. In the above case two constraints (and
343
+ # one temporary variable) are required, but in the case of equality only
344
+ # one constraint is required.
345
+ class CompositeStub < Gecode::Constraints::ExpressionStub #:nodoc:
346
+ include Gecode::Constraints::LeftHandSideMethods
347
+
348
+ # The composite expression class should be the class that the stub uses
349
+ # when creating its expressions.
350
+ def initialize(composite_expression_class, model, params)
351
+ super(model, params)
352
+ @composite_class = composite_expression_class
353
+ end
354
+
355
+ private
356
+
357
+ # Constrains the result of the stub to be equal to the specified variable
358
+ # with the specified parameters. If constrain is true then the variable's
359
+ # domain should additionally be constrained as much as possible.
360
+ def constrain_equal(variable, params, constrain)
361
+ raise NoMethodError, 'Abstract method has not been implemented.'
362
+ end
363
+
364
+ # Produces an expression with position for the lhs module.
365
+ def expression(params)
366
+ @params.update params
367
+ @composite_class.new(@model, @params) do |var, params, constrain|
368
+ constrain_equal(var, params, constrain)
369
+ end
370
+ end
371
+ end
372
+
373
+ # Base class for all constraints.
374
+ class Constraint
375
+ # Creates a constraint with the specified parameters, bound to the
376
+ # specified model.
377
+ def initialize(model, params)
378
+ @model = model
379
+ @params = params.clone
380
+ end
381
+
382
+ # Posts the constraint, adding it to the model. This is an abstract
383
+ # method and should be overridden by all sub-classes.
384
+ def post
385
+ raise NoMethodError, 'Abstract method has not been implemented.'
386
+ end
387
+ end
388
+ end
389
+ end
390
+
391
+ require 'gecoder/interface/constraints/reifiable_constraints'
392
+ require 'gecoder/interface/constraints/int_var_constraints'
393
+ require 'gecoder/interface/constraints/int_enum_constraints'
394
+ require 'gecoder/interface/constraints/bool_var_constraints'
395
+ require 'gecoder/interface/constraints/bool_enum_constraints'
396
+ require 'gecoder/interface/constraints/set_var_constraints'
397
+ require 'gecoder/interface/constraints/set_enum_constraints'
@@ -0,0 +1,246 @@
1
+ module Gecode
2
+ class FreeBoolVar
3
+ # Initiates a boolean constraint with this variable or +var+.
4
+ def |(var)
5
+ Constraints::Bool::ExpressionNode.new(self, @model) | var
6
+ end
7
+
8
+ # Initiates a boolean constraint with this variable and +var+.
9
+ def &(var)
10
+ Constraints::Bool::ExpressionNode.new(self, @model) & var
11
+ end
12
+
13
+ # Initiates a boolean constraint with this variable exclusive or +var+.
14
+ def ^(var)
15
+ Constraints::Bool::ExpressionNode.new(self, @model) ^ var
16
+ end
17
+
18
+ # Initiates a boolean constraint with this variable implies +var+.
19
+ def implies(var)
20
+ Constraints::Bool::ExpressionNode.new(self, @model).implies var
21
+ end
22
+ end
23
+
24
+ # A module that gathers the classes and modules used in boolean constraints.
25
+ module Constraints::Bool
26
+ # Describes a boolean expression (following after must*).
27
+ class Expression #:nodoc:
28
+ def ==(expression, options = {})
29
+ @params.update Gecode::Constraints::Util.decode_options(options)
30
+ @model.add_constraint BooleanConstraint.new(@model,
31
+ @params.update(:rhs => expression))
32
+ end
33
+ alias_comparison_methods
34
+
35
+ # Constrains the boolean expression to imply the specified expression.
36
+ def imply(expression, options = {})
37
+ @params.update Gecode::Constraints::Util.decode_options(options)
38
+ @params.update(:lhs => @params[:lhs].implies(expression), :rhs => true)
39
+ @model.add_constraint BooleanConstraint.new(@model, @params)
40
+ end
41
+
42
+ # Constrains the boolean expression to be true.
43
+ def true
44
+ @params.update Gecode::Constraints::Util.decode_options({})
45
+ @model.add_constraint BooleanConstraint.new(@model,
46
+ @params.update(:rhs => true))
47
+ end
48
+
49
+ # Constrains the boolean expression to be false.
50
+ def false
51
+ @params[:negate] = !@params[:negate]
52
+ self.true
53
+ end
54
+ end
55
+
56
+ # Describes a constraint on a boolean expression.
57
+ #
58
+ # == Boolean expressions
59
+ #
60
+ # A boolean expression consists of several boolean variable with various
61
+ # boolean operators. The available operators are:
62
+ #
63
+ # [<tt>|</tt>] Or
64
+ # [<tt>&</tt>] And
65
+ # [<tt>^</tt>] Exclusive or
66
+ # [+implies+] Implication
67
+ #
68
+ # === Examples
69
+ #
70
+ # # +b1+ and +b2+
71
+ # b1 & b2
72
+ #
73
+ # # (+b1+ and +b2+) or +b3+
74
+ # (b1 & b1) | b3
75
+ #
76
+ # # (+b1+ and +b2+) or (+b3+ exclusive or +b1+)
77
+ # (b1 & b2) | (b3 ^ b1)
78
+ #
79
+ # # (+b1+ implies +b2+) and (+b3+ implies +b2+)
80
+ # (b1.implies b2) & (b3.implies b2)
81
+ #
82
+ # == Domain
83
+ #
84
+ # A domain constraint just specifies that a boolean expression must be true
85
+ # or false. Negation and reification are supported.
86
+ #
87
+ # === Examples
88
+ #
89
+ # # +b1+ and +b2+ must be true.
90
+ # (b1 & b2).must_be.true
91
+ #
92
+ # # (+b1+ implies +b2+) and (+b3+ implies +b2+) must be false.
93
+ # ((b1.implies b2) & (b3.implies b2)).must_be.false
94
+ #
95
+ # # +b1+ and +b2+ must be true. We reify it with +bool+ and select the
96
+ # # strength +domain+.
97
+ # (b1 & b2).must_be.true(:reify => bool, :strength => :domain)
98
+ #
99
+ # == Equality
100
+ #
101
+ # A constraint with equality specifies that two boolean expressions must be
102
+ # equal. Negation and reification are supported. Any of <tt>==</tt>,
103
+ # +equal+ and +equal_to+ may be used for equality.
104
+ #
105
+ # === Examples
106
+ #
107
+ # # +b1+ and +b2+ must equal +b1+ or +b2+.
108
+ # (b1 & b2).must == (b1 | b2)
109
+ #
110
+ # # +b1+ and +b2+ must not equal +b3+. We reify it with +bool+ and select
111
+ # # the strength +domain+.
112
+ # (b1 & b2).must_not.equal(b3, :reify => bool, :select => :domain)
113
+ #
114
+ # == Implication
115
+ #
116
+ # A constraint using +imply+ specified that one boolean expression must
117
+ # imply the other. Negation and reification are supported.
118
+ #
119
+ # === Examples
120
+ #
121
+ # # +b1+ must imply +b2+
122
+ # b1.must.imply b2
123
+ #
124
+ # # +b1+ and +b2+ must not imply +b3+. We reify it with +bool+ and select
125
+ # # +domain+ as strength.
126
+ # (b1 & b2).must_not.imply b3
127
+ class BooleanConstraint < Gecode::Constraints::ReifiableConstraint
128
+ def post
129
+ lhs, rhs, negate, strength, reif_var = @params.values_at(:lhs, :rhs,
130
+ :negate, :strength, :reif)
131
+ space = (lhs.model || rhs.model).active_space
132
+
133
+ # TODO: It should be possible to reduce the number of necessary
134
+ # variables and constraints a bit by altering the way that the top node
135
+ # is posted, using its constraint for reification etc when possible.
136
+
137
+ if rhs.respond_to? :bind
138
+ if reif_var.nil?
139
+ Gecode::Raw::bool_eqv(space, lhs.bind, rhs.bind, !negate, strength)
140
+ else
141
+ if negate
142
+ Gecode::Raw::bool_xor(space, lhs.bind, rhs.bind, reif_var.bind,
143
+ strength)
144
+ else
145
+ Gecode::Raw::bool_eqv(space, lhs.bind, rhs.bind, reif_var.bind,
146
+ strength)
147
+ end
148
+ end
149
+ else
150
+ should_hold = !negate & rhs
151
+ if reif_var.nil?
152
+ Gecode::Raw::MiniModel::BoolExpr.new(lhs.bind).post(space,
153
+ should_hold)
154
+ else
155
+ Gecode::Raw::bool_eqv(space, lhs.bind, reif_var.bind, should_hold,
156
+ strength)
157
+ end
158
+ end
159
+ end
160
+ end
161
+
162
+ # A module containing the methods for the basic boolean operations. Depends
163
+ # on that the class mixing it in defined #model.
164
+ module OperationMethods #:nodoc
165
+ include Gecode::Constraints::LeftHandSideMethods
166
+
167
+ private
168
+
169
+ # Maps the names of the methods to the corresponding bool constraint in
170
+ # Gecode.
171
+ OPERATION_TYPES = {
172
+ :| => :bool_or,
173
+ :& => :bool_and,
174
+ :^ => :bool_xor,
175
+ :implies => :bool_imp
176
+ }
177
+
178
+ public
179
+
180
+ OPERATION_TYPES.each_pair do |name, operation|
181
+ module_eval <<-"end_code"
182
+ def #{name}(expression)
183
+ unless expression.kind_of? ExpressionTree
184
+ expression = ExpressionNode.new(expression)
185
+ end
186
+ ExpressionTree.new(self, expression) do |model, var1, var2|
187
+ new_var = model.bool_var
188
+ Gecode::Raw::#{operation}(model.active_space, var1.bind, var2.bind,
189
+ new_var.bind, Gecode::Raw::ICL_DEF)
190
+ new_var
191
+ end
192
+ end
193
+ end_code
194
+ end
195
+
196
+ private
197
+
198
+ # Produces an expression for the lhs module.
199
+ def expression(params)
200
+ params.update(:lhs => self)
201
+ Gecode::Constraints::Bool::Expression.new(model, params)
202
+ end
203
+ end
204
+
205
+ # Describes a binary tree of expression nodes which together form a boolean
206
+ # expression.
207
+ class ExpressionTree #:nodoc:
208
+ include OperationMethods
209
+
210
+ # Constructs a new expression with the specified nodes. The proc should
211
+ # take a model followed by two variables and return a new variable.
212
+ def initialize(left_tree, right_tree, &block)
213
+ @left = left_tree
214
+ @right = right_tree
215
+ @bind_proc = block
216
+ end
217
+
218
+ # Returns a bound boolean variable representing the expression.
219
+ def bind
220
+ @bind_proc.call(model, @left, @right).bind
221
+ end
222
+
223
+ # Fetches the space that the expression's variables is in.
224
+ def model
225
+ @left.model || @right.model
226
+ end
227
+ end
228
+
229
+ # Describes a single node in a boolean expression.
230
+ class ExpressionNode #:nodoc:
231
+ include OperationMethods
232
+
233
+ attr :model
234
+
235
+ def initialize(value, model = nil)
236
+ @value = value
237
+ @model = model
238
+ end
239
+
240
+ # Returns a bound boolean variable representing the expression.
241
+ def bind
242
+ @value.bind
243
+ end
244
+ end
245
+ end
246
+ end