gecoder 0.4.0 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGES +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
|