gecoder-with-gecode 0.7.1-mswin32
Sign up to get free protection for your applications and to get access to all the features.
- 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,126 @@
|
|
1
|
+
module Gecode::Constraints::IntEnum
|
2
|
+
class Expression
|
3
|
+
# Initiates a sort constraint. Beyond the common options the sort constraint
|
4
|
+
# can also take the following options:
|
5
|
+
#
|
6
|
+
# [:as] Defines a target (must be an int variable enumerable) that will
|
7
|
+
# hold the sorted version of the original enumerable. The original
|
8
|
+
# enumerable will not be affected (i.e. will not necessarily be
|
9
|
+
# sorted)
|
10
|
+
# [:order] Sets an int variable enumerable that should be used to store the
|
11
|
+
# order of the original enum's variables when sorted. The original
|
12
|
+
# enumerable will not be affected (i.e. will not necessarily be
|
13
|
+
# sorted)
|
14
|
+
#
|
15
|
+
# If neither of those options are specified then the original enumerable
|
16
|
+
# will be constrained to be sorted (otherwise not). Sort constraints with
|
17
|
+
# options do not allow negation.
|
18
|
+
def sorted(options = {})
|
19
|
+
# Extract and check options.
|
20
|
+
target = options.delete(:as)
|
21
|
+
order = options.delete(:order)
|
22
|
+
unless target.nil? or target.respond_to? :to_int_var_array
|
23
|
+
raise TypeError, 'Expected int var enum as :as, got ' +
|
24
|
+
"#{target.class}."
|
25
|
+
end
|
26
|
+
unless order.nil? or order.respond_to? :to_int_var_array
|
27
|
+
raise TypeError, 'Expected int var enum as :order, got ' +
|
28
|
+
"#{order.class}."
|
29
|
+
end
|
30
|
+
|
31
|
+
# Extract standard options and convert to constraint.
|
32
|
+
@params.update(Gecode::Constraints::Util.decode_options(options))
|
33
|
+
if target.nil? and order.nil?
|
34
|
+
@model.add_constraint Sort::SortConstraint.new(@model, @params)
|
35
|
+
else
|
36
|
+
# Do not allow negation.
|
37
|
+
if @params[:negate]
|
38
|
+
raise Gecode::MissingConstraintError, 'A negated sort with options ' +
|
39
|
+
'is not implemented.'
|
40
|
+
end
|
41
|
+
|
42
|
+
@params.update(:target => target, :order => order)
|
43
|
+
@model.add_constraint Sort::SortConstraintWithOptions.new(@model,
|
44
|
+
@params)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
# A module that gathers the classes and modules used in sort constraints.
|
50
|
+
module Sort #:nodoc:
|
51
|
+
# Describes a sort constraint which constrains a target enumeration of
|
52
|
+
# integer variables to be the sorted version of another set of integer
|
53
|
+
# variables. Optionally a third enumeration may be used to define the order
|
54
|
+
# in which the the variables should be sorted.
|
55
|
+
#
|
56
|
+
# Neither negation nor reification is supported.
|
57
|
+
#
|
58
|
+
# == Example
|
59
|
+
#
|
60
|
+
# # Constrains +sorted_numbers+ to be a sorted version of +numbers+.
|
61
|
+
# numbers.must_be.sorted(:as => sorted_numbers)
|
62
|
+
#
|
63
|
+
# # Constrains +sorted_numbers+ to be +numbers+ sorted in the order
|
64
|
+
# # described by the integer variable enumeration +order+.
|
65
|
+
# numbers.must_be.sorted(:as => sorted_numbers, :order => order)
|
66
|
+
class SortConstraintWithOptions < Gecode::Constraints::Constraint
|
67
|
+
def post
|
68
|
+
if @params[:target].nil?
|
69
|
+
# We must have a target.
|
70
|
+
lhs = @params[:lhs]
|
71
|
+
@params[:target] = @model.int_var_array(lhs.size, lhs.domain_range)
|
72
|
+
end
|
73
|
+
|
74
|
+
# Prepare the parameters.
|
75
|
+
params = @params.values_at(:lhs, :target, :order, :strength).map do |param|
|
76
|
+
if param.respond_to? :to_int_var_array
|
77
|
+
param.to_int_var_array
|
78
|
+
else
|
79
|
+
param
|
80
|
+
end
|
81
|
+
end.delete_if{ |param| param.nil? }
|
82
|
+
# Post the constraint.
|
83
|
+
Gecode::Raw::sortedness(@model.active_space, *params)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
# Describes a sort constraint which constrains an enumeration of integer
|
88
|
+
# variables to be sorted. Supports reification and negation.
|
89
|
+
#
|
90
|
+
# == Example
|
91
|
+
#
|
92
|
+
# # Constrains the variables in +int_enum+ to be sorted ascendingly.
|
93
|
+
# int_enum.must_be.sorted
|
94
|
+
#
|
95
|
+
# # Reifies the constraint that the variables in +int_enum+ to be sorted
|
96
|
+
# # ascendingly with the boolean variable +is_sorted+, while selecting
|
97
|
+
# # +domain+ as strength.
|
98
|
+
# int_enum.must_be.sorted(:reify => :is_sorted, :strength => :domain)
|
99
|
+
class SortConstraint < Gecode::Constraints::ReifiableConstraint
|
100
|
+
def post
|
101
|
+
lhs, strength, reif_var = @params.values_at(:lhs, :strength, :reif)
|
102
|
+
using_reification = !reif_var.nil?
|
103
|
+
|
104
|
+
# We translate the constraint into n-1 relation constraints.
|
105
|
+
options = {:strength =>
|
106
|
+
Gecode::Constraints::Util::PROPAGATION_STRENGTHS.invert[strength]}
|
107
|
+
if using_reification
|
108
|
+
reification_variables = @model.bool_var_array(lhs.size - 1)
|
109
|
+
end
|
110
|
+
(lhs.size - 1).times do |i|
|
111
|
+
first, second = lhs[i, 2]
|
112
|
+
rel_options = options.clone
|
113
|
+
if using_reification
|
114
|
+
# Reify each relation constraint and then bind them all together.
|
115
|
+
rel_options[:reify] = reification_variables[i]
|
116
|
+
end
|
117
|
+
first.must_be.less_than_or_equal_to(second, rel_options)
|
118
|
+
end
|
119
|
+
if using_reification
|
120
|
+
reification_variables.conjunction.must == reif_var
|
121
|
+
end
|
122
|
+
end
|
123
|
+
negate_using_reification
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module Gecode
|
2
|
+
module IntEnumMethods
|
3
|
+
include Gecode::Constraints::LeftHandSideMethods
|
4
|
+
|
5
|
+
private
|
6
|
+
|
7
|
+
# Produces an expression for the lhs module.
|
8
|
+
def expression(params)
|
9
|
+
params.update(:lhs => self)
|
10
|
+
Constraints::IntEnum::Expression.new(@model, params)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
# A module containing constraints that have enumerations of integer
|
15
|
+
# variables as left hand side.
|
16
|
+
module Constraints::IntEnum
|
17
|
+
# Expressions with int enums as left hand sides.
|
18
|
+
class Expression < Gecode::Constraints::Expression #:nodoc:
|
19
|
+
# Raises TypeError unless the left hand side is an int enum.
|
20
|
+
def initialize(model, params)
|
21
|
+
super
|
22
|
+
|
23
|
+
unless params[:lhs].respond_to? :to_int_var_array
|
24
|
+
raise TypeError, 'Must have int enum as left hand side.'
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
require 'gecoder/interface/constraints/int_enum/distinct'
|
32
|
+
require 'gecoder/interface/constraints/int_enum/equality'
|
33
|
+
require 'gecoder/interface/constraints/int_enum/channel'
|
34
|
+
require 'gecoder/interface/constraints/int_enum/element'
|
35
|
+
require 'gecoder/interface/constraints/int_enum/count'
|
36
|
+
require 'gecoder/interface/constraints/int_enum/sort'
|
37
|
+
require 'gecoder/interface/constraints/int_enum/arithmetic'
|
@@ -0,0 +1,58 @@
|
|
1
|
+
module Gecode
|
2
|
+
class FreeIntVar
|
3
|
+
include Gecode::Constraints::LeftHandSideMethods
|
4
|
+
|
5
|
+
private
|
6
|
+
|
7
|
+
# Produces an expression for the lhs module.
|
8
|
+
def expression(params)
|
9
|
+
params.update(:lhs => self)
|
10
|
+
Constraints::Int::Expression.new(@model, params)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
# A module containing constraints that have int variables as left hand side
|
15
|
+
# (but not enumerations).
|
16
|
+
module Constraints::Int
|
17
|
+
# Describes an integer expression.
|
18
|
+
class Expression < Gecode::Constraints::Expression #:nodoc:
|
19
|
+
end
|
20
|
+
|
21
|
+
# A composite expression which is an int expression with a left hand side
|
22
|
+
# resulting from a previous constraint.
|
23
|
+
class CompositeExpression < Gecode::Constraints::CompositeExpression #:nodoc:
|
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, lambda{ model.int_var }, model,
|
30
|
+
params, &block)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
# Describes a stub that produces an int variable, which can then be used
|
35
|
+
# with the normal int variable constraints. An example would be the element
|
36
|
+
# constraint.
|
37
|
+
#
|
38
|
+
# int_enum[int_var].must > rhs
|
39
|
+
#
|
40
|
+
# <tt>int_enum[int_var]</tt> produces an int variable which the constraint
|
41
|
+
# <tt>.must > rhs</tt> is then applied to. In the above case two
|
42
|
+
# constraints (and one temporary variable) are required, but in the case of
|
43
|
+
# equality only one constraint is required.
|
44
|
+
#
|
45
|
+
# Whether a constraint involving a reification stub supports negation,
|
46
|
+
# reification, strength options and so on depends on the constraint on the
|
47
|
+
# right hand side.
|
48
|
+
class CompositeStub < Gecode::Constraints::CompositeStub
|
49
|
+
def initialize(model, params)
|
50
|
+
super(CompositeExpression, model, params)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
require 'gecoder/interface/constraints/int/linear'
|
57
|
+
require 'gecoder/interface/constraints/int/domain'
|
58
|
+
require 'gecoder/interface/constraints/int/arithmetic'
|
@@ -0,0 +1,78 @@
|
|
1
|
+
module Gecode::Constraints
|
2
|
+
# Base class for all reifiable constraints.
|
3
|
+
class ReifiableConstraint < Constraint
|
4
|
+
# Gets the reification variable of the constraint, nil if none exists.
|
5
|
+
def reification_var
|
6
|
+
@params[:reif]
|
7
|
+
end
|
8
|
+
|
9
|
+
# Sets the reification variable of the constraint, nil if none should be
|
10
|
+
# used.
|
11
|
+
def reification_var=(new_var)
|
12
|
+
@params[:reif] = new_var
|
13
|
+
end
|
14
|
+
|
15
|
+
# Produces a disjunction of two reifiable constraints, producing a new
|
16
|
+
# reifiable constraint.
|
17
|
+
def |(constraint)
|
18
|
+
with_reification_variables(constraint) do |b1, b2|
|
19
|
+
# Create the disjunction constraint.
|
20
|
+
(b1 | b2).must_be.true
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
# Produces a conjunction of two reifiable constraints, producing a new
|
25
|
+
# reifiable constraint.
|
26
|
+
def &(constraint)
|
27
|
+
with_reification_variables(constraint) do |b1, b2|
|
28
|
+
# Create the conjunction constraint.
|
29
|
+
(b1 & b2).must_be.true
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
34
|
+
|
35
|
+
# Yields two boolean variables to the specified block. The first one is
|
36
|
+
# self's reification variable and the second one is the reification variable
|
37
|
+
# of the specified constraint. Reuses reification variables if possible,
|
38
|
+
# otherwise creates new ones.
|
39
|
+
def with_reification_variables(constraint, &block)
|
40
|
+
raise TypeError unless constraint.kind_of? ReifiableConstraint
|
41
|
+
|
42
|
+
# Set up the reification variables, using existing variables if they
|
43
|
+
# exist.
|
44
|
+
con1_holds = self.reification_var
|
45
|
+
con2_holds = constraint.reification_var
|
46
|
+
if con1_holds.nil?
|
47
|
+
con1_holds = @model.bool_var
|
48
|
+
self.reification_var = con1_holds
|
49
|
+
end
|
50
|
+
if con2_holds.nil?
|
51
|
+
con2_holds = @model.bool_var
|
52
|
+
constraint.reification_var = con2_holds
|
53
|
+
end
|
54
|
+
yield(con1_holds, con2_holds)
|
55
|
+
end
|
56
|
+
|
57
|
+
# If called the negation of the constraint will be handled using the
|
58
|
+
# reification variable. This means that the post method (which has to be
|
59
|
+
# defined prior to calling this method) doesn't have to bother about
|
60
|
+
# negation.
|
61
|
+
def self.negate_using_reification
|
62
|
+
class_eval do
|
63
|
+
alias_method :post_without_negation, :post
|
64
|
+
|
65
|
+
def post
|
66
|
+
if @params[:negate]
|
67
|
+
if @params[:reif].nil?
|
68
|
+
# Create a reification variable if none exists.
|
69
|
+
@params[:reif] = @model.bool_var
|
70
|
+
end
|
71
|
+
@params[:reif].must_be.false
|
72
|
+
end
|
73
|
+
post_without_negation
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
module Gecode
|
2
|
+
class FreeSetVar
|
3
|
+
# Starts a constraint on the size of the set.
|
4
|
+
def size
|
5
|
+
params = {:lhs => self}
|
6
|
+
Gecode::Constraints::Set::Cardinality::SizeExpressionStub.new(
|
7
|
+
@model, params)
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
module Gecode::Constraints::Set
|
13
|
+
# A module that gathers the classes and modules used in cardinality
|
14
|
+
# constraints.
|
15
|
+
module Cardinality #:nodoc:
|
16
|
+
# Describes a cardinality constraint specifically for ranges. This is just
|
17
|
+
# a special case which is used instead of the more general composite
|
18
|
+
# constraint when the target cardinality is a range.
|
19
|
+
class CardinalityConstraint < Gecode::Constraints::Constraint #:nodoc:
|
20
|
+
def post
|
21
|
+
var, range = @params.values_at(:lhs, :range)
|
22
|
+
Gecode::Raw::cardinality(@model.active_space, var.bind, range.first,
|
23
|
+
range.last)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
# A custom composite stub to change the composite expression used.
|
28
|
+
class CompositeStub < Gecode::Constraints::CompositeStub #:nodoc:
|
29
|
+
def initialize(model, params)
|
30
|
+
super(Expression, model, params)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
# Describes a cardinality expression started with set.size.must .
|
35
|
+
class Expression < Gecode::Constraints::Int::CompositeExpression #:nodoc:
|
36
|
+
def in(range)
|
37
|
+
if range.kind_of?(Range) and !@params[:negate]
|
38
|
+
@params.update(:range => range)
|
39
|
+
@model.add_constraint CardinalityConstraint.new(@model, @params)
|
40
|
+
else
|
41
|
+
super(range)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
# Describes a CompositeStub for the cardianlity constraint which constrains
|
47
|
+
# the cardianlity (size) of a set.
|
48
|
+
#
|
49
|
+
# == Example
|
50
|
+
#
|
51
|
+
# # The size of +set+ must be within 1..17
|
52
|
+
# set.size.must_be.in 1..17
|
53
|
+
#
|
54
|
+
# # The size must equal the integer variable +size+.
|
55
|
+
# set.size.must == size
|
56
|
+
#
|
57
|
+
# # The size must not be larger than 17
|
58
|
+
# set.size.must_not > 17
|
59
|
+
#
|
60
|
+
# # We reify the above with a boolean variable called +is_not_large+ and
|
61
|
+
# # select the strength +domain+.
|
62
|
+
# set.size.must_not_be.larger_than(17, :reify => is_not_large,
|
63
|
+
# :strength => :domain)
|
64
|
+
class SizeExpressionStub < CompositeStub
|
65
|
+
def constrain_equal(variable, params, constrain)
|
66
|
+
lhs = @params[:lhs]
|
67
|
+
if constrain
|
68
|
+
variable.must_be.in lhs.lower_bound.size..lhs.upper_bound.size
|
69
|
+
end
|
70
|
+
|
71
|
+
Gecode::Raw::cardinality(@model.active_space, lhs.bind, variable.bind)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
@@ -0,0 +1,193 @@
|
|
1
|
+
module Gecode
|
2
|
+
class FreeSetVar
|
3
|
+
# Starts a constraint on the minimum value of the set.
|
4
|
+
def min
|
5
|
+
params = {:lhs => self}
|
6
|
+
Gecode::Constraints::Set::Connection::MinExpressionStub.new(@model, params)
|
7
|
+
end
|
8
|
+
|
9
|
+
# Starts a constraint on the maximum value of the set.
|
10
|
+
def max
|
11
|
+
params = {:lhs => self}
|
12
|
+
Gecode::Constraints::Set::Connection::MaxExpressionStub.new(@model, params)
|
13
|
+
end
|
14
|
+
|
15
|
+
# Starts a constraint on the sum of the set. The option :weights may
|
16
|
+
# optionally be given with a hash of weights as value. If it is then the
|
17
|
+
# weighted sum, using the hash as weight function, will be constrained. The
|
18
|
+
# option :substitutions may also be given (with a hash as value), if it is
|
19
|
+
# then the sum of the set with all elements replaced according to the hash
|
20
|
+
# is constrained. Elements mapped to nil by the weights or substitutions
|
21
|
+
# hash are removed from the upper bound of the set. Only one of the two
|
22
|
+
# options may be given at the same time.
|
23
|
+
def sum(options = {:weights => weights = Hash.new(1)})
|
24
|
+
if options.empty? or options.keys.size > 1
|
25
|
+
raise ArgumentError, 'One of the options :weights and :substitutions, ' +
|
26
|
+
'or neither, must be specified.'
|
27
|
+
end
|
28
|
+
params = {:lhs => self}
|
29
|
+
unless options.empty?
|
30
|
+
case options.keys.first
|
31
|
+
when :substitutions: params.update(options)
|
32
|
+
when :weights:
|
33
|
+
weights = options[:weights]
|
34
|
+
substitutions = Hash.new do |hash, key|
|
35
|
+
if weights[key].nil?
|
36
|
+
hash[key] = nil
|
37
|
+
else
|
38
|
+
hash[key] = key * weights[key]
|
39
|
+
end
|
40
|
+
end
|
41
|
+
params.update(:substitutions => substitutions)
|
42
|
+
else raise ArgumentError, "Unrecognized option #{options.keys.first}."
|
43
|
+
end
|
44
|
+
end
|
45
|
+
Gecode::Constraints::Set::Connection::SumExpressionStub.new(@model, params)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
module Gecode::Constraints::Set
|
51
|
+
class Expression
|
52
|
+
# Adds a constraint that forces specified values to be included in the
|
53
|
+
# set. This constraint has the side effect of sorting the variables in
|
54
|
+
# non-descending order.
|
55
|
+
def include(variables)
|
56
|
+
unless variables.respond_to? :to_int_var_array
|
57
|
+
raise TypeError, "Expected int var enum, got #{variables.class}."
|
58
|
+
end
|
59
|
+
if @params[:negate]
|
60
|
+
raise Gecode::MissingConstraintError, 'A negated include is not ' +
|
61
|
+
'implemented.'
|
62
|
+
end
|
63
|
+
|
64
|
+
@params.update(:variables => variables)
|
65
|
+
@model.add_constraint Connection::IncludeConstraint.new(@model, @params)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
# A module that gathers the classes and modules used in connection
|
70
|
+
# constraints.
|
71
|
+
module Connection #:nodoc:
|
72
|
+
# Describes a CompositeStub for the min constraint which constrains the
|
73
|
+
# minimum value of a set variable.
|
74
|
+
#
|
75
|
+
# == Examples
|
76
|
+
#
|
77
|
+
# # Constrains the minimum value of +set+ to be larger than 17.
|
78
|
+
# set.min.must > 17
|
79
|
+
#
|
80
|
+
# # Constrains the minimum value of +set+ to equal the integer variable
|
81
|
+
# # +min+.
|
82
|
+
# set.min.must == min
|
83
|
+
#
|
84
|
+
# # Constrains the minimum value of +set+ to not be larger than the
|
85
|
+
# # integer variable +ceil+.
|
86
|
+
# set.min.must_not > ceil
|
87
|
+
#
|
88
|
+
# # The same as above but reified with the boolean variable
|
89
|
+
# # +is_not_above_ceiling+ and with the strength +domain+ applied.
|
90
|
+
# set.min.must_not_be.larger_than(ceil, :reify => :is_not_above_ceiling,
|
91
|
+
# :strength => :domain)
|
92
|
+
class MinExpressionStub < Gecode::Constraints::Int::CompositeStub
|
93
|
+
def constrain_equal(variable, params, constrain)
|
94
|
+
set = params[:lhs]
|
95
|
+
if constrain
|
96
|
+
variable.must_be.in set.upper_bound.min..set.lower_bound.min
|
97
|
+
end
|
98
|
+
|
99
|
+
Gecode::Raw::min(@model.active_space, set.bind, variable.bind)
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
# Describes a CompositeStub for the max constraint which constrains the
|
104
|
+
# maximum value of a set variable.
|
105
|
+
#
|
106
|
+
# == Examples
|
107
|
+
#
|
108
|
+
# # Constrains the maximum value of +set+ to be larger than 17.
|
109
|
+
# set.max.must > 17
|
110
|
+
#
|
111
|
+
# # Constrains the maximum value of +set+ to equal the integer variable
|
112
|
+
# # +max+.
|
113
|
+
# set.max.must == max
|
114
|
+
#
|
115
|
+
# # Constrains the maximum value of +set+ to not be less than the
|
116
|
+
# # integer variable +floor+.
|
117
|
+
# set.max.must_not < floor
|
118
|
+
#
|
119
|
+
# # The same as above but reified with the boolean variable
|
120
|
+
# # +is_not_below_floor+ and with the strength +domain+ applied.
|
121
|
+
# set.max.must_not_be.less_than(ceil, :reify => :is_not_below_floor,
|
122
|
+
# :strength => :domain)
|
123
|
+
class MaxExpressionStub < Gecode::Constraints::Int::CompositeStub
|
124
|
+
def constrain_equal(variable, params, constrain)
|
125
|
+
set = params[:lhs]
|
126
|
+
if constrain
|
127
|
+
variable.must_be.in set.lower_bound.max..set.upper_bound.max
|
128
|
+
end
|
129
|
+
|
130
|
+
Gecode::Raw::max(@model.active_space, set.bind, variable.bind)
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
# Describes a CompositeStub for the sum constraint which constrains the
|
135
|
+
# sum of all values in a set variable.
|
136
|
+
#
|
137
|
+
# == Examples
|
138
|
+
#
|
139
|
+
# # Constrains the sum of all values in +set+ to be larger than 17.
|
140
|
+
# set.sum.must > 17
|
141
|
+
#
|
142
|
+
# # Constrains the sum of all values in +set+ to equal the integer
|
143
|
+
# # variable +sum+.
|
144
|
+
# set.sum.must == sum
|
145
|
+
#
|
146
|
+
# # Constrains the sum of all values in +set+ to not be larger than the
|
147
|
+
# # integer variable +resources+.
|
148
|
+
# set.sum.must_not > resources
|
149
|
+
#
|
150
|
+
# # The same as above but reified with the boolean variable
|
151
|
+
# # +not_over_budget+ and with the strength +domain+ applied.
|
152
|
+
# set.sum.must_not_be.larger_than(resources, :reify => :not_over_budget,
|
153
|
+
# :strength => :domain)
|
154
|
+
class SumExpressionStub < Gecode::Constraints::Int::CompositeStub
|
155
|
+
def constrain_equal(variable, params, constrain)
|
156
|
+
set, subs = params.values_at(:lhs, :substitutions)
|
157
|
+
lub = set.upper_bound.to_a
|
158
|
+
lub.delete_if{ |e| subs[e].nil? }
|
159
|
+
substituted_lub = lub.map{ |e| subs[e] }
|
160
|
+
if constrain
|
161
|
+
# Compute the theoretical bounds of the weighted sum. This is slightly
|
162
|
+
# sloppy since we could also use the contents of the greatest lower
|
163
|
+
# bound.
|
164
|
+
min = substituted_lub.find_all{ |e| e < 0}.inject(0){ |x, y| x + y }
|
165
|
+
max = substituted_lub.find_all{ |e| e > 0}.inject(0){ |x, y| x + y }
|
166
|
+
variable.must_be.in min..max
|
167
|
+
end
|
168
|
+
|
169
|
+
Gecode::Raw::weights(@model.active_space, lub, substituted_lub,
|
170
|
+
set.bind, variable.bind)
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
174
|
+
# Describes an include constraint, which constrains the set to include the
|
175
|
+
# values of the specified enumeration of integer variables.
|
176
|
+
#
|
177
|
+
# The constraint has the side effect of sorting the integer variables in a
|
178
|
+
# non-descending order. It does not support reification nor negation.
|
179
|
+
#
|
180
|
+
# == Examples
|
181
|
+
#
|
182
|
+
# # Constrain +set+ to include the values of all variables in
|
183
|
+
# # +int_enum+.
|
184
|
+
# set.must.include int_enum
|
185
|
+
class IncludeConstraint < Gecode::Constraints::Constraint
|
186
|
+
def post
|
187
|
+
set, variables = @params.values_at(:lhs, :variables)
|
188
|
+
Gecode::Raw::match(@model.active_space, set.bind,
|
189
|
+
variables.to_int_var_array)
|
190
|
+
end
|
191
|
+
end
|
192
|
+
end
|
193
|
+
end
|