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: 600 635 94.5 %
Date: 2026-03-28 10:41:09 Functions: 17 22 77.3 %
Branches: 291 520 56.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                 :      20037 : ProofCnfStream::ProofCnfStream(Env& env,
      24                 :            :                                CnfStream& cnfStream,
      25                 :      20037 :                                PropPfManager* ppm)
      26                 :            :     : EnvObj(env),
      27                 :      20037 :       d_cnfStream(cnfStream),
      28                 :      20037 :       d_ppm(ppm),
      29                 :      20037 :       d_proof(ppm->getCnfProof())
      30                 :            : {
      31                 :      20037 : }
      32                 :            : 
      33                 :     766191 : void ProofCnfStream::convertAndAssert(TNode node,
      34                 :            :                                       bool negated,
      35                 :            :                                       bool removable,
      36                 :            :                                       bool input,
      37                 :            :                                       ProofGenerator* pg)
      38                 :            : {
      39                 :            :   // this method is re-entrant due to lemmas sent during preregistration of new
      40                 :            :   // lemmas, thus we must remember and revert d_input below.
      41                 :     766191 :   bool backupInput = d_input;
      42         [ +  - ]:    1532382 :   Trace("cnf") << "ProofCnfStream::convertAndAssert(" << node
      43         [ -  - ]:          0 :                << ", negated = " << (negated ? "true" : "false")
      44         [ -  - ]:          0 :                << ", removable = " << (removable ? "true" : "false")
      45         [ -  - ]:          0 :                << ", input = " << (input ? "true" : "false") << "), level "
      46                 :     766191 :                << userContext()->getLevel() << "\n";
      47                 :     766191 :   d_cnfStream.d_removable = removable;
      48                 :     766191 :   d_input = input;
      49         [ +  + ]:     766191 :   if (pg)
      50                 :            :   {
      51 [ +  - ][ -  + ]:     905844 :     Trace("cnf") << "ProofCnfStream::convertAndAssert: pg: " << pg->identify()
                 [ -  - ]
      52                 :     452922 :                  << "\n";
      53         [ +  + ]:     452922 :     Node toJustify = negated ? node.notNode() : static_cast<Node>(node);
      54                 :     452922 :     d_proof->addLazyStep(toJustify,
      55                 :            :                          pg,
      56                 :            :                          TrustId::NONE,
      57                 :            :                          true,
      58                 :            :                          "ProofCnfStream::convertAndAssert:cnf");
      59                 :     452922 :   }
      60                 :     766191 :   convertAndAssert(node, negated);
      61                 :     766191 :   d_input = backupInput;
      62                 :     766191 : }
      63                 :            : 
      64                 :     867262 : void ProofCnfStream::convertAndAssert(TNode node, bool negated)
      65                 :            : {
      66         [ +  - ]:    1734524 :   Trace("cnf") << "ProofCnfStream::convertAndAssert(" << node
      67         [ -  - ]:     867262 :                << ", negated = " << (negated ? "true" : "false") << ")\n"
      68                 :     867262 :                << push;
      69 [ +  + ][ +  + ]:     867262 :   switch (node.getKind())
         [ +  + ][ +  + ]
      70                 :            :   {
      71                 :     139534 :     case Kind::AND: convertAndAssertAnd(node, negated); break;
      72                 :     249872 :     case Kind::OR: convertAndAssertOr(node, negated); break;
      73                 :         42 :     case Kind::XOR: convertAndAssertXor(node, negated); break;
      74                 :     149722 :     case Kind::IMPLIES: convertAndAssertImplies(node, negated); break;
      75                 :      26636 :     case Kind::ITE: convertAndAssertIte(node, negated); break;
      76                 :      43413 :     case Kind::NOT:
      77                 :            :     {
      78                 :            :       // track double negation elimination
      79         [ +  + ]:      43413 :       if (negated)
      80                 :            :       {
      81                 :       4676 :         d_proof->addStep(
      82                 :            :             node[0], ProofRule::NOT_NOT_ELIM, {node.notNode()}, {});
      83         [ +  - ]:       4676 :         Trace("cnf")
      84                 :          0 :             << "ProofCnfStream::convertAndAssert: NOT_NOT_ELIM added norm "
      85 [ -  + ][ -  - ]:       2338 :             << node[0] << "\n";
      86                 :            :       }
      87                 :      43413 :       convertAndAssert(node[0], !negated);
      88                 :      43413 :       break;
      89                 :            :     }
      90                 :     106945 :     case Kind::EQUAL:
      91         [ +  + ]:     106945 :       if (node[0].getType().isBoolean())
      92                 :            :       {
      93                 :      33525 :         convertAndAssertIff(node, negated);
      94                 :      33525 :         break;
      95                 :            :       }
      96                 :            :       CVC5_FALLTHROUGH;
      97                 :            :     default:
      98                 :            :     {
      99                 :            :       // negate
     100         [ +  + ]:     224518 :       Node nnode = negated ? node.negate() : static_cast<Node>(node);
     101                 :            :       // Atoms
     102                 :     224518 :       SatLiteral lit = toCNF(node, negated);
     103                 :     224518 :       bool added = d_cnfStream.assertClause(nnode, lit);
     104 [ +  + ][ +  + ]:     224518 :       if (negated && added && nnode != node.notNode())
         [ -  + ][ +  + ]
         [ -  + ][ -  - ]
     105                 :            :       {
     106                 :            :         // track double negation elimination
     107                 :            :         //    (not (not n))
     108                 :            :         //   -------------- NOT_NOT_ELIM
     109                 :            :         //        n
     110                 :          0 :         d_proof->addStep(nnode, ProofRule::NOT_NOT_ELIM, {node.notNode()}, {});
     111         [ -  - ]:          0 :         Trace("cnf")
     112                 :          0 :             << "ProofCnfStream::convertAndAssert: NOT_NOT_ELIM added norm "
     113                 :          0 :             << nnode << "\n";
     114                 :            :       }
     115         [ +  + ]:     224518 :       if (added)
     116                 :            :       {
     117                 :            :         // note that we do not need to do the normalization here since this is
     118                 :            :         // not a clause and double negation is tracked in a dedicated manner
     119                 :            :         // above
     120                 :     140580 :         d_ppm->normalizeAndRegister(nnode, d_input, false);
     121                 :            :       }
     122                 :     224518 :     }
     123                 :            :   }
     124         [ +  - ]:     867262 :   Trace("cnf") << pop;
     125                 :     867262 : }
     126                 :            : 
     127                 :     139534 : void ProofCnfStream::convertAndAssertAnd(TNode node, bool negated)
     128                 :            : {
     129         [ +  - ]:     279068 :   Trace("cnf") << "ProofCnfStream::convertAndAssertAnd(" << node
     130         [ -  - ]:     139534 :                << ", negated = " << (negated ? "true" : "false") << ")\n"
     131                 :     139534 :                << push;
     132 [ -  + ][ -  + ]:     139534 :   Assert(node.getKind() == Kind::AND);
                 [ -  - ]
     133         [ +  + ]:     139534 :   if (!negated)
     134                 :            :   {
     135                 :            :     // If the node is a conjunction, we handle each conjunct separately
     136                 :      21322 :     NodeManager* nm = nodeManager();
     137         [ +  + ]:      75229 :     for (unsigned i = 0, size = node.getNumChildren(); i < size; ++i)
     138                 :            :     {
     139                 :            :       // Create a proof step for each n_i
     140                 :      53907 :       Node iNode = nm->mkConstInt(i);
     141                 :     161721 :       d_proof->addStep(node[i], ProofRule::AND_ELIM, {node}, {iNode});
     142         [ +  - ]:     107814 :       Trace("cnf") << "ProofCnfStream::convertAndAssertAnd: AND_ELIM " << i
     143 [ -  + ][ -  - ]:      53907 :                    << " added norm " << node[i] << "\n";
     144                 :      53907 :       convertAndAssert(node[i], false);
     145                 :      53907 :     }
     146                 :            :   }
     147                 :            :   else
     148                 :            :   {
     149                 :            :     // If the node is a disjunction, we construct a clause and assert it
     150                 :     118212 :     unsigned i, size = node.getNumChildren();
     151                 :     118212 :     SatClause clause(size);
     152         [ +  + ]:    1184202 :     for (i = 0; i < size; ++i)
     153                 :            :     {
     154                 :    1065990 :       clause[i] = toCNF(node[i], true);
     155                 :            :     }
     156                 :     118212 :     bool added = d_cnfStream.assertClause(node.negate(), clause);
     157                 :            :     // register proof step
     158         [ +  + ]:     118212 :     if (added)
     159                 :            :     {
     160                 :     118178 :       std::vector<Node> disjuncts;
     161         [ +  + ]:    1184043 :       for (i = 0; i < size; ++i)
     162                 :            :       {
     163                 :    1065865 :         disjuncts.push_back(node[i].notNode());
     164                 :            :       }
     165                 :     118178 :       Node clauseNode = nodeManager()->mkNode(Kind::OR, disjuncts);
     166                 :     236356 :       d_proof->addStep(clauseNode, ProofRule::NOT_AND, {node.notNode()}, {});
     167         [ +  - ]:     236356 :       Trace("cnf") << "ProofCnfStream::convertAndAssertAnd: NOT_AND added "
     168                 :     118178 :                    << clauseNode << "\n";
     169                 :     118178 :       d_ppm->normalizeAndRegister(clauseNode, d_input);
     170                 :     118178 :     }
     171                 :     118212 :   }
     172         [ +  - ]:     139534 :   Trace("cnf") << pop;
     173                 :     139534 : }
     174                 :            : 
     175                 :     249872 : void ProofCnfStream::convertAndAssertOr(TNode node, bool negated)
     176                 :            : {
     177         [ +  - ]:     499744 :   Trace("cnf") << "ProofCnfStream::convertAndAssertOr(" << node
     178         [ -  - ]:     249872 :                << ", negated = " << (negated ? "true" : "false") << ")\n"
     179                 :     249872 :                << push;
     180 [ -  + ][ -  + ]:     249872 :   Assert(node.getKind() == Kind::OR);
                 [ -  - ]
     181         [ +  + ]:     249872 :   if (!negated)
     182                 :            :   {
     183                 :            :     // If the node is a disjunction, we construct a clause and assert it
     184                 :     249636 :     unsigned size = node.getNumChildren();
     185                 :     249636 :     SatClause clause(size);
     186         [ +  + ]:    1065087 :     for (unsigned i = 0; i < size; ++i)
     187                 :            :     {
     188                 :     815451 :       clause[i] = toCNF(node[i], false);
     189                 :            :     }
     190                 :     249636 :     d_ppm->normalizeAndRegister(node, d_input);
     191                 :     249636 :     d_cnfStream.assertClause(node, clause);
     192                 :     249636 :   }
     193                 :            :   else
     194                 :            :   {
     195                 :            :     // If the node is a negated disjunction, we handle it as a conjunction of
     196                 :            :     // the negated arguments
     197                 :        236 :     NodeManager* nm = nodeManager();
     198         [ +  + ]:       3079 :     for (unsigned i = 0, size = node.getNumChildren(); i < size; ++i)
     199                 :            :     {
     200                 :            :       // Create a proof step for each (not n_i)
     201                 :       2843 :       Node iNode = nm->mkConstInt(i);
     202                 :      14215 :       d_proof->addStep(
     203                 :       5686 :           node[i].notNode(), ProofRule::NOT_OR_ELIM, {node.notNode()}, {iNode});
     204         [ +  - ]:       5686 :       Trace("cnf") << "ProofCnfStream::convertAndAssertOr: NOT_OR_ELIM " << i
     205                 :       2843 :                    << " added norm  " << node[i].notNode() << "\n";
     206                 :       2843 :       convertAndAssert(node[i], true);
     207                 :       2843 :     }
     208                 :            :   }
     209         [ +  - ]:     249872 :   Trace("cnf") << pop;
     210                 :     249872 : }
     211                 :            : 
     212                 :         42 : void ProofCnfStream::convertAndAssertXor(TNode node, bool negated)
     213                 :            : {
     214         [ +  - ]:         84 :   Trace("cnf") << "ProofCnfStream::convertAndAssertXor(" << node
     215         [ -  - ]:         42 :                << ", negated = " << (negated ? "true" : "false") << ")\n"
     216                 :         42 :                << push;
     217         [ +  + ]:         42 :   if (!negated)
     218                 :            :   {
     219                 :            :     // p XOR q
     220                 :         33 :     SatLiteral p = toCNF(node[0], false);
     221                 :         33 :     SatLiteral q = toCNF(node[1], false);
     222                 :            :     bool added;
     223                 :         33 :     NodeManager* nm = nodeManager();
     224                 :            :     // Construct the clause (~p v ~q)
     225                 :         33 :     SatClause clause1(2);
     226                 :         33 :     clause1[0] = ~p;
     227                 :         33 :     clause1[1] = ~q;
     228                 :         33 :     added = d_cnfStream.assertClause(node, clause1);
     229         [ +  - ]:         33 :     if (added)
     230                 :            :     {
     231                 :            :       Node clauseNode =
     232                 :         66 :           nm->mkNode(Kind::OR, node[0].notNode(), node[1].notNode());
     233                 :         66 :       d_proof->addStep(clauseNode, ProofRule::XOR_ELIM2, {node}, {});
     234         [ +  - ]:         66 :       Trace("cnf") << "ProofCnfStream::convertAndAssertXor: XOR_ELIM2 added "
     235                 :         33 :                    << clauseNode << "\n";
     236                 :         33 :       d_ppm->normalizeAndRegister(clauseNode, d_input);
     237                 :         33 :     }
     238                 :            :     // Construct the clause (p v q)
     239                 :         33 :     SatClause clause2(2);
     240                 :         33 :     clause2[0] = p;
     241                 :         33 :     clause2[1] = q;
     242                 :         33 :     added = d_cnfStream.assertClause(node, clause2);
     243         [ +  - ]:         33 :     if (added)
     244                 :            :     {
     245                 :         66 :       Node clauseNode = nm->mkNode(Kind::OR, node[0], node[1]);
     246                 :         66 :       d_proof->addStep(clauseNode, ProofRule::XOR_ELIM1, {node}, {});
     247         [ +  - ]:         66 :       Trace("cnf") << "ProofCnfStream::convertAndAssertXor: XOR_ELIM1 added "
     248                 :         33 :                    << clauseNode << "\n";
     249                 :         33 :       d_ppm->normalizeAndRegister(clauseNode, d_input);
     250                 :         33 :     }
     251                 :         33 :   }
     252                 :            :   else
     253                 :            :   {
     254                 :            :     // ~(p XOR q) is the same as p <=> q
     255                 :          9 :     SatLiteral p = toCNF(node[0], false);
     256                 :          9 :     SatLiteral q = toCNF(node[1], false);
     257                 :            :     bool added;
     258                 :          9 :     NodeManager* nm = nodeManager();
     259                 :            :     // Construct the clause ~p v q
     260                 :          9 :     SatClause clause1(2);
     261                 :          9 :     clause1[0] = ~p;
     262                 :          9 :     clause1[1] = q;
     263                 :          9 :     added = d_cnfStream.assertClause(node.negate(), clause1);
     264         [ +  - ]:          9 :     if (added)
     265                 :            :     {
     266                 :         18 :       Node clauseNode = nm->mkNode(Kind::OR, node[0].notNode(), node[1]);
     267                 :         18 :       d_proof->addStep(
     268                 :            :           clauseNode, ProofRule::NOT_XOR_ELIM2, {node.notNode()}, {});
     269         [ +  - ]:         18 :       Trace("cnf")
     270                 :          0 :           << "ProofCnfStream::convertAndAssertXor: NOT_XOR_ELIM2 added "
     271                 :          9 :           << clauseNode << "\n";
     272                 :          9 :       d_ppm->normalizeAndRegister(clauseNode, d_input);
     273                 :          9 :     }
     274                 :            :     // Construct the clause ~q v p
     275                 :          9 :     SatClause clause2(2);
     276                 :          9 :     clause2[0] = p;
     277                 :          9 :     clause2[1] = ~q;
     278                 :          9 :     added = d_cnfStream.assertClause(node.negate(), clause2);
     279         [ +  - ]:          9 :     if (added)
     280                 :            :     {
     281                 :         18 :       Node clauseNode = nm->mkNode(Kind::OR, node[0], node[1].notNode());
     282                 :         18 :       d_proof->addStep(
     283                 :            :           clauseNode, ProofRule::NOT_XOR_ELIM1, {node.notNode()}, {});
     284         [ +  - ]:         18 :       Trace("cnf")
     285                 :          0 :           << "ProofCnfStream::convertAndAssertXor: NOT_XOR_ELIM1 added "
     286                 :          9 :           << clauseNode << "\n";
     287                 :          9 :       d_ppm->normalizeAndRegister(clauseNode, d_input);
     288                 :          9 :     }
     289                 :          9 :   }
     290         [ +  - ]:         42 :   Trace("cnf") << pop;
     291                 :         42 : }
     292                 :            : 
     293                 :      33525 : void ProofCnfStream::convertAndAssertIff(TNode node, bool negated)
     294                 :            : {
     295         [ +  - ]:      67050 :   Trace("cnf") << "ProofCnfStream::convertAndAssertIff(" << node
     296         [ -  - ]:      33525 :                << ", negated = " << (negated ? "true" : "false") << ")\n"
     297                 :      33525 :                << push;
     298         [ +  + ]:      33525 :   if (!negated)
     299                 :            :   {
     300                 :            :     // p <=> q
     301         [ +  - ]:      33283 :     Trace("cnf") << push;
     302                 :      33283 :     SatLiteral p = toCNF(node[0], false);
     303                 :      33283 :     SatLiteral q = toCNF(node[1], false);
     304         [ +  - ]:      33283 :     Trace("cnf") << pop;
     305                 :            :     bool added;
     306                 :      33283 :     NodeManager* nm = nodeManager();
     307                 :            :     // Construct the clauses ~p v q
     308                 :      33283 :     SatClause clause1(2);
     309                 :      33283 :     clause1[0] = ~p;
     310                 :      33283 :     clause1[1] = q;
     311                 :      33283 :     added = d_cnfStream.assertClause(node, clause1);
     312         [ +  + ]:      33283 :     if (added)
     313                 :            :     {
     314                 :      61762 :       Node clauseNode = nm->mkNode(Kind::OR, node[0].notNode(), node[1]);
     315                 :      61762 :       d_proof->addStep(clauseNode, ProofRule::EQUIV_ELIM1, {node}, {});
     316         [ +  - ]:      61762 :       Trace("cnf") << "ProofCnfStream::convertAndAssertIff: EQUIV_ELIM1 added "
     317                 :      30881 :                    << clauseNode << "\n";
     318                 :      30881 :       d_ppm->normalizeAndRegister(clauseNode, d_input);
     319                 :      30881 :     }
     320                 :            :     // Construct the clauses ~q v p
     321                 :      33283 :     SatClause clause2(2);
     322                 :      33283 :     clause2[0] = p;
     323                 :      33283 :     clause2[1] = ~q;
     324                 :      33283 :     added = d_cnfStream.assertClause(node, clause2);
     325         [ +  + ]:      33283 :     if (added)
     326                 :            :     {
     327                 :      59164 :       Node clauseNode = nm->mkNode(Kind::OR, node[0], node[1].notNode());
     328                 :      59164 :       d_proof->addStep(clauseNode, ProofRule::EQUIV_ELIM2, {node}, {});
     329         [ +  - ]:      59164 :       Trace("cnf") << "ProofCnfStream::convertAndAssertIff: EQUIV_ELIM2 added "
     330                 :      29582 :                    << clauseNode << "\n";
     331                 :      29582 :       d_ppm->normalizeAndRegister(clauseNode, d_input);
     332                 :      29582 :     }
     333                 :      33283 :   }
     334                 :            :   else
     335                 :            :   {
     336                 :            :     // ~(p <=> q) is the same as p XOR q
     337         [ +  - ]:        242 :     Trace("cnf") << push;
     338                 :        242 :     SatLiteral p = toCNF(node[0], false);
     339                 :        242 :     SatLiteral q = toCNF(node[1], false);
     340         [ +  - ]:        242 :     Trace("cnf") << pop;
     341                 :            :     bool added;
     342                 :        242 :     NodeManager* nm = nodeManager();
     343                 :            :     // Construct the clauses ~p v ~q
     344                 :        242 :     SatClause clause1(2);
     345                 :        242 :     clause1[0] = ~p;
     346                 :        242 :     clause1[1] = ~q;
     347                 :        242 :     added = d_cnfStream.assertClause(node.negate(), clause1);
     348         [ +  + ]:        242 :     if (added)
     349                 :            :     {
     350                 :            :       Node clauseNode =
     351                 :        482 :           nm->mkNode(Kind::OR, node[0].notNode(), node[1].notNode());
     352                 :        482 :       d_proof->addStep(
     353                 :            :           clauseNode, ProofRule::NOT_EQUIV_ELIM2, {node.notNode()}, {});
     354         [ +  - ]:        482 :       Trace("cnf")
     355                 :          0 :           << "ProofCnfStream::convertAndAssertIff: NOT_EQUIV_ELIM2 added "
     356                 :        241 :           << clauseNode << "\n";
     357                 :        241 :       d_ppm->normalizeAndRegister(clauseNode, d_input);
     358                 :        241 :     }
     359                 :            :     // Construct the clauses q v p
     360                 :        242 :     SatClause clause2(2);
     361                 :        242 :     clause2[0] = p;
     362                 :        242 :     clause2[1] = q;
     363                 :        242 :     added = d_cnfStream.assertClause(node.negate(), clause2);
     364         [ +  + ]:        242 :     if (added)
     365                 :            :     {
     366                 :        466 :       Node clauseNode = nm->mkNode(Kind::OR, node[0], node[1]);
     367                 :        466 :       d_proof->addStep(
     368                 :            :           clauseNode, ProofRule::NOT_EQUIV_ELIM1, {node.notNode()}, {});
     369         [ +  - ]:        466 :       Trace("cnf")
     370                 :          0 :           << "ProofCnfStream::convertAndAssertIff: NOT_EQUIV_ELIM1 added "
     371                 :        233 :           << clauseNode << "\n";
     372                 :        233 :       d_ppm->normalizeAndRegister(clauseNode, d_input);
     373                 :        233 :     }
     374                 :        242 :   }
     375         [ +  - ]:      33525 :   Trace("cnf") << pop;
     376                 :      33525 : }
     377                 :            : 
     378                 :     149722 : void ProofCnfStream::convertAndAssertImplies(TNode node, bool negated)
     379                 :            : {
     380         [ +  - ]:     299444 :   Trace("cnf") << "ProofCnfStream::convertAndAssertImplies(" << node
     381         [ -  - ]:     149722 :                << ", negated = " << (negated ? "true" : "false") << ")\n"
     382                 :     149722 :                << push;
     383         [ +  + ]:     149722 :   if (!negated)
     384                 :            :   {
     385                 :            :     // ~p v q
     386                 :     149268 :     SatLiteral p = toCNF(node[0], false);
     387                 :     149268 :     SatLiteral q = toCNF(node[1], false);
     388                 :            :     // Construct the clause ~p || q
     389                 :     149268 :     SatClause clause(2);
     390                 :     149268 :     clause[0] = ~p;
     391                 :     149268 :     clause[1] = q;
     392                 :     149268 :     bool added = d_cnfStream.assertClause(node, clause);
     393         [ +  + ]:     149268 :     if (added)
     394                 :            :     {
     395                 :            :       Node clauseNode =
     396                 :     295638 :           nodeManager()->mkNode(Kind::OR, node[0].notNode(), node[1]);
     397                 :     295638 :       d_proof->addStep(clauseNode, ProofRule::IMPLIES_ELIM, {node}, {});
     398         [ +  - ]:     295638 :       Trace("cnf")
     399                 :          0 :           << "ProofCnfStream::convertAndAssertImplies: IMPLIES_ELIM added "
     400                 :     147819 :           << clauseNode << "\n";
     401                 :     147819 :       d_ppm->normalizeAndRegister(clauseNode, d_input);
     402                 :     147819 :     }
     403                 :     149268 :   }
     404                 :            :   else
     405                 :            :   {
     406                 :            :     // ~(p => q) is the same as p ^ ~q
     407                 :            :     // process p
     408                 :        454 :     convertAndAssert(node[0], false);
     409                 :        908 :     d_proof->addStep(
     410                 :            :         node[0], ProofRule::NOT_IMPLIES_ELIM1, {node.notNode()}, {});
     411         [ +  - ]:        908 :     Trace("cnf")
     412                 :          0 :         << "ProofCnfStream::convertAndAssertImplies: NOT_IMPLIES_ELIM1 added "
     413 [ -  + ][ -  - ]:        454 :         << node[0] << "\n";
     414                 :            :     // process ~q
     415                 :        454 :     convertAndAssert(node[1], true);
     416                 :       1816 :     d_proof->addStep(
     417                 :        908 :         node[1].notNode(), ProofRule::NOT_IMPLIES_ELIM2, {node.notNode()}, {});
     418         [ +  - ]:        908 :     Trace("cnf")
     419                 :          0 :         << "ProofCnfStream::convertAndAssertImplies: NOT_IMPLIES_ELIM2 added "
     420                 :        454 :         << node[1].notNode() << "\n";
     421                 :            :   }
     422         [ +  - ]:     149722 :   Trace("cnf") << pop;
     423                 :     149722 : }
     424                 :            : 
     425                 :      26636 : void ProofCnfStream::convertAndAssertIte(TNode node, bool negated)
     426                 :            : {
     427         [ +  - ]:      53272 :   Trace("cnf") << "ProofCnfStream::convertAndAssertIte(" << node
     428         [ -  - ]:      26636 :                << ", negated = " << (negated ? "true" : "false") << ")\n"
     429                 :      26636 :                << push;
     430                 :            :   // ITE(p, q, r)
     431                 :      26636 :   SatLiteral p = toCNF(node[0], false);
     432                 :      26636 :   SatLiteral q = toCNF(node[1], negated);
     433                 :      26636 :   SatLiteral r = toCNF(node[2], negated);
     434                 :            :   bool added;
     435                 :      26636 :   NodeManager* nm = nodeManager();
     436                 :            :   // Construct the clauses:
     437                 :            :   // (~p v q) and (p v r)
     438                 :            :   //
     439                 :            :   // Note that below q and r can be used directly because whether they are
     440                 :            :   // negated has been push to the literal definitions above
     441         [ +  + ]:      26636 :   Node nnode = negated ? node.negate() : static_cast<Node>(node);
     442                 :            :   // (~p v q)
     443                 :      26636 :   SatClause clause1(2);
     444                 :      26636 :   clause1[0] = ~p;
     445                 :      26636 :   clause1[1] = q;
     446                 :      26636 :   added = d_cnfStream.assertClause(nnode, clause1);
     447         [ +  + ]:      26636 :   if (added)
     448                 :            :   {
     449                 :            :     // redo the negation here to avoid silent double negation elimination
     450         [ +  + ]:      26136 :     if (!negated)
     451                 :            :     {
     452                 :      52236 :       Node clauseNode = nm->mkNode(Kind::OR, node[0].notNode(), node[1]);
     453                 :      52236 :       d_proof->addStep(clauseNode, ProofRule::ITE_ELIM1, {node}, {});
     454         [ +  - ]:      52236 :       Trace("cnf") << "ProofCnfStream::convertAndAssertIte: ITE_ELIM1 added "
     455                 :      26118 :                    << clauseNode << "\n";
     456                 :      26118 :       d_ppm->normalizeAndRegister(clauseNode, d_input);
     457                 :      26118 :     }
     458                 :            :     else
     459                 :            :     {
     460                 :            :       Node clauseNode =
     461                 :         36 :           nm->mkNode(Kind::OR, node[0].notNode(), node[1].notNode());
     462                 :         36 :       d_proof->addStep(
     463                 :            :           clauseNode, ProofRule::NOT_ITE_ELIM1, {node.notNode()}, {});
     464         [ +  - ]:         36 :       Trace("cnf")
     465                 :          0 :           << "ProofCnfStream::convertAndAssertIte: NOT_ITE_ELIM1 added "
     466                 :         18 :           << clauseNode << "\n";
     467                 :         18 :       d_ppm->normalizeAndRegister(clauseNode, d_input);
     468                 :         18 :     }
     469                 :            :   }
     470                 :            :   // (p v r)
     471                 :      26636 :   SatClause clause2(2);
     472                 :      26636 :   clause2[0] = p;
     473                 :      26636 :   clause2[1] = r;
     474                 :      26636 :   added = d_cnfStream.assertClause(nnode, clause2);
     475         [ +  + ]:      26636 :   if (added)
     476                 :            :   {
     477                 :            :     // redo the negation here to avoid silent double negation elimination
     478         [ +  + ]:      25946 :     if (!negated)
     479                 :            :     {
     480                 :      51856 :       Node clauseNode = nm->mkNode(Kind::OR, node[0], node[2]);
     481                 :      51856 :       d_proof->addStep(clauseNode, ProofRule::ITE_ELIM2, {node}, {});
     482         [ +  - ]:      51856 :       Trace("cnf") << "ProofCnfStream::convertAndAssertIte: ITE_ELIM2 added "
     483                 :      25928 :                    << clauseNode << "\n";
     484                 :      25928 :       d_ppm->normalizeAndRegister(clauseNode, d_input);
     485                 :      25928 :     }
     486                 :            :     else
     487                 :            :     {
     488                 :         36 :       Node clauseNode = nm->mkNode(Kind::OR, node[0], node[2].notNode());
     489                 :         36 :       d_proof->addStep(
     490                 :            :           clauseNode, ProofRule::NOT_ITE_ELIM2, {node.notNode()}, {});
     491         [ +  - ]:         36 :       Trace("cnf")
     492                 :          0 :           << "ProofCnfStream::convertAndAssertIte: NOT_ITE_ELIM2 added "
     493                 :         18 :           << clauseNode << "\n";
     494                 :         18 :       d_ppm->normalizeAndRegister(clauseNode, d_input);
     495                 :         18 :     }
     496                 :            :   }
     497         [ +  - ]:      26636 :   Trace("cnf") << pop;
     498                 :      26636 : }
     499                 :            : 
     500                 :     345649 : void ProofCnfStream::ensureLiteral(TNode n)
     501                 :            : {
     502         [ +  - ]:     345649 :   Trace("cnf") << "ProofCnfStream::ensureLiteral(" << n << ")\n";
     503         [ +  + ]:     345649 :   if (d_cnfStream.hasLiteral(n))
     504                 :            :   {
     505                 :     254129 :     d_cnfStream.ensureMappingForLiteral(n);
     506                 :     254129 :     return;
     507                 :            :   }
     508                 :            :   // remove top level negation. We don't need to track this because it's a
     509                 :            :   // literal.
     510         [ +  + ]:      91520 :   n = n.getKind() == Kind::NOT ? n[0] : n;
     511 [ +  + ][ +  + ]:      91520 :   if (d_env.theoryOf(n) == theory::THEORY_BOOL && !n.isVar())
         [ +  - ][ +  + ]
                 [ -  - ]
     512                 :            :   {
     513                 :            :     // These are not removable
     514                 :      54099 :     d_cnfStream.d_removable = false;
     515                 :      54099 :     SatLiteral lit = toCNF(n, false);
     516                 :            :     // Store backward-mappings
     517                 :            :     // These may already exist
     518                 :      54099 :     d_cnfStream.d_literalToNodeMap.insert_safe(lit, n);
     519                 :      54099 :     d_cnfStream.d_literalToNodeMap.insert_safe(~lit, n.notNode());
     520                 :            :   }
     521                 :            :   else
     522                 :            :   {
     523                 :      37421 :     d_cnfStream.convertAtom(n);
     524                 :            :   }
     525                 :            : }
     526                 :            : 
     527                 :          0 : bool ProofCnfStream::hasLiteral(TNode n) const
     528                 :            : {
     529                 :          0 :   return d_cnfStream.hasLiteral(n);
     530                 :            : }
     531                 :            : 
     532                 :          0 : SatLiteral ProofCnfStream::getLiteral(TNode node)
     533                 :            : {
     534                 :          0 :   return d_cnfStream.getLiteral(node);
     535                 :            : }
     536                 :            : 
     537                 :          0 : void ProofCnfStream::getBooleanVariables(
     538                 :            :     std::vector<TNode>& outputVariables) const
     539                 :            : {
     540                 :          0 :   d_cnfStream.getBooleanVariables(outputVariables);
     541                 :          0 : }
     542                 :            : 
     543                 :    4883465 : SatLiteral ProofCnfStream::toCNF(TNode node, bool negated)
     544                 :            : {
     545         [ +  - ]:    9766930 :   Trace("cnf") << "toCNF(" << node
     546         [ -  - ]:    4883465 :                << ", negated = " << (negated ? "true" : "false") << ")\n";
     547                 :    4883465 :   SatLiteral lit;
     548                 :            :   // If the node has already has a literal, return it (maybe negated)
     549         [ +  + ]:    4883465 :   if (d_cnfStream.hasLiteral(node))
     550                 :            :   {
     551         [ +  - ]:    3253187 :     Trace("cnf") << "toCNF(): already translated\n";
     552                 :    3253187 :     lit = d_cnfStream.getLiteral(node);
     553                 :            :     // Return the (maybe negated) literal
     554         [ +  + ]:    3253187 :     return !negated ? lit : ~lit;
     555                 :            :   }
     556                 :            : 
     557                 :            :   // Handle each Boolean operator case
     558 [ +  + ][ +  + ]:    1630278 :   switch (node.getKind())
         [ +  + ][ +  + ]
     559                 :            :   {
     560                 :     267660 :     case Kind::AND: lit = handleAnd(node); break;
     561                 :     184022 :     case Kind::OR: lit = handleOr(node); break;
     562                 :      40805 :     case Kind::XOR: lit = handleXor(node); break;
     563                 :       5054 :     case Kind::IMPLIES: lit = handleImplies(node); break;
     564                 :      42265 :     case Kind::ITE: lit = handleIte(node); break;
     565                 :     162815 :     case Kind::NOT: lit = ~toCNF(node[0]); break;
     566                 :     460211 :     case Kind::EQUAL:
     567 [ +  + ][ -  - ]:     920422 :       lit = node[0].getType().isBoolean() ? handleIff(node)
     568 [ +  + ][ +  + ]:     460211 :                                           : d_cnfStream.convertAtom(node);
                 [ -  - ]
     569                 :     460211 :       break;
     570                 :     467446 :     default:
     571                 :            :     {
     572                 :     467446 :       lit = d_cnfStream.convertAtom(node);
     573                 :            :     }
     574                 :     467446 :     break;
     575                 :            :   }
     576                 :            :   // Return the (maybe negated) literal
     577         [ +  + ]:    1630278 :   return !negated ? lit : ~lit;
     578                 :            : }
     579                 :            : 
     580                 :     267660 : SatLiteral ProofCnfStream::handleAnd(TNode node)
     581                 :            : {
     582 [ -  + ][ -  + ]:     267660 :   Assert(!d_cnfStream.hasLiteral(node)) << "Atom already mapped!";
                 [ -  - ]
     583 [ -  + ][ -  + ]:     267660 :   Assert(node.getKind() == Kind::AND) << "Expecting an AND expression!";
                 [ -  - ]
     584 [ -  + ][ -  + ]:     267660 :   Assert(node.getNumChildren() > 1) << "Expecting more than 1 child!";
                 [ -  - ]
     585 [ -  + ][ -  + ]:     267660 :   Assert(!d_cnfStream.d_removable)
                 [ -  - ]
     586                 :          0 :       << "Removable clauses cannot contain Boolean structure";
     587         [ +  - ]:     267660 :   Trace("cnf") << "ProofCnfStream::handleAnd(" << node << ")\n";
     588                 :            :   // Number of children
     589                 :     267660 :   unsigned size = node.getNumChildren();
     590                 :            :   // Transform all the children first (remembering the negation)
     591                 :     267660 :   SatClause clause(size + 1);
     592         [ +  + ]:    1316784 :   for (unsigned i = 0; i < size; ++i)
     593                 :            :   {
     594         [ +  - ]:    1049124 :     Trace("cnf") << push;
     595                 :    1049124 :     clause[i] = ~toCNF(node[i]);
     596         [ +  - ]:    1049124 :     Trace("cnf") << pop;
     597                 :            :   }
     598                 :            :   // Create literal for the node
     599                 :     267660 :   SatLiteral lit = d_cnfStream.newLiteral(node);
     600                 :            :   bool added;
     601                 :     267660 :   NodeManager* nm = nodeManager();
     602                 :            :   // lit -> (a_1 & a_2 & a_3 & ... & a_n)
     603                 :            :   // ~lit | (a_1 & a_2 & a_3 & ... & a_n)
     604                 :            :   // (~lit | a_1) & (~lit | a_2) & ... & (~lit | a_n)
     605         [ +  + ]:    1316784 :   for (unsigned i = 0; i < size; ++i)
     606                 :            :   {
     607         [ +  - ]:    1049124 :     Trace("cnf") << push;
     608                 :    1049124 :     added = d_cnfStream.assertClause(node.negate(), ~lit, ~clause[i]);
     609         [ +  - ]:    1049124 :     Trace("cnf") << pop;
     610         [ +  + ]:    1049124 :     if (added)
     611                 :            :     {
     612                 :    1980124 :       Node clauseNode = nm->mkNode(Kind::OR, node.notNode(), node[i]);
     613                 :     990062 :       Node iNode = nm->mkConstInt(i);
     614 [ +  + ][ -  - ]:    2970186 :       d_proof->addStep(clauseNode, ProofRule::CNF_AND_POS, {}, {node, iNode});
     615         [ +  - ]:    1980124 :       Trace("cnf") << "ProofCnfStream::handleAnd: CNF_AND_POS " << i
     616                 :     990062 :                    << " added " << clauseNode << "\n";
     617                 :     990062 :       d_ppm->normalizeAndRegister(clauseNode, d_input);
     618                 :     990062 :     }
     619                 :            :   }
     620                 :            :   // lit <- (a_1 & a_2 & a_3 & ... a_n)
     621                 :            :   // lit | ~(a_1 & a_2 & a_3 & ... & a_n)
     622                 :            :   // lit | ~a_1 | ~a_2 | ~a_3 | ... | ~a_n
     623                 :     267660 :   clause[size] = lit;
     624                 :            :   // This needs to go last, as the clause might get modified by the SAT solver
     625         [ +  - ]:     267660 :   Trace("cnf") << push;
     626                 :     267660 :   added = d_cnfStream.assertClause(node, clause);
     627         [ +  - ]:     267660 :   Trace("cnf") << pop;
     628         [ +  + ]:     267660 :   if (added)
     629                 :            :   {
     630                 :     789675 :     std::vector<Node> disjuncts{node};
     631         [ +  + ]:    1294180 :     for (unsigned i = 0; i < size; ++i)
     632                 :            :     {
     633                 :    1030955 :       disjuncts.push_back(node[i].notNode());
     634                 :            :     }
     635                 :     263225 :     Node clauseNode = nm->mkNode(Kind::OR, disjuncts);
     636                 :     526450 :     d_proof->addStep(clauseNode, ProofRule::CNF_AND_NEG, {}, {node});
     637         [ +  - ]:     526450 :     Trace("cnf") << "ProofCnfStream::handleAnd: CNF_AND_NEG added "
     638                 :     263225 :                  << clauseNode << "\n";
     639                 :     263225 :     d_ppm->normalizeAndRegister(clauseNode, d_input);
     640                 :     263225 :   }
     641                 :     267660 :   return lit;
     642                 :     267660 : }
     643                 :            : 
     644                 :     184022 : SatLiteral ProofCnfStream::handleOr(TNode node)
     645                 :            : {
     646 [ -  + ][ -  + ]:     184022 :   Assert(!d_cnfStream.hasLiteral(node)) << "Atom already mapped!";
                 [ -  - ]
     647 [ -  + ][ -  + ]:     184022 :   Assert(node.getKind() == Kind::OR) << "Expecting an OR expression!";
                 [ -  - ]
     648 [ -  + ][ -  + ]:     184022 :   Assert(node.getNumChildren() > 1) << "Expecting more then 1 child!";
                 [ -  - ]
     649 [ -  + ][ -  + ]:     184022 :   Assert(!d_cnfStream.d_removable)
                 [ -  - ]
     650                 :          0 :       << "Removable clauses can not contain Boolean structure";
     651         [ +  - ]:     184022 :   Trace("cnf") << "ProofCnfStream::handleOr(" << node << ")\n";
     652                 :            :   // Number of children
     653                 :     184022 :   unsigned size = node.getNumChildren();
     654                 :            :   // Transform all the children first
     655                 :     184022 :   SatClause clause(size + 1);
     656         [ +  + ]:     767731 :   for (unsigned i = 0; i < size; ++i)
     657                 :            :   {
     658                 :     583709 :     clause[i] = toCNF(node[i]);
     659                 :            :   }
     660                 :            :   // Create literal for the node
     661                 :     184022 :   SatLiteral lit = d_cnfStream.newLiteral(node);
     662                 :            :   bool added;
     663                 :     184022 :   NodeManager* nm = nodeManager();
     664                 :            :   // lit <- (a_1 | a_2 | a_3 | ... | a_n)
     665                 :            :   // lit | ~(a_1 | a_2 | a_3 | ... | a_n)
     666                 :            :   // (lit | ~a_1) & (lit | ~a_2) & (lit & ~a_3) & ... & (lit & ~a_n)
     667         [ +  + ]:     767731 :   for (unsigned i = 0; i < size; ++i)
     668                 :            :   {
     669                 :     583709 :     added = d_cnfStream.assertClause(node, lit, ~clause[i]);
     670         [ +  + ]:     583709 :     if (added)
     671                 :            :     {
     672                 :    1130804 :       Node clauseNode = nm->mkNode(Kind::OR, node, node[i].notNode());
     673                 :     565402 :       Node iNode = nm->mkConstInt(i);
     674 [ +  + ][ -  - ]:    1696206 :       d_proof->addStep(clauseNode, ProofRule::CNF_OR_NEG, {}, {node, iNode});
     675         [ +  - ]:    1130804 :       Trace("cnf") << "ProofCnfStream::handleOr: CNF_OR_NEG " << i << " added "
     676                 :     565402 :                    << clauseNode << "\n";
     677                 :     565402 :       d_ppm->normalizeAndRegister(clauseNode, d_input);
     678                 :     565402 :     }
     679                 :            :   }
     680                 :            :   // lit -> (a_1 | a_2 | a_3 | ... | a_n)
     681                 :            :   // ~lit | a_1 | a_2 | a_3 | ... | a_n
     682                 :     184022 :   clause[size] = ~lit;
     683                 :            :   // This needs to go last, as the clause might get modified by the SAT solver
     684                 :     184022 :   added = d_cnfStream.assertClause(node.negate(), clause);
     685         [ +  + ]:     184022 :   if (added)
     686                 :            :   {
     687                 :     543555 :     std::vector<Node> disjuncts{node.notNode()};
     688         [ +  + ]:     755876 :     for (unsigned i = 0; i < size; ++i)
     689                 :            :     {
     690                 :     574691 :       disjuncts.push_back(node[i]);
     691                 :            :     }
     692                 :     181185 :     Node clauseNode = nm->mkNode(Kind::OR, disjuncts);
     693                 :     362370 :     d_proof->addStep(clauseNode, ProofRule::CNF_OR_POS, {}, {node});
     694         [ +  - ]:     362370 :     Trace("cnf") << "ProofCnfStream::handleOr: CNF_OR_POS added " << clauseNode
     695                 :     181185 :                  << "\n";
     696                 :     181185 :     d_ppm->normalizeAndRegister(clauseNode, d_input);
     697                 :     181185 :   }
     698                 :     184022 :   return lit;
     699                 :     184022 : }
     700                 :            : 
     701                 :      40805 : SatLiteral ProofCnfStream::handleXor(TNode node)
     702                 :            : {
     703 [ -  + ][ -  + ]:      40805 :   Assert(!d_cnfStream.hasLiteral(node)) << "Atom already mapped!";
                 [ -  - ]
     704 [ -  + ][ -  + ]:      40805 :   Assert(node.getKind() == Kind::XOR) << "Expecting an XOR expression!";
                 [ -  - ]
     705 [ -  + ][ -  + ]:      40805 :   Assert(node.getNumChildren() == 2) << "Expecting exactly 2 children!";
                 [ -  - ]
     706 [ -  + ][ -  + ]:      40805 :   Assert(!d_cnfStream.d_removable)
                 [ -  - ]
     707                 :          0 :       << "Removable clauses can not contain Boolean structure";
     708         [ +  - ]:      40805 :   Trace("cnf") << "ProofCnfStream::handleXor(" << node << ")\n";
     709                 :      40805 :   SatLiteral a = toCNF(node[0]);
     710                 :      40805 :   SatLiteral b = toCNF(node[1]);
     711                 :      40805 :   SatLiteral lit = d_cnfStream.newLiteral(node);
     712                 :            :   bool added;
     713                 :      40805 :   added = d_cnfStream.assertClause(node.negate(), a, b, ~lit);
     714         [ +  + ]:      40805 :   if (added)
     715                 :            :   {
     716                 :            :     Node clauseNode =
     717                 :      81272 :         nodeManager()->mkNode(Kind::OR, node.notNode(), node[0], node[1]);
     718                 :      81272 :     d_proof->addStep(clauseNode, ProofRule::CNF_XOR_POS1, {}, {node});
     719         [ +  - ]:      81272 :     Trace("cnf") << "ProofCnfStream::handleXor: CNF_XOR_POS1 added "
     720                 :      40636 :                  << clauseNode << "\n";
     721                 :      40636 :     d_ppm->normalizeAndRegister(clauseNode, d_input);
     722                 :      40636 :   }
     723                 :      40805 :   added = d_cnfStream.assertClause(node.negate(), ~a, ~b, ~lit);
     724         [ +  + ]:      40805 :   if (added)
     725                 :            :   {
     726                 :      40635 :     Node clauseNode = nodeManager()->mkNode(
     727                 :      81270 :         Kind::OR, node.notNode(), node[0].notNode(), node[1].notNode());
     728                 :      81270 :     d_proof->addStep(clauseNode, ProofRule::CNF_XOR_POS2, {}, {node});
     729         [ +  - ]:      81270 :     Trace("cnf") << "ProofCnfStream::handleXor: CNF_XOR_POS2 added "
     730                 :      40635 :                  << clauseNode << "\n";
     731                 :      40635 :     d_ppm->normalizeAndRegister(clauseNode, d_input);
     732                 :      40635 :   }
     733                 :      40805 :   added = d_cnfStream.assertClause(node, a, ~b, lit);
     734         [ +  + ]:      40805 :   if (added)
     735                 :            :   {
     736                 :            :     Node clauseNode =
     737                 :      81254 :         nodeManager()->mkNode(Kind::OR, node, node[0], node[1].notNode());
     738                 :      81254 :     d_proof->addStep(clauseNode, ProofRule::CNF_XOR_NEG2, {}, {node});
     739         [ +  - ]:      81254 :     Trace("cnf") << "ProofCnfStream::handleXor: CNF_XOR_NEG2 added "
     740                 :      40627 :                  << clauseNode << "\n";
     741                 :      40627 :     d_ppm->normalizeAndRegister(clauseNode, d_input);
     742                 :      40627 :   }
     743                 :      40805 :   added = d_cnfStream.assertClause(node, ~a, b, lit);
     744         [ +  + ]:      40805 :   if (added)
     745                 :            :   {
     746                 :            :     Node clauseNode =
     747                 :      81328 :         nodeManager()->mkNode(Kind::OR, node, node[0].notNode(), node[1]);
     748                 :      81328 :     d_proof->addStep(clauseNode, ProofRule::CNF_XOR_NEG1, {}, {node});
     749         [ +  - ]:      81328 :     Trace("cnf") << "ProofCnfStream::handleXor: CNF_XOR_NEG1 added "
     750                 :      40664 :                  << clauseNode << "\n";
     751                 :      40664 :     d_ppm->normalizeAndRegister(clauseNode, d_input);
     752                 :      40664 :   }
     753                 :      40805 :   return lit;
     754                 :            : }
     755                 :            : 
     756                 :     131834 : SatLiteral ProofCnfStream::handleIff(TNode node)
     757                 :            : {
     758 [ -  + ][ -  + ]:     131834 :   Assert(!d_cnfStream.hasLiteral(node)) << "Atom already mapped!";
                 [ -  - ]
     759 [ -  + ][ -  + ]:     131834 :   Assert(node.getKind() == Kind::EQUAL) << "Expecting an EQUAL expression!";
                 [ -  - ]
     760 [ -  + ][ -  + ]:     131834 :   Assert(node.getNumChildren() == 2) << "Expecting exactly 2 children!";
                 [ -  - ]
     761         [ +  - ]:     131834 :   Trace("cnf") << "handleIff(" << node << ")\n";
     762                 :            :   // Convert the children to CNF
     763                 :     131834 :   SatLiteral a = toCNF(node[0]);
     764                 :     131834 :   SatLiteral b = toCNF(node[1]);
     765                 :            :   // Create literal for the node
     766                 :     131834 :   SatLiteral lit = d_cnfStream.newLiteral(node);
     767                 :            :   bool added;
     768                 :     131834 :   NodeManager* nm = nodeManager();
     769                 :            :   // lit -> ((a-> b) & (b->a))
     770                 :            :   // ~lit | ((~a | b) & (~b | a))
     771                 :            :   // (~a | b | ~lit) & (~b | a | ~lit)
     772                 :     131834 :   added = d_cnfStream.assertClause(node.negate(), ~a, b, ~lit);
     773         [ +  + ]:     131834 :   if (added)
     774                 :            :   {
     775                 :            :     Node clauseNode =
     776                 :     259346 :         nm->mkNode(Kind::OR, node.notNode(), node[0].notNode(), node[1]);
     777                 :     259346 :     d_proof->addStep(clauseNode, ProofRule::CNF_EQUIV_POS1, {}, {node});
     778         [ +  - ]:     259346 :     Trace("cnf") << "ProofCnfStream::handleIff: CNF_EQUIV_POS1 added "
     779                 :     129673 :                  << clauseNode << "\n";
     780                 :     129673 :     d_ppm->normalizeAndRegister(clauseNode, d_input);
     781                 :     129673 :   }
     782                 :     131834 :   added = d_cnfStream.assertClause(node.negate(), a, ~b, ~lit);
     783         [ +  + ]:     131834 :   if (added)
     784                 :            :   {
     785                 :            :     Node clauseNode =
     786                 :     253362 :         nm->mkNode(Kind::OR, node.notNode(), node[0], node[1].notNode());
     787                 :     253362 :     d_proof->addStep(clauseNode, ProofRule::CNF_EQUIV_POS2, {}, {node});
     788         [ +  - ]:     253362 :     Trace("cnf") << "ProofCnfStream::handleIff: CNF_EQUIV_POS2 added "
     789                 :     126681 :                  << clauseNode << "\n";
     790                 :     126681 :     d_ppm->normalizeAndRegister(clauseNode, d_input);
     791                 :     126681 :   }
     792                 :            :   // (a<->b) -> lit
     793                 :            :   // ~((a & b) | (~a & ~b)) | lit
     794                 :            :   // (~(a & b)) & (~(~a & ~b)) | lit
     795                 :            :   // ((~a | ~b) & (a | b)) | lit
     796                 :            :   // (~a | ~b | lit) & (a | b | lit)
     797                 :     131834 :   added = d_cnfStream.assertClause(node, ~a, ~b, lit);
     798         [ +  + ]:     131834 :   if (added)
     799                 :            :   {
     800                 :            :     Node clauseNode =
     801                 :     258822 :         nm->mkNode(Kind::OR, node, node[0].notNode(), node[1].notNode());
     802                 :     258822 :     d_proof->addStep(clauseNode, ProofRule::CNF_EQUIV_NEG2, {}, {node});
     803         [ +  - ]:     258822 :     Trace("cnf") << "ProofCnfStream::handleIff: CNF_EQUIV_NEG2 added "
     804                 :     129411 :                  << clauseNode << "\n";
     805                 :     129411 :     d_ppm->normalizeAndRegister(clauseNode, d_input);
     806                 :     129411 :   }
     807                 :     131834 :   added = d_cnfStream.assertClause(node, a, b, lit);
     808         [ +  + ]:     131834 :   if (added)
     809                 :            :   {
     810                 :     253952 :     Node clauseNode = nm->mkNode(Kind::OR, node, node[0], node[1]);
     811                 :     253952 :     d_proof->addStep(clauseNode, ProofRule::CNF_EQUIV_NEG1, {}, {node});
     812         [ +  - ]:     253952 :     Trace("cnf") << "ProofCnfStream::handleIff: CNF_EQUIV_NEG1 added "
     813                 :     126976 :                  << clauseNode << "\n";
     814                 :     126976 :     d_ppm->normalizeAndRegister(clauseNode, d_input);
     815                 :     126976 :   }
     816                 :     131834 :   return lit;
     817                 :            : }
     818                 :            : 
     819                 :       5054 : SatLiteral ProofCnfStream::handleImplies(TNode node)
     820                 :            : {
     821 [ -  + ][ -  + ]:       5054 :   Assert(!d_cnfStream.hasLiteral(node)) << "Atom already mapped!";
                 [ -  - ]
     822 [ -  + ][ -  + ]:       5054 :   Assert(node.getKind() == Kind::IMPLIES) << "Expecting an IMPLIES expression!";
                 [ -  - ]
     823 [ -  + ][ -  + ]:       5054 :   Assert(node.getNumChildren() == 2) << "Expecting exactly 2 children!";
                 [ -  - ]
     824 [ -  + ][ -  + ]:       5054 :   Assert(!d_cnfStream.d_removable)
                 [ -  - ]
     825                 :          0 :       << "Removable clauses can not contain Boolean structure";
     826         [ +  - ]:       5054 :   Trace("cnf") << "ProofCnfStream::handleImplies(" << node << ")\n";
     827                 :            :   // Convert the children to cnf
     828                 :       5054 :   SatLiteral a = toCNF(node[0]);
     829                 :       5054 :   SatLiteral b = toCNF(node[1]);
     830                 :       5054 :   SatLiteral lit = d_cnfStream.newLiteral(node);
     831                 :            :   bool added;
     832                 :       5054 :   NodeManager* nm = nodeManager();
     833                 :            :   // lit -> (a->b)
     834                 :            :   // ~lit | ~ a | b
     835                 :       5054 :   added = d_cnfStream.assertClause(node.negate(), ~lit, ~a, b);
     836         [ +  + ]:       5054 :   if (added)
     837                 :            :   {
     838                 :            :     Node clauseNode =
     839                 :      10024 :         nm->mkNode(Kind::OR, node.notNode(), node[0].notNode(), node[1]);
     840                 :      10024 :     d_proof->addStep(clauseNode, ProofRule::CNF_IMPLIES_POS, {}, {node});
     841         [ +  - ]:      10024 :     Trace("cnf") << "ProofCnfStream::handleImplies: CNF_IMPLIES_POS added "
     842                 :       5012 :                  << clauseNode << "\n";
     843                 :       5012 :     d_ppm->normalizeAndRegister(clauseNode, d_input);
     844                 :       5012 :   }
     845                 :            :   // (a->b) -> lit
     846                 :            :   // ~(~a | b) | lit
     847                 :            :   // (a | l) & (~b | l)
     848                 :       5054 :   added = d_cnfStream.assertClause(node, a, lit);
     849         [ +  + ]:       5054 :   if (added)
     850                 :            :   {
     851                 :      10074 :     Node clauseNode = nm->mkNode(Kind::OR, node, node[0]);
     852                 :      10074 :     d_proof->addStep(clauseNode, ProofRule::CNF_IMPLIES_NEG1, {}, {node});
     853         [ +  - ]:      10074 :     Trace("cnf") << "ProofCnfStream::handleImplies: CNF_IMPLIES_NEG1 added "
     854                 :       5037 :                  << clauseNode << "\n";
     855                 :       5037 :     d_ppm->normalizeAndRegister(clauseNode, d_input);
     856                 :       5037 :   }
     857                 :       5054 :   added = d_cnfStream.assertClause(node, ~b, lit);
     858         [ +  + ]:       5054 :   if (added)
     859                 :            :   {
     860                 :      10098 :     Node clauseNode = nm->mkNode(Kind::OR, node, node[1].notNode());
     861                 :      10098 :     d_proof->addStep(clauseNode, ProofRule::CNF_IMPLIES_NEG2, {}, {node});
     862         [ +  - ]:      10098 :     Trace("cnf") << "ProofCnfStream::handleImplies: CNF_IMPLIES_NEG2 added "
     863                 :       5049 :                  << clauseNode << "\n";
     864                 :       5049 :     d_ppm->normalizeAndRegister(clauseNode, d_input);
     865                 :       5049 :   }
     866                 :       5054 :   return lit;
     867                 :            : }
     868                 :            : 
     869                 :      42265 : SatLiteral ProofCnfStream::handleIte(TNode node)
     870                 :            : {
     871 [ -  + ][ -  + ]:      42265 :   Assert(!d_cnfStream.hasLiteral(node)) << "Atom already mapped!";
                 [ -  - ]
     872 [ -  + ][ -  + ]:      42265 :   Assert(node.getKind() == Kind::ITE);
                 [ -  - ]
     873 [ -  + ][ -  + ]:      42265 :   Assert(node.getNumChildren() == 3);
                 [ -  - ]
     874 [ -  + ][ -  + ]:      42265 :   Assert(!d_cnfStream.d_removable)
                 [ -  - ]
     875                 :          0 :       << "Removable clauses can not contain Boolean structure";
     876                 :      84530 :   Trace("cnf") << "handleIte(" << node[0] << " " << node[1] << " " << node[2]
     877                 :      42265 :                << ")\n";
     878                 :      42265 :   SatLiteral condLit = toCNF(node[0]);
     879                 :      42265 :   SatLiteral thenLit = toCNF(node[1]);
     880                 :      42265 :   SatLiteral elseLit = toCNF(node[2]);
     881                 :            :   // create literal to the node
     882                 :      42265 :   SatLiteral lit = d_cnfStream.newLiteral(node);
     883                 :            :   bool added;
     884                 :      42265 :   NodeManager* nm = nodeManager();
     885                 :            :   // If ITE is true then one of the branches is true and the condition
     886                 :            :   // implies which one
     887                 :            :   // lit -> (ite b t e)
     888                 :            :   // lit -> (t | e) & (b -> t) & (!b -> e)
     889                 :            :   // lit -> (t | e) & (!b | t) & (b | e)
     890                 :            :   // (!lit | t | e) & (!lit | !b | t) & (!lit | b | e)
     891                 :      42265 :   added = d_cnfStream.assertClause(node.negate(), ~lit, thenLit, elseLit);
     892         [ +  + ]:      42265 :   if (added)
     893                 :            :   {
     894                 :      84266 :     Node clauseNode = nm->mkNode(Kind::OR, node.notNode(), node[1], node[2]);
     895                 :      84266 :     d_proof->addStep(clauseNode, ProofRule::CNF_ITE_POS3, {}, {node});
     896         [ +  - ]:      84266 :     Trace("cnf") << "ProofCnfStream::handleIte: CNF_ITE_POS3 added "
     897                 :      42133 :                  << clauseNode << "\n";
     898                 :      42133 :     d_ppm->normalizeAndRegister(clauseNode, d_input);
     899                 :      42133 :   }
     900                 :      42265 :   added = d_cnfStream.assertClause(node.negate(), ~lit, ~condLit, thenLit);
     901         [ +  + ]:      42265 :   if (added)
     902                 :            :   {
     903                 :            :     Node clauseNode =
     904                 :      82056 :         nm->mkNode(Kind::OR, node.notNode(), node[0].notNode(), node[1]);
     905                 :      82056 :     d_proof->addStep(clauseNode, ProofRule::CNF_ITE_POS1, {}, {node});
     906         [ +  - ]:      82056 :     Trace("cnf") << "ProofCnfStream::handleIte: CNF_ITE_POS1 added "
     907                 :      41028 :                  << clauseNode << "\n";
     908                 :      41028 :     d_ppm->normalizeAndRegister(clauseNode, d_input);
     909                 :      41028 :   }
     910                 :      42265 :   added = d_cnfStream.assertClause(node.negate(), ~lit, condLit, elseLit);
     911         [ +  + ]:      42265 :   if (added)
     912                 :            :   {
     913                 :      77368 :     Node clauseNode = nm->mkNode(Kind::OR, node.notNode(), node[0], node[2]);
     914                 :      77368 :     d_proof->addStep(clauseNode, ProofRule::CNF_ITE_POS2, {}, {node});
     915         [ +  - ]:      77368 :     Trace("cnf") << "ProofCnfStream::handleIte: CNF_ITE_POS2 added "
     916                 :      38684 :                  << clauseNode << "\n";
     917                 :      38684 :     d_ppm->normalizeAndRegister(clauseNode, d_input);
     918                 :      38684 :   }
     919                 :            :   // If ITE is false then one of the branches is false and the condition
     920                 :            :   // implies which one
     921                 :            :   // !lit -> !(ite b t e)
     922                 :            :   // !lit -> (!t | !e) & (b -> !t) & (!b -> !e)
     923                 :            :   // !lit -> (!t | !e) & (!b | !t) & (b | !e)
     924                 :            :   // (lit | !t | !e) & (lit | !b | !t) & (lit | b | !e)
     925                 :      42265 :   added = d_cnfStream.assertClause(node, lit, ~thenLit, ~elseLit);
     926         [ +  + ]:      42265 :   if (added)
     927                 :            :   {
     928                 :            :     Node clauseNode =
     929                 :      84240 :         nm->mkNode(Kind::OR, node, node[1].notNode(), node[2].notNode());
     930                 :      84240 :     d_proof->addStep(clauseNode, ProofRule::CNF_ITE_NEG3, {}, {node});
     931         [ +  - ]:      84240 :     Trace("cnf") << "ProofCnfStream::handleIte: CNF_ITE_NEG3 added "
     932                 :      42120 :                  << clauseNode << "\n";
     933                 :      42120 :     d_ppm->normalizeAndRegister(clauseNode, d_input);
     934                 :      42120 :   }
     935                 :      42265 :   added = d_cnfStream.assertClause(node, lit, ~condLit, ~thenLit);
     936         [ +  + ]:      42265 :   if (added)
     937                 :            :   {
     938                 :            :     Node clauseNode =
     939                 :      81992 :         nm->mkNode(Kind::OR, node, node[0].notNode(), node[1].notNode());
     940                 :      81992 :     d_proof->addStep(clauseNode, ProofRule::CNF_ITE_NEG1, {}, {node});
     941         [ +  - ]:      81992 :     Trace("cnf") << "ProofCnfStream::handleIte: CNF_ITE_NEG1 added "
     942                 :      40996 :                  << clauseNode << "\n";
     943                 :      40996 :     d_ppm->normalizeAndRegister(clauseNode, d_input);
     944                 :      40996 :   }
     945                 :      42265 :   added = d_cnfStream.assertClause(node, lit, condLit, ~elseLit);
     946         [ +  + ]:      42265 :   if (added)
     947                 :            :   {
     948                 :      77326 :     Node clauseNode = nm->mkNode(Kind::OR, node, node[0], node[2].notNode());
     949                 :      77326 :     d_proof->addStep(clauseNode, ProofRule::CNF_ITE_NEG2, {}, {node});
     950         [ +  - ]:      77326 :     Trace("cnf") << "ProofCnfStream::handleIte: CNF_ITE_NEG2 added "
     951                 :      38663 :                  << clauseNode << "\n";
     952                 :      38663 :     d_ppm->normalizeAndRegister(clauseNode, d_input);
     953                 :      38663 :   }
     954                 :      42265 :   return lit;
     955                 :            : }
     956                 :            : 
     957                 :          0 : void ProofCnfStream::dumpDimacs(std::ostream& out,
     958                 :            :                                 const std::vector<Node>& clauses)
     959                 :            : {
     960                 :          0 :   d_cnfStream.dumpDimacs(out, clauses);
     961                 :          0 : }
     962                 :            : 
     963                 :          0 : void ProofCnfStream::dumpDimacs(std::ostream& out,
     964                 :            :                                 const std::vector<Node>& clauses,
     965                 :            :                                 const std::vector<Node>& auxUnits)
     966                 :            : {
     967                 :          0 :   d_cnfStream.dumpDimacs(out, clauses, auxUnits);
     968                 :          0 : }
     969                 :            : 
     970                 :            : }  // namespace prop
     971                 :            : }  // namespace cvc5::internal

Generated by: LCOV version 1.14