gecoder-with-gecode 0.8.1-mswin32 → 0.8.2-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 +10 -0
- data/lib/gecode.dll +0 -0
- data/lib/gecoder/bindings/bindings.rb +35 -0
- data/lib/gecoder/interface/constraints.rb +34 -0
- data/lib/gecoder/interface/constraints/bool/boolean.rb +7 -0
- data/lib/gecoder/interface/constraints/bool/channel.rb +23 -0
- data/lib/gecoder/interface/constraints/bool_enum/channel.rb +59 -0
- data/lib/gecoder/interface/constraints/bool_enum/extensional.rb +10 -9
- data/lib/gecoder/interface/constraints/bool_enum_constraints.rb +1 -0
- data/lib/gecoder/interface/constraints/bool_var_constraints.rb +1 -0
- data/lib/gecoder/interface/constraints/int/arithmetic.rb +78 -1
- data/lib/gecoder/interface/constraints/int/channel.rb +73 -0
- data/lib/gecoder/interface/constraints/int_enum/channel.rb +10 -2
- data/lib/gecoder/interface/constraints/int_enum/extensional.rb +12 -9
- data/lib/gecoder/interface/constraints/int_var_constraints.rb +1 -0
- data/lib/gecoder/interface/enum_wrapper.rb +3 -0
- data/lib/gecoder/interface/search.rb +34 -2
- data/lib/gecoder/version.rb +1 -1
- data/specs/constraints/arithmetic.rb +108 -41
- data/specs/constraints/boolean.rb +4 -0
- data/specs/constraints/channel.rb +235 -5
- data/specs/constraints/distinct.rb +1 -1
- data/specs/constraints/extensional.rb +46 -41
- data/specs/constraints/linear.rb +8 -0
- data/specs/enum_wrapper.rb +8 -1
- data/specs/search.rb +119 -61
- data/specs/spec_helper.rb +0 -28
- data/tasks/distribution.rake +2 -3
- metadata +10 -4
data/CHANGES
CHANGED
@@ -1,3 +1,13 @@
|
|
1
|
+
== Version 0.8.2
|
2
|
+
This release adds search statistics along with some new arithmetic constraints
|
3
|
+
and channel constraints between boolean and integer variables.
|
4
|
+
|
5
|
+
* Wrapping an enumerable that is already wrapped is no longer allowed.
|
6
|
+
* Added search statistics.
|
7
|
+
* Added squared value and square root constraints.
|
8
|
+
* Added channel constraints between single integer variables and boolean variables.
|
9
|
+
* Added channel constraints between enumerations of boolean variables and single integer variables.
|
10
|
+
|
1
11
|
== Version 0.8.1
|
2
12
|
This release adds tuple constraints along with a couple of minor features. It
|
3
13
|
also fixes a bug introduced in the previous version.
|
data/lib/gecode.dll
CHANGED
Binary file
|
@@ -908,6 +908,22 @@ Rust::Bindings::create_bindings Rust::Bindings::LangCxx, "gecode" do |b|
|
|
908
908
|
func.add_parameter "Gecode::PropKind", "pk"
|
909
909
|
end
|
910
910
|
|
911
|
+
ns.add_function "sqr" do |func|
|
912
|
+
func.add_parameter "Gecode::MSpace *", "home"
|
913
|
+
func.add_parameter "Gecode::IntVar", "x0"
|
914
|
+
func.add_parameter "Gecode::IntVar", "x1"
|
915
|
+
func.add_parameter "Gecode::IntConLevel", "icl"
|
916
|
+
func.add_parameter "Gecode::PropKind", "pk"
|
917
|
+
end
|
918
|
+
|
919
|
+
ns.add_function "sqrt" do |func|
|
920
|
+
func.add_parameter "Gecode::MSpace *", "home"
|
921
|
+
func.add_parameter "Gecode::IntVar", "x0"
|
922
|
+
func.add_parameter "Gecode::IntVar", "x1"
|
923
|
+
func.add_parameter "Gecode::IntConLevel", "icl"
|
924
|
+
func.add_parameter "Gecode::PropKind", "pk"
|
925
|
+
end
|
926
|
+
|
911
927
|
ns.add_function "branch" do |func|
|
912
928
|
func.add_parameter "Gecode::MSpace *", "home"
|
913
929
|
func.add_parameter "Gecode::MIntVarArray *", "iva" do |param|
|
@@ -955,6 +971,25 @@ Rust::Bindings::create_bindings Rust::Bindings::LangCxx, "gecode" do |b|
|
|
955
971
|
func.add_parameter "Gecode::PropKind", "pk"
|
956
972
|
end
|
957
973
|
|
974
|
+
ns.add_function "channel" do |func|
|
975
|
+
func.add_parameter "Gecode::MSpace*", "home"
|
976
|
+
func.add_parameter "Gecode::IntVar", "x0"
|
977
|
+
func.add_parameter "Gecode::BoolVar", "x1"
|
978
|
+
func.add_parameter "Gecode::IntConLevel", "icl"
|
979
|
+
func.add_parameter "Gecode::PropKind", "pk"
|
980
|
+
end
|
981
|
+
|
982
|
+
ns.add_function "channel" do |func|
|
983
|
+
func.add_parameter "Gecode::MSpace*", "home"
|
984
|
+
func.add_parameter "Gecode::MBoolVarArray *", "x" do |param|
|
985
|
+
param.custom_conversion = "*ruby2Gecode_MBoolVarArrayPtr(argv[1], 2)->ptr()"
|
986
|
+
end
|
987
|
+
func.add_parameter "Gecode::IntVar", "y"
|
988
|
+
func.add_parameter "int", "o"
|
989
|
+
func.add_parameter "Gecode::IntConLevel", "icl"
|
990
|
+
func.add_parameter "Gecode::PropKind", "pk"
|
991
|
+
end
|
992
|
+
|
958
993
|
ns.add_function "count" do |func|
|
959
994
|
func.add_parameter "Gecode::MSpace*", "home"
|
960
995
|
func.add_parameter "Gecode::MIntVarArray *", "x" do |param|
|
@@ -217,6 +217,40 @@ module Gecode
|
|
217
217
|
end
|
218
218
|
end
|
219
219
|
|
220
|
+
# A module that contains utility-methods for extensional constraints.
|
221
|
+
module Util::Extensional #:nodoc:
|
222
|
+
module_function
|
223
|
+
|
224
|
+
# Checks that the specified enumeration is an enumeration containing
|
225
|
+
# one or more tuples of the specified size. It also allows the caller
|
226
|
+
# to define additional tests by providing a block, which is given each
|
227
|
+
# tuple. If a test fails then an appropriate error is raised.
|
228
|
+
def perform_tuple_checks(tuples, expected_size, &additional_test)
|
229
|
+
unless tuples.respond_to?(:each)
|
230
|
+
raise TypeError, 'Expected an enumeration with tuples, got ' +
|
231
|
+
"#{tuples.class}."
|
232
|
+
end
|
233
|
+
|
234
|
+
if tuples.empty?
|
235
|
+
raise ArgumentError, 'One or more tuples must be specified.'
|
236
|
+
end
|
237
|
+
|
238
|
+
tuples.each do |tuple|
|
239
|
+
unless tuple.respond_to?(:each)
|
240
|
+
raise TypeError, 'Expected an enumeration containing enumeraions, ' +
|
241
|
+
"got #{tuple.class}."
|
242
|
+
end
|
243
|
+
|
244
|
+
unless tuple.size == expected_size
|
245
|
+
raise ArgumentError, 'All tuples must be of the same size as the ' +
|
246
|
+
'number of variables in the array.'
|
247
|
+
end
|
248
|
+
|
249
|
+
yield tuple
|
250
|
+
end
|
251
|
+
end
|
252
|
+
end
|
253
|
+
|
220
254
|
# Describes a constraint expressions. An expression is produced by calling
|
221
255
|
# some form of must on a left hand side. The expression waits for a right
|
222
256
|
# hand side so that it can post the corresponding constraint.
|
@@ -26,6 +26,13 @@ module Gecode
|
|
26
26
|
# Describes a boolean expression (following after must*).
|
27
27
|
class Expression #:nodoc:
|
28
28
|
def ==(expression, options = {})
|
29
|
+
unless expression.kind_of?(ExpressionTree) or
|
30
|
+
expression.kind_of?(Gecode::FreeBoolVar) or
|
31
|
+
expression.kind_of?(TrueClass) or expression.kind_of?(FalseClass) or
|
32
|
+
expression.respond_to?(:to_minimodel_lin_exp)
|
33
|
+
raise TypeError, 'Invalid right hand side of boolean equation.'
|
34
|
+
end
|
35
|
+
|
29
36
|
@params.update Gecode::Constraints::Util.decode_options(options)
|
30
37
|
@model.add_constraint BooleanConstraint.new(@model,
|
31
38
|
@params.update(:rhs => expression))
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Gecode::Constraints::Bool
|
2
|
+
class Expression
|
3
|
+
alias_method :pre_channel_equals, :==
|
4
|
+
|
5
|
+
# Constrains the boolean variable to be equal to the specified integer
|
6
|
+
# variable.
|
7
|
+
def ==(int, options = {})
|
8
|
+
unless @params[:lhs].kind_of?(Gecode::FreeBoolVar) and
|
9
|
+
int.kind_of?(Gecode::FreeIntVar)
|
10
|
+
return pre_channel_equals(int, options)
|
11
|
+
end
|
12
|
+
|
13
|
+
# Provide commutivity to the corresponding int variable constraint.
|
14
|
+
if @params[:negate]
|
15
|
+
int.must_not.equal(@params[:lhs], options)
|
16
|
+
else
|
17
|
+
int.must.equal(@params[:lhs], options)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
alias_comparison_methods
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
module Gecode::Constraints::BoolEnum
|
2
|
+
class Expression
|
3
|
+
# Adds a channel constraint on the variables in the enum with the specified
|
4
|
+
# integer variable. Beyond the common options the channel constraint can
|
5
|
+
# also take the following option:
|
6
|
+
#
|
7
|
+
# [:offset] Specifies an offset for the integer variable. If the offset is
|
8
|
+
# set to k then the integer variable takes value i+k exactly
|
9
|
+
# when the variable at index i in the boolean enumration is true
|
10
|
+
# and the rest are false.
|
11
|
+
def channel(int_var, options = {})
|
12
|
+
if @params[:negate]
|
13
|
+
raise Gecode::MissingConstraintError, 'A negated channel constraint ' +
|
14
|
+
'is not implemented.'
|
15
|
+
end
|
16
|
+
if options.has_key? :reify
|
17
|
+
raise ArgumentError, 'The channel constraint does not support the ' +
|
18
|
+
'reification option.'
|
19
|
+
end
|
20
|
+
unless int_var.kind_of? Gecode::FreeIntVar
|
21
|
+
raise TypeError, "Expected an integer variable, got #{int_var.class}."
|
22
|
+
end
|
23
|
+
|
24
|
+
@params.update(:rhs => int_var, :offset => options.delete(:offset) || 0)
|
25
|
+
@params.update(Gecode::Constraints::Util.decode_options(options))
|
26
|
+
@model.add_constraint Channel::ChannelConstraint.new(@model, @params)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
# A module that gathers the classes and modules used in channel constraints
|
31
|
+
# involving one boolean enum and one integer variable.
|
32
|
+
module Channel #:nodoc:
|
33
|
+
# Describes a channel constraint that "channels" an enumerations of
|
34
|
+
# boolean variables with an integer variable. This constrains the integer
|
35
|
+
# variable to take value i exactly when the variable at index i in the
|
36
|
+
# boolean enumeration is true and the others are false.
|
37
|
+
#
|
38
|
+
# Neither reification nor negation is supported.
|
39
|
+
#
|
40
|
+
# == Examples
|
41
|
+
#
|
42
|
+
# # Constrains the enumeration called +selected_option+ to be false in the
|
43
|
+
# # first four positions and have exactly one true variable in the other.
|
44
|
+
# selected_option.must.channel selected_option_index
|
45
|
+
# selected_option_index.must_be > 3
|
46
|
+
#
|
47
|
+
# # Constrains the enumeration called +selected_option+ to be false in the
|
48
|
+
# # first five positions and have exactly one true variable in the other.
|
49
|
+
# selected_option.must.channel(selected_option_index, :offset => 1)
|
50
|
+
# selected_option_index.must_be > 3
|
51
|
+
class ChannelConstraint < Gecode::Constraints::Constraint
|
52
|
+
def post
|
53
|
+
lhs, rhs, offset = @params.values_at(:lhs, :rhs, :offset)
|
54
|
+
Gecode::Raw::channel(@model.active_space, lhs.to_bool_var_array,
|
55
|
+
rhs.bind, offset, *propagation_options)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -10,16 +10,17 @@ module Gecode::Constraints::BoolEnum
|
|
10
10
|
raise ArgumentError, 'Reification is not supported by the tuple ' +
|
11
11
|
'constraint.'
|
12
12
|
end
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
13
|
+
|
14
|
+
util = Gecode::Constraints::Util
|
15
|
+
|
16
|
+
# Check that the tuples are correct.
|
17
|
+
expected_size = @params[:lhs].size
|
18
|
+
util::Extensional.perform_tuple_checks(tuples, expected_size) do |tuple|
|
19
|
+
unless tuple.all?{ |x| x.kind_of?(TrueClass) or x.kind_of?(FalseClass) }
|
20
|
+
raise TypeError, 'All tuples must contain booleans.'
|
21
|
+
end
|
21
22
|
end
|
22
|
-
|
23
|
+
|
23
24
|
@params[:tuples] = tuples
|
24
25
|
@model.add_constraint Extensional::TupleConstraint.new(@model,
|
25
26
|
@params.update(Gecode::Constraints::Util.decode_options(options)))
|
@@ -4,6 +4,20 @@ class Gecode::FreeIntVar
|
|
4
4
|
Gecode::Constraints::Int::Arithmetic::AbsExpressionStub.new(@model,
|
5
5
|
:lhs => self)
|
6
6
|
end
|
7
|
+
|
8
|
+
# Initiates an arithmetic squared value constraint.
|
9
|
+
def squared
|
10
|
+
Gecode::Constraints::Int::Arithmetic::SquaredExpressionStub.new(@model,
|
11
|
+
:lhs => self)
|
12
|
+
end
|
13
|
+
|
14
|
+
# Initiates an arithmetic squared root constraint.
|
15
|
+
def sqrt
|
16
|
+
Gecode::Constraints::Int::Arithmetic::SquareRootExpressionStub.new(@model,
|
17
|
+
:lhs => self)
|
18
|
+
end
|
19
|
+
alias_method :square_root, :sqrt
|
20
|
+
|
7
21
|
|
8
22
|
alias_method :pre_arith_mult, :* if instance_methods.include? '*'
|
9
23
|
|
@@ -52,7 +66,7 @@ module Gecode::Constraints::Int::Arithmetic #:nodoc:
|
|
52
66
|
# # The value of +x*y+ must be equal to their sum.
|
53
67
|
# (x*y).must == x + y
|
54
68
|
#
|
55
|
-
# # The
|
69
|
+
# # The value of +x*y+ must be less than 17, with +bool+ as reification
|
56
70
|
# # variable and +domain+ as strength.
|
57
71
|
# (x*y).must_be.less_than(17, :reify => bool, :strength => :domain)
|
58
72
|
class MultExpressionStub < Gecode::Constraints::Int::CompositeStub
|
@@ -69,4 +83,67 @@ module Gecode::Constraints::Int::Arithmetic #:nodoc:
|
|
69
83
|
variable.bind, *propagation_options)
|
70
84
|
end
|
71
85
|
end
|
86
|
+
|
87
|
+
# Describes a CompositeStub for the squared constraint, which constrain
|
88
|
+
# the squared value of the variable.
|
89
|
+
#
|
90
|
+
# == Examples
|
91
|
+
#
|
92
|
+
# # The value of +x*x+ must be equal to y.
|
93
|
+
# x.squared.must == y
|
94
|
+
#
|
95
|
+
# # The value of +x*x+ must be less than or equal to 16, with +bool+ as
|
96
|
+
# # reification variable and +domain+ as strength.
|
97
|
+
# x.squared.must_be.less_or_equal(16, :reify => bool, :strength => :domain)
|
98
|
+
class SquaredExpressionStub < Gecode::Constraints::Int::CompositeStub
|
99
|
+
def constrain_equal(variable, params, constrain)
|
100
|
+
lhs = @params[:lhs]
|
101
|
+
if constrain
|
102
|
+
min = lhs.min; max = lhs.max
|
103
|
+
products = [min*max, min*min, max*max]
|
104
|
+
variable.must_be.in products.min..products.max
|
105
|
+
end
|
106
|
+
|
107
|
+
Gecode::Raw::sqr(@model.active_space, lhs.bind, variable.bind,
|
108
|
+
*propagation_options)
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
# Describes a CompositeStub for the square root constraint, which constrain
|
113
|
+
# the rounded down square root of the variable.
|
114
|
+
#
|
115
|
+
# == Examples
|
116
|
+
#
|
117
|
+
# # The square root of +x+, rounded down, must equal y.
|
118
|
+
# x.square_root.must == y
|
119
|
+
#
|
120
|
+
# # The square root of +x+, rounded down, must be larger than 17, with
|
121
|
+
# # +bool+ as reification variable and +domain+ as strength.
|
122
|
+
# x.square_root.must_be.larger_than(17, :reify => bool, :strength => :domain)
|
123
|
+
class SquareRootExpressionStub < Gecode::Constraints::Int::CompositeStub
|
124
|
+
def constrain_equal(variable, params, constrain)
|
125
|
+
lhs = @params[:lhs]
|
126
|
+
if constrain
|
127
|
+
max = lhs.max
|
128
|
+
if max < 0
|
129
|
+
# The left hand side does not have a real valued square root.
|
130
|
+
upper_bound = 0
|
131
|
+
else
|
132
|
+
upper_bound = Math.sqrt(max).floor;
|
133
|
+
end
|
134
|
+
|
135
|
+
min = lhs.min
|
136
|
+
if min < 0
|
137
|
+
lower_bound = 0
|
138
|
+
else
|
139
|
+
lower_bound = Math.sqrt(min).floor;
|
140
|
+
end
|
141
|
+
|
142
|
+
variable.must_be.in lower_bound..upper_bound
|
143
|
+
end
|
144
|
+
|
145
|
+
Gecode::Raw::sqrt(@model.active_space, lhs.bind, variable.bind,
|
146
|
+
*propagation_options)
|
147
|
+
end
|
148
|
+
end
|
72
149
|
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
module Gecode::Constraints::Int
|
2
|
+
class Expression
|
3
|
+
alias_method :pre_channel_equals, :==
|
4
|
+
|
5
|
+
# Constrains the integer variable to be equal to the specified boolean
|
6
|
+
# variable. I.e. constrains the integer variable to be 1 when the boolean
|
7
|
+
# variable is true and 0 if the boolean variable is false.
|
8
|
+
def ==(bool, options = {})
|
9
|
+
unless @params[:lhs].kind_of?(Gecode::FreeIntVar) and
|
10
|
+
bool.kind_of?(Gecode::FreeBoolVar)
|
11
|
+
return pre_channel_equals(bool, options)
|
12
|
+
end
|
13
|
+
|
14
|
+
if @params[:negate]
|
15
|
+
raise Gecode::MissingConstraintError, 'A negated channel constraint ' +
|
16
|
+
'is not implemented.'
|
17
|
+
end
|
18
|
+
unless options[:reify].nil?
|
19
|
+
raise ArgumentError, 'Reification is not supported by the channel ' +
|
20
|
+
'constraint.'
|
21
|
+
end
|
22
|
+
|
23
|
+
@params.update(Gecode::Constraints::Util.decode_options(options))
|
24
|
+
@params[:rhs] = bool
|
25
|
+
@model.add_constraint Channel::ChannelConstraint.new(@model, @params)
|
26
|
+
end
|
27
|
+
|
28
|
+
alias_comparison_methods
|
29
|
+
|
30
|
+
# Adds a channel constraint on the integer variable and the variables in
|
31
|
+
# the specifed enum of boolean variables. Beyond the common options the
|
32
|
+
# channel constraint can also take the following option:
|
33
|
+
#
|
34
|
+
# [:offset] Specifies an offset for the integer variable. If the offset is
|
35
|
+
# set to k then the integer variable takes value i+k exactly
|
36
|
+
# when the variable at index i in the boolean enumration is true
|
37
|
+
# and the rest are false.
|
38
|
+
def channel(bool_enum, options = {})
|
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
|
51
|
+
end
|
52
|
+
|
53
|
+
# A module that gathers the classes and modules used in channel constraints
|
54
|
+
# involving a single integer variable.
|
55
|
+
module Channel #:nodoc:
|
56
|
+
# Describes a channel constraint that constrains an integer variable to be
|
57
|
+
# 1 if a boolean variable is true, and 0 when the boolean variable is false.
|
58
|
+
# Does not support negation nor reification.
|
59
|
+
#
|
60
|
+
# == Examples
|
61
|
+
#
|
62
|
+
# # The integer variable +x+ must be one exactly when the boolean
|
63
|
+
# # variable +bool+ is true.
|
64
|
+
# x.must == bool
|
65
|
+
class ChannelConstraint < Gecode::Constraints::Constraint
|
66
|
+
def post
|
67
|
+
lhs, rhs = @params.values_at(:lhs, :rhs)
|
68
|
+
Gecode::Raw::channel(@model.active_space, lhs.bind, rhs.bind,
|
69
|
+
*propagation_options)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
@@ -11,8 +11,16 @@ module Gecode::Constraints::IntEnum
|
|
11
11
|
enum.respond_to?(:to_set_var_array)
|
12
12
|
raise TypeError, "Expected int or set enum, got #{enum.class}."
|
13
13
|
end
|
14
|
+
if enum.respond_to? :to_set_var_array
|
15
|
+
if options.has_key? :reify
|
16
|
+
raise ArgumentError, 'The channel constraints does not support the ' +
|
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))
|
22
|
+
end
|
14
23
|
|
15
|
-
@params.update(Gecode::Constraints::Util.decode_options(options))
|
16
24
|
@params.update(:rhs => enum)
|
17
25
|
@model.add_constraint Channel::ChannelConstraint.new(@model, @params)
|
18
26
|
end
|
@@ -91,7 +99,7 @@ module Gecode::Constraints::IntEnum
|
|
91
99
|
Gecode::Raw::channel(@model.active_space, lhs, rhs.to_int_var_array,
|
92
100
|
*propagation_options)
|
93
101
|
else
|
94
|
-
# Set var array, no
|
102
|
+
# Set var array, no propagation options.
|
95
103
|
Gecode::Raw::channel(@model.active_space, lhs, rhs.to_set_var_array)
|
96
104
|
end
|
97
105
|
end
|
@@ -1,6 +1,7 @@
|
|
1
1
|
module Gecode::Constraints::IntEnum
|
2
2
|
class Expression
|
3
|
-
# Posts
|
3
|
+
# Posts a tuple constraint on the variables in the enum, constraining them
|
4
|
+
# to equal one of the specified tuples.
|
4
5
|
def in(tuples, options = {})
|
5
6
|
if @params[:negate]
|
6
7
|
raise Gecode::MissingConstraintError, 'A negated tuple constraint is ' +
|
@@ -10,18 +11,20 @@ module Gecode::Constraints::IntEnum
|
|
10
11
|
raise ArgumentError, 'Reification is not supported by the tuple ' +
|
11
12
|
'constraint.'
|
12
13
|
end
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
14
|
+
|
15
|
+
util = Gecode::Constraints::Util
|
16
|
+
|
17
|
+
# Check that the tuples are correct.
|
18
|
+
expected_size = @params[:lhs].size
|
19
|
+
util::Extensional.perform_tuple_checks(tuples, expected_size) do |tuple|
|
20
|
+
unless tuple.all?{ |x| x.kind_of? Fixnum }
|
21
|
+
raise TypeError, 'All tuples must contain Fixnum.'
|
22
|
+
end
|
20
23
|
end
|
21
24
|
|
22
25
|
@params[:tuples] = tuples
|
23
26
|
@model.add_constraint Extensional::TupleConstraint.new(@model,
|
24
|
-
@params.update(
|
27
|
+
@params.update(util.decode_options(options)))
|
25
28
|
end
|
26
29
|
end
|
27
30
|
|