Name | Total Lines | Lines of Code | Total Coverage | Code Coverage |
---|---|---|---|---|
lib/gecoder/interface/constraints/set_var_constraints.rb | 243 | 134 | 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 # A module containing constraints that have set operands as left hand side |
2 # (but not enumerations). |
3 module Gecode::Set #:nodoc: |
4 # A SetOperand is a combination of operands on which the |
5 # constraints defined in SetConstraintReceiver can be placed. |
6 # |
7 # Set operands can be created either by using Gecode::Mixin#set_var et |
8 # al, or by using properties that produce set operands. The operands, |
9 # no matter how they were created, all respond to the properties |
10 # defined by SetOperand. |
11 # |
12 # ==== Examples |
13 # |
14 # Produces a single set operand (more specifically a SetVar), with |
15 # greatest lower bound {0} and least upper bound {0, 1, 2}, inside a |
16 # problem formulation, using Gecode::Mixin#set_var: |
17 # |
18 # set_operand = set_var(0, 0..2) |
19 # |
20 # Uses the SetOperand#union property to produce a new set operand |
21 # representing the union between +set_operand1+ and +set_operand2+: |
22 # |
23 # new_set_operand = set_operand1.union(set_operand2) |
24 # |
25 # Uses the SetEnumOperand#union property to produce a new set operand |
26 # representing the union of the set operands in the enumeration |
27 # +set_enum+: |
28 # |
29 # new_set_operand = set_enum.union |
30 # |
31 # Uses the SetEnumOperand#[] property to produce a new set operand |
32 # representing the set operand at the index decided by |
33 # +int_operand+ (which can change during search) in the enumeration |
34 # +set_enum+: |
35 # |
36 # new_set_operand = set_enum[int_operand] |
37 # |
38 #-- |
39 # Classes that mix in SetOperand must define #model and #to_set_var . |
40 module SetOperand |
41 include Gecode::Operand |
42 |
43 def method_missing(method, *args) #:nodoc: |
44 if Gecode::SetVar.instance_methods.include? method.to_s |
45 # Delegate to the set var. |
46 to_set_var.method(method).call(*args) |
47 else |
48 super |
49 end |
50 end |
51 |
52 private |
53 |
54 def construct_receiver(params) |
55 SetConstraintReceiver.new(model, params) |
56 end |
57 end |
58 |
59 # An operand that short circuits set equality. |
60 class ShortCircuitEqualityOperand #:nodoc: |
61 include Gecode::Set::SetOperand |
62 attr :model |
63 |
64 def initialize(model) |
65 @model = model |
66 end |
67 |
68 def construct_receiver(params) |
69 params.update(:lhs => self) |
70 receiver = SetConstraintReceiver.new(@model, params) |
71 op = self |
72 receiver.instance_eval{ @short_circuit = op } |
73 class <<receiver |
74 alias_method :equality_without_short_circuit, :== |
75 def ==(operand, options = {}) |
76 if !@params[:negate] and !options.has_key?(:reify) and |
77 operand.respond_to? :to_set_var |
78 # Short circuit the constraint. |
79 @params.update Gecode::Util.decode_options(options) |
80 @model.add_constraint(Gecode::BlockConstraint.new( |
81 @model, @params) do |
82 @short_circuit.constrain_equal(operand, false, |
83 @params.values_at(:strength, :kind)) |
84 end) |
85 else |
86 equality_without_short_circuit(operand, options) |
87 end |
88 end |
89 alias_comparison_methods |
90 end |
91 |
92 return receiver |
93 end |
94 |
95 def to_set_var |
96 variable = model.set_var |
97 options = |
98 Gecode::Set::Util.decode_options( |
99 {}).values_at(:strength, :kind) |
100 model.add_interaction do |
101 constrain_equal(variable, true, options) |
102 end |
103 return variable |
104 end |
105 |
106 private |
107 |
108 # Constrains this operand to equal +set_operand+ using the |
109 # specified +propagation_options+. If +constrain_domain+ is true |
110 # then the method should also attempt to constrain the bounds of the |
111 # domain of +set_operand+. |
112 def constrain_equal(set_operand, constrain_domain, propagation_options) |
113 raise NotImplementedError, 'Abstract method has not been implemented.' |
114 end |
115 end |
116 |
117 # An operand that short circuits set non-negated and non-reified versions |
118 # of the relation constraints. |
119 class ShortCircuitRelationsOperand #:nodoc: |
120 include Gecode::Set::SetOperand |
121 attr :model |
122 |
123 def initialize(model) |
124 @model = model |
125 end |
126 |
127 def construct_receiver(params) |
128 params.update(:lhs => self) |
129 receiver = SetConstraintReceiver.new(@model, params) |
130 op = self |
131 receiver.instance_eval{ @short_circuit = op } |
132 class <<receiver |
133 Gecode::Util::SET_RELATION_TYPES.keys.each do |comp| |
134 eval <<-end_code |
135 alias_method :alias_#{comp.to_i}_without_short_circuit, :#{comp} |
136 def #{comp}(operand, options = {}) |
137 if !@params[:negate] && !options.has_key?(:reify) && |
138 (operand.respond_to?(:to_set_var) or |
139 Gecode::Util::constant_set?(operand)) |
140 # Short circuit the constraint. |
141 @params.update Gecode::Set::Util.decode_options(options) |
142 @model.add_constraint( |
143 @short_circuit.relation_constraint( |
144 :#{comp}, operand, @params)) |
145 else |
146 alias_#{comp.to_i}_without_short_circuit(operand, options) |
147 end |
148 end |
149 end_code |
150 end |
151 alias_comparison_methods |
152 end |
153 |
154 return receiver |
155 end |
156 |
157 def to_set_var |
158 variable = model.set_var |
159 params = {:lhs => self} |
160 params.update Gecode::Set::Util.decode_options({}) |
161 model.add_constraint relation_constraint(:==, variable, params) |
162 return variable |
163 end |
164 |
165 # Returns a constraint that constrains this operand to have relation |
166 # +relation+ to +set_operand_or_constant_set+, which is either a set |
167 # operand or a constant set, given the specified hash +params+ of |
168 # parameters. The constraints are never negated nor reified. |
169 def relation_constraint(relation, set_operand_or_constant_set, params) |
170 raise NotImplementedError, 'Abstract method has not been implemented.' |
171 end |
172 end |
173 |
174 # SetConstraintReceiver contains all constraints that can be |
175 # placed on a SetOperand. |
176 # |
177 # Constraints are placed by calling SetOperand#must (or any other |
178 # of the variations defined in Operand), which produces a |
179 # SetConstraintReceiver from which the desired constraint can be used. |
180 # |
181 # Most constraint accept :reify option. See ConstraintReceiver for |
182 # more information. |
183 # |
184 # ==== Examples |
185 # |
186 # Constrains +set_operand+ to be a subset of {0, 1, 2} using |
187 # an alias of SetConstraintReceiver#subset: |
188 # |
189 # set_operand.must_be.subset_of 0..2 |
190 # |
191 # Constrains the union of +set_operand1+ and +set_operand2+ to a |
192 # subset of {0, 1, 2} using the SetOperand#union property and |
193 # SetConstraintReceiver#subset: |
194 # |
195 # set_operand1.union(set_operand2).must_be.subset_of 0..2 |
196 # |
197 # Constrains the union of the set operands in +set_enum+ to _not_ |
198 # equal {0, 1, 2} by using the SetEnumOperand#union property and |
199 # an alias of SetConstraintReceiver#==: |
200 # |
201 # set_enum.union.must_not == 0..2 |
202 # |
203 # The same as above, but alsa specifying that the constraint should be |
204 # reified with +bool_operand+: |
205 # |
206 # set_enum.union.must_not.equal(0..2, :reify => bool_operand) |
207 # |
208 class SetConstraintReceiver < Gecode::ConstraintReceiver |
209 # Raises TypeError unless the left hand side is a set operand. |
210 def initialize(model, params) #:nodoc: |
211 super |
212 |
213 unless params[:lhs].respond_to? :to_set_var |
214 raise TypeError, 'Must have set operand as left hand side.' |
215 end |
216 end |
217 end |
218 |
219 # Utility methods for sets. |
220 module Util #:nodoc: |
221 module_function |
222 def decode_options(options) |
223 if options.has_key? :strength |
224 raise ArgumentError, 'Set constraints do not support the strength ' + |
225 'option.' |
226 end |
227 if options.has_key? :kind |
228 raise ArgumentError, 'Set constraints do not support the kind ' + |
229 'option.' |
230 end |
231 |
232 Gecode::Util.decode_options(options) |
233 end |
234 end |
235 end |
236 |
237 require 'gecoder/interface/constraints/set/domain' |
238 require 'gecoder/interface/constraints/set/relation' |
239 require 'gecoder/interface/constraints/set/cardinality' |
240 require 'gecoder/interface/constraints/set/connection' |
241 require 'gecoder/interface/constraints/set/include' |
242 require 'gecoder/interface/constraints/set/operation' |
243 require 'gecoder/interface/constraints/set/channel' |
Generated on Thu Jan 08 13:27:03 +0100 2015 with rcov 1.0.0