gecoder-with-gecode 0.9.0-x86-mswin32-60
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 +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'
|