LCOV - code coverage report
Current view: top level - buildbot/coverage/build/src/theory/arith/linear - infer_bounds.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 29 141 20.6 %
Date: 2026-09-01 09:48:01 Functions: 12 39 30.8 %
Branches: 3 47 6.4 %

           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/infer_bounds.h"
      17                 :            : 
      18                 :            : #include "theory/rewriter.h"
      19                 :            : 
      20                 :            : using namespace cvc5::internal::kind;
      21                 :            : 
      22                 :            : namespace cvc5::internal {
      23                 :            : namespace theory {
      24                 :            : namespace arith::linear {
      25                 :            : 
      26                 :            : using namespace inferbounds;
      27                 :            : 
      28                 :          0 : InferBoundAlgorithm::InferBoundAlgorithm() : d_alg(None) {}
      29                 :            : 
      30                 :      26488 : InferBoundAlgorithm::InferBoundAlgorithm(Algorithms a) : d_alg(a)
      31                 :            : {
      32 [ -  + ][ -  + ]:      26488 :   Assert(a != Simplex);
                 [ -  - ]
      33                 :      26488 : }
      34                 :            : 
      35                 :          0 : InferBoundAlgorithm::InferBoundAlgorithm(
      36                 :          0 :     const std::optional<int>& simplexRounds)
      37                 :          0 :     : d_alg(Simplex), d_simplexRounds(simplexRounds)
      38                 :            : {
      39                 :          0 : }
      40                 :            : 
      41                 :      50526 : Algorithms InferBoundAlgorithm::getAlgorithm() const { return d_alg; }
      42                 :            : 
      43                 :          0 : const std::optional<int>& InferBoundAlgorithm::getSimplexRounds() const
      44                 :            : {
      45                 :          0 :   Assert(getAlgorithm() == Simplex);
      46                 :          0 :   return d_simplexRounds;
      47                 :            : }
      48                 :            : 
      49                 :      13244 : InferBoundAlgorithm InferBoundAlgorithm::mkLookup()
      50                 :            : {
      51                 :      13244 :   return InferBoundAlgorithm(Lookup);
      52                 :            : }
      53                 :            : 
      54                 :      13244 : InferBoundAlgorithm InferBoundAlgorithm::mkRowSum()
      55                 :            : {
      56                 :      13244 :   return InferBoundAlgorithm(RowSum);
      57                 :            : }
      58                 :            : 
      59                 :          0 : InferBoundAlgorithm InferBoundAlgorithm::mkSimplex(
      60                 :            :     const std::optional<int>& rounds)
      61                 :            : {
      62                 :          0 :   return InferBoundAlgorithm(rounds);
      63                 :            : }
      64                 :            : 
      65                 :      13244 : ArithEntailmentCheckParameters::ArithEntailmentCheckParameters()
      66                 :      13244 :     : d_algorithms()
      67                 :            : {
      68                 :      13244 : }
      69                 :            : 
      70                 :      13244 : ArithEntailmentCheckParameters::~ArithEntailmentCheckParameters() {}
      71                 :            : 
      72                 :      13244 : void ArithEntailmentCheckParameters::addLookupRowSumAlgorithms()
      73                 :            : {
      74                 :      13244 :   addAlgorithm(InferBoundAlgorithm::mkLookup());
      75                 :      13244 :   addAlgorithm(InferBoundAlgorithm::mkRowSum());
      76                 :      13244 : }
      77                 :            : 
      78                 :      26488 : void ArithEntailmentCheckParameters::addAlgorithm(
      79                 :            :     const inferbounds::InferBoundAlgorithm& alg)
      80                 :            : {
      81                 :      26488 :   d_algorithms.push_back(alg);
      82                 :      26488 : }
      83                 :            : 
      84                 :            : ArithEntailmentCheckParameters::const_iterator
      85                 :      13244 : ArithEntailmentCheckParameters::begin() const
      86                 :            : {
      87                 :      13244 :   return d_algorithms.begin();
      88                 :            : }
      89                 :            : 
      90                 :            : ArithEntailmentCheckParameters::const_iterator
      91                 :      13244 : ArithEntailmentCheckParameters::end() const
      92                 :            : {
      93                 :      13244 :   return d_algorithms.end();
      94                 :            : }
      95                 :            : 
      96                 :          0 : InferBoundsResult::InferBoundsResult()
      97                 :          0 :     : d_foundBound(false),
      98                 :          0 :       d_budgetExhausted(false),
      99                 :          0 :       d_boundIsProvenOpt(false),
     100                 :          0 :       d_inconsistentState(false),
     101                 :          0 :       d_reachedThreshold(false),
     102                 :          0 :       d_value(false),
     103                 :          0 :       d_term(Node::null()),
     104                 :          0 :       d_upperBound(true),
     105                 :          0 :       d_explanation(Node::null())
     106                 :            : {
     107                 :          0 : }
     108                 :            : 
     109                 :          0 : InferBoundsResult::InferBoundsResult(Node term, bool ub)
     110                 :          0 :     : d_foundBound(false),
     111                 :          0 :       d_budgetExhausted(false),
     112                 :          0 :       d_boundIsProvenOpt(false),
     113                 :          0 :       d_inconsistentState(false),
     114                 :          0 :       d_reachedThreshold(false),
     115                 :          0 :       d_value(false),
     116                 :          0 :       d_term(term),
     117                 :          0 :       d_upperBound(ub),
     118                 :          0 :       d_explanation(Node::null())
     119                 :            : {
     120                 :          0 : }
     121                 :            : 
     122                 :          0 : bool InferBoundsResult::foundBound() const { return d_foundBound; }
     123                 :          0 : bool InferBoundsResult::boundIsOptimal() const { return d_boundIsProvenOpt; }
     124                 :          0 : bool InferBoundsResult::inconsistentState() const
     125                 :            : {
     126                 :          0 :   return d_inconsistentState;
     127                 :            : }
     128                 :            : 
     129                 :          0 : bool InferBoundsResult::boundIsInteger() const
     130                 :            : {
     131 [ -  - ][ -  - ]:          0 :   return foundBound() && d_value.isIntegral();
     132                 :            : }
     133                 :            : 
     134                 :          0 : bool InferBoundsResult::boundIsRational() const
     135                 :            : {
     136 [ -  - ][ -  - ]:          0 :   return foundBound() && d_value.infinitesimalIsZero();
     137                 :            : }
     138                 :            : 
     139                 :          0 : Integer InferBoundsResult::valueAsInteger() const
     140                 :            : {
     141                 :          0 :   Assert(boundIsInteger());
     142                 :          0 :   return getValue().floor();
     143                 :            : }
     144                 :          0 : const Rational& InferBoundsResult::valueAsRational() const
     145                 :            : {
     146                 :          0 :   Assert(boundIsRational());
     147                 :          0 :   return getValue().getNoninfinitesimalPart();
     148                 :            : }
     149                 :            : 
     150                 :          0 : const DeltaRational& InferBoundsResult::getValue() const { return d_value; }
     151                 :            : 
     152                 :          0 : Node InferBoundsResult::getTerm() const { return d_term; }
     153                 :            : 
     154                 :          0 : Node InferBoundsResult::getLiteral() const
     155                 :            : {
     156                 :          0 :   const Rational& q = getValue().getNoninfinitesimalPart();
     157                 :          0 :   NodeManager* nm = d_term.getNodeManager();
     158                 :          0 :   Node qnode = nm->mkConstReal(q);
     159                 :            : 
     160                 :            :   Kind k;
     161         [ -  - ]:          0 :   if (d_upperBound)
     162                 :            :   {
     163                 :            :     // x <= q + c*delta
     164                 :          0 :     Assert(getValue().infinitesimalSgn() <= 0);
     165         [ -  - ]:          0 :     k = boundIsRational() ? Kind::LEQ : Kind::LT;
     166                 :            :   }
     167                 :            :   else
     168                 :            :   {
     169                 :            :     // x >= q + c*delta
     170                 :          0 :     Assert(getValue().infinitesimalSgn() >= 0);
     171         [ -  - ]:          0 :     k = boundIsRational() ? Kind::GEQ : Kind::GT;
     172                 :            :   }
     173                 :          0 :   return nm->mkNode(k, getTerm(), qnode);
     174                 :          0 : }
     175                 :            : 
     176                 :            : /* If there is a bound, this is a node that explains the bound. */
     177                 :          0 : Node InferBoundsResult::getExplanation() const { return d_explanation; }
     178                 :            : 
     179                 :          0 : void InferBoundsResult::setBound(const DeltaRational& dr, Node exp)
     180                 :            : {
     181                 :          0 :   d_foundBound = true;
     182                 :          0 :   d_value = dr;
     183                 :          0 :   d_explanation = exp;
     184                 :          0 : }
     185                 :            : 
     186                 :          0 : void InferBoundsResult::setBudgetExhausted() { d_budgetExhausted = true; }
     187                 :          0 : void InferBoundsResult::setReachedThreshold() { d_reachedThreshold = true; }
     188                 :          0 : void InferBoundsResult::setIsOptimal() { d_boundIsProvenOpt = true; }
     189                 :          0 : void InferBoundsResult::setInconsistent() { d_inconsistentState = true; }
     190                 :            : 
     191                 :          0 : bool InferBoundsResult::thresholdWasReached() const
     192                 :            : {
     193                 :          0 :   return d_reachedThreshold;
     194                 :            : }
     195                 :          0 : bool InferBoundsResult::budgetIsExhausted() const { return d_budgetExhausted; }
     196                 :            : 
     197                 :          0 : std::ostream& operator<<(std::ostream& os, const InferBoundsResult& ibr)
     198                 :            : {
     199                 :          0 :   os << "{InferBoundsResult " << std::endl;
     200                 :          0 :   os << "on " << ibr.getTerm() << ", ";
     201         [ -  - ]:          0 :   if (ibr.findUpperBound())
     202                 :            :   {
     203                 :          0 :     os << "find upper bound, ";
     204                 :            :   }
     205                 :            :   else
     206                 :            :   {
     207                 :          0 :     os << "find lower bound, ";
     208                 :            :   }
     209         [ -  - ]:          0 :   if (ibr.foundBound())
     210                 :            :   {
     211                 :          0 :     os << "found a bound: ";
     212         [ -  - ]:          0 :     if (ibr.boundIsInteger())
     213                 :            :     {
     214                 :          0 :       os << ibr.valueAsInteger() << "(int), ";
     215                 :            :     }
     216         [ -  - ]:          0 :     else if (ibr.boundIsRational())
     217                 :            :     {
     218                 :          0 :       os << ibr.valueAsRational() << "(rat), ";
     219                 :            :     }
     220                 :            :     else
     221                 :            :     {
     222                 :          0 :       os << ibr.getValue() << "(extended), ";
     223                 :            :     }
     224                 :            : 
     225                 :          0 :     os << "as term " << ibr.getLiteral() << ", ";
     226                 :          0 :     os << "explanation " << ibr.getExplanation() << ", ";
     227                 :            :   }
     228                 :            :   else
     229                 :            :   {
     230                 :          0 :     os << "did not find a bound, ";
     231                 :            :   }
     232                 :            : 
     233         [ -  - ]:          0 :   if (ibr.boundIsOptimal())
     234                 :            :   {
     235                 :          0 :     os << "(opt), ";
     236                 :            :   }
     237                 :            : 
     238         [ -  - ]:          0 :   if (ibr.inconsistentState())
     239                 :            :   {
     240                 :          0 :     os << "(inconsistent), ";
     241                 :            :   }
     242         [ -  - ]:          0 :   if (ibr.budgetIsExhausted())
     243                 :            :   {
     244                 :          0 :     os << "(budget exhausted), ";
     245                 :            :   }
     246         [ -  - ]:          0 :   if (ibr.thresholdWasReached())
     247                 :            :   {
     248                 :          0 :     os << "(reached threshold), ";
     249                 :            :   }
     250                 :          0 :   os << "}";
     251                 :          0 :   return os;
     252                 :            : }
     253                 :            : 
     254                 :      13244 : ArithEntailmentCheckSideEffects::ArithEntailmentCheckSideEffects()
     255                 :      13244 :     : d_simplexSideEffects(nullptr)
     256                 :            : {
     257                 :      13244 : }
     258                 :            : 
     259                 :      13244 : ArithEntailmentCheckSideEffects::~ArithEntailmentCheckSideEffects()
     260                 :            : {
     261         [ -  + ]:      13244 :   if (d_simplexSideEffects != nullptr)
     262                 :            :   {
     263         [ -  - ]:          0 :     delete d_simplexSideEffects;
     264                 :          0 :     d_simplexSideEffects = nullptr;
     265                 :            :   }
     266                 :      13244 : }
     267                 :            : 
     268                 :          0 : InferBoundsResult& ArithEntailmentCheckSideEffects::getSimplexSideEffects()
     269                 :            : {
     270         [ -  - ]:          0 :   if (d_simplexSideEffects == nullptr)
     271                 :            :   {
     272                 :          0 :     d_simplexSideEffects = new InferBoundsResult;
     273                 :            :   }
     274                 :          0 :   return *d_simplexSideEffects;
     275                 :            : }
     276                 :            : 
     277                 :            : namespace inferbounds { /* namespace arith */
     278                 :            : 
     279                 :          0 : std::ostream& operator<<(std::ostream& os, const Algorithms a)
     280                 :            : {
     281 [ -  - ][ -  - ]:          0 :   switch (a)
                    [ - ]
     282                 :            :   {
     283                 :          0 :     case None: os << "AlgNone"; break;
     284                 :          0 :     case Lookup: os << "AlgLookup"; break;
     285                 :          0 :     case RowSum: os << "AlgRowSum"; break;
     286                 :          0 :     case Simplex: os << "AlgSimplex"; break;
     287                 :          0 :     default: Unhandled();
     288                 :            :   }
     289                 :            : 
     290                 :          0 :   return os;
     291                 :            : }
     292                 :            : 
     293                 :            : } /* namespace inferbounds */
     294                 :            : 
     295                 :            : }  // namespace arith::linear
     296                 :            : } /* namespace theory */
     297                 :            : }  // namespace cvc5::internal

Generated by: LCOV version 1.14