gecoder 0.8.2 → 0.8.3
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 +14 -0
- data/ext/gecoder.cpp +181 -0
- data/ext/gecoder.h +94 -0
- data/ext/vararray.cpp +3 -3
- data/lib/gecoder/bindings/bindings.rb +104 -46
- data/lib/gecoder/interface/binding_changes.rb +1 -301
- data/lib/gecoder/interface/branch.rb +15 -11
- data/lib/gecoder/interface/constraints/bool/boolean.rb +56 -52
- data/lib/gecoder/interface/constraints/bool/channel.rb +1 -16
- data/lib/gecoder/interface/constraints/bool_enum/channel.rb +13 -8
- data/lib/gecoder/interface/constraints/bool_enum/extensional.rb +48 -0
- data/lib/gecoder/interface/constraints/extensional_regexp.rb +101 -0
- data/lib/gecoder/interface/constraints/int/channel.rb +1 -13
- data/lib/gecoder/interface/constraints/int_enum/channel.rb +15 -35
- data/lib/gecoder/interface/constraints/int_enum/extensional.rb +130 -0
- data/lib/gecoder/interface/constraints/set/channel.rb +54 -0
- data/lib/gecoder/interface/constraints/set_enum/channel.rb +37 -6
- data/lib/gecoder/interface/constraints/set_var_constraints.rb +1 -0
- data/lib/gecoder/interface/constraints.rb +38 -0
- data/lib/gecoder/interface/model.rb +110 -85
- data/lib/gecoder/interface/variables.rb +3 -21
- data/lib/gecoder/version.rb +1 -1
- data/specs/branch.rb +16 -1
- data/specs/constraints/bool_enum_relation.rb +6 -6
- data/specs/constraints/boolean.rb +31 -25
- data/specs/constraints/channel.rb +102 -4
- data/specs/constraints/extensional.rb +185 -2
- data/specs/constraints/reification_sugar.rb +2 -46
- data/specs/model.rb +85 -7
- data/tasks/dependencies.txt +1 -0
- data/vendor/rust/rust/class.rb +33 -35
- data/vendor/rust/rust/templates/ClassDeclarations.rusttpl +1 -1
- data/vendor/rust/rust/templates/CxxClassDefinitions.rusttpl +10 -1
- metadata +185 -184
- data/example/raw_bindings.rb +0 -44
- data/ext/missing.cpp +0 -328
- data/ext/missing.h +0 -120
- data/specs/binding_changes.rb +0 -76
@@ -0,0 +1,101 @@
|
|
1
|
+
module Gecode
|
2
|
+
class Model
|
3
|
+
# Specifies an integer regexp that matches +regexp+ repeated between
|
4
|
+
# +at_least+ and +at_most+ times (inclusive). If +at_most+ is
|
5
|
+
# omitted then no upper bound is placed. If both +at_least+ and
|
6
|
+
# +at_most+ are omitted then no bounds are placed.
|
7
|
+
#
|
8
|
+
# See Constraints::IntEnum::Extensional::RegexpConstraint for the
|
9
|
+
# allowed syntax of +regexp+.
|
10
|
+
def repeat(regexp, at_least = nil, at_most = nil)
|
11
|
+
unless at_least.nil? or at_least.kind_of? Fixnum
|
12
|
+
raise TypeError,
|
13
|
+
"Expected the at_least argument to be a Fixnum, got #{at_least.class}"
|
14
|
+
end
|
15
|
+
unless at_most.nil? or at_most.kind_of?(Fixnum)
|
16
|
+
raise TypeError,
|
17
|
+
"Expected the at_most argument to be a Fixnum, got #{at_most.class}"
|
18
|
+
end
|
19
|
+
|
20
|
+
reg = Constraints::Util::Extensional.parse_regexp regexp
|
21
|
+
if at_most.nil?
|
22
|
+
if at_least.nil?
|
23
|
+
reg.send '*'
|
24
|
+
else
|
25
|
+
reg.send('()', at_least)
|
26
|
+
end
|
27
|
+
else
|
28
|
+
reg.send('()', at_least, at_most)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
# Matches +regexp+ repeated zero or one time (i.e. like '?' in normal
|
33
|
+
# regexps). Produces the same result as calling
|
34
|
+
#
|
35
|
+
# repeat(regexp, 0, 1)
|
36
|
+
def at_most_once(regexp)
|
37
|
+
repeat(regexp, 0, 1)
|
38
|
+
end
|
39
|
+
|
40
|
+
# Matches +regexp+ repeated at least one time (i.e. like '+' in normal
|
41
|
+
# regexps). Produces the same result as calling
|
42
|
+
#
|
43
|
+
# repeat(regexp, 1)
|
44
|
+
def at_least_once(regexp)
|
45
|
+
repeat(regexp, 1)
|
46
|
+
end
|
47
|
+
|
48
|
+
# Matches any of the specified +regexps+.
|
49
|
+
def any(*regexps)
|
50
|
+
regexps.inject(Gecode::Raw::REG.new) do |result, regexp|
|
51
|
+
result | Constraints::Util::Extensional.parse_regexp(regexp)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
module Constraints::Util::Extensional
|
57
|
+
module_function
|
58
|
+
|
59
|
+
# Parses a regular expression over the integer domain, returning
|
60
|
+
# an instance of Gecode::REG .
|
61
|
+
#
|
62
|
+
# Pseudo-BNF of the integer regexp representation:
|
63
|
+
# regexp ::= <Fixnum> | <TrueClass> | <FalseClass> | <Gecode::Raw::REG>
|
64
|
+
# | [<regexp>, ...]
|
65
|
+
def parse_regexp(regexp)
|
66
|
+
# Check the involved types.
|
67
|
+
unless regexp.kind_of? Enumerable
|
68
|
+
regexp = [regexp]
|
69
|
+
end
|
70
|
+
regexp.to_a.flatten.each do |element|
|
71
|
+
unless element.kind_of?(Fixnum) or element.kind_of?(Gecode::Raw::REG) or
|
72
|
+
element.kind_of?(TrueClass) or element.kind_of?(FalseClass)
|
73
|
+
raise TypeError,
|
74
|
+
"Can't translate #{element.class} into integer or boolean regexp."
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
# Convert it into a regexp.
|
79
|
+
internal_parse_regexp(regexp)
|
80
|
+
end
|
81
|
+
|
82
|
+
private
|
83
|
+
|
84
|
+
# Recursively converts arg into an instance of Gecode::REG. It is
|
85
|
+
# assumed that arg is of kind Gecode::Raw::REG, Fixnum, TrueClass,
|
86
|
+
# FalseClass or Enumerable.
|
87
|
+
def self.internal_parse_regexp(arg)
|
88
|
+
case arg
|
89
|
+
when Gecode::Raw::REG: arg
|
90
|
+
when Fixnum: Gecode::Raw::REG.new(arg)
|
91
|
+
when TrueClass: Gecode::Raw::REG.new(1)
|
92
|
+
when FalseClass: Gecode::Raw::REG.new(0)
|
93
|
+
when Enumerable
|
94
|
+
# Recursively convert the elements of the arg.
|
95
|
+
arg.inject(Gecode::Raw::REG.new) do |regexp, element|
|
96
|
+
regexp += internal_parse_regexp(element)
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
@@ -35,19 +35,7 @@ module Gecode::Constraints::Int
|
|
35
35
|
# set to k then the integer variable takes value i+k exactly
|
36
36
|
# when the variable at index i in the boolean enumration is true
|
37
37
|
# and the rest are false.
|
38
|
-
|
39
|
-
unless bool_enum.respond_to? :to_bool_var_array
|
40
|
-
raise TypeError, 'Expected an enumration of boolean variables, got ' +
|
41
|
-
"#{bool_enum.class}."
|
42
|
-
end
|
43
|
-
|
44
|
-
# Just provide commutivity with the boolean enum channel constraint.
|
45
|
-
if @params[:negate]
|
46
|
-
bool_enum.must_not.channel(@params[:lhs], options)
|
47
|
-
else
|
48
|
-
bool_enum.must.channel(@params[:lhs], options)
|
49
|
-
end
|
50
|
-
end
|
38
|
+
provide_commutivity(:channel){ |rhs, _| rhs.respond_to? :to_bool_var_array }
|
51
39
|
end
|
52
40
|
|
53
41
|
# A module that gathers the classes and modules used in channel constraints
|
@@ -7,23 +7,20 @@ module Gecode::Constraints::IntEnum
|
|
7
7
|
raise Gecode::MissingConstraintError, 'A negated channel constraint ' +
|
8
8
|
'is not implemented.'
|
9
9
|
end
|
10
|
-
unless enum.respond_to?(:to_int_var_array)
|
11
|
-
|
12
|
-
raise TypeError, "Expected int or set enum, got #{enum.class}."
|
10
|
+
unless enum.respond_to?(:to_int_var_array)
|
11
|
+
raise TypeError, "Expected int enum, got #{enum.class}."
|
13
12
|
end
|
14
|
-
if
|
15
|
-
|
16
|
-
|
17
|
-
'reification option.'
|
18
|
-
end
|
19
|
-
@params.update(Gecode::Constraints::Set::Util.decode_options(options))
|
20
|
-
else
|
21
|
-
@params.update(Gecode::Constraints::Util.decode_options(options))
|
13
|
+
if options.has_key? :reify
|
14
|
+
raise ArgumentError, 'The channel constraints does not support the ' +
|
15
|
+
'reification option.'
|
22
16
|
end
|
23
17
|
|
18
|
+
@params.update(Gecode::Constraints::Util.decode_options(options))
|
24
19
|
@params.update(:rhs => enum)
|
25
20
|
@model.add_constraint Channel::ChannelConstraint.new(@model, @params)
|
26
21
|
end
|
22
|
+
|
23
|
+
provide_commutivity(:channel){ |rhs, _| rhs.respond_to? :to_set_var_array }
|
27
24
|
end
|
28
25
|
|
29
26
|
# A module that gathers the classes and modules used in channel constraints.
|
@@ -33,14 +30,12 @@ module Gecode::Constraints::IntEnum
|
|
33
30
|
# enumeration of set variables. Channel constraints are used to give
|
34
31
|
# access to multiple viewpoints when modelling.
|
35
32
|
#
|
36
|
-
#
|
37
|
-
#
|
38
|
-
#
|
39
|
-
#
|
33
|
+
# The channel constraint can be thought of as constraining the arrays to
|
34
|
+
# be each other's inverses. I.e. if the i:th value in the first enumeration
|
35
|
+
# is j, then the j:th value in the second enumeration is constrained to be
|
36
|
+
# i.
|
40
37
|
#
|
41
|
-
# Neither reification nor negation is supported.
|
42
|
-
# supported when using the constraint between two integer enumerations,
|
43
|
-
# it's not supported when a set enumeration is used.
|
38
|
+
# Neither reification nor negation is supported.
|
44
39
|
#
|
45
40
|
# == Example
|
46
41
|
#
|
@@ -82,26 +77,11 @@ module Gecode::Constraints::IntEnum
|
|
82
77
|
#
|
83
78
|
# elements.must.channel positions
|
84
79
|
#
|
85
|
-
# == Example (sets)
|
86
|
-
#
|
87
|
-
# # +set_enum+ is constrained to channel +int_enum+.
|
88
|
-
# int_enum.must.channel set_enum
|
89
|
-
#
|
90
|
-
# # This is another way of saying the above.
|
91
|
-
# set_enum.must.channel int_enum
|
92
80
|
class ChannelConstraint < Gecode::Constraints::Constraint
|
93
81
|
def post
|
94
82
|
lhs, rhs = @params.values_at(:lhs, :rhs)
|
95
|
-
|
96
|
-
|
97
|
-
if rhs.respond_to? :to_int_var_array
|
98
|
-
# Int var array.
|
99
|
-
Gecode::Raw::channel(@model.active_space, lhs, rhs.to_int_var_array,
|
100
|
-
*propagation_options)
|
101
|
-
else
|
102
|
-
# Set var array, no propagation options.
|
103
|
-
Gecode::Raw::channel(@model.active_space, lhs, rhs.to_set_var_array)
|
104
|
-
end
|
83
|
+
Gecode::Raw::channel(@model.active_space, lhs.to_int_var_array,
|
84
|
+
rhs.to_int_var_array, *propagation_options)
|
105
85
|
end
|
106
86
|
end
|
107
87
|
end
|
@@ -26,6 +26,27 @@ module Gecode::Constraints::IntEnum
|
|
26
26
|
@model.add_constraint Extensional::TupleConstraint.new(@model,
|
27
27
|
@params.update(util.decode_options(options)))
|
28
28
|
end
|
29
|
+
|
30
|
+
# Adds a constraint that forces the enumeration to match the
|
31
|
+
# specified regular expression over the integer domain. The regular
|
32
|
+
# expression is expressed using arrays and integers. See
|
33
|
+
# IntEnum::Extensional::RegexpConstraint for more information and examples of
|
34
|
+
# such regexps.
|
35
|
+
def match(regexp, options = {})
|
36
|
+
if @params[:negate]
|
37
|
+
raise Gecode::MissingConstraintError, 'A negated regexp constraint ' +
|
38
|
+
'is not implemented.'
|
39
|
+
end
|
40
|
+
unless options[:reify].nil?
|
41
|
+
raise ArgumentError, 'Reification is not supported by the regexp ' +
|
42
|
+
'constraint.'
|
43
|
+
end
|
44
|
+
|
45
|
+
@params[:regexp] =
|
46
|
+
Gecode::Constraints::Util::Extensional.parse_regexp regexp
|
47
|
+
@params.update Gecode::Constraints::Util.decode_options(options)
|
48
|
+
@model.add_constraint Extensional::RegexpConstraint.new(@model, @params)
|
49
|
+
end
|
29
50
|
end
|
30
51
|
|
31
52
|
# A module that gathers the classes and modules used in extensional
|
@@ -60,5 +81,114 @@ module Gecode::Constraints::IntEnum
|
|
60
81
|
*propagation_options)
|
61
82
|
end
|
62
83
|
end
|
84
|
+
|
85
|
+
# Describes a regexp constraint, which constrains the enumeration of
|
86
|
+
# integer variables to match a specified regexp in the integer
|
87
|
+
# domain. Neither negation nor reification is supported.
|
88
|
+
#
|
89
|
+
# == Regexp syntax
|
90
|
+
#
|
91
|
+
# The regular expressions are specified using arrays, integers and a
|
92
|
+
# few methods provided by Model. Arrays are used to group the
|
93
|
+
# integers in sequences that must be matched. The following array
|
94
|
+
# describes a regular expression matching a 1 followed by a 7.
|
95
|
+
#
|
96
|
+
# [1, 7]
|
97
|
+
#
|
98
|
+
# Arrays can be nested or left out when not needed. I.e. the above
|
99
|
+
# is semantically equal to
|
100
|
+
#
|
101
|
+
# [[[1], 7]]
|
102
|
+
#
|
103
|
+
# A couple of methods provided by Model are used to express patterns
|
104
|
+
# beyond mere sequences:
|
105
|
+
#
|
106
|
+
# [Model#repeat] Used for specifying patterns that include patterns
|
107
|
+
# that may be repeated a given number of times. The
|
108
|
+
# number of times to repeat a pattern can be specified
|
109
|
+
# using a lower and upper bound, but the bounds can be
|
110
|
+
# omitted to for instance allow an expression to be
|
111
|
+
# repeated any number of times.
|
112
|
+
# [Model#any] Used for specifying alternatives.
|
113
|
+
#
|
114
|
+
# Additionally Model#at_least_once and Model#at_most_once are
|
115
|
+
# provided as convenience methods.
|
116
|
+
#
|
117
|
+
# === Examples
|
118
|
+
#
|
119
|
+
# # Matches 1 followed by any number of 2s.
|
120
|
+
# [1, repeat(2)]
|
121
|
+
#
|
122
|
+
# # Semantically the same as above. It just has a bunch of
|
123
|
+
# # needless brackets thrown in.
|
124
|
+
# [[1], [repeat([2])]]
|
125
|
+
#
|
126
|
+
# # Matches 1 followed by [a 2 followed by a 3] at least two times.
|
127
|
+
# # Matches e.g. 1, 2, 3, 2, 3
|
128
|
+
# [1, repeat([2, 3], 2)]
|
129
|
+
#
|
130
|
+
# # Matches between one and two [2 followed by [at least three 1]]
|
131
|
+
# # followed by between three and four 3. Matches e.g.
|
132
|
+
# # 2, 1, 1, 1, 2, 1, 1, 1, 3, 3, 3
|
133
|
+
# [repeat([2, repeat(1, 3], 1, 2), repeat(3, 3, 4)]
|
134
|
+
#
|
135
|
+
# # Matches [1, 2 or 3] followed by 4. Matches e.g. 2, 4
|
136
|
+
# [any(1, 2, 3), 4]
|
137
|
+
#
|
138
|
+
# # Matches 0 followed by [[1 followed by 2] or [3 followed by 5]].
|
139
|
+
# # Matches e.g. 0, 1, 2 as well as 0, 3, 5
|
140
|
+
# [0, any([1, 2], [3, 5])]
|
141
|
+
#
|
142
|
+
# # Matches 0 followed by [[[1 followed by 7] at least two times]
|
143
|
+
# # or [[8, 9], at most two times]. Matches e.g.
|
144
|
+
# # 0, 1, 7, 1, 7, 1, 7 as well as 0, 8, 9
|
145
|
+
# [0, any(repeat([1, 7], 2), repeat([8, 9], 0, 2)]
|
146
|
+
#
|
147
|
+
# # Matches 0 followed by at least one 1.
|
148
|
+
# [0, at_least_once(1)]
|
149
|
+
#
|
150
|
+
# # Exactly the same as the above.
|
151
|
+
# [0, repeat(1, 1)]
|
152
|
+
#
|
153
|
+
# # Matches 0 followed by at least one [[1 followed by 7] or [3
|
154
|
+
# # followed by 2]]. Matches e.g. 0, 1, 7, 3, 2, 1, 7
|
155
|
+
# [0, at_least_once(any([1, 7], [3, 2]]
|
156
|
+
#
|
157
|
+
# # Matches 0 followed by at either [[1 followed by 7] at least once]
|
158
|
+
# # or [[3 followed by 2] at least once]. Matches e.g.
|
159
|
+
# # 0, 1, 7, 1, 7 but does _not_ match 0, 1, 7, 3, 2, 1, 7
|
160
|
+
# [0, any(at_least_once([1, 7]), at_least_once([3, 2])]
|
161
|
+
#
|
162
|
+
# # Matches 0, followed by at most one 1. Matches 0 as well as
|
163
|
+
# # 0, 1
|
164
|
+
# [0, at_most_once(1)]
|
165
|
+
#
|
166
|
+
# # Exactly the same as the above.
|
167
|
+
# [0, repeat(1, 0, 1)]
|
168
|
+
#
|
169
|
+
# == Example
|
170
|
+
#
|
171
|
+
# # Constrains the two integer variables in +numbers+ to have
|
172
|
+
# # values 1 and 7.
|
173
|
+
# numbers.must.match [1, 7]
|
174
|
+
#
|
175
|
+
# # Constrains the integer variables in +numbers+ to contain the
|
176
|
+
# # value 47 followed by 11, with all other values set to -1.
|
177
|
+
# numbers.must.match [repeat(-1), 47, 11, repeat(-1)]
|
178
|
+
#
|
179
|
+
# # Constrains exactly three of the integer variables in +numbers+ to
|
180
|
+
# # contain 47 or 11, each followed by at least two
|
181
|
+
# # variables set to -1. All other variables are constrained to
|
182
|
+
# # equal -1.
|
183
|
+
# numbers.must.match repeat([repeat(-1), any(11, 47),
|
184
|
+
# repeat(-1, 2)], 3, 3)
|
185
|
+
#
|
186
|
+
class RegexpConstraint < Gecode::Constraints::Constraint
|
187
|
+
def post
|
188
|
+
lhs, regexp = @params.values_at(:lhs, :regexp)
|
189
|
+
Gecode::Raw::extensional(@model.active_space, lhs.to_int_var_array,
|
190
|
+
regexp, *propagation_options)
|
191
|
+
end
|
192
|
+
end
|
63
193
|
end
|
64
194
|
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
module Gecode::Constraints::Set
|
2
|
+
class Expression
|
3
|
+
# Adds a channel constraint on the set variable with the specified enum of
|
4
|
+
# boolean variables.
|
5
|
+
def channel(bool_enum, options = {})
|
6
|
+
if @params[:negate]
|
7
|
+
raise Gecode::MissingConstraintError, 'A negated channel constraint ' +
|
8
|
+
'is not implemented.'
|
9
|
+
end
|
10
|
+
if options.has_key? :reify
|
11
|
+
raise ArgumentError, 'The channel constraint does not support the ' +
|
12
|
+
'reification option.'
|
13
|
+
end
|
14
|
+
unless bool_enum.respond_to? :to_bool_var_array
|
15
|
+
raise TypeError, 'Expected an enum of bool variables, ' +
|
16
|
+
"got #{bool_enum.class}."
|
17
|
+
end
|
18
|
+
|
19
|
+
@params.update(:rhs => bool_enum)
|
20
|
+
@params.update Gecode::Constraints::Set::Util.decode_options(options)
|
21
|
+
@model.add_constraint Channel::ChannelConstraint.new(@model, @params)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
# A module that gathers the classes and modules used in channel constraints
|
26
|
+
# involving one set variable and a boolean enum.
|
27
|
+
module Channel #:nodoc:
|
28
|
+
# Describes a channel constraint that "channels" a set variable and an
|
29
|
+
# enumerations of boolean variables. This constrains the set variable to
|
30
|
+
# include value i exactly when the variable at index i in the boolean
|
31
|
+
# enumeration is true.
|
32
|
+
#
|
33
|
+
# Neither reification nor negation is supported. The boolean enum and set
|
34
|
+
# can be interchanged.
|
35
|
+
#
|
36
|
+
# == Examples
|
37
|
+
#
|
38
|
+
# # Constrains the enumeration of boolean variables called +bools+ to at
|
39
|
+
# # least have the first and third variables set to true
|
40
|
+
# set.must_be.superset_of [0, 2]
|
41
|
+
# set.must.channel bools
|
42
|
+
#
|
43
|
+
# # An alternative way of writing the above.
|
44
|
+
# set.must_be.superset_of [0, 2]
|
45
|
+
# bools.must.channel set
|
46
|
+
class ChannelConstraint < Gecode::Constraints::Constraint
|
47
|
+
def post
|
48
|
+
lhs, rhs = @params.values_at(:lhs, :rhs)
|
49
|
+
Gecode::Raw::channel(@model.active_space, rhs.to_bool_var_array,
|
50
|
+
lhs.bind)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -2,16 +2,47 @@ module Gecode::Constraints::SetEnum
|
|
2
2
|
class Expression
|
3
3
|
# Posts a channel constraint on the variables in the enum with the specified
|
4
4
|
# int enum.
|
5
|
-
def channel(enum)
|
5
|
+
def channel(enum, options = {})
|
6
6
|
unless enum.respond_to? :to_int_var_array
|
7
7
|
raise TypeError, "Expected integer variable enum, for #{enum.class}."
|
8
8
|
end
|
9
|
-
|
10
|
-
# Just provide commutativity to the corresponding int enum constraint.
|
11
9
|
if @params[:negate]
|
12
|
-
|
13
|
-
|
14
|
-
|
10
|
+
raise Gecode::MissingConstraintError, 'A negated channel constraint ' +
|
11
|
+
'is not implemented.'
|
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::Set::Util.decode_options(options))
|
19
|
+
@params.update(:rhs => enum)
|
20
|
+
@model.add_constraint Channel::IntChannelConstraint.new(@model, @params)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
# A module that gathers the classes and modules used in channel constraints.
|
25
|
+
module Channel #:nodoc:
|
26
|
+
# Describes a channel constraint which "channels" one enumeration of
|
27
|
+
# integer variables with one enumeration of set variables. The i:th set
|
28
|
+
# in the enumeration of set variables is constrainde to includes the value
|
29
|
+
# of the j:th integer variable.
|
30
|
+
#
|
31
|
+
# Neither reification nor negation is supported.
|
32
|
+
#
|
33
|
+
# == Examples
|
34
|
+
#
|
35
|
+
# # +set_enum+ is constrained to channel +int_enum+.
|
36
|
+
# int_enum.must.channel set_enum
|
37
|
+
#
|
38
|
+
# # This is another way of saying the above.
|
39
|
+
# set_enum.must.channel int_enum
|
40
|
+
#
|
41
|
+
class IntChannelConstraint < Gecode::Constraints::Constraint
|
42
|
+
def post
|
43
|
+
lhs, rhs = @params.values_at(:lhs, :rhs)
|
44
|
+
Gecode::Raw::channel(@model.active_space, rhs.to_int_var_array,
|
45
|
+
lhs.to_set_var_array)
|
15
46
|
end
|
16
47
|
end
|
17
48
|
end
|
@@ -75,3 +75,4 @@ require 'gecoder/interface/constraints/set/relation'
|
|
75
75
|
require 'gecoder/interface/constraints/set/cardinality'
|
76
76
|
require 'gecoder/interface/constraints/set/connection'
|
77
77
|
require 'gecoder/interface/constraints/set/operation'
|
78
|
+
require 'gecoder/interface/constraints/set/channel'
|
@@ -271,6 +271,43 @@ module Gecode
|
|
271
271
|
|
272
272
|
private
|
273
273
|
|
274
|
+
# Provides commutivity for the constraint with the specified method name.
|
275
|
+
# If the method with the specified method name is called with something
|
276
|
+
# that, when given to the block, evaluates to true, then the constraint
|
277
|
+
# will be called on the right hand side with the left hand side as
|
278
|
+
# argument.
|
279
|
+
#
|
280
|
+
# The original constraint method is assumed to take two arguments: a
|
281
|
+
# right hand side and a hash of options.
|
282
|
+
def self.provide_commutivity(constraint_name, &block)
|
283
|
+
unique_id = constraint_name.to_sym.to_i
|
284
|
+
pre_alias_method_name = 'pre_commutivity_' << unique_id.to_s
|
285
|
+
if method_defined? constraint_name
|
286
|
+
alias_method pre_alias_method_name, constraint_name
|
287
|
+
end
|
288
|
+
|
289
|
+
module_eval <<-end_code
|
290
|
+
@@commutivity_check_#{unique_id} = block
|
291
|
+
def #{constraint_name}(rhs, options = {})
|
292
|
+
if @@commutivity_check_#{unique_id}.call(rhs, options)
|
293
|
+
if @params[:negate]
|
294
|
+
rhs.must_not.method(:#{constraint_name}).call(
|
295
|
+
@params[:lhs], options)
|
296
|
+
else
|
297
|
+
rhs.must.method(:#{constraint_name}).call(
|
298
|
+
@params[:lhs], options)
|
299
|
+
end
|
300
|
+
else
|
301
|
+
if self.class.method_defined? :#{pre_alias_method_name}
|
302
|
+
#{pre_alias_method_name}(rhs, options)
|
303
|
+
else
|
304
|
+
raise TypeError, \"Unexpected argument type \#{rhs.class}.\"
|
305
|
+
end
|
306
|
+
end
|
307
|
+
end
|
308
|
+
end_code
|
309
|
+
end
|
310
|
+
|
274
311
|
# Creates aliases for any defined comparison methods.
|
275
312
|
def self.alias_comparison_methods
|
276
313
|
Gecode::Constraints::Util::COMPARISON_ALIASES.each_pair do |orig, aliases|
|
@@ -472,3 +509,4 @@ require 'gecoder/interface/constraints/bool_var_constraints'
|
|
472
509
|
require 'gecoder/interface/constraints/bool_enum_constraints'
|
473
510
|
require 'gecoder/interface/constraints/set_var_constraints'
|
474
511
|
require 'gecoder/interface/constraints/set_enum_constraints'
|
512
|
+
require 'gecoder/interface/constraints/extensional_regexp'
|