LCOV - code coverage report
Current view: top level - buildbot/coverage/build/src/theory/strings - eqc_info.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 72 72 100.0 %
Date: 2026-03-04 11:41:08 Functions: 3 3 100.0 %
Branches: 68 106 64.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                 :            :  * Implementation of equivalence class info for the theory of strings.
      11                 :            :  */
      12                 :            : 
      13                 :            : #include "theory/strings/eqc_info.h"
      14                 :            : 
      15                 :            : #include "theory/strings/theory_strings_utils.h"
      16                 :            : #include "theory/strings/word.h"
      17                 :            : 
      18                 :            : using namespace std;
      19                 :            : using namespace cvc5::context;
      20                 :            : using namespace cvc5::internal::kind;
      21                 :            : 
      22                 :            : namespace cvc5::internal {
      23                 :            : namespace theory {
      24                 :            : namespace strings {
      25                 :            : 
      26                 :     125724 : EqcInfo::EqcInfo(context::Context* c)
      27                 :     125724 :     : d_lengthTerm(c),
      28                 :     125724 :       d_codeTerm(c),
      29                 :     125724 :       d_cardinalityLemK(c),
      30                 :     125724 :       d_normalizedLength(c),
      31                 :     125724 :       d_firstBound(c),
      32                 :     125724 :       d_secondBound(c)
      33                 :            : {
      34                 :     125724 : }
      35                 :            : 
      36                 :     156352 : Node EqcInfo::addEndpointConst(Node t, Node c, bool isSuf)
      37                 :            : {
      38                 :            :   // check conflict
      39         [ +  + ]:     156352 :   Node prev = isSuf ? d_secondBound : d_firstBound;
      40         [ +  + ]:     156352 :   if (!prev.isNull())
      41                 :            :   {
      42         [ +  - ]:     272596 :     Trace("strings-eager-pconf-debug") << "Check conflict " << prev << ", " << t
      43                 :     136298 :                                        << " post=" << isSuf << std::endl;
      44                 :     136298 :     Node prevC = utils::getConstantEndpoint(prev, isSuf);
      45 [ -  + ][ -  + ]:     136298 :     Assert(!prevC.isNull());
                 [ -  - ]
      46 [ -  + ][ -  + ]:     136298 :     Assert(prevC.isConst());
                 [ -  - ]
      47         [ +  + ]:     136298 :     if (c.isNull())
      48                 :            :     {
      49                 :     136130 :       c = utils::getConstantEndpoint(t, isSuf);
      50 [ -  + ][ -  + ]:     136130 :       Assert(!c.isNull());
                 [ -  - ]
      51                 :            :     }
      52 [ -  + ][ -  + ]:     136298 :     Assert(c.isConst());
                 [ -  - ]
      53                 :     136298 :     bool conflict = false;
      54                 :            :     // if the constant prefixes are different
      55         [ +  + ]:     136298 :     if (c != prevC)
      56                 :            :     {
      57                 :            :       // conflicts between constants should be handled by equality engine
      58 [ -  + ][ -  - ]:      26886 :       Assert(!t.isConst() || !prev.isConst());
         [ -  + ][ -  + ]
                 [ -  - ]
      59         [ +  - ]:      53772 :       Trace("strings-eager-pconf-debug")
      60                 :      26886 :           << "Check conflict constants " << prevC << ", " << c << std::endl;
      61                 :      26886 :       size_t pvs = Word::getLength(prevC);
      62                 :      26886 :       size_t cvs = Word::getLength(c);
      63 [ +  + ][ +  - ]:      26701 :       if (pvs == cvs || (pvs > cvs && t.isConst())
      64 [ +  + ][ +  + ]:      53587 :           || (cvs > pvs && prev.isConst()))
         [ +  + ][ +  + ]
      65                 :            :       {
      66                 :            :         // If equal length, cannot be equal due to node check above.
      67                 :            :         // If one is fully constant and has less length than the other, then the
      68                 :            :         // other will not fit and we are in conflict.
      69                 :        548 :         conflict = true;
      70                 :            :       }
      71                 :            :       else
      72                 :            :       {
      73         [ +  + ]:      26338 :         Node larges = pvs > cvs ? prevC : c;
      74         [ +  + ]:      26338 :         Node smalls = pvs > cvs ? c : prevC;
      75         [ +  + ]:      26338 :         if (isSuf)
      76                 :            :         {
      77                 :      19041 :           conflict = !Word::hasSuffix(larges, smalls);
      78                 :            :         }
      79                 :            :         else
      80                 :            :         {
      81                 :       7297 :           conflict = !Word::hasPrefix(larges, smalls);
      82                 :            :         }
      83                 :      26338 :       }
      84 [ +  + ][ +  + ]:      26886 :       if (!conflict && (pvs > cvs || prev.isConst()))
         [ -  + ][ +  + ]
      85                 :            :       {
      86                 :            :         // current is subsumed, either shorter prefix or the other is a full
      87                 :            :         // constant
      88                 :      25609 :         return Node::null();
      89                 :            :       }
      90                 :            :     }
      91         [ +  - ]:     109412 :     else if (!t.isConst())
      92                 :            :     {
      93                 :            :       // current is subsumed since the other may be a full constant
      94                 :     109412 :       return Node::null();
      95                 :            :     }
      96         [ +  + ]:       1277 :     if (conflict)
      97                 :            :     {
      98         [ +  - ]:       1536 :       Trace("strings-eager-pconf")
      99                 :        768 :           << "Conflict for " << prevC << ", " << c << std::endl;
     100                 :       1536 :       Node ret = mkMergeConflict(t, prev, false);
     101         [ +  - ]:       1536 :       Trace("strings-eager-pconf")
     102                 :        768 :           << "String: eager prefix conflict: " << ret << std::endl;
     103                 :        768 :       return ret;
     104                 :        768 :     }
     105         [ +  + ]:     136298 :   }
     106         [ +  + ]:      20563 :   if (isSuf)
     107                 :            :   {
     108                 :      11774 :     d_secondBound = t;
     109                 :            :   }
     110                 :            :   else
     111                 :            :   {
     112                 :       8789 :     d_firstBound = t;
     113                 :            :   }
     114                 :      20563 :   return Node::null();
     115                 :     156352 : }
     116                 :            : 
     117                 :       1136 : Node EqcInfo::mkMergeConflict(Node t, Node prev, bool isArith)
     118                 :            : {
     119         [ +  - ]:       2272 :   Trace("strings-eager-debug")
     120                 :       1136 :       << "mkMergeConflict " << t << ", " << prev << std::endl;
     121                 :       1136 :   NodeManager* nm = t.getNodeManager();
     122                 :       1136 :   std::vector<Node> ccs;
     123         [ +  + ]:       6816 :   Node r[2];
     124         [ +  + ]:       3408 :   for (unsigned i = 0; i < 2; i++)
     125                 :            :   {
     126         [ +  + ]:       2272 :     Node tp = i == 0 ? t : prev;
     127         [ +  + ]:       2272 :     if (tp.getKind() == Kind::STRING_IN_REGEXP)
     128                 :            :     {
     129                 :        387 :       ccs.push_back(tp);
     130                 :        387 :       r[i] = isArith ? nm->mkNode(Kind::STRING_LENGTH, tp[0]) : tp[0];
     131                 :            :     }
     132                 :            :     else
     133                 :            :     {
     134                 :       1885 :       r[i] = tp;
     135                 :            :     }
     136                 :       2272 :   }
     137         [ +  - ]:       1136 :   if (r[0] != r[1])
     138                 :            :   {
     139                 :       1136 :     ccs.push_back(r[0].eqNode(r[1]));
     140                 :            :   }
     141 [ -  + ][ -  + ]:       1136 :   Assert(!ccs.empty());
                 [ -  - ]
     142                 :       2272 :   return nm->mkAnd(ccs);
     143 [ +  + ][ -  - ]:       4544 : }
     144                 :            : 
     145                 :            : }  // namespace strings
     146                 :            : }  // namespace theory
     147                 :            : }  // namespace cvc5::internal

Generated by: LCOV version 1.14