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,36 @@
1
+ module Gecode::Set
2
+ class SetConstraintReceiver
3
+ # Constrains this set to include the values of +int_enum+.
4
+ #
5
+ # The constraint has the side effect of sorting the integer operands in a
6
+ # non-descending order. It does not support reification nor negation.
7
+ #
8
+ # ==== Examples
9
+ #
10
+ # # Constrain +set+ to include the values of all operands in
11
+ # # +int_enum+.
12
+ # set.must.include int_enum
13
+ def include(int_enum)
14
+ unless int_enum.respond_to? :to_int_enum
15
+ raise TypeError, "Expected int var enum, got #{int_enum.class}."
16
+ end
17
+ if @params[:negate]
18
+ raise Gecode::MissingConstraintError, 'A negated include is not ' +
19
+ 'implemented.'
20
+ end
21
+
22
+ @params.update(:variables => int_enum)
23
+ @model.add_constraint Connection::IncludeConstraint.new(@model, @params)
24
+ end
25
+ end
26
+
27
+ module Connection #:nodoc:
28
+ class IncludeConstraint < Gecode::Constraint #:nodoc:
29
+ def post
30
+ set, variables = @params.values_at(:lhs, :variables)
31
+ Gecode::Raw::match(@model.active_space, set.to_set_var.bind,
32
+ variables.to_int_enum.bind_array)
33
+ end
34
+ end
35
+ end
36
+ end
@@ -1,132 +1,118 @@
1
- module Gecode
2
- class FreeSetVar
3
- Gecode::Constraints::Util::SET_OPERATION_TYPES.each_pair do |name, type|
4
- module_eval <<-"end_code"
5
- # Starts a constraint on this set #{name} the specified set.
6
- def #{name}(operand)
7
- unless operand.kind_of?(Gecode::FreeSetVar) or
8
- Gecode::Constraints::Util::constant_set?(operand)
9
- raise TypeError, 'Expected set variable or constant set as ' +
10
- "operand, got \#{operand.class}."
11
- end
1
+ module Gecode::Set
2
+ module SetOperand
3
+ # Produces a new SetOperand representing the union between this operand
4
+ # and +set_operand_or_constant_set+.
5
+ #
6
+ # ==== Examples
7
+ #
8
+ # # The union between +set1+ and +set2+.
9
+ # set1.union set2
10
+ #
11
+ # # The union between +set+ and {1, 3, 5}.
12
+ # set.union [1,3,5]
13
+ def union(set_operand_or_constant_set)
14
+ set_operation(:union, set_operand_or_constant_set)
15
+ end
12
16
 
13
- params = {:lhs => self, :op2 => operand, :operation => #{type}}
14
- Gecode::Constraints::SimpleExpressionStub.new(@model, params) do |m, ps|
15
- Gecode::Constraints::Set::Operation::Expression.new(m, ps)
16
- end
17
- end
18
- end_code
17
+ # Produces a new SetOperand representing the disjoint union between
18
+ # this operand and +set_operand_or_constant_set+. The disjoint union
19
+ # is the union of the disjoint parts of the sets.
20
+ #
21
+ # ==== Examples
22
+ #
23
+ # # The disjoint union between +set1+ and +set2+.
24
+ # set1.disjoint_union set2
25
+ #
26
+ # # The disjoint union between +set+ and {1, 3, 5}.
27
+ # set.disjoint_union [1,3,5]
28
+ def disjoint_union(set_operand_or_constant_set)
29
+ set_operation(:disjoint_union, set_operand_or_constant_set)
19
30
  end
20
- end
21
-
22
- module FixnumEnumMethods
23
- Gecode::Constraints::Util::SET_OPERATION_TYPES.each_pair do |name, type|
24
- module_eval <<-"end_code"
25
- # Starts a constraint on this set union the specified set.
26
- def #{name}(operand)
27
- unless operand.kind_of?(Gecode::FreeSetVar) or
28
- Gecode::Constraints::Util::constant_set?(operand)
29
- raise TypeError, 'Expected set variable or constant set as ' +
30
- "operand, got \#{operand.class}."
31
- end
32
31
 
33
- params = {:lhs => self, :op2 => operand, :operation => #{type}}
34
- Gecode::Constraints::SimpleExpressionStub.new(@model, params) do |m, ps|
35
- Gecode::Constraints::Set::Operation::Expression.new(m, ps)
36
- end
37
- end
38
- end_code
32
+ # Produces a new SetOperand representing the intersection between
33
+ # this operand and +set_operand_or_constant_set+.
34
+ #
35
+ # ==== Examples
36
+ #
37
+ # # The intersection between +set1+ and +set2+.
38
+ # set1.intersection set2
39
+ #
40
+ # # The intersection between +set+ and {1, 3, 5}.
41
+ # set.intersection [1,3,5]
42
+ def intersection(set_operand_or_constant_set)
43
+ set_operation(:intersection, set_operand_or_constant_set)
44
+ end
45
+
46
+ # Produces a new SetOperand representing this operand minus
47
+ # +set_operand_or_constant_set+.
48
+ #
49
+ # ==== Examples
50
+ #
51
+ # # +set1+ minus +set2+.
52
+ # set1.minus set2
53
+ #
54
+ # # +set+ minus {1, 3, 5}.
55
+ # set.minus [1,3,5]
56
+ def minus(set_operand_or_constant_set)
57
+ set_operation(:minus, set_operand_or_constant_set)
58
+ end
59
+
60
+ private
61
+
62
+ # Produces the SetOperand resulting from +operator+ applied to this
63
+ # operand and +operand2+.
64
+ def set_operation(operator, operand2)
65
+ unless operand2.respond_to? :to_set_var or
66
+ Gecode::Util::constant_set?(operand2)
67
+ raise TypeError, 'Expected set operand or constant set as ' +
68
+ "operand, got \#{operand2.class}."
69
+ end
70
+
71
+ return Operation::OperationSetOperand.new(model, self, operator,
72
+ operand2)
39
73
  end
40
74
  end
41
- end
42
75
 
43
- module Gecode::Constraints::Set
44
76
  # A module that gathers the classes and modules used in operation constraints.
45
77
  module Operation #:nodoc:
46
- # An expression with a set operand and two operands followed by must.
47
- class Expression < Gecode::Constraints::Expression #:nodoc:
48
- Gecode::Constraints::Util::SET_RELATION_TYPES.each_pair do |name, type|
49
- module_eval <<-"end_code"
50
- # Creates an operation constraint using the specified expression.
51
- def #{name}(expression)
52
- if @params[:negate]
53
- # We do not allow negation.
54
- raise Gecode::MissingConstraintError, 'A negated set operation ' +
55
- 'constraint is not implemented.'
56
- end
57
- unless expression.kind_of?(Gecode::FreeSetVar) or
58
- Gecode::Constraints::Util::constant_set?(expression)
59
- raise TypeError, 'Expected set variable or constant set, got ' +
60
- "\#{expression.class}."
61
- end
62
-
63
- @params[:rhs] = expression
64
- @params[:relation] = #{type}
65
- unless @params.values_at(:lhs, :op2, :rhs).any?{ |element|
66
- element.kind_of? Gecode::FreeSetVar}
67
- # At least one variable must be involved in the constraint.
68
- raise ArgumentError, 'At least one variable must be involved ' +
69
- 'in the constraint, but all given were constants.'
70
- end
71
-
72
- @model.add_constraint OperationConstraint.new(@model, @params)
73
- end
74
- end_code
78
+ class OperationSetOperand < Gecode::Set::ShortCircuitRelationsOperand #:nodoc:
79
+ def initialize(model, op1, operator, op2)
80
+ super model
81
+ @op1 = op1
82
+ @op2 = op2
83
+ @operator = operator
84
+ end
85
+
86
+ def relation_constraint(relation, set_operand_or_constant_set, params)
87
+ relation_type =
88
+ Gecode::Util::SET_RELATION_TYPES[relation]
89
+
90
+ operation = Gecode::Util::SET_OPERATION_TYPES[@operator]
91
+ params.update(:rhs => set_operand_or_constant_set,
92
+ :relation_type => relation_type, :op1 => @op1, :op2 => @op2,
93
+ :operation => operation)
94
+ OperationConstraint.new(model, params)
75
95
  end
76
- alias_set_methods
77
96
  end
78
97
 
79
- # Describes an operation constraint, which constrains the result of an
80
- # operation with two sets as operands. Either constant sets or set
81
- # variables may be used for the result and operands, with the exception of
82
- # that all three may not be constant sets.
83
- #
84
- # The typical form is
85
- # set_operand_1.<operation>(set_operand_2).must.<relation>(result_set)
86
- #
87
- # The following operations are supported:
88
- #
89
- # * union
90
- # * disjoint_union
91
- # * intersection
92
- # * minus
93
- #
94
- # The allowed relations are the same as for
95
- # <tt>Set::Relation::RelationConstraint</tt>.
96
- #
97
- # Neither reification nor negation is supported.
98
- #
99
- # == Examples
100
- #
101
- # # +set_1+ union +set_2+ must equal +set_3+.
102
- # set_1.union(set_2).must == set_3
103
- #
104
- # # +set_1+ intersection [3,5,6] must equal +set_3+.
105
- # set_1.intersection([3,5,6]).must == set_3
106
- #
107
- # # [0,1,2] minus +set_2+ must be superset of +set_3+.
108
- # wrap_enum([0,1,2]).minus(set_2).must_be.superset_of(set_3)
109
- #
110
- # # +set_1+ disjoint union with [0] must be subset of 0..17.
111
- # set_1.disjoint_union(0).must_be.subset_of 0..17
112
- class OperationConstraint < Gecode::Constraints::Constraint
98
+ class OperationConstraint < Gecode::Constraint #:nodoc:
113
99
  def post
114
- op1, op2, operation, relation, rhs, negate = @params.values_at(:lhs,
115
- :op2, :operation, :relation, :rhs, :negate)
100
+ op1, op2, operation, relation, rhs, negate = @params.values_at(:op1,
101
+ :op2, :operation, :relation_type, :rhs, :negate)
116
102
 
117
103
  op1, op2, rhs = [op1, op2, rhs].map do |expression|
118
- # The expressions can either be set variables or constant sets,
104
+ # The expressions can either be set operands or constant sets,
119
105
  # convert them appropriately.
120
- if expression.respond_to? :bind
121
- expression.bind
106
+ if expression.respond_to? :to_set_var
107
+ expression.to_set_var.bind
122
108
  else
123
- Gecode::Constraints::Util::constant_set_to_int_set(expression)
109
+ Gecode::Util::constant_set_to_int_set(expression)
124
110
  end
125
111
  end
126
112
 
127
- Gecode::Raw::rel(@model.active_space, op1, operation, op2, relation,
128
- rhs)
113
+ Gecode::Raw::rel(@model.active_space, op1, operation, op2,
114
+ relation, rhs)
129
115
  end
130
116
  end
131
117
  end
132
- end
118
+ end
@@ -1,44 +1,110 @@
1
- module Gecode
2
- class FreeSetVar
3
- # Starts a constraint on all the elements of the set.
4
- def elements
5
- params = {:lhs => self}
6
- Gecode::Constraints::SimpleExpressionStub.new(@model, params) do |m, ps|
7
- Gecode::Constraints::Set::Relation::ElementExpression.new(m, ps)
1
+ module Gecode::Set
2
+ class SetConstraintReceiver
3
+ alias_method :pre_relation_equality, :==
4
+ # Constrains the set operand to equal +set_operand+.
5
+ #
6
+ # ==== Examples
7
+ #
8
+ # # +set1+ must equal +set2+
9
+ # set1.must == set2
10
+ #
11
+ # # +set1+ must equal +set2+. Reify the constraint with the
12
+ # # boolean operand +bool+.
13
+ # set1.must.equal(set2, :reify => bool)
14
+ def ==(set_operand, options = {})
15
+ if set_operand.respond_to? :to_set_var
16
+ add_relation_constraint(:==, set_operand, options)
17
+ else
18
+ pre_relation_equality(set_operand, options)
8
19
  end
9
20
  end
10
- end
11
- end
12
21
 
13
- module Gecode::Constraints::Set
14
- class Expression
15
- Gecode::Constraints::Util::SET_RELATION_TYPES.each_pair do |name, type|
16
- module_eval <<-"end_code"
17
- # Wrap previous relation methods providing support for relation
18
- # constraints.
19
- alias_method 'pre_relation_#{type}_method'.to_sym, :#{name}
20
-
21
- # Creates a relation constraint using the specified expression.
22
- def #{name}(expression, options = {})
23
- if expression.kind_of? Gecode::FreeSetVar
24
- add_relation_constraint(:#{name}, expression, options)
25
- else
26
- # Send it on.
27
- pre_relation_#{type}_method(expression, options)
28
- end
29
- end
30
- end_code
22
+ alias_method :pre_relation_superset, :superset
23
+ # Constrains the set operand to be a superset of +set_operand+.
24
+ #
25
+ # ==== Examples
26
+ #
27
+ # # +set1+ must be a superset of +set2+
28
+ # set1.must_be.superset_of set2
29
+ #
30
+ # # +set1+ must be a superset of +set2+. Reify the constraint
31
+ # # with the boolean operand +bool+.
32
+ # set1.must_be.superset(set2, :reify => bool)
33
+ def superset(set_operand, options = {})
34
+ if set_operand.respond_to? :to_set_var
35
+ add_relation_constraint(:superset, set_operand, options)
36
+ else
37
+ pre_relation_superset(set_operand, options)
38
+ end
31
39
  end
40
+
41
+ alias_method :pre_relation_subset, :subset
42
+ # Constrains the set operand to be a subeset of +set_operand+.
43
+ #
44
+ # ==== Examples
45
+ #
46
+ # # +set1+ must be a subset of +set2+
47
+ # set1.must_be.subset_of == set2
48
+ #
49
+ # # +set1+ must be a subset of +set2+. Reify the constraint
50
+ # # with the boolean operand +bool+.
51
+ # set1.must_be.subset(set2, :reify => bool)
52
+ def subset(set_operand, options = {})
53
+ if set_operand.respond_to? :to_set_var
54
+ add_relation_constraint(:subset, set_operand, options)
55
+ else
56
+ pre_relation_subset(set_operand, options)
57
+ end
58
+ end
59
+
60
+ alias_method :pre_relation_disjoint, :disjoint
61
+ # Constrains the set operand to be disjoint with +set_operand+.
62
+ #
63
+ # ==== Examples
64
+ #
65
+ # # +set1+ must be disjoint with +set2+
66
+ # set1.must_be.disjoint_with set2
67
+ #
68
+ # # +set1+ must be disjoint with +set2+. Reify the constraint
69
+ # # with the boolean operand +bool+.
70
+ # set1.must_be.disjoint(set2, :reify => bool)
71
+ def disjoint(set_operand, options = {})
72
+ if set_operand.respond_to? :to_set_var
73
+ add_relation_constraint(:disjoint, set_operand, options)
74
+ else
75
+ pre_relation_disjoint(set_operand, options)
76
+ end
77
+ end
78
+
79
+ alias_method :pre_relation_complement, :complement
80
+ # Constrains the set operand to be the complement of +set_operand+.
81
+ #
82
+ # ==== Examples
83
+ #
84
+ # # +set1+ must be the complement of +set2+
85
+ # set1.must_be.complement_of set2
86
+ #
87
+ # # +set1+ must be the complement of +set2+. Reify the constraint
88
+ # # with the boolean operand +bool+.
89
+ # set1.must_be.complement(set2, :reify => bool)
90
+ def complement(set_operand, options = {})
91
+ if set_operand.respond_to? :to_set_var
92
+ add_relation_constraint(:complement, set_operand, options)
93
+ else
94
+ pre_relation_complement(set_operand, options)
95
+ end
96
+ end
97
+
32
98
  alias_set_methods
33
99
 
34
100
  private
35
101
 
36
- # Adds a relation constraint for the specified relation name, set variable
37
- # and options.
102
+ # Adds a relation constraint for the specified relation name, set
103
+ # operand and options.
38
104
  def add_relation_constraint(relation_name, set, options)
39
105
  @params[:rhs] = set
40
106
  @params[:relation] = relation_name
41
- @params.update Gecode::Constraints::Set::Util.decode_options(options)
107
+ @params.update Gecode::Set::Util.decode_options(options)
42
108
  if relation_name == :==
43
109
  @model.add_constraint Relation::EqualityRelationConstraint.new(@model,
44
110
  @params)
@@ -50,129 +116,40 @@ module Gecode::Constraints::Set
50
116
 
51
117
  # A module that gathers the classes and modules used in relation constraints.
52
118
  module Relation #:nodoc:
53
- # Describes a relation constraint which constrains a set variable to be
54
- # equal to another set variable. Equality may either be expressed as
55
- # +==+, +equal+ or +equal_to+.
56
- #
57
- # == Examples
58
- #
59
- # # +set_1+ must be equal to +set_2+
60
- # set_1.must == set_2
61
- #
62
- # # +set_1+ must not be equal to +set_2+
63
- # set_1.must_not == set_2
64
- #
65
- # # The same as above but reified with the boolean variable
66
- # # +are_not_equal+.
67
- # set_1.must_not.equal(set_2, :reify => are_not_equal)
68
- class EqualityRelationConstraint < Gecode::Constraints::ReifiableConstraint
119
+ class EqualityRelationConstraint < Gecode::ReifiableConstraint #:nodoc:
69
120
  def post
70
- var, rhs, reif_var, negate = @params.values_at(:lhs, :rhs, :reif,
121
+ lhs, rhs, reif_var, negate = @params.values_at(:lhs, :rhs, :reif,
71
122
  :negate)
72
123
  if negate
73
- rel_type = Gecode::Constraints::Util::NEGATED_SET_RELATION_TYPES[:==]
124
+ rel_type = Gecode::Util::NEGATED_SET_RELATION_TYPES[:==]
74
125
  else
75
- rel_type = Gecode::Constraints::Util::SET_RELATION_TYPES[:==]
126
+ rel_type = Gecode::Util::SET_RELATION_TYPES[:==]
76
127
  end
77
128
 
78
- (params = []) << var.bind
129
+ (params = []) << lhs.to_set_var.bind
79
130
  params << rel_type
80
- params << rhs.bind
81
- params << reif_var.bind if reif_var.respond_to? :bind
131
+ params << rhs.to_set_var.bind
132
+ if reif_var.respond_to? :to_bool_var
133
+ params << reif_var.to_bool_var.bind
134
+ end
82
135
  Gecode::Raw::rel(@model.active_space, *params)
83
136
  end
84
137
  end
85
138
 
86
- # Describes a relation constraint which constrains a set variable to have
87
- # a specified relation to another set variable. The allowed relations and
88
- # their aliases are
89
- #
90
- # * subset, subset_of
91
- # * superset, superset_of
92
- # * disjoint, disjoint_with
93
- # * complement, complement_of
94
- #
95
- # == Examples
96
- #
97
- # # +set_1+ must be subset of +set_2+
98
- # set_1.must_be.subset_of set_2
99
- #
100
- # # +set_1+ must not be superset of +set_2+
101
- # set_1.must_not_be.superset_of set_2
102
- #
103
- # # +set_1+ must be disjoint with +set_2+
104
- # set_1.must_be.disjoint set_2
105
- #
106
- # # The same as above but reified with the boolean variable
107
- # # +are_disjoint+.
108
- # set_1.must_be.disjoint(set_2, :reify => are_disjoint)
109
- class RelationConstraint < Gecode::Constraints::ReifiableConstraint
139
+ class RelationConstraint < Gecode::ReifiableConstraint #:nodoc:
110
140
  def post
111
- var, rhs, reif_var, relation = @params.values_at(:lhs, :rhs, :reif,
141
+ lhs, rhs, reif_var, relation = @params.values_at(:lhs, :rhs, :reif,
112
142
  :relation)
113
143
 
114
- (params = []) << var.bind
115
- params << Gecode::Constraints::Util::SET_RELATION_TYPES[relation]
116
- params << rhs.bind
117
- params << reif_var.bind if reif_var.respond_to? :bind
144
+ (params = []) << lhs.to_set_var.bind
145
+ params << Gecode::Util::SET_RELATION_TYPES[relation]
146
+ params << rhs.to_set_var.bind
147
+ if reif_var.respond_to? :to_bool_var
148
+ params << reif_var.to_bool_var.bind
149
+ end
118
150
  Gecode::Raw::rel(@model.active_space, *params)
119
151
  end
120
152
  negate_using_reification
121
153
  end
122
-
123
- # Describes an element relation constraint which constrains all elements in
124
- # a set variable to satisfy an integer relation constraint. The relations
125
- # supported are the same as in
126
- # <tt>Int::Linear::SimpleRelationConstraint</tt>.
127
- #
128
- # Reification is not supported.
129
- #
130
- # == Examples
131
- #
132
- # # All elements in +set+ must be larger than 5.
133
- # set.elements.must > 5
134
- #
135
- # # No element in +set+ may equal 0.
136
- # set.elements.must_not == 0
137
- #
138
- # # No element in +set+ may contain the value of the integer variable
139
- # # +forbidden_number+.
140
- # set.elements.must_not == forbidden_number
141
- class ElementRelationConstraint < Gecode::Constraints::Constraint
142
- def post
143
- var, rhs, relation = @params.values_at(:lhs, :rhs, :relation)
144
-
145
- if @params[:negate]
146
- type = Gecode::Constraints::Util::NEGATED_RELATION_TYPES[relation]
147
- else
148
- type = Gecode::Constraints::Util::RELATION_TYPES[relation]
149
- end
150
-
151
- if rhs.kind_of? Fixnum
152
- # Use a proxy int variable to cover.
153
- rhs = @model.int_var(rhs)
154
- end
155
- Gecode::Raw::rel(@model.active_space, var.bind, type, rhs.bind)
156
- end
157
- end
158
-
159
- # Describes an expression which starts with set.elements.must* .
160
- class ElementExpression < Gecode::Constraints::Expression #:nodoc:
161
- Gecode::Constraints::Util::RELATION_TYPES.each_key do |name|
162
- module_eval <<-"end_code"
163
- # Creates an elements constraint using the specified expression, which
164
- # may be either a constant integer of variable.
165
- def #{name}(expression)
166
- unless expression.kind_of?(Fixnum) or
167
- expression.kind_of?(Gecode::FreeIntVar)
168
- raise TypeError, "Invalid expression type \#{expression.class}."
169
- end
170
- @params.update(:rhs => expression, :relation => :#{name})
171
- @model.add_constraint ElementRelationConstraint.new(@model, @params)
172
- end
173
- end_code
174
- end
175
- alias_comparison_methods
176
- end
177
154
  end
178
- end
155
+ end