LCOV - code coverage report
Current view: top level - buildbot/coverage/build/src/theory/uf - proof_checker.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 117 128 91.4 %
Date: 2026-02-27 11:41:18 Functions: 2 2 100.0 %
Branches: 97 194 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 equality proof checker.
      11                 :            :  */
      12                 :            : 
      13                 :            : #include "theory/uf/proof_checker.h"
      14                 :            : 
      15                 :            : #include "theory/uf/theory_uf_rewriter.h"
      16                 :            : 
      17                 :            : using namespace cvc5::internal::kind;
      18                 :            : 
      19                 :            : namespace cvc5::internal {
      20                 :            : namespace theory {
      21                 :            : namespace uf {
      22                 :            : 
      23                 :      18893 : void UfProofRuleChecker::registerTo(ProofChecker* pc)
      24                 :            : {
      25                 :            :   // add checkers
      26                 :      18893 :   pc->registerChecker(ProofRule::REFL, this);
      27                 :      18893 :   pc->registerChecker(ProofRule::SYMM, this);
      28                 :      18893 :   pc->registerChecker(ProofRule::TRANS, this);
      29                 :      18893 :   pc->registerChecker(ProofRule::CONG, this);
      30                 :      18893 :   pc->registerChecker(ProofRule::NARY_CONG, this);
      31                 :      18893 :   pc->registerChecker(ProofRule::PAIRWISE_CONG, this);
      32                 :      18893 :   pc->registerChecker(ProofRule::TRUE_INTRO, this);
      33                 :      18893 :   pc->registerChecker(ProofRule::TRUE_ELIM, this);
      34                 :      18893 :   pc->registerChecker(ProofRule::FALSE_INTRO, this);
      35                 :      18893 :   pc->registerChecker(ProofRule::FALSE_ELIM, this);
      36                 :      18893 :   pc->registerChecker(ProofRule::HO_CONG, this);
      37                 :      18893 :   pc->registerChecker(ProofRule::HO_APP_ENCODE, this);
      38                 :      18893 : }
      39                 :            : 
      40                 :    3927638 : Node UfProofRuleChecker::checkInternal(ProofRule id,
      41                 :            :                                        const std::vector<Node>& children,
      42                 :            :                                        const std::vector<Node>& args)
      43                 :            : {
      44                 :            :   // compute what was proven
      45         [ +  + ]:    3927638 :   if (id == ProofRule::REFL)
      46                 :            :   {
      47 [ -  + ][ -  + ]:     622645 :     Assert(children.empty());
                 [ -  - ]
      48 [ -  + ][ -  + ]:     622645 :     Assert(args.size() == 1);
                 [ -  - ]
      49                 :     622645 :     return args[0].eqNode(args[0]);
      50                 :            :   }
      51         [ +  + ]:    3304993 :   else if (id == ProofRule::SYMM)
      52                 :            :   {
      53 [ -  + ][ -  + ]:    1418660 :     Assert(children.size() == 1);
                 [ -  - ]
      54 [ -  + ][ -  + ]:    1418660 :     Assert(args.empty());
                 [ -  - ]
      55                 :    1418660 :     bool polarity = children[0].getKind() != Kind::NOT;
      56         [ +  + ]:    1418660 :     Node eqp = polarity ? children[0] : children[0][0];
      57         [ -  + ]:    1418660 :     if (eqp.getKind() != Kind::EQUAL)
      58                 :            :     {
      59                 :            :       // not a (dis)equality
      60                 :          0 :       return Node::null();
      61                 :            :     }
      62                 :    2837320 :     Node conc = eqp[1].eqNode(eqp[0]);
      63         [ +  + ]:    1418660 :     return polarity ? conc : conc.notNode();
      64                 :    1418660 :   }
      65         [ +  + ]:    1886333 :   else if (id == ProofRule::TRANS)
      66                 :            :   {
      67 [ -  + ][ -  + ]:     831955 :     Assert(children.size() > 0);
                 [ -  - ]
      68 [ -  + ][ -  + ]:     831955 :     Assert(args.empty());
                 [ -  - ]
      69                 :     831955 :     Node first;
      70                 :     831955 :     Node curr;
      71         [ +  + ]:    2763541 :     for (size_t i = 0, nchild = children.size(); i < nchild; i++)
      72                 :            :     {
      73                 :    1931586 :       Node eqp = children[i];
      74         [ -  + ]:    1931586 :       if (eqp.getKind() != Kind::EQUAL)
      75                 :            :       {
      76                 :          0 :         return Node::null();
      77                 :            :       }
      78         [ +  + ]:    1931586 :       if (first.isNull())
      79                 :            :       {
      80                 :     831955 :         first = eqp[0];
      81                 :            :       }
      82         [ -  + ]:    1099631 :       else if (eqp[0] != curr)
      83                 :            :       {
      84                 :          0 :         return Node::null();
      85                 :            :       }
      86                 :    1931586 :       curr = eqp[1];
      87         [ +  - ]:    1931586 :     }
      88                 :     831955 :     return first.eqNode(curr);
      89                 :     831955 :   }
      90 [ +  + ][ +  + ]:    1054378 :   else if (id == ProofRule::CONG || id == ProofRule::NARY_CONG
      91         [ +  + ]:      77827 :            || id == ProofRule::PAIRWISE_CONG)
      92                 :            :   {
      93 [ -  + ][ -  + ]:     979038 :     Assert(children.size() > 0);
                 [ -  - ]
      94         [ -  + ]:     979038 :     if (args.size() != 1)
      95                 :            :     {
      96                 :          0 :       return Node::null();
      97                 :            :     }
      98                 :     979038 :     Node t = args[0];
      99         [ +  - ]:    1958076 :     Trace("uf-pfcheck") << "congruence " << id << " for " << args[0]
     100                 :     979038 :                         << std::endl;
     101                 :            :     // We do congruence over builtin kinds using operatorToKind
     102                 :     979038 :     std::vector<Node> lchildren;
     103                 :     979038 :     std::vector<Node> rchildren;
     104                 :     979038 :     Kind k = args[0].getKind();
     105         [ +  + ]:     979038 :     if (t.getMetaKind() == metakind::PARAMETERIZED)
     106                 :            :     {
     107                 :            :       // parameterized kinds require the operator
     108                 :     173330 :       lchildren.push_back(t.getOperator());
     109                 :     173330 :       rchildren.push_back(t.getOperator());
     110                 :            :     }
     111                 :            :     // congruence automatically adds variable lists
     112         [ +  + ]:     979038 :     if (t.isClosure())
     113                 :            :     {
     114                 :      12104 :       lchildren.push_back(t[0]);
     115                 :      12104 :       rchildren.push_back(t[0]);
     116                 :            :     }
     117         [ +  + ]:    3735265 :     for (size_t i = 0, nchild = children.size(); i < nchild; i++)
     118                 :            :     {
     119                 :    2756227 :       Node eqp = children[i];
     120         [ -  + ]:    2756227 :       if (eqp.getKind() != Kind::EQUAL)
     121                 :            :       {
     122                 :          0 :         return Node::null();
     123                 :            :       }
     124                 :    2756227 :       lchildren.push_back(eqp[0]);
     125                 :    2756227 :       rchildren.push_back(eqp[1]);
     126         [ +  - ]:    2756227 :     }
     127                 :     979038 :     NodeManager* nm = nodeManager();
     128                 :     979038 :     Node l = nm->mkNode(k, lchildren);
     129                 :     979038 :     Node r = nm->mkNode(k, rchildren);
     130                 :     979038 :     return l.eqNode(r);
     131                 :     979038 :   }
     132         [ +  + ]:      75340 :   else if (id == ProofRule::TRUE_INTRO)
     133                 :            :   {
     134 [ -  + ][ -  + ]:       4946 :     Assert(children.size() == 1);
                 [ -  - ]
     135 [ -  + ][ -  + ]:       4946 :     Assert(args.empty());
                 [ -  - ]
     136                 :       4946 :     Node trueNode = nodeManager()->mkConst(true);
     137                 :       4946 :     return children[0].eqNode(trueNode);
     138                 :       4946 :   }
     139         [ +  + ]:      70394 :   else if (id == ProofRule::TRUE_ELIM)
     140                 :            :   {
     141 [ -  + ][ -  + ]:      45464 :     Assert(children.size() == 1);
                 [ -  - ]
     142 [ -  + ][ -  + ]:      45464 :     Assert(args.empty());
                 [ -  - ]
     143 [ +  - ][ -  + ]:     136392 :     if (children[0].getKind() != Kind::EQUAL || !children[0][1].isConst()
                 [ -  - ]
     144 [ +  - ][ -  + ]:     136392 :         || !children[0][1].getConst<bool>())
         [ +  - ][ +  - ]
                 [ -  - ]
     145                 :            :     {
     146                 :          0 :       return Node::null();
     147                 :            :     }
     148                 :      45464 :     return children[0][0];
     149                 :            :   }
     150         [ +  + ]:      24930 :   else if (id == ProofRule::FALSE_INTRO)
     151                 :            :   {
     152 [ -  + ][ -  + ]:       7534 :     Assert(children.size() == 1);
                 [ -  - ]
     153 [ -  + ][ -  + ]:       7534 :     Assert(args.empty());
                 [ -  - ]
     154         [ -  + ]:       7534 :     if (children[0].getKind() != Kind::NOT)
     155                 :            :     {
     156                 :          0 :       return Node::null();
     157                 :            :     }
     158                 :       7534 :     Node falseNode = nodeManager()->mkConst(false);
     159                 :       7534 :     return children[0][0].eqNode(falseNode);
     160                 :       7534 :   }
     161         [ +  + ]:      17396 :   else if (id == ProofRule::FALSE_ELIM)
     162                 :            :   {
     163 [ -  + ][ -  + ]:      16306 :     Assert(children.size() == 1);
                 [ -  - ]
     164 [ -  + ][ -  + ]:      16306 :     Assert(args.empty());
                 [ -  - ]
     165 [ +  - ][ -  + ]:      48918 :     if (children[0].getKind() != Kind::EQUAL || !children[0][1].isConst()
                 [ -  - ]
     166 [ +  - ][ -  + ]:      48918 :         || children[0][1].getConst<bool>())
         [ +  - ][ +  - ]
                 [ -  - ]
     167                 :            :     {
     168                 :          0 :       return Node::null();
     169                 :            :     }
     170                 :      16306 :     return children[0][0].notNode();
     171                 :            :   }
     172         [ +  + ]:       1090 :   if (id == ProofRule::HO_CONG)
     173                 :            :   {
     174                 :       1067 :     Kind k = Kind::HO_APPLY;
     175                 :            :     // kind argument is optional, defaults to HO_APPLY
     176         [ +  + ]:       1067 :     if (args.size() == 1)
     177                 :            :     {
     178         [ -  + ]:        819 :       if (!getKind(args[0], k))
     179                 :            :       {
     180                 :          0 :         return Node::null();
     181                 :            :       }
     182                 :            :     }
     183                 :       1067 :     std::vector<Node> lchildren;
     184                 :       1067 :     std::vector<Node> rchildren;
     185         [ +  + ]:       4482 :     for (size_t i = 0, nchild = children.size(); i < nchild; ++i)
     186                 :            :     {
     187                 :       3415 :       Node eqp = children[i];
     188         [ -  + ]:       3415 :       if (eqp.getKind() != Kind::EQUAL)
     189                 :            :       {
     190                 :          0 :         return Node::null();
     191                 :            :       }
     192                 :       3415 :       lchildren.push_back(eqp[0]);
     193                 :       3415 :       rchildren.push_back(eqp[1]);
     194         [ +  - ]:       3415 :     }
     195                 :       1067 :     NodeManager* nm = nodeManager();
     196                 :       1067 :     Node l = nm->mkNode(k, lchildren);
     197                 :       1067 :     Node r = nm->mkNode(k, rchildren);
     198                 :       1067 :     return l.eqNode(r);
     199                 :       1067 :   }
     200         [ +  - ]:         23 :   else if (id == ProofRule::HO_APP_ENCODE)
     201                 :            :   {
     202 [ -  + ][ -  + ]:         23 :     Assert(args.size() == 1);
                 [ -  - ]
     203                 :         23 :     Node ret = TheoryUfRewriter::getHoApplyForApplyUf(args[0]);
     204                 :         23 :     return args[0].eqNode(ret);
     205                 :         23 :   }
     206                 :            :   // no rule
     207                 :          0 :   return Node::null();
     208                 :            : }
     209                 :            : 
     210                 :            : }  // namespace uf
     211                 :            : }  // namespace theory
     212                 :            : }  // namespace cvc5::internal

Generated by: LCOV version 1.14