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.
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