gecoder 0.3.0 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGES +17 -2
- data/README +7 -1
- data/Rakefile +4 -0
- data/lib/gecoder/interface/constraints/bool/boolean.rb +1 -4
- data/lib/gecoder/interface/constraints/int/arithmetic.rb +77 -0
- data/lib/gecoder/interface/constraints/int/domain.rb +50 -0
- data/lib/gecoder/interface/constraints/int/linear.rb +12 -44
- data/lib/gecoder/interface/constraints/int_enum/arithmetic.rb +72 -0
- data/lib/gecoder/interface/constraints/int_enum/channel.rb +32 -0
- data/lib/gecoder/interface/constraints/int_enum/count.rb +90 -0
- data/lib/gecoder/interface/constraints/int_enum/distinct.rb +3 -8
- data/lib/gecoder/interface/constraints/int_enum/element.rb +75 -0
- data/lib/gecoder/interface/constraints/int_enum/equality.rb +31 -0
- data/lib/gecoder/interface/constraints/int_enum/sort.rb +104 -0
- data/lib/gecoder/interface/constraints/int_enum_constraints.rb +6 -0
- data/lib/gecoder/interface/constraints/int_var_constraints.rb +2 -0
- data/lib/gecoder/interface/constraints/reifiable_constraints.rb +21 -0
- data/lib/gecoder/interface/constraints.rb +57 -6
- data/lib/gecoder/interface/enum_matrix.rb +64 -0
- data/lib/gecoder/interface/enum_wrapper.rb +33 -5
- data/lib/gecoder/interface/model.rb +36 -6
- data/lib/gecoder/interface.rb +1 -0
- data/lib/gecoder/version.rb +4 -0
- data/lib/gecoder.rb +1 -0
- data/specs/binding_changes.rb +72 -0
- data/specs/bool_var.rb +20 -0
- data/specs/branch.rb +104 -0
- data/specs/constraints/arithmetic.rb +227 -0
- data/specs/constraints/boolean.rb +132 -0
- data/specs/constraints/channel.rb +55 -0
- data/specs/constraints/constraint_helper.rb +48 -0
- data/specs/constraints/constraints.rb +28 -0
- data/specs/constraints/count.rb +99 -0
- data/specs/constraints/distinct.rb +99 -0
- data/specs/constraints/domain.rb +56 -0
- data/specs/constraints/element.rb +128 -0
- data/specs/constraints/equality.rb +30 -0
- data/specs/constraints/linear.rb +166 -0
- data/specs/constraints/reification_sugar.rb +92 -0
- data/specs/constraints/relation.rb +72 -0
- data/specs/constraints/sort.rb +173 -0
- data/specs/enum_matrix.rb +43 -0
- data/specs/enum_wrapper.rb +100 -0
- data/specs/int_var.rb +108 -0
- data/specs/model.rb +84 -0
- data/specs/search.rb +157 -0
- data/specs/spec_helper.rb +63 -0
- data/specs/tmp +135 -0
- data/tasks/all_tasks.rb +1 -0
- data/tasks/distribution.rake +64 -0
- data/tasks/rcov.rake +17 -0
- data/tasks/specs.rake +16 -0
- data/tasks/svn.rake +11 -0
- data/tasks/website.rake +58 -0
- data/vendor/rust/include/rust_conversions.hh +1 -2
- metadata +53 -2
data/CHANGES
CHANGED
@@ -1,9 +1,25 @@
|
|
1
|
+
== Version 0.4.0
|
2
|
+
This release adds most of the constraints supported by Gecode for integer
|
3
|
+
variables.
|
4
|
+
|
5
|
+
* [#11861] Fixed a bug stopping the creating of int variables with non-range domains.
|
6
|
+
* Added domain constraints for int variables.
|
7
|
+
* Added equality constraint for int enums.
|
8
|
+
* Matrices of integer and boolean variables can now be created using Model#int_var_matrix Model#bool_var_matrix.
|
9
|
+
* Added channel constraint for int enums.
|
10
|
+
* Added element constraints (variable array access).
|
11
|
+
* Added count constraints.
|
12
|
+
* Added sortedness constraints.
|
13
|
+
* Added arithmetic constraints (min, max, abs and variable multiplication).
|
14
|
+
|
1
15
|
== Version 0.3.0
|
16
|
+
This release fleshes out the existing constraints with things such as
|
17
|
+
reification and adds boolean variables and their basic constraints.
|
2
18
|
|
3
19
|
* The constructor of Gecode::Model no longer has to be called by classes inheriting from it.
|
4
20
|
* Added Model#reset! which resets a model after search.
|
5
21
|
* Added Model#solution which passes the first solution to a block and returns the result of that block.
|
6
|
-
* Added Model#
|
22
|
+
* Added Model#each_solution which iterates over each solution.
|
7
23
|
* Added boolean variables. They are created using Model#bool_var and Model#bool_var_array .
|
8
24
|
* Added two options to constraints: propagation strength and reification variable.
|
9
25
|
* Linear and simple relation constraints can now also be specified using #equal, #equal_to, #greater, #greater_than,... in addition to comparison operators.
|
@@ -13,7 +29,6 @@
|
|
13
29
|
* Added syntactic sugar for combining reifiable constraints with | and &.
|
14
30
|
|
15
31
|
== Version 0.2.0
|
16
|
-
|
17
32
|
This is the first release of Gecode/R, a Ruby interface to Gecode.
|
18
33
|
|
19
34
|
* Added support for finite domain integers.
|
data/README
CHANGED
data/Rakefile
CHANGED
@@ -10,14 +10,11 @@ module Gecode
|
|
10
10
|
end
|
11
11
|
|
12
12
|
module Constraints::Bool
|
13
|
-
# Add some relation selection based on whether the expression is negated.
|
14
|
-
alias_method :pre_bool_rel_initialize, :initialize
|
15
13
|
class Expression
|
16
14
|
def ==(expression)
|
17
15
|
add_boolean_constraint(expression)
|
18
16
|
end
|
19
|
-
|
20
|
-
alias_method :equal_to, :==
|
17
|
+
alias_comparison_methods
|
21
18
|
|
22
19
|
def true
|
23
20
|
# Bind parameters.
|
@@ -0,0 +1,77 @@
|
|
1
|
+
class Gecode::FreeIntVar
|
2
|
+
# Initiates an arithmetic absolute value constraint.
|
3
|
+
def abs
|
4
|
+
Gecode::Constraints::Int::Arithmetic::AbsExpressionStub.new(@model,
|
5
|
+
:lhs => self)
|
6
|
+
end
|
7
|
+
|
8
|
+
# Creates a linear expression where the int variable is multiplied with
|
9
|
+
# a constant integer.
|
10
|
+
alias_method :pre_arith_mult, :* if instance_methods.include? '*'
|
11
|
+
def *(var)
|
12
|
+
if var.kind_of? Gecode::FreeIntVar
|
13
|
+
Gecode::Constraints::Int::Arithmetic::MultExpressionStub.new(
|
14
|
+
@model, :lhs => self, :var => var)
|
15
|
+
else
|
16
|
+
pre_arith_mult(var) if respond_to? :pre_arith_mult
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
# A module that gathers the classes and modules used by arithmetic constraints.
|
22
|
+
module Gecode::Constraints::Int::Arithmetic
|
23
|
+
# Describes an expression stub started with an integer variable followed by
|
24
|
+
# #abs .
|
25
|
+
class AbsExpressionStub < Gecode::Constraints::ExpressionStub
|
26
|
+
include Gecode::Constraints::LeftHandSideMethods
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
# Produces a proxy expression for the lhs module.
|
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.
|
38
|
+
|
39
|
+
params.update(@params)
|
40
|
+
lhs = params[:lhs]
|
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))
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
# Describes an expression stub started with an integer variable followed by
|
52
|
+
# #* .
|
53
|
+
class MultExpressionStub < Gecode::Constraints::ExpressionStub
|
54
|
+
include Gecode::Constraints::LeftHandSideMethods
|
55
|
+
|
56
|
+
private
|
57
|
+
|
58
|
+
# Produces a proxy expression for the lhs module.
|
59
|
+
def expression(params)
|
60
|
+
# We extract the integer and continue as if it had been specified as
|
61
|
+
# left hand side. This might be elegant, but it could get away with
|
62
|
+
# fewer constraints at times (when only equality is used) and
|
63
|
+
# propagation strength can't be specified.
|
64
|
+
# TODO: cut down on the number of constraints when possible. See if
|
65
|
+
# there's some neat way of getting the above remarks.
|
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))
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
module Gecode::Constraints::Int
|
2
|
+
class Expression
|
3
|
+
# Creates a domain constraint using the specified domain.
|
4
|
+
def in(domain, options = {})
|
5
|
+
@params.update(Gecode::Constraints::Util.decode_options(options))
|
6
|
+
@params[:domain] = domain
|
7
|
+
if domain.kind_of? Range
|
8
|
+
@model.add_constraint Domain::RangeDomainConstraint.new(@model, @params)
|
9
|
+
else
|
10
|
+
@model.add_constraint Domain::NonRangeDomainConstraint.new(@model,
|
11
|
+
@params)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
# A module that gathers the classes and modules used in domain constraints.
|
17
|
+
module Domain
|
18
|
+
# Describes a range domain constraint.
|
19
|
+
class RangeDomainConstraint < Gecode::Constraints::ReifiableConstraint
|
20
|
+
def post
|
21
|
+
var, domain, reif_var, strength = @params.values_at(:lhs, :domain,
|
22
|
+
:reif, :strength)
|
23
|
+
(params = []) << var.bind
|
24
|
+
params << domain.first << domain.last
|
25
|
+
params << reif_var.bind if reif_var.respond_to? :bind
|
26
|
+
params << strength
|
27
|
+
Gecode::Raw::dom(@model.active_space, *params)
|
28
|
+
end
|
29
|
+
negate_using_reification
|
30
|
+
end
|
31
|
+
|
32
|
+
# Describes a non-range domain constraint.
|
33
|
+
class NonRangeDomainConstraint < Gecode::Constraints::ReifiableConstraint
|
34
|
+
def post
|
35
|
+
space = @model.active_space
|
36
|
+
|
37
|
+
var, domain, reif_var, strength = @params.values_at(:lhs, :domain,
|
38
|
+
:reif, :strength)
|
39
|
+
domain = domain.to_a
|
40
|
+
|
41
|
+
(params = []) << var.bind
|
42
|
+
params << Gecode::Raw::IntSet.new(domain, domain.size)
|
43
|
+
params << reif_var.bind if reif_var.respond_to? :bind
|
44
|
+
params << strength
|
45
|
+
Gecode::Raw::dom(space, *params)
|
46
|
+
end
|
47
|
+
negate_using_reification
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -8,9 +8,14 @@ module Gecode
|
|
8
8
|
|
9
9
|
# Creates a linear expression where the int variable is multiplied with
|
10
10
|
# a constant integer.
|
11
|
+
alias_method :pre_linear_mult, :* if instance_methods.include? '*'
|
11
12
|
def *(int)
|
12
|
-
|
13
|
-
|
13
|
+
if int.kind_of? Fixnum
|
14
|
+
Gecode::Constraints::Int::Linear::ExpressionNode.new(self,
|
15
|
+
@model) * int
|
16
|
+
else
|
17
|
+
pre_linear_mult(int) if respond_to? :pre_linear_mult
|
18
|
+
end
|
14
19
|
end
|
15
20
|
|
16
21
|
# Creates a linear expression where the specified variable is subtracted
|
@@ -23,55 +28,24 @@ module Gecode
|
|
23
28
|
|
24
29
|
module Constraints::Int
|
25
30
|
class Expression
|
26
|
-
private
|
27
|
-
|
28
|
-
# Maps the names of the methods to the corresponding integer relation
|
29
|
-
# type in Gecode.
|
30
|
-
RELATION_TYPES = {
|
31
|
-
:== => Gecode::Raw::IRT_EQ,
|
32
|
-
:<= => Gecode::Raw::IRT_LQ,
|
33
|
-
:< => Gecode::Raw::IRT_LE,
|
34
|
-
:>= => Gecode::Raw::IRT_GQ,
|
35
|
-
:> => Gecode::Raw::IRT_GR }
|
36
|
-
# The same as above, but negated.
|
37
|
-
NEGATED_RELATION_TYPES = {
|
38
|
-
:== => Gecode::Raw::IRT_NQ,
|
39
|
-
:<= => Gecode::Raw::IRT_GR,
|
40
|
-
:< => Gecode::Raw::IRT_GQ,
|
41
|
-
:>= => Gecode::Raw::IRT_LE,
|
42
|
-
:> => Gecode::Raw::IRT_LQ
|
43
|
-
}
|
44
|
-
|
45
|
-
# Various method aliases for the class. Maps the original name to an
|
46
|
-
# array of aliases.
|
47
|
-
METHOD_ALIASES = {
|
48
|
-
:== => [:equal, :equal_to],
|
49
|
-
:> => [:greater, :greater_than],
|
50
|
-
:>= => [:greater_or_equal, :greater_than_or_equal_to],
|
51
|
-
:< => [:less, :less_than],
|
52
|
-
:<= => [:less_or_equal, :less_than_or_equal_to]
|
53
|
-
}
|
54
|
-
|
55
|
-
public
|
56
|
-
|
57
31
|
# Add some relation selection based on whether the expression is negated.
|
58
32
|
alias_method :pre_linear_initialize, :initialize
|
59
33
|
def initialize(model, params)
|
60
34
|
pre_linear_initialize(model, params)
|
61
35
|
unless params[:negate]
|
62
|
-
@method_relations = RELATION_TYPES
|
36
|
+
@method_relations = Constraints::Util::RELATION_TYPES
|
63
37
|
else
|
64
|
-
@method_relations = NEGATED_RELATION_TYPES
|
38
|
+
@method_relations = Constraints::Util::NEGATED_RELATION_TYPES
|
65
39
|
end
|
66
40
|
end
|
67
41
|
|
68
42
|
# Define the relation methods.
|
69
|
-
RELATION_TYPES.each_key do |name|
|
43
|
+
Constraints::Util::RELATION_TYPES.each_key do |name|
|
70
44
|
module_eval <<-"end_code"
|
71
45
|
def #{name}(expression, options = {})
|
72
46
|
relation = @method_relations[:#{name}]
|
73
47
|
@params.update(
|
74
|
-
Gecode::Constraints::
|
48
|
+
Gecode::Constraints::Util.decode_options(options))
|
75
49
|
if self.simple_expression? and simple_expression?(expression)
|
76
50
|
# A relation constraint is enough.
|
77
51
|
add_relation_constraint(relation, expression)
|
@@ -81,13 +55,7 @@ module Gecode
|
|
81
55
|
end
|
82
56
|
end_code
|
83
57
|
end
|
84
|
-
|
85
|
-
# Various aliases.
|
86
|
-
METHOD_ALIASES.each_pair do |orig, alias_names|
|
87
|
-
alias_names.each do |name|
|
88
|
-
alias_method name, orig
|
89
|
-
end
|
90
|
-
end
|
58
|
+
alias_comparison_methods
|
91
59
|
|
92
60
|
protected
|
93
61
|
|
@@ -0,0 +1,72 @@
|
|
1
|
+
module Gecode::IntEnumMethods
|
2
|
+
# Starts an arithmetic max constraint. This overrides the normal enum max, but
|
3
|
+
# that's not a problem since variables are not implemented to be comparable.
|
4
|
+
def max
|
5
|
+
return Gecode::Constraints::IntEnum::Arithmetic::MaxExpressionStub.new(
|
6
|
+
@model, :lhs => self)
|
7
|
+
end
|
8
|
+
|
9
|
+
# Starts an arithmetic min constraint. This overrides the normal enum min, but
|
10
|
+
# that's not a problem since variables are not implemented to be comparable.
|
11
|
+
def min
|
12
|
+
return Gecode::Constraints::IntEnum::Arithmetic::MinExpressionStub.new(
|
13
|
+
@model, :lhs => self)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
# A module that gathers the classes and modules used by arithmetic constraints.
|
18
|
+
module Gecode::Constraints::IntEnum::Arithmetic
|
19
|
+
# Describes an expression stub started with an int var enum following by #max.
|
20
|
+
class MaxExpressionStub < Gecode::Constraints::ExpressionStub
|
21
|
+
include Gecode::Constraints::LeftHandSideMethods
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
# Produces an expression for the lhs module.
|
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.
|
33
|
+
|
34
|
+
params.update(@params)
|
35
|
+
lhs = params[:lhs]
|
36
|
+
proxy = @model.int_var(lhs.domain_range)
|
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))
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
# Describes an expression stub started with an int var enum following by #min.
|
47
|
+
class MinExpressionStub < Gecode::Constraints::ExpressionStub
|
48
|
+
include Gecode::Constraints::LeftHandSideMethods
|
49
|
+
|
50
|
+
private
|
51
|
+
|
52
|
+
# Produces an expression for the lhs module.
|
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
|
65
|
+
|
66
|
+
Gecode::Raw::min(@model.active_space, lhs, proxy.bind,
|
67
|
+
Gecode::Raw::ICL_DEF)
|
68
|
+
Gecode::Constraints::Int::Expression.new(@model,
|
69
|
+
params.update(:lhs => proxy))
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module Gecode::Constraints::IntEnum
|
2
|
+
class Expression
|
3
|
+
# Posts a channel constraint on the variables in the enum with the specified
|
4
|
+
# other enum.
|
5
|
+
def channel(enum, options = {})
|
6
|
+
if @params[:negate]
|
7
|
+
raise Gecode::MissingConstraintError, 'A negated channel constraint ' +
|
8
|
+
'is not implemented.'
|
9
|
+
end
|
10
|
+
|
11
|
+
@params.update(Gecode::Constraints::Util.decode_options(options))
|
12
|
+
@params.update(:rhs => enum)
|
13
|
+
@model.add_constraint Channel::ChannelConstraint.new(@model, @params)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
# A module that gathers the classes and modules used in channel constraints.
|
18
|
+
module Channel
|
19
|
+
# Describes a channel constraint.
|
20
|
+
class ChannelConstraint < Gecode::Constraints::Constraint
|
21
|
+
def post
|
22
|
+
lhs, rhs, strength = @params.values_at(:lhs, :rhs, :strength)
|
23
|
+
|
24
|
+
# Bind both sides.
|
25
|
+
lhs = lhs.to_int_var_array
|
26
|
+
rhs = rhs.to_int_var_array
|
27
|
+
|
28
|
+
Gecode::Raw::channel(@model.active_space, lhs, rhs, strength)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,90 @@
|
|
1
|
+
module Gecode
|
2
|
+
module IntEnumMethods
|
3
|
+
# Specifies that a specific element should be counted, starting a count
|
4
|
+
# constraint. The element can be either an int var or a fixnum.
|
5
|
+
def count(element)
|
6
|
+
unless element.kind_of?(FreeIntVar) or element.kind_of?(Fixnum)
|
7
|
+
raise TypeError, 'Elements used with count can not be of type ' +
|
8
|
+
"#{element.class}."
|
9
|
+
end
|
10
|
+
params = {:lhs => self, :element => element}
|
11
|
+
return Gecode::Constraints::IntEnum::Count::ExpressionStub.new(
|
12
|
+
@model, params)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
# A module that gathers the classes and modules used in count constraints.
|
18
|
+
module Gecode::Constraints::IntEnum::Count
|
19
|
+
|
20
|
+
|
21
|
+
# Describes an expression stub started with an int var enum followed by
|
22
|
+
# #count .
|
23
|
+
class ExpressionStub < Gecode::Constraints::ExpressionStub
|
24
|
+
include Gecode::Constraints::LeftHandSideMethods
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
# Produces an expression with the element for the lhs module.
|
29
|
+
def expression(params)
|
30
|
+
params.update(@params)
|
31
|
+
Gecode::Constraints::IntEnum::Count::Expression.new(@model, params)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
# Describes an expression
|
36
|
+
class Expression < Gecode::Constraints::IntEnum::Expression
|
37
|
+
def initialize(model, params)
|
38
|
+
super
|
39
|
+
unless params[:negate]
|
40
|
+
@method_relations = Gecode::Constraints::Util::RELATION_TYPES
|
41
|
+
else
|
42
|
+
@method_relations = Gecode::Constraints::Util::NEGATED_RELATION_TYPES
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
Gecode::Constraints::Util::RELATION_TYPES.each_pair do |name, type|
|
47
|
+
class_eval <<-"end_code"
|
48
|
+
def #{name}(expression, options = {})
|
49
|
+
unless expression.kind_of?(Fixnum) or
|
50
|
+
expression.kind_of?(Gecode::FreeIntVar)
|
51
|
+
raise TypeError, 'Invalid right hand side of count constraint: ' +
|
52
|
+
"\#{expression.class}."
|
53
|
+
end
|
54
|
+
|
55
|
+
relation = @method_relations[:#{name}]
|
56
|
+
@params.update(Gecode::Constraints::Util.decode_options(options))
|
57
|
+
@params.update(:rhs => expression, :relation_type => relation)
|
58
|
+
@model.add_constraint CountConstraint.new(@model, @params)
|
59
|
+
end
|
60
|
+
end_code
|
61
|
+
end
|
62
|
+
alias_comparison_methods
|
63
|
+
end
|
64
|
+
|
65
|
+
# Describes a count constraint.
|
66
|
+
class CountConstraint < Gecode::Constraints::ReifiableConstraint
|
67
|
+
def post
|
68
|
+
lhs, element, relation_type, rhs, strength, reif_var =
|
69
|
+
@params.values_at(:lhs, :element, :relation_type, :rhs, :strength,
|
70
|
+
:reif)
|
71
|
+
|
72
|
+
# Bind variables if needed.
|
73
|
+
element = element.bind if element.respond_to? :bind
|
74
|
+
rhs = rhs.bind if rhs.respond_to? :bind
|
75
|
+
|
76
|
+
# Post the constraint to gecode.
|
77
|
+
if reif_var.nil?
|
78
|
+
Gecode::Raw::count(@model.active_space, lhs.to_int_var_array,
|
79
|
+
element, relation_type, rhs, strength)
|
80
|
+
else
|
81
|
+
# We use a proxy int variable to get the reification.
|
82
|
+
proxy = @model.int_var(rhs.min..rhs.max)
|
83
|
+
rel = Gecode::Constraints::Util::RELATION_TYPES.invert[relation_type]
|
84
|
+
proxy.must.send(rel, @params[:rhs], :reify => reif_var)
|
85
|
+
Gecode::Raw::count(@model.active_space, lhs.to_int_var_array,
|
86
|
+
element, Gecode::Raw::IRT_EQ, proxy.bind, strength)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
@@ -7,7 +7,7 @@ module Gecode
|
|
7
7
|
offsets = *offsets
|
8
8
|
end
|
9
9
|
params = {:lhs => self, :offsets => offsets}
|
10
|
-
return Gecode::Constraints::IntEnum::Distinct::
|
10
|
+
return Gecode::Constraints::IntEnum::Distinct::OffsetExpressionStub.new(
|
11
11
|
@model, params)
|
12
12
|
end
|
13
13
|
end
|
@@ -25,7 +25,7 @@ module Gecode::Constraints::IntEnum
|
|
25
25
|
end
|
26
26
|
|
27
27
|
@model.add_constraint Distinct::DistinctConstraint.new(@model,
|
28
|
-
@params.update(Gecode::Constraints::
|
28
|
+
@params.update(Gecode::Constraints::Util.decode_options(options)))
|
29
29
|
end
|
30
30
|
end
|
31
31
|
|
@@ -33,14 +33,9 @@ module Gecode::Constraints::IntEnum
|
|
33
33
|
module Distinct
|
34
34
|
# Describes an expression started with an int var enum following with
|
35
35
|
# #with_offsets .
|
36
|
-
class
|
36
|
+
class OffsetExpressionStub < Gecode::Constraints::ExpressionStub
|
37
37
|
include Gecode::Constraints::LeftHandSideMethods
|
38
38
|
|
39
|
-
def initialize(model, params)
|
40
|
-
@model = model
|
41
|
-
@params = params
|
42
|
-
end
|
43
|
-
|
44
39
|
private
|
45
40
|
|
46
41
|
# Produces an expression with offsets for the lhs module.
|
@@ -0,0 +1,75 @@
|
|
1
|
+
# A module that gathers the classes and modules used by element constraints.
|
2
|
+
module Gecode::Constraints::IntEnum::Element
|
3
|
+
# Describes an expression stub started with an int var enum following with an
|
4
|
+
# array access using an integer variables .
|
5
|
+
class ExpressionStub < Gecode::Constraints::ExpressionStub
|
6
|
+
include Gecode::Constraints::LeftHandSideMethods
|
7
|
+
|
8
|
+
private
|
9
|
+
|
10
|
+
# Produces an expression with position for the lhs module.
|
11
|
+
def expression(params)
|
12
|
+
# We extract the integer and continue as if it had been specified as
|
13
|
+
# left hand side. This might be elegant, but it could get away with
|
14
|
+
# fewer constraints at times (when only equality is used) and
|
15
|
+
# propagation strength can't be specified.
|
16
|
+
# TODO: cut down on the number of constraints when possible. See if
|
17
|
+
# there's some neat way of getting the above remarks.
|
18
|
+
|
19
|
+
params.update(@params)
|
20
|
+
enum, position = params.values_at(:lhs, :position)
|
21
|
+
tmp = @model.int_var(enum.domain_range)
|
22
|
+
enum = enum.to_int_var_array if enum.respond_to? :to_int_var_array
|
23
|
+
|
24
|
+
Gecode::Raw::element(@model.active_space, enum,
|
25
|
+
position.bind, tmp.bind, Gecode::Raw::ICL_DEF)
|
26
|
+
Gecode::Constraints::Int::Expression.new(@model,
|
27
|
+
params.update(:lhs => tmp))
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
# Methods needed to add support for element constraints to enums.
|
32
|
+
module AdditionalEnumMethods
|
33
|
+
# This adds the adder for the methods in the modules including it. The
|
34
|
+
# reason for doing it so indirect is that the first #[] won't be defined
|
35
|
+
# before the module that this is mixed into is mixed into an enum.
|
36
|
+
def self.included(enum_mod)
|
37
|
+
enum_mod.module_eval do
|
38
|
+
# Now we enter the module AdditionalEnumMethods is mixed into.
|
39
|
+
class << self
|
40
|
+
alias_method :pre_element_included, :included
|
41
|
+
def included(mod)
|
42
|
+
mod.module_eval do
|
43
|
+
# Now we enter the module that the module possibly defining #[]
|
44
|
+
# is mixed into.
|
45
|
+
if instance_methods.include? '[]'
|
46
|
+
alias_method :pre_element_access, :[]
|
47
|
+
end
|
48
|
+
|
49
|
+
def [](*vars)
|
50
|
+
# Hook in an element constraint if a variable is used for array
|
51
|
+
# access.
|
52
|
+
if vars.first.kind_of? Gecode::FreeIntVar
|
53
|
+
params = {:lhs => self, :position => vars.first}
|
54
|
+
return Gecode::Constraints::IntEnum::Element::ExpressionStub.new(
|
55
|
+
@model, params)
|
56
|
+
else
|
57
|
+
pre_element_access(*vars) if respond_to? :pre_element_access
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
pre_element_included(mod)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
module Gecode::IntEnumMethods
|
70
|
+
include Gecode::Constraints::IntEnum::Element::AdditionalEnumMethods
|
71
|
+
end
|
72
|
+
|
73
|
+
module Gecode::FixnumEnumMethods
|
74
|
+
include Gecode::Constraints::IntEnum::Element::AdditionalEnumMethods
|
75
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module Gecode::Constraints::IntEnum
|
2
|
+
class Expression
|
3
|
+
# Posts an equality constraint on the variables in the enum.
|
4
|
+
def equal(options = {})
|
5
|
+
if @params[:negate]
|
6
|
+
# The best we could implement it as from here would be a bunch of
|
7
|
+
# reified pairwise inequality constraints.
|
8
|
+
raise Gecode::MissingConstraintError, 'A negated equality is not ' +
|
9
|
+
'implemented.'
|
10
|
+
end
|
11
|
+
|
12
|
+
@model.add_constraint Equality::EqualityConstraint.new(@model,
|
13
|
+
@params.update(Gecode::Constraints::Util.decode_options(options)))
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
# A module that gathers the classes and modules used in equality constraints.
|
18
|
+
module Equality
|
19
|
+
# Describes an equality constraint.
|
20
|
+
class EqualityConstraint < Gecode::Constraints::Constraint
|
21
|
+
def post
|
22
|
+
# Bind lhs.
|
23
|
+
@params[:lhs] = @params[:lhs].to_int_var_array
|
24
|
+
|
25
|
+
# Fetch the parameters to Gecode.
|
26
|
+
params = @params.values_at(:lhs, :strength)
|
27
|
+
Gecode::Raw::eq(@model.active_space, *params)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|