Name | Total Lines | Lines of Code | Total Coverage | Code Coverage |
---|---|---|---|---|
lib/gecoder/interface/variables.rb | 306 | 176 | 100.00%
|
100.00%
|
Code reported as executed by Ruby looks like this...and this: this line is also marked as covered.Lines considered as run by rcov, but not reported by Ruby, look like this,and this: these lines were inferred by rcov (using simple heuristics).Finally, here's a line marked as not executed.
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 |
Generated on Thu Jan 08 13:27:03 +0100 2015 with rcov 1.0.0