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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (203) hide show
  1. data/CHANGES +137 -0
  2. data/COPYING +17 -0
  3. data/LGPL-LICENSE +458 -0
  4. data/README +58 -0
  5. data/Rakefile +14 -0
  6. data/example/equation_system.rb +15 -0
  7. data/example/example_helper.rb +1 -0
  8. data/example/magic_sequence.rb +43 -0
  9. data/example/money.rb +36 -0
  10. data/example/queens.rb +42 -0
  11. data/example/send_more_money.rb +43 -0
  12. data/example/send_most_money.rb +58 -0
  13. data/example/square_tiling.rb +84 -0
  14. data/example/sudoku-set.rb +106 -0
  15. data/example/sudoku.rb +56 -0
  16. data/lib/gecode.dll +0 -0
  17. data/lib/gecoder.rb +5 -0
  18. data/lib/gecoder/bindings.rb +96 -0
  19. data/lib/gecoder/bindings/bindings.rb +2029 -0
  20. data/lib/gecoder/interface.rb +9 -0
  21. data/lib/gecoder/interface/binding_changes.rb +9 -0
  22. data/lib/gecoder/interface/branch.rb +163 -0
  23. data/lib/gecoder/interface/constraints.rb +471 -0
  24. data/lib/gecoder/interface/constraints/bool/boolean.rb +251 -0
  25. data/lib/gecoder/interface/constraints/bool/channel.rb +7 -0
  26. data/lib/gecoder/interface/constraints/bool/linear.rb +200 -0
  27. data/lib/gecoder/interface/constraints/bool_enum/channel.rb +68 -0
  28. data/lib/gecoder/interface/constraints/bool_enum/extensional.rb +106 -0
  29. data/lib/gecoder/interface/constraints/bool_enum/relation.rb +55 -0
  30. data/lib/gecoder/interface/constraints/bool_enum_constraints.rb +84 -0
  31. data/lib/gecoder/interface/constraints/bool_var_constraints.rb +155 -0
  32. data/lib/gecoder/interface/constraints/extensional_regexp.rb +101 -0
  33. data/lib/gecoder/interface/constraints/fixnum_enum/element.rb +63 -0
  34. data/lib/gecoder/interface/constraints/fixnum_enum/operation.rb +65 -0
  35. data/lib/gecoder/interface/constraints/fixnum_enum_constraints.rb +42 -0
  36. data/lib/gecoder/interface/constraints/int/arithmetic.rb +150 -0
  37. data/lib/gecoder/interface/constraints/int/channel.rb +51 -0
  38. data/lib/gecoder/interface/constraints/int/domain.rb +80 -0
  39. data/lib/gecoder/interface/constraints/int/linear.rb +143 -0
  40. data/lib/gecoder/interface/constraints/int/relation.rb +141 -0
  41. data/lib/gecoder/interface/constraints/int_enum/arithmetic.rb +63 -0
  42. data/lib/gecoder/interface/constraints/int_enum/channel.rb +86 -0
  43. data/lib/gecoder/interface/constraints/int_enum/count.rb +66 -0
  44. data/lib/gecoder/interface/constraints/int_enum/distinct.rb +64 -0
  45. data/lib/gecoder/interface/constraints/int_enum/element.rb +64 -0
  46. data/lib/gecoder/interface/constraints/int_enum/equality.rb +37 -0
  47. data/lib/gecoder/interface/constraints/int_enum/extensional.rb +187 -0
  48. data/lib/gecoder/interface/constraints/int_enum/sort.rb +135 -0
  49. data/lib/gecoder/interface/constraints/int_enum_constraints.rb +95 -0
  50. data/lib/gecoder/interface/constraints/int_var_constraints.rb +230 -0
  51. data/lib/gecoder/interface/constraints/reifiable_constraints.rb +78 -0
  52. data/lib/gecoder/interface/constraints/selected_set/select.rb +120 -0
  53. data/lib/gecoder/interface/constraints/selected_set_constraints.rb +75 -0
  54. data/lib/gecoder/interface/constraints/set/cardinality.rb +65 -0
  55. data/lib/gecoder/interface/constraints/set/channel.rb +51 -0
  56. data/lib/gecoder/interface/constraints/set/connection.rb +130 -0
  57. data/lib/gecoder/interface/constraints/set/domain.rb +156 -0
  58. data/lib/gecoder/interface/constraints/set/include.rb +36 -0
  59. data/lib/gecoder/interface/constraints/set/operation.rb +118 -0
  60. data/lib/gecoder/interface/constraints/set/relation.rb +155 -0
  61. data/lib/gecoder/interface/constraints/set_elements/relation.rb +116 -0
  62. data/lib/gecoder/interface/constraints/set_elements_constraints.rb +97 -0
  63. data/lib/gecoder/interface/constraints/set_enum/channel.rb +45 -0
  64. data/lib/gecoder/interface/constraints/set_enum/distinct.rb +43 -0
  65. data/lib/gecoder/interface/constraints/set_enum/operation.rb +69 -0
  66. data/lib/gecoder/interface/constraints/set_enum/select.rb +79 -0
  67. data/lib/gecoder/interface/constraints/set_enum_constraints.rb +84 -0
  68. data/lib/gecoder/interface/constraints/set_var_constraints.rb +243 -0
  69. data/lib/gecoder/interface/enum_matrix.rb +64 -0
  70. data/lib/gecoder/interface/enum_wrapper.rb +205 -0
  71. data/lib/gecoder/interface/model.rb +453 -0
  72. data/lib/gecoder/interface/model_sugar.rb +84 -0
  73. data/lib/gecoder/interface/search.rb +197 -0
  74. data/lib/gecoder/interface/variables.rb +306 -0
  75. data/lib/gecoder/version.rb +4 -0
  76. data/specs/bool_var.rb +81 -0
  77. data/specs/branch.rb +185 -0
  78. data/specs/constraints/bool/boolean.rb +317 -0
  79. data/specs/constraints/bool/boolean_properties.rb +51 -0
  80. data/specs/constraints/bool/linear.rb +213 -0
  81. data/specs/constraints/bool_enum/bool_enum_relation.rb +117 -0
  82. data/specs/constraints/bool_enum/channel.rb +102 -0
  83. data/specs/constraints/bool_enum/extensional.rb +225 -0
  84. data/specs/constraints/constraint_helper.rb +234 -0
  85. data/specs/constraints/constraint_receivers.rb +103 -0
  86. data/specs/constraints/constraints.rb +26 -0
  87. data/specs/constraints/fixnum_enum/element.rb +58 -0
  88. data/specs/constraints/fixnum_enum/operation.rb +67 -0
  89. data/specs/constraints/int/arithmetic.rb +149 -0
  90. data/specs/constraints/int/channel.rb +101 -0
  91. data/specs/constraints/int/domain.rb +106 -0
  92. data/specs/constraints/int/linear.rb +183 -0
  93. data/specs/constraints/int/linear_properties.rb +97 -0
  94. data/specs/constraints/int/relation.rb +84 -0
  95. data/specs/constraints/int_enum/arithmetic.rb +72 -0
  96. data/specs/constraints/int_enum/channel.rb +57 -0
  97. data/specs/constraints/int_enum/count.rb +72 -0
  98. data/specs/constraints/int_enum/distinct.rb +80 -0
  99. data/specs/constraints/int_enum/element.rb +61 -0
  100. data/specs/constraints/int_enum/equality.rb +29 -0
  101. data/specs/constraints/int_enum/extensional.rb +224 -0
  102. data/specs/constraints/int_enum/sort.rb +167 -0
  103. data/specs/constraints/operands.rb +264 -0
  104. data/specs/constraints/property_helper.rb +443 -0
  105. data/specs/constraints/reification_sugar.rb +69 -0
  106. data/specs/constraints/selected_set/select.rb +56 -0
  107. data/specs/constraints/selected_set/select_properties.rb +157 -0
  108. data/specs/constraints/set/cardinality.rb +58 -0
  109. data/specs/constraints/set/cardinality_properties.rb +46 -0
  110. data/specs/constraints/set/channel.rb +77 -0
  111. data/specs/constraints/set/connection.rb +176 -0
  112. data/specs/constraints/set/domain.rb +197 -0
  113. data/specs/constraints/set/include.rb +36 -0
  114. data/specs/constraints/set/operation.rb +132 -0
  115. data/specs/constraints/set/relation.rb +117 -0
  116. data/specs/constraints/set_elements/relation.rb +84 -0
  117. data/specs/constraints/set_enum/channel.rb +80 -0
  118. data/specs/constraints/set_enum/distinct.rb +59 -0
  119. data/specs/constraints/set_enum/operation.rb +111 -0
  120. data/specs/constraints/set_enum/select.rb +73 -0
  121. data/specs/distribution.rb +14 -0
  122. data/specs/enum_matrix.rb +43 -0
  123. data/specs/enum_wrapper.rb +179 -0
  124. data/specs/examples.rb +17 -0
  125. data/specs/int_var.rb +163 -0
  126. data/specs/logging.rb +24 -0
  127. data/specs/model.rb +325 -0
  128. data/specs/model_sugar.rb +30 -0
  129. data/specs/search.rb +383 -0
  130. data/specs/selected_set.rb +39 -0
  131. data/specs/set_elements.rb +34 -0
  132. data/specs/set_var.rb +82 -0
  133. data/specs/spec_helper.rb +265 -0
  134. data/tasks/all_tasks.rb +1 -0
  135. data/tasks/dependencies.txt +22 -0
  136. data/tasks/distribution.rake +194 -0
  137. data/tasks/rcov.rake +18 -0
  138. data/tasks/specs.rake +21 -0
  139. data/tasks/svn.rake +16 -0
  140. data/tasks/website.rake +51 -0
  141. data/vendor/gecode/win32/lib/libgecodeint.dll +0 -0
  142. data/vendor/gecode/win32/lib/libgecodekernel.dll +0 -0
  143. data/vendor/gecode/win32/lib/libgecodeminimodel.dll +0 -0
  144. data/vendor/gecode/win32/lib/libgecodesearch.dll +0 -0
  145. data/vendor/gecode/win32/lib/libgecodeset.dll +0 -0
  146. data/vendor/gecode/win32/lib/libgecodesupport.dll +0 -0
  147. data/vendor/rust/README +28 -0
  148. data/vendor/rust/bin/cxxgenerator.rb +93 -0
  149. data/vendor/rust/include/rust_checks.hh +116 -0
  150. data/vendor/rust/include/rust_conversions.hh +102 -0
  151. data/vendor/rust/rust.rb +67 -0
  152. data/vendor/rust/rust/attribute.rb +51 -0
  153. data/vendor/rust/rust/bindings.rb +172 -0
  154. data/vendor/rust/rust/class.rb +337 -0
  155. data/vendor/rust/rust/constants.rb +48 -0
  156. data/vendor/rust/rust/container.rb +110 -0
  157. data/vendor/rust/rust/cppifaceparser.rb +129 -0
  158. data/vendor/rust/rust/cwrapper.rb +72 -0
  159. data/vendor/rust/rust/cxxclass.rb +96 -0
  160. data/vendor/rust/rust/element.rb +81 -0
  161. data/vendor/rust/rust/enum.rb +63 -0
  162. data/vendor/rust/rust/function.rb +407 -0
  163. data/vendor/rust/rust/namespace.rb +61 -0
  164. data/vendor/rust/rust/templates/AttributeDefinition.rusttpl +17 -0
  165. data/vendor/rust/rust/templates/AttributeInitBinding.rusttpl +9 -0
  166. data/vendor/rust/rust/templates/BindingsHeader.rusttpl +24 -0
  167. data/vendor/rust/rust/templates/BindingsUnit.rusttpl +46 -0
  168. data/vendor/rust/rust/templates/CWrapperClassDefinitions.rusttpl +64 -0
  169. data/vendor/rust/rust/templates/ClassDeclarations.rusttpl +7 -0
  170. data/vendor/rust/rust/templates/ClassInitialize.rusttpl +6 -0
  171. data/vendor/rust/rust/templates/ConstructorStub.rusttpl +21 -0
  172. data/vendor/rust/rust/templates/CxxClassDefinitions.rusttpl +100 -0
  173. data/vendor/rust/rust/templates/CxxMethodStub.rusttpl +12 -0
  174. data/vendor/rust/rust/templates/CxxStandaloneClassDefinitions.rusttpl +26 -0
  175. data/vendor/rust/rust/templates/EnumDeclarations.rusttpl +3 -0
  176. data/vendor/rust/rust/templates/EnumDefinitions.rusttpl +29 -0
  177. data/vendor/rust/rust/templates/FunctionDefinition.rusttpl +9 -0
  178. data/vendor/rust/rust/templates/FunctionInitAlias.rusttpl +5 -0
  179. data/vendor/rust/rust/templates/FunctionInitBinding.rusttpl +9 -0
  180. data/vendor/rust/rust/templates/MethodInitBinding.rusttpl +9 -0
  181. data/vendor/rust/rust/templates/ModuleDeclarations.rusttpl +3 -0
  182. data/vendor/rust/rust/templates/ModuleDefinitions.rusttpl +3 -0
  183. data/vendor/rust/rust/templates/StandaloneClassDeclarations.rusttpl +7 -0
  184. data/vendor/rust/rust/templates/VariableFunctionCall.rusttpl +14 -0
  185. data/vendor/rust/rust/type.rb +98 -0
  186. data/vendor/rust/test/Makefile +4 -0
  187. data/vendor/rust/test/constants.rb +36 -0
  188. data/vendor/rust/test/cppclass.cc +45 -0
  189. data/vendor/rust/test/cppclass.hh +67 -0
  190. data/vendor/rust/test/cppclass.rb +59 -0
  191. data/vendor/rust/test/cwrapper.c +74 -0
  192. data/vendor/rust/test/cwrapper.h +41 -0
  193. data/vendor/rust/test/cwrapper.rb +56 -0
  194. data/vendor/rust/test/dummyclass.hh +31 -0
  195. data/vendor/rust/test/lib/extension-test.rb +98 -0
  196. data/vendor/rust/test/operators.cc +41 -0
  197. data/vendor/rust/test/operators.hh +39 -0
  198. data/vendor/rust/test/operators.rb +39 -0
  199. data/vendor/rust/test/test-constants.rb +43 -0
  200. data/vendor/rust/test/test-cppclass.rb +82 -0
  201. data/vendor/rust/test/test-cwrapper.rb +80 -0
  202. data/vendor/rust/test/test-operators.rb +42 -0
  203. metadata +393 -0
@@ -0,0 +1,66 @@
1
+ module Gecode::IntEnum
2
+ module IntEnumOperand
3
+ # Produces a new IntOperand representing the number of times
4
+ # +int_operand_or_fixnum+ is present in this enumeration.
5
+ #
6
+ # ==== Examples
7
+ #
8
+ # # The number of times 17 occurs in +int_enum+.
9
+ # int_enum.count(17)
10
+ #
11
+ # # The number of times +int_operand+ occurs in +int_enum+.
12
+ # int_enum.count(int_operand)
13
+ def count(int_operand_or_fixnum)
14
+ unless int_operand_or_fixnum.respond_to? :to_int_var or
15
+ int_operand_or_fixnum.kind_of?(Fixnum)
16
+ raise TypeError, 'Expected integer operand of fixnum, got ' +
17
+ "#{int_operand_or_fixnum.class}."
18
+ end
19
+ Count::IntEnumCountOperand.new(@model, self, int_operand_or_fixnum)
20
+ end
21
+ end
22
+
23
+ # A module that gathers the classes and modules used in count constraints.
24
+ module Count #:nodoc:
25
+ class IntEnumCountOperand < Gecode::Int::ShortCircuitRelationsOperand #:nodoc:
26
+ def initialize(model, int_enum, element)
27
+ super model
28
+ @enum = int_enum
29
+ @element = element
30
+ end
31
+
32
+ def relation_constraint(relation, int_operand_or_fix, params)
33
+ unless params[:negate]
34
+ relation_type =
35
+ Gecode::Util::RELATION_TYPES[relation]
36
+ else
37
+ relation_type =
38
+ Gecode::Util::NEGATED_RELATION_TYPES[relation]
39
+ end
40
+
41
+ params.update(:enum => @enum, :element => @element,
42
+ :rhs => int_operand_or_fix, :relation_type => relation_type)
43
+ CountConstraint.new(@model, params)
44
+ end
45
+ end
46
+
47
+ class CountConstraint < Gecode::ReifiableConstraint #:nodoc:
48
+ def post
49
+ enum, element, relation_type, rhs =
50
+ @params.values_at(:enum, :element, :relation_type, :rhs)
51
+
52
+ # Bind variables if needed.
53
+ unless element.kind_of? Fixnum
54
+ element = element.to_int_var.bind
55
+ end
56
+ unless rhs.kind_of? Fixnum
57
+ rhs = rhs.to_int_var.bind
58
+ end
59
+
60
+ # Post the constraint to gecode.
61
+ Gecode::Raw::count(@model.active_space, enum.to_int_enum.bind_array,
62
+ element, relation_type, rhs, *propagation_options)
63
+ end
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,64 @@
1
+ module Gecode::IntEnum
2
+ class IntEnumConstraintReceiver
3
+ # Constrains all integer operands in the enumeration to be distinct
4
+ # (different). The constraint can also be used with constant
5
+ # offsets, so that the operands, with specified offsets added, must
6
+ # be distinct.
7
+ #
8
+ # The constraint does not support negation nor reification.
9
+ #
10
+ # ==== Examples
11
+ #
12
+ # # Constrains all operands in +int_enum+ to be assigned different
13
+ # # values.
14
+ # int_enum.must_be.distinct
15
+ #
16
+ # # The same as above, but also selects that the strength +domain+ should
17
+ # # be used.
18
+ # int_enum.must_be.distinct(:strength => :domain)
19
+ #
20
+ # # Uses the offset to constrain that no number may be the previous number
21
+ # # incremented by one.
22
+ # numbers = int_var_array(8, 0..9)
23
+ # numbers.must_be.distinct(:offsets => (1..numbers.size).to_a.reverse)
24
+ def distinct(options = {})
25
+ if @params[:negate]
26
+ # The best we could implement it as from here would be a bunch of
27
+ # reified pairwise equality constraints.
28
+ raise Gecode::MissingConstraintError, 'A negated distinct is not ' +
29
+ 'implemented.'
30
+ end
31
+ unless options[:reify].nil?
32
+ raise ArgumentError, 'Reification is not supported by the distinct ' +
33
+ 'constraint.'
34
+ end
35
+
36
+ if options.has_key? :offsets
37
+ offsets = options.delete(:offsets)
38
+ unless offsets.kind_of? Enumerable
39
+ raise TypeError, 'Expected Enumerable as offsets, got ' +
40
+ "#{offsets.class}."
41
+ end
42
+ @params[:offsets] = offsets
43
+ end
44
+ @model.add_constraint Distinct::DistinctConstraint.new(@model,
45
+ @params.update(Gecode::Util.decode_options(options)))
46
+ end
47
+ end
48
+
49
+ # A module that gathers the classes and modules used in distinct constraints.
50
+ module Distinct #:nodoc:
51
+ class DistinctConstraint < Gecode::Constraint #:nodoc:
52
+ def post
53
+ # Bind lhs.
54
+ @params[:lhs] = @params[:lhs].to_int_enum.bind_array
55
+
56
+ # Fetch the parameters to Gecode.
57
+ params = @params.values_at(:offsets, :lhs)
58
+ params.delete_if{ |x| x.nil? }
59
+ params.concat propagation_options
60
+ Gecode::Raw::distinct(@model.active_space, *params)
61
+ end
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,64 @@
1
+ module Gecode::IntEnum
2
+ module IntEnumOperand
3
+ # This adds the adder for the methods in the modules including it. The
4
+ # reason for doing it so indirect is that the first #[] won't be defined
5
+ # before the module that this is mixed into is mixed into an enum.
6
+ def self.included(enum_mod) #:nodoc:
7
+ enum_mod.module_eval do
8
+ # Now we enter the module IntEnumOperands is mixed into.
9
+ class << self
10
+ alias_method :pre_element_included, :included
11
+ def included(mod) #:nodoc:
12
+ mod.module_eval do
13
+ if instance_methods.include? '[]'
14
+ alias_method :pre_element_access, :[]
15
+ end
16
+
17
+ # Produces an IntOperand representing the
18
+ # i:th integer operand in the enumeration, where i is the
19
+ # value of the integer operand used as index. Think of it
20
+ # as array access in the world of constraint programming.
21
+ #
22
+ # ==== Examples
23
+ #
24
+ # # The operand at the +x+:th position in +int_enum+,
25
+ # # where +x+ is an integer operand.
26
+ # int_enum[x]
27
+ #
28
+ def [](*vars)
29
+ if vars.first.respond_to? :to_int_var
30
+ return Element::ElementIntOperand.new(
31
+ model, self, vars.first)
32
+ else
33
+ pre_element_access(*vars) if respond_to? :pre_element_access
34
+ end
35
+ end
36
+ end
37
+ pre_element_included(mod)
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
43
+
44
+ module Element #:nodoc:
45
+ class ElementIntOperand < Gecode::Int::ShortCircuitEqualityOperand #:nodoc:
46
+ def initialize(model, enum_op, position_int_var_op)
47
+ super model
48
+ @enum = enum_op
49
+ @position = position_int_var_op
50
+ end
51
+
52
+ def constrain_equal(int_operand, constrain, propagation_options)
53
+ enum = @enum.to_int_enum
54
+ if constrain
55
+ int_operand.must_be.in enum.domain_range
56
+ end
57
+
58
+ Gecode::Raw::element(model.active_space, enum.bind_array,
59
+ @position.to_int_var.bind, int_operand.to_int_var.bind,
60
+ *propagation_options)
61
+ end
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,37 @@
1
+ module Gecode::IntEnum
2
+ class IntEnumConstraintReceiver
3
+ # Constrains all operands in the enumeration to be equal.
4
+ # Neither negation nor reification is supported.
5
+ #
6
+ # ==== Examples
7
+ #
8
+ # # Constrains all operands in +int_enum+ to be equal.
9
+ # int_enum.must_be.equal
10
+ def equal(options = {})
11
+ if @params[:negate]
12
+ # The best we could implement it as from here would be a bunch of
13
+ # reified pairwise inequality constraints.
14
+ raise Gecode::MissingConstraintError, 'A negated equality is not ' +
15
+ 'implemented.'
16
+ end
17
+ unless options[:reify].nil?
18
+ raise ArgumentError, 'Reification is not supported by the equality ' +
19
+ 'constraint.'
20
+ end
21
+
22
+ @model.add_constraint Equality::EqualityConstraint.new(@model,
23
+ @params.update(Gecode::Util.decode_options(options)))
24
+ end
25
+ end
26
+
27
+ # A module that gathers the classes and modules used in equality constraints.
28
+ module Equality #:nodoc:
29
+ class EqualityConstraint < Gecode::Constraint #:nodoc:
30
+ def post
31
+ Gecode::Raw::rel(@model.active_space,
32
+ @params[:lhs].to_int_enum.bind_array,
33
+ Gecode::Raw::IRT_EQ, *propagation_options)
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,187 @@
1
+ module Gecode::IntEnum
2
+ class IntEnumConstraintReceiver
3
+ # Constrains all the operands in this enumeration to be equal to
4
+ # one of the specified tuples. Neither negation nor reification is
5
+ # supported.
6
+ #
7
+ # ==== Examples
8
+ #
9
+ # # Constrains the two integer operands in +numbers+ to either have
10
+ # # values 1 and 7, or values 47 and 11.
11
+ # numbers.must_be.in [[1,7], [47,11]]
12
+ #
13
+ # # The same as above, but preferring speed over low memory usage.
14
+ # numbers.must_be.in([[1,7], [47,11]], :kind => :speed)
15
+ def in(tuples, options = {})
16
+ if @params[:negate]
17
+ raise Gecode::MissingConstraintError, 'A negated tuple constraint is ' +
18
+ 'not implemented.'
19
+ end
20
+ unless options[:reify].nil?
21
+ raise ArgumentError, 'Reification is not supported by the tuple ' +
22
+ 'constraint.'
23
+ end
24
+
25
+ util = Gecode::Util
26
+
27
+ # Check that the tuples are correct.
28
+ expected_size = @params[:lhs].size
29
+ util::Extensional.perform_tuple_checks(tuples, expected_size) do |tuple|
30
+ unless tuple.all?{ |x| x.kind_of? Fixnum }
31
+ raise TypeError, 'All tuples must contain Fixnum.'
32
+ end
33
+ end
34
+
35
+ @params[:tuples] = tuples
36
+ @model.add_constraint Extensional::TupleConstraint.new(@model,
37
+ @params.update(util.decode_options(options)))
38
+ end
39
+
40
+ # Constrains the sequence of operands in this enumeration to match
41
+ # a specified regexp in the integer domain. Neither negation nor
42
+ # reification is supported.
43
+ #
44
+ # == Regexp syntax
45
+ #
46
+ # The regular expressions are specified using arrays, integers and a
47
+ # few methods provided by Model. Arrays are used to group the
48
+ # integers in sequences that must be matched. The following array
49
+ # describes a regular expression matching a 1 followed by a 7.
50
+ #
51
+ # [1, 7]
52
+ #
53
+ # Arrays can be nested or left out when not needed. I.e. the above
54
+ # is semantically equal to
55
+ #
56
+ # [[[1], 7]]
57
+ #
58
+ # A couple of methods provided by Model are used to express patterns
59
+ # beyond mere sequences:
60
+ #
61
+ # [Model#repeat] Used for specifying patterns that include patterns
62
+ # that may be repeated a given number of times. The
63
+ # number of times to repeat a pattern can be specified
64
+ # using a lower and upper bound, but the bounds can be
65
+ # omitted to for instance allow an expression to be
66
+ # repeated any number of times.
67
+ # [Model#any] Used for specifying alternatives.
68
+ #
69
+ # Additionally Model#at_least_once and Model#at_most_once are
70
+ # provided as convenience methods.
71
+ #
72
+ # ==== Examples
73
+ #
74
+ # # Matches 1 followed by any number of 2s.
75
+ # [1, repeat(2)]
76
+ #
77
+ # # Semantically the same as above. It just has a bunch of
78
+ # # needless brackets thrown in.
79
+ # [[1], [repeat([2])]]
80
+ #
81
+ # # Matches 1 followed by [a 2 followed by a 3] at least two times.
82
+ # # Matches e.g. 1, 2, 3, 2, 3
83
+ # [1, repeat([2, 3], 2)]
84
+ #
85
+ # # Matches between one and two [2 followed by [at least three 1]]
86
+ # # followed by between three and four 3. Matches e.g.
87
+ # # 2, 1, 1, 1, 2, 1, 1, 1, 3, 3, 3
88
+ # [repeat([2, repeat(1, 3], 1, 2), repeat(3, 3, 4)]
89
+ #
90
+ # # Matches [1, 2 or 3] followed by 4. Matches e.g. 2, 4
91
+ # [any(1, 2, 3), 4]
92
+ #
93
+ # # Matches 0 followed by [[1 followed by 2] or [3 followed by 5]].
94
+ # # Matches e.g. 0, 1, 2 as well as 0, 3, 5
95
+ # [0, any([1, 2], [3, 5])]
96
+ #
97
+ # # Matches 0 followed by [[[1 followed by 7] at least two times]
98
+ # # or [[8, 9], at most two times]. Matches e.g.
99
+ # # 0, 1, 7, 1, 7, 1, 7 as well as 0, 8, 9
100
+ # [0, any(repeat([1, 7], 2), repeat([8, 9], 0, 2)]
101
+ #
102
+ # # Matches 0 followed by at least one 1.
103
+ # [0, at_least_once(1)]
104
+ #
105
+ # # Exactly the same as the above.
106
+ # [0, repeat(1, 1)]
107
+ #
108
+ # # Matches 0 followed by at least one [[1 followed by 7] or [3
109
+ # # followed by 2]]. Matches e.g. 0, 1, 7, 3, 2, 1, 7
110
+ # [0, at_least_once(any([1, 7], [3, 2]]
111
+ #
112
+ # # Matches 0 followed by at either [[1 followed by 7] at least once]
113
+ # # or [[3 followed by 2] at least once]. Matches e.g.
114
+ # # 0, 1, 7, 1, 7 but does _not_ match 0, 1, 7, 3, 2, 1, 7
115
+ # [0, any(at_least_once([1, 7]), at_least_once([3, 2])]
116
+ #
117
+ # # Matches 0, followed by at most one 1. Matches 0 as well as
118
+ # # 0, 1
119
+ # [0, at_most_once(1)]
120
+ #
121
+ # # Exactly the same as the above.
122
+ # [0, repeat(1, 0, 1)]
123
+ #
124
+ # ==== Examples
125
+ #
126
+ # # Constrains the two integer operands in +numbers+ to have
127
+ # # values 1 and 7.
128
+ # numbers.must.match [1, 7]
129
+ #
130
+ # # Constrains the integer operands in +numbers+ to contain the
131
+ # # value 47 followed by 11, with all other values set to -1.
132
+ # numbers.must.match [repeat(-1), 47, 11, repeat(-1)]
133
+ #
134
+ # # Constrains exactly three of the integer operands in +numbers+ to
135
+ # # contain 47 or 11, each followed by at least two
136
+ # # operands set to -1. All other operands are constrained to
137
+ # # equal -1.
138
+ # numbers.must.match repeat([repeat(-1), any(11, 47),
139
+ # repeat(-1, 2)], 3, 3)
140
+ #
141
+ def match(regexp, options = {})
142
+ if @params[:negate]
143
+ raise Gecode::MissingConstraintError, 'A negated regexp constraint ' +
144
+ 'is not implemented.'
145
+ end
146
+ unless options[:reify].nil?
147
+ raise ArgumentError, 'Reification is not supported by the regexp ' +
148
+ 'constraint.'
149
+ end
150
+
151
+ @params[:regexp] =
152
+ Gecode::Util::Extensional.parse_regexp regexp
153
+ @params.update Gecode::Util.decode_options(options)
154
+ @model.add_constraint Extensional::RegexpConstraint.new(@model, @params)
155
+ end
156
+ end
157
+
158
+ # A module that gathers the classes and modules used in extensional
159
+ # constraints.
160
+ module Extensional #:nodoc:
161
+ class TupleConstraint < Gecode::Constraint #:nodoc:
162
+ def post
163
+ # Bind lhs.
164
+ lhs = @params[:lhs].to_int_enum.bind_array
165
+
166
+ # Create the tuple set.
167
+ tuple_set = Gecode::Raw::TupleSet.new
168
+ @params[:tuples].each do |tuple|
169
+ tuple_set.add tuple
170
+ end
171
+ tuple_set.finalize
172
+
173
+ # Post the constraint.
174
+ Gecode::Raw::extensional(@model.active_space, lhs, tuple_set,
175
+ *propagation_options)
176
+ end
177
+ end
178
+
179
+ class RegexpConstraint < Gecode::Constraint #:nodoc:
180
+ def post
181
+ lhs, regexp = @params.values_at(:lhs, :regexp)
182
+ Gecode::Raw::extensional(@model.active_space,
183
+ lhs.to_int_enum.bind_array, regexp, *propagation_options)
184
+ end
185
+ end
186
+ end
187
+ end
@@ -0,0 +1,135 @@
1
+ module Gecode::IntEnum
2
+ class IntEnumConstraintReceiver
3
+ # Constrains the elements in this enumeration to be sorted in ascending
4
+ # order. The following options can be given in addition to the
5
+ # common constraint options:
6
+ #
7
+ # [:as] Defines a target (must be an IntEnum) that will
8
+ # hold the sorted version of the original enumerable. The original
9
+ # enumerable will not be affected (i.e. will not necessarily be
10
+ # sorted)
11
+ # [:order] Sets an IntEnum that should be used to store the
12
+ # order of the original enum's operands when sorted. The original
13
+ # enumerable will not be affected (i.e. will not necessarily be
14
+ # sorted)
15
+ #
16
+ # If neither of those options are specified then the original enumerable
17
+ # will be constrained to be sorted (otherwise not). Sort constraints with
18
+ # options do not allow negation.
19
+ #
20
+ # ==== Examples
21
+ #
22
+ # # Constrain +numbers+ to be sorted.
23
+ # numbers.must_be.sorted
24
+ #
25
+ # # Constrain +numbers+ to not be sorted.
26
+ # numbers.must_not_be.sorted
27
+ #
28
+ # # Constrain +sorted_numbers+ to be a sorted version of +numbers+.
29
+ # numbers.must_be.sorted(:as => sorted_numbers)
30
+ #
31
+ # # Constrain +order+ to be the order in which +numbers+ has to be
32
+ # # ordered to be sorted.
33
+ # numbers.must_be.sorted(:order => order)
34
+ #
35
+ # # Constrain +sorted_numbers+ to be +numbers+ sorted in the order
36
+ # # described by the IntEnum +order+.
37
+ # numbers.must_be.sorted(:as => sorted_numbers, :order => order)
38
+ #
39
+ # # Constrains +numbers+ to be sorted, reifying with the boolean
40
+ # # operand +is_sorted+, while selecting +domain+ as strength.
41
+ # numbers.must_be.sorted(:reify => :is_sorted, :strength => :domain)
42
+ def sorted(options = {})
43
+ # Extract and check options.
44
+ target = options.delete(:as)
45
+ order = options.delete(:order)
46
+ unless target.nil? or target.respond_to? :to_int_enum
47
+ raise TypeError, 'Expected int var enum as :as, got ' +
48
+ "#{target.class}."
49
+ end
50
+ unless order.nil? or order.respond_to? :to_int_enum
51
+ raise TypeError, 'Expected int var enum as :order, got ' +
52
+ "#{order.class}."
53
+ end
54
+
55
+ # Extract standard options and convert to constraint.
56
+ reified = !options[:reify].nil?
57
+ @params.update(Gecode::Util.decode_options(options))
58
+ if target.nil? and order.nil?
59
+ @model.add_constraint Sort::SortConstraint.new(@model, @params)
60
+ else
61
+ # Do not allow negation.
62
+ if @params[:negate]
63
+ raise Gecode::MissingConstraintError, 'A negated sort with options ' +
64
+ 'is not implemented.'
65
+ end
66
+ if reified
67
+ raise ArgumentError, 'Reification is not supported by the sorted ' +
68
+ 'constraint.'
69
+ end
70
+
71
+ @params.update(:target => target, :order => order)
72
+ @model.add_constraint Sort::SortConstraintWithOptions.new(@model,
73
+ @params)
74
+ end
75
+ end
76
+ end
77
+
78
+ # A module that gathers the classes and modules used in sort constraints.
79
+ module Sort #:nodoc:
80
+ class SortConstraintWithOptions < Gecode::Constraint #:nodoc:
81
+ def post
82
+ if @params[:target].nil?
83
+ # We must have a target.
84
+ lhs = @params[:lhs].to_int_enum
85
+ @params[:target] = @model.int_var_array(lhs.size, lhs.domain_range)
86
+ end
87
+
88
+ # Prepare the parameters.
89
+ params = @params.values_at(:lhs, :target, :order).map do |param|
90
+ if param.respond_to? :to_int_enum
91
+ param.to_int_enum.bind_array
92
+ else
93
+ param
94
+ end
95
+ end.delete_if{ |param| param.nil? }
96
+ params.concat propagation_options
97
+
98
+ # Post the constraint.
99
+ Gecode::Raw::sorted(@model.active_space, *params)
100
+ end
101
+ end
102
+
103
+ class SortConstraint < Gecode::ReifiableConstraint #:nodoc:
104
+ def post
105
+ lhs, strength, kind, reif_var =
106
+ @params.values_at(:lhs, :strength, :kind, :reif)
107
+ using_reification = !reif_var.nil?
108
+
109
+ # We translate the constraint into n-1 relation constraints.
110
+ options = {
111
+ :strength =>
112
+ Gecode::Util::PROPAGATION_STRENGTHS.invert[strength],
113
+ :kind =>
114
+ Gecode::Util::PROPAGATION_KINDS.invert[kind]
115
+ }
116
+ if using_reification
117
+ reification_variables = @model.bool_var_array(lhs.size - 1)
118
+ end
119
+ (lhs.size - 1).times do |i|
120
+ first, second = lhs[i, 2]
121
+ rel_options = options.clone
122
+ if using_reification
123
+ # Reify each relation constraint and then bind them all together.
124
+ rel_options[:reify] = reification_variables[i]
125
+ end
126
+ first.must_be.less_than_or_equal_to(second, rel_options)
127
+ end
128
+ if using_reification
129
+ reification_variables.conjunction.must == reif_var
130
+ end
131
+ end
132
+ negate_using_reification
133
+ end
134
+ end
135
+ end