1 /********************* */
2 /*! \file cnf_stream.cpp
4 ** Top contributors (to current version):
5 ** Dejan Jovanovic, Liana Hadarean, Tim King
6 ** This file is part of the CVC4 project.
7 ** Copyright (c) 2009-2019 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.\endverbatim
12 ** \brief A CNF converter that takes in asserts and has the side effect
13 ** of given an equisatisfiable stream of assertions to PropEngine.
15 ** A CNF converter that takes in asserts and has the side effect
16 ** of given an equisatisfiable stream of assertions to PropEngine.
18 #include "prop/cnf_stream.h"
22 #include "base/check.h"
23 #include "base/output.h"
24 #include "expr/expr.h"
25 #include "expr/node.h"
26 #include "options/bv_options.h"
27 #include "proof/clause_id.h"
28 #include "proof/cnf_proof.h"
29 #include "proof/proof_manager.h"
30 #include "proof/sat_proof.h"
31 #include "prop/minisat/minisat.h"
32 #include "prop/prop_engine.h"
33 #include "prop/theory_proxy.h"
34 #include "smt/command.h"
35 #include "smt/smt_engine_scope.h"
36 #include "theory/theory.h"
37 #include "theory/theory_engine.h"
40 using namespace CVC4::kind
;
45 CnfStream::CnfStream(SatSolver
* satSolver
, Registrar
* registrar
,
46 context::Context
* context
, bool fullLitToNodeMap
,
48 : d_satSolver(satSolver
),
49 d_booleanVariables(context
),
50 d_nodeToLiteralMap(context
),
51 d_literalToNodeMap(context
),
52 d_fullLitToNodeMap(fullLitToNodeMap
),
53 d_convertAndAssertCounter(0),
54 d_registrar(registrar
),
60 TseitinCnfStream::TseitinCnfStream(SatSolver
* satSolver
,
62 context::Context
* context
,
64 bool fullLitToNodeMap
,
66 : CnfStream(satSolver
, registrar
, context
, fullLitToNodeMap
, name
),
70 void CnfStream::assertClause(TNode node
, SatClause
& c
) {
71 Debug("cnf") << "Inserting into stream " << c
<< " node = " << node
<< endl
;
72 if(Dump
.isOn("clauses")) {
74 Dump("clauses") << AssertCommand(Expr(getNode(c
[0]).toExpr()));
77 NodeBuilder
<> b(kind::OR
);
78 for(unsigned i
= 0; i
< c
.size(); ++i
) {
82 Dump("clauses") << AssertCommand(Expr(n
.toExpr()));
86 if (PROOF_ON() && d_cnfProof
)
88 d_cnfProof
->pushCurrentDefinition(node
);
91 ClauseId clause_id
= d_satSolver
->addClause(c
, d_removable
);
92 if (clause_id
== ClauseIdUndef
) return; // nothing to store (no clause was added)
94 if (PROOF_ON() && d_cnfProof
)
96 if (clause_id
!= ClauseIdError
)
98 d_cnfProof
->registerConvertedClause(clause_id
);
100 d_cnfProof
->popCurrentDefinition();
104 void CnfStream::assertClause(TNode node
, SatLiteral a
) {
107 assertClause(node
, clause
);
110 void CnfStream::assertClause(TNode node
, SatLiteral a
, SatLiteral b
) {
114 assertClause(node
, clause
);
117 void CnfStream::assertClause(TNode node
, SatLiteral a
, SatLiteral b
, SatLiteral c
) {
122 assertClause(node
, clause
);
125 bool CnfStream::hasLiteral(TNode n
) const {
126 NodeToLiteralMap::const_iterator find
= d_nodeToLiteralMap
.find(n
);
127 return find
!= d_nodeToLiteralMap
.end();
130 void TseitinCnfStream::ensureLiteral(TNode n
, bool noPreregistration
) {
131 // These are not removable and have no proof ID
134 Debug("cnf") << "ensureLiteral(" << n
<< ")" << endl
;
136 SatLiteral lit
= getLiteral(n
);
137 if(!d_literalToNodeMap
.contains(lit
)){
138 // Store backward-mappings
139 d_literalToNodeMap
.insert(lit
, n
);
140 d_literalToNodeMap
.insert(~lit
, n
.notNode());
145 AlwaysAssertArgument(
146 n
.getType().isBoolean(),
148 "CnfStream::ensureLiteral() requires a node of Boolean type.\n"
151 n
.toString().c_str(),
152 n
.getType().toString().c_str());
154 bool negated CVC4_UNUSED
= false;
157 if(n
.getKind() == kind::NOT
) {
162 if( theory::Theory::theoryOf(n
) == theory::THEORY_BOOL
&&
164 // If we were called with something other than a theory atom (or
165 // Boolean variable), we get a SatLiteral that is definitionally
168 // We are setting the current assertion to be null. This is because `toCNF`
169 // may add clauses to the SAT solver and we look up the current assertion
170 // in that case. Setting it to null ensures that the assertion stack is
171 // non-empty and that we are not associating a bogus assertion with the
172 // clause. This should be ok because we use the mapping back to assertions
173 // for clauses from input assertions only.
174 PROOF(if (d_cnfProof
) { d_cnfProof
->pushCurrentAssertion(Node::null()); });
176 lit
= toCNF(n
, false);
178 PROOF(if (d_cnfProof
) { d_cnfProof
->popCurrentAssertion(); });
180 // Store backward-mappings
181 // These may already exist
182 d_literalToNodeMap
.insert_safe(lit
, n
);
183 d_literalToNodeMap
.insert_safe(~lit
, n
.notNode());
185 // We have a theory atom or variable.
186 lit
= convertAtom(n
, noPreregistration
);
189 Assert(hasLiteral(n
) && getNode(lit
) == n
);
190 Debug("ensureLiteral") << "CnfStream::ensureLiteral(): out lit is " << lit
<< std::endl
;
193 SatLiteral
CnfStream::newLiteral(TNode node
, bool isTheoryAtom
, bool preRegister
, bool canEliminate
) {
194 Debug("cnf") << d_name
<< "::newLiteral(" << node
<< ", " << isTheoryAtom
<< ")" << endl
;
195 Assert(node
.getKind() != kind::NOT
);
197 // Get the literal for this node
199 if (!hasLiteral(node
)) {
200 // If no literal, we'll make one
201 if (node
.getKind() == kind::CONST_BOOLEAN
) {
202 if (node
.getConst
<bool>()) {
203 lit
= SatLiteral(d_satSolver
->trueVar());
205 lit
= SatLiteral(d_satSolver
->falseVar());
208 lit
= SatLiteral(d_satSolver
->newVar(isTheoryAtom
, preRegister
, canEliminate
));
210 d_nodeToLiteralMap
.insert(node
, lit
);
211 d_nodeToLiteralMap
.insert(node
.notNode(), ~lit
);
213 lit
= getLiteral(node
);
216 // If it's a theory literal, need to store it for back queries
217 if ( isTheoryAtom
|| d_fullLitToNodeMap
|| (Dump
.isOn("clauses")) ) {
218 d_literalToNodeMap
.insert_safe(lit
, node
);
219 d_literalToNodeMap
.insert_safe(~lit
, node
.notNode());
222 // If a theory literal, we pre-register it
224 // In case we are re-entered due to lemmas, save our state
225 bool backupRemovable
= d_removable
;
226 // Should be fine since cnfProof current assertion is stack based.
227 d_registrar
->preRegister(node
);
228 d_removable
= backupRemovable
;
231 // Here, you can have it
232 Debug("cnf") << "newLiteral(" << node
<< ") => " << lit
<< endl
;
237 TNode
CnfStream::getNode(const SatLiteral
& literal
) {
238 Debug("cnf") << "getNode(" << literal
<< ")" << endl
;
239 Debug("cnf") << "getNode(" << literal
<< ") => " << d_literalToNodeMap
[literal
] << endl
;
240 return d_literalToNodeMap
[literal
];
243 void CnfStream::getBooleanVariables(std::vector
<TNode
>& outputVariables
) const {
244 context::CDList
<TNode
>::const_iterator it
, it_end
;
245 for (it
= d_booleanVariables
.begin(); it
!= d_booleanVariables
.end(); ++ it
) {
246 outputVariables
.push_back(*it
);
250 void CnfStream::setProof(CnfProof
* proof
) {
251 Assert(d_cnfProof
== NULL
);
255 SatLiteral
CnfStream::convertAtom(TNode node
, bool noPreregistration
) {
256 Debug("cnf") << "convertAtom(" << node
<< ")" << endl
;
258 Assert(!hasLiteral(node
)) << "atom already mapped!";
260 bool theoryLiteral
= false;
261 bool canEliminate
= true;
262 bool preRegister
= false;
264 // Is this a variable add it to the list
265 if (node
.isVar() && node
.getKind()!=BOOLEAN_TERM_VARIABLE
) {
266 d_booleanVariables
.push_back(node
);
268 theoryLiteral
= true;
269 canEliminate
= false;
270 preRegister
= !noPreregistration
;
273 // Make a new literal (variables are not considered theory literals)
274 SatLiteral lit
= newLiteral(node
, theoryLiteral
, preRegister
, canEliminate
);
275 // Return the resulting literal
279 SatLiteral
CnfStream::getLiteral(TNode node
) {
280 Assert(!node
.isNull()) << "CnfStream: can't getLiteral() of null node";
282 Assert(d_nodeToLiteralMap
.contains(node
))
283 << "Literal not in the CNF Cache: " << node
<< "\n";
285 SatLiteral literal
= d_nodeToLiteralMap
[node
];
286 Debug("cnf") << "CnfStream::getLiteral(" << node
<< ") => " << literal
<< std::endl
;
290 SatLiteral
TseitinCnfStream::handleXor(TNode xorNode
) {
291 Assert(!hasLiteral(xorNode
)) << "Atom already mapped!";
292 Assert(xorNode
.getKind() == XOR
) << "Expecting an XOR expression!";
293 Assert(xorNode
.getNumChildren() == 2) << "Expecting exactly 2 children!";
294 Assert(!d_removable
) << "Removable clauses can not contain Boolean structure";
296 SatLiteral a
= toCNF(xorNode
[0]);
297 SatLiteral b
= toCNF(xorNode
[1]);
299 SatLiteral xorLit
= newLiteral(xorNode
);
301 assertClause(xorNode
.negate(), a
, b
, ~xorLit
);
302 assertClause(xorNode
.negate(), ~a
, ~b
, ~xorLit
);
303 assertClause(xorNode
, a
, ~b
, xorLit
);
304 assertClause(xorNode
, ~a
, b
, xorLit
);
309 SatLiteral
TseitinCnfStream::handleOr(TNode orNode
) {
310 Assert(!hasLiteral(orNode
)) << "Atom already mapped!";
311 Assert(orNode
.getKind() == OR
) << "Expecting an OR expression!";
312 Assert(orNode
.getNumChildren() > 1) << "Expecting more then 1 child!";
313 Assert(!d_removable
) << "Removable clauses can not contain Boolean structure";
315 // Number of children
316 unsigned n_children
= orNode
.getNumChildren();
318 // Transform all the children first
319 TNode::const_iterator node_it
= orNode
.begin();
320 TNode::const_iterator node_it_end
= orNode
.end();
321 SatClause
clause(n_children
+ 1);
322 for(int i
= 0; node_it
!= node_it_end
; ++node_it
, ++i
) {
323 clause
[i
] = toCNF(*node_it
);
326 // Get the literal for this node
327 SatLiteral orLit
= newLiteral(orNode
);
329 // lit <- (a_1 | a_2 | a_3 | ... | a_n)
330 // lit | ~(a_1 | a_2 | a_3 | ... | a_n)
331 // (lit | ~a_1) & (lit | ~a_2) & (lit & ~a_3) & ... & (lit & ~a_n)
332 for(unsigned i
= 0; i
< n_children
; ++i
) {
333 assertClause(orNode
, orLit
, ~clause
[i
]);
336 // lit -> (a_1 | a_2 | a_3 | ... | a_n)
337 // ~lit | a_1 | a_2 | a_3 | ... | a_n
338 clause
[n_children
] = ~orLit
;
339 // This needs to go last, as the clause might get modified by the SAT solver
340 assertClause(orNode
.negate(), clause
);
342 // Return the literal
346 SatLiteral
TseitinCnfStream::handleAnd(TNode andNode
) {
347 Assert(!hasLiteral(andNode
)) << "Atom already mapped!";
348 Assert(andNode
.getKind() == AND
) << "Expecting an AND expression!";
349 Assert(andNode
.getNumChildren() > 1) << "Expecting more than 1 child!";
350 Assert(!d_removable
) << "Removable clauses can not contain Boolean structure";
352 // Number of children
353 unsigned n_children
= andNode
.getNumChildren();
355 // Transform all the children first (remembering the negation)
356 TNode::const_iterator node_it
= andNode
.begin();
357 TNode::const_iterator node_it_end
= andNode
.end();
358 SatClause
clause(n_children
+ 1);
359 for(int i
= 0; node_it
!= node_it_end
; ++node_it
, ++i
) {
360 clause
[i
] = ~toCNF(*node_it
);
363 // Get the literal for this node
364 SatLiteral andLit
= newLiteral(andNode
);
366 // lit -> (a_1 & a_2 & a_3 & ... & a_n)
367 // ~lit | (a_1 & a_2 & a_3 & ... & a_n)
368 // (~lit | a_1) & (~lit | a_2) & ... & (~lit | a_n)
369 for(unsigned i
= 0; i
< n_children
; ++i
) {
370 assertClause(andNode
.negate(), ~andLit
, ~clause
[i
]);
373 // lit <- (a_1 & a_2 & a_3 & ... a_n)
374 // lit | ~(a_1 & a_2 & a_3 & ... & a_n)
375 // lit | ~a_1 | ~a_2 | ~a_3 | ... | ~a_n
376 clause
[n_children
] = andLit
;
377 // This needs to go last, as the clause might get modified by the SAT solver
378 assertClause(andNode
, clause
);
383 SatLiteral
TseitinCnfStream::handleImplies(TNode impliesNode
) {
384 Assert(!hasLiteral(impliesNode
)) << "Atom already mapped!";
385 Assert(impliesNode
.getKind() == IMPLIES
)
386 << "Expecting an IMPLIES expression!";
387 Assert(impliesNode
.getNumChildren() == 2) << "Expecting exactly 2 children!";
388 Assert(!d_removable
) << "Removable clauses can not contain Boolean structure";
390 // Convert the children to cnf
391 SatLiteral a
= toCNF(impliesNode
[0]);
392 SatLiteral b
= toCNF(impliesNode
[1]);
394 SatLiteral impliesLit
= newLiteral(impliesNode
);
398 assertClause(impliesNode
.negate(), ~impliesLit
, ~a
, b
);
402 // (a | l) & (~b | l)
403 assertClause(impliesNode
, a
, impliesLit
);
404 assertClause(impliesNode
, ~b
, impliesLit
);
410 SatLiteral
TseitinCnfStream::handleIff(TNode iffNode
) {
411 Assert(!hasLiteral(iffNode
)) << "Atom already mapped!";
412 Assert(iffNode
.getKind() == EQUAL
) << "Expecting an EQUAL expression!";
413 Assert(iffNode
.getNumChildren() == 2) << "Expecting exactly 2 children!";
415 Debug("cnf") << "handleIff(" << iffNode
<< ")" << endl
;
417 // Convert the children to CNF
418 SatLiteral a
= toCNF(iffNode
[0]);
419 SatLiteral b
= toCNF(iffNode
[1]);
421 // Get the now literal
422 SatLiteral iffLit
= newLiteral(iffNode
);
424 // lit -> ((a-> b) & (b->a))
425 // ~lit | ((~a | b) & (~b | a))
426 // (~a | b | ~lit) & (~b | a | ~lit)
427 assertClause(iffNode
.negate(), ~a
, b
, ~iffLit
);
428 assertClause(iffNode
.negate(), a
, ~b
, ~iffLit
);
431 // ~((a & b) | (~a & ~b)) | lit
432 // (~(a & b)) & (~(~a & ~b)) | lit
433 // ((~a | ~b) & (a | b)) | lit
434 // (~a | ~b | lit) & (a | b | lit)
435 assertClause(iffNode
, ~a
, ~b
, iffLit
);
436 assertClause(iffNode
, a
, b
, iffLit
);
442 SatLiteral
TseitinCnfStream::handleNot(TNode notNode
) {
443 Assert(!hasLiteral(notNode
)) << "Atom already mapped!";
444 Assert(notNode
.getKind() == NOT
) << "Expecting a NOT expression!";
445 Assert(notNode
.getNumChildren() == 1) << "Expecting exactly 1 child!";
447 SatLiteral notLit
= ~toCNF(notNode
[0]);
452 SatLiteral
TseitinCnfStream::handleIte(TNode iteNode
) {
453 Assert(iteNode
.getKind() == ITE
);
454 Assert(iteNode
.getNumChildren() == 3);
455 Assert(!d_removable
) << "Removable clauses can not contain Boolean structure";
457 Debug("cnf") << "handleIte(" << iteNode
[0] << " " << iteNode
[1] << " " << iteNode
[2] << ")" << endl
;
459 SatLiteral condLit
= toCNF(iteNode
[0]);
460 SatLiteral thenLit
= toCNF(iteNode
[1]);
461 SatLiteral elseLit
= toCNF(iteNode
[2]);
463 SatLiteral iteLit
= newLiteral(iteNode
);
465 // If ITE is true then one of the branches is true and the condition
467 // lit -> (ite b t e)
468 // lit -> (t | e) & (b -> t) & (!b -> e)
469 // lit -> (t | e) & (!b | t) & (b | e)
470 // (!lit | t | e) & (!lit | !b | t) & (!lit | b | e)
471 assertClause(iteNode
.negate(), ~iteLit
, thenLit
, elseLit
);
472 assertClause(iteNode
.negate(), ~iteLit
, ~condLit
, thenLit
);
473 assertClause(iteNode
.negate(), ~iteLit
, condLit
, elseLit
);
475 // If ITE is false then one of the branches is false and the condition
477 // !lit -> !(ite b t e)
478 // !lit -> (!t | !e) & (b -> !t) & (!b -> !e)
479 // !lit -> (!t | !e) & (!b | !t) & (b | !e)
480 // (lit | !t | !e) & (lit | !b | !t) & (lit | b | !e)
481 assertClause(iteNode
, iteLit
, ~thenLit
, ~elseLit
);
482 assertClause(iteNode
, iteLit
, ~condLit
, ~thenLit
);
483 assertClause(iteNode
, iteLit
, condLit
, ~elseLit
);
489 SatLiteral
TseitinCnfStream::toCNF(TNode node
, bool negated
) {
490 Debug("cnf") << "toCNF(" << node
<< ", negated = " << (negated
? "true" : "false") << ")" << endl
;
493 Node negatedNode
= node
.notNode();
495 // If the non-negated node has already been translated, get the translation
496 if(hasLiteral(node
)) {
497 Debug("cnf") << "toCNF(): already translated" << endl
;
498 nodeLit
= getLiteral(node
);
500 // Handle each Boolean operator case
501 switch(node
.getKind()) {
503 nodeLit
= handleNot(node
);
506 nodeLit
= handleXor(node
);
509 nodeLit
= handleIte(node
);
512 nodeLit
= handleImplies(node
);
515 nodeLit
= handleOr(node
);
518 nodeLit
= handleAnd(node
);
521 if(node
[0].getType().isBoolean()) {
522 nodeLit
= handleIff(node
);
524 nodeLit
= convertAtom(node
);
529 //TODO make sure this does not contain any boolean substructure
530 nodeLit
= convertAtom(node
);
532 //Node atomic = handleNonAtomicNode(node);
533 //return isCached(atomic) ? lookupInCache(atomic) : convertAtom(atomic);
539 // Return the appropriate (negated) literal
540 if (!negated
) return nodeLit
;
541 else return ~nodeLit
;
544 void TseitinCnfStream::convertAndAssertAnd(TNode node
, bool negated
) {
545 Assert(node
.getKind() == AND
);
547 // If the node is a conjunction, we handle each conjunct separately
548 for(TNode::const_iterator conjunct
= node
.begin(), node_end
= node
.end();
549 conjunct
!= node_end
; ++conjunct
) {
550 PROOF(if (d_cnfProof
) d_cnfProof
->setCnfDependence(*conjunct
, node
););
551 convertAndAssert(*conjunct
, false);
554 // If the node is a disjunction, we construct a clause and assert it
555 int nChildren
= node
.getNumChildren();
556 SatClause
clause(nChildren
);
557 TNode::const_iterator disjunct
= node
.begin();
558 for(int i
= 0; i
< nChildren
; ++ disjunct
, ++ i
) {
559 Assert(disjunct
!= node
.end());
560 clause
[i
] = toCNF(*disjunct
, true);
562 Assert(disjunct
== node
.end());
563 assertClause(node
.negate(), clause
);
567 void TseitinCnfStream::convertAndAssertOr(TNode node
, bool negated
) {
568 Assert(node
.getKind() == OR
);
570 // If the node is a disjunction, we construct a clause and assert it
571 int nChildren
= node
.getNumChildren();
572 SatClause
clause(nChildren
);
573 TNode::const_iterator disjunct
= node
.begin();
574 for(int i
= 0; i
< nChildren
; ++ disjunct
, ++ i
) {
575 Assert(disjunct
!= node
.end());
576 clause
[i
] = toCNF(*disjunct
, false);
578 Assert(disjunct
== node
.end());
579 assertClause(node
, clause
);
581 // If the node is a conjunction, we handle each conjunct separately
582 for(TNode::const_iterator conjunct
= node
.begin(), node_end
= node
.end();
583 conjunct
!= node_end
; ++conjunct
) {
584 PROOF(if (d_cnfProof
) d_cnfProof
->setCnfDependence((*conjunct
).negate(), node
.negate()););
585 convertAndAssert(*conjunct
, true);
590 void TseitinCnfStream::convertAndAssertXor(TNode node
, bool negated
) {
593 SatLiteral p
= toCNF(node
[0], false);
594 SatLiteral q
= toCNF(node
[1], false);
595 // Construct the clauses (p => !q) and (!q => p)
596 SatClause
clause1(2);
599 assertClause(node
, clause1
);
600 SatClause
clause2(2);
603 assertClause(node
, clause2
);
605 // !(p XOR q) is the same as p <=> q
606 SatLiteral p
= toCNF(node
[0], false);
607 SatLiteral q
= toCNF(node
[1], false);
608 // Construct the clauses (p => q) and (q => p)
609 SatClause
clause1(2);
612 assertClause(node
.negate(), clause1
);
613 SatClause
clause2(2);
616 assertClause(node
.negate(), clause2
);
620 void TseitinCnfStream::convertAndAssertIff(TNode node
, bool negated
) {
623 SatLiteral p
= toCNF(node
[0], false);
624 SatLiteral q
= toCNF(node
[1], false);
625 // Construct the clauses (p => q) and (q => p)
626 SatClause
clause1(2);
629 assertClause(node
, clause1
);
630 SatClause
clause2(2);
633 assertClause(node
, clause2
);
635 // !(p <=> q) is the same as p XOR q
636 SatLiteral p
= toCNF(node
[0], false);
637 SatLiteral q
= toCNF(node
[1], false);
638 // Construct the clauses (p => !q) and (!q => p)
639 SatClause
clause1(2);
642 assertClause(node
.negate(), clause1
);
643 SatClause
clause2(2);
646 assertClause(node
.negate(), clause2
);
650 void TseitinCnfStream::convertAndAssertImplies(TNode node
, bool negated
) {
653 SatLiteral p
= toCNF(node
[0], false);
654 SatLiteral q
= toCNF(node
[1], false);
655 // Construct the clause ~p || q
659 assertClause(node
, clause
);
660 } else {// Construct the
661 PROOF(if (d_cnfProof
) d_cnfProof
->setCnfDependence(node
[0], node
.negate()););
662 PROOF(if (d_cnfProof
) d_cnfProof
->setCnfDependence(node
[1].negate(), node
.negate()););
663 // !(p => q) is the same as (p && ~q)
664 convertAndAssert(node
[0], false);
665 convertAndAssert(node
[1], true);
669 void TseitinCnfStream::convertAndAssertIte(TNode node
, bool negated
) {
671 SatLiteral p
= toCNF(node
[0], false);
672 SatLiteral q
= toCNF(node
[1], negated
);
673 SatLiteral r
= toCNF(node
[2], negated
);
674 // Construct the clauses:
675 // (p => q) and (!p => r)
678 nnode
= node
.negate();
680 SatClause
clause1(2);
683 assertClause(nnode
, clause1
);
684 SatClause
clause2(2);
687 assertClause(nnode
, clause2
);
690 // At the top level we must ensure that all clauses that are asserted are
691 // not unit, except for the direct assertions. This allows us to remove the
692 // clauses later when they are not needed anymore (lemmas for example).
693 void TseitinCnfStream::convertAndAssert(TNode node
,
698 Debug("cnf") << "convertAndAssert(" << node
699 << ", removable = " << (removable
? "true" : "false")
700 << ", negated = " << (negated
? "true" : "false") << ")" << endl
;
701 d_removable
= removable
;
704 Node assertion
= negated
? node
.notNode() : (Node
)node
;
705 Node from_assertion
= negated
? from
.notNode() : (Node
) from
;
707 if (proof_id
!= RULE_INVALID
) {
708 d_cnfProof
->pushCurrentAssertion(from
.isNull() ? assertion
: from_assertion
);
709 d_cnfProof
->registerAssertion(from
.isNull() ? assertion
: from_assertion
, proof_id
);
712 d_cnfProof
->pushCurrentAssertion(assertion
);
713 d_cnfProof
->registerAssertion(assertion
, proof_id
);
717 convertAndAssert(node
, negated
);
720 d_cnfProof
->popCurrentAssertion();
724 void TseitinCnfStream::convertAndAssert(TNode node
, bool negated
) {
725 Debug("cnf") << "convertAndAssert(" << node
726 << ", negated = " << (negated
? "true" : "false") << ")" << endl
;
728 if (d_convertAndAssertCounter
% ResourceManager::getFrequencyCount() == 0) {
729 d_resourceManager
->spendResource(ResourceManager::Resource::CnfStep
);
730 d_convertAndAssertCounter
= 0;
732 ++d_convertAndAssertCounter
;
734 switch(node
.getKind()) {
736 convertAndAssertAnd(node
, negated
);
739 convertAndAssertOr(node
, negated
);
742 convertAndAssertXor(node
, negated
);
745 convertAndAssertImplies(node
, negated
);
748 convertAndAssertIte(node
, negated
);
751 convertAndAssert(node
[0], !negated
);
754 if( node
[0].getType().isBoolean() ){
755 convertAndAssertIff(node
, negated
);
763 nnode
= node
.negate();
766 assertClause(nnode
, toCNF(node
, negated
));
772 }/* CVC4::prop namespace */
773 }/* CVC4 namespace */