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.
- data/CHANGES +15 -0
- data/README +6 -2
- data/example/equation_system.rb +15 -0
- data/example/magic_sequence.rb +7 -7
- data/example/money.rb +36 -0
- data/example/queens.rb +7 -8
- data/example/send_most_money.rb +1 -1
- data/example/square_tiling.rb +2 -2
- data/example/sudoku-set.rb +11 -12
- data/example/sudoku.rb +40 -45
- data/ext/extconf.rb +0 -0
- data/lib/gecoder/bindings.rb +42 -0
- data/lib/gecoder/bindings/bindings.rb +16 -0
- data/lib/gecoder/interface.rb +2 -1
- data/lib/gecoder/interface/branch.rb +16 -9
- data/lib/gecoder/interface/constraints.rb +410 -451
- data/lib/gecoder/interface/constraints/bool/boolean.rb +205 -213
- data/lib/gecoder/interface/constraints/bool/channel.rb +4 -5
- data/lib/gecoder/interface/constraints/bool/linear.rb +192 -21
- data/lib/gecoder/interface/constraints/bool_enum/channel.rb +43 -39
- data/lib/gecoder/interface/constraints/bool_enum/extensional.rb +43 -49
- data/lib/gecoder/interface/constraints/bool_enum/relation.rb +38 -71
- data/lib/gecoder/interface/constraints/bool_enum_constraints.rb +73 -22
- data/lib/gecoder/interface/constraints/bool_var_constraints.rb +140 -61
- data/lib/gecoder/interface/constraints/extensional_regexp.rb +4 -4
- data/lib/gecoder/interface/constraints/fixnum_enum/element.rb +63 -0
- data/lib/gecoder/interface/constraints/fixnum_enum/operation.rb +65 -0
- data/lib/gecoder/interface/constraints/fixnum_enum_constraints.rb +42 -0
- data/lib/gecoder/interface/constraints/int/arithmetic.rb +131 -130
- data/lib/gecoder/interface/constraints/int/channel.rb +21 -31
- data/lib/gecoder/interface/constraints/int/domain.rb +45 -42
- data/lib/gecoder/interface/constraints/int/linear.rb +85 -239
- data/lib/gecoder/interface/constraints/int/relation.rb +141 -0
- data/lib/gecoder/interface/constraints/int_enum/arithmetic.rb +55 -64
- data/lib/gecoder/interface/constraints/int_enum/channel.rb +35 -37
- data/lib/gecoder/interface/constraints/int_enum/count.rb +53 -78
- data/lib/gecoder/interface/constraints/int_enum/distinct.rb +36 -46
- data/lib/gecoder/interface/constraints/int_enum/element.rb +39 -57
- data/lib/gecoder/interface/constraints/int_enum/equality.rb +15 -19
- data/lib/gecoder/interface/constraints/int_enum/extensional.rb +65 -72
- data/lib/gecoder/interface/constraints/int_enum/sort.rb +42 -45
- data/lib/gecoder/interface/constraints/int_enum_constraints.rb +79 -22
- data/lib/gecoder/interface/constraints/int_var_constraints.rb +215 -44
- data/lib/gecoder/interface/constraints/reifiable_constraints.rb +14 -14
- data/lib/gecoder/interface/constraints/selected_set/select.rb +120 -0
- data/lib/gecoder/interface/constraints/selected_set_constraints.rb +75 -0
- data/lib/gecoder/interface/constraints/set/cardinality.rb +43 -53
- data/lib/gecoder/interface/constraints/set/channel.rb +26 -29
- data/lib/gecoder/interface/constraints/set/connection.rb +89 -152
- data/lib/gecoder/interface/constraints/set/domain.rb +112 -65
- data/lib/gecoder/interface/constraints/set/include.rb +36 -0
- data/lib/gecoder/interface/constraints/set/operation.rb +96 -110
- data/lib/gecoder/interface/constraints/set/relation.rb +114 -137
- data/lib/gecoder/interface/constraints/set_elements/relation.rb +116 -0
- data/lib/gecoder/interface/constraints/set_elements_constraints.rb +97 -0
- data/lib/gecoder/interface/constraints/set_enum/channel.rb +23 -27
- data/lib/gecoder/interface/constraints/set_enum/distinct.rb +18 -19
- data/lib/gecoder/interface/constraints/set_enum/operation.rb +62 -53
- data/lib/gecoder/interface/constraints/set_enum/select.rb +79 -0
- data/lib/gecoder/interface/constraints/set_enum_constraints.rb +73 -23
- data/lib/gecoder/interface/constraints/set_var_constraints.rb +222 -57
- data/lib/gecoder/interface/enum_matrix.rb +4 -4
- data/lib/gecoder/interface/enum_wrapper.rb +71 -22
- data/lib/gecoder/interface/model.rb +167 -12
- data/lib/gecoder/interface/model_sugar.rb +84 -0
- data/lib/gecoder/interface/search.rb +30 -18
- data/lib/gecoder/interface/variables.rb +103 -33
- data/lib/gecoder/version.rb +2 -2
- data/specs/bool_var.rb +19 -12
- data/specs/constraints/{boolean.rb → bool/boolean.rb} +103 -28
- data/specs/constraints/bool/boolean_properties.rb +51 -0
- data/specs/constraints/bool/linear.rb +213 -0
- data/specs/constraints/bool_enum/bool_enum_relation.rb +117 -0
- data/specs/constraints/bool_enum/channel.rb +102 -0
- data/specs/constraints/{extensional.rb → bool_enum/extensional.rb} +32 -101
- data/specs/constraints/constraint_helper.rb +149 -179
- data/specs/constraints/constraint_receivers.rb +103 -0
- data/specs/constraints/constraints.rb +6 -63
- data/specs/constraints/fixnum_enum/element.rb +58 -0
- data/specs/constraints/fixnum_enum/operation.rb +67 -0
- data/specs/constraints/int/arithmetic.rb +149 -0
- data/specs/constraints/int/channel.rb +101 -0
- data/specs/constraints/int/domain.rb +106 -0
- data/specs/constraints/int/linear.rb +183 -0
- data/specs/constraints/int/linear_properties.rb +97 -0
- data/specs/constraints/int/relation.rb +84 -0
- data/specs/constraints/int_enum/arithmetic.rb +72 -0
- data/specs/constraints/int_enum/channel.rb +57 -0
- data/specs/constraints/int_enum/count.rb +72 -0
- data/specs/constraints/int_enum/distinct.rb +80 -0
- data/specs/constraints/int_enum/element.rb +61 -0
- data/specs/constraints/int_enum/equality.rb +29 -0
- data/specs/constraints/int_enum/extensional.rb +224 -0
- data/specs/constraints/int_enum/sort.rb +167 -0
- data/specs/constraints/operands.rb +264 -0
- data/specs/constraints/property_helper.rb +443 -0
- data/specs/constraints/reification_sugar.rb +4 -5
- data/specs/constraints/selected_set/select.rb +56 -0
- data/specs/constraints/selected_set/select_properties.rb +157 -0
- data/specs/constraints/set/cardinality.rb +58 -0
- data/specs/constraints/set/cardinality_properties.rb +46 -0
- data/specs/constraints/set/channel.rb +77 -0
- data/specs/constraints/set/connection.rb +176 -0
- data/specs/constraints/set/domain.rb +197 -0
- data/specs/constraints/set/include.rb +36 -0
- data/specs/constraints/set/operation.rb +132 -0
- data/specs/constraints/set/relation.rb +117 -0
- data/specs/constraints/set_elements/relation.rb +84 -0
- data/specs/constraints/set_enum/channel.rb +80 -0
- data/specs/constraints/set_enum/distinct.rb +59 -0
- data/specs/constraints/set_enum/operation.rb +111 -0
- data/specs/constraints/set_enum/select.rb +73 -0
- data/specs/enum_wrapper.rb +53 -3
- data/specs/int_var.rb +44 -25
- data/specs/model.rb +58 -1
- data/specs/model_sugar.rb +30 -0
- data/specs/search.rb +24 -5
- data/specs/selected_set.rb +39 -0
- data/specs/set_elements.rb +34 -0
- data/specs/set_var.rb +22 -8
- data/specs/spec_helper.rb +206 -6
- data/tasks/distribution.rake +22 -7
- data/tasks/svn.rake +3 -1
- metadata +218 -134
- data/lib/gecoder/interface/constraints/set_enum/selection.rb +0 -217
- data/specs/constraints/arithmetic.rb +0 -351
- data/specs/constraints/bool_enum_relation.rb +0 -160
- data/specs/constraints/cardinality.rb +0 -157
- data/specs/constraints/channel.rb +0 -454
- data/specs/constraints/connection.rb +0 -369
- data/specs/constraints/count.rb +0 -146
- data/specs/constraints/distinct.rb +0 -164
- data/specs/constraints/element.rb +0 -108
- data/specs/constraints/equality.rb +0 -31
- data/specs/constraints/int_domain.rb +0 -70
- data/specs/constraints/int_relation.rb +0 -82
- data/specs/constraints/linear.rb +0 -340
- data/specs/constraints/selection.rb +0 -292
- data/specs/constraints/set_domain.rb +0 -185
- data/specs/constraints/set_operation.rb +0 -285
- data/specs/constraints/set_relation.rb +0 -197
- 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
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
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
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
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
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
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
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
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
|
-
|
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(:
|
115
|
-
:op2, :operation, :
|
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
|
104
|
+
# The expressions can either be set operands or constant sets,
|
119
105
|
# convert them appropriately.
|
120
|
-
if expression.respond_to? :
|
121
|
-
expression.bind
|
106
|
+
if expression.respond_to? :to_set_var
|
107
|
+
expression.to_set_var.bind
|
122
108
|
else
|
123
|
-
Gecode::
|
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,
|
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
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
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
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
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
|
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::
|
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
|
-
|
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
|
-
|
121
|
+
lhs, rhs, reif_var, negate = @params.values_at(:lhs, :rhs, :reif,
|
71
122
|
:negate)
|
72
123
|
if negate
|
73
|
-
rel_type = Gecode::
|
124
|
+
rel_type = Gecode::Util::NEGATED_SET_RELATION_TYPES[:==]
|
74
125
|
else
|
75
|
-
rel_type = Gecode::
|
126
|
+
rel_type = Gecode::Util::SET_RELATION_TYPES[:==]
|
76
127
|
end
|
77
128
|
|
78
|
-
(params = []) <<
|
129
|
+
(params = []) << lhs.to_set_var.bind
|
79
130
|
params << rel_type
|
80
|
-
params << rhs.bind
|
81
|
-
|
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
|
-
|
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
|
-
|
141
|
+
lhs, rhs, reif_var, relation = @params.values_at(:lhs, :rhs, :reif,
|
112
142
|
:relation)
|
113
143
|
|
114
|
-
(params = []) <<
|
115
|
-
params << Gecode::
|
116
|
-
params << rhs.bind
|
117
|
-
|
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
|