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.
Files changed (203) hide show
  1. data/CHANGES +137 -0
  2. data/COPYING +17 -0
  3. data/LGPL-LICENSE +458 -0
  4. data/README +58 -0
  5. data/Rakefile +14 -0
  6. data/example/equation_system.rb +15 -0
  7. data/example/example_helper.rb +1 -0
  8. data/example/magic_sequence.rb +43 -0
  9. data/example/money.rb +36 -0
  10. data/example/queens.rb +42 -0
  11. data/example/send_more_money.rb +43 -0
  12. data/example/send_most_money.rb +58 -0
  13. data/example/square_tiling.rb +84 -0
  14. data/example/sudoku-set.rb +106 -0
  15. data/example/sudoku.rb +56 -0
  16. data/lib/gecode.dll +0 -0
  17. data/lib/gecoder.rb +5 -0
  18. data/lib/gecoder/bindings.rb +96 -0
  19. data/lib/gecoder/bindings/bindings.rb +2029 -0
  20. data/lib/gecoder/interface.rb +9 -0
  21. data/lib/gecoder/interface/binding_changes.rb +9 -0
  22. data/lib/gecoder/interface/branch.rb +163 -0
  23. data/lib/gecoder/interface/constraints.rb +471 -0
  24. data/lib/gecoder/interface/constraints/bool/boolean.rb +251 -0
  25. data/lib/gecoder/interface/constraints/bool/channel.rb +7 -0
  26. data/lib/gecoder/interface/constraints/bool/linear.rb +200 -0
  27. data/lib/gecoder/interface/constraints/bool_enum/channel.rb +68 -0
  28. data/lib/gecoder/interface/constraints/bool_enum/extensional.rb +106 -0
  29. data/lib/gecoder/interface/constraints/bool_enum/relation.rb +55 -0
  30. data/lib/gecoder/interface/constraints/bool_enum_constraints.rb +84 -0
  31. data/lib/gecoder/interface/constraints/bool_var_constraints.rb +155 -0
  32. data/lib/gecoder/interface/constraints/extensional_regexp.rb +101 -0
  33. data/lib/gecoder/interface/constraints/fixnum_enum/element.rb +63 -0
  34. data/lib/gecoder/interface/constraints/fixnum_enum/operation.rb +65 -0
  35. data/lib/gecoder/interface/constraints/fixnum_enum_constraints.rb +42 -0
  36. data/lib/gecoder/interface/constraints/int/arithmetic.rb +150 -0
  37. data/lib/gecoder/interface/constraints/int/channel.rb +51 -0
  38. data/lib/gecoder/interface/constraints/int/domain.rb +80 -0
  39. data/lib/gecoder/interface/constraints/int/linear.rb +143 -0
  40. data/lib/gecoder/interface/constraints/int/relation.rb +141 -0
  41. data/lib/gecoder/interface/constraints/int_enum/arithmetic.rb +63 -0
  42. data/lib/gecoder/interface/constraints/int_enum/channel.rb +86 -0
  43. data/lib/gecoder/interface/constraints/int_enum/count.rb +66 -0
  44. data/lib/gecoder/interface/constraints/int_enum/distinct.rb +64 -0
  45. data/lib/gecoder/interface/constraints/int_enum/element.rb +64 -0
  46. data/lib/gecoder/interface/constraints/int_enum/equality.rb +37 -0
  47. data/lib/gecoder/interface/constraints/int_enum/extensional.rb +187 -0
  48. data/lib/gecoder/interface/constraints/int_enum/sort.rb +135 -0
  49. data/lib/gecoder/interface/constraints/int_enum_constraints.rb +95 -0
  50. data/lib/gecoder/interface/constraints/int_var_constraints.rb +230 -0
  51. data/lib/gecoder/interface/constraints/reifiable_constraints.rb +78 -0
  52. data/lib/gecoder/interface/constraints/selected_set/select.rb +120 -0
  53. data/lib/gecoder/interface/constraints/selected_set_constraints.rb +75 -0
  54. data/lib/gecoder/interface/constraints/set/cardinality.rb +65 -0
  55. data/lib/gecoder/interface/constraints/set/channel.rb +51 -0
  56. data/lib/gecoder/interface/constraints/set/connection.rb +130 -0
  57. data/lib/gecoder/interface/constraints/set/domain.rb +156 -0
  58. data/lib/gecoder/interface/constraints/set/include.rb +36 -0
  59. data/lib/gecoder/interface/constraints/set/operation.rb +118 -0
  60. data/lib/gecoder/interface/constraints/set/relation.rb +155 -0
  61. data/lib/gecoder/interface/constraints/set_elements/relation.rb +116 -0
  62. data/lib/gecoder/interface/constraints/set_elements_constraints.rb +97 -0
  63. data/lib/gecoder/interface/constraints/set_enum/channel.rb +45 -0
  64. data/lib/gecoder/interface/constraints/set_enum/distinct.rb +43 -0
  65. data/lib/gecoder/interface/constraints/set_enum/operation.rb +69 -0
  66. data/lib/gecoder/interface/constraints/set_enum/select.rb +79 -0
  67. data/lib/gecoder/interface/constraints/set_enum_constraints.rb +84 -0
  68. data/lib/gecoder/interface/constraints/set_var_constraints.rb +243 -0
  69. data/lib/gecoder/interface/enum_matrix.rb +64 -0
  70. data/lib/gecoder/interface/enum_wrapper.rb +205 -0
  71. data/lib/gecoder/interface/model.rb +453 -0
  72. data/lib/gecoder/interface/model_sugar.rb +84 -0
  73. data/lib/gecoder/interface/search.rb +197 -0
  74. data/lib/gecoder/interface/variables.rb +306 -0
  75. data/lib/gecoder/version.rb +4 -0
  76. data/specs/bool_var.rb +81 -0
  77. data/specs/branch.rb +185 -0
  78. data/specs/constraints/bool/boolean.rb +317 -0
  79. data/specs/constraints/bool/boolean_properties.rb +51 -0
  80. data/specs/constraints/bool/linear.rb +213 -0
  81. data/specs/constraints/bool_enum/bool_enum_relation.rb +117 -0
  82. data/specs/constraints/bool_enum/channel.rb +102 -0
  83. data/specs/constraints/bool_enum/extensional.rb +225 -0
  84. data/specs/constraints/constraint_helper.rb +234 -0
  85. data/specs/constraints/constraint_receivers.rb +103 -0
  86. data/specs/constraints/constraints.rb +26 -0
  87. data/specs/constraints/fixnum_enum/element.rb +58 -0
  88. data/specs/constraints/fixnum_enum/operation.rb +67 -0
  89. data/specs/constraints/int/arithmetic.rb +149 -0
  90. data/specs/constraints/int/channel.rb +101 -0
  91. data/specs/constraints/int/domain.rb +106 -0
  92. data/specs/constraints/int/linear.rb +183 -0
  93. data/specs/constraints/int/linear_properties.rb +97 -0
  94. data/specs/constraints/int/relation.rb +84 -0
  95. data/specs/constraints/int_enum/arithmetic.rb +72 -0
  96. data/specs/constraints/int_enum/channel.rb +57 -0
  97. data/specs/constraints/int_enum/count.rb +72 -0
  98. data/specs/constraints/int_enum/distinct.rb +80 -0
  99. data/specs/constraints/int_enum/element.rb +61 -0
  100. data/specs/constraints/int_enum/equality.rb +29 -0
  101. data/specs/constraints/int_enum/extensional.rb +224 -0
  102. data/specs/constraints/int_enum/sort.rb +167 -0
  103. data/specs/constraints/operands.rb +264 -0
  104. data/specs/constraints/property_helper.rb +443 -0
  105. data/specs/constraints/reification_sugar.rb +69 -0
  106. data/specs/constraints/selected_set/select.rb +56 -0
  107. data/specs/constraints/selected_set/select_properties.rb +157 -0
  108. data/specs/constraints/set/cardinality.rb +58 -0
  109. data/specs/constraints/set/cardinality_properties.rb +46 -0
  110. data/specs/constraints/set/channel.rb +77 -0
  111. data/specs/constraints/set/connection.rb +176 -0
  112. data/specs/constraints/set/domain.rb +197 -0
  113. data/specs/constraints/set/include.rb +36 -0
  114. data/specs/constraints/set/operation.rb +132 -0
  115. data/specs/constraints/set/relation.rb +117 -0
  116. data/specs/constraints/set_elements/relation.rb +84 -0
  117. data/specs/constraints/set_enum/channel.rb +80 -0
  118. data/specs/constraints/set_enum/distinct.rb +59 -0
  119. data/specs/constraints/set_enum/operation.rb +111 -0
  120. data/specs/constraints/set_enum/select.rb +73 -0
  121. data/specs/distribution.rb +14 -0
  122. data/specs/enum_matrix.rb +43 -0
  123. data/specs/enum_wrapper.rb +179 -0
  124. data/specs/examples.rb +17 -0
  125. data/specs/int_var.rb +163 -0
  126. data/specs/logging.rb +24 -0
  127. data/specs/model.rb +325 -0
  128. data/specs/model_sugar.rb +30 -0
  129. data/specs/search.rb +383 -0
  130. data/specs/selected_set.rb +39 -0
  131. data/specs/set_elements.rb +34 -0
  132. data/specs/set_var.rb +82 -0
  133. data/specs/spec_helper.rb +265 -0
  134. data/tasks/all_tasks.rb +1 -0
  135. data/tasks/dependencies.txt +22 -0
  136. data/tasks/distribution.rake +194 -0
  137. data/tasks/rcov.rake +18 -0
  138. data/tasks/specs.rake +21 -0
  139. data/tasks/svn.rake +16 -0
  140. data/tasks/website.rake +51 -0
  141. data/vendor/gecode/win32/lib/libgecodeint.dll +0 -0
  142. data/vendor/gecode/win32/lib/libgecodekernel.dll +0 -0
  143. data/vendor/gecode/win32/lib/libgecodeminimodel.dll +0 -0
  144. data/vendor/gecode/win32/lib/libgecodesearch.dll +0 -0
  145. data/vendor/gecode/win32/lib/libgecodeset.dll +0 -0
  146. data/vendor/gecode/win32/lib/libgecodesupport.dll +0 -0
  147. data/vendor/rust/README +28 -0
  148. data/vendor/rust/bin/cxxgenerator.rb +93 -0
  149. data/vendor/rust/include/rust_checks.hh +116 -0
  150. data/vendor/rust/include/rust_conversions.hh +102 -0
  151. data/vendor/rust/rust.rb +67 -0
  152. data/vendor/rust/rust/attribute.rb +51 -0
  153. data/vendor/rust/rust/bindings.rb +172 -0
  154. data/vendor/rust/rust/class.rb +337 -0
  155. data/vendor/rust/rust/constants.rb +48 -0
  156. data/vendor/rust/rust/container.rb +110 -0
  157. data/vendor/rust/rust/cppifaceparser.rb +129 -0
  158. data/vendor/rust/rust/cwrapper.rb +72 -0
  159. data/vendor/rust/rust/cxxclass.rb +96 -0
  160. data/vendor/rust/rust/element.rb +81 -0
  161. data/vendor/rust/rust/enum.rb +63 -0
  162. data/vendor/rust/rust/function.rb +407 -0
  163. data/vendor/rust/rust/namespace.rb +61 -0
  164. data/vendor/rust/rust/templates/AttributeDefinition.rusttpl +17 -0
  165. data/vendor/rust/rust/templates/AttributeInitBinding.rusttpl +9 -0
  166. data/vendor/rust/rust/templates/BindingsHeader.rusttpl +24 -0
  167. data/vendor/rust/rust/templates/BindingsUnit.rusttpl +46 -0
  168. data/vendor/rust/rust/templates/CWrapperClassDefinitions.rusttpl +64 -0
  169. data/vendor/rust/rust/templates/ClassDeclarations.rusttpl +7 -0
  170. data/vendor/rust/rust/templates/ClassInitialize.rusttpl +6 -0
  171. data/vendor/rust/rust/templates/ConstructorStub.rusttpl +21 -0
  172. data/vendor/rust/rust/templates/CxxClassDefinitions.rusttpl +100 -0
  173. data/vendor/rust/rust/templates/CxxMethodStub.rusttpl +12 -0
  174. data/vendor/rust/rust/templates/CxxStandaloneClassDefinitions.rusttpl +26 -0
  175. data/vendor/rust/rust/templates/EnumDeclarations.rusttpl +3 -0
  176. data/vendor/rust/rust/templates/EnumDefinitions.rusttpl +29 -0
  177. data/vendor/rust/rust/templates/FunctionDefinition.rusttpl +9 -0
  178. data/vendor/rust/rust/templates/FunctionInitAlias.rusttpl +5 -0
  179. data/vendor/rust/rust/templates/FunctionInitBinding.rusttpl +9 -0
  180. data/vendor/rust/rust/templates/MethodInitBinding.rusttpl +9 -0
  181. data/vendor/rust/rust/templates/ModuleDeclarations.rusttpl +3 -0
  182. data/vendor/rust/rust/templates/ModuleDefinitions.rusttpl +3 -0
  183. data/vendor/rust/rust/templates/StandaloneClassDeclarations.rusttpl +7 -0
  184. data/vendor/rust/rust/templates/VariableFunctionCall.rusttpl +14 -0
  185. data/vendor/rust/rust/type.rb +98 -0
  186. data/vendor/rust/test/Makefile +4 -0
  187. data/vendor/rust/test/constants.rb +36 -0
  188. data/vendor/rust/test/cppclass.cc +45 -0
  189. data/vendor/rust/test/cppclass.hh +67 -0
  190. data/vendor/rust/test/cppclass.rb +59 -0
  191. data/vendor/rust/test/cwrapper.c +74 -0
  192. data/vendor/rust/test/cwrapper.h +41 -0
  193. data/vendor/rust/test/cwrapper.rb +56 -0
  194. data/vendor/rust/test/dummyclass.hh +31 -0
  195. data/vendor/rust/test/lib/extension-test.rb +98 -0
  196. data/vendor/rust/test/operators.cc +41 -0
  197. data/vendor/rust/test/operators.hh +39 -0
  198. data/vendor/rust/test/operators.rb +39 -0
  199. data/vendor/rust/test/test-constants.rb +43 -0
  200. data/vendor/rust/test/test-cppclass.rb +82 -0
  201. data/vendor/rust/test/test-cwrapper.rb +80 -0
  202. data/vendor/rust/test/test-operators.rb +42 -0
  203. 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