LCOV - code coverage report
Current view: top level - buildbot/coverage/build/src/theory/sets - rels_utils.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 75 77 97.4 %
Date: 2026-04-29 10:45:04 Functions: 5 5 100.0 %
Branches: 33 44 75.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                 :            :  * Utility functions for relations.
      11                 :            :  */
      12                 :            : 
      13                 :            : #include "rels_utils.h"
      14                 :            : 
      15                 :            : #include "expr/dtype.h"
      16                 :            : #include "expr/dtype_cons.h"
      17                 :            : #include "theory/datatypes/project_op.h"
      18                 :            : #include "theory/datatypes/tuple_utils.h"
      19                 :            : #include "theory/sets/normal_form.h"
      20                 :            : #include "theory/sets/set_reduction.h"
      21                 :            : 
      22                 :            : using namespace cvc5::internal::kind;
      23                 :            : using namespace cvc5::internal::theory::datatypes;
      24                 :            : using namespace cvc5::internal::theory::sets;
      25                 :            : 
      26                 :            : namespace cvc5::internal {
      27                 :            : namespace theory {
      28                 :            : namespace sets {
      29                 :            : 
      30                 :          9 : std::set<Node> RelsUtils::computeTC(const std::set<Node>& members, Node rel)
      31                 :            : {
      32                 :          9 :   std::set<Node>::iterator mem_it = members.begin();
      33                 :          9 :   std::map<Node, int> ele_num_map;
      34                 :          9 :   std::set<Node> tc_rel_mem;
      35                 :            : 
      36         [ +  + ]:         29 :   while (mem_it != members.end())
      37                 :            :   {
      38                 :         20 :     Node fst = TupleUtils::nthElementOfTuple(*mem_it, 0);
      39                 :         20 :     Node snd = TupleUtils::nthElementOfTuple(*mem_it, 1);
      40                 :         20 :     std::set<Node> traversed;
      41                 :         20 :     traversed.insert(fst);
      42                 :         20 :     computeTC(rel, members, fst, snd, traversed, tc_rel_mem);
      43                 :         20 :     mem_it++;
      44                 :         20 :   }
      45                 :         18 :   return tc_rel_mem;
      46                 :          9 : }
      47                 :            : 
      48                 :         37 : void RelsUtils::computeTC(Node rel,
      49                 :            :                           const std::set<Node>& members,
      50                 :            :                           Node a,
      51                 :            :                           Node b,
      52                 :            :                           std::set<Node>& traversed,
      53                 :            :                           std::set<Node>& transitiveClosureMembers)
      54                 :            : {
      55                 :         37 :   transitiveClosureMembers.insert(constructPair(rel, a, b));
      56         [ +  + ]:         37 :   if (traversed.find(b) != traversed.end())
      57                 :            :   {
      58                 :          3 :     return;
      59                 :            :   }
      60                 :         34 :   traversed.insert(b);
      61                 :         34 :   std::set<Node>::iterator mem_it = members.begin();
      62         [ +  + ]:        151 :   while (mem_it != members.end())
      63                 :            :   {
      64                 :        117 :     Node new_fst = TupleUtils::nthElementOfTuple(*mem_it, 0);
      65                 :        117 :     Node new_snd = TupleUtils::nthElementOfTuple(*mem_it, 1);
      66         [ +  + ]:        117 :     if (b == new_fst)
      67                 :            :     {
      68                 :         17 :       computeTC(rel, members, a, new_snd, traversed, transitiveClosureMembers);
      69                 :            :     }
      70                 :        117 :     mem_it++;
      71                 :        117 :   }
      72                 :            : }
      73                 :            : 
      74                 :       2400 : Node RelsUtils::constructPair(Node rel, Node a, Node b)
      75                 :            : {
      76                 :       2400 :   const DType& dt = rel.getType().getSetElementType().getDType();
      77                 :            :   return NodeManager::mkNode(
      78                 :       2400 :       Kind::APPLY_CONSTRUCTOR, dt[0].getConstructor(), a, b);
      79                 :            : }
      80                 :            : 
      81                 :         17 : Node RelsUtils::evaluateGroup(TNode n)
      82                 :            : {
      83 [ -  + ][ -  + ]:         17 :   Assert(n.getKind() == Kind::RELATION_GROUP);
                 [ -  - ]
      84                 :            : 
      85                 :         17 :   Node A = n[0];
      86                 :         17 :   TypeNode setType = A.getType();
      87                 :         17 :   TypeNode partitionType = n.getType();
      88                 :            : 
      89         [ -  + ]:         17 :   if (A.getKind() == Kind::SET_EMPTY)
      90                 :            :   {
      91                 :            :     // return a nonempty partition
      92                 :          0 :     return NodeManager::mkNode(Kind::SET_SINGLETON, A);
      93                 :            :   }
      94                 :            : 
      95                 :            :   std::vector<uint32_t> indices =
      96                 :         17 :       n.getOperator().getConst<ProjectOp>().getIndices();
      97                 :            : 
      98                 :         17 :   std::set<Node> elements = NormalForm::getElementsFromNormalConstant(A);
      99         [ +  - ]:         17 :   Trace("sets-group") << "elements: " << elements << std::endl;
     100                 :            :   // a simple map from elements to equivalent classes with this invariant:
     101                 :            :   // each key element must appear exactly once in one of the values.
     102                 :         17 :   std::map<Node, std::set<Node>> sets;
     103                 :         17 :   std::set<Node> emptyClass;
     104         [ +  + ]:        127 :   for (const Node& element : elements)
     105                 :            :   {
     106                 :            :     // initially each singleton element is an equivalence class
     107                 :        220 :     sets[element] = {element};
     108                 :            :   }
     109         [ +  + ]:        127 :   for (std::set<Node>::iterator i = elements.begin(); i != elements.end(); ++i)
     110                 :            :   {
     111                 :        110 :     Node iElement = *i;
     112         [ +  + ]:        110 :     if (sets[iElement].empty())
     113                 :            :     {
     114                 :            :       // skip this element since its equivalent class has already been processed
     115                 :         63 :       continue;
     116                 :            :     }
     117                 :         47 :     std::set<Node>::iterator j = i;
     118                 :         47 :     ++j;
     119         [ +  + ]:        230 :     while (j != elements.end())
     120                 :            :     {
     121                 :        183 :       Node jElement = *j;
     122         [ +  + ]:        183 :       if (TupleUtils::sameProjection(indices, iElement, jElement))
     123                 :            :       {
     124                 :            :         // add element j to the equivalent class
     125                 :         63 :         sets[iElement].insert(jElement);
     126                 :            :         // mark the equivalent class of j as processed
     127                 :         63 :         sets[jElement] = emptyClass;
     128                 :            :       }
     129                 :        183 :       ++j;
     130                 :        183 :     }
     131         [ +  + ]:        110 :   }
     132                 :            : 
     133                 :            :   // construct the partition parts
     134                 :         17 :   std::set<Node> parts;
     135         [ +  + ]:        127 :   for (std::pair<Node, std::set<Node>> pair : sets)
     136                 :            :   {
     137                 :        110 :     const std::set<Node>& eqc = pair.second;
     138         [ +  + ]:        110 :     if (eqc.empty())
     139                 :            :     {
     140                 :         63 :       continue;
     141                 :            :     }
     142                 :         47 :     Node part = NormalForm::elementsToSet(eqc, setType);
     143                 :         47 :     parts.insert(part);
     144         [ +  + ]:        110 :   }
     145                 :         17 :   Node ret = NormalForm::elementsToSet(parts, partitionType);
     146         [ +  - ]:         17 :   Trace("sets-group") << "ret: " << ret << std::endl;
     147                 :         17 :   return ret;
     148                 :         17 : }
     149                 :            : 
     150                 :          2 : Node RelsUtils::evaluateRelationAggregate(TNode n)
     151                 :            : {
     152 [ -  + ][ -  + ]:          2 :   Assert(n.getKind() == Kind::RELATION_AGGREGATE);
                 [ -  - ]
     153                 :          2 :   if (!(n[1].isConst() && n[2].isConst()))
     154                 :            :   {
     155                 :            :     // we can't proceed further.
     156                 :          0 :     return n;
     157                 :            :   }
     158                 :            : 
     159                 :          2 :   Node reduction = SetReduction::reduceAggregateOperator(n);
     160                 :          2 :   return reduction;
     161                 :          2 : }
     162                 :            : 
     163                 :            : }  // namespace sets
     164                 :            : }  // namespace theory
     165                 :            : }  // namespace cvc5::internal

Generated by: LCOV version 1.14