gecoder-with-gecode 0.9.0-x86-mswin32-60
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGES +137 -0
- data/COPYING +17 -0
- data/LGPL-LICENSE +458 -0
- data/README +58 -0
- data/Rakefile +14 -0
- data/example/equation_system.rb +15 -0
- data/example/example_helper.rb +1 -0
- data/example/magic_sequence.rb +43 -0
- data/example/money.rb +36 -0
- data/example/queens.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 +106 -0
- data/example/sudoku.rb +56 -0
- data/lib/gecode.dll +0 -0
- data/lib/gecoder.rb +5 -0
- data/lib/gecoder/bindings.rb +96 -0
- data/lib/gecoder/bindings/bindings.rb +2029 -0
- data/lib/gecoder/interface.rb +9 -0
- data/lib/gecoder/interface/binding_changes.rb +9 -0
- data/lib/gecoder/interface/branch.rb +163 -0
- data/lib/gecoder/interface/constraints.rb +471 -0
- data/lib/gecoder/interface/constraints/bool/boolean.rb +251 -0
- data/lib/gecoder/interface/constraints/bool/channel.rb +7 -0
- data/lib/gecoder/interface/constraints/bool/linear.rb +200 -0
- data/lib/gecoder/interface/constraints/bool_enum/channel.rb +68 -0
- data/lib/gecoder/interface/constraints/bool_enum/extensional.rb +106 -0
- data/lib/gecoder/interface/constraints/bool_enum/relation.rb +55 -0
- data/lib/gecoder/interface/constraints/bool_enum_constraints.rb +84 -0
- data/lib/gecoder/interface/constraints/bool_var_constraints.rb +155 -0
- data/lib/gecoder/interface/constraints/extensional_regexp.rb +101 -0
- data/lib/gecoder/interface/constraints/fixnum_enum/element.rb +63 -0
- data/lib/gecoder/interface/constraints/fixnum_enum/operation.rb +65 -0
- data/lib/gecoder/interface/constraints/fixnum_enum_constraints.rb +42 -0
- data/lib/gecoder/interface/constraints/int/arithmetic.rb +150 -0
- data/lib/gecoder/interface/constraints/int/channel.rb +51 -0
- data/lib/gecoder/interface/constraints/int/domain.rb +80 -0
- data/lib/gecoder/interface/constraints/int/linear.rb +143 -0
- data/lib/gecoder/interface/constraints/int/relation.rb +141 -0
- data/lib/gecoder/interface/constraints/int_enum/arithmetic.rb +63 -0
- data/lib/gecoder/interface/constraints/int_enum/channel.rb +86 -0
- data/lib/gecoder/interface/constraints/int_enum/count.rb +66 -0
- data/lib/gecoder/interface/constraints/int_enum/distinct.rb +64 -0
- data/lib/gecoder/interface/constraints/int_enum/element.rb +64 -0
- data/lib/gecoder/interface/constraints/int_enum/equality.rb +37 -0
- data/lib/gecoder/interface/constraints/int_enum/extensional.rb +187 -0
- data/lib/gecoder/interface/constraints/int_enum/sort.rb +135 -0
- data/lib/gecoder/interface/constraints/int_enum_constraints.rb +95 -0
- data/lib/gecoder/interface/constraints/int_var_constraints.rb +230 -0
- data/lib/gecoder/interface/constraints/reifiable_constraints.rb +78 -0
- data/lib/gecoder/interface/constraints/selected_set/select.rb +120 -0
- data/lib/gecoder/interface/constraints/selected_set_constraints.rb +75 -0
- data/lib/gecoder/interface/constraints/set/cardinality.rb +65 -0
- data/lib/gecoder/interface/constraints/set/channel.rb +51 -0
- data/lib/gecoder/interface/constraints/set/connection.rb +130 -0
- data/lib/gecoder/interface/constraints/set/domain.rb +156 -0
- data/lib/gecoder/interface/constraints/set/include.rb +36 -0
- data/lib/gecoder/interface/constraints/set/operation.rb +118 -0
- data/lib/gecoder/interface/constraints/set/relation.rb +155 -0
- data/lib/gecoder/interface/constraints/set_elements/relation.rb +116 -0
- data/lib/gecoder/interface/constraints/set_elements_constraints.rb +97 -0
- data/lib/gecoder/interface/constraints/set_enum/channel.rb +45 -0
- data/lib/gecoder/interface/constraints/set_enum/distinct.rb +43 -0
- data/lib/gecoder/interface/constraints/set_enum/operation.rb +69 -0
- data/lib/gecoder/interface/constraints/set_enum/select.rb +79 -0
- data/lib/gecoder/interface/constraints/set_enum_constraints.rb +84 -0
- data/lib/gecoder/interface/constraints/set_var_constraints.rb +243 -0
- data/lib/gecoder/interface/enum_matrix.rb +64 -0
- data/lib/gecoder/interface/enum_wrapper.rb +205 -0
- data/lib/gecoder/interface/model.rb +453 -0
- data/lib/gecoder/interface/model_sugar.rb +84 -0
- data/lib/gecoder/interface/search.rb +197 -0
- data/lib/gecoder/interface/variables.rb +306 -0
- data/lib/gecoder/version.rb +4 -0
- data/specs/bool_var.rb +81 -0
- data/specs/branch.rb +185 -0
- data/specs/constraints/bool/boolean.rb +317 -0
- data/specs/constraints/bool/boolean_properties.rb +51 -0
- data/specs/constraints/bool/linear.rb +213 -0
- data/specs/constraints/bool_enum/bool_enum_relation.rb +117 -0
- data/specs/constraints/bool_enum/channel.rb +102 -0
- data/specs/constraints/bool_enum/extensional.rb +225 -0
- data/specs/constraints/constraint_helper.rb +234 -0
- data/specs/constraints/constraint_receivers.rb +103 -0
- data/specs/constraints/constraints.rb +26 -0
- data/specs/constraints/fixnum_enum/element.rb +58 -0
- data/specs/constraints/fixnum_enum/operation.rb +67 -0
- data/specs/constraints/int/arithmetic.rb +149 -0
- data/specs/constraints/int/channel.rb +101 -0
- data/specs/constraints/int/domain.rb +106 -0
- data/specs/constraints/int/linear.rb +183 -0
- data/specs/constraints/int/linear_properties.rb +97 -0
- data/specs/constraints/int/relation.rb +84 -0
- data/specs/constraints/int_enum/arithmetic.rb +72 -0
- data/specs/constraints/int_enum/channel.rb +57 -0
- data/specs/constraints/int_enum/count.rb +72 -0
- data/specs/constraints/int_enum/distinct.rb +80 -0
- data/specs/constraints/int_enum/element.rb +61 -0
- data/specs/constraints/int_enum/equality.rb +29 -0
- data/specs/constraints/int_enum/extensional.rb +224 -0
- data/specs/constraints/int_enum/sort.rb +167 -0
- data/specs/constraints/operands.rb +264 -0
- data/specs/constraints/property_helper.rb +443 -0
- data/specs/constraints/reification_sugar.rb +69 -0
- data/specs/constraints/selected_set/select.rb +56 -0
- data/specs/constraints/selected_set/select_properties.rb +157 -0
- data/specs/constraints/set/cardinality.rb +58 -0
- data/specs/constraints/set/cardinality_properties.rb +46 -0
- data/specs/constraints/set/channel.rb +77 -0
- data/specs/constraints/set/connection.rb +176 -0
- data/specs/constraints/set/domain.rb +197 -0
- data/specs/constraints/set/include.rb +36 -0
- data/specs/constraints/set/operation.rb +132 -0
- data/specs/constraints/set/relation.rb +117 -0
- data/specs/constraints/set_elements/relation.rb +84 -0
- data/specs/constraints/set_enum/channel.rb +80 -0
- data/specs/constraints/set_enum/distinct.rb +59 -0
- data/specs/constraints/set_enum/operation.rb +111 -0
- data/specs/constraints/set_enum/select.rb +73 -0
- data/specs/distribution.rb +14 -0
- data/specs/enum_matrix.rb +43 -0
- data/specs/enum_wrapper.rb +179 -0
- data/specs/examples.rb +17 -0
- data/specs/int_var.rb +163 -0
- data/specs/logging.rb +24 -0
- data/specs/model.rb +325 -0
- data/specs/model_sugar.rb +30 -0
- data/specs/search.rb +383 -0
- data/specs/selected_set.rb +39 -0
- data/specs/set_elements.rb +34 -0
- data/specs/set_var.rb +82 -0
- data/specs/spec_helper.rb +265 -0
- data/tasks/all_tasks.rb +1 -0
- data/tasks/dependencies.txt +22 -0
- data/tasks/distribution.rake +194 -0
- data/tasks/rcov.rake +18 -0
- data/tasks/specs.rake +21 -0
- data/tasks/svn.rake +16 -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/gecode/win32/lib/libgecodesupport.dll +0 -0
- data/vendor/rust/README +28 -0
- data/vendor/rust/bin/cxxgenerator.rb +93 -0
- data/vendor/rust/include/rust_checks.hh +116 -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 +337 -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 +96 -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 +100 -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 +393 -0
@@ -0,0 +1,9 @@
|
|
1
|
+
require 'gecoder/interface/binding_changes'
|
2
|
+
require 'gecoder/interface/enum_matrix'
|
3
|
+
require 'gecoder/interface/model'
|
4
|
+
require 'gecoder/interface/search'
|
5
|
+
require 'gecoder/interface/constraints'
|
6
|
+
require 'gecoder/interface/variables'
|
7
|
+
require 'gecoder/interface/enum_wrapper'
|
8
|
+
require 'gecoder/interface/branch'
|
9
|
+
require 'gecoder/interface/model_sugar'
|
@@ -0,0 +1,163 @@
|
|
1
|
+
module Gecode
|
2
|
+
class Model
|
3
|
+
# Specifies which variables that should be branched on (given as an
|
4
|
+
# enum of operands or as a single operand). One can optionally
|
5
|
+
# also select which of the variables that should be used first with
|
6
|
+
# the :variable option and which value in that variable's domain
|
7
|
+
# that should be used with the :value option. If nothing is
|
8
|
+
# specified then :variable uses :none and value uses :min.
|
9
|
+
#
|
10
|
+
# The following values can be used with :variable for integer and
|
11
|
+
# boolean enums:
|
12
|
+
# [:none] The first unassigned variable.
|
13
|
+
# [:smallest_min] The one with the smallest minimum.
|
14
|
+
# [:largest_min] The one with the largest minimum.
|
15
|
+
# [:smallest_max] The one with the smallest maximum.
|
16
|
+
# [:largest_max] The one with the largest maximum.
|
17
|
+
# [:smallest_size] The one with the smallest size.
|
18
|
+
# [:largest_size] The one with the larges size.
|
19
|
+
# [:smallest_degree] The one with the smallest degree. The degree of a
|
20
|
+
# variable is defined as the number of dependant
|
21
|
+
# propagators. In case of ties, choose the variable
|
22
|
+
# with smallest domain.
|
23
|
+
# [:largest_degree] The one with the largest degree. The degree of a
|
24
|
+
# variable is defined as the number of dependant
|
25
|
+
# propagators. In case of ties, choose the variable
|
26
|
+
# with smallest domain.
|
27
|
+
# [:smallest_min_regret] The one with the smallest min-regret. The
|
28
|
+
# min-regret of a variable is the difference between
|
29
|
+
# the smallest and second-smallest value still in
|
30
|
+
# the domain.
|
31
|
+
# [:largest_min_regret] The one with the largest min-regret. The
|
32
|
+
# min-regret of a variable is the difference between
|
33
|
+
# the smallest and second-smallest value still in
|
34
|
+
# the domain.
|
35
|
+
# [:smallest_max_regret] The one with the smallest max-regret The
|
36
|
+
# max-regret of a variable is the difference between
|
37
|
+
# the largest and second-largest value still in
|
38
|
+
# the domain.
|
39
|
+
# [:largest_max_regret] The one with the largest max-regret. The
|
40
|
+
# max-regret of a variable is the difference between
|
41
|
+
# the largest and second-largest value still in
|
42
|
+
# the domain.
|
43
|
+
#
|
44
|
+
# The following values can be used with :value for integer and boolean
|
45
|
+
# enums:
|
46
|
+
# [:min] Selects the smallest value.
|
47
|
+
# [:med] Select the median value.
|
48
|
+
# [:max] Selects the largest vale
|
49
|
+
# [:split_min] Selects the lower half of the domain.
|
50
|
+
# [:split_max] Selects the upper half of the domain.
|
51
|
+
#
|
52
|
+
# The following values can be used with :variable for set enums:
|
53
|
+
# [:none] The first unassigned set.
|
54
|
+
# [:smallest_cardinality] The one with the smallest cardinality.
|
55
|
+
# [:largest_cardinality] The one with the largest cardinality.
|
56
|
+
# [:smallest_unknown] The one with the smallest number of unknown
|
57
|
+
# elements
|
58
|
+
# [:largest_unknown] The one with the largest number of unknown
|
59
|
+
# elements
|
60
|
+
#
|
61
|
+
# The following values can be used with :value set enums:
|
62
|
+
# [:min] Selects the smallest value in the unknown part of the set.
|
63
|
+
# [:max] Selects the largest value in the unknown part of the set.
|
64
|
+
def branch_on(variables, options = {})
|
65
|
+
if variables.respond_to?(:to_int_var) or
|
66
|
+
variables.respond_to?(:to_bool_var) or
|
67
|
+
variables.respond_to?(:to_set_var)
|
68
|
+
variables = wrap_enum [variables]
|
69
|
+
end
|
70
|
+
|
71
|
+
if variables.respond_to? :to_int_enum
|
72
|
+
add_branch(variables.to_int_enum, options,
|
73
|
+
Constants::BRANCH_INT_VAR_CONSTANTS,
|
74
|
+
Constants::BRANCH_INT_VALUE_CONSTANTS)
|
75
|
+
elsif variables.respond_to? :to_bool_enum
|
76
|
+
add_branch(variables.to_bool_enum, options,
|
77
|
+
Constants::BRANCH_INT_VAR_CONSTANTS,
|
78
|
+
Constants::BRANCH_INT_VALUE_CONSTANTS)
|
79
|
+
elsif variables.respond_to? :to_set_enum
|
80
|
+
add_branch(variables.to_set_enum, options,
|
81
|
+
Constants::BRANCH_SET_VAR_CONSTANTS,
|
82
|
+
Constants::BRANCH_SET_VALUE_CONSTANTS)
|
83
|
+
else
|
84
|
+
raise TypeError, "Unknown type of variable enum #{variables.class}."
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
private
|
89
|
+
|
90
|
+
# This is a hack to get RDoc to ignore the constants.
|
91
|
+
module Constants #:nodoc:
|
92
|
+
# Maps the names of the supported variable branch strategies for
|
93
|
+
# integer and booleans to the corresponding constant in Gecode.
|
94
|
+
BRANCH_INT_VAR_CONSTANTS = {
|
95
|
+
:none => Gecode::Raw::INT_VAR_NONE,
|
96
|
+
:smallest_min => Gecode::Raw::INT_VAR_MIN_MIN,
|
97
|
+
:largest_min => Gecode::Raw::INT_VAR_MIN_MAX,
|
98
|
+
:smallest_max => Gecode::Raw::INT_VAR_MAX_MIN,
|
99
|
+
:largest_max => Gecode::Raw::INT_VAR_MAX_MAX,
|
100
|
+
:smallest_size => Gecode::Raw::INT_VAR_SIZE_MIN,
|
101
|
+
:largest_size => Gecode::Raw::INT_VAR_SIZE_MAX,
|
102
|
+
:smallest_degree => Gecode::Raw::INT_VAR_DEGREE_MIN,
|
103
|
+
:largest_degree => Gecode::Raw::INT_VAR_DEGREE_MAX,
|
104
|
+
:smallest_min_regret => Gecode::Raw::INT_VAR_REGRET_MIN_MIN,
|
105
|
+
:largest_min_regret => Gecode::Raw::INT_VAR_REGRET_MIN_MAX,
|
106
|
+
:smallest_max_regret => Gecode::Raw::INT_VAR_REGRET_MAX_MIN,
|
107
|
+
:largest_max_regret => Gecode::Raw::INT_VAR_REGRET_MAX_MAX
|
108
|
+
}
|
109
|
+
# Maps the names of the supported variable branch strategies for sets to
|
110
|
+
# the corresponding constant in Gecode.
|
111
|
+
BRANCH_SET_VAR_CONSTANTS = { #:nodoc:
|
112
|
+
:none => Gecode::Raw::SET_VAR_NONE,
|
113
|
+
:smallest_cardinality => Gecode::Raw::SET_VAR_MIN_CARD,
|
114
|
+
:largest_cardinality => Gecode::Raw::SET_VAR_MAX_CARD,
|
115
|
+
:smallest_unknown => Gecode::Raw::SET_VAR_MIN_UNKNOWN_ELEM,
|
116
|
+
:largest_unknown => Gecode::Raw::SET_VAR_MAX_UNKNOWN_ELEM
|
117
|
+
}
|
118
|
+
|
119
|
+
# Maps the names of the supported value branch strategies for integers and
|
120
|
+
# booleans to the corresponding constant in Gecode.
|
121
|
+
BRANCH_INT_VALUE_CONSTANTS = { #:nodoc:
|
122
|
+
:min => Gecode::Raw::INT_VAL_MIN,
|
123
|
+
:med => Gecode::Raw::INT_VAL_MED,
|
124
|
+
:max => Gecode::Raw::INT_VAL_MAX,
|
125
|
+
:split_min => Gecode::Raw::INT_VAL_SPLIT_MIN,
|
126
|
+
:split_max => Gecode::Raw::INT_VAL_SPLIT_MAX
|
127
|
+
}
|
128
|
+
# Maps the names of the supported value branch strategies for sets to the
|
129
|
+
# corresponding constant in Gecode.
|
130
|
+
BRANCH_SET_VALUE_CONSTANTS = { #:nodoc:
|
131
|
+
:min => Gecode::Raw::SET_VAL_MIN,
|
132
|
+
:max => Gecode::Raw::SET_VAL_MAX
|
133
|
+
}
|
134
|
+
end
|
135
|
+
|
136
|
+
# Adds a branching selection for the specified variables with the specified
|
137
|
+
# options. The hashes are used to decode the options into Gecode's
|
138
|
+
# constants.
|
139
|
+
def add_branch(variables, options, branch_var_hash, branch_value_hash)
|
140
|
+
# Extract optional arguments.
|
141
|
+
var_strat = options.delete(:variable) || :none
|
142
|
+
val_strat = options.delete(:value) || :min
|
143
|
+
|
144
|
+
# Check that the options are correct.
|
145
|
+
unless options.empty?
|
146
|
+
raise ArgumentError, 'Unknown branching option given: ' +
|
147
|
+
options.keys.join(', ')
|
148
|
+
end
|
149
|
+
unless branch_var_hash.include? var_strat
|
150
|
+
raise ArgumentError, "Unknown variable selection strategy: #{var_strat}"
|
151
|
+
end
|
152
|
+
unless branch_value_hash.include? val_strat
|
153
|
+
raise ArgumentError, "Unknown value selection strategy: #{val_strat}"
|
154
|
+
end
|
155
|
+
|
156
|
+
# Add the branching as a gecode interaction.
|
157
|
+
add_interaction do
|
158
|
+
Gecode::Raw.branch(active_space, variables.bind_array,
|
159
|
+
branch_var_hash[var_strat], branch_value_hash[val_strat])
|
160
|
+
end
|
161
|
+
end
|
162
|
+
end
|
163
|
+
end
|
@@ -0,0 +1,471 @@
|
|
1
|
+
module Gecode
|
2
|
+
# An error signaling that the constraint specified is missing (e.g. one tried
|
3
|
+
# to negate a constraint, but no negated form is implemented).
|
4
|
+
class MissingConstraintError < StandardError
|
5
|
+
end
|
6
|
+
|
7
|
+
# Describes an operand, something that a constraint can be placed
|
8
|
+
# on. Constraints are placed by calling #must or #must_not (the
|
9
|
+
# latter negates the constraint). This produces a
|
10
|
+
# ConstraintReceiver, which defines methods that places constraints
|
11
|
+
# on the operand.
|
12
|
+
#
|
13
|
+
# In general this produces something like the following.
|
14
|
+
#
|
15
|
+
# operand.must.constraint_method(params)
|
16
|
+
#
|
17
|
+
# See e.g. Gecode::Int::IntOperand for concrete examples.
|
18
|
+
#
|
19
|
+
# Classes that mix in Operand must define the methods #model
|
20
|
+
# and #construct_receiver. They should also define a method that converts
|
21
|
+
# the operand into a variable of the operand's type (e.g. int var
|
22
|
+
# operands should define a method #to_int_var that returns an
|
23
|
+
# instance of Gecode::IntVar that represents the operand). The
|
24
|
+
# latter method should be used by constraints to fetch variables
|
25
|
+
# needed when posting constraints. The presence of the method should
|
26
|
+
# also be used for type checking (rather than e.g. checking whether
|
27
|
+
# a parameter is of type IntOperand).
|
28
|
+
module Operand
|
29
|
+
# Specifies that a constraint must hold for the left hand side.
|
30
|
+
def must
|
31
|
+
construct_receiver :lhs => self, :negate => false
|
32
|
+
end
|
33
|
+
alias_method :must_be, :must
|
34
|
+
|
35
|
+
# Specifies that the negation of a constraint must hold for the left hand
|
36
|
+
# side.
|
37
|
+
def must_not
|
38
|
+
construct_receiver :lhs => self, :negate => true
|
39
|
+
end
|
40
|
+
alias_method :must_not_be, :must_not
|
41
|
+
|
42
|
+
# Fetches the model that the operand belongs to.
|
43
|
+
def model
|
44
|
+
raise NotImplementedError, 'Abstract method has not been implemented.'
|
45
|
+
end
|
46
|
+
|
47
|
+
private
|
48
|
+
|
49
|
+
# Constructs the appropriate constraint receiver given the
|
50
|
+
# specified parameters.
|
51
|
+
def construct_receiver(params)
|
52
|
+
raise NotImplementedError, 'Abstract method has not been implemented.'
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
# Describes a constraint receiver, something that receives and
|
57
|
+
# places constraints on various Operand. Constraint receivers
|
58
|
+
# are created by calling #must or #must_not (the latter negates
|
59
|
+
# the constraint) on something that mixes in Operand.
|
60
|
+
#
|
61
|
+
# A constraint is placed on an Operand +operand+ as follows:
|
62
|
+
#
|
63
|
+
# operand.must.constraint_method(params)
|
64
|
+
#
|
65
|
+
# The constraint receiver is created by the call to #must and the
|
66
|
+
# constraint is then placed by the call to #constraint_method.
|
67
|
+
# See e.g. Gecode::Int::IntConstraintReceiver for
|
68
|
+
# concrete examples.
|
69
|
+
#
|
70
|
+
# The following options can be specified in a hash with symbols as
|
71
|
+
# keys when placing a constraint:
|
72
|
+
#
|
73
|
+
# [:strength] The propagation strength suggests how much effort the
|
74
|
+
# solver should put into trying to prune the domains of
|
75
|
+
# variables using the constraint.
|
76
|
+
#
|
77
|
+
# The allowed values are:
|
78
|
+
# [:value] Value consistency (naive).
|
79
|
+
# [:bounds] Bounds consistency. The bounds of the operand
|
80
|
+
# will always be constrained as much as possible
|
81
|
+
# (but pruning may not be done inside the
|
82
|
+
# bounds, even though it may be possible).
|
83
|
+
# [:domain] Domain consistency. All values that can be pruned
|
84
|
+
# away, given the current amount of information,
|
85
|
+
# are pruned away.
|
86
|
+
# [:default] Uses the default consistency of the constraint.
|
87
|
+
#
|
88
|
+
# The strength generally progresses as
|
89
|
+
# :value < :bounds < :domain (:value being the weakest,
|
90
|
+
# :domain being the strongest). A higher strength can
|
91
|
+
# reduce the search space quicker, but at the cost of
|
92
|
+
# making each propagation more costly.
|
93
|
+
#
|
94
|
+
# [:kind] The propagation kind option suggests the implementation
|
95
|
+
# that should be preferred if there are multiple
|
96
|
+
# implementations of a constraint.
|
97
|
+
#
|
98
|
+
# The different kinds are:
|
99
|
+
# [:speed] Prefer speed over memory consumption.
|
100
|
+
# [:memory] Prefer low memory consumption over speed.
|
101
|
+
# [:default] Uses the constraint's default propagation kind.
|
102
|
+
#
|
103
|
+
# [:reify] Reification is used to link a constraint to a boolean
|
104
|
+
# operand in such a way that the variable is true if and
|
105
|
+
# only if the constraint is satisfied. The propagation
|
106
|
+
# goes both ways, so if the variable is constrained to be
|
107
|
+
# false then the constraint is not allowed to be
|
108
|
+
# satisfied.
|
109
|
+
#
|
110
|
+
# Reification can be thought of as a last resort glue which
|
111
|
+
# can be used to combine constraints so that e.g. exactly
|
112
|
+
# 3 out of 17 constraints must be satisfied.
|
113
|
+
#
|
114
|
+
# Not all constraints accept all options. Constraints that have sets
|
115
|
+
# as operands (e.g. SetConstraintReceiver and
|
116
|
+
# SetEnumConstraintReceiver) do not accept the :strength and :kind
|
117
|
+
# options, all other do. Some constraints do not accept the :reify
|
118
|
+
# option.
|
119
|
+
#
|
120
|
+
# See e.g. Gecode::Int::IntConstraintReceiver for
|
121
|
+
# concrete examples of options being specified.
|
122
|
+
class ConstraintReceiver
|
123
|
+
# Constructs a new expression with the specified parameters. The
|
124
|
+
# parameters should at least contain the keys :lhs, and :negate.
|
125
|
+
#
|
126
|
+
# Raises ArgumentError if any of those keys are missing or if :lhs
|
127
|
+
# is not an operand.
|
128
|
+
def initialize(model, params)
|
129
|
+
unless params.has_key?(:lhs) and params.has_key?(:negate)
|
130
|
+
raise ArgumentError, 'Expression requires at least :lhs, ' +
|
131
|
+
"and :negate as parameter keys, got #{params.keys.join(', ')}."
|
132
|
+
end
|
133
|
+
unless params[:lhs].kind_of? Operand
|
134
|
+
raise ArgumentError, 'Expected :lhs to be an operand, received ' +
|
135
|
+
"#{params[:lhs].class}."
|
136
|
+
end
|
137
|
+
|
138
|
+
@model = model
|
139
|
+
@params = params
|
140
|
+
end
|
141
|
+
|
142
|
+
private
|
143
|
+
|
144
|
+
# Provides commutativity for the constraint with the specified
|
145
|
+
# method name. If the method with the specified method name is
|
146
|
+
# called with something that, when given to the block, evaluates
|
147
|
+
# to true, then the constraint will be called on the right hand
|
148
|
+
# side with the left hand side as argument.
|
149
|
+
#
|
150
|
+
# The original constraint method is assumed to take two arguments:
|
151
|
+
# a right hand side and a hash of options.
|
152
|
+
def self.provide_commutativity(constraint_name, &block)
|
153
|
+
unique_id = constraint_name.to_sym.to_i
|
154
|
+
pre_alias_method_name = 'pre_commutivity_' << unique_id.to_s
|
155
|
+
if method_defined? constraint_name
|
156
|
+
alias_method pre_alias_method_name, constraint_name
|
157
|
+
end
|
158
|
+
|
159
|
+
module_eval <<-end_code
|
160
|
+
@@commutivity_check_#{unique_id} = block
|
161
|
+
def #{constraint_name}(rhs, options = {})
|
162
|
+
if @@commutivity_check_#{unique_id}.call(rhs, options)
|
163
|
+
if @params[:negate]
|
164
|
+
rhs.must_not.method(:#{constraint_name}).call(
|
165
|
+
@params[:lhs], options)
|
166
|
+
else
|
167
|
+
rhs.must.method(:#{constraint_name}).call(
|
168
|
+
@params[:lhs], options)
|
169
|
+
end
|
170
|
+
else
|
171
|
+
if self.class.method_defined? :#{pre_alias_method_name}
|
172
|
+
#{pre_alias_method_name}(rhs, options)
|
173
|
+
else
|
174
|
+
raise TypeError, \"Unexpected argument type \#{rhs.class}.\"
|
175
|
+
end
|
176
|
+
end
|
177
|
+
end
|
178
|
+
end_code
|
179
|
+
end
|
180
|
+
|
181
|
+
# Creates aliases for any defined comparison methods.
|
182
|
+
def self.alias_comparison_methods
|
183
|
+
Gecode::Util::COMPARISON_ALIASES.each_pair do |orig, aliases|
|
184
|
+
if instance_methods.include?(orig.to_s)
|
185
|
+
aliases.each do |name|
|
186
|
+
alias_method(name, orig)
|
187
|
+
end
|
188
|
+
end
|
189
|
+
end
|
190
|
+
end
|
191
|
+
|
192
|
+
# Creates aliases for any defined set methods.
|
193
|
+
def self.alias_set_methods
|
194
|
+
Gecode::Util::SET_ALIASES.each_pair do |orig, aliases|
|
195
|
+
if instance_methods.include?(orig.to_s)
|
196
|
+
aliases.each do |name|
|
197
|
+
alias_method(name, orig)
|
198
|
+
end
|
199
|
+
end
|
200
|
+
end
|
201
|
+
end
|
202
|
+
end
|
203
|
+
|
204
|
+
# Base class for all constraints.
|
205
|
+
class Constraint #:nodoc:
|
206
|
+
# Creates a constraint with the specified parameters, bound to the
|
207
|
+
# specified model.
|
208
|
+
def initialize(model, params)
|
209
|
+
@model = model
|
210
|
+
@params = params.clone
|
211
|
+
end
|
212
|
+
|
213
|
+
# Posts the constraint, adding it to the model. This is an abstract
|
214
|
+
# method and should be overridden by all sub-classes.
|
215
|
+
def post
|
216
|
+
raise NotImplementedError, 'Abstract method has not been implemented.'
|
217
|
+
end
|
218
|
+
|
219
|
+
private
|
220
|
+
|
221
|
+
# Gives an array of the values selected for the standard propagation
|
222
|
+
# options (propagation strength and propagation kind) in the order that
|
223
|
+
# they are given when posting constraints to Gecode.
|
224
|
+
def propagation_options
|
225
|
+
Gecode::Util::extract_propagation_options(@params)
|
226
|
+
end
|
227
|
+
end
|
228
|
+
|
229
|
+
# A constraint that can be specified by providing a block containing the
|
230
|
+
# post method.
|
231
|
+
class BlockConstraint < Constraint #:nodoc:
|
232
|
+
def initialize(model, params, &block)
|
233
|
+
super(model, params)
|
234
|
+
@proc = block
|
235
|
+
end
|
236
|
+
|
237
|
+
def post
|
238
|
+
@proc.call
|
239
|
+
end
|
240
|
+
end
|
241
|
+
|
242
|
+
# A module that provides some utility-methods for constraints.
|
243
|
+
module Util #:nodoc:
|
244
|
+
# Maps the name used in options to the value used in Gecode for
|
245
|
+
# propagation strengths.
|
246
|
+
PROPAGATION_STRENGTHS = {
|
247
|
+
:default => Gecode::Raw::ICL_DEF,
|
248
|
+
:value => Gecode::Raw::ICL_VAL,
|
249
|
+
:bounds => Gecode::Raw::ICL_BND,
|
250
|
+
:domain => Gecode::Raw::ICL_DOM
|
251
|
+
}
|
252
|
+
|
253
|
+
# Maps the name used in options to the value used in Gecode for
|
254
|
+
# propagation kinds.
|
255
|
+
PROPAGATION_KINDS = {
|
256
|
+
:default => Gecode::Raw::PK_DEF,
|
257
|
+
:speed => Gecode::Raw::PK_SPEED,
|
258
|
+
:memory => Gecode::Raw::PK_MEMORY,
|
259
|
+
}
|
260
|
+
|
261
|
+
# Maps the names of the methods to the corresponding integer relation
|
262
|
+
# type in Gecode.
|
263
|
+
RELATION_TYPES = {
|
264
|
+
:== => Gecode::Raw::IRT_EQ,
|
265
|
+
:<= => Gecode::Raw::IRT_LQ,
|
266
|
+
:< => Gecode::Raw::IRT_LE,
|
267
|
+
:>= => Gecode::Raw::IRT_GQ,
|
268
|
+
:> => Gecode::Raw::IRT_GR
|
269
|
+
}
|
270
|
+
# The same as above, but negated.
|
271
|
+
NEGATED_RELATION_TYPES = {
|
272
|
+
:== => Gecode::Raw::IRT_NQ,
|
273
|
+
:<= => Gecode::Raw::IRT_GR,
|
274
|
+
:< => Gecode::Raw::IRT_GQ,
|
275
|
+
:>= => Gecode::Raw::IRT_LE,
|
276
|
+
:> => Gecode::Raw::IRT_LQ
|
277
|
+
}
|
278
|
+
|
279
|
+
# Maps the names of the methods to the corresponding set relation type in
|
280
|
+
# Gecode.
|
281
|
+
SET_RELATION_TYPES = {
|
282
|
+
:== => Gecode::Raw::SRT_EQ,
|
283
|
+
:superset => Gecode::Raw::SRT_SUP,
|
284
|
+
:subset => Gecode::Raw::SRT_SUB,
|
285
|
+
:disjoint => Gecode::Raw::SRT_DISJ,
|
286
|
+
:complement => Gecode::Raw::SRT_CMPL
|
287
|
+
}
|
288
|
+
# The same as above, but negated.
|
289
|
+
NEGATED_SET_RELATION_TYPES = {
|
290
|
+
:== => Gecode::Raw::SRT_NQ
|
291
|
+
}
|
292
|
+
# Maps the names of the methods to the corresponding set operation type in
|
293
|
+
# Gecode.
|
294
|
+
SET_OPERATION_TYPES = {
|
295
|
+
:union => Gecode::Raw::SOT_UNION,
|
296
|
+
:disjoint_union => Gecode::Raw::SOT_DUNION,
|
297
|
+
:intersection => Gecode::Raw::SOT_INTER,
|
298
|
+
:minus => Gecode::Raw::SOT_MINUS
|
299
|
+
}
|
300
|
+
|
301
|
+
# Various method aliases for comparison methods. Maps the original
|
302
|
+
# (symbol) name to an array of aliases.
|
303
|
+
COMPARISON_ALIASES = {
|
304
|
+
:== => [:equal, :equal_to],
|
305
|
+
:> => [:greater, :greater_than],
|
306
|
+
:>= => [:greater_or_equal, :greater_than_or_equal_to],
|
307
|
+
:< => [:less, :less_than],
|
308
|
+
:<= => [:less_or_equal, :less_than_or_equal_to]
|
309
|
+
}
|
310
|
+
SET_ALIASES = {
|
311
|
+
:== => [:equal, :equal_to],
|
312
|
+
:superset => [:superset_of],
|
313
|
+
:subset => [:subset_of],
|
314
|
+
:disjoint => [:disjoint_with],
|
315
|
+
:complement => [:complement_of]
|
316
|
+
}
|
317
|
+
|
318
|
+
module_function
|
319
|
+
|
320
|
+
# Decodes the common options to constraints: strength, kind and
|
321
|
+
# reification. Returns a hash with up to three values. :strength is the
|
322
|
+
# strength that should be used for the constraint, :kind is the
|
323
|
+
# propagation kind that should be used, and :reif is the (bound) boolean
|
324
|
+
# operand that should be used for reification. The decoded options are
|
325
|
+
# removed from the hash (so in general the hash will be consumed in the
|
326
|
+
# process).
|
327
|
+
#
|
328
|
+
# Raises ArgumentError if an unrecognized option is found in the specified
|
329
|
+
# hash. Or if an unrecognized strength is given. Raises TypeError if the
|
330
|
+
# reification operand is not a boolean operand.
|
331
|
+
def decode_options(options)
|
332
|
+
# Propagation strength.
|
333
|
+
strength = options.delete(:strength) || :default
|
334
|
+
unless PROPAGATION_STRENGTHS.include? strength
|
335
|
+
raise ArgumentError, "Unrecognized propagation strength #{strength}."
|
336
|
+
end
|
337
|
+
|
338
|
+
# Propagation kind.
|
339
|
+
kind = options.delete(:kind) || :default
|
340
|
+
unless PROPAGATION_KINDS.include? kind
|
341
|
+
raise ArgumentError, "Unrecognized propagation kind #{kind}."
|
342
|
+
end
|
343
|
+
|
344
|
+
# Reification.
|
345
|
+
reif_var = options.delete(:reify)
|
346
|
+
unless reif_var.nil? or reif_var.respond_to? :to_bool_var
|
347
|
+
raise TypeError, 'Only boolean operands may be used for reification.'
|
348
|
+
end
|
349
|
+
|
350
|
+
# Check for unrecognized options.
|
351
|
+
unless options.empty?
|
352
|
+
raise ArgumentError, 'Unrecognized constraint option: ' +
|
353
|
+
options.keys.first.to_s
|
354
|
+
end
|
355
|
+
return {
|
356
|
+
:strength => PROPAGATION_STRENGTHS[strength],
|
357
|
+
:kind => PROPAGATION_KINDS[kind],
|
358
|
+
:reif => reif_var
|
359
|
+
}
|
360
|
+
end
|
361
|
+
|
362
|
+
# Converts the different ways to specify constant sets in the interface
|
363
|
+
# to the form that the set should be represented in Gecode (possibly
|
364
|
+
# multiple paramters. The different forms accepted are:
|
365
|
+
# * Single instance of Fixnum (singleton set).
|
366
|
+
# * Range (set containing all numbers in range), treated differently from
|
367
|
+
# other enumerations.
|
368
|
+
# * Enumeration of integers (set contaning all numbers in set).
|
369
|
+
def constant_set_to_params(constant_set)
|
370
|
+
unless constant_set?(constant_set)
|
371
|
+
raise TypeError, "Expected a constant set, got: #{constant_set}."
|
372
|
+
end
|
373
|
+
|
374
|
+
if constant_set.kind_of? Range
|
375
|
+
return constant_set.first, constant_set.last
|
376
|
+
elsif constant_set.kind_of? Fixnum
|
377
|
+
return constant_set
|
378
|
+
else
|
379
|
+
constant_set = constant_set.to_a
|
380
|
+
return Gecode::Raw::IntSet.new(constant_set, constant_set.size)
|
381
|
+
end
|
382
|
+
end
|
383
|
+
|
384
|
+
# Converts the different ways to specify constant sets in the interface
|
385
|
+
# to an instance of Gecode::Raw::IntSet. The different forms accepted are:
|
386
|
+
# * Single instance of Fixnum (singleton set).
|
387
|
+
# * Range (set containing all numbers in range), treated differently from
|
388
|
+
# other enumerations.
|
389
|
+
# * Enumeration of integers (set contaning all numbers in set).
|
390
|
+
def constant_set_to_int_set(constant_set)
|
391
|
+
unless constant_set?(constant_set)
|
392
|
+
raise TypeError, "Expected a constant set, got: #{constant_set}."
|
393
|
+
end
|
394
|
+
|
395
|
+
if constant_set.kind_of? Range
|
396
|
+
return Gecode::Raw::IntSet.new(constant_set.first, constant_set.last)
|
397
|
+
elsif constant_set.kind_of? Fixnum
|
398
|
+
return Gecode::Raw::IntSet.new([constant_set], 1)
|
399
|
+
else
|
400
|
+
constant_set = constant_set.to_a
|
401
|
+
return Gecode::Raw::IntSet.new(constant_set, constant_set.size)
|
402
|
+
end
|
403
|
+
end
|
404
|
+
|
405
|
+
# Checks whether the specified expression is regarded as a constant set.
|
406
|
+
# Returns true if it is, false otherwise.
|
407
|
+
def constant_set?(expression)
|
408
|
+
return (
|
409
|
+
expression.kind_of?(Range) && # It's a range.
|
410
|
+
expression.first.kind_of?(Fixnum) &&
|
411
|
+
expression.last.kind_of?(Fixnum)) ||
|
412
|
+
expression.kind_of?(Fixnum) || # It's a single fixnum.
|
413
|
+
(expression.kind_of?(Enumerable) && # It's an enum of fixnums.
|
414
|
+
expression.all?{ |e| e.kind_of? Fixnum })
|
415
|
+
end
|
416
|
+
|
417
|
+
# Extracts an array of the values selected for the standard propagation
|
418
|
+
# options (propagation strength and propagation kind) from the hash of
|
419
|
+
# parameters given. The options are returned in the order that they are
|
420
|
+
# given when posting constraints to Gecode.
|
421
|
+
def extract_propagation_options(params)
|
422
|
+
params.values_at(:strength, :kind)
|
423
|
+
end
|
424
|
+
end
|
425
|
+
|
426
|
+
# A module that contains utility-methods for extensional constraints.
|
427
|
+
module Util::Extensional #:nodoc:
|
428
|
+
module_function
|
429
|
+
|
430
|
+
# Checks that the specified enumeration is an enumeration containing
|
431
|
+
# one or more tuples of the specified size. It also allows the caller
|
432
|
+
# to define additional tests by providing a block, which is given each
|
433
|
+
# tuple. If a test fails then an appropriate error is raised.
|
434
|
+
def perform_tuple_checks(tuples, expected_size, &additional_test)
|
435
|
+
unless tuples.respond_to?(:each)
|
436
|
+
raise TypeError, 'Expected an enumeration with tuples, got ' +
|
437
|
+
"#{tuples.class}."
|
438
|
+
end
|
439
|
+
|
440
|
+
if tuples.empty?
|
441
|
+
raise ArgumentError, 'One or more tuples must be specified.'
|
442
|
+
end
|
443
|
+
|
444
|
+
tuples.each do |tuple|
|
445
|
+
unless tuple.respond_to?(:each)
|
446
|
+
raise TypeError, 'Expected an enumeration containing enumeraions, ' +
|
447
|
+
"got #{tuple.class}."
|
448
|
+
end
|
449
|
+
|
450
|
+
unless tuple.size == expected_size
|
451
|
+
raise ArgumentError, 'All tuples must be of the same size as the ' +
|
452
|
+
'number of operands in the array.'
|
453
|
+
end
|
454
|
+
|
455
|
+
yield tuple
|
456
|
+
end
|
457
|
+
end
|
458
|
+
end
|
459
|
+
end
|
460
|
+
|
461
|
+
require 'gecoder/interface/constraints/reifiable_constraints'
|
462
|
+
require 'gecoder/interface/constraints/int_var_constraints'
|
463
|
+
require 'gecoder/interface/constraints/int_enum_constraints'
|
464
|
+
require 'gecoder/interface/constraints/bool_var_constraints'
|
465
|
+
require 'gecoder/interface/constraints/bool_enum_constraints'
|
466
|
+
require 'gecoder/interface/constraints/set_var_constraints'
|
467
|
+
require 'gecoder/interface/constraints/set_enum_constraints'
|
468
|
+
require 'gecoder/interface/constraints/selected_set_constraints'
|
469
|
+
require 'gecoder/interface/constraints/set_elements_constraints'
|
470
|
+
require 'gecoder/interface/constraints/fixnum_enum_constraints'
|
471
|
+
require 'gecoder/interface/constraints/extensional_regexp'
|