LCOV - code coverage report
Current view: top level - buildbot/coverage/build/src/theory/arith/linear - partial_model.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 351 414 84.8 %
Date: 2026-08-04 10:35:26 Functions: 71 81 87.7 %
Branches: 213 356 59.8 %

           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                 :            :  * [[ Add one-line brief description here ]]
      11                 :            :  *
      12                 :            :  * [[ Add lengthier description here ]]
      13                 :            :  * \todo document this file
      14                 :            :  */
      15                 :            : 
      16                 :            : #include "theory/arith/linear/partial_model.h"
      17                 :            : 
      18                 :            : #include "base/output.h"
      19                 :            : #include "theory/arith/linear/constraint.h"
      20                 :            : #include "theory/arith/linear/normal_form.h"
      21                 :            : 
      22                 :            : using namespace std;
      23                 :            : 
      24                 :            : namespace cvc5::internal {
      25                 :            : namespace theory {
      26                 :            : namespace arith::linear {
      27                 :            : 
      28                 :      28663 : ArithVariables::ArithVariables(context::Context* c,
      29                 :      28663 :                                DeltaComputeCallback deltaComputingFunc)
      30                 :      28663 :     : d_vars(),
      31                 :      28663 :       d_safeAssignment(),
      32                 :      28663 :       d_numberOfVariables(0),
      33                 :      28663 :       d_pool(),
      34                 :      28663 :       d_released(),
      35                 :      28663 :       d_nodeToArithVarMap(),
      36                 :      28663 :       d_boundsQueue(),
      37                 :      28663 :       d_enqueueingBoundCounts(true),
      38                 :      28663 :       d_lbRevertHistory(c, true, LowerBoundCleanUp(this)),
      39                 :      28663 :       d_ubRevertHistory(c, true, UpperBoundCleanUp(this)),
      40                 :      28663 :       d_deltaIsSafe(false),
      41                 :      28663 :       d_delta(-1, 1),
      42                 :      28663 :       d_deltaComputingFunc(deltaComputingFunc)
      43                 :            : {
      44                 :      28663 : }
      45                 :            : 
      46                 :   78417712 : ArithVar ArithVariables::getNumberOfVariables() const
      47                 :            : {
      48                 :   78417712 :   return d_numberOfVariables;
      49                 :            : }
      50                 :            : 
      51                 :   13274234 : bool ArithVariables::hasArithVar(TNode x) const
      52                 :            : {
      53                 :   13274234 :   return d_nodeToArithVarMap.find(x) != d_nodeToArithVarMap.end();
      54                 :            : }
      55                 :            : 
      56                 :   29784084 : bool ArithVariables::hasNode(ArithVar a) const { return d_vars.isKey(a); }
      57                 :            : 
      58                 :    5544103 : ArithVar ArithVariables::asArithVar(TNode x) const
      59                 :            : {
      60 [ -  + ][ -  + ]:    5544103 :   Assert(hasArithVar(x));
                 [ -  - ]
      61 [ -  + ][ -  + ]:    5544103 :   Assert((d_nodeToArithVarMap.find(x))->second <= ARITHVAR_SENTINEL);
                 [ -  - ]
      62                 :    5544103 :   return (d_nodeToArithVarMap.find(x))->second;
      63                 :            : }
      64                 :            : 
      65                 :   19172811 : Node ArithVariables::asNode(ArithVar a) const
      66                 :            : {
      67 [ -  + ][ -  + ]:   19172811 :   Assert(hasNode(a));
                 [ -  - ]
      68                 :   19172811 :   return d_vars[a].d_node;
      69                 :            : }
      70                 :            : 
      71                 :          0 : ArithVariables::var_iterator::var_iterator() : d_vars(nullptr), d_wrapped() {}
      72                 :            : 
      73                 :     462674 : ArithVariables::var_iterator::var_iterator(const VarInfoVec* vars,
      74                 :     462674 :                                            VarInfoVec::const_iterator ci)
      75                 :     462674 :     : d_vars(vars), d_wrapped(ci)
      76                 :            : {
      77                 :     462674 :   nextInitialized();
      78                 :     462674 : }
      79                 :            : 
      80                 :   15225162 : ArithVariables::var_iterator& ArithVariables::var_iterator::operator++()
      81                 :            : {
      82                 :   15225162 :   ++d_wrapped;
      83                 :   15225162 :   nextInitialized();
      84                 :   15225162 :   return *this;
      85                 :            : }
      86                 :          0 : bool ArithVariables::var_iterator::operator==(
      87                 :            :     const ArithVariables::var_iterator& other) const
      88                 :            : {
      89                 :          0 :   return d_wrapped == other.d_wrapped;
      90                 :            : }
      91                 :   15456499 : bool ArithVariables::var_iterator::operator!=(
      92                 :            :     const ArithVariables::var_iterator& other) const
      93                 :            : {
      94                 :   15456499 :   return d_wrapped != other.d_wrapped;
      95                 :            : }
      96                 :   15225162 : ArithVar ArithVariables::var_iterator::operator*() const { return *d_wrapped; }
      97                 :            : 
      98                 :   15687836 : void ArithVariables::var_iterator::nextInitialized()
      99                 :            : {
     100                 :   15687836 :   VarInfoVec::const_iterator end = d_vars->end();
     101 [ +  + ][ +  + ]:   15687986 :   while (d_wrapped != end && !((*d_vars)[*d_wrapped].initialized()))
                 [ +  + ]
     102                 :            :   {
     103                 :        150 :     ++d_wrapped;
     104                 :            :   }
     105                 :   15687836 : }
     106                 :            : 
     107                 :     231337 : ArithVariables::var_iterator ArithVariables::var_begin() const
     108                 :            : {
     109                 :     231337 :   return var_iterator(&d_vars, d_vars.begin());
     110                 :            : }
     111                 :            : 
     112                 :     231337 : ArithVariables::var_iterator ArithVariables::var_end() const
     113                 :            : {
     114                 :     231337 :   return var_iterator(&d_vars, d_vars.end());
     115                 :            : }
     116                 :   38152959 : bool ArithVariables::isInteger(ArithVar x) const
     117                 :            : {
     118                 :   38152959 :   return d_vars[x].d_type >= ArithType::Integer;
     119                 :            : }
     120                 :            : 
     121                 :            : /** Is the assignment to x integral? */
     122                 :    3375260 : bool ArithVariables::integralAssignment(ArithVar x) const
     123                 :            : {
     124                 :    3375260 :   return getAssignment(x).isIntegral();
     125                 :            : }
     126                 :   15411015 : bool ArithVariables::isAuxiliary(ArithVar x) const
     127                 :            : {
     128                 :   15411015 :   return d_vars[x].d_auxiliary;
     129                 :            : }
     130                 :            : 
     131                 :    7842885 : bool ArithVariables::isIntegerInput(ArithVar x) const
     132                 :            : {
     133 [ +  + ][ +  + ]:    7842885 :   return isInteger(x) && !isAuxiliary(x);
     134                 :            : }
     135                 :            : 
     136                 :     708404 : ArithVariables::VarInfo::VarInfo()
     137                 :     708404 :     : d_var(ARITHVAR_SENTINEL),
     138                 :     708404 :       d_assignment(0),
     139                 :     708404 :       d_lb(NullConstraint),
     140                 :     708404 :       d_ub(NullConstraint),
     141                 :     708404 :       d_cmpAssignmentLB(1),
     142                 :     708404 :       d_cmpAssignmentUB(-1),
     143                 :     708404 :       d_pushCount(0),
     144                 :     708404 :       d_type(ArithType::Unset),
     145                 :     708404 :       d_node(Node::null()),
     146                 :     708404 :       d_auxiliary(false)
     147                 :            : {
     148                 :     708404 : }
     149                 :            : 
     150                 :   42845891 : bool ArithVariables::VarInfo::initialized() const
     151                 :            : {
     152                 :   42845891 :   return d_var != ARITHVAR_SENTINEL;
     153                 :            : }
     154                 :            : 
     155                 :     356241 : void ArithVariables::VarInfo::initialize(ArithVar v, Node n, bool aux)
     156                 :            : {
     157 [ -  + ][ -  + ]:     356241 :   Assert(!initialized());
                 [ -  - ]
     158 [ -  + ][ -  + ]:     356241 :   Assert(d_lb == NullConstraint);
                 [ -  - ]
     159 [ -  + ][ -  + ]:     356241 :   Assert(d_ub == NullConstraint);
                 [ -  - ]
     160 [ -  + ][ -  + ]:     356241 :   Assert(d_cmpAssignmentLB > 0);
                 [ -  - ]
     161 [ -  + ][ -  + ]:     356241 :   Assert(d_cmpAssignmentUB < 0);
                 [ -  - ]
     162                 :     356241 :   d_var = v;
     163                 :     356241 :   d_node = n;
     164                 :     356241 :   d_auxiliary = aux;
     165                 :            : 
     166         [ +  + ]:     356241 :   if (d_auxiliary)
     167                 :            :   {
     168                 :            :     // The type computation is not quite accurate for Rationals that are
     169                 :            :     // integral.
     170                 :            :     // We'll use the isIntegral check from the polynomial package instead.
     171                 :     193523 :     Polynomial p = Polynomial::parsePolynomial(n);
     172         [ +  + ]:     193523 :     d_type = p.isIntegral() ? ArithType::Integer : ArithType::Real;
     173                 :     193523 :   }
     174                 :            :   else
     175                 :            :   {
     176         [ +  + ]:     162718 :     d_type = n.getType().isInteger() ? ArithType::Integer : ArithType::Real;
     177                 :            :   }
     178                 :            : 
     179 [ -  + ][ -  + ]:     356241 :   Assert(initialized());
                 [ -  - ]
     180                 :     356241 : }
     181                 :            : 
     182                 :       4096 : void ArithVariables::VarInfo::uninitialize()
     183                 :            : {
     184                 :       4096 :   d_var = ARITHVAR_SENTINEL;
     185                 :       4096 :   d_node = Node::null();
     186                 :       4096 : }
     187                 :            : 
     188                 :   10480335 : bool ArithVariables::VarInfo::setAssignment(const DeltaRational& a,
     189                 :            :                                             BoundsInfo& prev)
     190                 :            : {
     191 [ -  + ][ -  + ]:   10480335 :   Assert(initialized());
                 [ -  - ]
     192                 :   10480335 :   d_assignment = a;
     193                 :            :   int cmpUB =
     194         [ +  + ]:   10480335 :       (d_ub == NullConstraint) ? -1 : d_assignment.cmp(d_ub->getValue());
     195                 :            : 
     196         [ +  + ]:   10480335 :   int cmpLB = (d_lb == NullConstraint) ? 1 : d_assignment.cmp(d_lb->getValue());
     197                 :            : 
     198                 :   10480335 :   bool lbChanged =
     199 [ +  + ][ +  + ]:   10480335 :       cmpLB != d_cmpAssignmentLB && (cmpLB == 0 || d_cmpAssignmentLB == 0);
                 [ +  + ]
     200                 :   10480335 :   bool ubChanged =
     201 [ +  + ][ +  + ]:   10480335 :       cmpUB != d_cmpAssignmentUB && (cmpUB == 0 || d_cmpAssignmentUB == 0);
                 [ +  + ]
     202                 :            : 
     203 [ +  + ][ +  + ]:   10480335 :   if (lbChanged || ubChanged)
     204                 :            :   {
     205                 :    1485899 :     prev = boundsInfo();
     206                 :            :   }
     207                 :            : 
     208                 :   10480335 :   d_cmpAssignmentUB = cmpUB;
     209                 :   10480335 :   d_cmpAssignmentLB = cmpLB;
     210 [ +  + ][ +  + ]:   10480335 :   return lbChanged || ubChanged;
     211                 :            : }
     212                 :            : 
     213                 :       4096 : void ArithVariables::releaseArithVar(ArithVar v)
     214                 :            : {
     215                 :       4096 :   VarInfo& vi = d_vars.get(v);
     216                 :            : 
     217                 :       4096 :   size_t removed CVC5_UNUSED = d_nodeToArithVarMap.erase(vi.d_node);
     218 [ -  + ][ -  + ]:       4096 :   Assert(removed == 1);
                 [ -  - ]
     219                 :            : 
     220                 :       4096 :   vi.uninitialize();
     221                 :            : 
     222         [ +  - ]:       4096 :   if (d_safeAssignment.isKey(v))
     223                 :            :   {
     224                 :       4096 :     d_safeAssignment.remove(v);
     225                 :            :   }
     226         [ +  - ]:       4096 :   if (vi.canBeReclaimed())
     227                 :            :   {
     228                 :       4096 :     d_pool.push_back(v);
     229                 :            :   }
     230                 :            :   else
     231                 :            :   {
     232                 :          0 :     d_released.push_back(v);
     233                 :            :   }
     234                 :       4096 : }
     235                 :            : 
     236                 :    8000834 : bool ArithVariables::VarInfo::setUpperBound(ConstraintP ub, BoundsInfo& prev)
     237                 :            : {
     238 [ -  + ][ -  + ]:    8000834 :   Assert(initialized());
                 [ -  - ]
     239                 :    8000834 :   bool wasNull = d_ub == NullConstraint;
     240                 :    8000834 :   bool isNull = ub == NullConstraint;
     241                 :            : 
     242         [ +  + ]:    8000834 :   int cmpUB = isNull ? -1 : d_assignment.cmp(ub->getValue());
     243                 :    8000834 :   bool ubChanged =
     244                 :            :       (wasNull != isNull)
     245 [ +  + ][ +  + ]:    8000834 :       || (cmpUB != d_cmpAssignmentUB && (cmpUB == 0 || d_cmpAssignmentUB == 0));
         [ +  + ][ +  + ]
     246         [ +  + ]:    8000834 :   if (ubChanged)
     247                 :            :   {
     248                 :    7600526 :     prev = boundsInfo();
     249                 :            :   }
     250                 :    8000834 :   d_ub = ub;
     251                 :    8000834 :   d_cmpAssignmentUB = cmpUB;
     252                 :    8000834 :   return ubChanged;
     253                 :            : }
     254                 :            : 
     255                 :    8426924 : bool ArithVariables::VarInfo::setLowerBound(ConstraintP lb, BoundsInfo& prev)
     256                 :            : {
     257 [ -  + ][ -  + ]:    8426924 :   Assert(initialized());
                 [ -  - ]
     258                 :    8426924 :   bool wasNull = d_lb == NullConstraint;
     259                 :    8426924 :   bool isNull = lb == NullConstraint;
     260                 :            : 
     261         [ +  + ]:    8426924 :   int cmpLB = isNull ? 1 : d_assignment.cmp(lb->getValue());
     262                 :            : 
     263                 :    8426924 :   bool lbChanged =
     264                 :            :       (wasNull != isNull)
     265 [ +  + ][ +  + ]:    8426924 :       || (cmpLB != d_cmpAssignmentLB && (cmpLB == 0 || d_cmpAssignmentLB == 0));
         [ +  + ][ +  + ]
     266         [ +  + ]:    8426924 :   if (lbChanged)
     267                 :            :   {
     268                 :    7618933 :     prev = boundsInfo();
     269                 :            :   }
     270                 :    8426924 :   d_lb = lb;
     271                 :    8426924 :   d_cmpAssignmentLB = cmpLB;
     272                 :    8426924 :   return lbChanged;
     273                 :            : }
     274                 :            : 
     275                 :  122108749 : BoundCounts ArithVariables::VarInfo::atBoundCounts() const
     276                 :            : {
     277         [ +  + ]:  122108749 :   uint32_t lbIndc = (d_cmpAssignmentLB == 0) ? 1 : 0;
     278         [ +  + ]:  122108749 :   uint32_t ubIndc = (d_cmpAssignmentUB == 0) ? 1 : 0;
     279                 :  122108749 :   return BoundCounts(lbIndc, ubIndc);
     280                 :            : }
     281                 :            : 
     282                 :  107847907 : BoundCounts ArithVariables::VarInfo::hasBoundCounts() const
     283                 :            : {
     284         [ +  + ]:  107847907 :   uint32_t lbIndc = (d_lb != NullConstraint) ? 1 : 0;
     285         [ +  + ]:  107847907 :   uint32_t ubIndc = (d_ub != NullConstraint) ? 1 : 0;
     286                 :  107847907 :   return BoundCounts(lbIndc, ubIndc);
     287                 :            : }
     288                 :            : 
     289                 :  107847907 : BoundsInfo ArithVariables::VarInfo::boundsInfo() const
     290                 :            : {
     291                 :  107847907 :   return BoundsInfo(atBoundCounts(), hasBoundCounts());
     292                 :            : }
     293                 :            : 
     294                 :       4096 : bool ArithVariables::VarInfo::canBeReclaimed() const
     295                 :            : {
     296                 :       4096 :   return d_pushCount == 0;
     297                 :            : }
     298                 :            : 
     299                 :          0 : bool ArithVariables::canBeReleased(ArithVar v) const
     300                 :            : {
     301                 :          0 :   return d_vars[v].canBeReclaimed();
     302                 :            : }
     303                 :            : 
     304                 :     352163 : void ArithVariables::attemptToReclaimReleased()
     305                 :            : {
     306                 :     352163 :   size_t readPos = 0, writePos = 0, N = d_released.size();
     307         [ -  + ]:     352163 :   for (; readPos < N; ++readPos)
     308                 :            :   {
     309                 :          0 :     ArithVar v = d_released[readPos];
     310         [ -  - ]:          0 :     if (canBeReleased(v))
     311                 :            :     {
     312                 :          0 :       d_pool.push_back(v);
     313                 :            :     }
     314                 :            :     else
     315                 :            :     {
     316                 :          0 :       d_released[writePos] = v;
     317                 :          0 :       writePos++;
     318                 :            :     }
     319                 :            :   }
     320                 :     352163 :   d_released.resize(writePos);
     321                 :     352163 : }
     322                 :            : 
     323                 :     356241 : ArithVar ArithVariables::allocateVariable()
     324                 :            : {
     325         [ +  + ]:     356241 :   if (d_pool.empty())
     326                 :            :   {
     327                 :     352163 :     attemptToReclaimReleased();
     328                 :            :   }
     329                 :     356241 :   bool reclaim = !d_pool.empty();
     330                 :            : 
     331                 :            :   ArithVar varX;
     332         [ +  + ]:     356241 :   if (reclaim)
     333                 :            :   {
     334                 :       4078 :     varX = d_pool.back();
     335                 :       4078 :     d_pool.pop_back();
     336                 :            :   }
     337                 :            :   else
     338                 :            :   {
     339                 :     352163 :     varX = d_numberOfVariables;
     340                 :     352163 :     ++d_numberOfVariables;
     341                 :            :   }
     342                 :     356241 :   d_vars.set(varX, VarInfo());
     343                 :     356241 :   return varX;
     344                 :            : }
     345                 :            : 
     346                 :     128725 : const Rational& ArithVariables::getDelta()
     347                 :            : {
     348         [ +  + ]:     128725 :   if (!d_deltaIsSafe)
     349                 :            :   {
     350                 :     100273 :     Rational nextDelta = d_deltaComputingFunc();
     351                 :     100273 :     setDelta(nextDelta);
     352                 :     100273 :   }
     353 [ -  + ][ -  + ]:     128725 :   Assert(d_deltaIsSafe);
                 [ -  - ]
     354                 :     128725 :   return d_delta;
     355                 :            : }
     356                 :            : 
     357                 :     249800 : bool ArithVariables::boundsAreEqual(ArithVar x) const
     358                 :            : {
     359 [ +  + ][ +  + ]:     249800 :   if (hasLowerBound(x) && hasUpperBound(x))
                 [ +  + ]
     360                 :            :   {
     361                 :     113118 :     return getUpperBound(x) == getLowerBound(x);
     362                 :            :   }
     363                 :            :   else
     364                 :            :   {
     365                 :     136682 :     return false;
     366                 :            :   }
     367                 :            : }
     368                 :            : 
     369                 :          0 : std::pair<ConstraintP, ConstraintP> ArithVariables::explainEqualBounds(
     370                 :            :     ArithVar x) const
     371                 :            : {
     372                 :          0 :   Assert(boundsAreEqual(x));
     373                 :            : 
     374                 :          0 :   ConstraintP lb = getLowerBoundConstraint(x);
     375                 :          0 :   ConstraintP ub = getUpperBoundConstraint(x);
     376         [ -  - ]:          0 :   if (lb->isEquality())
     377                 :            :   {
     378                 :          0 :     return make_pair(lb, NullConstraint);
     379                 :            :   }
     380         [ -  - ]:          0 :   else if (ub->isEquality())
     381                 :            :   {
     382                 :          0 :     return make_pair(ub, NullConstraint);
     383                 :            :   }
     384                 :            :   else
     385                 :            :   {
     386                 :          0 :     return make_pair(lb, ub);
     387                 :            :   }
     388                 :            : }
     389                 :            : 
     390                 :   10286812 : void ArithVariables::setAssignment(ArithVar x, const DeltaRational& r)
     391                 :            : {
     392         [ +  - ]:   20573624 :   Trace("partial_model") << "pm: updating the assignment to" << x << " now "
     393                 :   10286812 :                          << r << endl;
     394                 :   10286812 :   VarInfo& vi = d_vars.get(x);
     395         [ +  + ]:   10286812 :   if (!d_safeAssignment.isKey(x))
     396                 :            :   {
     397                 :    6087601 :     d_safeAssignment.set(x, vi.d_assignment);
     398                 :            :   }
     399                 :   10286812 :   invalidateDelta();
     400                 :            : 
     401                 :   10286812 :   BoundsInfo prev;
     402         [ +  + ]:   10286812 :   if (vi.setAssignment(r, prev))
     403                 :            :   {
     404                 :    1485899 :     addToBoundQueue(x, prev);
     405                 :            :   }
     406                 :   10286812 : }
     407                 :            : 
     408                 :     193523 : void ArithVariables::setAssignment(ArithVar x,
     409                 :            :                                    const DeltaRational& safe,
     410                 :            :                                    const DeltaRational& r)
     411                 :            : {
     412         [ +  - ]:     387046 :   Trace("partial_model") << "pm: updating the assignment to" << x << " now "
     413                 :     193523 :                          << r << endl;
     414         [ +  + ]:     193523 :   if (safe == r)
     415                 :            :   {
     416         [ -  + ]:     191989 :     if (d_safeAssignment.isKey(x))
     417                 :            :     {
     418                 :          0 :       d_safeAssignment.remove(x);
     419                 :            :     }
     420                 :            :   }
     421                 :            :   else
     422                 :            :   {
     423                 :       1534 :     d_safeAssignment.set(x, safe);
     424                 :            :   }
     425                 :            : 
     426                 :     193523 :   invalidateDelta();
     427                 :     193523 :   VarInfo& vi = d_vars.get(x);
     428                 :     193523 :   BoundsInfo prev;
     429         [ -  + ]:     193523 :   if (vi.setAssignment(r, prev))
     430                 :            :   {
     431                 :          0 :     addToBoundQueue(x, prev);
     432                 :            :   }
     433                 :     193523 : }
     434                 :            : 
     435                 :     356241 : void ArithVariables::initialize(ArithVar x, Node n, bool aux)
     436                 :            : {
     437                 :     356241 :   VarInfo& vi = d_vars.get(x);
     438                 :     356241 :   vi.initialize(x, n, aux);
     439                 :     356241 :   d_nodeToArithVarMap[n] = x;
     440                 :     356241 : }
     441                 :            : 
     442                 :     356241 : ArithVar ArithVariables::allocate(Node n, bool aux)
     443                 :            : {
     444                 :     356241 :   ArithVar v = allocateVariable();
     445                 :     356241 :   initialize(v, n, aux);
     446                 :     356241 :   return v;
     447                 :            : }
     448                 :            : 
     449                 :            : // void ArithVariables::initialize(ArithVar x, const DeltaRational& r){
     450                 :            : //   Assert(x == d_mapSize);
     451                 :            : //   Assert(equalSizes());
     452                 :            : //   ++d_mapSize;
     453                 :            : 
     454                 :            : //   // Is worth mentioning that this is not strictly necessary, but this
     455                 :            : //   maintains the internal invariant
     456                 :            : //   // that when d_assignment is set this gets set.
     457                 :            : //   invalidateDelta();
     458                 :            : //   d_assignment.push_back( r );
     459                 :            : 
     460                 :            : //   d_boundRel.push_back(BetweenBounds);
     461                 :            : 
     462                 :            : //   d_ubc.push_back(NullConstraint);
     463                 :            : //   d_lbc.push_back(NullConstraint);
     464                 :            : // }
     465                 :            : 
     466                 :            : /** Must know that the bound exists both calling this! */
     467                 :   12518339 : const DeltaRational& ArithVariables::getUpperBound(ArithVar x) const
     468                 :            : {
     469 [ -  + ][ -  + ]:   12518339 :   Assert(inMaps(x));
                 [ -  - ]
     470 [ -  + ][ -  + ]:   12518339 :   Assert(hasUpperBound(x));
                 [ -  - ]
     471                 :            : 
     472                 :   12518339 :   return getUpperBoundConstraint(x)->getValue();
     473                 :            : }
     474                 :            : 
     475                 :   13504524 : const DeltaRational& ArithVariables::getLowerBound(ArithVar x) const
     476                 :            : {
     477 [ -  + ][ -  + ]:   13504524 :   Assert(inMaps(x));
                 [ -  - ]
     478 [ -  + ][ -  + ]:   13504524 :   Assert(hasLowerBound(x));
                 [ -  - ]
     479                 :            : 
     480                 :   13504524 :   return getLowerBoundConstraint(x)->getValue();
     481                 :            : }
     482                 :            : 
     483                 :          0 : const DeltaRational& ArithVariables::getSafeAssignment(ArithVar x) const
     484                 :            : {
     485                 :          0 :   Assert(inMaps(x));
     486         [ -  - ]:          0 :   if (d_safeAssignment.isKey(x))
     487                 :            :   {
     488                 :          0 :     return d_safeAssignment[x];
     489                 :            :   }
     490                 :            :   else
     491                 :            :   {
     492                 :          0 :     return d_vars[x].d_assignment;
     493                 :            :   }
     494                 :            : }
     495                 :            : 
     496                 :    1566604 : const DeltaRational& ArithVariables::getAssignment(ArithVar x, bool safe) const
     497                 :            : {
     498 [ -  + ][ -  + ]:    1566604 :   Assert(inMaps(x));
                 [ -  - ]
     499 [ +  + ][ +  + ]:    1566604 :   if (safe && d_safeAssignment.isKey(x))
                 [ +  + ]
     500                 :            :   {
     501                 :       1605 :     return d_safeAssignment[x];
     502                 :            :   }
     503                 :            :   else
     504                 :            :   {
     505                 :    1564999 :     return d_vars[x].d_assignment;
     506                 :            :   }
     507                 :            : }
     508                 :            : 
     509                 :   41764897 : const DeltaRational& ArithVariables::getAssignment(ArithVar x) const
     510                 :            : {
     511 [ -  + ][ -  + ]:   41764897 :   Assert(inMaps(x));
                 [ -  - ]
     512                 :   41764897 :   return d_vars[x].d_assignment;
     513                 :            : }
     514                 :            : 
     515                 :    4213462 : void ArithVariables::setLowerBoundConstraint(ConstraintP c)
     516                 :            : {
     517         [ -  + ]:    4213462 :   AssertArgument(c != NullConstraint,
     518                 :            :                  "Cannot set a lower bound to NullConstraint.");
     519 [ +  + ][ -  + ]:    4213462 :   AssertArgument(c->isEquality() || c->isLowerBound(),
                 [ -  + ]
     520                 :            :                  "Constraint type must be set to an equality or UpperBound.");
     521                 :    4213462 :   ArithVar x = c->getVariable();
     522         [ +  - ]:    8426924 :   Trace("partial_model") << "setLowerBoundConstraint(" << x << ":" << c << ")"
     523                 :    4213462 :                          << endl;
     524 [ -  + ][ -  + ]:    4213462 :   Assert(inMaps(x));
                 [ -  - ]
     525 [ -  + ][ -  + ]:    4213462 :   Assert(greaterThanLowerBound(x, c->getValue()));
                 [ -  - ]
     526                 :            : 
     527                 :    4213462 :   invalidateDelta();
     528                 :    4213462 :   VarInfo& vi = d_vars.get(x);
     529                 :    4213462 :   pushLowerBound(vi);
     530                 :    4213462 :   BoundsInfo prev;
     531         [ +  + ]:    4213462 :   if (vi.setLowerBound(c, prev))
     532                 :            :   {
     533                 :    3812730 :     addToBoundQueue(x, prev);
     534                 :            :   }
     535                 :    4213462 : }
     536                 :            : 
     537                 :    4000417 : void ArithVariables::setUpperBoundConstraint(ConstraintP c)
     538                 :            : {
     539         [ -  + ]:    4000417 :   AssertArgument(c != NullConstraint,
     540                 :            :                  "Cannot set a upper bound to NullConstraint.");
     541 [ +  + ][ -  + ]:    4000417 :   AssertArgument(c->isEquality() || c->isUpperBound(),
                 [ -  + ]
     542                 :            :                  "Constraint type must be set to an equality or UpperBound.");
     543                 :            : 
     544                 :    4000417 :   ArithVar x = c->getVariable();
     545         [ +  - ]:    8000834 :   Trace("partial_model") << "setUpperBoundConstraint(" << x << ":" << c << ")"
     546                 :    4000417 :                          << endl;
     547 [ -  + ][ -  + ]:    4000417 :   Assert(inMaps(x));
                 [ -  - ]
     548 [ -  + ][ -  + ]:    4000417 :   Assert(lessThanUpperBound(x, c->getValue()));
                 [ -  - ]
     549                 :            : 
     550                 :    4000417 :   invalidateDelta();
     551                 :    4000417 :   VarInfo& vi = d_vars.get(x);
     552                 :    4000417 :   pushUpperBound(vi);
     553                 :    4000417 :   BoundsInfo prev;
     554         [ +  + ]:    4000417 :   if (vi.setUpperBound(c, prev))
     555                 :            :   {
     556                 :    3802030 :     addToBoundQueue(x, prev);
     557                 :            :   }
     558                 :    4000417 : }
     559                 :            : 
     560                 :   14804710 : int ArithVariables::cmpToLowerBound(ArithVar x, const DeltaRational& c) const
     561                 :            : {
     562         [ +  + ]:   14804710 :   if (!hasLowerBound(x))
     563                 :            :   {
     564                 :            :     // l = -\intfy
     565                 :            :     // ? c < -\infty |-  _|_
     566                 :    9974839 :     return 1;
     567                 :            :   }
     568                 :            :   else
     569                 :            :   {
     570                 :    4829871 :     return c.cmp(getLowerBound(x));
     571                 :            :   }
     572                 :            : }
     573                 :            : 
     574                 :   13628685 : int ArithVariables::cmpToUpperBound(ArithVar x, const DeltaRational& c) const
     575                 :            : {
     576         [ +  + ]:   13628685 :   if (!hasUpperBound(x))
     577                 :            :   {
     578                 :            :     // u = \intfy
     579                 :            :     //  ? c > \infty |-  _|_
     580                 :    9684606 :     return -1;
     581                 :            :   }
     582                 :            :   else
     583                 :            :   {
     584                 :    3944079 :     return c.cmp(getUpperBound(x));
     585                 :            :   }
     586                 :            : }
     587                 :            : 
     588                 :          0 : bool ArithVariables::equalsLowerBound(ArithVar x, const DeltaRational& c)
     589                 :            : {
     590         [ -  - ]:          0 :   if (!hasLowerBound(x))
     591                 :            :   {
     592                 :          0 :     return false;
     593                 :            :   }
     594                 :            :   else
     595                 :            :   {
     596                 :          0 :     return c == getLowerBound(x);
     597                 :            :   }
     598                 :            : }
     599                 :          0 : bool ArithVariables::equalsUpperBound(ArithVar x, const DeltaRational& c)
     600                 :            : {
     601         [ -  - ]:          0 :   if (!hasUpperBound(x))
     602                 :            :   {
     603                 :          0 :     return false;
     604                 :            :   }
     605                 :            :   else
     606                 :            :   {
     607                 :          0 :     return c == getUpperBound(x);
     608                 :            :   }
     609                 :            : }
     610                 :            : 
     611                 :    3284266 : bool ArithVariables::hasEitherBound(ArithVar x) const
     612                 :            : {
     613 [ +  + ][ +  + ]:    3284266 :   return hasLowerBound(x) || hasUpperBound(x);
     614                 :            : }
     615                 :            : 
     616                 :    1979716 : bool ArithVariables::strictlyBelowUpperBound(ArithVar x) const
     617                 :            : {
     618                 :    1979716 :   return d_vars[x].d_cmpAssignmentUB < 0;
     619                 :            : }
     620                 :            : 
     621                 :    3400491 : bool ArithVariables::strictlyAboveLowerBound(ArithVar x) const
     622                 :            : {
     623                 :    3400491 :   return d_vars[x].d_cmpAssignmentLB > 0;
     624                 :            : }
     625                 :            : 
     626                 :   28272818 : bool ArithVariables::assignmentIsConsistent(ArithVar x) const
     627                 :            : {
     628 [ +  + ][ +  + ]:   28272818 :   return d_vars[x].d_cmpAssignmentLB >= 0 && d_vars[x].d_cmpAssignmentUB <= 0;
     629                 :            : }
     630                 :            : 
     631                 :    3528954 : void ArithVariables::clearSafeAssignments(bool revert)
     632                 :            : {
     633 [ +  + ][ -  + ]:    3528954 :   if (revert && !d_safeAssignment.empty())
                 [ -  + ]
     634                 :            :   {
     635                 :          0 :     invalidateDelta();
     636                 :            :   }
     637                 :            : 
     638         [ +  + ]:    9613993 :   while (!d_safeAssignment.empty())
     639                 :            :   {
     640                 :    6085039 :     ArithVar atBack = d_safeAssignment.back();
     641         [ -  + ]:    6085039 :     if (revert)
     642                 :            :     {
     643                 :          0 :       VarInfo& vi = d_vars.get(atBack);
     644                 :          0 :       BoundsInfo prev;
     645         [ -  - ]:          0 :       if (vi.setAssignment(d_safeAssignment[atBack], prev))
     646                 :            :       {
     647                 :          0 :         addToBoundQueue(atBack, prev);
     648                 :            :       }
     649                 :            :     }
     650                 :    6085039 :     d_safeAssignment.pop_back();
     651                 :            :   }
     652                 :    3528954 : }
     653                 :            : 
     654                 :      87229 : void ArithVariables::revertAssignmentChanges() { clearSafeAssignments(true); }
     655                 :    3441725 : void ArithVariables::commitAssignmentChanges() { clearSafeAssignments(false); }
     656                 :            : 
     657                 :    2016802 : bool ArithVariables::lowerBoundIsZero(ArithVar x)
     658                 :            : {
     659 [ +  + ][ +  + ]:    2016802 :   return hasLowerBound(x) && getLowerBound(x).sgn() == 0;
     660                 :            : }
     661                 :            : 
     662                 :    2057664 : bool ArithVariables::upperBoundIsZero(ArithVar x)
     663                 :            : {
     664 [ +  + ][ +  + ]:    2057664 :   return hasUpperBound(x) && getUpperBound(x).sgn() == 0;
     665                 :            : }
     666                 :            : 
     667                 :          0 : void ArithVariables::printEntireModel(std::ostream& out) const
     668                 :            : {
     669                 :          0 :   out << "---Printing Model ---" << std::endl;
     670         [ -  - ]:          0 :   for (var_iterator i = var_begin(), iend = var_end(); i != iend; ++i)
     671                 :            :   {
     672                 :          0 :     printModel(*i, out);
     673                 :            :   }
     674                 :          0 :   out << "---Done Model ---" << std::endl;
     675                 :          0 : }
     676                 :            : 
     677                 :          0 : void ArithVariables::printModel(ArithVar x, std::ostream& out) const
     678                 :            : {
     679                 :          0 :   out << "model" << x << ": " << asNode(x) << " " << getAssignment(x) << " ";
     680         [ -  - ]:          0 :   if (!hasLowerBound(x))
     681                 :            :   {
     682                 :          0 :     out << "no lb ";
     683                 :            :   }
     684                 :            :   else
     685                 :            :   {
     686                 :          0 :     out << getLowerBound(x) << " ";
     687                 :          0 :     out << getLowerBoundConstraint(x) << " ";
     688                 :            :   }
     689         [ -  - ]:          0 :   if (!hasUpperBound(x))
     690                 :            :   {
     691                 :          0 :     out << "no ub ";
     692                 :            :   }
     693                 :            :   else
     694                 :            :   {
     695                 :          0 :     out << getUpperBound(x) << " ";
     696                 :          0 :     out << getUpperBoundConstraint(x) << " ";
     697                 :            :   }
     698                 :            : 
     699 [ -  - ][ -  - ]:          0 :   if (isInteger(x) && !integralAssignment(x))
                 [ -  - ]
     700                 :            :   {
     701                 :          0 :     out << "(not an integer)" << endl;
     702                 :            :   }
     703                 :          0 :   out << endl;
     704                 :          0 : }
     705                 :            : 
     706                 :          0 : void ArithVariables::printModel(ArithVar x) const
     707                 :            : {
     708         [ -  - ]:          0 :   printModel(x, Trace("model"));
     709                 :          0 : }
     710                 :            : 
     711                 :    4000417 : void ArithVariables::pushUpperBound(VarInfo& vi)
     712                 :            : {
     713                 :    4000417 :   ++vi.d_pushCount;
     714                 :    4000417 :   d_ubRevertHistory.push_back(make_pair(vi.d_var, vi.d_ub));
     715                 :    4000417 : }
     716                 :    4213462 : void ArithVariables::pushLowerBound(VarInfo& vi)
     717                 :            : {
     718                 :    4213462 :   ++vi.d_pushCount;
     719                 :    4213462 :   d_lbRevertHistory.push_back(make_pair(vi.d_var, vi.d_lb));
     720                 :    4213462 : }
     721                 :            : 
     722                 :    4000417 : void ArithVariables::popUpperBound(AVCPair* c)
     723                 :            : {
     724                 :    4000417 :   ArithVar x = c->first;
     725                 :    4000417 :   VarInfo& vi = d_vars.get(x);
     726                 :    4000417 :   BoundsInfo prev;
     727         [ +  + ]:    4000417 :   if (vi.setUpperBound(c->second, prev))
     728                 :            :   {
     729                 :    3798496 :     addToBoundQueue(x, prev);
     730                 :            :   }
     731                 :    4000417 :   --vi.d_pushCount;
     732                 :    4000417 : }
     733                 :            : 
     734                 :    4213462 : void ArithVariables::popLowerBound(AVCPair* c)
     735                 :            : {
     736                 :    4213462 :   ArithVar x = c->first;
     737                 :    4213462 :   VarInfo& vi = d_vars.get(x);
     738                 :    4213462 :   BoundsInfo prev;
     739         [ +  + ]:    4213462 :   if (vi.setLowerBound(c->second, prev))
     740                 :            :   {
     741                 :    3806203 :     addToBoundQueue(x, prev);
     742                 :            :   }
     743                 :    4213462 :   --vi.d_pushCount;
     744                 :    4213462 : }
     745                 :            : 
     746                 :   16705358 : void ArithVariables::addToBoundQueue(ArithVar v, const BoundsInfo& prev)
     747                 :            : {
     748 [ +  + ][ +  + ]:   16705358 :   if (d_enqueueingBoundCounts && !d_boundsQueue.isKey(v))
                 [ +  + ]
     749                 :            :   {
     750                 :    9612750 :     d_boundsQueue.set(v, prev);
     751                 :            :   }
     752                 :   16705358 : }
     753                 :            : 
     754                 :    1006778 : BoundsInfo ArithVariables::selectBoundsInfo(ArithVar v, bool old) const
     755                 :            : {
     756 [ +  - ][ +  + ]:    1006778 :   if (old && d_boundsQueue.isKey(v))
                 [ +  + ]
     757                 :            :   {
     758                 :      23263 :     return d_boundsQueue[v];
     759                 :            :   }
     760                 :            :   else
     761                 :            :   {
     762                 :     983515 :     return boundsInfo(v);
     763                 :            :   }
     764                 :            : }
     765                 :            : 
     766                 :   33404784 : bool ArithVariables::boundsQueueEmpty() const { return d_boundsQueue.empty(); }
     767                 :            : 
     768                 :    5254052 : void ArithVariables::processBoundsQueue(BoundUpdateCallback& changed)
     769                 :            : {
     770         [ +  + ]:   14668411 :   while (!boundsQueueEmpty())
     771                 :            :   {
     772                 :    9414359 :     ArithVar v = d_boundsQueue.back();
     773                 :    9414359 :     BoundsInfo prev = d_boundsQueue[v];
     774                 :    9414359 :     d_boundsQueue.pop_back();
     775                 :    9414359 :     BoundsInfo curr = boundsInfo(v);
     776         [ +  + ]:    9414359 :     if (prev != curr)
     777                 :            :     {
     778                 :    9076685 :       changed(v, prev);
     779                 :            :     }
     780                 :            :   }
     781                 :    5254052 : }
     782                 :            : 
     783                 :   19166071 : void ArithVariables::invalidateDelta() { d_deltaIsSafe = false; }
     784                 :            : 
     785                 :     100273 : void ArithVariables::setDelta(const Rational& d)
     786                 :            : {
     787                 :     100273 :   d_delta = d;
     788                 :     100273 :   d_deltaIsSafe = true;
     789                 :     100273 : }
     790                 :            : 
     791                 :    3295680 : void ArithVariables::startQueueingBoundCounts()
     792                 :            : {
     793                 :    3295680 :   d_enqueueingBoundCounts = true;
     794                 :    3295680 : }
     795                 :    3295680 : void ArithVariables::stopQueueingBoundCounts()
     796                 :            : {
     797                 :    3295680 :   d_enqueueingBoundCounts = false;
     798                 :    3295680 : }
     799                 :            : 
     800                 :   77568243 : bool ArithVariables::inMaps(ArithVar x) const
     801                 :            : {
     802                 :   77568243 :   return x < getNumberOfVariables();
     803                 :            : }
     804                 :            : 
     805                 :      28663 : ArithVariables::LowerBoundCleanUp::LowerBoundCleanUp(ArithVariables* pm)
     806                 :      28663 :     : d_pm(pm)
     807                 :            : {
     808                 :      28663 : }
     809                 :    4213462 : void ArithVariables::LowerBoundCleanUp::operator()(AVCPair& p)
     810                 :            : {
     811                 :    4213462 :   d_pm->popLowerBound(&p);
     812                 :    4213462 : }
     813                 :            : 
     814                 :      28663 : ArithVariables::UpperBoundCleanUp::UpperBoundCleanUp(ArithVariables* pm)
     815                 :      28663 :     : d_pm(pm)
     816                 :            : {
     817                 :      28663 : }
     818                 :    4000417 : void ArithVariables::UpperBoundCleanUp::operator()(AVCPair& p)
     819                 :            : {
     820                 :    4000417 :   d_pm->popUpperBound(&p);
     821                 :    4000417 : }
     822                 :            : 
     823                 :            : }  // namespace arith::linear
     824                 :            : }  // namespace theory
     825                 :            : }  // namespace cvc5::internal

Generated by: LCOV version 1.14