LCOV - code coverage report
Current view: top level - buildbot/coverage/build/src/preprocessing/passes - ff_bitsum.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 62 63 98.4 %
Date: 2026-04-07 10:40:57 Functions: 4 4 100.0 %
Branches: 37 52 71.2 %

           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                 :            :  * parse ff bitsums
      11                 :            :  */
      12                 :            : 
      13                 :            : #include "preprocessing/passes/ff_bitsum.h"
      14                 :            : 
      15                 :            : // external includes
      16                 :            : 
      17                 :            : // std includes
      18                 :            : #include <unordered_set>
      19                 :            : 
      20                 :            : // internal includes
      21                 :            : #include "expr/algorithm/flatten.h"
      22                 :            : #include "expr/node_traversal.h"
      23                 :            : #include "preprocessing/assertion_pipeline.h"
      24                 :            : #include "theory/ff/parse.h"
      25                 :            : 
      26                 :            : namespace cvc5::internal {
      27                 :            : namespace preprocessing {
      28                 :            : namespace passes {
      29                 :            : 
      30                 :      51598 : FfBitsum::FfBitsum(PreprocessingPassContext* preprocContext)
      31                 :      51598 :     : PreprocessingPass(preprocContext, "ff-bitsum")
      32                 :            : {
      33                 :      51598 : }
      34                 :            : 
      35                 :         10 : Node mkAdd(NodeManager* nm, const std::vector<Node>& children)
      36                 :            : {
      37 [ -  + ][ -  + ]:         10 :   Assert(children.size() > 0);
                 [ -  - ]
      38                 :         17 :   return children.size() == 1 ? children[0]
      39         [ +  + ]:         27 :                               : nm->mkNode(Kind::FINITE_FIELD_ADD, children);
      40                 :            : }
      41                 :            : 
      42                 :         66 : PreprocessingPassResult FfBitsum::applyInternal(
      43                 :            :     AssertionPipeline* assertionsToPreprocess)
      44                 :            : {
      45                 :            :   // collect bits
      46                 :         66 :   std::unordered_set<Node> bits;
      47         [ +  + ]:        390 :   for (uint64_t i = 0, n = assertionsToPreprocess->size(); i < n; ++i)
      48                 :            :   {
      49                 :        324 :     std::vector<TNode> anded{};
      50                 :        324 :     TNode assertion = (*assertionsToPreprocess)[i];
      51                 :        324 :     expr::algorithm::flatten(assertion, anded, Kind::AND);
      52         [ +  + ]:        648 :     for (const auto& fact : anded)
      53                 :            :     {
      54                 :        324 :       if (fact.getKind() == Kind::EQUAL && fact[0].getType().isFiniteField())
      55                 :            :       {
      56                 :        110 :         auto bitOpt = theory::ff::parse::bitConstraint(fact);
      57         [ +  + ]:        110 :         if (bitOpt.has_value())
      58                 :            :         {
      59                 :         57 :           bits.insert(*bitOpt);
      60                 :            :         }
      61                 :        110 :       }
      62                 :            :     }
      63                 :        324 :   }
      64                 :            : 
      65                 :            :   // collect bitsums
      66                 :         66 :   auto nm = nodeManager();
      67                 :         66 :   std::unordered_map<Node, Node> cache{};
      68         [ +  + ]:        390 :   for (uint64_t i = 0, n = assertionsToPreprocess->size(); i < n; ++i)
      69                 :            :   {
      70                 :        324 :     Node fact = (*assertionsToPreprocess)[i];
      71                 :        324 :     for (TNode current :
      72                 :       1851 :          NodeDfsIterable(fact, VisitOrder::POSTORDER, [&cache](TNode nn) {
      73                 :       1851 :            return cache.count(nn);
      74         [ +  + ]:       2096 :          }))
      75                 :            :     {
      76                 :       1448 :       Node translation;
      77 [ -  + ][ -  + ]:       1448 :       Assert(!cache.count(current));
                 [ -  - ]
      78         [ +  + ]:       1448 :       if (current.getNumChildren() == 0)
      79                 :            :       {
      80                 :        430 :         translation = current;
      81                 :            :       }
      82                 :            :       else
      83                 :            :       {
      84                 :       1018 :         Kind oldKind = current.getKind();
      85                 :       1018 :         NodeBuilder builder(nm, oldKind);
      86         [ +  + ]:       1018 :         if (current.getMetaKind() == kind::MetaKind::PARAMETERIZED)
      87                 :            :         {
      88                 :         32 :           builder << current.getOperator();
      89                 :            :         }
      90         [ +  + ]:       3225 :         for (TNode c : current)
      91                 :            :         {
      92                 :       2207 :           builder << cache.at(c);
      93                 :       2207 :         }
      94                 :       1018 :         translation = builder;
      95         [ +  + ]:       1018 :         if (translation.getKind() == Kind::FINITE_FIELD_ADD)
      96                 :            :         {
      97                 :        143 :           auto bs = theory::ff::parse::bitSums(translation, bits);
      98 [ +  + ][ +  + ]:        143 :           if (bs.has_value() && bs->first.size() > 0)
                 [ +  + ]
      99                 :            :           {
     100         [ +  + ]:         20 :             for (const auto& [multiplier, bitSeq] : bs->first)
     101                 :            :             {
     102 [ -  + ][ -  + ]:         10 :               Assert(bitSeq.size() > 1);
                 [ -  - ]
     103                 :         10 :               Node bitsum = nm->mkNode(Kind::FINITE_FIELD_BITSUM, bitSeq);
     104                 :         10 :               Node scaled = multiplier.isOne()
     105                 :            :                                 ? bitsum
     106                 :            :                                 : nm->mkNode(Kind::FINITE_FIELD_MULT,
     107         [ -  - ]:          0 :                                              nm->mkConst(multiplier),
     108                 :         14 :                                              bitsum);
     109         [ +  - ]:         10 :               Trace("ff::bitsum") << "found " << scaled << std::endl;
     110                 :         10 :               bs->second.push_back(scaled);
     111                 :         10 :             }
     112                 :         10 :             translation = mkAdd(nm, std::move(bs->second));
     113                 :            :           }
     114                 :        143 :         }
     115                 :       1018 :       }
     116                 :       1448 :       cache[current] = translation;
     117                 :       1772 :     }
     118                 :        324 :     Node newFact = cache[fact];
     119         [ +  + ]:        324 :     if (newFact != fact)
     120                 :            :     {
     121                 :         18 :       assertionsToPreprocess->replace(
     122                 :            :           i, newFact, nullptr, TrustId::PREPROCESS_FF_BITSUM);
     123                 :            :     }
     124                 :        324 :   }
     125                 :            : 
     126                 :         66 :   return PreprocessingPassResult::NO_CONFLICT;
     127                 :         66 : }
     128                 :            : 
     129                 :            : }  // namespace passes
     130                 :            : }  // namespace preprocessing
     131                 :            : }  // namespace cvc5::internal

Generated by: LCOV version 1.14