gecoder 0.4.0 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGES +11 -0
- data/README +12 -1
- data/example/example_helper.rb +1 -0
- data/example/magic_sequence.rb +43 -0
- data/example/queens.rb +43 -0
- data/example/raw_bindings.rb +42 -0
- data/example/send_more_money.rb +43 -0
- data/example/sudoku.rb +65 -0
- data/ext/missing.cpp +15 -21
- data/ext/missing.h +14 -20
- data/ext/vararray.cpp +14 -20
- data/ext/vararray.h +18 -22
- data/lib/gecoder/bindings/bindings.rb +1979 -1969
- data/lib/gecoder/interface/binding_changes.rb +123 -2
- data/lib/gecoder/interface/constraints/bool/boolean.rb +80 -65
- data/lib/gecoder/interface/constraints/bool_enum/boolean.rb +59 -0
- data/lib/gecoder/interface/constraints/bool_enum_constraints.rb +8 -0
- data/lib/gecoder/interface/constraints/bool_var_constraints.rb +42 -0
- data/lib/gecoder/interface/constraints/int/arithmetic.rb +21 -44
- data/lib/gecoder/interface/constraints/int/domain.rb +6 -4
- data/lib/gecoder/interface/constraints/int_enum/arithmetic.rb +18 -44
- data/lib/gecoder/interface/constraints/int_enum/count.rb +3 -18
- data/lib/gecoder/interface/constraints/int_enum/distinct.rb +4 -16
- data/lib/gecoder/interface/constraints/int_enum/element.rb +9 -20
- data/lib/gecoder/interface/constraints/int_var_constraints.rb +28 -0
- data/lib/gecoder/interface/constraints/set/cardinality.rb +56 -0
- data/lib/gecoder/interface/constraints/set/domain.rb +66 -0
- data/lib/gecoder/interface/constraints/set/relation.rb +125 -0
- data/lib/gecoder/interface/constraints/set_var_constraints.rb +37 -0
- data/lib/gecoder/interface/constraints.rb +229 -65
- data/lib/gecoder/interface/enum_wrapper.rb +42 -11
- data/lib/gecoder/interface/model.rb +75 -0
- data/lib/gecoder/interface/search.rb +4 -9
- data/lib/gecoder/interface/variables.rb +36 -2
- data/lib/gecoder/version.rb +1 -1
- data/specs/bool_var.rb +58 -0
- data/specs/constraints/arithmetic.rb +91 -90
- data/specs/constraints/bool_enum.rb +130 -0
- data/specs/constraints/boolean.rb +95 -2
- data/specs/constraints/cardinality.rb +127 -0
- data/specs/constraints/constraint_helper.rb +91 -0
- data/specs/constraints/constraints.rb +31 -0
- data/specs/constraints/element.rb +43 -72
- data/specs/constraints/{domain.rb → int_domain.rb} +4 -0
- data/specs/constraints/{relation.rb → int_relation.rb} +0 -0
- data/specs/constraints/set_domain.rb +165 -0
- data/specs/constraints/set_relation.rb +181 -0
- data/specs/enum_wrapper.rb +13 -2
- data/specs/int_var.rb +33 -1
- data/specs/model.rb +80 -0
- data/specs/set_var.rb +39 -0
- data/specs/spec_helper.rb +35 -0
- data/specs/tmp +11 -124
- data/tasks/distribution.rake +1 -1
- data/vendor/rust/rust/class.rb +10 -10
- data/vendor/rust/rust/constants.rb +1 -1
- data/vendor/rust/rust/function.rb +5 -5
- data/vendor/rust/rust/type.rb +1 -1
- data/vendor/rust/test/constants.rb +1 -0
- data/vendor/rust/test/cppclass.cc +5 -0
- data/vendor/rust/test/cppclass.hh +4 -0
- data/vendor/rust/test/lib/extension-test.rb +1 -1
- data/vendor/rust/test/operators.cc +41 -0
- data/vendor/rust/test/operators.hh +39 -0
- data/vendor/rust/test/operators.rb +39 -0
- data/vendor/rust/test/test-cwrapper.rb +3 -0
- data/vendor/rust/test/test-operators.rb +42 -0
- metadata +31 -4
@@ -21,16 +21,31 @@ module Gecode
|
|
21
21
|
end
|
22
22
|
|
23
23
|
# Creates the specified number of boolean variables in the space. Returns
|
24
|
-
# the indices with which they can then be accessed using
|
24
|
+
# the indices with which they can then be accessed using bool_var.
|
25
25
|
def new_bool_vars(count = 1)
|
26
26
|
bool_var_store.new_vars(count)
|
27
27
|
end
|
28
28
|
|
29
|
-
# Gets the
|
29
|
+
# Gets the bool variable with the specified index, nil if none exists.
|
30
30
|
def bool_var(index)
|
31
31
|
bool_var_store[index]
|
32
32
|
end
|
33
33
|
|
34
|
+
# Creates the specified number of set variables in the space with the
|
35
|
+
# specified domain for greatest lower bound and least upper bound
|
36
|
+
# (specified as either a range or enum). A range for the allowed
|
37
|
+
# cardinality of the set can also be specified, if none is specified, or
|
38
|
+
# nil is given, then the default range (anything) will be used. Returns
|
39
|
+
# the indices with which they can then be accessed using set_var.
|
40
|
+
def new_set_vars(*vars)
|
41
|
+
set_var_store.new_vars(*vars)
|
42
|
+
end
|
43
|
+
|
44
|
+
# Gets the set variable with the specified index, nil if none exists.
|
45
|
+
def set_var(index)
|
46
|
+
set_var_store[index]
|
47
|
+
end
|
48
|
+
|
34
49
|
private
|
35
50
|
|
36
51
|
# Retrieves the store used for integer variables. Creates one if none
|
@@ -50,6 +65,14 @@ module Gecode
|
|
50
65
|
end
|
51
66
|
return @bool_var_store
|
52
67
|
end
|
68
|
+
|
69
|
+
# Retrieves the store used for set variables. Creates one if none exists.
|
70
|
+
def set_var_store
|
71
|
+
if @set_var_store.nil?
|
72
|
+
@set_var_store = Gecode::Util::SetVarStore.new(self)
|
73
|
+
end
|
74
|
+
return @set_var_store
|
75
|
+
end
|
53
76
|
end
|
54
77
|
|
55
78
|
class IntVar
|
@@ -67,6 +90,33 @@ module Gecode
|
|
67
90
|
def true?
|
68
91
|
val == 1
|
69
92
|
end
|
93
|
+
|
94
|
+
def false?
|
95
|
+
val == 0
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
class SetVar
|
100
|
+
# Aliases to make method-names more ruby-like.
|
101
|
+
alias_method :assigned?, :assigned
|
102
|
+
|
103
|
+
alias_method :include_glb?, :contains
|
104
|
+
alias_method :include?, :contains
|
105
|
+
def include_lub?(element)
|
106
|
+
!notContains(element)
|
107
|
+
end
|
108
|
+
|
109
|
+
alias_method :glb_min, :glbMin
|
110
|
+
alias_method :glb_max, :glbMax
|
111
|
+
alias_method :lub_min, :lubMin
|
112
|
+
alias_method :lub_max, :lubMax
|
113
|
+
|
114
|
+
alias_method :glb_size, :glbSize
|
115
|
+
alias_method :val_size, :glbSize
|
116
|
+
alias_method :lub_size, :lubSize
|
117
|
+
|
118
|
+
alias_method :card_min, :cardMin
|
119
|
+
alias_method :card_max, :cardMax
|
70
120
|
end
|
71
121
|
end
|
72
122
|
|
@@ -209,5 +259,76 @@ module Gecode
|
|
209
259
|
return arr
|
210
260
|
end
|
211
261
|
end
|
262
|
+
|
263
|
+
# A store in which int variables are created and stored.
|
264
|
+
class SetVarStore
|
265
|
+
include VarStoreMethods
|
266
|
+
|
267
|
+
private
|
268
|
+
|
269
|
+
# A string that identifies the array used by the store.
|
270
|
+
ARRAY_IDENTIFIER = 'set_array'
|
271
|
+
|
272
|
+
public
|
273
|
+
|
274
|
+
# Creates a store for the specified space with the specified capacit.
|
275
|
+
def initialize(space)
|
276
|
+
@space = space
|
277
|
+
|
278
|
+
@var_array = space.set_var_array(ARRAY_IDENTIFIER)
|
279
|
+
if @var_array.nil?
|
280
|
+
# Create a new one.
|
281
|
+
@var_array = new_storage_array(0)
|
282
|
+
end
|
283
|
+
|
284
|
+
@size = @var_array.size
|
285
|
+
@next_index = @size
|
286
|
+
end
|
287
|
+
|
288
|
+
# Creates the specified number of set variables in the space with the
|
289
|
+
# specified domain for greatest lower bound and least upper bound
|
290
|
+
# (specified as either a range or enum). A range for the allowed
|
291
|
+
# cardinality of the set can also be specified, if none is specified, or
|
292
|
+
# nil is given, then the default range (anything) will be used. Returns
|
293
|
+
# the indices with which they can then be accessed using set_var.
|
294
|
+
def new_vars(glb_domain, lub_domain, cardinality_range = nil, count = 1)
|
295
|
+
grow(@next_index + count) # See the design note for more information.
|
296
|
+
|
297
|
+
if cardinality_range.nil?
|
298
|
+
cardinality_range = 0..Gecode::Raw::Limits::Set::CARD_MAX
|
299
|
+
end
|
300
|
+
|
301
|
+
params = [@space]
|
302
|
+
params << domain_to_args(glb_domain)
|
303
|
+
params << domain_to_args(lub_domain)
|
304
|
+
params << cardinality_range.first << cardinality_range.last
|
305
|
+
count.times do |i|
|
306
|
+
@var_array[@next_index] = Gecode::Raw::SetVar.new(*params.flatten)
|
307
|
+
@next_index += 1
|
308
|
+
end
|
309
|
+
|
310
|
+
((@next_index - count)...@next_index).to_a
|
311
|
+
end
|
312
|
+
|
313
|
+
private
|
314
|
+
|
315
|
+
# Transforms a lub or glb domain given as a range or enumeration into one
|
316
|
+
# or more parameters that describe the domain to Gecode::Raw::SetVar .
|
317
|
+
def domain_to_args(domain)
|
318
|
+
if domain.kind_of? Range
|
319
|
+
return domain.first, domain.last
|
320
|
+
else
|
321
|
+
elements = domain.to_a
|
322
|
+
return Gecode::Raw::IntSet.new(domain, domain.size)
|
323
|
+
end
|
324
|
+
end
|
325
|
+
|
326
|
+
# Creates a new storage array for bool variables.
|
327
|
+
def new_storage_array(new_size)
|
328
|
+
arr = Gecode::Raw::SetVarArray.new(@space, new_size)
|
329
|
+
@space.own(arr, ARRAY_IDENTIFIER)
|
330
|
+
return arr
|
331
|
+
end
|
332
|
+
end
|
212
333
|
end
|
213
334
|
end
|
@@ -7,71 +7,81 @@ module Gecode
|
|
7
7
|
def &(var)
|
8
8
|
Constraints::Bool::ExpressionNode.new(self, @model) & var
|
9
9
|
end
|
10
|
+
|
11
|
+
def ^(var)
|
12
|
+
Constraints::Bool::ExpressionNode.new(self, @model) ^ var
|
13
|
+
end
|
14
|
+
|
15
|
+
def implies(var)
|
16
|
+
Constraints::Bool::ExpressionNode.new(self, @model).implies var
|
17
|
+
end
|
10
18
|
end
|
11
19
|
|
20
|
+
# A module that gathers the classes and modules used in boolean constraints.
|
12
21
|
module Constraints::Bool
|
22
|
+
# Describes a boolean expression (following after must*).
|
13
23
|
class Expression
|
14
|
-
def ==(expression)
|
15
|
-
|
24
|
+
def ==(expression, options = {})
|
25
|
+
@params.update Gecode::Constraints::Util.decode_options(options)
|
26
|
+
@model.add_constraint BooleanConstraint.new(@model,
|
27
|
+
@params.update(:rhs => expression))
|
16
28
|
end
|
17
29
|
alias_comparison_methods
|
18
30
|
|
31
|
+
# Constrains the boolean expression to imply the specified expression.
|
32
|
+
def imply(expression, options = {})
|
33
|
+
@params.update Gecode::Constraints::Util.decode_options(options)
|
34
|
+
@params.update(:lhs => @params[:lhs].implies(expression), :rhs => true)
|
35
|
+
@model.add_constraint BooleanConstraint.new(@model, @params)
|
36
|
+
end
|
37
|
+
|
38
|
+
# Constrains the boolean expression to be true.
|
19
39
|
def true
|
20
|
-
|
21
|
-
lhs = @params[:lhs]
|
22
|
-
unless lhs.respond_to? :to_minimodel_lin_exp
|
23
|
-
lhs = ExpressionNode.new(lhs, @model)
|
24
|
-
end
|
25
|
-
|
40
|
+
@params.update Gecode::Constraints::Util.decode_options({})
|
26
41
|
@model.add_constraint BooleanConstraint.new(@model,
|
27
|
-
@params.update(:
|
42
|
+
@params.update(:rhs => true))
|
28
43
|
end
|
29
44
|
|
45
|
+
# Constrains the boolean expression to be false.
|
30
46
|
def false
|
31
|
-
|
32
|
-
|
33
|
-
unless lhs.respond_to? :to_minimodel_lin_exp
|
34
|
-
lhs = ExpressionNode.new(lhs, @model)
|
35
|
-
end
|
36
|
-
|
37
|
-
@params.update(:expression => Gecode::Raw::MiniModel::BoolExpr.new(
|
38
|
-
lhs.to_minimodel_lin_exp, Gecode::Raw::MiniModel::BoolExpr::BT_NOT))
|
39
|
-
@model.add_constraint BooleanConstraint.new(@model, @params)
|
40
|
-
end
|
41
|
-
|
42
|
-
private
|
43
|
-
|
44
|
-
# Adds the boolean constraint corresponding to equivalence between the
|
45
|
-
# left and right hand sides.
|
46
|
-
#
|
47
|
-
# Raises TypeError if the element is of a type that doesn't allow a
|
48
|
-
# relation to be specified.
|
49
|
-
def add_boolean_constraint(right_hand_side = nil)
|
50
|
-
# Bind parameters.
|
51
|
-
lhs = @params[:lhs]
|
52
|
-
unless lhs.respond_to? :to_minimodel_lin_exp
|
53
|
-
lhs = ExpressionNode.new(lhs, @model)
|
54
|
-
end
|
55
|
-
unless right_hand_side.respond_to? :to_minimodel_lin_exp
|
56
|
-
right_hand_side = ExpressionNode.new(right_hand_side, @model)
|
57
|
-
end
|
58
|
-
|
59
|
-
expression = ExpressionTree.new(lhs, right_hand_side,
|
60
|
-
Gecode::Raw::MiniModel::BoolExpr::BT_EQV)
|
61
|
-
@model.add_constraint BooleanConstraint.new(@model,
|
62
|
-
@params.update(:expression => expression.to_minimodel_lin_exp))
|
47
|
+
@params[:negate] = !@params[:negate]
|
48
|
+
self.true
|
63
49
|
end
|
64
50
|
end
|
65
51
|
|
66
52
|
# Describes a boolean constraint.
|
67
53
|
class BooleanConstraint < Gecode::Constraints::ReifiableConstraint
|
68
54
|
def post
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
55
|
+
lhs, rhs, negate, strength, reif_var = @params.values_at(:lhs, :rhs,
|
56
|
+
:negate, :strength, :reif)
|
57
|
+
space = (lhs.model || rhs.model).active_space
|
58
|
+
|
59
|
+
# TODO: It should be possible to reduce the number of necessary
|
60
|
+
# variables and constraints a bit by altering the way that the top node
|
61
|
+
# is posted, using its constraint for reification etc when possible.
|
62
|
+
|
63
|
+
if rhs.respond_to? :bind
|
64
|
+
if reif_var.nil?
|
65
|
+
Gecode::Raw::bool_eqv(space, lhs.bind, rhs.bind, !negate, strength)
|
66
|
+
else
|
67
|
+
if negate
|
68
|
+
Gecode::Raw::bool_xor(space, lhs.bind, rhs.bind, reif_var.bind,
|
69
|
+
strength)
|
70
|
+
else
|
71
|
+
Gecode::Raw::bool_eqv(space, lhs.bind, rhs.bind, reif_var.bind,
|
72
|
+
strength)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
else
|
76
|
+
should_hold = !negate & rhs
|
77
|
+
if reif_var.nil?
|
78
|
+
Gecode::Raw::MiniModel::BoolExpr.new(lhs.bind).post(space,
|
79
|
+
should_hold)
|
80
|
+
else
|
81
|
+
Gecode::Raw::bool_eqv(space, lhs.bind, reif_var.bind, should_hold,
|
82
|
+
strength)
|
83
|
+
end
|
73
84
|
end
|
74
|
-
@params[:expression].post(@model.active_space, !@params[:negate])
|
75
85
|
end
|
76
86
|
end
|
77
87
|
|
@@ -82,11 +92,13 @@ module Gecode
|
|
82
92
|
|
83
93
|
private
|
84
94
|
|
85
|
-
# Maps the names of the methods to the corresponding bool
|
86
|
-
#
|
95
|
+
# Maps the names of the methods to the corresponding bool constraint in
|
96
|
+
# Gecode.
|
87
97
|
OPERATION_TYPES = {
|
88
|
-
:|
|
89
|
-
:&
|
98
|
+
:| => :bool_or,
|
99
|
+
:& => :bool_and,
|
100
|
+
:^ => :bool_xor,
|
101
|
+
:implies => :bool_imp
|
90
102
|
}
|
91
103
|
|
92
104
|
public
|
@@ -97,7 +109,12 @@ module Gecode
|
|
97
109
|
unless expression.kind_of? ExpressionTree
|
98
110
|
expression = ExpressionNode.new(expression)
|
99
111
|
end
|
100
|
-
ExpressionTree.new(self, expression,
|
112
|
+
ExpressionTree.new(self, expression) do |model, var1, var2|
|
113
|
+
new_var = model.bool_var
|
114
|
+
Gecode::Raw::#{operation}(model.active_space, var1.bind, var2.bind,
|
115
|
+
new_var.bind, Gecode::Raw::ICL_DEF)
|
116
|
+
new_var
|
117
|
+
end
|
101
118
|
end
|
102
119
|
end_code
|
103
120
|
end
|
@@ -116,18 +133,17 @@ module Gecode
|
|
116
133
|
class ExpressionTree
|
117
134
|
include OperationMethods
|
118
135
|
|
119
|
-
# Constructs a new expression with the specified
|
120
|
-
|
121
|
-
|
122
|
-
@
|
123
|
-
@
|
136
|
+
# Constructs a new expression with the specified nodes. The proc should
|
137
|
+
# take a model followed by two variables and return a new variable.
|
138
|
+
def initialize(left_tree, right_tree, &block)
|
139
|
+
@left = left_tree
|
140
|
+
@right = right_tree
|
141
|
+
@bind_proc = block
|
124
142
|
end
|
125
143
|
|
126
|
-
#
|
127
|
-
|
128
|
-
|
129
|
-
Gecode::Raw::MiniModel::BoolExpr.new(@left.to_minimodel_lin_exp,
|
130
|
-
@operation, @right.to_minimodel_lin_exp)
|
144
|
+
# Returns a bound boolean variable representing the expression.
|
145
|
+
def bind
|
146
|
+
@bind_proc.call(model, @left, @right).bind
|
131
147
|
end
|
132
148
|
|
133
149
|
# Fetches the space that the expression's variables is in.
|
@@ -147,10 +163,9 @@ module Gecode
|
|
147
163
|
@model = model
|
148
164
|
end
|
149
165
|
|
150
|
-
#
|
151
|
-
|
152
|
-
|
153
|
-
Gecode::Raw::MiniModel::BoolExpr.new(@value.bind)
|
166
|
+
# Returns a bound boolean variable representing the expression.
|
167
|
+
def bind
|
168
|
+
@value.bind
|
154
169
|
end
|
155
170
|
end
|
156
171
|
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
module Gecode
|
2
|
+
module BoolEnumMethods
|
3
|
+
# Produces an expression that can be handled as if it was a variable
|
4
|
+
# representing the conjunction of all boolean variables in the enumeration.
|
5
|
+
def conjunction
|
6
|
+
return Gecode::Constraints::BoolEnum::ConjunctionStub.new(
|
7
|
+
@model, :lhs => self)
|
8
|
+
end
|
9
|
+
|
10
|
+
# Produces an expression that can be handled as if it was a variable
|
11
|
+
# representing the disjunction of all boolean variables in the enumeration.
|
12
|
+
def disjunction
|
13
|
+
return Gecode::Constraints::BoolEnum::DisjunctionStub.new(
|
14
|
+
@model, :lhs => self)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
module Constraints::BoolEnum
|
19
|
+
# Describes an expression stub started with a bool var enum following by
|
20
|
+
# #conjunction.
|
21
|
+
class ConjunctionStub < Gecode::Constraints::Bool::CompositeStub
|
22
|
+
def constrain_equal(variable, params)
|
23
|
+
enum, strength = @params.values_at(:lhs, :strength)
|
24
|
+
if variable.nil?
|
25
|
+
variable = @model.bool_var
|
26
|
+
end
|
27
|
+
|
28
|
+
if variable.respond_to? :bind
|
29
|
+
bound = variable.bind
|
30
|
+
else
|
31
|
+
bound = variable
|
32
|
+
end
|
33
|
+
Gecode::Raw::bool_and(@model.active_space, enum.to_bool_var_array,
|
34
|
+
bound, strength)
|
35
|
+
return variable
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
# Describes an expression stub started with a bool var enum following by
|
40
|
+
# #disjunction.
|
41
|
+
class DisjunctionStub < Gecode::Constraints::Bool::CompositeStub
|
42
|
+
def constrain_equal(variable, params)
|
43
|
+
enum, strength = @params.values_at(:lhs, :strength)
|
44
|
+
if variable.nil?
|
45
|
+
variable = @model.bool_var
|
46
|
+
end
|
47
|
+
|
48
|
+
if variable.respond_to? :bind
|
49
|
+
bound = variable.bind
|
50
|
+
else
|
51
|
+
bound = variable
|
52
|
+
end
|
53
|
+
Gecode::Raw::bool_or(@model.active_space, enum.to_bool_var_array,
|
54
|
+
bound, strength)
|
55
|
+
return variable
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -17,6 +17,48 @@ module Gecode
|
|
17
17
|
# Describes a boolean expression.
|
18
18
|
class Expression < Gecode::Constraints::Expression
|
19
19
|
end
|
20
|
+
|
21
|
+
# A composite expression which is an bool expression with a left hand side
|
22
|
+
# resulting from a previous constraint.
|
23
|
+
class CompositeExpression < Gecode::Constraints::CompositeExpression
|
24
|
+
# The block given should take three parameters. The first is the variable
|
25
|
+
# that should be the left hand side, if it's nil then a new one should be
|
26
|
+
# created. The second is the has of parameters. The block should return
|
27
|
+
# the variable used as left hand side.
|
28
|
+
def initialize(model, params, &block)
|
29
|
+
super(Expression, Gecode::FreeIntVar, model, params, &block)
|
30
|
+
end
|
31
|
+
|
32
|
+
# Override to also deal with constant booleans.
|
33
|
+
def true(options = {})
|
34
|
+
# We don't need any additional constraints.
|
35
|
+
@params.update Gecode::Constraints::Util.decode_options(options)
|
36
|
+
@proc.call(!@params[:negate], @params)
|
37
|
+
end
|
38
|
+
|
39
|
+
# Override to also deal with constant booleans.
|
40
|
+
def false(options = {})
|
41
|
+
# We don't need any additional constraints.
|
42
|
+
@params.update Gecode::Constraints::Util.decode_options(options)
|
43
|
+
@proc.call(@params[:negate], @params)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
# Describes a stub that produces an int variable, which can then be used with
|
48
|
+
# the normal bool variable constraints. An example for boolean composite
|
49
|
+
# constraints would be conjunction.
|
50
|
+
#
|
51
|
+
# bools.conjunction.must == b1 | b2
|
52
|
+
#
|
53
|
+
# "bools.conjunction" produces a bool variable which the constraint
|
54
|
+
# ".must == b1 | b2" is then applied to.In the above case two constraints
|
55
|
+
# (and one temporary variable) are required, but in the case of equality
|
56
|
+
# only one constraint is required.
|
57
|
+
class CompositeStub < Gecode::Constraints::CompositeStub
|
58
|
+
def initialize(model, params)
|
59
|
+
super(CompositeExpression, model, params)
|
60
|
+
end
|
61
|
+
end
|
20
62
|
end
|
21
63
|
end
|
22
64
|
|
@@ -22,56 +22,33 @@ end
|
|
22
22
|
module Gecode::Constraints::Int::Arithmetic
|
23
23
|
# Describes an expression stub started with an integer variable followed by
|
24
24
|
# #abs .
|
25
|
-
class AbsExpressionStub < Gecode::Constraints::
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
def expression(params)
|
32
|
-
# We extract the integer and continue as if it had been specified as
|
33
|
-
# left hand side. This might be elegant, but it could get away with
|
34
|
-
# fewer constraints at times (when only equality is used) and
|
35
|
-
# propagation strength can't be specified.
|
36
|
-
# TODO: cut down on the number of constraints when possible. See if
|
37
|
-
# there's some neat way of getting the above remarks.
|
25
|
+
class AbsExpressionStub < Gecode::Constraints::Int::CompositeStub
|
26
|
+
def constrain_equal(variable, params)
|
27
|
+
lhs, strength = @params.values_at(:lhs, :strength)
|
28
|
+
if variable.nil?
|
29
|
+
variable = @model.int_var(lhs.min..lhs.max)
|
30
|
+
end
|
38
31
|
|
39
|
-
|
40
|
-
|
41
|
-
proxy = @model.int_var(lhs.min..lhs.max)
|
42
|
-
lhs = lhs.bind
|
43
|
-
|
44
|
-
Gecode::Raw::abs(@model.active_space, lhs, proxy.bind,
|
45
|
-
Gecode::Raw::ICL_DEF)
|
46
|
-
Gecode::Constraints::Int::Expression.new(@model,
|
47
|
-
params.update(:lhs => proxy))
|
32
|
+
Gecode::Raw::abs(@model.active_space, lhs.bind, variable.bind, strength)
|
33
|
+
return variable
|
48
34
|
end
|
49
35
|
end
|
50
36
|
|
51
37
|
# Describes an expression stub started with an integer variable followed by
|
52
38
|
# #* .
|
53
|
-
class MultExpressionStub < Gecode::Constraints::
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
params.update(@params)
|
68
|
-
lhs, var = params.values_at(:lhs, :var)
|
69
|
-
proxy = @model.int_var(-(lhs.min*var.min).abs..(lhs.max*var.max).abs) # Sloppy
|
70
|
-
|
71
|
-
Gecode::Raw::mult(@model.active_space, lhs.bind, var.bind, proxy.bind,
|
72
|
-
Gecode::Raw::ICL_DEF)
|
73
|
-
Gecode::Constraints::Int::Expression.new(@model,
|
74
|
-
params.update(:lhs => proxy))
|
39
|
+
class MultExpressionStub < Gecode::Constraints::Int::CompositeStub
|
40
|
+
def constrain_equal(variable, params)
|
41
|
+
lhs, lhs2, strength = @params.values_at(:lhs, :var, :strength)
|
42
|
+
if variable.nil?
|
43
|
+
a_min = lhs.min; a_max = lhs.max
|
44
|
+
b_min = lhs2.min; b_max = lhs2.max
|
45
|
+
products = [a_min*b_min, a_min*b_max, a_max*b_min, a_max*b_max]
|
46
|
+
variable = @model.int_var(products.min..products.max)
|
47
|
+
end
|
48
|
+
|
49
|
+
Gecode::Raw::mult(@model.active_space, lhs.bind, lhs2.bind,
|
50
|
+
variable.bind, strength)
|
51
|
+
return variable
|
75
52
|
end
|
76
53
|
end
|
77
54
|
end
|
@@ -6,9 +6,11 @@ module Gecode::Constraints::Int
|
|
6
6
|
@params[:domain] = domain
|
7
7
|
if domain.kind_of? Range
|
8
8
|
@model.add_constraint Domain::RangeDomainConstraint.new(@model, @params)
|
9
|
-
|
10
|
-
@model.add_constraint Domain::
|
9
|
+
elsif domain.kind_of?(Enumerable) and domain.all?{ |e| e.kind_of? Fixnum }
|
10
|
+
@model.add_constraint Domain::EnumDomainConstraint.new(@model,
|
11
11
|
@params)
|
12
|
+
else
|
13
|
+
raise TypeError, "Expected integer enumerable, got #{domain.class}."
|
12
14
|
end
|
13
15
|
end
|
14
16
|
end
|
@@ -29,8 +31,8 @@ module Gecode::Constraints::Int
|
|
29
31
|
negate_using_reification
|
30
32
|
end
|
31
33
|
|
32
|
-
# Describes a
|
33
|
-
class
|
34
|
+
# Describes a enum domain constraint.
|
35
|
+
class EnumDomainConstraint < Gecode::Constraints::ReifiableConstraint
|
34
36
|
def post
|
35
37
|
space = @model.active_space
|
36
38
|
|
@@ -17,56 +17,30 @@ end
|
|
17
17
|
# A module that gathers the classes and modules used by arithmetic constraints.
|
18
18
|
module Gecode::Constraints::IntEnum::Arithmetic
|
19
19
|
# Describes an expression stub started with an int var enum following by #max.
|
20
|
-
class MaxExpressionStub < Gecode::Constraints::
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
def expression(params)
|
27
|
-
# We extract the integer and continue as if it had been specified as
|
28
|
-
# left hand side. This might be elegant, but it could get away with
|
29
|
-
# fewer constraints at times (when only equality is used) and
|
30
|
-
# propagation strength can't be specified.
|
31
|
-
# TODO: cut down on the number of constraints when possible. See if
|
32
|
-
# there's some neat way of getting the above remarks.
|
20
|
+
class MaxExpressionStub < Gecode::Constraints::Int::CompositeStub
|
21
|
+
def constrain_equal(variable, params)
|
22
|
+
enum, strength = @params.values_at(:lhs, :strength)
|
23
|
+
if variable.nil?
|
24
|
+
variable = @model.int_var(enum.domain_range)
|
25
|
+
end
|
33
26
|
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
lhs = lhs.to_int_var_array
|
38
|
-
|
39
|
-
Gecode::Raw::max(@model.active_space, lhs, proxy.bind,
|
40
|
-
Gecode::Raw::ICL_DEF)
|
41
|
-
Gecode::Constraints::Int::Expression.new(@model,
|
42
|
-
params.update(:lhs => proxy))
|
27
|
+
Gecode::Raw::max(@model.active_space, enum.to_int_var_array,
|
28
|
+
variable.bind, strength)
|
29
|
+
return variable
|
43
30
|
end
|
44
31
|
end
|
45
32
|
|
46
33
|
# Describes an expression stub started with an int var enum following by #min.
|
47
|
-
class MinExpressionStub < Gecode::Constraints::
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
def expression(params)
|
54
|
-
# We extract the integer and continue as if it had been specified as
|
55
|
-
# left hand side. This might be elegant, but it could get away with
|
56
|
-
# fewer constraints at times (when only equality is used) and
|
57
|
-
# propagation strength can't be specified.
|
58
|
-
# TODO: cut down on the number of constraints when possible. See if
|
59
|
-
# there's some neat way of getting the above remarks.
|
60
|
-
|
61
|
-
params.update(@params)
|
62
|
-
lhs = params[:lhs]
|
63
|
-
proxy = @model.int_var(lhs.domain_range)
|
64
|
-
lhs = lhs.to_int_var_array
|
34
|
+
class MinExpressionStub < Gecode::Constraints::Int::CompositeStub
|
35
|
+
def constrain_equal(variable, params)
|
36
|
+
enum, strength = @params.values_at(:lhs, :strength)
|
37
|
+
if variable.nil?
|
38
|
+
variable = @model.int_var(enum.domain_range)
|
39
|
+
end
|
65
40
|
|
66
|
-
Gecode::Raw::min(@model.active_space,
|
67
|
-
|
68
|
-
|
69
|
-
params.update(:lhs => proxy))
|
41
|
+
Gecode::Raw::min(@model.active_space, enum.to_int_var_array,
|
42
|
+
variable.bind, strength)
|
43
|
+
return variable
|
70
44
|
end
|
71
45
|
end
|
72
46
|
end
|