gecoder-with-gecode 0.8.2-mswin32 → 0.8.3-mswin32
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/lib/gecode.dll +0 -0
- 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.rb +38 -0
- 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/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 +186 -185
- data/example/raw_bindings.rb +0 -44
- data/specs/binding_changes.rb +0 -76
@@ -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'
|
@@ -1,117 +1,109 @@
|
|
1
1
|
module Gecode
|
2
2
|
# Model is the base class that all models must inherit from.
|
3
3
|
class Model
|
4
|
+
# The largest integer allowed in the domain of an integer variable.
|
5
|
+
MAX_INT = Gecode::Raw::IntLimits::MAX
|
6
|
+
# The smallest integer allowed in the domain of an integer variable.
|
7
|
+
MIN_INT = Gecode::Raw::IntLimits::MIN
|
8
|
+
|
9
|
+
# The largest integer allowed in the domain of a set variable.
|
10
|
+
SET_MAX_INT = Gecode::Raw::SetLimits::MAX
|
11
|
+
# The smallest integer allowed in the domain of a set variable.
|
12
|
+
SET_MIN_INT = Gecode::Raw::SetLimits::MIN
|
13
|
+
|
14
|
+
# The largest possible domain for an integer variable.
|
15
|
+
LARGEST_INT_DOMAIN = MIN_INT..MAX_INT
|
16
|
+
# The largest possible domain, without negative integers, for an
|
17
|
+
# integer variable.
|
18
|
+
NON_NEGATIVE_INT_DOMAIN = 0..MAX_INT
|
19
|
+
|
20
|
+
# The largest possible bound for a set variable.
|
21
|
+
LARGEST_SET_BOUND = SET_MIN_INT..SET_MAX_INT
|
22
|
+
|
4
23
|
# Creates a new integer variable with the specified domain. The domain can
|
5
24
|
# either be a range, a single element, or an enumeration of elements. If no
|
6
25
|
# domain is specified then the largest possible domain is used.
|
7
|
-
def int_var(domain =
|
8
|
-
|
9
|
-
|
10
|
-
index = variable_creation_space.new_int_vars(enum).first
|
11
|
-
FreeIntVar.new(self, index)
|
26
|
+
def int_var(domain = LARGEST_INT_DOMAIN)
|
27
|
+
args = domain_arguments(domain)
|
28
|
+
FreeIntVar.new(self, variable_creation_space.new_int_var(*args))
|
12
29
|
end
|
13
30
|
|
14
31
|
# Creates an array containing the specified number of integer variables
|
15
32
|
# with the specified domain. The domain can either be a range, a single
|
16
|
-
# element, or an enumeration of elements.
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
33
|
+
# element, or an enumeration of elements. If no domain is specified then
|
34
|
+
# the largest possible domain is used.
|
35
|
+
def int_var_array(count, domain = LARGEST_INT_DOMAIN)
|
36
|
+
args = domain_arguments(domain)
|
37
|
+
build_var_array(count) do
|
38
|
+
FreeIntVar.new(self, variable_creation_space.new_int_var(*args))
|
22
39
|
end
|
23
|
-
return wrap_enum(variables)
|
24
40
|
end
|
25
41
|
|
26
42
|
# Creates a matrix containing the specified number rows and columns of
|
27
43
|
# integer variables with the specified domain. The domain can either be a
|
28
|
-
# range, a single element, or an enumeration of elements.
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
rows << indices[(i*col_count)...(i.succ*col_count)].map! do |index|
|
35
|
-
FreeIntVar.new(self, index)
|
36
|
-
end
|
44
|
+
# range, a single element, or an enumeration of elements. If no domain
|
45
|
+
# is specified then the largest possible domain is used.
|
46
|
+
def int_var_matrix(row_count, col_count, domain = LARGEST_INT_DOMAIN)
|
47
|
+
args = domain_arguments(domain)
|
48
|
+
build_var_matrix(row_count, col_count) do
|
49
|
+
FreeIntVar.new(self, variable_creation_space.new_int_var(*args))
|
37
50
|
end
|
38
|
-
return wrap_enum(Util::EnumMatrix.rows(rows, false))
|
39
51
|
end
|
40
52
|
|
41
53
|
# Creates a new boolean variable.
|
42
54
|
def bool_var
|
43
|
-
|
44
|
-
FreeBoolVar.new(self, index)
|
55
|
+
FreeBoolVar.new(self, variable_creation_space.new_bool_var)
|
45
56
|
end
|
46
57
|
|
47
58
|
# Creates an array containing the specified number of boolean variables.
|
48
59
|
def bool_var_array(count)
|
49
|
-
|
50
|
-
|
51
|
-
variables << FreeBoolVar.new(self, index)
|
60
|
+
build_var_array(count) do
|
61
|
+
FreeBoolVar.new(self, variable_creation_space.new_bool_var)
|
52
62
|
end
|
53
|
-
return wrap_enum(variables)
|
54
63
|
end
|
55
64
|
|
56
65
|
# Creates a matrix containing the specified number rows and columns of
|
57
66
|
# boolean variables.
|
58
67
|
def bool_var_matrix(row_count, col_count)
|
59
|
-
|
60
|
-
|
61
|
-
row_count.times do |i|
|
62
|
-
rows << indices[(i*col_count)...(i.succ*col_count)].map! do |index|
|
63
|
-
FreeBoolVar.new(self, index)
|
64
|
-
end
|
68
|
+
build_var_matrix(row_count, col_count) do
|
69
|
+
FreeBoolVar.new(self, variable_creation_space.new_bool_var)
|
65
70
|
end
|
66
|
-
return wrap_enum(Util::EnumMatrix.rows(rows, false))
|
67
71
|
end
|
68
72
|
|
69
73
|
# Creates a set variable with the specified domain for greatest lower bound
|
70
74
|
# and least upper bound (specified as either a fixnum, range or enum). If
|
71
|
-
# no bounds are specified then the empty set is used as
|
72
|
-
# and the
|
73
|
-
#
|
74
|
-
#
|
75
|
+
# no bounds are specified then the empty set is used as greatest lower
|
76
|
+
# bound and the largest possible set as least upper bound.
|
77
|
+
#
|
78
|
+
# A range for the allowed cardinality of the set can also be
|
79
|
+
# specified, if none is specified, or nil is given, then the default
|
80
|
+
# range (anything) will be used. If only a single Fixnum is
|
75
81
|
# specified as cardinality_range then it's used as lower bound.
|
76
|
-
def set_var(glb_domain = [], lub_domain =
|
77
|
-
Gecode::Raw::SetLimits::MIN..Gecode::Raw::SetLimits::MAX,
|
82
|
+
def set_var(glb_domain = [], lub_domain = LARGEST_SET_BOUND,
|
78
83
|
cardinality_range = nil)
|
79
|
-
|
80
|
-
|
81
|
-
index = variable_creation_space.new_set_vars(glb_domain, lub_domain,
|
82
|
-
to_set_cardinality_range(cardinality_range)).first
|
83
|
-
FreeSetVar.new(self, index)
|
84
|
+
args = set_bounds_to_parameters(glb_domain, lub_domain, cardinality_range)
|
85
|
+
FreeSetVar.new(self, variable_creation_space.new_set_var(*args))
|
84
86
|
end
|
85
87
|
|
86
88
|
# Creates an array containing the specified number of set variables. The
|
87
89
|
# parameters beyond count are the same as for #set_var .
|
88
|
-
def set_var_array(count, glb_domain, lub_domain
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
to_set_cardinality_range(cardinality_range), count).each do |index|
|
94
|
-
variables << FreeSetVar.new(self, index)
|
90
|
+
def set_var_array(count, glb_domain = [], lub_domain = LARGEST_SET_BOUND,
|
91
|
+
cardinality_range = nil)
|
92
|
+
args = set_bounds_to_parameters(glb_domain, lub_domain, cardinality_range)
|
93
|
+
build_var_array(count) do
|
94
|
+
FreeSetVar.new(self, variable_creation_space.new_set_var(*args))
|
95
95
|
end
|
96
|
-
return wrap_enum(variables)
|
97
96
|
end
|
98
97
|
|
99
98
|
# Creates a matrix containing the specified number of rows and columns
|
100
99
|
# filled with set variables. The parameters beyond row and column counts are
|
101
100
|
# the same as for #set_var .
|
102
|
-
def set_var_matrix(row_count, col_count, glb_domain
|
103
|
-
cardinality_range = nil)
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
to_set_cardinality_range(cardinality_range), row_count*col_count)
|
108
|
-
rows = []
|
109
|
-
row_count.times do |i|
|
110
|
-
rows << indices[(i*col_count)...(i.succ*col_count)].map! do |index|
|
111
|
-
FreeSetVar.new(self, index)
|
112
|
-
end
|
101
|
+
def set_var_matrix(row_count, col_count, glb_domain = [],
|
102
|
+
lub_domain = LARGEST_SET_BOUND, cardinality_range = nil)
|
103
|
+
args = set_bounds_to_parameters(glb_domain, lub_domain, cardinality_range)
|
104
|
+
build_var_matrix(row_count, col_count) do
|
105
|
+
FreeSetVar.new(self, variable_creation_space.new_set_var(*args))
|
113
106
|
end
|
114
|
-
return wrap_enum(Util::EnumMatrix.rows(rows, false))
|
115
107
|
end
|
116
108
|
|
117
109
|
# Retrieves the currently used space. Calling this method is only allowed
|
@@ -176,20 +168,49 @@ module Gecode
|
|
176
168
|
|
177
169
|
private
|
178
170
|
|
179
|
-
#
|
180
|
-
#
|
181
|
-
def
|
171
|
+
# Creates an array containing the specified number of variables, all
|
172
|
+
# constructed using the provided block..
|
173
|
+
def build_var_array(count, &block)
|
174
|
+
variables = []
|
175
|
+
count.times do
|
176
|
+
variables << yield
|
177
|
+
end
|
178
|
+
return wrap_enum(variables)
|
179
|
+
end
|
180
|
+
|
181
|
+
# Creates a matrix containing the specified number rows and columns of
|
182
|
+
# variables, all constructed using the provided block.
|
183
|
+
def build_var_matrix(row_count, col_count, &block)
|
184
|
+
rows = []
|
185
|
+
row_count.times do |i|
|
186
|
+
row = []
|
187
|
+
col_count.times do |j|
|
188
|
+
row << yield
|
189
|
+
end
|
190
|
+
rows << row
|
191
|
+
end
|
192
|
+
return wrap_enum(Util::EnumMatrix.rows(rows, false))
|
193
|
+
end
|
194
|
+
|
195
|
+
# Returns the array of arguments that correspond to the specified
|
196
|
+
# domain when given to Gecode. The domain can be given as a range,
|
197
|
+
# a single number, or an enumerable of elements.
|
198
|
+
def domain_arguments(domain)
|
182
199
|
if domain.respond_to?(:first) and domain.respond_to?(:last) and
|
183
200
|
domain.respond_to?(:exclude_end?)
|
184
201
|
if domain.exclude_end?
|
185
|
-
return domain.first
|
202
|
+
return [domain.first, (domain.last - 1)]
|
186
203
|
else
|
187
|
-
return domain
|
204
|
+
return [domain.first, domain.last]
|
188
205
|
end
|
189
206
|
elsif domain.kind_of? Enumerable
|
190
|
-
|
207
|
+
array = domain.to_a
|
208
|
+
return [Gecode::Raw::IntSet.new(array, array.size)]
|
209
|
+
elsif domain.kind_of? Fixnum
|
210
|
+
return [domain, domain]
|
191
211
|
else
|
192
|
-
|
212
|
+
raise TypeError, 'The domain must be given as an instance of ' +
|
213
|
+
"Enumerable or Fixnum, but #{domain.class} was given."
|
193
214
|
end
|
194
215
|
end
|
195
216
|
|
@@ -204,6 +225,21 @@ module Gecode
|
|
204
225
|
end
|
205
226
|
end
|
206
227
|
|
228
|
+
# Converts the specified set var domain to parameters accepted by
|
229
|
+
# Gecode. The bounds can be specified as a fixnum, range or # enum.
|
230
|
+
# The parameters are returned as an array.
|
231
|
+
def set_bounds_to_parameters(glb_domain, lub_domain, cardinality_range)
|
232
|
+
check_set_bounds(glb_domain, lub_domain)
|
233
|
+
args = []
|
234
|
+
args << Gecode::Constraints::Util.constant_set_to_int_set(glb_domain)
|
235
|
+
args << Gecode::Constraints::Util.constant_set_to_int_set(lub_domain)
|
236
|
+
card_range = to_set_cardinality_range(cardinality_range)
|
237
|
+
if card_range.nil?
|
238
|
+
card_range = 0..Gecode::Raw::SetLimits::CARD
|
239
|
+
end
|
240
|
+
args << card_range.first << card_range.last
|
241
|
+
end
|
242
|
+
|
207
243
|
# Checks whether the specified greatest lower bound is a subset of least
|
208
244
|
# upper bound. Raises ArgumentError if that is not the case.
|
209
245
|
def check_set_bounds(glb, lub)
|
@@ -243,15 +279,6 @@ module Gecode
|
|
243
279
|
@variable_creation_space || selected_space
|
244
280
|
end
|
245
281
|
|
246
|
-
# Refreshes all cached variables. This should be called if the variables
|
247
|
-
# in an existing space were changed.
|
248
|
-
def refresh_variables
|
249
|
-
return if @variables.nil?
|
250
|
-
@variables.each do |variable|
|
251
|
-
variable.refresh if variable.cached?
|
252
|
-
end
|
253
|
-
end
|
254
|
-
|
255
282
|
# Executes any interactions with Gecode still waiting in the queue
|
256
283
|
# (emptying the queue) in the process.
|
257
284
|
def perform_queued_gecode_interactions
|
@@ -266,8 +293,6 @@ module Gecode
|
|
266
293
|
# assigned directly.
|
267
294
|
def active_space=(new_space)
|
268
295
|
@active_space = new_space
|
269
|
-
new_space.refresh
|
270
|
-
refresh_variables
|
271
296
|
end
|
272
297
|
end
|
273
|
-
end
|
298
|
+
end
|