gecoder-with-gecode 0.7.1-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 +81 -0
- data/COPYING +17 -0
- data/LGPL-LICENSE +458 -0
- data/README +45 -0
- data/Rakefile +13 -0
- 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/send_most_money.rb +58 -0
- data/example/square_tiling.rb +84 -0
- data/example/sudoku-set.rb +110 -0
- data/example/sudoku.rb +61 -0
- data/lib/gecode.dll +0 -0
- data/lib/gecoder.rb +5 -0
- data/lib/gecoder/bindings.rb +54 -0
- data/lib/gecoder/bindings/bindings.rb +2210 -0
- data/lib/gecoder/interface.rb +8 -0
- data/lib/gecoder/interface/binding_changes.rb +313 -0
- data/lib/gecoder/interface/branch.rb +152 -0
- data/lib/gecoder/interface/constraints.rb +397 -0
- data/lib/gecoder/interface/constraints/bool/boolean.rb +246 -0
- data/lib/gecoder/interface/constraints/bool/linear.rb +29 -0
- data/lib/gecoder/interface/constraints/bool_enum/boolean.rb +84 -0
- data/lib/gecoder/interface/constraints/bool_enum_constraints.rb +8 -0
- data/lib/gecoder/interface/constraints/bool_var_constraints.rb +75 -0
- data/lib/gecoder/interface/constraints/int/arithmetic.rb +71 -0
- data/lib/gecoder/interface/constraints/int/domain.rb +78 -0
- data/lib/gecoder/interface/constraints/int/linear.rb +295 -0
- data/lib/gecoder/interface/constraints/int_enum/arithmetic.rb +72 -0
- data/lib/gecoder/interface/constraints/int_enum/channel.rb +100 -0
- data/lib/gecoder/interface/constraints/int_enum/count.rb +92 -0
- data/lib/gecoder/interface/constraints/int_enum/distinct.rb +69 -0
- data/lib/gecoder/interface/constraints/int_enum/element.rb +82 -0
- data/lib/gecoder/interface/constraints/int_enum/equality.rb +38 -0
- data/lib/gecoder/interface/constraints/int_enum/sort.rb +126 -0
- data/lib/gecoder/interface/constraints/int_enum_constraints.rb +37 -0
- data/lib/gecoder/interface/constraints/int_var_constraints.rb +58 -0
- data/lib/gecoder/interface/constraints/reifiable_constraints.rb +78 -0
- data/lib/gecoder/interface/constraints/set/cardinality.rb +75 -0
- data/lib/gecoder/interface/constraints/set/connection.rb +193 -0
- data/lib/gecoder/interface/constraints/set/domain.rb +109 -0
- data/lib/gecoder/interface/constraints/set/operation.rb +132 -0
- data/lib/gecoder/interface/constraints/set/relation.rb +178 -0
- data/lib/gecoder/interface/constraints/set_enum/channel.rb +18 -0
- data/lib/gecoder/interface/constraints/set_enum/distinct.rb +80 -0
- data/lib/gecoder/interface/constraints/set_enum/operation.rb +60 -0
- data/lib/gecoder/interface/constraints/set_enum/selection.rb +217 -0
- data/lib/gecoder/interface/constraints/set_enum_constraints.rb +34 -0
- data/lib/gecoder/interface/constraints/set_var_constraints.rb +72 -0
- data/lib/gecoder/interface/enum_matrix.rb +64 -0
- data/lib/gecoder/interface/enum_wrapper.rb +153 -0
- data/lib/gecoder/interface/model.rb +251 -0
- data/lib/gecoder/interface/search.rb +123 -0
- data/lib/gecoder/interface/variables.rb +254 -0
- data/lib/gecoder/version.rb +4 -0
- data/specs/binding_changes.rb +76 -0
- data/specs/bool_var.rb +74 -0
- data/specs/branch.rb +170 -0
- data/specs/constraints/arithmetic.rb +266 -0
- data/specs/constraints/bool_enum.rb +140 -0
- data/specs/constraints/boolean.rb +232 -0
- data/specs/constraints/cardinality.rb +154 -0
- data/specs/constraints/channel.rb +126 -0
- data/specs/constraints/connection.rb +373 -0
- data/specs/constraints/constraint_helper.rb +180 -0
- data/specs/constraints/constraints.rb +74 -0
- data/specs/constraints/count.rb +139 -0
- data/specs/constraints/distinct.rb +218 -0
- data/specs/constraints/element.rb +106 -0
- data/specs/constraints/equality.rb +31 -0
- data/specs/constraints/int_domain.rb +69 -0
- data/specs/constraints/int_relation.rb +78 -0
- data/specs/constraints/linear.rb +332 -0
- data/specs/constraints/reification_sugar.rb +96 -0
- data/specs/constraints/selection.rb +292 -0
- data/specs/constraints/set_domain.rb +181 -0
- data/specs/constraints/set_operation.rb +285 -0
- data/specs/constraints/set_relation.rb +201 -0
- data/specs/constraints/sort.rb +175 -0
- data/specs/distribution.rb +14 -0
- data/specs/enum_matrix.rb +43 -0
- data/specs/enum_wrapper.rb +122 -0
- data/specs/int_var.rb +144 -0
- data/specs/logging.rb +24 -0
- data/specs/model.rb +190 -0
- data/specs/search.rb +246 -0
- data/specs/set_var.rb +68 -0
- data/specs/spec_helper.rb +93 -0
- data/tasks/all_tasks.rb +1 -0
- data/tasks/building.howto +65 -0
- data/tasks/distribution.rake +156 -0
- data/tasks/rcov.rake +17 -0
- data/tasks/specs.rake +15 -0
- data/tasks/svn.rake +11 -0
- data/tasks/website.rake +51 -0
- data/vendor/gecode/win32/lib/libgecodeint.dll +0 -0
- data/vendor/gecode/win32/lib/libgecodekernel.dll +0 -0
- data/vendor/gecode/win32/lib/libgecodeminimodel.dll +0 -0
- data/vendor/gecode/win32/lib/libgecodesearch.dll +0 -0
- data/vendor/gecode/win32/lib/libgecodeset.dll +0 -0
- data/vendor/rust/README +28 -0
- data/vendor/rust/bin/cxxgenerator.rb +93 -0
- data/vendor/rust/include/rust_checks.hh +115 -0
- data/vendor/rust/include/rust_conversions.hh +102 -0
- data/vendor/rust/rust.rb +67 -0
- data/vendor/rust/rust/attribute.rb +51 -0
- data/vendor/rust/rust/bindings.rb +172 -0
- data/vendor/rust/rust/class.rb +339 -0
- data/vendor/rust/rust/constants.rb +48 -0
- data/vendor/rust/rust/container.rb +110 -0
- data/vendor/rust/rust/cppifaceparser.rb +129 -0
- data/vendor/rust/rust/cwrapper.rb +72 -0
- data/vendor/rust/rust/cxxclass.rb +98 -0
- data/vendor/rust/rust/element.rb +81 -0
- data/vendor/rust/rust/enum.rb +63 -0
- data/vendor/rust/rust/function.rb +407 -0
- data/vendor/rust/rust/namespace.rb +61 -0
- data/vendor/rust/rust/templates/AttributeDefinition.rusttpl +17 -0
- data/vendor/rust/rust/templates/AttributeInitBinding.rusttpl +9 -0
- data/vendor/rust/rust/templates/BindingsHeader.rusttpl +24 -0
- data/vendor/rust/rust/templates/BindingsUnit.rusttpl +46 -0
- data/vendor/rust/rust/templates/CWrapperClassDefinitions.rusttpl +64 -0
- data/vendor/rust/rust/templates/ClassDeclarations.rusttpl +7 -0
- data/vendor/rust/rust/templates/ClassInitialize.rusttpl +6 -0
- data/vendor/rust/rust/templates/ConstructorStub.rusttpl +21 -0
- data/vendor/rust/rust/templates/CxxClassDefinitions.rusttpl +91 -0
- data/vendor/rust/rust/templates/CxxMethodStub.rusttpl +12 -0
- data/vendor/rust/rust/templates/CxxStandaloneClassDefinitions.rusttpl +26 -0
- data/vendor/rust/rust/templates/EnumDeclarations.rusttpl +3 -0
- data/vendor/rust/rust/templates/EnumDefinitions.rusttpl +29 -0
- data/vendor/rust/rust/templates/FunctionDefinition.rusttpl +9 -0
- data/vendor/rust/rust/templates/FunctionInitAlias.rusttpl +5 -0
- data/vendor/rust/rust/templates/FunctionInitBinding.rusttpl +9 -0
- data/vendor/rust/rust/templates/MethodInitBinding.rusttpl +9 -0
- data/vendor/rust/rust/templates/ModuleDeclarations.rusttpl +3 -0
- data/vendor/rust/rust/templates/ModuleDefinitions.rusttpl +3 -0
- data/vendor/rust/rust/templates/StandaloneClassDeclarations.rusttpl +7 -0
- data/vendor/rust/rust/templates/VariableFunctionCall.rusttpl +14 -0
- data/vendor/rust/rust/type.rb +98 -0
- data/vendor/rust/test/Makefile +4 -0
- data/vendor/rust/test/constants.rb +36 -0
- data/vendor/rust/test/cppclass.cc +45 -0
- data/vendor/rust/test/cppclass.hh +67 -0
- data/vendor/rust/test/cppclass.rb +59 -0
- data/vendor/rust/test/cwrapper.c +74 -0
- data/vendor/rust/test/cwrapper.h +41 -0
- data/vendor/rust/test/cwrapper.rb +56 -0
- data/vendor/rust/test/dummyclass.hh +31 -0
- data/vendor/rust/test/lib/extension-test.rb +98 -0
- 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-constants.rb +43 -0
- data/vendor/rust/test/test-cppclass.rb +82 -0
- data/vendor/rust/test/test-cwrapper.rb +80 -0
- data/vendor/rust/test/test-operators.rb +42 -0
- metadata +293 -0
@@ -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 #:nodoc:
|
19
|
+
# Describes a CompositeStub for the max constraint, which constrains the
|
20
|
+
# maximum value of the integer variables in an enumeration.
|
21
|
+
#
|
22
|
+
# == Example
|
23
|
+
#
|
24
|
+
# # The maximum must be positive.
|
25
|
+
# int_enum.max.must > 0
|
26
|
+
#
|
27
|
+
# # The maximum must equal a integer variable +max+.
|
28
|
+
# int_enum.max.must == max
|
29
|
+
#
|
30
|
+
# # The maximum must not be negative. The constraint is reified with the
|
31
|
+
# # boolean variable +is_negative+ and strength +domain+ is selected.
|
32
|
+
# int_enum.max.must_not_be.less_than(0, :reify => is_negative,
|
33
|
+
# :strength => :domain)
|
34
|
+
class MaxExpressionStub < Gecode::Constraints::Int::CompositeStub
|
35
|
+
def constrain_equal(variable, params, constrain)
|
36
|
+
enum, strength = @params.values_at(:lhs, :strength)
|
37
|
+
if constrain
|
38
|
+
variable.must_be.in enum.domain_range
|
39
|
+
end
|
40
|
+
|
41
|
+
Gecode::Raw::max(@model.active_space, enum.to_int_var_array,
|
42
|
+
variable.bind, strength)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
# Describes a CompositeStub for the min constraint, which constrains the
|
47
|
+
# minimum value of the integer variables in an enumeration.
|
48
|
+
#
|
49
|
+
# == Example
|
50
|
+
#
|
51
|
+
# # The minimum must be positive.
|
52
|
+
# int_enum.min.must > 0
|
53
|
+
#
|
54
|
+
# # The minimum must equal a integer variable +min+.
|
55
|
+
# int_enum.min.must == min
|
56
|
+
#
|
57
|
+
# # The minimum must not be non-positive. The constraint is reified with the
|
58
|
+
# # boolean variable +is_positive+ and strength +domain+ is selected.
|
59
|
+
# int_enum.min.must_not_be.less_or_equal(0, :reify => is_positive,
|
60
|
+
# :strength => :domain)
|
61
|
+
class MinExpressionStub < Gecode::Constraints::Int::CompositeStub
|
62
|
+
def constrain_equal(variable, params, constrain)
|
63
|
+
enum, strength = @params.values_at(:lhs, :strength)
|
64
|
+
if constrain
|
65
|
+
variable.must_be.in enum.domain_range
|
66
|
+
end
|
67
|
+
|
68
|
+
Gecode::Raw::min(@model.active_space, enum.to_int_var_array,
|
69
|
+
variable.bind, strength)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
@@ -0,0 +1,100 @@
|
|
1
|
+
module Gecode::Constraints::IntEnum
|
2
|
+
class Expression
|
3
|
+
# Adds a channel constraint on the variables in the enum with the specified
|
4
|
+
# other set or int 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
|
+
unless enum.respond_to?(:to_int_var_array) or
|
11
|
+
enum.respond_to?(:to_set_var_array)
|
12
|
+
raise TypeError, "Expected int or set enum, got #{enum.class}."
|
13
|
+
end
|
14
|
+
|
15
|
+
@params.update(Gecode::Constraints::Util.decode_options(options))
|
16
|
+
@params.update(:rhs => enum)
|
17
|
+
@model.add_constraint Channel::ChannelConstraint.new(@model, @params)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
# A module that gathers the classes and modules used in channel constraints.
|
22
|
+
module Channel #:nodoc:
|
23
|
+
# Describes a channel constraint which "channels" two enumerations of
|
24
|
+
# integer variables or one enumeration of integer variables and one
|
25
|
+
# enumeration of set variables. Channel constraints are used to give
|
26
|
+
# access to multiple viewpoints when modelling.
|
27
|
+
#
|
28
|
+
# When used on two integer enumeration, the channel constraint can be
|
29
|
+
# thought of as constraining the arrays to be each other's inverses. When
|
30
|
+
# used with an enumeration of sets the i:th set includes the value of the
|
31
|
+
# j:th integer.
|
32
|
+
#
|
33
|
+
# Neither reification nor negation is supported. Selecting strength is only
|
34
|
+
# supported when using the constraint between two integer enumerations,
|
35
|
+
# it's not supported when a set enumeration is used.
|
36
|
+
#
|
37
|
+
# == Example
|
38
|
+
#
|
39
|
+
# Lets say that we’re modelling a sequence of numbers that must be distinct
|
40
|
+
# and that we want access to the following two view simultaneously.
|
41
|
+
#
|
42
|
+
# === First view
|
43
|
+
#
|
44
|
+
# The sequence is modelled as an array of integer variables where the first
|
45
|
+
# variable holds the value of the first position in the sequence, the
|
46
|
+
# second the value of the second position and so on.
|
47
|
+
#
|
48
|
+
# # n variables with values from 0 to n-1.
|
49
|
+
# elements = int_var_array(n, 0...n)
|
50
|
+
# elements.must_be.distinct
|
51
|
+
#
|
52
|
+
# That way +elements+ will contain the actual sequence when the problem has
|
53
|
+
# been solved.
|
54
|
+
#
|
55
|
+
# === Second view
|
56
|
+
#
|
57
|
+
# The sequence is modelled as the positions of each value in 0..(n-1) in
|
58
|
+
# the sequence. That way the first variable would hold the positions of 0
|
59
|
+
# in the sequence, the second variable would hold the positions of 1 in the
|
60
|
+
# sequence and so on.
|
61
|
+
#
|
62
|
+
# positions = int_var_array(n, 0...n)
|
63
|
+
# positions.must_be.distinct
|
64
|
+
#
|
65
|
+
# === Connecting the views
|
66
|
+
#
|
67
|
+
# In essence the relationship between the two arrays +elements+ and
|
68
|
+
# +positions+ is that
|
69
|
+
#
|
70
|
+
# elements.map{ |e| e.val }[i] == positions.map{ |p| p.val }.index(i)
|
71
|
+
#
|
72
|
+
# for all i in 0..(n-1). This relationship is enforced by the channel
|
73
|
+
# constraint as follows.
|
74
|
+
#
|
75
|
+
# elements.must.channel positions
|
76
|
+
#
|
77
|
+
# == Example (sets)
|
78
|
+
#
|
79
|
+
# # +set_enum+ is constrained to channel +int_enum+.
|
80
|
+
# int_enum.must.channel set_enum
|
81
|
+
#
|
82
|
+
# # This is another way of saying the above.
|
83
|
+
# set_enum.must.channel int_enum
|
84
|
+
class ChannelConstraint < Gecode::Constraints::Constraint
|
85
|
+
def post
|
86
|
+
lhs, rhs, strength = @params.values_at(:lhs, :rhs, :strength)
|
87
|
+
|
88
|
+
lhs = lhs.to_int_var_array
|
89
|
+
if rhs.respond_to? :to_int_var_array
|
90
|
+
# Int var array.
|
91
|
+
Gecode::Raw::channel(@model.active_space, lhs, rhs.to_int_var_array,
|
92
|
+
strength)
|
93
|
+
else
|
94
|
+
# Set var array, no strength.
|
95
|
+
Gecode::Raw::channel(@model.active_space, lhs, rhs.to_set_var_array)
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
@@ -0,0 +1,92 @@
|
|
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
|
+
Gecode::Constraints::SimpleExpressionStub.new(@model, params) do |m, ps|
|
12
|
+
Gecode::Constraints::IntEnum::Count::Expression.new(m, ps)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
# A module that gathers the classes and modules used in count constraints.
|
19
|
+
module Gecode::Constraints::IntEnum::Count #:nodoc:
|
20
|
+
# Describes an expression
|
21
|
+
class Expression < Gecode::Constraints::IntEnum::Expression #:nodoc:
|
22
|
+
def initialize(model, params)
|
23
|
+
super
|
24
|
+
unless params[:negate]
|
25
|
+
@method_relations = Gecode::Constraints::Util::RELATION_TYPES
|
26
|
+
else
|
27
|
+
@method_relations = Gecode::Constraints::Util::NEGATED_RELATION_TYPES
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
Gecode::Constraints::Util::RELATION_TYPES.each_pair do |name, type|
|
32
|
+
class_eval <<-"end_code"
|
33
|
+
def #{name}(expression, options = {})
|
34
|
+
unless expression.kind_of?(Fixnum) or
|
35
|
+
expression.kind_of?(Gecode::FreeIntVar)
|
36
|
+
raise TypeError, 'Invalid right hand side of count constraint: ' +
|
37
|
+
"\#{expression.class}."
|
38
|
+
end
|
39
|
+
|
40
|
+
relation = @method_relations[:#{name}]
|
41
|
+
@params.update(Gecode::Constraints::Util.decode_options(options))
|
42
|
+
@params.update(:rhs => expression, :relation_type => relation)
|
43
|
+
@model.add_constraint CountConstraint.new(@model, @params)
|
44
|
+
end
|
45
|
+
end_code
|
46
|
+
end
|
47
|
+
alias_comparison_methods
|
48
|
+
end
|
49
|
+
|
50
|
+
# Describes a count constraint, which constrains the number of times a value
|
51
|
+
# (constant or a variable) may occurr in an enumeration of integer variable.
|
52
|
+
#
|
53
|
+
# All relations available for +SimpleRelationConstraint+ can be used with
|
54
|
+
# count constraints. Negation and reification is supported.
|
55
|
+
#
|
56
|
+
# == Examples
|
57
|
+
#
|
58
|
+
# # Constrain +int_enum+ to not contain 0 exactly once.
|
59
|
+
# int_enum.count(0).must_not == 1
|
60
|
+
#
|
61
|
+
# # Constrain +int_enum+ to contain +x+ exactly +x_count+ times.
|
62
|
+
# int_enum.count(x).must == x_count
|
63
|
+
#
|
64
|
+
# # Reifies the constraint that +int_enum+ has +x+ zeros with the boolean
|
65
|
+
# # variable +has_x_zeros+ and selects the strength +domain+.
|
66
|
+
# int_enum.count(0).must.equal(x, :reify => has_x_zeros,
|
67
|
+
# :strength => :domain)
|
68
|
+
class CountConstraint < Gecode::Constraints::ReifiableConstraint
|
69
|
+
def post
|
70
|
+
lhs, element, relation_type, rhs, strength, reif_var =
|
71
|
+
@params.values_at(:lhs, :element, :relation_type, :rhs, :strength,
|
72
|
+
:reif)
|
73
|
+
|
74
|
+
# Bind variables if needed.
|
75
|
+
element = element.bind if element.respond_to? :bind
|
76
|
+
rhs = rhs.bind if rhs.respond_to? :bind
|
77
|
+
|
78
|
+
# Post the constraint to gecode.
|
79
|
+
if reif_var.nil?
|
80
|
+
Gecode::Raw::count(@model.active_space, lhs.to_int_var_array,
|
81
|
+
element, relation_type, rhs, strength)
|
82
|
+
else
|
83
|
+
# We use a proxy int variable to get the reification.
|
84
|
+
proxy = @model.int_var(rhs.min..rhs.max)
|
85
|
+
rel = Gecode::Constraints::Util::RELATION_TYPES.invert[relation_type]
|
86
|
+
proxy.must.send(rel, @params[:rhs], :reify => reif_var)
|
87
|
+
Gecode::Raw::count(@model.active_space, lhs.to_int_var_array,
|
88
|
+
element, Gecode::Raw::IRT_EQ, proxy.bind, strength)
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
module Gecode
|
2
|
+
module IntEnumMethods
|
3
|
+
# Specifies offsets to be used with a distinct constraint. The offsets can
|
4
|
+
# be specified one by one or as an array of offsets.
|
5
|
+
def with_offsets(*offsets)
|
6
|
+
if offsets.kind_of? Enumerable
|
7
|
+
offsets = *offsets
|
8
|
+
end
|
9
|
+
params = {:lhs => self, :offsets => offsets}
|
10
|
+
|
11
|
+
Gecode::Constraints::SimpleExpressionStub.new(@model, params) do |m, ps|
|
12
|
+
Gecode::Constraints::IntEnum::Expression.new(m, ps)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
module Gecode::Constraints::IntEnum
|
19
|
+
class Expression
|
20
|
+
# Posts a distinct constraint on the variables in the enum.
|
21
|
+
def distinct(options = {})
|
22
|
+
if @params[:negate]
|
23
|
+
# The best we could implement it as from here would be a bunch of
|
24
|
+
# reified pairwise equality constraints.
|
25
|
+
raise Gecode::MissingConstraintError, 'A negated distinct is not ' +
|
26
|
+
'implemented.'
|
27
|
+
end
|
28
|
+
|
29
|
+
@model.add_constraint Distinct::DistinctConstraint.new(@model,
|
30
|
+
@params.update(Gecode::Constraints::Util.decode_options(options)))
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
# A module that gathers the classes and modules used in distinct constraints.
|
35
|
+
module Distinct #:nodoc:
|
36
|
+
# Describes a distinct constraint, which constrains all integer variables
|
37
|
+
# in an enumeration to be distinct (different). The constraint can also be
|
38
|
+
# used with constant offsets, so that the variables, with specified offsets
|
39
|
+
# added, must be distinct.
|
40
|
+
#
|
41
|
+
# The constraint does not support negation nor reification.
|
42
|
+
#
|
43
|
+
# == Examples
|
44
|
+
#
|
45
|
+
# # Constrains all variables in +int_enum+ to be assigned different
|
46
|
+
# # values.
|
47
|
+
# int_enum.must_be.distinct
|
48
|
+
#
|
49
|
+
# # The same as above, but also selects that the strength +domain+ should
|
50
|
+
# # be used.
|
51
|
+
# int_enum.must_be.distinct(:strength => :domain)
|
52
|
+
#
|
53
|
+
# # Uses the offset to constrain that no number may be the previous number
|
54
|
+
# # incremented by one.
|
55
|
+
# numbers = int_var_array(8, 0..9)
|
56
|
+
# numbers.with_offset((1..numbers.size).to_a.reverse).must_be.distinct
|
57
|
+
class DistinctConstraint < Gecode::Constraints::Constraint
|
58
|
+
def post
|
59
|
+
# Bind lhs.
|
60
|
+
@params[:lhs] = @params[:lhs].to_int_var_array
|
61
|
+
|
62
|
+
# Fetch the parameters to Gecode.
|
63
|
+
params = @params.values_at(:offsets, :lhs, :strength)
|
64
|
+
params.delete_if{ |x| x.nil? }
|
65
|
+
Gecode::Raw::distinct(@model.active_space, *params)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
# A module that gathers the classes and modules used by element constraints.
|
2
|
+
module Gecode::Constraints::IntEnum::Element #:nodoc:
|
3
|
+
# Describes a CompositeStub for the element constraint, which places a
|
4
|
+
# constraint on a variable at the specified position in an enumeration of
|
5
|
+
# integer variables. It's basically the array access of constraint
|
6
|
+
# programming.
|
7
|
+
#
|
8
|
+
# == Example
|
9
|
+
#
|
10
|
+
# # The variable at the +x+:th position in +int_enum+ must be larger than
|
11
|
+
# # +y+.
|
12
|
+
# int_enum[x].must > y
|
13
|
+
#
|
14
|
+
# # The price of +selected_item+ as described by +prices+ must not be
|
15
|
+
# # larger than 100.
|
16
|
+
# prices = wrap_enum([500, 24, 4711, 412, 24])
|
17
|
+
# prices[selected_item].must_not > 100
|
18
|
+
#
|
19
|
+
# # Reify the constraint that the +x+:th variable in +int_enum+ must be in
|
20
|
+
# # range 7..17 with the boolean variable +bool+ and select strength
|
21
|
+
# # +domain+.
|
22
|
+
#
|
23
|
+
# int_enum[x].must_be.in(7..17, :reify => bool, :strength => :domain)
|
24
|
+
class ExpressionStub < Gecode::Constraints::Int::CompositeStub
|
25
|
+
def constrain_equal(variable, params, constrain)
|
26
|
+
enum, position, strength = @params.values_at(:lhs, :position, :strength)
|
27
|
+
if constrain
|
28
|
+
variable.must_be.in enum.domain_range
|
29
|
+
end
|
30
|
+
|
31
|
+
# The enum can be a constant array.
|
32
|
+
enum = enum.to_int_var_array if enum.respond_to? :to_int_var_array
|
33
|
+
Gecode::Raw::element(@model.active_space, enum,
|
34
|
+
position.bind, variable.bind, strength)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
# Methods needed to add support for element constraints to enums.
|
39
|
+
module AdditionalEnumMethods #:nodoc:
|
40
|
+
# This adds the adder for the methods in the modules including it. The
|
41
|
+
# reason for doing it so indirect is that the first #[] won't be defined
|
42
|
+
# before the module that this is mixed into is mixed into an enum.
|
43
|
+
def self.included(enum_mod)
|
44
|
+
enum_mod.module_eval do
|
45
|
+
# Now we enter the module AdditionalEnumMethods is mixed into.
|
46
|
+
class << self
|
47
|
+
alias_method :pre_element_included, :included
|
48
|
+
def included(mod)
|
49
|
+
mod.module_eval do
|
50
|
+
# Now we enter the module that the module possibly defining #[]
|
51
|
+
# is mixed into.
|
52
|
+
if instance_methods.include? '[]'
|
53
|
+
alias_method :pre_element_access, :[]
|
54
|
+
end
|
55
|
+
|
56
|
+
def [](*vars)
|
57
|
+
# Hook in an element constraint if a variable is used for array
|
58
|
+
# access.
|
59
|
+
if vars.first.kind_of? Gecode::FreeIntVar
|
60
|
+
params = {:lhs => self, :position => vars.first}
|
61
|
+
return Gecode::Constraints::IntEnum::Element::ExpressionStub.new(
|
62
|
+
@model, params)
|
63
|
+
else
|
64
|
+
pre_element_access(*vars) if respond_to? :pre_element_access
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
pre_element_included(mod)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
module Gecode::IntEnumMethods
|
77
|
+
include Gecode::Constraints::IntEnum::Element::AdditionalEnumMethods
|
78
|
+
end
|
79
|
+
|
80
|
+
module Gecode::FixnumEnumMethods
|
81
|
+
include Gecode::Constraints::IntEnum::Element::AdditionalEnumMethods
|
82
|
+
end
|
@@ -0,0 +1,38 @@
|
|
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 #:nodoc:
|
19
|
+
# Describes an equality constraint, which constrains all variables in an
|
20
|
+
# integer enumeration to be equal. Neither negation nor reification is
|
21
|
+
# supported.
|
22
|
+
#
|
23
|
+
# == Example
|
24
|
+
#
|
25
|
+
# # Constrains all variables in +int_enum+ to be equal.
|
26
|
+
# int_enum.must_be.equal
|
27
|
+
class EqualityConstraint < Gecode::Constraints::Constraint
|
28
|
+
def post
|
29
|
+
# Bind lhs.
|
30
|
+
@params[:lhs] = @params[:lhs].to_int_var_array
|
31
|
+
|
32
|
+
# Fetch the parameters to Gecode.
|
33
|
+
params = @params.values_at(:lhs, :strength)
|
34
|
+
Gecode::Raw::eq(@model.active_space, *params)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|