gecoder 0.8.3 → 0.9.0

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 (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,23 +1,26 @@
1
- module Gecode
2
- module IntEnumMethods
3
- # Specifies offsets to be used with a distinct constraint. The offsets can
4
- # be specified one by one or as an array of offsets.
5
- def with_offsets(*offsets)
6
- if offsets.kind_of? Enumerable
7
- offsets = *offsets
8
- end
9
- params = {:lhs => self, :offsets => offsets}
10
-
11
- Gecode::Constraints::SimpleExpressionStub.new(@model, params) do |m, ps|
12
- Gecode::Constraints::IntEnum::Expression.new(m, ps)
13
- end
14
- end
15
- end
16
- end
17
-
18
- module Gecode::Constraints::IntEnum
19
- class Expression
20
- # Posts a distinct constraint on the variables in the enum.
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)
21
24
  def distinct(options = {})
22
25
  if @params[:negate]
23
26
  # The best we could implement it as from here would be a bunch of
@@ -29,39 +32,26 @@ module Gecode::Constraints::IntEnum
29
32
  raise ArgumentError, 'Reification is not supported by the distinct ' +
30
33
  'constraint.'
31
34
  end
32
-
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
33
44
  @model.add_constraint Distinct::DistinctConstraint.new(@model,
34
- @params.update(Gecode::Constraints::Util.decode_options(options)))
45
+ @params.update(Gecode::Util.decode_options(options)))
35
46
  end
36
47
  end
37
48
 
38
49
  # A module that gathers the classes and modules used in distinct constraints.
39
50
  module Distinct #:nodoc:
40
- # Describes a distinct constraint, which constrains all integer variables
41
- # in an enumeration to be distinct (different). The constraint can also be
42
- # used with constant offsets, so that the variables, with specified offsets
43
- # added, must be distinct.
44
- #
45
- # The constraint does not support negation nor reification.
46
- #
47
- # == Examples
48
- #
49
- # # Constrains all variables in +int_enum+ to be assigned different
50
- # # values.
51
- # int_enum.must_be.distinct
52
- #
53
- # # The same as above, but also selects that the strength +domain+ should
54
- # # be used.
55
- # int_enum.must_be.distinct(:strength => :domain)
56
- #
57
- # # Uses the offset to constrain that no number may be the previous number
58
- # # incremented by one.
59
- # numbers = int_var_array(8, 0..9)
60
- # numbers.with_offset((1..numbers.size).to_a.reverse).must_be.distinct
61
- class DistinctConstraint < Gecode::Constraints::Constraint
51
+ class DistinctConstraint < Gecode::Constraint #:nodoc:
62
52
  def post
63
53
  # Bind lhs.
64
- @params[:lhs] = @params[:lhs].to_int_var_array
54
+ @params[:lhs] = @params[:lhs].to_int_enum.bind_array
65
55
 
66
56
  # Fetch the parameters to Gecode.
67
57
  params = @params.values_at(:offsets, :lhs)
@@ -71,4 +61,4 @@ module Gecode::Constraints::IntEnum
71
61
  end
72
62
  end
73
63
  end
74
- end
64
+ end
@@ -1,65 +1,34 @@
1
- # A module that gathers the classes and modules used by element constraints.
2
- module Gecode::Constraints::IntEnum::Element #:nodoc:
3
- # Describes a CompositeStub for the element constraint, which places a
4
- # constraint on a variable at the specified position in an enumeration of
5
- # integer variables. It's basically the array access of constraint
6
- # programming.
7
- #
8
- # == Example
9
- #
10
- # # The variable at the +x+:th position in +int_enum+ must be larger than
11
- # # +y+.
12
- # int_enum[x].must > y
13
- #
14
- # # The price of +selected_item+ as described by +prices+ must not be
15
- # # larger than 100.
16
- # prices = wrap_enum([500, 24, 4711, 412, 24])
17
- # prices[selected_item].must_not > 100
18
- #
19
- # # Reify the constraint that the +x+:th variable in +int_enum+ must be in
20
- # # range 7..17 with the boolean variable +bool+ and select strength
21
- # # +domain+.
22
- #
23
- # int_enum[x].must_be.in(7..17, :reify => bool, :strength => :domain)
24
- class ExpressionStub < Gecode::Constraints::Int::CompositeStub
25
- def constrain_equal(variable, params, constrain)
26
- enum, position = @params.values_at(:lhs, :position)
27
- if constrain
28
- variable.must_be.in enum.domain_range
29
- end
30
-
31
- # The enum can be a constant array.
32
- enum = enum.to_int_var_array if enum.respond_to? :to_int_var_array
33
- Gecode::Raw::element(@model.active_space, enum,
34
- position.bind, variable.bind, *propagation_options)
35
- end
36
- end
37
-
38
- # Methods needed to add support for element constraints to enums.
39
- module AdditionalEnumMethods #:nodoc:
1
+ module Gecode::IntEnum
2
+ module IntEnumOperand
40
3
  # This adds the adder for the methods in the modules including it. The
41
4
  # reason for doing it so indirect is that the first #[] won't be defined
42
5
  # before the module that this is mixed into is mixed into an enum.
43
- def self.included(enum_mod)
6
+ def self.included(enum_mod) #:nodoc:
44
7
  enum_mod.module_eval do
45
- # Now we enter the module AdditionalEnumMethods is mixed into.
8
+ # Now we enter the module IntEnumOperands is mixed into.
46
9
  class << self
47
10
  alias_method :pre_element_included, :included
48
- def included(mod)
11
+ def included(mod) #:nodoc:
49
12
  mod.module_eval do
50
- # Now we enter the module that the module possibly defining #[]
51
- # is mixed into.
52
13
  if instance_methods.include? '[]'
53
14
  alias_method :pre_element_access, :[]
54
15
  end
55
-
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
+ #
56
28
  def [](*vars)
57
- # Hook in an element constraint if a variable is used for array
58
- # access.
59
- if vars.first.kind_of? Gecode::FreeIntVar
60
- params = {:lhs => self, :position => vars.first}
61
- return Gecode::Constraints::IntEnum::Element::ExpressionStub.new(
62
- @model, params)
29
+ if vars.first.respond_to? :to_int_var
30
+ return Element::ElementIntOperand.new(
31
+ model, self, vars.first)
63
32
  else
64
33
  pre_element_access(*vars) if respond_to? :pre_element_access
65
34
  end
@@ -71,12 +40,25 @@ module Gecode::Constraints::IntEnum::Element #:nodoc:
71
40
  end
72
41
  end
73
42
  end
74
- end
75
43
 
76
- module Gecode::IntEnumMethods
77
- include Gecode::Constraints::IntEnum::Element::AdditionalEnumMethods
78
- end
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
79
51
 
80
- module Gecode::FixnumEnumMethods
81
- include Gecode::Constraints::IntEnum::Element::AdditionalEnumMethods
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
82
64
  end
@@ -1,6 +1,12 @@
1
- module Gecode::Constraints::IntEnum
2
- class Expression
3
- # Posts an equality constraint on the variables in the enum.
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
4
10
  def equal(options = {})
5
11
  if @params[:negate]
6
12
  # The best we could implement it as from here would be a bunch of
@@ -14,28 +20,18 @@ module Gecode::Constraints::IntEnum
14
20
  end
15
21
 
16
22
  @model.add_constraint Equality::EqualityConstraint.new(@model,
17
- @params.update(Gecode::Constraints::Util.decode_options(options)))
23
+ @params.update(Gecode::Util.decode_options(options)))
18
24
  end
19
25
  end
20
26
 
21
27
  # A module that gathers the classes and modules used in equality constraints.
22
28
  module Equality #:nodoc:
23
- # Describes an equality constraint, which constrains all variables in an
24
- # integer enumeration to be equal. Neither negation nor reification is
25
- # supported.
26
- #
27
- # == Example
28
- #
29
- # # Constrains all variables in +int_enum+ to be equal.
30
- # int_enum.must_be.equal
31
- class EqualityConstraint < Gecode::Constraints::Constraint
29
+ class EqualityConstraint < Gecode::Constraint #:nodoc:
32
30
  def post
33
- # Bind lhs.
34
- lhs = @params[:lhs].to_int_var_array
35
-
36
- # Fetch the parameters to Gecode.
37
- Gecode::Raw::eq(@model.active_space, lhs, *propagation_options)
31
+ Gecode::Raw::rel(@model.active_space,
32
+ @params[:lhs].to_int_enum.bind_array,
33
+ Gecode::Raw::IRT_EQ, *propagation_options)
38
34
  end
39
35
  end
40
36
  end
41
- end
37
+ end
@@ -1,7 +1,17 @@
1
- module Gecode::Constraints::IntEnum
2
- class Expression
3
- # Posts a tuple constraint on the variables in the enum, constraining them
4
- # to equal one of the specified tuples.
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)
5
15
  def in(tuples, options = {})
6
16
  if @params[:negate]
7
17
  raise Gecode::MissingConstraintError, 'A negated tuple constraint is ' +
@@ -12,7 +22,7 @@ module Gecode::Constraints::IntEnum
12
22
  'constraint.'
13
23
  end
14
24
 
15
- util = Gecode::Constraints::Util
25
+ util = Gecode::Util
16
26
 
17
27
  # Check that the tuples are correct.
18
28
  expected_size = @params[:lhs].size
@@ -27,64 +37,9 @@ module Gecode::Constraints::IntEnum
27
37
  @params.update(util.decode_options(options)))
28
38
  end
29
39
 
30
- # Adds a constraint that forces the enumeration to match the
31
- # specified regular expression over the integer domain. The regular
32
- # expression is expressed using arrays and integers. See
33
- # IntEnum::Extensional::RegexpConstraint for more information and examples of
34
- # such regexps.
35
- def match(regexp, options = {})
36
- if @params[:negate]
37
- raise Gecode::MissingConstraintError, 'A negated regexp constraint ' +
38
- 'is not implemented.'
39
- end
40
- unless options[:reify].nil?
41
- raise ArgumentError, 'Reification is not supported by the regexp ' +
42
- 'constraint.'
43
- end
44
-
45
- @params[:regexp] =
46
- Gecode::Constraints::Util::Extensional.parse_regexp regexp
47
- @params.update Gecode::Constraints::Util.decode_options(options)
48
- @model.add_constraint Extensional::RegexpConstraint.new(@model, @params)
49
- end
50
- end
51
-
52
- # A module that gathers the classes and modules used in extensional
53
- # constraints.
54
- module Extensional #:nodoc:
55
- # Describes a tuple constraint, which constrains all the variables in an
56
- # enumeration of integer variables to be equal to one of the specified
57
- # tuples. Neither negation nor reification is supported.
58
- #
59
- # == Example
60
- #
61
- # # Constrains the two integer variables in +numbers+ to either have
62
- # # values 1 and 7, or values 47 and 11.
63
- # numbers.must_be.in [[1,7], [47,11]]
64
- #
65
- # # The same as above, but preferring speed over low memory usage.
66
- # numbers.must_be.in([[1,7], [47,11]], :kind => :speed)
67
- class TupleConstraint < Gecode::Constraints::Constraint
68
- def post
69
- # Bind lhs.
70
- lhs = @params[:lhs].to_int_var_array
71
-
72
- # Create the tuple set.
73
- tuple_set = Gecode::Raw::TupleSet.new
74
- @params[:tuples].each do |tuple|
75
- tuple_set.add tuple
76
- end
77
- tuple_set.finalize
78
-
79
- # Post the constraint.
80
- Gecode::Raw::extensional(@model.active_space, lhs, tuple_set,
81
- *propagation_options)
82
- end
83
- end
84
-
85
- # Describes a regexp constraint, which constrains the enumeration of
86
- # integer variables to match a specified regexp in the integer
87
- # domain. Neither negation nor reification is supported.
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.
88
43
  #
89
44
  # == Regexp syntax
90
45
  #
@@ -114,7 +69,7 @@ module Gecode::Constraints::IntEnum
114
69
  # Additionally Model#at_least_once and Model#at_most_once are
115
70
  # provided as convenience methods.
116
71
  #
117
- # === Examples
72
+ # ==== Examples
118
73
  #
119
74
  # # Matches 1 followed by any number of 2s.
120
75
  # [1, repeat(2)]
@@ -166,28 +121,66 @@ module Gecode::Constraints::IntEnum
166
121
  # # Exactly the same as the above.
167
122
  # [0, repeat(1, 0, 1)]
168
123
  #
169
- # == Example
124
+ # ==== Examples
170
125
  #
171
- # # Constrains the two integer variables in +numbers+ to have
126
+ # # Constrains the two integer operands in +numbers+ to have
172
127
  # # values 1 and 7.
173
128
  # numbers.must.match [1, 7]
174
129
  #
175
- # # Constrains the integer variables in +numbers+ to contain the
130
+ # # Constrains the integer operands in +numbers+ to contain the
176
131
  # # value 47 followed by 11, with all other values set to -1.
177
132
  # numbers.must.match [repeat(-1), 47, 11, repeat(-1)]
178
133
  #
179
- # # Constrains exactly three of the integer variables in +numbers+ to
134
+ # # Constrains exactly three of the integer operands in +numbers+ to
180
135
  # # contain 47 or 11, each followed by at least two
181
- # # variables set to -1. All other variables are constrained to
136
+ # # operands set to -1. All other operands are constrained to
182
137
  # # equal -1.
183
138
  # numbers.must.match repeat([repeat(-1), any(11, 47),
184
139
  # repeat(-1, 2)], 3, 3)
185
140
  #
186
- class RegexpConstraint < Gecode::Constraints::Constraint
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:
187
180
  def post
188
181
  lhs, regexp = @params.values_at(:lhs, :regexp)
189
- Gecode::Raw::extensional(@model.active_space, lhs.to_int_var_array,
190
- regexp, *propagation_options)
182
+ Gecode::Raw::extensional(@model.active_space,
183
+ lhs.to_int_enum.bind_array, regexp, *propagation_options)
191
184
  end
192
185
  end
193
186
  end