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,141 @@
|
|
1
|
+
module Gecode::Int
|
2
|
+
class IntConstraintReceiver
|
3
|
+
# Constrains the integer operand to equal +int_operand_or_fixnum+.
|
4
|
+
# #equal and #equal_to are aliases of this method.
|
5
|
+
#
|
6
|
+
# ==== Examples
|
7
|
+
#
|
8
|
+
# # +int1+ must equal +int2+
|
9
|
+
# int1.must == int2
|
10
|
+
#
|
11
|
+
# # +int+ must equal 17
|
12
|
+
# int.must == 17
|
13
|
+
#
|
14
|
+
# # +int1+ must equal +int2+. We reify the constraint with
|
15
|
+
# # +bool+ and select +domain+ as strength.
|
16
|
+
# int1.must.equal(int2, :reify => bool, :strength => :domain)
|
17
|
+
def ==(int_operand_or_fixnum, options = {})
|
18
|
+
comparison(:==, int_operand_or_fixnum, options)
|
19
|
+
end
|
20
|
+
|
21
|
+
# Constrains the integer operand to be strictly greater than
|
22
|
+
# +int_operand_or_fixnum+. #greater and #greater_than are
|
23
|
+
# aliases of this method.
|
24
|
+
#
|
25
|
+
# ==== Examples
|
26
|
+
#
|
27
|
+
# # +int1+ must be strictly greater than +int2+
|
28
|
+
# int1.must > int2
|
29
|
+
#
|
30
|
+
# # +int+ must be strictly greater than 17
|
31
|
+
# int.must > 17
|
32
|
+
#
|
33
|
+
# # +int1+ must be strictly greater than +int2+. We reify the
|
34
|
+
# # constraint with +bool+ and select +domain+ as strength.
|
35
|
+
# int1.must_be.greater_than(int2, :reify => bool, :strength => :domain)
|
36
|
+
def >(int_operand_or_fixnum, options = {})
|
37
|
+
comparison(:>, int_operand_or_fixnum, options)
|
38
|
+
end
|
39
|
+
|
40
|
+
# Constrains the integer operand to be greater than or equal to
|
41
|
+
# +int_operand_or_fixnum+. #greater_or_equal and
|
42
|
+
# #greater_than_or_equal_to are aliases of this method.
|
43
|
+
#
|
44
|
+
# ==== Examples
|
45
|
+
#
|
46
|
+
# # +int1+ must be greater than or equal to +int2+
|
47
|
+
# int1.must >= int2
|
48
|
+
#
|
49
|
+
# # +int+ must be greater than or equal to 17
|
50
|
+
# int.must >= 17
|
51
|
+
#
|
52
|
+
# # +int1+ must be greater than or equal to +int2+. We reify the
|
53
|
+
# # constraint with +bool+ and select +domain+ as strength.
|
54
|
+
# int1.must.greater_or_equal(int2, :reify => bool, :strength => :domain)
|
55
|
+
def >=(int_operand_or_fixnum, options = {})
|
56
|
+
comparison(:>=, int_operand_or_fixnum, options)
|
57
|
+
end
|
58
|
+
|
59
|
+
# Constrains the integer operand to be strictly less than
|
60
|
+
# +int_operand_or_fixnum+. #lesser and #lesser_than are
|
61
|
+
# aliases of this method.
|
62
|
+
#
|
63
|
+
# ==== Examples
|
64
|
+
#
|
65
|
+
# # +int1+ must be strictly less than +int2+
|
66
|
+
# int1.must < int2
|
67
|
+
#
|
68
|
+
# # +int+ must be strictly less than 17
|
69
|
+
# int.must < 17
|
70
|
+
#
|
71
|
+
# # +int1+ must be strictly less than +int2+. We reify the
|
72
|
+
# # constraint with +bool+ and select +domain+ as strength.
|
73
|
+
# int1.must_be.less_than(int2, :reify => bool, :strength => :domain)
|
74
|
+
def <(int_operand_or_fixnum, options = {})
|
75
|
+
comparison(:<, int_operand_or_fixnum, options)
|
76
|
+
end
|
77
|
+
|
78
|
+
# Constrains the integer operand to be less than or equal to
|
79
|
+
# +int_operand_or_fixnum+. #less_or_equal and
|
80
|
+
# #less_than_or_equal_to are aliases of this method.
|
81
|
+
#
|
82
|
+
# ==== Examples
|
83
|
+
#
|
84
|
+
# # +int1+ must be less than or equal to +int2+
|
85
|
+
# int1.must <= int2
|
86
|
+
#
|
87
|
+
# # +int+ must be less than or equal to 17
|
88
|
+
# int.must <= 17
|
89
|
+
#
|
90
|
+
# # +int1+ must be less than or equal to +int2+. We reify the
|
91
|
+
# # constraint with +bool+ and select +domain+ as strength.
|
92
|
+
# int1.must.less_or_equal(int2, :reify => bool, :strength => :domain)
|
93
|
+
def <=(int_operand_or_fixnum, options = {})
|
94
|
+
comparison(:<=, int_operand_or_fixnum, options)
|
95
|
+
end
|
96
|
+
|
97
|
+
alias_comparison_methods
|
98
|
+
|
99
|
+
private
|
100
|
+
|
101
|
+
# Helper for the comparison methods. The reason that they are not
|
102
|
+
# generated in a loop is that it would mess up the RDoc.
|
103
|
+
def comparison(name, int_operand_or_fixnum, options)
|
104
|
+
unless int_operand_or_fixnum.respond_to?(:to_int_var) or
|
105
|
+
int_operand_or_fixnum.kind_of?(Fixnum)
|
106
|
+
raise TypeError, "Expected int operand or integer, got " +
|
107
|
+
"#{int_operand_or_fixnum.class}."
|
108
|
+
end
|
109
|
+
|
110
|
+
unless @params[:negate]
|
111
|
+
relation_type = Gecode::Util::RELATION_TYPES[name]
|
112
|
+
else
|
113
|
+
relation_type = Gecode::Util::NEGATED_RELATION_TYPES[name]
|
114
|
+
end
|
115
|
+
@params.update Gecode::Util.decode_options(options)
|
116
|
+
@model.add_constraint Relation::RelationConstraint.new(@model,
|
117
|
+
@params.update(:relation_type => relation_type,
|
118
|
+
:rhs => int_operand_or_fixnum))
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
# A module that gathers the classes and modules used in relation constraints.
|
123
|
+
module Relation #:nodoc:
|
124
|
+
class RelationConstraint < Gecode::ReifiableConstraint #:nodoc:
|
125
|
+
def post
|
126
|
+
# Fetch the parameters to Gecode.
|
127
|
+
lhs, relation, rhs, reif_var =
|
128
|
+
@params.values_at(:lhs, :relation_type, :rhs, :reif)
|
129
|
+
|
130
|
+
rhs = rhs.to_int_var.bind if rhs.respond_to? :to_int_var
|
131
|
+
if reif_var.nil?
|
132
|
+
Gecode::Raw::rel(@model.active_space, lhs.to_int_var.bind,
|
133
|
+
relation, rhs, *propagation_options)
|
134
|
+
else
|
135
|
+
Gecode::Raw::rel(@model.active_space, lhs.to_int_var.bind,
|
136
|
+
relation, rhs, reif_var.to_bool_var.bind, *propagation_options)
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
@@ -1,72 +1,63 @@
|
|
1
|
-
module Gecode::
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
1
|
+
module Gecode::IntEnum
|
2
|
+
module IntEnumOperand
|
3
|
+
# Produces an IntOperand representing the maximum value of the
|
4
|
+
# integer operands in this enumeration.
|
5
|
+
#
|
6
|
+
# ==== Examples
|
7
|
+
#
|
8
|
+
# # The maximum of +int_enum+.
|
9
|
+
# int_enum.max
|
10
|
+
def max
|
11
|
+
Arithmetic::IntEnumMaxOperand.new(@model, self)
|
12
|
+
end
|
13
|
+
|
14
|
+
# Produces an IntOperand representing the minimum value of the
|
15
|
+
# integer operands in this enumeration.
|
16
|
+
#
|
17
|
+
# ==== Examples
|
18
|
+
#
|
19
|
+
# # The minimum of +int_enum+.
|
20
|
+
# int_enum.min
|
21
|
+
def min
|
22
|
+
Arithmetic::IntEnumMinOperand.new(@model, self)
|
23
|
+
end
|
14
24
|
end
|
15
|
-
end
|
16
25
|
|
17
|
-
# A module that gathers the classes and modules used by arithmetic
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
class MaxExpressionStub < Gecode::Constraints::Int::CompositeStub
|
35
|
-
def constrain_equal(variable, params, constrain)
|
36
|
-
enum = @params[:lhs]
|
37
|
-
if constrain
|
38
|
-
variable.must_be.in enum.domain_range
|
26
|
+
# A module that gathers the classes and modules used by arithmetic
|
27
|
+
# constraints.
|
28
|
+
module Arithmetic #:nodoc:
|
29
|
+
class IntEnumMaxOperand < Gecode::Int::ShortCircuitEqualityOperand #:nodoc:
|
30
|
+
def initialize(model, int_enum)
|
31
|
+
super model
|
32
|
+
@int_enum = int_enum
|
33
|
+
end
|
34
|
+
|
35
|
+
def constrain_equal(int_operand, constrain, propagation_options)
|
36
|
+
enum = @int_enum.to_int_enum
|
37
|
+
if constrain
|
38
|
+
int_operand.must_be.in enum.domain_range
|
39
|
+
end
|
40
|
+
|
41
|
+
Gecode::Raw::max(@model.active_space, enum.bind_array,
|
42
|
+
int_operand.to_int_var.bind, *propagation_options)
|
39
43
|
end
|
40
|
-
|
41
|
-
Gecode::Raw::max(@model.active_space, enum.to_int_var_array,
|
42
|
-
variable.bind, *propagation_options)
|
43
44
|
end
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
# int_enum.min.must_not_be.less_or_equal(0, :reify => is_positive,
|
60
|
-
# :strength => :domain)
|
61
|
-
class MinExpressionStub < Gecode::Constraints::Int::CompositeStub
|
62
|
-
def constrain_equal(variable, params, constrain)
|
63
|
-
enum = @params[:lhs]
|
64
|
-
if constrain
|
65
|
-
variable.must_be.in enum.domain_range
|
45
|
+
|
46
|
+
class IntEnumMinOperand < Gecode::Int::ShortCircuitEqualityOperand #:nodoc:
|
47
|
+
def initialize(model, int_enum)
|
48
|
+
super model
|
49
|
+
@int_enum = int_enum
|
50
|
+
end
|
51
|
+
|
52
|
+
def constrain_equal(int_operand, constrain, propagation_options)
|
53
|
+
enum = @int_enum.to_int_enum
|
54
|
+
if constrain
|
55
|
+
int_operand.must_be.in enum.domain_range
|
56
|
+
end
|
57
|
+
|
58
|
+
Gecode::Raw::min(@model.active_space, enum.bind_array,
|
59
|
+
int_operand.to_int_var.bind, *propagation_options)
|
66
60
|
end
|
67
|
-
|
68
|
-
Gecode::Raw::min(@model.active_space, enum.to_int_var_array,
|
69
|
-
variable.bind, *propagation_options)
|
70
61
|
end
|
71
62
|
end
|
72
63
|
end
|
@@ -1,34 +1,8 @@
|
|
1
|
-
module Gecode::
|
2
|
-
class
|
3
|
-
#
|
4
|
-
#
|
5
|
-
|
6
|
-
if @params[:negate]
|
7
|
-
raise Gecode::MissingConstraintError, 'A negated channel constraint ' +
|
8
|
-
'is not implemented.'
|
9
|
-
end
|
10
|
-
unless enum.respond_to?(:to_int_var_array)
|
11
|
-
raise TypeError, "Expected int enum, got #{enum.class}."
|
12
|
-
end
|
13
|
-
if options.has_key? :reify
|
14
|
-
raise ArgumentError, 'The channel constraints does not support the ' +
|
15
|
-
'reification option.'
|
16
|
-
end
|
17
|
-
|
18
|
-
@params.update(Gecode::Constraints::Util.decode_options(options))
|
19
|
-
@params.update(:rhs => enum)
|
20
|
-
@model.add_constraint Channel::ChannelConstraint.new(@model, @params)
|
21
|
-
end
|
22
|
-
|
23
|
-
provide_commutivity(:channel){ |rhs, _| rhs.respond_to? :to_set_var_array }
|
24
|
-
end
|
25
|
-
|
26
|
-
# A module that gathers the classes and modules used in channel constraints.
|
27
|
-
module Channel #:nodoc:
|
28
|
-
# Describes a channel constraint which "channels" two enumerations of
|
29
|
-
# integer variables or one enumeration of integer variables and one
|
30
|
-
# enumeration of set variables. Channel constraints are used to give
|
31
|
-
# access to multiple viewpoints when modelling.
|
1
|
+
module Gecode::IntEnum
|
2
|
+
class IntEnumConstraintReceiver
|
3
|
+
# Constrains this enumeration to "channel" +int_enum+. Channel
|
4
|
+
# constraints are used to give access to multiple viewpoints when
|
5
|
+
# modelling.
|
32
6
|
#
|
33
7
|
# The channel constraint can be thought of as constraining the arrays to
|
34
8
|
# be each other's inverses. I.e. if the i:th value in the first enumeration
|
@@ -37,9 +11,9 @@ module Gecode::Constraints::IntEnum
|
|
37
11
|
#
|
38
12
|
# Neither reification nor negation is supported.
|
39
13
|
#
|
40
|
-
#
|
14
|
+
# ==== Examples
|
41
15
|
#
|
42
|
-
# Lets say that we
|
16
|
+
# Lets say that we're modelling a sequence of numbers that must be distinct
|
43
17
|
# and that we want access to the following two view simultaneously.
|
44
18
|
#
|
45
19
|
# === First view
|
@@ -77,12 +51,36 @@ module Gecode::Constraints::IntEnum
|
|
77
51
|
#
|
78
52
|
# elements.must.channel positions
|
79
53
|
#
|
80
|
-
|
54
|
+
def channel(int_enum, options = {})
|
55
|
+
if @params[:negate]
|
56
|
+
raise Gecode::MissingConstraintError, 'A negated channel constraint ' +
|
57
|
+
'is not implemented.'
|
58
|
+
end
|
59
|
+
unless int_enum.respond_to? :to_int_enum
|
60
|
+
raise TypeError, "Expected int enum, got #{int_enum.class}."
|
61
|
+
end
|
62
|
+
if options.has_key? :reify
|
63
|
+
raise ArgumentError, 'The channel constraints does not support the ' +
|
64
|
+
'reification option.'
|
65
|
+
end
|
66
|
+
|
67
|
+
@params.update(Gecode::Util.decode_options(options))
|
68
|
+
@params.update(:rhs => int_enum)
|
69
|
+
@model.add_constraint Channel::ChannelConstraint.new(@model, @params)
|
70
|
+
end
|
71
|
+
|
72
|
+
# Provides commutativity with SetEnumConstraintReceiver#channel .
|
73
|
+
provide_commutativity(:channel){ |rhs, _| rhs.respond_to? :to_set_enum }
|
74
|
+
end
|
75
|
+
|
76
|
+
# A module that gathers the classes and modules used in channel constraints.
|
77
|
+
module Channel #:nodoc:
|
78
|
+
class ChannelConstraint < Gecode::Constraint #:nodoc:
|
81
79
|
def post
|
82
80
|
lhs, rhs = @params.values_at(:lhs, :rhs)
|
83
|
-
Gecode::Raw::channel(@model.active_space, lhs.
|
84
|
-
rhs.
|
81
|
+
Gecode::Raw::channel(@model.active_space, lhs.to_int_enum.bind_array,
|
82
|
+
rhs.to_int_enum.bind_array, *propagation_options)
|
85
83
|
end
|
86
84
|
end
|
87
85
|
end
|
88
|
-
end
|
86
|
+
end
|
@@ -1,91 +1,66 @@
|
|
1
|
-
module Gecode
|
2
|
-
module
|
3
|
-
#
|
4
|
-
#
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
1
|
+
module Gecode::IntEnum
|
2
|
+
module IntEnumOperand
|
3
|
+
# Produces a new IntOperand representing the number of times
|
4
|
+
# +int_operand_or_fixnum+ is present in this enumeration.
|
5
|
+
#
|
6
|
+
# ==== Examples
|
7
|
+
#
|
8
|
+
# # The number of times 17 occurs in +int_enum+.
|
9
|
+
# int_enum.count(17)
|
10
|
+
#
|
11
|
+
# # The number of times +int_operand+ occurs in +int_enum+.
|
12
|
+
# int_enum.count(int_operand)
|
13
|
+
def count(int_operand_or_fixnum)
|
14
|
+
unless int_operand_or_fixnum.respond_to? :to_int_var or
|
15
|
+
int_operand_or_fixnum.kind_of?(Fixnum)
|
16
|
+
raise TypeError, 'Expected integer operand of fixnum, got ' +
|
17
|
+
"#{int_operand_or_fixnum.class}."
|
13
18
|
end
|
19
|
+
Count::IntEnumCountOperand.new(@model, self, int_operand_or_fixnum)
|
14
20
|
end
|
15
21
|
end
|
16
|
-
end
|
17
22
|
|
18
|
-
# A module that gathers the classes and modules used in count constraints.
|
19
|
-
module
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
23
|
+
# A module that gathers the classes and modules used in count constraints.
|
24
|
+
module Count #:nodoc:
|
25
|
+
class IntEnumCountOperand < Gecode::Int::ShortCircuitRelationsOperand #:nodoc:
|
26
|
+
def initialize(model, int_enum, element)
|
27
|
+
super model
|
28
|
+
@enum = int_enum
|
29
|
+
@element = element
|
30
|
+
end
|
31
|
+
|
32
|
+
def relation_constraint(relation, int_operand_or_fix, params)
|
33
|
+
unless params[:negate]
|
34
|
+
relation_type =
|
35
|
+
Gecode::Util::RELATION_TYPES[relation]
|
36
|
+
else
|
37
|
+
relation_type =
|
38
|
+
Gecode::Util::NEGATED_RELATION_TYPES[relation]
|
39
|
+
end
|
40
|
+
|
41
|
+
params.update(:enum => @enum, :element => @element,
|
42
|
+
:rhs => int_operand_or_fix, :relation_type => relation_type)
|
43
|
+
CountConstraint.new(@model, params)
|
28
44
|
end
|
29
45
|
end
|
30
46
|
|
31
|
-
Gecode::
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
expression.kind_of?(Gecode::FreeIntVar)
|
36
|
-
raise TypeError, 'Invalid right hand side of count constraint: ' +
|
37
|
-
"\#{expression.class}."
|
38
|
-
end
|
47
|
+
class CountConstraint < Gecode::ReifiableConstraint #:nodoc:
|
48
|
+
def post
|
49
|
+
enum, element, relation_type, rhs =
|
50
|
+
@params.values_at(:enum, :element, :relation_type, :rhs)
|
39
51
|
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
@model.add_constraint CountConstraint.new(@model, @params)
|
52
|
+
# Bind variables if needed.
|
53
|
+
unless element.kind_of? Fixnum
|
54
|
+
element = element.to_int_var.bind
|
44
55
|
end
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
# (constant or a variable) may occurr in an enumeration of integer variable.
|
52
|
-
#
|
53
|
-
# All relations available for +SimpleRelationConstraint+ can be used with
|
54
|
-
# count constraints. Negation and reification is supported.
|
55
|
-
#
|
56
|
-
# == Examples
|
57
|
-
#
|
58
|
-
# # Constrain +int_enum+ to not contain 0 exactly once.
|
59
|
-
# int_enum.count(0).must_not == 1
|
60
|
-
#
|
61
|
-
# # Constrain +int_enum+ to contain +x+ exactly +x_count+ times.
|
62
|
-
# int_enum.count(x).must == x_count
|
63
|
-
#
|
64
|
-
# # Reifies the constraint that +int_enum+ has +x+ zeros with the boolean
|
65
|
-
# # variable +has_x_zeros+ and selects the strength +domain+.
|
66
|
-
# int_enum.count(0).must.equal(x, :reify => has_x_zeros,
|
67
|
-
# :strength => :domain)
|
68
|
-
class CountConstraint < Gecode::Constraints::ReifiableConstraint
|
69
|
-
def post
|
70
|
-
lhs, element, relation_type, rhs, reif_var =
|
71
|
-
@params.values_at(:lhs, :element, :relation_type, :rhs, :reif)
|
72
|
-
|
73
|
-
# Bind variables if needed.
|
74
|
-
element = element.bind if element.respond_to? :bind
|
75
|
-
rhs = rhs.bind if rhs.respond_to? :bind
|
76
|
-
|
77
|
-
# Post the constraint to gecode.
|
78
|
-
if reif_var.nil?
|
79
|
-
Gecode::Raw::count(@model.active_space, lhs.to_int_var_array,
|
56
|
+
unless rhs.kind_of? Fixnum
|
57
|
+
rhs = rhs.to_int_var.bind
|
58
|
+
end
|
59
|
+
|
60
|
+
# Post the constraint to gecode.
|
61
|
+
Gecode::Raw::count(@model.active_space, enum.to_int_enum.bind_array,
|
80
62
|
element, relation_type, rhs, *propagation_options)
|
81
|
-
else
|
82
|
-
# We use a proxy int variable to get the reification.
|
83
|
-
proxy = @model.int_var(rhs.min..rhs.max)
|
84
|
-
rel = Gecode::Constraints::Util::RELATION_TYPES.invert[relation_type]
|
85
|
-
proxy.must.send(rel, @params[:rhs], :reify => reif_var)
|
86
|
-
Gecode::Raw::count(@model.active_space, lhs.to_int_var_array,
|
87
|
-
element, Gecode::Raw::IRT_EQ, proxy.bind, *propagation_options)
|
88
63
|
end
|
89
64
|
end
|
90
65
|
end
|
91
|
-
end
|
66
|
+
end
|