1 |
|
/****************************************************************************** |
2 |
|
* Top contributors (to current version): |
3 |
|
* Gereon Kremer |
4 |
|
* |
5 |
|
* This file is part of the cvc5 project. |
6 |
|
* |
7 |
|
* Copyright (c) 2009-2021 by the authors listed in the file AUTHORS |
8 |
|
* in the top-level source directory and their institutional affiliations. |
9 |
|
* All rights reserved. See the file COPYING in the top-level source |
10 |
|
* directory for licensing information. |
11 |
|
* **************************************************************************** |
12 |
|
* |
13 |
|
* Proofs for the non-clausal circuit propagator. |
14 |
|
*/ |
15 |
|
|
16 |
|
#include "theory/booleans/proof_circuit_propagator.h" |
17 |
|
|
18 |
|
#include <sstream> |
19 |
|
|
20 |
|
#include "expr/proof_node.h" |
21 |
|
#include "expr/proof_node_manager.h" |
22 |
|
|
23 |
|
namespace cvc5 { |
24 |
|
namespace theory { |
25 |
|
namespace booleans { |
26 |
|
|
27 |
|
namespace { |
28 |
|
|
29 |
|
/** Shorthand to create a Node from a constant number */ |
30 |
|
template <typename T> |
31 |
41066 |
Node mkRat(T val) |
32 |
|
{ |
33 |
41066 |
return NodeManager::currentNM()->mkConst<Rational>(val); |
34 |
|
} |
35 |
|
|
36 |
|
/** |
37 |
|
* Collect all children from parent except for one particular child (the |
38 |
|
* "holdout"). The holdout is given as iterator, and should be an iterator into |
39 |
|
* the [parent.begin(),parent.end()] range. |
40 |
|
*/ |
41 |
665 |
inline std::vector<Node> collectButHoldout(TNode parent, |
42 |
|
TNode::iterator holdout) |
43 |
|
{ |
44 |
665 |
std::vector<Node> lits; |
45 |
2248 |
for (TNode::iterator i = parent.begin(), i_end = parent.end(); i != i_end; |
46 |
|
++i) |
47 |
|
{ |
48 |
1583 |
if (i != holdout) |
49 |
|
{ |
50 |
918 |
lits.emplace_back(*i); |
51 |
|
} |
52 |
|
} |
53 |
665 |
return lits; |
54 |
|
} |
55 |
|
|
56 |
|
} // namespace |
57 |
|
|
58 |
1095897 |
ProofCircuitPropagator::ProofCircuitPropagator(ProofNodeManager* pnm) |
59 |
1095897 |
: d_pnm(pnm) |
60 |
|
{ |
61 |
1095897 |
} |
62 |
|
|
63 |
1022641 |
bool ProofCircuitPropagator::disabled() const { return d_pnm == nullptr; } |
64 |
|
|
65 |
8978654 |
std::shared_ptr<ProofNode> ProofCircuitPropagator::assume(Node n) |
66 |
|
{ |
67 |
8978654 |
return d_pnm->mkAssume(n); |
68 |
|
} |
69 |
|
|
70 |
103 |
std::shared_ptr<ProofNode> ProofCircuitPropagator::conflict( |
71 |
|
const std::shared_ptr<ProofNode>& a, const std::shared_ptr<ProofNode>& b) |
72 |
|
{ |
73 |
103 |
if (a->getResult().notNode() == b->getResult()) |
74 |
|
{ |
75 |
68 |
return mkProof(PfRule::CONTRA, {a, b}); |
76 |
|
} |
77 |
35 |
Assert(a->getResult() == b->getResult().notNode()); |
78 |
35 |
return mkProof(PfRule::CONTRA, {b, a}); |
79 |
|
} |
80 |
|
|
81 |
810 |
std::shared_ptr<ProofNode> ProofCircuitPropagator::andFalse( |
82 |
|
Node parent, TNode::iterator holdout) |
83 |
|
{ |
84 |
810 |
if (disabled()) |
85 |
|
{ |
86 |
560 |
return nullptr; |
87 |
|
} |
88 |
|
return mkNot( |
89 |
500 |
mkCResolution(mkProof(PfRule::NOT_AND, {assume(parent.notNode())}), |
90 |
500 |
collectButHoldout(parent, holdout), |
91 |
250 |
false)); |
92 |
|
} |
93 |
|
|
94 |
87937 |
std::shared_ptr<ProofNode> ProofCircuitPropagator::orTrue( |
95 |
|
Node parent, TNode::iterator holdout) |
96 |
|
{ |
97 |
87937 |
if (disabled()) |
98 |
|
{ |
99 |
87522 |
return nullptr; |
100 |
|
} |
101 |
|
return mkCResolution( |
102 |
415 |
assume(parent), collectButHoldout(parent, holdout), true); |
103 |
|
} |
104 |
|
|
105 |
138076 |
std::shared_ptr<ProofNode> ProofCircuitPropagator::Not(bool negate, Node parent) |
106 |
|
{ |
107 |
138076 |
if (disabled()) |
108 |
|
{ |
109 |
112326 |
return nullptr; |
110 |
|
} |
111 |
25750 |
return mkNot(assume(negate ? Node(parent[0]) : parent)); |
112 |
|
} |
113 |
|
|
114 |
56 |
std::shared_ptr<ProofNode> ProofCircuitPropagator::impliesXFromY(Node parent) |
115 |
|
{ |
116 |
56 |
if (disabled()) |
117 |
|
{ |
118 |
29 |
return nullptr; |
119 |
|
} |
120 |
108 |
return mkNot(mkResolution( |
121 |
81 |
mkProof(PfRule::IMPLIES_ELIM, {assume(parent)}), parent[1], true)); |
122 |
|
} |
123 |
|
|
124 |
674 |
std::shared_ptr<ProofNode> ProofCircuitPropagator::impliesYFromX(Node parent) |
125 |
|
{ |
126 |
674 |
if (disabled()) |
127 |
|
{ |
128 |
449 |
return nullptr; |
129 |
|
} |
130 |
|
return mkResolution( |
131 |
225 |
mkProof(PfRule::IMPLIES_ELIM, {assume(parent)}), parent[0], false); |
132 |
|
} |
133 |
|
|
134 |
116 |
std::shared_ptr<ProofNode> ProofCircuitPropagator::eqXFromY(bool y, Node parent) |
135 |
|
{ |
136 |
116 |
if (disabled()) |
137 |
|
{ |
138 |
53 |
return nullptr; |
139 |
|
} |
140 |
63 |
if (y) |
141 |
|
{ |
142 |
|
return mkProof( |
143 |
|
PfRule::EQ_RESOLVE, |
144 |
52 |
{assume(parent[1]), mkProof(PfRule::SYMM, {assume(parent)})}); |
145 |
|
} |
146 |
44 |
return mkNot(mkResolution( |
147 |
33 |
mkProof(PfRule::EQUIV_ELIM1, {assume(parent)}), parent[1], true)); |
148 |
|
} |
149 |
|
|
150 |
766 |
std::shared_ptr<ProofNode> ProofCircuitPropagator::eqYFromX(bool x, Node parent) |
151 |
|
{ |
152 |
766 |
if (disabled()) |
153 |
|
{ |
154 |
97 |
return nullptr; |
155 |
|
} |
156 |
669 |
if (x) |
157 |
|
{ |
158 |
609 |
return mkProof(PfRule::EQ_RESOLVE, {assume(parent[0]), assume(parent)}); |
159 |
|
} |
160 |
240 |
return mkNot(mkResolution( |
161 |
180 |
mkProof(PfRule::EQUIV_ELIM2, {assume(parent)}), parent[0], true)); |
162 |
|
} |
163 |
|
|
164 |
3 |
std::shared_ptr<ProofNode> ProofCircuitPropagator::neqXFromY(bool y, |
165 |
|
Node parent) |
166 |
|
{ |
167 |
3 |
if (disabled()) |
168 |
|
{ |
169 |
2 |
return nullptr; |
170 |
|
} |
171 |
|
return mkResolution( |
172 |
5 |
mkProof(y ? PfRule::NOT_EQUIV_ELIM2 : PfRule::NOT_EQUIV_ELIM1, |
173 |
3 |
{assume(parent.notNode())}), |
174 |
|
parent[1], |
175 |
3 |
!y); |
176 |
|
} |
177 |
|
|
178 |
7 |
std::shared_ptr<ProofNode> ProofCircuitPropagator::neqYFromX(bool x, |
179 |
|
Node parent) |
180 |
|
{ |
181 |
7 |
if (disabled()) |
182 |
|
{ |
183 |
6 |
return nullptr; |
184 |
|
} |
185 |
|
return mkResolution( |
186 |
5 |
mkProof(x ? PfRule::NOT_EQUIV_ELIM2 : PfRule::NOT_EQUIV_ELIM1, |
187 |
3 |
{assume(parent.notNode())}), |
188 |
|
parent[0], |
189 |
3 |
!x); |
190 |
|
} |
191 |
|
|
192 |
24 |
std::shared_ptr<ProofNode> ProofCircuitPropagator::xorXFromY(bool negated, |
193 |
|
bool y, |
194 |
|
Node parent) |
195 |
|
{ |
196 |
24 |
if (disabled()) |
197 |
|
{ |
198 |
16 |
return nullptr; |
199 |
|
} |
200 |
8 |
if (y) |
201 |
|
{ |
202 |
32 |
return mkNot(mkResolution( |
203 |
40 |
mkProof(negated ? PfRule::NOT_XOR_ELIM1 : PfRule::XOR_ELIM2, |
204 |
24 |
{assume(negated ? parent.notNode() : Node(parent))}), |
205 |
|
parent[1], |
206 |
8 |
false)); |
207 |
|
} |
208 |
|
return mkResolution( |
209 |
|
mkProof(negated ? PfRule::NOT_XOR_ELIM2 : PfRule::XOR_ELIM1, |
210 |
|
{assume(negated ? parent.notNode() : Node(parent))}), |
211 |
|
parent[1], |
212 |
|
true); |
213 |
|
} |
214 |
|
|
215 |
25 |
std::shared_ptr<ProofNode> ProofCircuitPropagator::xorYFromX(bool negated, |
216 |
|
bool x, |
217 |
|
Node parent) |
218 |
|
{ |
219 |
25 |
if (disabled()) |
220 |
|
{ |
221 |
16 |
return nullptr; |
222 |
|
} |
223 |
9 |
if (x) |
224 |
|
{ |
225 |
|
return mkResolution( |
226 |
20 |
mkProof(negated ? PfRule::NOT_XOR_ELIM2 : PfRule::XOR_ELIM2, |
227 |
12 |
{assume(negated ? parent.notNode() : Node(parent))}), |
228 |
|
parent[0], |
229 |
12 |
false); |
230 |
|
} |
231 |
|
return mkNot( |
232 |
25 |
mkResolution(mkProof(negated ? PfRule::NOT_XOR_ELIM1 : PfRule::XOR_ELIM1, |
233 |
15 |
{assume(negated ? parent.notNode() : Node(parent))}), |
234 |
|
parent[0], |
235 |
5 |
true)); |
236 |
|
} |
237 |
|
|
238 |
61202 |
std::shared_ptr<ProofNode> ProofCircuitPropagator::mkProof( |
239 |
|
PfRule rule, |
240 |
|
const std::vector<std::shared_ptr<ProofNode>>& children, |
241 |
|
const std::vector<Node>& args) |
242 |
|
{ |
243 |
61202 |
if (Trace.isOn("circuit-prop")) |
244 |
|
{ |
245 |
|
std::stringstream ss; |
246 |
|
ss << "Constructing (" << rule; |
247 |
|
for (const auto& c : children) |
248 |
|
{ |
249 |
|
ss << " " << *c; |
250 |
|
} |
251 |
|
if (!args.empty()) |
252 |
|
{ |
253 |
|
ss << " :args"; |
254 |
|
for (const auto& a : args) |
255 |
|
{ |
256 |
|
ss << " " << a; |
257 |
|
} |
258 |
|
} |
259 |
|
ss << ")"; |
260 |
|
Trace("circuit-prop") << ss.str() << std::endl; |
261 |
|
} |
262 |
61202 |
return d_pnm->mkNode(rule, children, args); |
263 |
|
} |
264 |
|
|
265 |
3842 |
std::shared_ptr<ProofNode> ProofCircuitPropagator::mkCResolution( |
266 |
|
const std::shared_ptr<ProofNode>& clause, |
267 |
|
const std::vector<Node>& lits, |
268 |
|
const std::vector<bool>& polarity) |
269 |
|
{ |
270 |
3842 |
auto* nm = NodeManager::currentNM(); |
271 |
7684 |
std::vector<std::shared_ptr<ProofNode>> children = {clause}; |
272 |
7684 |
std::vector<Node> args; |
273 |
3842 |
Assert(lits.size() == polarity.size()); |
274 |
199106 |
for (std::size_t i = 0, n = lits.size(); i < n; ++i) |
275 |
|
{ |
276 |
195264 |
bool pol = polarity[i]; |
277 |
390528 |
Node lit = lits[i]; |
278 |
195264 |
if (polarity[i]) |
279 |
|
{ |
280 |
192158 |
if (lit.getKind() == Kind::NOT) |
281 |
|
{ |
282 |
173809 |
lit = lit[0]; |
283 |
173809 |
pol = !pol; |
284 |
173809 |
children.emplace_back(assume(lit)); |
285 |
|
} |
286 |
|
else |
287 |
|
{ |
288 |
18349 |
children.emplace_back(assume(lit.notNode())); |
289 |
|
} |
290 |
|
} |
291 |
|
else |
292 |
|
{ |
293 |
3106 |
children.emplace_back(assume(lit)); |
294 |
|
} |
295 |
195264 |
args.emplace_back(nm->mkConst(pol)); |
296 |
195264 |
args.emplace_back(lit); |
297 |
|
} |
298 |
7684 |
return mkProof(PfRule::CHAIN_RESOLUTION, children, args); |
299 |
|
} |
300 |
|
|
301 |
1986 |
std::shared_ptr<ProofNode> ProofCircuitPropagator::mkCResolution( |
302 |
|
const std::shared_ptr<ProofNode>& clause, |
303 |
|
const std::vector<Node>& lits, |
304 |
|
bool polarity) |
305 |
|
{ |
306 |
1986 |
return mkCResolution(clause, lits, std::vector<bool>(lits.size(), polarity)); |
307 |
|
} |
308 |
|
|
309 |
3230 |
std::shared_ptr<ProofNode> ProofCircuitPropagator::mkResolution( |
310 |
|
const std::shared_ptr<ProofNode>& clause, const Node& lit, bool polarity) |
311 |
|
{ |
312 |
3230 |
auto* nm = NodeManager::currentNM(); |
313 |
3230 |
if (polarity) |
314 |
|
{ |
315 |
1396 |
if (lit.getKind() == Kind::NOT) |
316 |
|
{ |
317 |
|
return mkProof(PfRule::RESOLUTION, |
318 |
|
{clause, assume(lit[0])}, |
319 |
323 |
{nm->mkConst(false), lit[0]}); |
320 |
|
} |
321 |
|
return mkProof(PfRule::RESOLUTION, |
322 |
2146 |
{clause, assume(lit.notNode())}, |
323 |
3219 |
{nm->mkConst(true), lit}); |
324 |
|
} |
325 |
|
return mkProof( |
326 |
1834 |
PfRule::RESOLUTION, {clause, assume(lit)}, {nm->mkConst(false), lit}); |
327 |
|
} |
328 |
|
|
329 |
29277 |
std::shared_ptr<ProofNode> ProofCircuitPropagator::mkNot( |
330 |
|
const std::shared_ptr<ProofNode>& n) |
331 |
|
{ |
332 |
58554 |
Node m = n->getResult(); |
333 |
29277 |
if (m.getKind() == Kind::NOT && m[0].getKind() == Kind::NOT) |
334 |
|
{ |
335 |
879 |
return mkProof(PfRule::NOT_NOT_ELIM, {n}); |
336 |
|
} |
337 |
28398 |
return n; |
338 |
|
} |
339 |
|
|
340 |
567347 |
ProofCircuitPropagatorBackward::ProofCircuitPropagatorBackward( |
341 |
567347 |
ProofNodeManager* pnm, TNode parent, bool parentAssignment) |
342 |
|
: ProofCircuitPropagator(pnm), |
343 |
|
d_parent(parent), |
344 |
567347 |
d_parentAssignment(parentAssignment) |
345 |
|
{ |
346 |
567347 |
} |
347 |
|
|
348 |
515323 |
std::shared_ptr<ProofNode> ProofCircuitPropagatorBackward::andTrue( |
349 |
|
TNode::iterator i) |
350 |
|
{ |
351 |
515323 |
if (disabled()) |
352 |
|
{ |
353 |
478210 |
return nullptr; |
354 |
|
} |
355 |
|
return mkProof( |
356 |
37113 |
PfRule::AND_ELIM, {assume(d_parent)}, {mkRat(i - d_parent.begin())}); |
357 |
|
} |
358 |
|
|
359 |
4296 |
std::shared_ptr<ProofNode> ProofCircuitPropagatorBackward::orFalse( |
360 |
|
TNode::iterator i) |
361 |
|
{ |
362 |
4296 |
if (disabled()) |
363 |
|
{ |
364 |
2953 |
return nullptr; |
365 |
|
} |
366 |
8058 |
return mkNot(mkProof(PfRule::NOT_OR_ELIM, |
367 |
2686 |
{assume(d_parent.notNode())}, |
368 |
5372 |
{mkRat(i - d_parent.begin())})); |
369 |
|
} |
370 |
|
|
371 |
14 |
std::shared_ptr<ProofNode> ProofCircuitPropagatorBackward::iteC(bool c) |
372 |
|
{ |
373 |
14 |
if (disabled()) |
374 |
|
{ |
375 |
8 |
return nullptr; |
376 |
|
} |
377 |
6 |
if (d_parentAssignment) |
378 |
|
{ |
379 |
|
return mkResolution( |
380 |
8 |
mkProof(c ? PfRule::ITE_ELIM1 : PfRule::ITE_ELIM2, {assume(d_parent)}), |
381 |
|
d_parent[0], |
382 |
12 |
!c); |
383 |
|
} |
384 |
10 |
return mkResolution(mkProof(c ? PfRule::NOT_ITE_ELIM1 : PfRule::NOT_ITE_ELIM2, |
385 |
6 |
{assume(d_parent.notNode())}), |
386 |
|
d_parent[0], |
387 |
6 |
!c); |
388 |
|
} |
389 |
|
|
390 |
|
std::shared_ptr<ProofNode> ProofCircuitPropagatorBackward::iteIsCase(unsigned c) |
391 |
|
{ |
392 |
|
if (disabled()) |
393 |
|
{ |
394 |
|
return nullptr; |
395 |
|
} |
396 |
|
if (d_parentAssignment) |
397 |
|
{ |
398 |
|
return mkResolution( |
399 |
|
mkProof(PfRule::ITE_ELIM2, {assume(d_parent)}), d_parent[c + 1], false); |
400 |
|
} |
401 |
|
return mkResolution( |
402 |
|
mkProof(PfRule::NOT_ITE_ELIM2, {assume(d_parent.notNode())}), |
403 |
|
d_parent[c + 1], |
404 |
|
false); |
405 |
|
} |
406 |
|
|
407 |
633 |
std::shared_ptr<ProofNode> ProofCircuitPropagatorBackward::impliesNegX() |
408 |
|
{ |
409 |
633 |
if (disabled()) |
410 |
|
{ |
411 |
396 |
return nullptr; |
412 |
|
} |
413 |
|
return mkNot( |
414 |
237 |
mkProof(PfRule::NOT_IMPLIES_ELIM1, {assume(d_parent.notNode())})); |
415 |
|
} |
416 |
|
|
417 |
633 |
std::shared_ptr<ProofNode> ProofCircuitPropagatorBackward::impliesNegY() |
418 |
|
{ |
419 |
633 |
if (disabled()) |
420 |
|
{ |
421 |
396 |
return nullptr; |
422 |
|
} |
423 |
|
return mkNot( |
424 |
237 |
mkProof(PfRule::NOT_IMPLIES_ELIM2, {assume(d_parent.notNode())})); |
425 |
|
} |
426 |
|
|
427 |
528232 |
ProofCircuitPropagatorForward::ProofCircuitPropagatorForward( |
428 |
528232 |
ProofNodeManager* pnm, Node child, bool childAssignment, Node parent) |
429 |
|
: ProofCircuitPropagator{pnm}, |
430 |
|
d_child(child), |
431 |
|
d_childAssignment(childAssignment), |
432 |
528232 |
d_parent(parent) |
433 |
|
{ |
434 |
528232 |
} |
435 |
|
|
436 |
17808 |
std::shared_ptr<ProofNode> ProofCircuitPropagatorForward::andAllTrue() |
437 |
|
{ |
438 |
17808 |
if (disabled()) |
439 |
|
{ |
440 |
10960 |
return nullptr; |
441 |
|
} |
442 |
13696 |
std::vector<std::shared_ptr<ProofNode>> children; |
443 |
8718765 |
for (const auto& child : d_parent) |
444 |
|
{ |
445 |
8711917 |
children.emplace_back(assume(child)); |
446 |
|
} |
447 |
6848 |
return mkProof(PfRule::AND_INTRO, children); |
448 |
|
} |
449 |
|
|
450 |
4149 |
std::shared_ptr<ProofNode> ProofCircuitPropagatorForward::andOneFalse() |
451 |
|
{ |
452 |
4149 |
if (disabled()) |
453 |
|
{ |
454 |
2888 |
return nullptr; |
455 |
|
} |
456 |
1261 |
auto it = std::find(d_parent.begin(), d_parent.end(), d_child); |
457 |
|
return mkResolution( |
458 |
5044 |
mkProof( |
459 |
2522 |
PfRule::CNF_AND_POS, {}, {d_parent, mkRat(it - d_parent.begin())}), |
460 |
|
d_child, |
461 |
2522 |
true); |
462 |
|
} |
463 |
|
|
464 |
243394 |
std::shared_ptr<ProofNode> ProofCircuitPropagatorForward::orOneTrue() |
465 |
|
{ |
466 |
243394 |
if (disabled()) |
467 |
|
{ |
468 |
242045 |
return nullptr; |
469 |
|
} |
470 |
1349 |
auto it = std::find(d_parent.begin(), d_parent.end(), d_child); |
471 |
4047 |
return mkNot(mkResolution( |
472 |
2698 |
mkProof(PfRule::CNF_OR_NEG, {}, {d_parent, mkRat(it - d_parent.begin())}), |
473 |
|
d_child, |
474 |
2698 |
false)); |
475 |
|
} |
476 |
|
|
477 |
4223 |
std::shared_ptr<ProofNode> ProofCircuitPropagatorForward::orFalse() |
478 |
|
{ |
479 |
4223 |
if (disabled()) |
480 |
|
{ |
481 |
2902 |
return nullptr; |
482 |
|
} |
483 |
2642 |
std::vector<Node> children(d_parent.begin(), d_parent.end()); |
484 |
|
return mkCResolution( |
485 |
1321 |
mkProof(PfRule::CNF_OR_POS, {}, {d_parent}), children, true); |
486 |
|
} |
487 |
|
|
488 |
17 |
std::shared_ptr<ProofNode> ProofCircuitPropagatorForward::iteEvalThen(bool x) |
489 |
|
{ |
490 |
17 |
if (disabled()) |
491 |
|
{ |
492 |
10 |
return nullptr; |
493 |
|
} |
494 |
|
return mkCResolution( |
495 |
14 |
mkProof(x ? PfRule::CNF_ITE_NEG1 : PfRule::CNF_ITE_POS1, {}, {d_parent}), |
496 |
|
{d_parent[0], d_parent[1]}, |
497 |
21 |
{false, !x}); |
498 |
|
} |
499 |
|
|
500 |
11 |
std::shared_ptr<ProofNode> ProofCircuitPropagatorForward::iteEvalElse(bool y) |
501 |
|
{ |
502 |
11 |
if (disabled()) |
503 |
|
{ |
504 |
7 |
return nullptr; |
505 |
|
} |
506 |
|
return mkCResolution( |
507 |
8 |
mkProof(y ? PfRule::CNF_ITE_NEG2 : PfRule::CNF_ITE_POS2, {}, {d_parent}), |
508 |
|
{d_parent[0], d_parent[2]}, |
509 |
12 |
{true, !y}); |
510 |
|
} |
511 |
|
|
512 |
1587 |
std::shared_ptr<ProofNode> ProofCircuitPropagatorForward::eqEval(bool x, bool y) |
513 |
|
{ |
514 |
1587 |
if (disabled()) |
515 |
|
{ |
516 |
213 |
return nullptr; |
517 |
|
} |
518 |
1374 |
if (x == y) |
519 |
|
{ |
520 |
|
return mkCResolution( |
521 |
4104 |
mkProof(x ? PfRule::CNF_EQUIV_NEG2 : PfRule::CNF_EQUIV_NEG1, |
522 |
|
{}, |
523 |
1368 |
{d_parent}), |
524 |
|
{d_parent[0], d_parent[1]}, |
525 |
4104 |
{!x, !y}); |
526 |
|
} |
527 |
|
return mkCResolution( |
528 |
18 |
mkProof( |
529 |
6 |
x ? PfRule::CNF_EQUIV_POS1 : PfRule::CNF_EQUIV_POS2, {}, {d_parent}), |
530 |
|
{d_parent[0], d_parent[1]}, |
531 |
18 |
{!x, !y}); |
532 |
|
} |
533 |
|
|
534 |
2022 |
std::shared_ptr<ProofNode> ProofCircuitPropagatorForward::impliesEval( |
535 |
|
bool premise, bool conclusion) |
536 |
|
{ |
537 |
2022 |
if (disabled()) |
538 |
|
{ |
539 |
1292 |
return nullptr; |
540 |
|
} |
541 |
730 |
if (!premise) |
542 |
|
{ |
543 |
|
return mkResolution( |
544 |
31 |
mkProof(PfRule::CNF_IMPLIES_NEG1, {}, {d_parent}), d_parent[0], true); |
545 |
|
} |
546 |
699 |
if (conclusion) |
547 |
|
{ |
548 |
|
return mkResolution( |
549 |
241 |
mkProof(PfRule::CNF_IMPLIES_NEG2, {}, {d_parent}), d_parent[1], false); |
550 |
|
} |
551 |
916 |
return mkCResolution(mkProof(PfRule::CNF_IMPLIES_POS, {}, {d_parent}), |
552 |
|
{d_parent[0], d_parent[1]}, |
553 |
1374 |
{false, true}); |
554 |
|
} |
555 |
|
|
556 |
37 |
std::shared_ptr<ProofNode> ProofCircuitPropagatorForward::xorEval(bool x, |
557 |
|
bool y) |
558 |
|
{ |
559 |
37 |
if (disabled()) |
560 |
|
{ |
561 |
24 |
return nullptr; |
562 |
|
} |
563 |
13 |
if (x && y) |
564 |
|
{ |
565 |
8 |
return mkCResolution(mkProof(PfRule::CNF_XOR_POS2, {}, {d_parent}), |
566 |
|
{d_parent[0], d_parent[1]}, |
567 |
12 |
{false, false}); |
568 |
|
} |
569 |
9 |
else if (x && !y) |
570 |
|
{ |
571 |
2 |
return mkCResolution(mkProof(PfRule::CNF_XOR_NEG1, {}, {d_parent}), |
572 |
|
{d_parent[0], d_parent[1]}, |
573 |
3 |
{false, true}); |
574 |
|
} |
575 |
8 |
else if (!x && y) |
576 |
|
{ |
577 |
12 |
return mkCResolution(mkProof(PfRule::CNF_XOR_NEG2, {}, {d_parent}), |
578 |
|
{d_parent[0], d_parent[1]}, |
579 |
18 |
{true, false}); |
580 |
|
} |
581 |
2 |
Assert(!x && !y); |
582 |
4 |
return mkCResolution(mkProof(PfRule::CNF_XOR_POS1, {}, {d_parent}), |
583 |
|
{d_parent[0], d_parent[1]}, |
584 |
6 |
{true, true}); |
585 |
|
} |
586 |
|
|
587 |
|
} // namespace booleans |
588 |
|
} // namespace theory |
589 |
28191 |
} // namespace cvc5 |