Name | Total Lines | Lines of Code | Total Coverage | Code Coverage |
---|---|---|---|---|
lib/gecoder/interface/constraints/bool/boolean.rb | 251 | 140 | 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::Bool |
2 module BoolOperand |
3 # Produces a new BoolOperand representing this operand OR +bool_op+. |
4 # |
5 # ==== Examples |
6 # |
7 # # +b1+ and +b2+ |
8 # b1 & b2 |
9 def |(bool_op) |
10 bool_expression_operation(:|, bool_op) |
11 end |
12 |
13 # Produces a new BoolOperand representing this operand AND +bool_op+. |
14 # |
15 # ==== Examples |
16 # |
17 # # (+b1+ and +b2+) or +b3+ |
18 # (b1 & b1) | b3 |
19 def &(bool_op) |
20 bool_expression_operation(:&, bool_op) |
21 end |
22 |
23 # Produces a new BoolOperand representing this operand XOR +bool_op+. |
24 # |
25 # ==== Examples |
26 # |
27 # # (+b1+ and +b2+) or (+b3+ exclusive or +b1+) |
28 # (b1 & b2) | (b3 ^ b1) |
29 def ^(bool_op) |
30 bool_expression_operation(:^, bool_op) |
31 end |
32 |
33 # Produces a new BoolOperand representing that this operand implies |
34 # +bool_op+. |
35 # |
36 # ==== Examples |
37 # |
38 # # (+b1+ implies +b2+) and (+b3+ implies +b2+) |
39 # (b1.implies b2) & (b3.implies b2) |
40 def implies(bool_op) |
41 bool_expression_operation(:implies, bool_op) |
42 end |
43 |
44 private |
45 |
46 # Performs the bool expression operation +operator+ on self |
47 # and +operand2+. |
48 def bool_expression_operation(operator, operand2) |
49 unless operand2.respond_to? :to_minimodel_bool_expr |
50 operand2 = ExpressionNode.new operand2 |
51 end |
52 operand1 = self |
53 unless operand1.respond_to? :to_minimodel_bool_expr |
54 operand1 = ExpressionNode.new(self, @model) |
55 end |
56 ExpressionTree.new(operand1, operator, operand2) |
57 end |
58 end |
59 |
60 class BoolConstraintReceiver |
61 # Constrains the boolean operand to be equal to +bool_op+. Any of |
62 # <tt>==</tt>, +equal+ and +equal_to+ may be used for equality. |
63 # |
64 # ==== Examples |
65 # |
66 # # +b1+ and +b2+ must equal +b1+ or +b2+. |
67 # (b1 & b2).must == (b1 | b2) |
68 # |
69 # # +b1+ and +b2+ must not equal +b3+. We reify it with +bool+ and select |
70 # # the strength +domain+. |
71 # (b1 & b2).must_not.equal(b3, :reify => bool, :select => :domain) |
72 def ==(bool_op, options = {}) |
73 unless bool_op.respond_to? :to_minimodel_bool_expr |
74 bool_op = ExpressionNode.new(bool_op, @model) |
75 end |
76 @params.update Gecode::Util.decode_options(options) |
77 @params.update(:lhs => @params[:lhs], :rhs => bool_op) |
78 @model.add_constraint BooleanConstraint.new(@model, @params) |
79 end |
80 alias_comparison_methods |
81 |
82 # Constrains the boolean operand to imply +bool_op+. |
83 # |
84 # ==== Examples |
85 # |
86 # # +b1+ must imply +b2+ |
87 # b1.must.imply b2 |
88 # |
89 # # +b1+ and +b2+ must not imply +b3+. We reify it with +bool+ and select |
90 # # +domain+ as strength. |
91 # (b1 & b2).must_not.imply(b3, :reify => bool, :strength => :domain) |
92 def imply(bool_op, options = {}) |
93 @params.update Gecode::Util.decode_options(options) |
94 @params.update(:lhs => @params[:lhs].implies(bool_op), :rhs => true) |
95 @model.add_constraint BooleanConstraint.new(@model, @params) |
96 end |
97 |
98 # Constrains the boolean operand to be true. |
99 # |
100 # ==== Examples |
101 # |
102 # # +b1+ and +b2+ must be true. |
103 # (b1 & b2).must_be.true |
104 # |
105 # # (+b1+ implies +b2+) and (+b3+ implies +b2+) must be true. |
106 # ((b1.implies b2) & (b3.implies b2)).must_be.true |
107 # |
108 # # +b1+ and +b2+ must be true. We reify it with +bool+ and select the |
109 # # strength +domain+. |
110 # (b1 & b2).must_be.true(:reify => bool, :strength => :domain) |
111 def true(options = {}) |
112 @params.update Gecode::Util.decode_options(options) |
113 @model.add_constraint BooleanConstraint.new(@model, |
114 @params.update(:rhs => true)) |
115 end |
116 |
117 # Constrains the boolean operand to be false. |
118 # |
119 # ==== Examples |
120 # |
121 # # +b1+ and +b2+ must be false. |
122 # (b1 & b2).must_be.false |
123 # |
124 # # (+b1+ implies +b2+) and (+b3+ implies +b2+) must be false. |
125 # ((b1.implies b2) & (b3.implies b2)).must_be.false |
126 # |
127 # # +b1+ and +b2+ must be false. We reify it with +bool+ and select the |
128 # # strength +domain+. |
129 # (b1 & b2).must_be.false(:reify => bool, :strength => :domain) |
130 def false(options = {}) |
131 @params[:negate] = !@params[:negate] |
132 self.true(options) |
133 end |
134 end |
135 |
136 class BooleanConstraint < Gecode::ReifiableConstraint #:nodoc: |
137 def post |
138 lhs, rhs, negate, reif_var = |
139 @params.values_at(:lhs, :rhs, :negate, :reif) |
140 |
141 if lhs.respond_to? :to_bool_var |
142 lhs = ExpressionNode.new(lhs, @model) |
143 end |
144 space = (lhs.model || rhs.model).active_space |
145 |
146 bot_eqv = Gecode::Raw::IRT_EQ |
147 bot_xor = Gecode::Raw::IRT_NQ |
148 |
149 if rhs.respond_to? :to_minimodel_bool_expr |
150 if reif_var.nil? |
151 tree = ExpressionTree.new(lhs, :==, rhs) |
152 tree.to_minimodel_bool_expr.post(space, !negate, |
153 *propagation_options) |
154 else |
155 tree = ExpressionTree.new(lhs, :==, rhs) |
156 var = tree.to_minimodel_bool_expr.post(space, *propagation_options) |
157 Gecode::Raw::rel(space, var, (negate ? bot_xor : bot_eqv), |
158 reif_var.to_bool_var.bind, *propagation_options) |
159 end |
160 else |
161 should_hold = !negate & rhs |
162 if reif_var.nil? |
163 lhs.to_minimodel_bool_expr.post(space, should_hold, |
164 *propagation_options) |
165 else |
166 var = lhs.to_minimodel_bool_expr.post(space, *propagation_options) |
167 Gecode::Raw::rel(space, var, |
168 (should_hold ? bot_eqv : bot_xor), |
169 reif_var.to_bool_var.bind, *propagation_options) |
170 end |
171 end |
172 end |
173 end |
174 |
175 # Describes a binary tree of expression nodes which together form a boolean |
176 # expression. |
177 class ExpressionTree #:nodoc: |
178 include BoolOperand |
179 |
180 private |
181 |
182 # Maps the names of the methods to the corresponding bool constraint in |
183 # Gecode. |
184 OPERATION_TYPES = { |
185 :| => Gecode::Raw::MiniModel::BoolExpr::NT_OR, |
186 :& => Gecode::Raw::MiniModel::BoolExpr::NT_AND, |
187 :^ => Gecode::Raw::MiniModel::BoolExpr::NT_XOR, |
188 :implies => Gecode::Raw::MiniModel::BoolExpr::NT_IMP, |
189 :== => Gecode::Raw::MiniModel::BoolExpr::NT_EQV |
190 } |
191 |
192 public |
193 |
194 # Constructs a new expression with the specified binary operation |
195 # applied to the specified trees. |
196 def initialize(left_tree, operation, right_tree) |
197 @left = left_tree |
198 @operation = operation |
199 @right = right_tree |
200 end |
201 |
202 # Returns a MiniModel boolean expression representing the tree. |
203 def to_minimodel_bool_expr |
204 Gecode::Raw::MiniModel::BoolExpr.new( |
205 @left.to_minimodel_bool_expr, OPERATION_TYPES[@operation], |
206 @right.to_minimodel_bool_expr) |
207 end |
208 |
209 # Fetches the space that the expression's variables is in. |
210 def model |
211 @left.model || @right.model |
212 end |
213 |
214 def to_bool_var |
215 bool_var = model.bool_var |
216 tree = ExpressionTree.new(self, :==, ExpressionNode.new(bool_var)) |
217 model.add_interaction do |
218 tree.to_minimodel_bool_expr.post(model.active_space, true, |
219 Gecode::Raw::ICL_DEF, Gecode::Raw::PK_DEF) |
220 end |
221 return bool_var |
222 end |
223 |
224 private |
225 |
226 # Produces a receiver (for the BoolOperand module). |
227 def construct_receiver(params) |
228 params.update(:lhs => self) |
229 BoolConstraintReceiver.new(model, params) |
230 end |
231 end |
232 |
233 # Describes a single node in a boolean expression. |
234 class ExpressionNode #:nodoc: |
235 attr :model |
236 |
237 def initialize(value, model = nil) |
238 unless value.respond_to? :to_bool_var |
239 raise TypeError, 'Invalid type used in boolean equation: ' + |
240 "#{value.class}." |
241 end |
242 @value = value |
243 @model = model |
244 end |
245 |
246 # Returns a MiniModel boolean expression representing the tree. |
247 def to_minimodel_bool_expr |
248 Gecode::Raw::MiniModel::BoolExpr.new(@value.to_bool_var.bind) |
249 end |
250 end |
251 end |
Generated on Thu Jan 08 13:27:03 +0100 2015 with rcov 1.0.0