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,84 @@
|
|
1
|
+
module Gecode
|
2
|
+
# Provides a convenient way to construct a model and then find a
|
3
|
+
# solution. The model constructed uses the specified block as
|
4
|
+
# initialization method. The first solution to the model is then
|
5
|
+
# returned.
|
6
|
+
#
|
7
|
+
# For instance
|
8
|
+
#
|
9
|
+
# solution = Gecode.solve do
|
10
|
+
# # Do something
|
11
|
+
# end
|
12
|
+
#
|
13
|
+
# is equivalent to
|
14
|
+
#
|
15
|
+
# class Foo < Gecode::Model
|
16
|
+
# def initialize
|
17
|
+
# # Do something
|
18
|
+
# end
|
19
|
+
# end
|
20
|
+
# solution = Foo.new.solve!
|
21
|
+
def self.solve(&block)
|
22
|
+
create_model(&block).solve!
|
23
|
+
end
|
24
|
+
|
25
|
+
# Provides a convenient way to construct a model and then find the
|
26
|
+
# solution that maximizes a given variable. The model constructed
|
27
|
+
# uses the specified block as initialization method. The solution
|
28
|
+
# that maximizes the specified variable is then returned.
|
29
|
+
#
|
30
|
+
# For instance
|
31
|
+
#
|
32
|
+
# solution = Gecode.maximize :variable_bar do
|
33
|
+
# # Do something
|
34
|
+
# end
|
35
|
+
#
|
36
|
+
# is equivalent to
|
37
|
+
#
|
38
|
+
# class Foo < Gecode::Model
|
39
|
+
# def initialize
|
40
|
+
# # Do something
|
41
|
+
# end
|
42
|
+
# end
|
43
|
+
# solution = Foo.new.maximize :variable_bar
|
44
|
+
def self.maximize(variable_to_maximize, &block)
|
45
|
+
create_model(&block).maximize! variable_to_maximize
|
46
|
+
end
|
47
|
+
|
48
|
+
# Provides a convenient way to construct a model and then find the
|
49
|
+
# solution that minimizes a given variable. The model constructed
|
50
|
+
# uses the specified block as initialization method. The solution
|
51
|
+
# that minimizes the specified variable is then returned.
|
52
|
+
#
|
53
|
+
# For instance
|
54
|
+
#
|
55
|
+
# solution = Gecode.minimize :variable_bar do
|
56
|
+
# # Do something
|
57
|
+
# end
|
58
|
+
#
|
59
|
+
# is equivalent to
|
60
|
+
#
|
61
|
+
# class Foo < Gecode::Model
|
62
|
+
# def initialize
|
63
|
+
# # Do something
|
64
|
+
# end
|
65
|
+
# end
|
66
|
+
# solution = Foo.new.minimize :variable_bar
|
67
|
+
def self.minimize(variable_to_minimize, &block)
|
68
|
+
create_model(&block).minimize! variable_to_minimize
|
69
|
+
end
|
70
|
+
|
71
|
+
private
|
72
|
+
|
73
|
+
# Creates an instance of a class that subclasses Model and uses the
|
74
|
+
# specified block as initialization method.
|
75
|
+
def self.create_model(&block)
|
76
|
+
model = Class.new(Gecode::Model)
|
77
|
+
model.class_eval do
|
78
|
+
def initialize(&init_block) #:nodoc:
|
79
|
+
instance_eval &init_block
|
80
|
+
end
|
81
|
+
end
|
82
|
+
model.new(&block)
|
83
|
+
end
|
84
|
+
end
|
@@ -0,0 +1,197 @@
|
|
1
|
+
module Gecode
|
2
|
+
# An exception raised when a search failed because there are no
|
3
|
+
# solutions.
|
4
|
+
class NoSolutionError < RuntimeError
|
5
|
+
def initialize #:nodoc:
|
6
|
+
super('No solution could be found.')
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
class Model
|
11
|
+
# Finds the first solution to the modelled problem and updates the variables
|
12
|
+
# to that solution. The found solution is also returned. Raises
|
13
|
+
# Gecode::NoSolutionError if no solution can be found.
|
14
|
+
def solve!
|
15
|
+
dfs = dfs_engine
|
16
|
+
space = dfs.next
|
17
|
+
@statistics = dfs.statistics
|
18
|
+
raise Gecode::NoSolutionError if space.nil?
|
19
|
+
self.active_space = space
|
20
|
+
return self
|
21
|
+
end
|
22
|
+
|
23
|
+
# Returns to the original state, before any search was made (but
|
24
|
+
# propagation might have been performed). Returns the reset model.
|
25
|
+
def reset!
|
26
|
+
self.active_space = base_space
|
27
|
+
@statistics = nil
|
28
|
+
return self
|
29
|
+
end
|
30
|
+
|
31
|
+
# Yields the first solution (if any) to the block. If no solution is found
|
32
|
+
# then the block is not used. Returns the result of the block (nil in case
|
33
|
+
# the block wasn't run).
|
34
|
+
def solution(&block)
|
35
|
+
begin
|
36
|
+
solution = self.solve!
|
37
|
+
res = yield solution
|
38
|
+
self.reset!
|
39
|
+
return res
|
40
|
+
rescue Gecode::NoSolutionError
|
41
|
+
return nil
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
# Yields each solution that the model has.
|
46
|
+
def each_solution(&block)
|
47
|
+
dfs = dfs_engine
|
48
|
+
next_solution = nil
|
49
|
+
while not (next_solution = dfs.next).nil?
|
50
|
+
self.active_space = next_solution
|
51
|
+
@statistics = dfs.statistics
|
52
|
+
yield self
|
53
|
+
end
|
54
|
+
self.reset!
|
55
|
+
end
|
56
|
+
|
57
|
+
# Returns search statistics providing various information from Gecode about
|
58
|
+
# the search that resulted in the model's current variable state. If the
|
59
|
+
# model's variables have not undergone any search then nil is returned. The
|
60
|
+
# statistics is a hash with the following keys:
|
61
|
+
# [:propagations] The number of propagation steps performed.
|
62
|
+
# [:failures] The number of failed nodes in the search tree.
|
63
|
+
# [:clones] The number of clones created.
|
64
|
+
# [:commits] The number of commit operations performed.
|
65
|
+
# [:memory] The peak memory allocated to Gecode.
|
66
|
+
def search_stats
|
67
|
+
return nil if @statistics.nil?
|
68
|
+
|
69
|
+
return {
|
70
|
+
:propagations => @statistics.propagate,
|
71
|
+
:failures => @statistics.fail,
|
72
|
+
:clones => @statistics.clone,
|
73
|
+
:commits => @statistics.commit,
|
74
|
+
:memory => @statistics.memory
|
75
|
+
}
|
76
|
+
end
|
77
|
+
|
78
|
+
# Finds the optimal solution. Optimality is defined by the provided block
|
79
|
+
# which is given one parameter, a solution to the problem. The block should
|
80
|
+
# constrain the solution so that that only "better" solutions can be new
|
81
|
+
# solutions. For instance if one wants to optimize a variable named price
|
82
|
+
# (accessible from the model) to be as low as possible then one should write
|
83
|
+
# the following.
|
84
|
+
#
|
85
|
+
# model.optimize! do |model, best_so_far|
|
86
|
+
# model.price.must < best_so_far.price.val
|
87
|
+
# end
|
88
|
+
#
|
89
|
+
# Raises Gecode::NoSolutionError if no solution can be found.
|
90
|
+
def optimize!(&block)
|
91
|
+
# Execute constraints.
|
92
|
+
perform_queued_gecode_interactions
|
93
|
+
|
94
|
+
# Set the method used for constrain calls by the BAB-search.
|
95
|
+
Model.constrain_proc = lambda do |home_space, best_space|
|
96
|
+
self.active_space = best_space
|
97
|
+
@variable_creation_space = home_space
|
98
|
+
yield(self, self)
|
99
|
+
self.active_space = home_space
|
100
|
+
@variable_creation_space = nil
|
101
|
+
|
102
|
+
perform_queued_gecode_interactions
|
103
|
+
end
|
104
|
+
|
105
|
+
# Perform the search.
|
106
|
+
options = Gecode::Raw::Search::Options.new
|
107
|
+
options.c_d = Gecode::Raw::Search::Config::MINIMAL_DISTANCE
|
108
|
+
options.a_d = Gecode::Raw::Search::Config::ADAPTIVE_DISTANCE
|
109
|
+
options.stop = nil
|
110
|
+
bab = Gecode::Raw::BAB.new(selected_space, options)
|
111
|
+
|
112
|
+
result = nil
|
113
|
+
previous_solution = nil
|
114
|
+
until (previous_solution = bab.next).nil?
|
115
|
+
result = previous_solution
|
116
|
+
end
|
117
|
+
@statistics = bab.statistics
|
118
|
+
|
119
|
+
# Reset the method used constrain calls and return the result.
|
120
|
+
Model.constrain_proc = nil
|
121
|
+
raise Gecode::NoSolutionError if result.nil?
|
122
|
+
|
123
|
+
# Switch to the result.
|
124
|
+
self.active_space = result
|
125
|
+
return self
|
126
|
+
end
|
127
|
+
|
128
|
+
# Finds the solution that maximizes a given integer variable. The name of
|
129
|
+
# the method that accesses the variable from the model should be given. To
|
130
|
+
# for instance maximize a variable named "profit", that's accessible
|
131
|
+
# through the model, one would use the following.
|
132
|
+
#
|
133
|
+
# model.maximize! :profit
|
134
|
+
#
|
135
|
+
# Raises Gecode::NoSolutionError if no solution can be found.
|
136
|
+
def maximize!(var)
|
137
|
+
variable = self.method(var).call
|
138
|
+
unless variable.kind_of? Gecode::IntVar
|
139
|
+
raise ArgumentError.new("Expected integer variable, got #{variable.class}.")
|
140
|
+
end
|
141
|
+
|
142
|
+
optimize! do |model, best_so_far|
|
143
|
+
model.method(var).call.must > best_so_far.method(var).call.value
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
# Finds the solution that minimizes a given integer variable. The name of
|
148
|
+
# the method that accesses the variable from the model should be given. To
|
149
|
+
# for instance minimize a variable named "cost", that's accessible through
|
150
|
+
# the model, one would use the following.
|
151
|
+
#
|
152
|
+
# model.minimize! :cost
|
153
|
+
#
|
154
|
+
# Raises Gecode::NoSolutionError if no solution can be found.
|
155
|
+
def minimize!(var)
|
156
|
+
variable = self.method(var).call
|
157
|
+
unless variable.kind_of? Gecode::IntVar
|
158
|
+
raise ArgumentError.new("Expected integer variable, got #{variable.class}.")
|
159
|
+
end
|
160
|
+
|
161
|
+
optimize! do |model, best_so_far|
|
162
|
+
model.method(var).call.must < best_so_far.method(var).call.value
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
class <<self
|
167
|
+
# Sets the proc that should be used to handle constrain requests.
|
168
|
+
def constrain_proc=(proc) #:nodoc:
|
169
|
+
@constrain_proc = proc
|
170
|
+
end
|
171
|
+
|
172
|
+
# Called by spaces when they want to constrain as part of BAB-search.
|
173
|
+
def constrain(home, best) #:nodoc:
|
174
|
+
if @constrain_proc.nil?
|
175
|
+
raise NotImplementedError, 'Constrain method not implemented.'
|
176
|
+
else
|
177
|
+
@constrain_proc.call(home, best)
|
178
|
+
end
|
179
|
+
end
|
180
|
+
end
|
181
|
+
|
182
|
+
private
|
183
|
+
|
184
|
+
# Creates a depth first search engine for search, executing any
|
185
|
+
# unexecuted constraints first.
|
186
|
+
def dfs_engine
|
187
|
+
# Execute constraints.
|
188
|
+
perform_queued_gecode_interactions
|
189
|
+
|
190
|
+
# Construct the engine.
|
191
|
+
Gecode::Raw::DFS.new(selected_space,
|
192
|
+
Gecode::Raw::Search::Config::MINIMAL_DISTANCE,
|
193
|
+
Gecode::Raw::Search::Config::ADAPTIVE_DISTANCE,
|
194
|
+
nil)
|
195
|
+
end
|
196
|
+
end
|
197
|
+
end
|
@@ -0,0 +1,306 @@
|
|
1
|
+
module Gecode
|
2
|
+
# Describes a variable that is bound to a model, but not to a particular
|
3
|
+
# space.
|
4
|
+
class FreeVarBase #:nodoc:
|
5
|
+
attr_accessor :model
|
6
|
+
|
7
|
+
# Creates an int variable with the specified index.
|
8
|
+
def initialize(model, index)
|
9
|
+
@model = model
|
10
|
+
@index = index
|
11
|
+
model.track_variable(self)
|
12
|
+
end
|
13
|
+
|
14
|
+
def inspect
|
15
|
+
if assigned?
|
16
|
+
"#<#{self.class} #{domain_string}>"
|
17
|
+
else
|
18
|
+
"#<#{self.class} #{domain_string}>"
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
# Returns the space that the int variable should bind to when needed.
|
25
|
+
def active_space
|
26
|
+
@model.active_space
|
27
|
+
end
|
28
|
+
|
29
|
+
# Sends the specified method name and arguments to the bound variable.
|
30
|
+
def send_bound(method_name, *args)
|
31
|
+
@model.allow_space_access do
|
32
|
+
bind.send(method_name, *args)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
# Creates a class for a free variable that can be bound into the specified
|
38
|
+
# class using the specified method in a space.
|
39
|
+
def Gecode::FreeVar(bound_class, space_bind_method) #:nodoc:
|
40
|
+
clazz = Class.new(FreeVarBase)
|
41
|
+
clazz.class_eval <<-"end_method_definitions"
|
42
|
+
# Binds the variable to the currently active space of the model,
|
43
|
+
# returning the bound variable.
|
44
|
+
def bind
|
45
|
+
active_space.method(:#{space_bind_method}).call(@index)
|
46
|
+
end
|
47
|
+
|
48
|
+
private
|
49
|
+
|
50
|
+
# Delegates the method with the specified name to a method with the
|
51
|
+
# specified name when the variable is bound. If the bound method's name
|
52
|
+
# is nil then the same name as the new method's name is assumed.
|
53
|
+
def self.delegate(method_name, bound_method_name = nil)
|
54
|
+
bound_method_name = method_name if bound_method_name.nil?
|
55
|
+
module_eval <<-"end_code"
|
56
|
+
def \#{method_name}(*args)
|
57
|
+
@model.allow_space_access do
|
58
|
+
bind.method(:\#{bound_method_name}).call(*args)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end_code
|
62
|
+
end
|
63
|
+
end_method_definitions
|
64
|
+
return clazz
|
65
|
+
end
|
66
|
+
|
67
|
+
IntVar = FreeVar(Gecode::Raw::IntVar, :int_var)
|
68
|
+
# Describes an integer variable.
|
69
|
+
#
|
70
|
+
# An integer variable can take the value of any integer in its
|
71
|
+
# domain, which is specified upon constructing the variable and
|
72
|
+
# further constrained by placing constraints on the variable.
|
73
|
+
# An integer variable is said to be assigned once the domain only
|
74
|
+
# contains a single element, at which point #value can be used to
|
75
|
+
# retrieve the value.
|
76
|
+
#
|
77
|
+
# Integer variables are integer operands and hence respond to
|
78
|
+
# everything that Gecode::Int::IntOperand responds to.
|
79
|
+
# Any constraint found in
|
80
|
+
# Gecode::Int::IntConstraintReceiver can thereby be
|
81
|
+
# placed on integer variables.
|
82
|
+
class IntVar
|
83
|
+
include Gecode::Int::IntOperand
|
84
|
+
attr :model
|
85
|
+
|
86
|
+
# Gets the minimum value still in the domain of the variable.
|
87
|
+
delegate :min
|
88
|
+
# Gets the maximum value still in the domain of the variable.
|
89
|
+
delegate :max
|
90
|
+
# Gets the number of elements still in the domain of the variable.
|
91
|
+
delegate :size
|
92
|
+
# Gets the width of the variable's domain, i.e. the distance between the
|
93
|
+
# maximum and minimum values.
|
94
|
+
delegate :width
|
95
|
+
# Gets the degree of the variable. The degree is the number of constraints
|
96
|
+
# that are affected by the variable. So if the variable is used in two
|
97
|
+
# constraints then the value will be 2.
|
98
|
+
delegate :degree
|
99
|
+
# Checks whether the domain is a range, i.e. doesn't contain any holes.
|
100
|
+
delegate :range?, :range
|
101
|
+
# Checks whether the variable has been assigned, i.e. its domain only
|
102
|
+
# contains one element.
|
103
|
+
delegate :assigned?, :assigned
|
104
|
+
# Checks whether a specified integer is in the variable's domain.
|
105
|
+
delegate :include?, :in
|
106
|
+
|
107
|
+
# Gets the value of the assigned integer variable (a Fixnum). The variable
|
108
|
+
# must be assigned, if it isn't then a RuntimeError is raised.
|
109
|
+
def value
|
110
|
+
raise 'No value is assigned.' unless assigned?
|
111
|
+
send_bound(:val)
|
112
|
+
end
|
113
|
+
|
114
|
+
# Returns the receiver.
|
115
|
+
def to_int_var
|
116
|
+
self
|
117
|
+
end
|
118
|
+
|
119
|
+
# Returns an enumeration corresponding to the domain.
|
120
|
+
def domain
|
121
|
+
if range?
|
122
|
+
min..max
|
123
|
+
else
|
124
|
+
(min..max).select do |i|
|
125
|
+
include? i
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
private
|
131
|
+
|
132
|
+
# Returns a string representation of the range of the variable's domain.
|
133
|
+
def domain_string #:nodoc:
|
134
|
+
if assigned?
|
135
|
+
"range: #{value.to_s}"
|
136
|
+
else
|
137
|
+
"range: #{min}..#{max}"
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
BoolVar = FreeVar(Gecode::Raw::BoolVar, :bool_var)
|
143
|
+
# Describes a boolean variable.
|
144
|
+
#
|
145
|
+
# A boolean variable can be either true or false.
|
146
|
+
#
|
147
|
+
# Boolean variables are boolean operands and hence respond to
|
148
|
+
# everything that Gecode::Bool::BoolOperand responds to.
|
149
|
+
# Any constraint found in
|
150
|
+
# Gecode::Bool::BoolConstraintReceiver can thereby be
|
151
|
+
# placed on boolean variables.
|
152
|
+
class BoolVar
|
153
|
+
include Gecode::Bool::BoolOperand
|
154
|
+
attr :model
|
155
|
+
|
156
|
+
# Checks whether the variable has been assigned.
|
157
|
+
delegate :assigned?, :assigned
|
158
|
+
|
159
|
+
# Gets the values in the assigned boolean variable (true or false). The
|
160
|
+
# variable must be assigned, if it isn't then a RuntimeError is raised.
|
161
|
+
def value
|
162
|
+
raise 'No value is assigned.' unless assigned?
|
163
|
+
send_bound(:val) == 1
|
164
|
+
end
|
165
|
+
|
166
|
+
# Returns the receiver.
|
167
|
+
def to_bool_var
|
168
|
+
self
|
169
|
+
end
|
170
|
+
|
171
|
+
private
|
172
|
+
|
173
|
+
# Returns a string representation of the the variable's domain.
|
174
|
+
def domain_string
|
175
|
+
if assigned?
|
176
|
+
value.to_s
|
177
|
+
else
|
178
|
+
'unassigned'
|
179
|
+
end
|
180
|
+
end
|
181
|
+
end
|
182
|
+
|
183
|
+
SetVar = FreeVar(Gecode::Raw::SetVar, :set_var)
|
184
|
+
# Describes a set variable.
|
185
|
+
#
|
186
|
+
# A set variable's domain, i.e. possible values that it can take, are
|
187
|
+
# represented with a greatest lower bound (GLB) and a least upper
|
188
|
+
# bound (LUB). The set variable may then take any set value S such
|
189
|
+
# that S is a subset of the least upper bound and the greatest lower
|
190
|
+
# bound is a subset of S.
|
191
|
+
#
|
192
|
+
# If for instance the set has a greatest lower bound {1} and least
|
193
|
+
# upper bound {1,3,5} then the assigned set may be any of the
|
194
|
+
# following four sets: {1}, {1,3}, {1,5}, {1,3,5}.
|
195
|
+
#
|
196
|
+
# The domain of a set variable may also specify the cardinality of the
|
197
|
+
# set, i.e. the number of elements that the set may contains.
|
198
|
+
#
|
199
|
+
# Set variables are set operands and hence respond to everything that
|
200
|
+
# Gecode::Set::SetOperand responds to. Any constraint
|
201
|
+
# found in Gecode::Set::SetConstraintReceiver can thereby
|
202
|
+
# be placed on set variables.
|
203
|
+
class SetVar
|
204
|
+
include Gecode::Set::SetOperand
|
205
|
+
attr :model
|
206
|
+
|
207
|
+
# Checks whether the variable has been assigned.
|
208
|
+
delegate :assigned?, :assigned
|
209
|
+
# Checks whether a value is included in the set.
|
210
|
+
delegate :in_lower_bound?, :contains
|
211
|
+
# Checks whether a value is not included in the set.
|
212
|
+
delegate :not_in_upper_bound?, :notContains
|
213
|
+
|
214
|
+
# Gets all the elements located in the greatest lower bound of the set (an
|
215
|
+
# Enumerable).
|
216
|
+
def lower_bound
|
217
|
+
min = send_bound(:glbMin)
|
218
|
+
max = send_bound(:glbMax)
|
219
|
+
EnumerableView.new(min, max, send_bound(:glbSize)) do
|
220
|
+
(min..max).to_a.delete_if{ |e| not send_bound(:contains, e) }
|
221
|
+
end
|
222
|
+
end
|
223
|
+
|
224
|
+
# Gets all the elements located in the least upper bound of the set (an
|
225
|
+
# Enumerable).
|
226
|
+
def upper_bound
|
227
|
+
min = send_bound(:lubMin)
|
228
|
+
max = send_bound(:lubMax)
|
229
|
+
EnumerableView.new(min, max, send_bound(:lubSize)) do
|
230
|
+
(min..max).to_a.delete_if{ |e| send_bound(:notContains, e) }
|
231
|
+
end
|
232
|
+
end
|
233
|
+
|
234
|
+
# Gets the values in the assigned set variable (an enumerable).
|
235
|
+
def value
|
236
|
+
raise 'No value is assigned.' unless assigned?
|
237
|
+
lower_bound
|
238
|
+
end
|
239
|
+
|
240
|
+
# Returns a range containing the allowed values for the set's cardinality.
|
241
|
+
def cardinality
|
242
|
+
send_bound(:cardMin)..send_bound(:cardMax)
|
243
|
+
end
|
244
|
+
|
245
|
+
# Returns the receiver.
|
246
|
+
def to_set_var
|
247
|
+
self
|
248
|
+
end
|
249
|
+
|
250
|
+
private
|
251
|
+
|
252
|
+
# Returns a string representation of the the variable's domain.
|
253
|
+
def domain_string
|
254
|
+
if assigned?
|
255
|
+
if lower_bound.size < 100
|
256
|
+
lower_bound.to_a.inspect
|
257
|
+
else
|
258
|
+
"the domain is too large to display"
|
259
|
+
end
|
260
|
+
else
|
261
|
+
if upper_bound.size < 100
|
262
|
+
"glb-range: #{lower_bound.to_a.inspect}, lub-range: #{upper_bound.to_a.inspect}"
|
263
|
+
else
|
264
|
+
"the domain is too large to display"
|
265
|
+
end
|
266
|
+
end
|
267
|
+
end
|
268
|
+
end
|
269
|
+
|
270
|
+
# Describes an immutable view of an enumerable.
|
271
|
+
class EnumerableView #:nodoc:
|
272
|
+
# Gets the number of elements in the view.
|
273
|
+
attr :size
|
274
|
+
# Gets the minimum element of the view.
|
275
|
+
attr :min
|
276
|
+
# Gets the maximum element of the view.
|
277
|
+
attr :max
|
278
|
+
include Enumerable
|
279
|
+
|
280
|
+
# Constructs a view with the specified minimum, maximum and size. The block
|
281
|
+
# should construct an enumerable containing the elements of the set.
|
282
|
+
def initialize(min, max, size, &enum_constructor)
|
283
|
+
@min = min
|
284
|
+
@max = max
|
285
|
+
@size = size
|
286
|
+
@constructor = enum_constructor
|
287
|
+
@enum = nil
|
288
|
+
end
|
289
|
+
|
290
|
+
# Iterates over every element in the view.
|
291
|
+
def each(&block)
|
292
|
+
enum.each(&block)
|
293
|
+
end
|
294
|
+
|
295
|
+
private
|
296
|
+
|
297
|
+
# Gets the enumeration being viewed.
|
298
|
+
def enum
|
299
|
+
if @enum.nil?
|
300
|
+
@enum = @constructor.call
|
301
|
+
else
|
302
|
+
return @enum
|
303
|
+
end
|
304
|
+
end
|
305
|
+
end
|
306
|
+
end
|