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
@@ -0,0 +1,79 @@
1
+ module Gecode::SetEnum
2
+ module SetEnumOperand
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(mod) #:nodoc:
7
+ mod.module_eval do
8
+ # Now we enter the module SetEnumOperands is mixed into.
9
+ class << self
10
+ alias_method :pre_selection_included, :included
11
+ def included(mod) #:nodoc:
12
+ mod.module_eval do
13
+ # Now we enter the module that the module possibly defining #[]
14
+ # is mixed into.
15
+ if instance_methods.include?('[]') and
16
+ not instance_methods.include?('pre_selection_access')
17
+ alias_method :pre_selection_access, :[]
18
+ end
19
+
20
+ # Produces a SetOperand representing the i:th set
21
+ # operand in the enumeration, where i is the value of the
22
+ # int operand used as index.
23
+ #
24
+ # A set can also be used as index, in which case a
25
+ # SelectedSetOperand is produced.
26
+ #
27
+ # ==== Examples
28
+ #
29
+ # # The set operand at the +x+:th position in +set_enum+,
30
+ # # where +x+ is a int operand.
31
+ # set_enum[x]
32
+ #
33
+ # # The SelectedSetOperand representing sets at positions
34
+ # # included in the value of +set+ in +set_enum+,
35
+ # set_enum[set]
36
+ #
37
+ def [](*vars)
38
+ # Hook in an element constraint if a operand is used for array
39
+ # access.
40
+ if vars.first.respond_to? :to_int_var
41
+ Select::SelectSetOperand.new(
42
+ model, self, vars.first)
43
+ elsif vars.first.respond_to? :to_set_var
44
+ Gecode::SelectedSet::SelectedSetOperand.new(
45
+ self, vars.first)
46
+ else
47
+ if respond_to? :pre_selection_access
48
+ pre_selection_access(*vars)
49
+ end
50
+ end
51
+ end
52
+ end
53
+ pre_selection_included(mod)
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
59
+
60
+ module Select #:nodoc:
61
+ class SelectSetOperand < Gecode::Set::ShortCircuitEqualityOperand #:nodoc:
62
+ def initialize(model, enum_op, position_int_op)
63
+ super model
64
+ @enum = enum_op
65
+ @position = position_int_op
66
+ end
67
+
68
+ def constrain_equal(set_operand, constrain, propagation_options)
69
+ enum = @enum.to_set_enum
70
+ if constrain
71
+ set_operand.must_be.subset_of enum.upper_bound_range
72
+ end
73
+
74
+ Gecode::Raw::selectSet(@model.active_space, enum.bind_array,
75
+ @position.to_int_var.bind, set_operand.to_set_var.bind)
76
+ end
77
+ end
78
+ end
79
+ end
@@ -1,28 +1,78 @@
1
- module Gecode
2
- module SetEnumMethods
3
- include Gecode::Constraints::LeftHandSideMethods
4
-
1
+ # A module containing constraints that have enumerations of set operands as
2
+ # left hand side.
3
+ module Gecode::SetEnum #:nodoc:
4
+ # A SetEnumOperand is a enumeration of SetOperand on which the
5
+ # constraints defined in SetEnumConstraintReceiver can be placed.
6
+ #
7
+ # Enumerations of set operands can be created either by using
8
+ # Gecode::Model#set_var_array and Gecode::Model#set_var_matrix, or
9
+ # by wrapping an existing enumeration containing SetOperand using
10
+ # Gecode::Model#wrap_enum. The enumerations, no matter how they were
11
+ # created, all respond to the properties defined by SetEnumOperand.
12
+ #
13
+ # ==== Examples
14
+ #
15
+ # Produces an array of five set operands, with greatest lower bound
16
+ # {0} and least upper bound {0, 1, 2}, inside a problem formulation
17
+ # using Gecode::Model#set_var_array:
18
+ #
19
+ # set_enum = set_var_array(5, 0, 1..2)
20
+ #
21
+ # Uses Gecode::Model#wrap_enum inside a problem formulation to create
22
+ # a SetEnumOperand from an existing enumeration containing the
23
+ # set operands +set_operand1+ and +set_operand2+:
24
+ #
25
+ # set_enum = wrap_enum([set_operand1, set_operand2])
26
+ #
27
+ #--
28
+ # Classes that mix in SetEnumOperand must define #model and
29
+ # #to_set_enum .
30
+ module SetEnumOperand
31
+ include Gecode::Operand
32
+
33
+ def method_missing(method, *args) #:nodoc:
34
+ if Gecode::SetEnum::Dummy.instance_methods.include? method.to_s
35
+ # Delegate to the set enum.
36
+ to_set_enum.method(method).call(*args)
37
+ else
38
+ super
39
+ end
40
+ end
41
+
5
42
  private
6
-
7
- # Produces an expression for the lhs module.
8
- def expression(params)
9
- params.update(:lhs => self)
10
- Constraints::SetEnum::Expression.new(@model, params)
43
+
44
+ def construct_receiver(params)
45
+ Gecode::SetEnum::SetEnumConstraintReceiver.new(@model, params)
11
46
  end
12
47
  end
13
-
14
- # A module containing constraints that have enumerations of set variables as
15
- # left hand side.
16
- module Constraints::SetEnum
17
- # Expressions with set enums as left hand sides.
18
- class Expression < Gecode::Constraints::Expression
19
- # Raises TypeError unless the left hand side is a set enum.
20
- def initialize(model, params)
21
- super
22
-
23
- unless params[:lhs].respond_to? :to_set_var_array
24
- raise TypeError, 'Must have set enum as left hand side.'
25
- end
48
+
49
+ # SetEnumConstraintReceiver contains all constraints that can be
50
+ # placed on a SetEnumOperand.
51
+ #
52
+ # Constraints are placed by calling SetEnumOperand#must (or any other
53
+ # of the variations defined in Operand), which produces a
54
+ # SetEnumConstraintReceiver from which the desired constraint can be used.
55
+ #
56
+ # ==== Examples
57
+ #
58
+ # Constrains +set_enum+ to channel +int_enum+ by using
59
+ # SetEnumConstraintReceiver#channel:
60
+ #
61
+ # set_enum.must.channel set_enum
62
+ #
63
+ # Constrains each pair of set operands in +set_enum+ to at most share
64
+ # one element. Also constrains each set to have size 17. Uses
65
+ # SetEnumConstraintReceiver#at_most_share_one_element.
66
+ #
67
+ # set_enum.must.at_most_share_one_element(:size => 17)
68
+ #
69
+ class SetEnumConstraintReceiver < Gecode::ConstraintReceiver
70
+ # Raises TypeError unless the left hand side is a set enum operand.
71
+ def initialize(model, params) #:nodoc:
72
+ super
73
+
74
+ unless params[:lhs].respond_to? :to_set_enum
75
+ raise TypeError, 'Must have set enum operand as left hand side.'
26
76
  end
27
77
  end
28
78
  end
@@ -30,5 +80,5 @@ end
30
80
 
31
81
  require 'gecoder/interface/constraints/set_enum/channel'
32
82
  require 'gecoder/interface/constraints/set_enum/distinct'
33
- require 'gecoder/interface/constraints/set_enum/selection'
83
+ require 'gecoder/interface/constraints/set_enum/select'
34
84
  require 'gecoder/interface/constraints/set_enum/operation'
@@ -1,71 +1,235 @@
1
- module Gecode
2
- class FreeSetVar
3
- include Gecode::Constraints::LeftHandSideMethods
4
-
1
+ # A module containing constraints that have set operands as left hand side
2
+ # (but not enumerations).
3
+ module Gecode::Set #:nodoc:
4
+ # A SetOperand is a combination of operands on which the
5
+ # constraints defined in SetConstraintReceiver can be placed.
6
+ #
7
+ # Set operands can be created either by using Gecode::Model#set_var et
8
+ # al, or by using properties that produce set operands. The operands,
9
+ # no matter how they were created, all respond to the properties
10
+ # defined by SetOperand.
11
+ #
12
+ # ==== Examples
13
+ #
14
+ # Produces a single set operand (more specifically a SetVar), with
15
+ # greatest lower bound {0} and least upper bound {0, 1, 2}, inside a
16
+ # problem formulation, using Gecode::Model#set_var:
17
+ #
18
+ # set_operand = set_var(0, 0..2)
19
+ #
20
+ # Uses the SetOperand#union property to produce a new set operand
21
+ # representing the union between +set_operand1+ and +set_operand2+:
22
+ #
23
+ # new_set_operand = set_operand1.union(set_operand2)
24
+ #
25
+ # Uses the SetEnumOperand#union property to produce a new set operand
26
+ # representing the union of the set operands in the enumeration
27
+ # +set_enum+:
28
+ #
29
+ # new_set_operand = set_enum.union
30
+ #
31
+ # Uses the SetEnumOperand#[] property to produce a new set operand
32
+ # representing the set operand at the index decided by
33
+ # +int_operand+ (which can change during search) in the enumeration
34
+ # +set_enum+:
35
+ #
36
+ # new_set_operand = set_enum[int_operand]
37
+ #
38
+ #--
39
+ # Classes that mix in SetOperand must define #model and #to_set_var .
40
+ module SetOperand
41
+ include Gecode::Operand
42
+
43
+ def method_missing(method, *args) #:nodoc:
44
+ if Gecode::SetVar.instance_methods.include? method.to_s
45
+ # Delegate to the set var.
46
+ to_set_var.method(method).call(*args)
47
+ else
48
+ super
49
+ end
50
+ end
51
+
5
52
  private
6
-
7
- # Produces an expression for the lhs module.
8
- def expression(params)
9
- params.update(:lhs => self)
10
- Constraints::Set::Expression.new(@model, params)
53
+
54
+ def construct_receiver(params)
55
+ SetConstraintReceiver.new(model, params)
11
56
  end
12
57
  end
13
-
14
- # A module containing constraints that have set variables as left hand side
15
- # (but not enumerations).
16
- module Constraints::Set
17
- # An expression with a set as left hand side.
18
- class Expression < Gecode::Constraints::Expression #:nodoc:
58
+
59
+ # An operand that short circuits set equality.
60
+ class ShortCircuitEqualityOperand #:nodoc:
61
+ include Gecode::Set::SetOperand
62
+ attr :model
63
+
64
+ def initialize(model)
65
+ @model = model
19
66
  end
20
-
21
- # Utility methods for sets.
22
- module Util #:nodoc:
23
- module_function
24
- def decode_options(options)
25
- if options.has_key? :strength
26
- raise ArgumentError, 'Set constraints do not support the strength ' +
27
- 'option.'
67
+
68
+ def construct_receiver(params)
69
+ params.update(:lhs => self)
70
+ receiver = SetConstraintReceiver.new(@model, params)
71
+ op = self
72
+ receiver.instance_eval{ @short_circuit = op }
73
+ class <<receiver
74
+ alias_method :equality_without_short_circuit, :==
75
+ def ==(operand, options = {})
76
+ if !@params[:negate] and !options.has_key?(:reify) and
77
+ operand.respond_to? :to_set_var
78
+ # Short circuit the constraint.
79
+ @params.update Gecode::Util.decode_options(options)
80
+ @model.add_constraint(Gecode::BlockConstraint.new(
81
+ @model, @params) do
82
+ @short_circuit.constrain_equal(operand, false,
83
+ @params.values_at(:strength, :kind))
84
+ end)
85
+ else
86
+ equality_without_short_circuit(operand, options)
87
+ end
28
88
  end
29
- if options.has_key? :kind
30
- raise ArgumentError, 'Set constraints do not support the kind ' +
31
- 'option.'
89
+ alias_comparison_methods
90
+ end
91
+
92
+ return receiver
93
+ end
94
+
95
+ def to_set_var
96
+ variable = model.set_var
97
+ options =
98
+ Gecode::Set::Util.decode_options(
99
+ {}).values_at(:strength, :kind)
100
+ model.add_interaction do
101
+ constrain_equal(variable, true, options)
102
+ end
103
+ return variable
104
+ end
105
+
106
+ private
107
+
108
+ # Constrains this operand to equal +set_operand+ using the
109
+ # specified +propagation_options+. If +constrain_domain+ is true
110
+ # then the method should also attempt to constrain the bounds of the
111
+ # domain of +set_operand+.
112
+ def constrain_equal(set_operand, constrain_domain, propagation_options)
113
+ raise NotImplementedError, 'Abstract method has not been implemented.'
114
+ end
115
+ end
116
+
117
+ # An operand that short circuits set non-negated and non-reified versions
118
+ # of the relation constraints.
119
+ class ShortCircuitRelationsOperand #:nodoc:
120
+ include Gecode::Set::SetOperand
121
+ attr :model
122
+
123
+ def initialize(model)
124
+ @model = model
125
+ end
126
+
127
+ def construct_receiver(params)
128
+ params.update(:lhs => self)
129
+ receiver = SetConstraintReceiver.new(@model, params)
130
+ op = self
131
+ receiver.instance_eval{ @short_circuit = op }
132
+ class <<receiver
133
+ Gecode::Util::SET_RELATION_TYPES.keys.each do |comp|
134
+ eval <<-end_code
135
+ alias_method :alias_#{comp.to_i}_without_short_circuit, :#{comp}
136
+ def #{comp}(operand, options = {})
137
+ if !@params[:negate] && !options.has_key?(:reify) &&
138
+ (operand.respond_to?(:to_set_var) or
139
+ Gecode::Util::constant_set?(operand))
140
+ # Short circuit the constraint.
141
+ @params.update Gecode::Set::Util.decode_options(options)
142
+ @model.add_constraint(
143
+ @short_circuit.relation_constraint(
144
+ :#{comp}, operand, @params))
145
+ else
146
+ alias_#{comp.to_i}_without_short_circuit(operand, options)
147
+ end
148
+ end
149
+ end_code
32
150
  end
33
-
34
- Gecode::Constraints::Util.decode_options(options)
151
+ alias_comparison_methods
35
152
  end
153
+
154
+ return receiver
155
+ end
156
+
157
+ def to_set_var
158
+ variable = model.set_var
159
+ params = {:lhs => self}
160
+ params.update Gecode::Set::Util.decode_options({})
161
+ model.add_constraint relation_constraint(:==, variable, params)
162
+ return variable
163
+ end
164
+
165
+ # Returns a constraint that constrains this operand to have relation
166
+ # +relation+ to +set_operand_or_constant_set+, which is either a set
167
+ # operand or a constant set, given the specified hash +params+ of
168
+ # parameters. The constraints are never negated nor reified.
169
+ def relation_constraint(relation, set_operand_or_constant_set, params)
170
+ raise NotImplementedError, 'Abstract method has not been implemented.'
36
171
  end
37
-
38
- # A composite expression which is an set expression with a left hand side
39
- # resulting from a previous constraint.
40
- class CompositeExpression < Gecode::Constraints::CompositeExpression #:nodoc:
41
- # The block given should take three parameters. The first is the variable
42
- # that should be the left hand side, if it's nil then a new one should be
43
- # created. The second is the has of parameters. The block should return
44
- # the variable used as left hand side.
45
- def initialize(model, params, &block)
46
- super(Expression, Gecode::FreeSetVar, lambda{ model.set_var }, model,
47
- params, &block)
172
+ end
173
+
174
+ # SetConstraintReceiver contains all constraints that can be
175
+ # placed on a SetOperand.
176
+ #
177
+ # Constraints are placed by calling SetOperand#must (or any other
178
+ # of the variations defined in Operand), which produces a
179
+ # SetConstraintReceiver from which the desired constraint can be used.
180
+ #
181
+ # Most constraint accept :reify option. See ConstraintReceiver for
182
+ # more information.
183
+ #
184
+ # ==== Examples
185
+ #
186
+ # Constrains +set_operand+ to be a subset of {0, 1, 2} using
187
+ # an alias of SetConstraintReceiver#subset:
188
+ #
189
+ # set_operand.must_be.subset_of 0..2
190
+ #
191
+ # Constrains the union of +set_operand1+ and +set_operand2+ to a
192
+ # subset of {0, 1, 2} using the SetOperand#union property and
193
+ # SetConstraintReceiver#subset:
194
+ #
195
+ # set_operand1.union(set_operand2).must_be.subset_of 0..2
196
+ #
197
+ # Constrains the union of the set operands in +set_enum+ to _not_
198
+ # equal {0, 1, 2} by using the SetEnumOperand#union property and
199
+ # an alias of SetConstraintReceiver#==:
200
+ #
201
+ # set_enum.union.must_not == 0..2
202
+ #
203
+ # The same as above, but alsa specifying that the constraint should be
204
+ # reified with +bool_operand+:
205
+ #
206
+ # set_enum.union.must_not.equal(0..2, :reify => bool_operand)
207
+ #
208
+ class SetConstraintReceiver < Gecode::ConstraintReceiver
209
+ # Raises TypeError unless the left hand side is a set operand.
210
+ def initialize(model, params) #:nodoc:
211
+ super
212
+
213
+ unless params[:lhs].respond_to? :to_set_var
214
+ raise TypeError, 'Must have set operand as left hand side.'
48
215
  end
49
216
  end
50
-
51
- # Describes a stub that produces a set variable, which can then be used with
52
- # the normal set variable constraints. An example of a set composite
53
- # constraints would be set selection constraint.
54
- #
55
- # sets[int_var].must_be.subset_of(another_set)
56
- #
57
- # <tt>sets[int_var]</tt> produces a set variable which the constraint
58
- # <tt>.must_be.subset_of(another_set)</tt> is then applied to.In the above
59
- # case two constraints (and one temporary variable) are required, but in the
60
- # case of equality only one constraint is required.
61
- #
62
- # Whether a constraint involving a reification stub supports negation and
63
- # reification depends on the constraint on the right hand side (none
64
- # support the strength option as no set constraints do).
65
- class CompositeStub < Gecode::Constraints::CompositeStub
66
- def initialize(model, params)
67
- super(CompositeExpression, model, params)
217
+ end
218
+
219
+ # Utility methods for sets.
220
+ module Util #:nodoc:
221
+ module_function
222
+ def decode_options(options)
223
+ if options.has_key? :strength
224
+ raise ArgumentError, 'Set constraints do not support the strength ' +
225
+ 'option.'
226
+ end
227
+ if options.has_key? :kind
228
+ raise ArgumentError, 'Set constraints do not support the kind ' +
229
+ 'option.'
68
230
  end
231
+
232
+ Gecode::Util.decode_options(options)
69
233
  end
70
234
  end
71
235
  end
@@ -74,5 +238,6 @@ require 'gecoder/interface/constraints/set/domain'
74
238
  require 'gecoder/interface/constraints/set/relation'
75
239
  require 'gecoder/interface/constraints/set/cardinality'
76
240
  require 'gecoder/interface/constraints/set/connection'
241
+ require 'gecoder/interface/constraints/set/include'
77
242
  require 'gecoder/interface/constraints/set/operation'
78
243
  require 'gecoder/interface/constraints/set/channel'