LCOV - code coverage report
Current view: top level - buildbot/coverage/build/src/theory/arith/linear - bound_counts.h (source / functions) Hit Total Coverage
Test: coverage.info Lines: 89 96 92.7 %
Date: 2026-02-23 11:51:46 Functions: 26 29 89.7 %
Branches: 52 84 61.9 %

           Branch data     Line data    Source code
       1                 :            : /******************************************************************************
       2                 :            :  * Top contributors (to current version):
       3                 :            :  *   Tim King, Clark Barrett
       4                 :            :  *
       5                 :            :  * This file is part of the cvc5 project.
       6                 :            :  *
       7                 :            :  * Copyright (c) 2009-2025 by the authors listed in the file AUTHORS
       8                 :            :  * in the top-level source directory and their institutional affiliations.
       9                 :            :  * All rights reserved.  See the file COPYING in the top-level source
      10                 :            :  * directory for licensing information.
      11                 :            :  * ****************************************************************************
      12                 :            :  *
      13                 :            :  * [[ Add one-line brief description here ]]
      14                 :            :  *
      15                 :            :  * [[ Add lengthier description here ]]
      16                 :            :  * \todo document this file
      17                 :            :  */
      18                 :            : 
      19                 :            : #include "cvc5_private.h"
      20                 :            : #pragma once
      21                 :            : 
      22                 :            : #include "base/check.h"
      23                 :            : #include "theory/arith/linear/arithvar.h"
      24                 :            : #include "util/dense_map.h"
      25                 :            : 
      26                 :            : namespace cvc5::internal {
      27                 :            : namespace theory {
      28                 :            : namespace arith::linear {
      29                 :            : 
      30                 :            : class BoundCounts {
      31                 :            : private:
      32                 :            :   uint32_t d_lowerBoundCount;
      33                 :            :   uint32_t d_upperBoundCount;
      34                 :            : 
      35                 :            : public:
      36                 :   74610280 :   BoundCounts() : d_lowerBoundCount(0), d_upperBoundCount(0) {}
      37                 :  262508320 :   BoundCounts(uint32_t lbs, uint32_t ubs)
      38                 :  262508320 :   : d_lowerBoundCount(lbs), d_upperBoundCount(ubs) {}
      39                 :            : 
      40                 :  120173629 :   bool operator==(BoundCounts bc) const {
      41                 :  120173629 :     return d_lowerBoundCount == bc.d_lowerBoundCount
      42 [ +  + ][ +  + ]:  120173629 :       && d_upperBoundCount == bc.d_upperBoundCount;
      43                 :            :   }
      44                 :    7103312 :   bool operator!=(BoundCounts bc) const {
      45                 :    7103312 :     return  d_lowerBoundCount != bc.d_lowerBoundCount
      46 [ +  + ][ +  + ]:    7103312 :       || d_upperBoundCount != bc.d_upperBoundCount;
      47                 :            :   }
      48                 :            :   /** This is not a total order! */
      49                 :     124970 :   bool operator>=(BoundCounts bc) const {
      50         [ +  - ]:     249940 :     return d_lowerBoundCount >= bc.d_lowerBoundCount &&
      51         [ +  - ]:     249940 :       d_upperBoundCount >= bc.d_upperBoundCount;
      52                 :            :   }
      53                 :            : 
      54 [ +  + ][ +  + ]:  335110098 :   inline bool isZero() const{ return d_lowerBoundCount == 0 && d_upperBoundCount == 0; }
      55                 :   35514779 :   inline uint32_t lowerBoundCount() const{
      56                 :   35514779 :     return d_lowerBoundCount;
      57                 :            :   }
      58                 :   35177263 :   inline uint32_t upperBoundCount() const{
      59                 :   35177263 :     return d_upperBoundCount;
      60                 :            :   }
      61                 :            : 
      62                 :            :   inline BoundCounts operator+(BoundCounts bc) const{
      63                 :            :     return BoundCounts(d_lowerBoundCount + bc.d_lowerBoundCount,
      64                 :            :                        d_upperBoundCount + bc.d_upperBoundCount);
      65                 :            :   }
      66                 :            : 
      67                 :     124970 :   inline BoundCounts operator-(BoundCounts bc) const {
      68 [ -  + ][ -  + ]:     124970 :     Assert(*this >= bc);
                 [ -  - ]
      69                 :     249940 :     return BoundCounts(d_lowerBoundCount - bc.d_lowerBoundCount,
      70                 :     124970 :                        d_upperBoundCount - bc.d_upperBoundCount);
      71                 :            :   }
      72                 :            : 
      73                 :            : 
      74                 :    1966858 :   inline BoundCounts& operator+=(BoundCounts bc) {
      75                 :    1966858 :     d_upperBoundCount += bc.d_upperBoundCount;
      76                 :    1966858 :     d_lowerBoundCount += bc.d_lowerBoundCount;
      77                 :    1966858 :     return *this;
      78                 :            :   }
      79                 :            : 
      80                 :            :   inline BoundCounts& operator-=(BoundCounts bc) {
      81                 :            :     Assert(d_lowerBoundCount >= bc.d_lowerBoundCount);
      82                 :            :     Assert(d_upperBoundCount >= bc.d_upperBoundCount);
      83                 :            :     d_upperBoundCount -= bc.d_upperBoundCount;
      84                 :            :     d_lowerBoundCount -= bc.d_lowerBoundCount;
      85                 :            : 
      86                 :            :     return *this;
      87                 :            :   }
      88                 :            : 
      89                 :            :   /** Based on the sign coefficient a variable is multiplied by,
      90                 :            :    * the effects the bound counts either has no effect (sgn == 0),
      91                 :            :    * the lower bounds and upper bounds flip (sgn < 0), or nothing (sgn >0).
      92                 :            :    */
      93                 :    2624214 :   inline BoundCounts multiplyBySgn(int sgn) const{
      94         [ +  + ]:    2624214 :     if(sgn > 0){
      95                 :     984034 :       return *this;
      96         [ -  + ]:    1640180 :     }else if(sgn == 0){
      97                 :          0 :       return BoundCounts(0,0);
      98                 :            :     }else{
      99                 :    1640180 :       return BoundCounts(d_upperBoundCount, d_lowerBoundCount);
     100                 :            :     }
     101                 :            :   }
     102                 :            : 
     103                 :   96734815 :   inline void addInChange(int sgn, BoundCounts before, BoundCounts after){
     104         [ +  + ]:   96734815 :     if(before == after){
     105                 :    6515223 :       return;
     106         [ +  + ]:   90219592 :     }else if(sgn < 0){
     107 [ -  + ][ -  + ]:   50080447 :       Assert(d_upperBoundCount >= before.d_lowerBoundCount);
                 [ -  - ]
     108 [ -  + ][ -  + ]:   50080447 :       Assert(d_lowerBoundCount >= before.d_upperBoundCount);
                 [ -  - ]
     109                 :   50080447 :       d_upperBoundCount += after.d_lowerBoundCount - before.d_lowerBoundCount;
     110                 :   50080447 :       d_lowerBoundCount += after.d_upperBoundCount - before.d_upperBoundCount;
     111         [ +  - ]:   40139145 :     }else if(sgn > 0){
     112 [ -  + ][ -  + ]:   40139145 :       Assert(d_upperBoundCount >= before.d_upperBoundCount);
                 [ -  - ]
     113 [ -  + ][ -  + ]:   40139145 :       Assert(d_lowerBoundCount >= before.d_lowerBoundCount);
                 [ -  - ]
     114                 :   40139145 :       d_upperBoundCount += after.d_upperBoundCount - before.d_upperBoundCount;
     115                 :   40139145 :       d_lowerBoundCount += after.d_lowerBoundCount - before.d_lowerBoundCount;
     116                 :            :     }
     117                 :            :   }
     118                 :            : 
     119                 :  161530398 :   inline void addInSgn(BoundCounts bc, int before, int after){
     120 [ -  + ][ -  + ]:  161530398 :     Assert(before != after);
                 [ -  - ]
     121 [ -  + ][ -  + ]:  161530398 :     Assert(!bc.isZero());
                 [ -  - ]
     122                 :            : 
     123         [ +  + ]:  161530398 :     if(before < 0){
     124                 :   40155140 :       d_upperBoundCount -= bc.d_lowerBoundCount;
     125                 :   40155140 :       d_lowerBoundCount -= bc.d_upperBoundCount;
     126         [ +  + ]:  121375258 :     }else if(before > 0){
     127                 :   41086476 :       d_upperBoundCount -= bc.d_upperBoundCount;
     128                 :   41086476 :       d_lowerBoundCount -= bc.d_lowerBoundCount;
     129                 :            :     }
     130         [ +  + ]:  161530398 :     if(after < 0){
     131                 :   47472615 :       d_upperBoundCount += bc.d_lowerBoundCount;
     132                 :   47472615 :       d_lowerBoundCount += bc.d_upperBoundCount;
     133         [ +  + ]:  114057783 :     }else if(after > 0){
     134                 :   43610928 :       d_upperBoundCount += bc.d_upperBoundCount;
     135                 :   43610928 :       d_lowerBoundCount += bc.d_lowerBoundCount;
     136                 :            :     }
     137                 :  161530398 :   }
     138                 :            : };
     139                 :            : 
     140                 :            : class BoundsInfo {
     141                 :            : private:
     142                 :            : 
     143                 :            :   /**
     144                 :            :    * x = \sum_{a < 0} a_i i + \sum_{b > 0} b_j j
     145                 :            :    *
     146                 :            :    * AtUpperBound = {assignment(i) = lb(i)} \cup {assignment(j) = ub(j)}
     147                 :            :    * AtLowerBound = {assignment(i) = ub(i)} \cup {assignment(j) = lb(j)}
     148                 :            :    */
     149                 :            :   BoundCounts d_atBounds;
     150                 :            : 
     151                 :            :   /** This is for counting how many upper and lower bounds a row has. */
     152                 :            :   BoundCounts d_hasBounds;
     153                 :            : 
     154                 :            : public:
     155                 :   37305140 :   BoundsInfo() : d_atBounds(), d_hasBounds() {}
     156                 :  124267955 :   BoundsInfo(BoundCounts atBounds, BoundCounts hasBounds)
     157                 :  124267955 :     : d_atBounds(atBounds), d_hasBounds(hasBounds) {}
     158                 :            : 
     159                 :    1558416 :   BoundCounts atBounds() const { return d_atBounds; }
     160                 :   18669269 :   BoundCounts hasBounds() const { return d_hasBounds; }
     161                 :            : 
     162                 :            :   /** This corresponds to adding in another variable to the row. */
     163                 :            :   inline BoundsInfo operator+(const BoundsInfo& bc) const{
     164                 :            :     return BoundsInfo(d_atBounds + bc.d_atBounds,
     165                 :            :                       d_hasBounds + bc.d_hasBounds);
     166                 :            :   }
     167                 :            :   /** This corresponds to removing a variable from the row. */
     168                 :            :   inline BoundsInfo operator-(const BoundsInfo& bc) const {
     169                 :            :     Assert(*this >= bc);
     170                 :            :     return BoundsInfo(d_atBounds - bc.d_atBounds,
     171                 :            :                       d_hasBounds - bc.d_hasBounds);
     172                 :            :   }
     173                 :            : 
     174                 :     983429 :   inline BoundsInfo& operator+=(const BoundsInfo& bc) {
     175                 :     983429 :     d_atBounds += bc.d_atBounds;
     176                 :     983429 :     d_hasBounds += bc.d_hasBounds;
     177                 :     983429 :     return (*this);
     178                 :            :   }
     179                 :            : 
     180                 :            :   /** Based on the sign coefficient a variable is multiplied by,
     181                 :            :    * the effects the bound counts either has no effect (sgn == 0),
     182                 :            :    * the lower bounds and upper bounds flip (sgn < 0), or nothing (sgn >0).
     183                 :            :    */
     184                 :    1187137 :   inline BoundsInfo multiplyBySgn(int sgn) const{
     185                 :    1187137 :     return BoundsInfo(d_atBounds.multiplyBySgn(sgn), d_hasBounds.multiplyBySgn(sgn));
     186                 :            :   }
     187                 :            : 
     188                 :   18545821 :   bool operator==(const BoundsInfo& other) const{
     189 [ +  + ][ +  + ]:   18545821 :     return d_atBounds == other.d_atBounds && d_hasBounds == other.d_hasBounds;
     190                 :            :   }
     191                 :   18545821 :   bool operator!=(const BoundsInfo& other) const{
     192                 :   18545821 :     return !(*this == other);
     193                 :            :   }
     194                 :            :   /** This is not a total order! */
     195                 :            :   bool operator>=(const BoundsInfo& other) const{
     196                 :            :     return d_atBounds >= other.d_atBounds && d_hasBounds >= other.d_hasBounds;
     197                 :            :   }
     198                 :   45527534 :   void addInChange(int sgn, const BoundsInfo& before, const BoundsInfo& after){
     199                 :   45527534 :     addInAtBoundChange(sgn, before.d_atBounds, after.d_atBounds);
     200                 :   45527534 :     addInHasBoundChange(sgn, before.d_hasBounds, after.d_hasBounds);
     201                 :   45527534 :   }
     202                 :   51082311 :   void addInAtBoundChange(int sgn, BoundCounts before, BoundCounts after){
     203                 :   51082311 :     d_atBounds.addInChange(sgn, before, after);
     204                 :   51082311 :   }
     205                 :   45527534 :   void addInHasBoundChange(int sgn, BoundCounts before, BoundCounts after){
     206                 :   45527534 :     d_hasBounds.addInChange(sgn, before, after);
     207                 :   45527534 :   }
     208                 :            : 
     209                 :   86789850 :   inline void addInSgn(const BoundsInfo& bc, int before, int after){
     210         [ +  + ]:   86789850 :     if(!bc.d_atBounds.isZero()){ d_atBounds.addInSgn(bc.d_atBounds, before, after);}
     211         [ +  + ]:   86789850 :     if(!bc.d_hasBounds.isZero()){ d_hasBounds.addInSgn(bc.d_hasBounds, before, after);}
     212                 :   86789850 :   }
     213                 :            : };
     214                 :            : 
     215                 :            : /** This is intended to map each row to its relevant bound information. */
     216                 :            : typedef DenseMap<BoundsInfo> BoundInfoMap;
     217                 :            : 
     218                 :          0 : inline std::ostream& operator<<(std::ostream& os, const BoundCounts& bc){
     219                 :          0 :   os << "[bc " << bc.lowerBoundCount() << ", " << bc.upperBoundCount() << "]";
     220                 :          0 :   return os;
     221                 :            : }
     222                 :            : 
     223                 :          0 : inline std::ostream& operator<<(std::ostream& os, const BoundsInfo& inf){
     224                 :          0 :   os << "[bi : @ " << inf.atBounds() << ", " << inf.hasBounds() << "]";
     225                 :          0 :   return os;
     226                 :            : }
     227                 :            : class BoundUpdateCallback {
     228                 :            : public:
     229                 :    5117697 :   virtual ~BoundUpdateCallback() {}
     230                 :            :   virtual void operator()(ArithVar v, const BoundsInfo&  up) = 0;
     231                 :            : };
     232                 :            : 
     233                 :            : }  // namespace arith
     234                 :            : }  // namespace theory
     235                 :            : }  // namespace cvc5::internal

Generated by: LCOV version 1.14