LCOV - code coverage report
Current view: top level - buildbot/coverage/build/src/prop - proof_cnf_stream.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 544 575 94.6 %
Date: 2026-08-18 10:33:07 Functions: 17 22 77.3 %
Branches: 225 450 50.0 %

           Branch data     Line data    Source code
       1                 :            : /******************************************************************************
       2                 :            :  * This file is part of the cvc5 project.
       3                 :            :  *
       4                 :            :  * Copyright (c) 2009-2026 by the authors listed in the file AUTHORS
       5                 :            :  * in the top-level source directory and their institutional affiliations.
       6                 :            :  * All rights reserved.  See the file COPYING in the top-level source
       7                 :            :  * directory for licensing information.
       8                 :            :  * ****************************************************************************
       9                 :            :  *
      10                 :            :  * Implementation of the proof-producing CNF stream.
      11                 :            :  */
      12                 :            : 
      13                 :            : #include "prop/proof_cnf_stream.h"
      14                 :            : 
      15                 :            : #include "options/smt_options.h"
      16                 :            : #include "prop/minisat/minisat.h"
      17                 :            : #include "theory/builtin/proof_checker.h"
      18                 :            : #include "util/rational.h"
      19                 :            : 
      20                 :            : namespace cvc5::internal {
      21                 :            : namespace prop {
      22                 :            : 
      23                 :      15206 : ProofCnfStream::ProofCnfStream(Env& env,
      24                 :            :                                CnfStream& cnfStream,
      25                 :      15206 :                                PropPfManager* ppm)
      26                 :            :     : EnvObj(env),
      27                 :      15206 :       d_cnfStream(cnfStream),
      28                 :      15206 :       d_ppm(ppm),
      29                 :      15206 :       d_proof(ppm->getCnfProof())
      30                 :            : {
      31                 :      15206 : }
      32                 :            : 
      33                 :     754855 : void ProofCnfStream::convertAndAssert(
      34                 :            :     TNode node, bool negated, bool removable, bool input, ProofGenerator* pg)
      35                 :            : {
      36                 :            :   // this method is re-entrant due to lemmas sent during preregistration of new
      37                 :            :   // lemmas, thus we must remember and revert d_input below.
      38                 :     754855 :   bool backupInput = d_input;
      39         [ +  - ]:    1509710 :   Trace("cnf") << "ProofCnfStream::convertAndAssert(" << node
      40         [ -  - ]:          0 :                << ", negated = " << (negated ? "true" : "false")
      41         [ -  - ]:          0 :                << ", removable = " << (removable ? "true" : "false")
      42         [ -  - ]:          0 :                << ", input = " << (input ? "true" : "false") << "), level "
      43                 :     754855 :                << userContext()->getLevel() << "\n";
      44                 :     754855 :   d_cnfStream.d_removable = removable;
      45                 :     754855 :   d_input = input;
      46         [ +  + ]:     754855 :   if (pg)
      47                 :            :   {
      48 [ +  - ][ -  + ]:     909562 :     Trace("cnf") << "ProofCnfStream::convertAndAssert: pg: " << pg->identify()
                 [ -  - ]
      49                 :     454781 :                  << "\n";
      50         [ +  + ]:     454781 :     Node toJustify = negated ? node.notNode() : static_cast<Node>(node);
      51                 :     454781 :     d_proof->addLazyStep(toJustify,
      52                 :            :                          pg,
      53                 :            :                          TrustId::NONE,
      54                 :            :                          true,
      55                 :            :                          "ProofCnfStream::convertAndAssert:cnf");
      56                 :     454781 :   }
      57                 :     754855 :   convertAndAssert(node, negated);
      58                 :     754855 :   d_input = backupInput;
      59                 :     754855 : }
      60                 :            : 
      61                 :     852246 : void ProofCnfStream::convertAndAssert(TNode node, bool negated)
      62                 :            : {
      63         [ +  - ]:    1704492 :   Trace("cnf") << "ProofCnfStream::convertAndAssert(" << node
      64         [ -  - ]:     852246 :                << ", negated = " << (negated ? "true" : "false") << ")\n"
      65                 :     852246 :                << push;
      66 [ +  + ][ +  + ]:     852246 :   switch (node.getKind())
         [ +  + ][ +  + ]
      67                 :            :   {
      68                 :     140585 :     case Kind::AND: convertAndAssertAnd(node, negated); break;
      69                 :     249666 :     case Kind::OR: convertAndAssertOr(node, negated); break;
      70                 :         42 :     case Kind::XOR: convertAndAssertXor(node, negated); break;
      71                 :     151209 :     case Kind::IMPLIES: convertAndAssertImplies(node, negated); break;
      72                 :      28245 :     case Kind::ITE: convertAndAssertIte(node, negated); break;
      73                 :      38792 :     case Kind::NOT:
      74                 :            :     {
      75                 :            :       // track double negation elimination
      76         [ +  + ]:      38792 :       if (negated)
      77                 :            :       {
      78                 :       4672 :         d_proof->addStep(
      79                 :            :             node[0], ProofRule::NOT_NOT_ELIM, {node.notNode()}, {});
      80         [ +  - ]:       4672 :         Trace("cnf")
      81                 :          0 :             << "ProofCnfStream::convertAndAssert: NOT_NOT_ELIM added norm "
      82 [ -  + ][ -  - ]:       2336 :             << node[0] << "\n";
      83                 :            :       }
      84                 :      38792 :       convertAndAssert(node[0], !negated);
      85                 :      38792 :       break;
      86                 :            :     }
      87                 :     109489 :     case Kind::EQUAL:
      88         [ +  + ]:     109489 :       if (node[0].getType().isBoolean())
      89                 :            :       {
      90                 :      33118 :         convertAndAssertIff(node, negated);
      91                 :      33118 :         break;
      92                 :            :       }
      93                 :            :       CVC5_FALLTHROUGH;
      94                 :            :     default:
      95                 :            :     {
      96                 :            :       // negate
      97         [ +  + ]:     210589 :       Node nnode = negated ? node.negate() : static_cast<Node>(node);
      98                 :            :       // Atoms
      99                 :     210589 :       SatLiteral lit = toCNF(node, negated);
     100 [ +  + ][ -  + ]:     210589 :       if (negated && nnode != node.notNode())
         [ +  + ][ -  + ]
                 [ -  - ]
     101                 :            :       {
     102                 :            :         // track double negation elimination
     103                 :            :         //    (not (not n))
     104                 :            :         //   -------------- NOT_NOT_ELIM
     105                 :            :         //        n
     106                 :          0 :         d_proof->addStep(nnode, ProofRule::NOT_NOT_ELIM, {node.notNode()}, {});
     107         [ -  - ]:          0 :         Trace("cnf")
     108                 :          0 :             << "ProofCnfStream::convertAndAssert: NOT_NOT_ELIM added norm "
     109                 :          0 :             << nnode << "\n";
     110                 :            :       }
     111                 :            :       // note that we do not need to do the normalization here, just add it,
     112                 :            :       // since this is not a clause and double negation is tracked in a
     113                 :            :       // dedicated manner above
     114                 :     210589 :       d_ppm->normalizeAndRegister(nnode, d_input, false);
     115                 :     210589 :       d_cnfStream.assertClause(nnode, lit);
     116                 :     210589 :     }
     117                 :            :   }
     118         [ +  - ]:     852246 :   Trace("cnf") << pop;
     119                 :     852246 : }
     120                 :            : 
     121                 :     140585 : void ProofCnfStream::convertAndAssertAnd(TNode node, bool negated)
     122                 :            : {
     123         [ +  - ]:     281170 :   Trace("cnf") << "ProofCnfStream::convertAndAssertAnd(" << node
     124         [ -  - ]:     140585 :                << ", negated = " << (negated ? "true" : "false") << ")\n"
     125                 :     140585 :                << push;
     126 [ -  + ][ -  + ]:     140585 :   Assert(node.getKind() == Kind::AND);
                 [ -  - ]
     127         [ +  + ]:     140585 :   if (!negated)
     128                 :            :   {
     129                 :            :     // If the node is a conjunction, we handle each conjunct separately
     130                 :      21681 :     NodeManager* nm = nodeManager();
     131         [ +  + ]:      76521 :     for (unsigned i = 0, size = node.getNumChildren(); i < size; ++i)
     132                 :            :     {
     133                 :            :       // Create a proof step for each n_i
     134                 :      54840 :       Node iNode = nm->mkConstInt(i);
     135                 :     164520 :       d_proof->addStep(node[i], ProofRule::AND_ELIM, {node}, {iNode});
     136         [ +  - ]:     109680 :       Trace("cnf") << "ProofCnfStream::convertAndAssertAnd: AND_ELIM " << i
     137 [ -  + ][ -  - ]:      54840 :                    << " added norm " << node[i] << "\n";
     138                 :      54840 :       convertAndAssert(node[i], false);
     139                 :      54840 :     }
     140                 :            :   }
     141                 :            :   else
     142                 :            :   {
     143                 :            :     // If the node is a disjunction, we construct a clause and assert it
     144                 :     118904 :     unsigned i, size = node.getNumChildren();
     145                 :     118904 :     SatClause clause(size);
     146         [ +  + ]:    1195436 :     for (i = 0; i < size; ++i)
     147                 :            :     {
     148                 :    1076532 :       clause[i] = toCNF(node[i], true);
     149                 :            :     }
     150                 :            :     // register proof step
     151                 :     118904 :     std::vector<Node> disjuncts;
     152         [ +  + ]:    1195436 :     for (i = 0; i < size; ++i)
     153                 :            :     {
     154                 :    1076532 :       disjuncts.push_back(node[i].notNode());
     155                 :            :     }
     156                 :     118904 :     Node clauseNode = nodeManager()->mkNode(Kind::OR, disjuncts);
     157                 :     237808 :     d_proof->addStep(clauseNode, ProofRule::NOT_AND, {node.notNode()}, {});
     158         [ +  - ]:     237808 :     Trace("cnf") << "ProofCnfStream::convertAndAssertAnd: NOT_AND added "
     159                 :     118904 :                  << clauseNode << "\n";
     160                 :     118904 :     d_ppm->normalizeAndRegister(clauseNode, d_input);
     161                 :     118904 :     d_cnfStream.assertClause(node.negate(), clause);
     162                 :     118904 :   }
     163         [ +  - ]:     140585 :   Trace("cnf") << pop;
     164                 :     140585 : }
     165                 :            : 
     166                 :     249666 : void ProofCnfStream::convertAndAssertOr(TNode node, bool negated)
     167                 :            : {
     168         [ +  - ]:     499332 :   Trace("cnf") << "ProofCnfStream::convertAndAssertOr(" << node
     169         [ -  - ]:     249666 :                << ", negated = " << (negated ? "true" : "false") << ")\n"
     170                 :     249666 :                << push;
     171 [ -  + ][ -  + ]:     249666 :   Assert(node.getKind() == Kind::OR);
                 [ -  - ]
     172         [ +  + ]:     249666 :   if (!negated)
     173                 :            :   {
     174                 :            :     // If the node is a disjunction, we construct a clause and assert it
     175                 :     249422 :     unsigned size = node.getNumChildren();
     176                 :     249422 :     SatClause clause(size);
     177         [ +  + ]:    1061419 :     for (unsigned i = 0; i < size; ++i)
     178                 :            :     {
     179                 :     811997 :       clause[i] = toCNF(node[i], false);
     180                 :            :     }
     181                 :     249422 :     d_ppm->normalizeAndRegister(node, d_input);
     182                 :     249422 :     d_cnfStream.assertClause(node, clause);
     183                 :     249422 :   }
     184                 :            :   else
     185                 :            :   {
     186                 :            :     // If the node is a negated disjunction, we handle it as a conjunction of
     187                 :            :     // the negated arguments
     188                 :        244 :     NodeManager* nm = nodeManager();
     189         [ +  + ]:       3103 :     for (unsigned i = 0, size = node.getNumChildren(); i < size; ++i)
     190                 :            :     {
     191                 :            :       // Create a proof step for each (not n_i)
     192                 :       2859 :       Node iNode = nm->mkConstInt(i);
     193                 :            :       // Use notNode to ensure deterministic node ID assignments
     194                 :       2859 :       Node notNode = node.notNode();
     195                 :      14295 :       d_proof->addStep(
     196                 :       5718 :           node[i].notNode(), ProofRule::NOT_OR_ELIM, {notNode}, {iNode});
     197         [ +  - ]:       5718 :       Trace("cnf") << "ProofCnfStream::convertAndAssertOr: NOT_OR_ELIM " << i
     198                 :       2859 :                    << " added norm  " << node[i].notNode() << "\n";
     199                 :       2859 :       convertAndAssert(node[i], true);
     200                 :       2859 :     }
     201                 :            :   }
     202         [ +  - ]:     249666 :   Trace("cnf") << pop;
     203                 :     249666 : }
     204                 :            : 
     205                 :         42 : void ProofCnfStream::convertAndAssertXor(TNode node, bool negated)
     206                 :            : {
     207         [ +  - ]:         84 :   Trace("cnf") << "ProofCnfStream::convertAndAssertXor(" << node
     208         [ -  - ]:         42 :                << ", negated = " << (negated ? "true" : "false") << ")\n"
     209                 :         42 :                << push;
     210         [ +  + ]:         42 :   if (!negated)
     211                 :            :   {
     212                 :            :     // p XOR q
     213                 :         33 :     SatLiteral p = toCNF(node[0], false);
     214                 :         33 :     SatLiteral q = toCNF(node[1], false);
     215                 :         33 :     NodeManager* nm = nodeManager();
     216                 :            :     // Construct the clause (~p v ~q)
     217                 :         33 :     SatClause clause1(2);
     218                 :         33 :     clause1[0] = ~p;
     219                 :         33 :     clause1[1] = ~q;
     220                 :            :     Node clauseNode0 =
     221                 :        132 :         nm->mkNode(Kind::OR, {node[0].notNode(), node[1].notNode()});
     222                 :         66 :     d_proof->addStep(clauseNode0, ProofRule::XOR_ELIM2, {node}, {});
     223         [ +  - ]:         66 :     Trace("cnf") << "ProofCnfStream::convertAndAssertXor: XOR_ELIM2 added "
     224                 :         33 :                  << clauseNode0 << "\n";
     225                 :         33 :     d_ppm->normalizeAndRegister(clauseNode0, d_input);
     226                 :         33 :     d_cnfStream.assertClause(node, clause1);
     227                 :            :     // Construct the clause (p v q)
     228                 :         33 :     SatClause clause2(2);
     229                 :         33 :     clause2[0] = p;
     230                 :         33 :     clause2[1] = q;
     231                 :         66 :     Node clauseNode1 = nm->mkNode(Kind::OR, node[0], node[1]);
     232                 :         66 :     d_proof->addStep(clauseNode1, ProofRule::XOR_ELIM1, {node}, {});
     233         [ +  - ]:         66 :     Trace("cnf") << "ProofCnfStream::convertAndAssertXor: XOR_ELIM1 added "
     234                 :         33 :                  << clauseNode1 << "\n";
     235                 :         33 :     d_ppm->normalizeAndRegister(clauseNode1, d_input);
     236                 :         33 :     d_cnfStream.assertClause(node, clause2);
     237                 :         33 :   }
     238                 :            :   else
     239                 :            :   {
     240                 :            :     // ~(p XOR q) is the same as p <=> q
     241                 :          9 :     SatLiteral p = toCNF(node[0], false);
     242                 :          9 :     SatLiteral q = toCNF(node[1], false);
     243                 :          9 :     NodeManager* nm = nodeManager();
     244                 :            :     // Construct the clause ~p v q
     245                 :          9 :     SatClause clause1(2);
     246                 :          9 :     clause1[0] = ~p;
     247                 :          9 :     clause1[1] = q;
     248                 :         18 :     Node clauseNode0 = nm->mkNode(Kind::OR, node[0].notNode(), node[1]);
     249                 :         18 :     d_proof->addStep(
     250                 :            :         clauseNode0, ProofRule::NOT_XOR_ELIM2, {node.notNode()}, {});
     251         [ +  - ]:         18 :     Trace("cnf") << "ProofCnfStream::convertAndAssertXor: NOT_XOR_ELIM2 added "
     252                 :          9 :                  << clauseNode0 << "\n";
     253                 :          9 :     d_ppm->normalizeAndRegister(clauseNode0, d_input);
     254                 :          9 :     d_cnfStream.assertClause(node.negate(), clause1);
     255                 :            :     // Construct the clause ~q v p
     256                 :          9 :     SatClause clause2(2);
     257                 :          9 :     clause2[0] = p;
     258                 :          9 :     clause2[1] = ~q;
     259                 :         18 :     Node clauseNode1 = nm->mkNode(Kind::OR, node[0], node[1].notNode());
     260                 :         18 :     d_proof->addStep(
     261                 :            :         clauseNode1, ProofRule::NOT_XOR_ELIM1, {node.notNode()}, {});
     262         [ +  - ]:         18 :     Trace("cnf") << "ProofCnfStream::convertAndAssertXor: NOT_XOR_ELIM1 added "
     263                 :          9 :                  << clauseNode1 << "\n";
     264                 :          9 :     d_ppm->normalizeAndRegister(clauseNode1, d_input);
     265                 :          9 :     d_cnfStream.assertClause(node.negate(), clause2);
     266                 :          9 :   }
     267         [ +  - ]:         42 :   Trace("cnf") << pop;
     268                 :         42 : }
     269                 :            : 
     270                 :      33118 : void ProofCnfStream::convertAndAssertIff(TNode node, bool negated)
     271                 :            : {
     272         [ +  - ]:      66236 :   Trace("cnf") << "ProofCnfStream::convertAndAssertIff(" << node
     273         [ -  - ]:      33118 :                << ", negated = " << (negated ? "true" : "false") << ")\n"
     274                 :      33118 :                << push;
     275         [ +  + ]:      33118 :   if (!negated)
     276                 :            :   {
     277                 :            :     // p <=> q
     278         [ +  - ]:      32874 :     Trace("cnf") << push;
     279                 :      32874 :     SatLiteral p = toCNF(node[0], false);
     280                 :      32874 :     SatLiteral q = toCNF(node[1], false);
     281         [ +  - ]:      32874 :     Trace("cnf") << pop;
     282                 :      32874 :     NodeManager* nm = nodeManager();
     283                 :            :     // Construct the clauses ~p v q
     284                 :      32874 :     SatClause clause1(2);
     285                 :      32874 :     clause1[0] = ~p;
     286                 :      32874 :     clause1[1] = q;
     287                 :      65748 :     Node clauseNode0 = nm->mkNode(Kind::OR, node[0].notNode(), node[1]);
     288                 :      65748 :     d_proof->addStep(clauseNode0, ProofRule::EQUIV_ELIM1, {node}, {});
     289         [ +  - ]:      65748 :     Trace("cnf") << "ProofCnfStream::convertAndAssertIff: EQUIV_ELIM1 added "
     290                 :      32874 :                  << clauseNode0 << "\n";
     291                 :      32874 :     d_ppm->normalizeAndRegister(clauseNode0, d_input);
     292                 :      32874 :     d_cnfStream.assertClause(node, clause1);
     293                 :            :     // Construct the clauses ~q v p
     294                 :      32874 :     SatClause clause2(2);
     295                 :      32874 :     clause2[0] = p;
     296                 :      32874 :     clause2[1] = ~q;
     297                 :      65748 :     Node clauseNode1 = nm->mkNode(Kind::OR, node[0], node[1].notNode());
     298                 :      65748 :     d_proof->addStep(clauseNode1, ProofRule::EQUIV_ELIM2, {node}, {});
     299         [ +  - ]:      65748 :     Trace("cnf") << "ProofCnfStream::convertAndAssertIff: EQUIV_ELIM2 added "
     300                 :      32874 :                  << clauseNode1 << "\n";
     301                 :      32874 :     d_ppm->normalizeAndRegister(clauseNode1, d_input);
     302                 :      32874 :     d_cnfStream.assertClause(node, clause2);
     303                 :      32874 :   }
     304                 :            :   else
     305                 :            :   {
     306                 :            :     // ~(p <=> q) is the same as p XOR q
     307         [ +  - ]:        244 :     Trace("cnf") << push;
     308                 :        244 :     SatLiteral p = toCNF(node[0], false);
     309                 :        244 :     SatLiteral q = toCNF(node[1], false);
     310         [ +  - ]:        244 :     Trace("cnf") << pop;
     311                 :        244 :     NodeManager* nm = nodeManager();
     312                 :            :     // Construct the clauses ~p v ~q
     313                 :        244 :     SatClause clause1(2);
     314                 :        244 :     clause1[0] = ~p;
     315                 :        244 :     clause1[1] = ~q;
     316                 :            :     Node clauseNode0 =
     317                 :        976 :         nm->mkNode(Kind::OR, {node[0].notNode(), node[1].notNode()});
     318                 :        488 :     d_proof->addStep(
     319                 :            :         clauseNode0, ProofRule::NOT_EQUIV_ELIM2, {node.notNode()}, {});
     320         [ +  - ]:        488 :     Trace("cnf")
     321                 :          0 :         << "ProofCnfStream::convertAndAssertIff: NOT_EQUIV_ELIM2 added "
     322                 :        244 :         << clauseNode0 << "\n";
     323                 :        244 :     d_ppm->normalizeAndRegister(clauseNode0, d_input);
     324                 :        244 :     d_cnfStream.assertClause(node.negate(), clause1);
     325                 :            :     // Construct the clauses q v p
     326                 :        244 :     SatClause clause2(2);
     327                 :        244 :     clause2[0] = p;
     328                 :        244 :     clause2[1] = q;
     329                 :        488 :     Node clauseNode1 = nm->mkNode(Kind::OR, node[0], node[1]);
     330                 :        488 :     d_proof->addStep(
     331                 :            :         clauseNode1, ProofRule::NOT_EQUIV_ELIM1, {node.notNode()}, {});
     332         [ +  - ]:        488 :     Trace("cnf")
     333                 :          0 :         << "ProofCnfStream::convertAndAssertIff: NOT_EQUIV_ELIM1 added "
     334                 :        244 :         << clauseNode1 << "\n";
     335                 :        244 :     d_ppm->normalizeAndRegister(clauseNode1, d_input);
     336                 :        244 :     d_cnfStream.assertClause(node.negate(), clause2);
     337                 :        244 :   }
     338         [ +  - ]:      33118 :   Trace("cnf") << pop;
     339                 :      33118 : }
     340                 :            : 
     341                 :     151209 : void ProofCnfStream::convertAndAssertImplies(TNode node, bool negated)
     342                 :            : {
     343         [ +  - ]:     302418 :   Trace("cnf") << "ProofCnfStream::convertAndAssertImplies(" << node
     344         [ -  - ]:     151209 :                << ", negated = " << (negated ? "true" : "false") << ")\n"
     345                 :     151209 :                << push;
     346         [ +  + ]:     151209 :   if (!negated)
     347                 :            :   {
     348                 :            :     // ~p v q
     349                 :     150759 :     SatLiteral p = toCNF(node[0], false);
     350                 :     150759 :     SatLiteral q = toCNF(node[1], false);
     351                 :            :     // Construct the clause ~p || q
     352                 :     150759 :     SatClause clause(2);
     353                 :     150759 :     clause[0] = ~p;
     354                 :     150759 :     clause[1] = q;
     355                 :            :     Node clauseNode =
     356                 :     301518 :         nodeManager()->mkNode(Kind::OR, node[0].notNode(), node[1]);
     357                 :     301518 :     d_proof->addStep(clauseNode, ProofRule::IMPLIES_ELIM, {node}, {});
     358         [ +  - ]:     301518 :     Trace("cnf")
     359                 :          0 :         << "ProofCnfStream::convertAndAssertImplies: IMPLIES_ELIM added "
     360                 :     150759 :         << clauseNode << "\n";
     361                 :     150759 :     d_ppm->normalizeAndRegister(clauseNode, d_input);
     362                 :     150759 :     d_cnfStream.assertClause(node, clause);
     363                 :     150759 :   }
     364                 :            :   else
     365                 :            :   {
     366                 :            :     // ~(p => q) is the same as p ^ ~q
     367                 :            :     // process p
     368                 :        450 :     convertAndAssert(node[0], false);
     369                 :        900 :     d_proof->addStep(
     370                 :            :         node[0], ProofRule::NOT_IMPLIES_ELIM1, {node.notNode()}, {});
     371         [ +  - ]:        900 :     Trace("cnf")
     372                 :          0 :         << "ProofCnfStream::convertAndAssertImplies: NOT_IMPLIES_ELIM1 added "
     373 [ -  + ][ -  - ]:        450 :         << node[0] << "\n";
     374                 :            :     // process ~q
     375                 :        450 :     convertAndAssert(node[1], true);
     376                 :            :     // Use notNode to ensure deterministic node ID assignments
     377                 :        450 :     Node notNode = node.notNode();
     378                 :       1800 :     d_proof->addStep(
     379                 :        900 :         node[1].notNode(), ProofRule::NOT_IMPLIES_ELIM2, {notNode}, {});
     380         [ +  - ]:        900 :     Trace("cnf")
     381                 :          0 :         << "ProofCnfStream::convertAndAssertImplies: NOT_IMPLIES_ELIM2 added "
     382                 :        450 :         << node[1].notNode() << "\n";
     383                 :        450 :   }
     384         [ +  - ]:     151209 :   Trace("cnf") << pop;
     385                 :     151209 : }
     386                 :            : 
     387                 :      28245 : void ProofCnfStream::convertAndAssertIte(TNode node, bool negated)
     388                 :            : {
     389         [ +  - ]:      56490 :   Trace("cnf") << "ProofCnfStream::convertAndAssertIte(" << node
     390         [ -  - ]:      28245 :                << ", negated = " << (negated ? "true" : "false") << ")\n"
     391                 :      28245 :                << push;
     392                 :            :   // ITE(p, q, r)
     393                 :      28245 :   SatLiteral p = toCNF(node[0], false);
     394                 :      28245 :   SatLiteral q = toCNF(node[1], negated);
     395                 :      28245 :   SatLiteral r = toCNF(node[2], negated);
     396                 :      28245 :   NodeManager* nm = nodeManager();
     397                 :            :   // Construct the clauses:
     398                 :            :   // (~p v q) and (p v r)
     399                 :            :   //
     400                 :            :   // Note that below q and r can be used directly because whether they are
     401                 :            :   // negated has been push to the literal definitions above
     402         [ +  + ]:      28245 :   Node nnode = negated ? node.negate() : static_cast<Node>(node);
     403                 :            :   // (~p v q)
     404                 :      28245 :   SatClause clause1(2);
     405                 :      28245 :   clause1[0] = ~p;
     406                 :      28245 :   clause1[1] = q;
     407                 :            :   // redo the negation here to avoid silent double negation elimination
     408         [ +  + ]:      28245 :   if (!negated)
     409                 :            :   {
     410                 :      56408 :     Node clauseNode = nm->mkNode(Kind::OR, node[0].notNode(), node[1]);
     411                 :      56408 :     d_proof->addStep(clauseNode, ProofRule::ITE_ELIM1, {node}, {});
     412         [ +  - ]:      56408 :     Trace("cnf") << "ProofCnfStream::convertAndAssertIte: ITE_ELIM1 added "
     413                 :      28204 :                  << clauseNode << "\n";
     414                 :      28204 :     d_ppm->normalizeAndRegister(clauseNode, d_input);
     415                 :      28204 :   }
     416                 :            :   else
     417                 :            :   {
     418                 :            :     Node clauseNode =
     419                 :        164 :         nm->mkNode(Kind::OR, {node[0].notNode(), node[1].notNode()});
     420                 :         82 :     d_proof->addStep(
     421                 :            :         clauseNode, ProofRule::NOT_ITE_ELIM1, {node.notNode()}, {});
     422         [ +  - ]:         82 :     Trace("cnf") << "ProofCnfStream::convertAndAssertIte: NOT_ITE_ELIM1 added "
     423                 :         41 :                  << clauseNode << "\n";
     424                 :         41 :     d_ppm->normalizeAndRegister(clauseNode, d_input);
     425                 :         41 :   }
     426                 :      28245 :   d_cnfStream.assertClause(nnode, clause1);
     427                 :            :   // (p v r)
     428                 :      28245 :   SatClause clause2(2);
     429                 :      28245 :   clause2[0] = p;
     430                 :      28245 :   clause2[1] = r;
     431                 :            :   // redo the negation here to avoid silent double negation elimination
     432         [ +  + ]:      28245 :   if (!negated)
     433                 :            :   {
     434                 :      56408 :     Node clauseNode = nm->mkNode(Kind::OR, node[0], node[2]);
     435                 :      56408 :     d_proof->addStep(clauseNode, ProofRule::ITE_ELIM2, {node}, {});
     436         [ +  - ]:      56408 :     Trace("cnf") << "ProofCnfStream::convertAndAssertIte: ITE_ELIM2 added "
     437                 :      28204 :                  << clauseNode << "\n";
     438                 :      28204 :     d_ppm->normalizeAndRegister(clauseNode, d_input);
     439                 :      28204 :   }
     440                 :            :   else
     441                 :            :   {
     442                 :         82 :     Node clauseNode = nm->mkNode(Kind::OR, node[0], node[2].notNode());
     443                 :         82 :     d_proof->addStep(
     444                 :            :         clauseNode, ProofRule::NOT_ITE_ELIM2, {node.notNode()}, {});
     445         [ +  - ]:         82 :     Trace("cnf") << "ProofCnfStream::convertAndAssertIte: NOT_ITE_ELIM2 added "
     446                 :         41 :                  << clauseNode << "\n";
     447                 :         41 :     d_ppm->normalizeAndRegister(clauseNode, d_input);
     448                 :         41 :   }
     449                 :      28245 :   d_cnfStream.assertClause(nnode, clause2);
     450         [ +  - ]:      28245 :   Trace("cnf") << pop;
     451                 :      28245 : }
     452                 :            : 
     453                 :     348476 : void ProofCnfStream::ensureLiteral(TNode n)
     454                 :            : {
     455         [ +  - ]:     348476 :   Trace("cnf") << "ProofCnfStream::ensureLiteral(" << n << ")\n";
     456         [ +  + ]:     348476 :   if (d_cnfStream.hasLiteral(n))
     457                 :            :   {
     458                 :     257292 :     d_cnfStream.ensureMappingForLiteral(n);
     459                 :     257292 :     return;
     460                 :            :   }
     461                 :            :   // remove top level negation. We don't need to track this because it's a
     462                 :            :   // literal.
     463         [ +  + ]:      91184 :   n = n.getKind() == Kind::NOT ? n[0] : n;
     464 [ +  + ][ +  + ]:      91184 :   if (d_env.theoryOf(n) == theory::THEORY_BOOL && !n.isVar())
         [ +  - ][ +  + ]
                 [ -  - ]
     465                 :            :   {
     466                 :            :     // These are not removable
     467                 :      54325 :     d_cnfStream.d_removable = false;
     468                 :      54325 :     SatLiteral lit = toCNF(n, false);
     469                 :            :     // Store backward-mappings
     470                 :            :     // These may already exist
     471                 :      54325 :     d_cnfStream.d_literalToNodeMap.insert_safe(lit, n);
     472                 :      54325 :     d_cnfStream.d_literalToNodeMap.insert_safe(~lit, n.notNode());
     473                 :            :   }
     474                 :            :   else
     475                 :            :   {
     476                 :      36859 :     d_cnfStream.convertAtom(n);
     477                 :            :   }
     478                 :            : }
     479                 :            : 
     480                 :          0 : bool ProofCnfStream::hasLiteral(TNode n) const
     481                 :            : {
     482                 :          0 :   return d_cnfStream.hasLiteral(n);
     483                 :            : }
     484                 :            : 
     485                 :          0 : SatLiteral ProofCnfStream::getLiteral(TNode node)
     486                 :            : {
     487                 :          0 :   return d_cnfStream.getLiteral(node);
     488                 :            : }
     489                 :            : 
     490                 :          0 : void ProofCnfStream::getBooleanVariables(
     491                 :            :     std::vector<TNode>& outputVariables) const
     492                 :            : {
     493                 :          0 :   d_cnfStream.getBooleanVariables(outputVariables);
     494                 :          0 : }
     495                 :            : 
     496                 :    4881275 : SatLiteral ProofCnfStream::toCNF(TNode node, bool negated)
     497                 :            : {
     498         [ +  - ]:    9762550 :   Trace("cnf") << "toCNF(" << node
     499         [ -  - ]:    4881275 :                << ", negated = " << (negated ? "true" : "false") << ")\n";
     500                 :    4881275 :   SatLiteral lit;
     501                 :            :   // If the node has already has a literal, return it (maybe negated)
     502         [ +  + ]:    4881275 :   if (d_cnfStream.hasLiteral(node))
     503                 :            :   {
     504         [ +  - ]:    3275099 :     Trace("cnf") << "toCNF(): already translated\n";
     505                 :    3275099 :     lit = d_cnfStream.getLiteral(node);
     506                 :            :     // Return the (maybe negated) literal
     507         [ +  + ]:    3275099 :     return !negated ? lit : ~lit;
     508                 :            :   }
     509                 :            : 
     510                 :            :   // Handle each Boolean operator case
     511 [ +  + ][ +  + ]:    1606176 :   switch (node.getKind())
         [ +  + ][ +  + ]
     512                 :            :   {
     513                 :     269896 :     case Kind::AND: lit = handleAnd(node); break;
     514                 :     183658 :     case Kind::OR: lit = handleOr(node); break;
     515                 :      41267 :     case Kind::XOR: lit = handleXor(node); break;
     516                 :       5050 :     case Kind::IMPLIES: lit = handleImplies(node); break;
     517                 :      42587 :     case Kind::ITE: lit = handleIte(node); break;
     518                 :     155940 :     case Kind::NOT: lit = ~toCNF(node[0]); break;
     519                 :     465742 :     case Kind::EQUAL:
     520 [ +  + ][ -  - ]:     931484 :       lit = node[0].getType().isBoolean() ? handleIff(node)
     521 [ +  + ][ +  + ]:     465742 :                                           : d_cnfStream.convertAtom(node);
                 [ -  - ]
     522                 :     465742 :       break;
     523                 :     442036 :     default:
     524                 :            :     {
     525                 :     442036 :       lit = d_cnfStream.convertAtom(node);
     526                 :            :     }
     527                 :     442036 :     break;
     528                 :            :   }
     529                 :            :   // Return the (maybe negated) literal
     530         [ +  + ]:    1606176 :   return !negated ? lit : ~lit;
     531                 :            : }
     532                 :            : 
     533                 :     269896 : SatLiteral ProofCnfStream::handleAnd(TNode node)
     534                 :            : {
     535 [ -  + ][ -  + ]:     269896 :   Assert(!d_cnfStream.hasLiteral(node)) << "Atom already mapped!";
                 [ -  - ]
     536 [ -  + ][ -  + ]:     269896 :   Assert(node.getKind() == Kind::AND) << "Expecting an AND expression!";
                 [ -  - ]
     537 [ -  + ][ -  + ]:     269896 :   Assert(node.getNumChildren() > 1) << "Expecting more than 1 child!";
                 [ -  - ]
     538 [ -  + ][ -  + ]:     269896 :   Assert(!d_cnfStream.d_removable)
                 [ -  - ]
     539                 :          0 :       << "Removable clauses cannot contain Boolean structure";
     540         [ +  - ]:     269896 :   Trace("cnf") << "ProofCnfStream::handleAnd(" << node << ")\n";
     541                 :            :   // Number of children
     542                 :     269896 :   unsigned size = node.getNumChildren();
     543                 :            :   // Transform all the children first (remembering the negation)
     544                 :     269896 :   SatClause clause(size + 1);
     545         [ +  + ]:    1326216 :   for (unsigned i = 0; i < size; ++i)
     546                 :            :   {
     547         [ +  - ]:    1056320 :     Trace("cnf") << push;
     548                 :    1056320 :     clause[i] = ~toCNF(node[i]);
     549         [ +  - ]:    1056320 :     Trace("cnf") << pop;
     550                 :            :   }
     551                 :            :   // Create literal for the node
     552                 :     269896 :   SatLiteral lit = d_cnfStream.newLiteral(node);
     553                 :     269896 :   NodeManager* nm = nodeManager();
     554                 :            :   // lit -> (a_1 & a_2 & a_3 & ... & a_n)
     555                 :            :   // ~lit | (a_1 & a_2 & a_3 & ... & a_n)
     556                 :            :   // (~lit | a_1) & (~lit | a_2) & ... & (~lit | a_n)
     557         [ +  + ]:    1326216 :   for (unsigned i = 0; i < size; ++i)
     558                 :            :   {
     559         [ +  - ]:    1056320 :     Trace("cnf") << push;
     560                 :    2112640 :     Node clauseNode = nm->mkNode(Kind::OR, node.notNode(), node[i]);
     561                 :    1056320 :     Node iNode = nm->mkConstInt(i);
     562 [ +  + ][ -  - ]:    3168960 :     d_proof->addStep(clauseNode, ProofRule::CNF_AND_POS, {}, {node, iNode});
     563         [ +  - ]:    2112640 :     Trace("cnf") << "ProofCnfStream::handleAnd: CNF_AND_POS " << i << " added "
     564                 :    1056320 :                  << clauseNode << "\n";
     565                 :    1056320 :     d_ppm->normalizeAndRegister(clauseNode, d_input);
     566                 :    1056320 :     d_cnfStream.assertClause(node.negate(), ~lit, ~clause[i]);
     567         [ +  - ]:    1056320 :     Trace("cnf") << pop;
     568                 :    1056320 :   }
     569                 :            :   // lit <- (a_1 & a_2 & a_3 & ... a_n)
     570                 :            :   // lit | ~(a_1 & a_2 & a_3 & ... & a_n)
     571                 :            :   // lit | ~a_1 | ~a_2 | ~a_3 | ... | ~a_n
     572                 :     269896 :   clause[size] = lit;
     573                 :            :   // This needs to go last, as the clause might get modified by the SAT solver
     574         [ +  - ]:     269896 :   Trace("cnf") << push;
     575                 :     809688 :   std::vector<Node> disjuncts{node};
     576         [ +  + ]:    1326216 :   for (unsigned i = 0; i < size; ++i)
     577                 :            :   {
     578                 :    1056320 :     disjuncts.push_back(node[i].notNode());
     579                 :            :   }
     580                 :     269896 :   Node clauseNode = nm->mkNode(Kind::OR, disjuncts);
     581                 :     539792 :   d_proof->addStep(clauseNode, ProofRule::CNF_AND_NEG, {}, {node});
     582         [ +  - ]:     539792 :   Trace("cnf") << "ProofCnfStream::handleAnd: CNF_AND_NEG added " << clauseNode
     583                 :     269896 :                << "\n";
     584                 :     269896 :   d_ppm->normalizeAndRegister(clauseNode, d_input);
     585                 :     269896 :   d_cnfStream.assertClause(node, clause);
     586         [ +  - ]:     269896 :   Trace("cnf") << pop;
     587                 :     269896 :   return lit;
     588                 :     269896 : }
     589                 :            : 
     590                 :     183658 : SatLiteral ProofCnfStream::handleOr(TNode node)
     591                 :            : {
     592 [ -  + ][ -  + ]:     183658 :   Assert(!d_cnfStream.hasLiteral(node)) << "Atom already mapped!";
                 [ -  - ]
     593 [ -  + ][ -  + ]:     183658 :   Assert(node.getKind() == Kind::OR) << "Expecting an OR expression!";
                 [ -  - ]
     594 [ -  + ][ -  + ]:     183658 :   Assert(node.getNumChildren() > 1) << "Expecting more then 1 child!";
                 [ -  - ]
     595 [ -  + ][ -  + ]:     183658 :   Assert(!d_cnfStream.d_removable)
                 [ -  - ]
     596                 :          0 :       << "Removable clauses can not contain Boolean structure";
     597         [ +  - ]:     183658 :   Trace("cnf") << "ProofCnfStream::handleOr(" << node << ")\n";
     598                 :            :   // Number of children
     599                 :     183658 :   unsigned size = node.getNumChildren();
     600                 :            :   // Transform all the children first
     601                 :     183658 :   SatClause clause(size + 1);
     602         [ +  + ]:     766638 :   for (unsigned i = 0; i < size; ++i)
     603                 :            :   {
     604                 :     582980 :     clause[i] = toCNF(node[i]);
     605                 :            :   }
     606                 :            :   // Create literal for the node
     607                 :     183658 :   SatLiteral lit = d_cnfStream.newLiteral(node);
     608                 :     183658 :   NodeManager* nm = nodeManager();
     609                 :            :   // lit <- (a_1 | a_2 | a_3 | ... | a_n)
     610                 :            :   // lit | ~(a_1 | a_2 | a_3 | ... | a_n)
     611                 :            :   // (lit | ~a_1) & (lit | ~a_2) & (lit & ~a_3) & ... & (lit & ~a_n)
     612         [ +  + ]:     766638 :   for (unsigned i = 0; i < size; ++i)
     613                 :            :   {
     614                 :    1165960 :     Node clauseNode = nm->mkNode(Kind::OR, node, node[i].notNode());
     615                 :     582980 :     Node iNode = nm->mkConstInt(i);
     616 [ +  + ][ -  - ]:    1748940 :     d_proof->addStep(clauseNode, ProofRule::CNF_OR_NEG, {}, {node, iNode});
     617         [ +  - ]:    1165960 :     Trace("cnf") << "ProofCnfStream::handleOr: CNF_OR_NEG " << i << " added "
     618                 :     582980 :                  << clauseNode << "\n";
     619                 :     582980 :     d_ppm->normalizeAndRegister(clauseNode, d_input);
     620                 :     582980 :     d_cnfStream.assertClause(node, lit, ~clause[i]);
     621                 :     582980 :   }
     622                 :            :   // lit -> (a_1 | a_2 | a_3 | ... | a_n)
     623                 :            :   // ~lit | a_1 | a_2 | a_3 | ... | a_n
     624                 :     183658 :   clause[size] = ~lit;
     625                 :            :   // This needs to go last, as the clause might get modified by the SAT solver
     626                 :     550974 :   std::vector<Node> disjuncts{node.notNode()};
     627         [ +  + ]:     766638 :   for (unsigned i = 0; i < size; ++i)
     628                 :            :   {
     629                 :     582980 :     disjuncts.push_back(node[i]);
     630                 :            :   }
     631                 :     183658 :   Node clauseNode = nm->mkNode(Kind::OR, disjuncts);
     632                 :     367316 :   d_proof->addStep(clauseNode, ProofRule::CNF_OR_POS, {}, {node});
     633         [ +  - ]:     367316 :   Trace("cnf") << "ProofCnfStream::handleOr: CNF_OR_POS added " << clauseNode
     634                 :     183658 :                << "\n";
     635                 :     183658 :   d_ppm->normalizeAndRegister(clauseNode, d_input);
     636                 :     183658 :   d_cnfStream.assertClause(node.negate(), clause);
     637                 :     183658 :   return lit;
     638                 :     183658 : }
     639                 :            : 
     640                 :      41267 : SatLiteral ProofCnfStream::handleXor(TNode node)
     641                 :            : {
     642 [ -  + ][ -  + ]:      41267 :   Assert(!d_cnfStream.hasLiteral(node)) << "Atom already mapped!";
                 [ -  - ]
     643 [ -  + ][ -  + ]:      41267 :   Assert(node.getKind() == Kind::XOR) << "Expecting an XOR expression!";
                 [ -  - ]
     644 [ -  + ][ -  + ]:      41267 :   Assert(node.getNumChildren() == 2) << "Expecting exactly 2 children!";
                 [ -  - ]
     645 [ -  + ][ -  + ]:      41267 :   Assert(!d_cnfStream.d_removable)
                 [ -  - ]
     646                 :          0 :       << "Removable clauses can not contain Boolean structure";
     647         [ +  - ]:      41267 :   Trace("cnf") << "ProofCnfStream::handleXor(" << node << ")\n";
     648                 :      41267 :   SatLiteral a = toCNF(node[0]);
     649                 :      41267 :   SatLiteral b = toCNF(node[1]);
     650                 :      41267 :   SatLiteral lit = d_cnfStream.newLiteral(node);
     651                 :            :   Node clauseNode0 =
     652                 :      82534 :       nodeManager()->mkNode(Kind::OR, node.notNode(), node[0], node[1]);
     653                 :      82534 :   d_proof->addStep(clauseNode0, ProofRule::CNF_XOR_POS1, {}, {node});
     654         [ +  - ]:      82534 :   Trace("cnf") << "ProofCnfStream::handleXor: CNF_XOR_POS1 added "
     655                 :      41267 :                << clauseNode0 << "\n";
     656                 :      41267 :   d_ppm->normalizeAndRegister(clauseNode0, d_input);
     657                 :      41267 :   d_cnfStream.assertClause(node.negate(), a, b, ~lit);
     658                 :     206335 :   Node clauseNode1 = nodeManager()->mkNode(
     659                 :      82534 :       Kind::OR, {node.notNode(), node[0].notNode(), node[1].notNode()});
     660                 :      82534 :   d_proof->addStep(clauseNode1, ProofRule::CNF_XOR_POS2, {}, {node});
     661         [ +  - ]:      82534 :   Trace("cnf") << "ProofCnfStream::handleXor: CNF_XOR_POS2 added "
     662                 :      41267 :                << clauseNode1 << "\n";
     663                 :      41267 :   d_ppm->normalizeAndRegister(clauseNode1, d_input);
     664                 :      41267 :   d_cnfStream.assertClause(node.negate(), ~a, ~b, ~lit);
     665                 :            :   Node clauseNode2 =
     666                 :      82534 :       nodeManager()->mkNode(Kind::OR, node, node[0], node[1].notNode());
     667                 :      82534 :   d_proof->addStep(clauseNode2, ProofRule::CNF_XOR_NEG2, {}, {node});
     668         [ +  - ]:      82534 :   Trace("cnf") << "ProofCnfStream::handleXor: CNF_XOR_NEG2 added "
     669                 :      41267 :                << clauseNode2 << "\n";
     670                 :      41267 :   d_ppm->normalizeAndRegister(clauseNode2, d_input);
     671                 :      41267 :   d_cnfStream.assertClause(node, a, ~b, lit);
     672                 :            :   Node clauseNode3 =
     673                 :      82534 :       nodeManager()->mkNode(Kind::OR, node, node[0].notNode(), node[1]);
     674                 :      82534 :   d_proof->addStep(clauseNode3, ProofRule::CNF_XOR_NEG1, {}, {node});
     675         [ +  - ]:      82534 :   Trace("cnf") << "ProofCnfStream::handleXor: CNF_XOR_NEG1 added "
     676                 :      41267 :                << clauseNode3 << "\n";
     677                 :      41267 :   d_ppm->normalizeAndRegister(clauseNode3, d_input);
     678                 :      41267 :   d_cnfStream.assertClause(node, ~a, b, lit);
     679                 :      41267 :   return lit;
     680                 :      41267 : }
     681                 :            : 
     682                 :     129812 : SatLiteral ProofCnfStream::handleIff(TNode node)
     683                 :            : {
     684 [ -  + ][ -  + ]:     129812 :   Assert(!d_cnfStream.hasLiteral(node)) << "Atom already mapped!";
                 [ -  - ]
     685 [ -  + ][ -  + ]:     129812 :   Assert(node.getKind() == Kind::EQUAL) << "Expecting an EQUAL expression!";
                 [ -  - ]
     686 [ -  + ][ -  + ]:     129812 :   Assert(node.getNumChildren() == 2) << "Expecting exactly 2 children!";
                 [ -  - ]
     687         [ +  - ]:     129812 :   Trace("cnf") << "handleIff(" << node << ")\n";
     688                 :            :   // Convert the children to CNF
     689                 :     129812 :   SatLiteral a = toCNF(node[0]);
     690                 :     129812 :   SatLiteral b = toCNF(node[1]);
     691                 :            :   // Create literal for the node
     692                 :     129812 :   SatLiteral lit = d_cnfStream.newLiteral(node);
     693                 :     129812 :   NodeManager* nm = nodeManager();
     694                 :            :   // lit -> ((a-> b) & (b->a))
     695                 :            :   // ~lit | ((~a | b) & (~b | a))
     696                 :            :   // (~a | b | ~lit) & (~b | a | ~lit)
     697                 :            :   Node clauseNode0 =
     698                 :     649060 :       nm->mkNode(Kind::OR, {node.notNode(), node[0].notNode(), node[1]});
     699                 :     259624 :   d_proof->addStep(clauseNode0, ProofRule::CNF_EQUIV_POS1, {}, {node});
     700         [ +  - ]:     259624 :   Trace("cnf") << "ProofCnfStream::handleIff: CNF_EQUIV_POS1 added "
     701                 :     129812 :                << clauseNode0 << "\n";
     702                 :     129812 :   d_ppm->normalizeAndRegister(clauseNode0, d_input);
     703                 :     129812 :   d_cnfStream.assertClause(node.negate(), ~a, b, ~lit);
     704                 :            :   Node clauseNode1 =
     705                 :     649060 :       nm->mkNode(Kind::OR, {node.notNode(), node[0], node[1].notNode()});
     706                 :     259624 :   d_proof->addStep(clauseNode1, ProofRule::CNF_EQUIV_POS2, {}, {node});
     707         [ +  - ]:     259624 :   Trace("cnf") << "ProofCnfStream::handleIff: CNF_EQUIV_POS2 added "
     708                 :     129812 :                << clauseNode1 << "\n";
     709                 :     129812 :   d_ppm->normalizeAndRegister(clauseNode1, d_input);
     710                 :     129812 :   d_cnfStream.assertClause(node.negate(), a, ~b, ~lit);
     711                 :            :   // (a<->b) -> lit
     712                 :            :   // ~((a & b) | (~a & ~b)) | lit
     713                 :            :   // (~(a & b)) & (~(~a & ~b)) | lit
     714                 :            :   // ((~a | ~b) & (a | b)) | lit
     715                 :            :   // (~a | ~b | lit) & (a | b | lit)
     716                 :            :   Node clauseNode2 =
     717                 :     649060 :       nm->mkNode(Kind::OR, {node, node[0].notNode(), node[1].notNode()});
     718                 :     259624 :   d_proof->addStep(clauseNode2, ProofRule::CNF_EQUIV_NEG2, {}, {node});
     719         [ +  - ]:     259624 :   Trace("cnf") << "ProofCnfStream::handleIff: CNF_EQUIV_NEG2 added "
     720                 :     129812 :                << clauseNode2 << "\n";
     721                 :     129812 :   d_ppm->normalizeAndRegister(clauseNode2, d_input);
     722                 :     129812 :   d_cnfStream.assertClause(node, ~a, ~b, lit);
     723                 :     259624 :   Node clauseNode3 = nm->mkNode(Kind::OR, node, node[0], node[1]);
     724                 :     259624 :   d_proof->addStep(clauseNode3, ProofRule::CNF_EQUIV_NEG1, {}, {node});
     725         [ +  - ]:     259624 :   Trace("cnf") << "ProofCnfStream::handleIff: CNF_EQUIV_NEG1 added "
     726                 :     129812 :                << clauseNode3 << "\n";
     727                 :     129812 :   d_ppm->normalizeAndRegister(clauseNode3, d_input);
     728                 :     129812 :   d_cnfStream.assertClause(node, a, b, lit);
     729                 :     129812 :   return lit;
     730                 :     129812 : }
     731                 :            : 
     732                 :       5050 : SatLiteral ProofCnfStream::handleImplies(TNode node)
     733                 :            : {
     734 [ -  + ][ -  + ]:       5050 :   Assert(!d_cnfStream.hasLiteral(node)) << "Atom already mapped!";
                 [ -  - ]
     735 [ -  + ][ -  + ]:       5050 :   Assert(node.getKind() == Kind::IMPLIES) << "Expecting an IMPLIES expression!";
                 [ -  - ]
     736 [ -  + ][ -  + ]:       5050 :   Assert(node.getNumChildren() == 2) << "Expecting exactly 2 children!";
                 [ -  - ]
     737 [ -  + ][ -  + ]:       5050 :   Assert(!d_cnfStream.d_removable)
                 [ -  - ]
     738                 :          0 :       << "Removable clauses can not contain Boolean structure";
     739         [ +  - ]:       5050 :   Trace("cnf") << "ProofCnfStream::handleImplies(" << node << ")\n";
     740                 :            :   // Convert the children to cnf
     741                 :       5050 :   SatLiteral a = toCNF(node[0]);
     742                 :       5050 :   SatLiteral b = toCNF(node[1]);
     743                 :       5050 :   SatLiteral lit = d_cnfStream.newLiteral(node);
     744                 :       5050 :   NodeManager* nm = nodeManager();
     745                 :            :   // lit -> (a->b)
     746                 :            :   // ~lit | ~ a | b
     747                 :            :   Node clauseNode0 =
     748                 :      25250 :       nm->mkNode(Kind::OR, {node.notNode(), node[0].notNode(), node[1]});
     749                 :      10100 :   d_proof->addStep(clauseNode0, ProofRule::CNF_IMPLIES_POS, {}, {node});
     750         [ +  - ]:      10100 :   Trace("cnf") << "ProofCnfStream::handleImplies: CNF_IMPLIES_POS added "
     751                 :       5050 :                << clauseNode0 << "\n";
     752                 :       5050 :   d_ppm->normalizeAndRegister(clauseNode0, d_input);
     753                 :       5050 :   d_cnfStream.assertClause(node.negate(), ~lit, ~a, b);
     754                 :            :   // (a->b) -> lit
     755                 :            :   // ~(~a | b) | lit
     756                 :            :   // (a | l) & (~b | l)
     757                 :      10100 :   Node clauseNode1 = nm->mkNode(Kind::OR, node, node[0]);
     758                 :      10100 :   d_proof->addStep(clauseNode1, ProofRule::CNF_IMPLIES_NEG1, {}, {node});
     759         [ +  - ]:      10100 :   Trace("cnf") << "ProofCnfStream::handleImplies: CNF_IMPLIES_NEG1 added "
     760                 :       5050 :                << clauseNode1 << "\n";
     761                 :       5050 :   d_ppm->normalizeAndRegister(clauseNode1, d_input);
     762                 :       5050 :   d_cnfStream.assertClause(node, a, lit);
     763                 :      10100 :   Node clauseNode2 = nm->mkNode(Kind::OR, node, node[1].notNode());
     764                 :      10100 :   d_proof->addStep(clauseNode2, ProofRule::CNF_IMPLIES_NEG2, {}, {node});
     765         [ +  - ]:      10100 :   Trace("cnf") << "ProofCnfStream::handleImplies: CNF_IMPLIES_NEG2 added "
     766                 :       5050 :                << clauseNode2 << "\n";
     767                 :       5050 :   d_ppm->normalizeAndRegister(clauseNode2, d_input);
     768                 :       5050 :   d_cnfStream.assertClause(node, ~b, lit);
     769                 :       5050 :   return lit;
     770                 :       5050 : }
     771                 :            : 
     772                 :      42587 : SatLiteral ProofCnfStream::handleIte(TNode node)
     773                 :            : {
     774 [ -  + ][ -  + ]:      42587 :   Assert(!d_cnfStream.hasLiteral(node)) << "Atom already mapped!";
                 [ -  - ]
     775 [ -  + ][ -  + ]:      42587 :   Assert(node.getKind() == Kind::ITE);
                 [ -  - ]
     776 [ -  + ][ -  + ]:      42587 :   Assert(node.getNumChildren() == 3);
                 [ -  - ]
     777 [ -  + ][ -  + ]:      42587 :   Assert(!d_cnfStream.d_removable)
                 [ -  - ]
     778                 :          0 :       << "Removable clauses can not contain Boolean structure";
     779                 :      85174 :   Trace("cnf") << "handleIte(" << node[0] << " " << node[1] << " " << node[2]
     780                 :      42587 :                << ")\n";
     781                 :      42587 :   SatLiteral condLit = toCNF(node[0]);
     782                 :      42587 :   SatLiteral thenLit = toCNF(node[1]);
     783                 :      42587 :   SatLiteral elseLit = toCNF(node[2]);
     784                 :            :   // create literal to the node
     785                 :      42587 :   SatLiteral lit = d_cnfStream.newLiteral(node);
     786                 :      42587 :   NodeManager* nm = nodeManager();
     787                 :            :   // If ITE is true then one of the branches is true and the condition
     788                 :            :   // implies which one
     789                 :            :   // lit -> (ite b t e)
     790                 :            :   // lit -> (t | e) & (b -> t) & (!b -> e)
     791                 :            :   // lit -> (t | e) & (!b | t) & (b | e)
     792                 :            :   // (!lit | t | e) & (!lit | !b | t) & (!lit | b | e)
     793                 :      85174 :   Node clauseNode0 = nm->mkNode(Kind::OR, node.notNode(), node[1], node[2]);
     794                 :      85174 :   d_proof->addStep(clauseNode0, ProofRule::CNF_ITE_POS3, {}, {node});
     795         [ +  - ]:      85174 :   Trace("cnf") << "ProofCnfStream::handleIte: CNF_ITE_POS3 added "
     796                 :      42587 :                << clauseNode0 << "\n";
     797                 :      42587 :   d_ppm->normalizeAndRegister(clauseNode0, d_input);
     798                 :      42587 :   d_cnfStream.assertClause(node.negate(), ~lit, thenLit, elseLit);
     799                 :            :   Node clauseNode1 =
     800                 :     212935 :       nm->mkNode(Kind::OR, {node.notNode(), node[0].notNode(), node[1]});
     801                 :      85174 :   d_proof->addStep(clauseNode1, ProofRule::CNF_ITE_POS1, {}, {node});
     802         [ +  - ]:      85174 :   Trace("cnf") << "ProofCnfStream::handleIte: CNF_ITE_POS1 added "
     803                 :      42587 :                << clauseNode1 << "\n";
     804                 :      42587 :   d_ppm->normalizeAndRegister(clauseNode1, d_input);
     805                 :      42587 :   d_cnfStream.assertClause(node.negate(), ~lit, ~condLit, thenLit);
     806                 :      85174 :   Node clauseNode2 = nm->mkNode(Kind::OR, node.notNode(), node[0], node[2]);
     807                 :      85174 :   d_proof->addStep(clauseNode2, ProofRule::CNF_ITE_POS2, {}, {node});
     808         [ +  - ]:      85174 :   Trace("cnf") << "ProofCnfStream::handleIte: CNF_ITE_POS2 added "
     809                 :      42587 :                << clauseNode2 << "\n";
     810                 :      42587 :   d_ppm->normalizeAndRegister(clauseNode2, d_input);
     811                 :      42587 :   d_cnfStream.assertClause(node.negate(), ~lit, condLit, elseLit);
     812                 :            :   // If ITE is false then one of the branches is false and the condition
     813                 :            :   // implies which one
     814                 :            :   // !lit -> !(ite b t e)
     815                 :            :   // !lit -> (!t | !e) & (b -> !t) & (!b -> !e)
     816                 :            :   // !lit -> (!t | !e) & (!b | !t) & (b | !e)
     817                 :            :   // (lit | !t | !e) & (lit | !b | !t) & (lit | b | !e)
     818                 :            :   Node clauseNode3 =
     819                 :     212935 :       nm->mkNode(Kind::OR, {node, node[1].notNode(), node[2].notNode()});
     820                 :      85174 :   d_proof->addStep(clauseNode3, ProofRule::CNF_ITE_NEG3, {}, {node});
     821         [ +  - ]:      85174 :   Trace("cnf") << "ProofCnfStream::handleIte: CNF_ITE_NEG3 added "
     822                 :      42587 :                << clauseNode3 << "\n";
     823                 :      42587 :   d_ppm->normalizeAndRegister(clauseNode3, d_input);
     824                 :      42587 :   d_cnfStream.assertClause(node, lit, ~thenLit, ~elseLit);
     825                 :            :   Node clauseNode4 =
     826                 :     212935 :       nm->mkNode(Kind::OR, {node, node[0].notNode(), node[1].notNode()});
     827                 :      85174 :   d_proof->addStep(clauseNode4, ProofRule::CNF_ITE_NEG1, {}, {node});
     828         [ +  - ]:      85174 :   Trace("cnf") << "ProofCnfStream::handleIte: CNF_ITE_NEG1 added "
     829                 :      42587 :                << clauseNode4 << "\n";
     830                 :      42587 :   d_ppm->normalizeAndRegister(clauseNode4, d_input);
     831                 :      42587 :   d_cnfStream.assertClause(node, lit, ~condLit, ~thenLit);
     832                 :      85174 :   Node clauseNode5 = nm->mkNode(Kind::OR, node, node[0], node[2].notNode());
     833                 :      85174 :   d_proof->addStep(clauseNode5, ProofRule::CNF_ITE_NEG2, {}, {node});
     834         [ +  - ]:      85174 :   Trace("cnf") << "ProofCnfStream::handleIte: CNF_ITE_NEG2 added "
     835                 :      42587 :                << clauseNode5 << "\n";
     836                 :      42587 :   d_ppm->normalizeAndRegister(clauseNode5, d_input);
     837                 :      42587 :   d_cnfStream.assertClause(node, lit, condLit, ~elseLit);
     838                 :      42587 :   return lit;
     839                 :      42587 : }
     840                 :            : 
     841                 :          0 : void ProofCnfStream::dumpDimacs(std::ostream& out,
     842                 :            :                                 const std::vector<Node>& clauses)
     843                 :            : {
     844                 :          0 :   d_cnfStream.dumpDimacs(out, clauses);
     845                 :          0 : }
     846                 :            : 
     847                 :          0 : void ProofCnfStream::dumpDimacs(std::ostream& out,
     848                 :            :                                 const std::vector<Node>& clauses,
     849                 :            :                                 const std::vector<Node>& auxUnits)
     850                 :            : {
     851                 :          0 :   d_cnfStream.dumpDimacs(out, clauses, auxUnits);
     852                 :          0 : }
     853                 :            : 
     854                 :            : }  // namespace prop
     855                 :            : }  // namespace cvc5::internal

Generated by: LCOV version 1.14