LCOV - code coverage report
Current view: top level - buildbot/coverage/build/src/theory/arith/linear - linear_equality.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 622 828 75.1 %
Date: 2026-05-02 10:46:03 Functions: 38 49 77.6 %
Branches: 474 926 51.2 %

           Branch data     Line data    Source code
       1                 :            : /******************************************************************************
       2                 :            :  * This file is part of the cvc5 project.
       3                 :            :  *
       4                 :            :  * Copyright (c) 2009-2026 by the authors listed in the file AUTHORS
       5                 :            :  * in the top-level source directory and their institutional affiliations.
       6                 :            :  * All rights reserved.  See the file COPYING in the top-level source
       7                 :            :  * directory for licensing information.
       8                 :            :  * ****************************************************************************
       9                 :            :  *
      10                 :            :  * This implements the LinearEqualityModule.
      11                 :            :  */
      12                 :            : #include "theory/arith/linear/linear_equality.h"
      13                 :            : 
      14                 :            : #include "base/output.h"
      15                 :            : #include "theory/arith/linear/constraint.h"
      16                 :            : #include "util/statistics_registry.h"
      17                 :            : 
      18                 :            : using namespace std;
      19                 :            : 
      20                 :            : namespace cvc5::internal {
      21                 :            : namespace theory {
      22                 :            : namespace arith::linear {
      23                 :            : 
      24                 :            : /* Explicitly instatiate these functions. */
      25                 :            : 
      26                 :            : template ArithVar LinearEqualityModule::selectSlack<true>(
      27                 :            :     ArithVar x_i, VarPreferenceFunction pf) const;
      28                 :            : template ArithVar LinearEqualityModule::selectSlack<false>(
      29                 :            :     ArithVar x_i, VarPreferenceFunction pf) const;
      30                 :            : 
      31                 :            : template bool LinearEqualityModule::preferWitness<true>(
      32                 :            :     const UpdateInfo& a, const UpdateInfo& b) const;
      33                 :            : template bool LinearEqualityModule::preferWitness<false>(
      34                 :            :     const UpdateInfo& a, const UpdateInfo& b) const;
      35                 :            : 
      36                 :          0 : void Border::output(std::ostream& out) const
      37                 :            : {
      38                 :            :   out << "{Border"
      39                 :          0 :       << ", " << d_bound->getVariable() << ", " << d_bound->getValue() << ", "
      40                 :          0 :       << d_diff << ", " << d_areFixing << ", " << d_upperbound;
      41         [ -  - ]:          0 :   if (ownBorder())
      42                 :            :   {
      43                 :          0 :     out << ", ownBorder";
      44                 :            :   }
      45                 :            :   else
      46                 :            :   {
      47                 :          0 :     out << ", " << d_entry->getCoefficient();
      48                 :            :   }
      49                 :          0 :   out << ", " << d_bound << "}";
      50                 :          0 : }
      51                 :            : 
      52                 :      51016 : LinearEqualityModule::LinearEqualityModule(StatisticsRegistry& sr,
      53                 :            :                                            ArithVariables& vars,
      54                 :            :                                            Tableau& t,
      55                 :            :                                            BoundInfoMap& boundsTracking,
      56                 :      51016 :                                            BasicVarModelUpdateCallBack f)
      57                 :      51016 :     : d_variables(vars),
      58                 :      51016 :       d_tableau(t),
      59                 :      51016 :       d_basicVariableUpdates(f),
      60                 :      51016 :       d_increasing(1),
      61                 :      51016 :       d_decreasing(-1),
      62                 :      51016 :       d_upperBoundDifference(),
      63                 :      51016 :       d_lowerBoundDifference(),
      64                 :      51016 :       d_one(1),
      65                 :      51016 :       d_negOne(-1),
      66                 :      51016 :       d_btracking(boundsTracking),
      67                 :      51016 :       d_areTracking(false),
      68                 :      51016 :       d_trackCallback(this),
      69                 :      51016 :       d_statistics(sr)
      70                 :            : {
      71                 :      51016 : }
      72                 :            : 
      73                 :      51016 : LinearEqualityModule::Statistics::Statistics(StatisticsRegistry& sr)
      74                 :      51016 :     : d_statPivots(sr.registerInt("theory::arith::pivots")),
      75                 :      51016 :       d_statUpdates(sr.registerInt("theory::arith::updates")),
      76                 :      51016 :       d_pivotTime(sr.registerTimer("theory::arith::pivotTime")),
      77                 :      51016 :       d_adjTime(sr.registerTimer("theory::arith::adjTime")),
      78                 :      51016 :       d_weakeningAttempts(sr.registerInt("theory::arith::weakening::attempts")),
      79                 :      51016 :       d_weakeningSuccesses(sr.registerInt("theory::arith::weakening::success")),
      80                 :      51016 :       d_weakenings(sr.registerInt("theory::arith::weakening::total")),
      81                 :      51016 :       d_weakenTime(sr.registerTimer("theory::arith::weakening::time")),
      82                 :      51016 :       d_forceTime(sr.registerTimer("theory::arith::forcing::time"))
      83                 :            : {
      84                 :      51016 : }
      85                 :            : 
      86                 :    9026703 : void LinearEqualityModule::includeBoundUpdate(ArithVar v,
      87                 :            :                                               const BoundsInfo& prev)
      88                 :            : {
      89 [ -  + ][ -  + ]:    9026703 :   Assert(!d_areTracking);
                 [ -  - ]
      90                 :            : 
      91                 :    9026703 :   BoundsInfo curr = d_variables.boundsInfo(v);
      92                 :            : 
      93 [ -  + ][ -  + ]:    9026703 :   Assert(prev != curr);
                 [ -  - ]
      94                 :    9026703 :   Tableau::ColIterator basicIter = d_tableau.colIterator(v);
      95         [ +  + ]:   54242429 :   for (; !basicIter.atEnd(); ++basicIter)
      96                 :            :   {
      97                 :   45215726 :     const Tableau::Entry& entry = *basicIter;
      98 [ -  + ][ -  + ]:   45215726 :     Assert(entry.getColVar() == v);
                 [ -  - ]
      99                 :   45215726 :     int a_ijSgn = entry.getCoefficient().sgn();
     100                 :            : 
     101                 :   45215726 :     RowIndex ridx = entry.getRowIndex();
     102                 :   45215726 :     BoundsInfo& counts = d_btracking.get(ridx);
     103         [ +  - ]:   90431452 :     Trace("includeBoundUpdate")
     104                 :   45215726 :         << d_tableau.rowIndexToBasic(ridx) << " " << counts << " to ";
     105                 :   45215726 :     counts.addInChange(a_ijSgn, prev, curr);
     106         [ +  - ]:   45215726 :     Trace("includeBoundUpdate") << counts << " " << a_ijSgn << std::endl;
     107                 :            :   }
     108                 :    9026703 : }
     109                 :            : 
     110                 :          0 : void LinearEqualityModule::updateMany(const DenseMap<DeltaRational>& many)
     111                 :            : {
     112                 :          0 :   for (DenseMap<DeltaRational>::const_iterator i = many.begin(),
     113                 :          0 :                                                i_end = many.end();
     114         [ -  - ]:          0 :        i != i_end;
     115                 :          0 :        ++i)
     116                 :            :   {
     117                 :          0 :     ArithVar nb = *i;
     118         [ -  - ]:          0 :     if (!d_tableau.isBasic(nb))
     119                 :            :     {
     120                 :          0 :       Assert(!d_tableau.isBasic(nb));
     121                 :          0 :       const DeltaRational& newValue = many[nb];
     122         [ -  - ]:          0 :       if (newValue != d_variables.getAssignment(nb))
     123                 :            :       {
     124         [ -  - ]:          0 :         Trace("arith::updateMany")
     125                 :          0 :             << "updateMany:" << nb << " " << d_variables.getAssignment(nb)
     126                 :          0 :             << " to " << newValue << endl;
     127                 :          0 :         update(nb, newValue);
     128                 :            :       }
     129                 :            :     }
     130                 :            :   }
     131                 :          0 : }
     132                 :            : 
     133                 :          0 : void LinearEqualityModule::applySolution(
     134                 :            :     const DenseSet& newBasis, const DenseMap<DeltaRational>& newValues)
     135                 :            : {
     136                 :          0 :   forceNewBasis(newBasis);
     137                 :          0 :   updateMany(newValues);
     138                 :          0 : }
     139                 :            : 
     140                 :          0 : void LinearEqualityModule::forceNewBasis(const DenseSet& newBasis)
     141                 :            : {
     142                 :          0 :   TimerStat::CodeTimer codeTimer(d_statistics.d_forceTime);
     143                 :          0 :   DenseSet needsToBeAdded;
     144                 :          0 :   for (DenseSet::const_iterator i = newBasis.begin(), i_end = newBasis.end();
     145         [ -  - ]:          0 :        i != i_end;
     146                 :          0 :        ++i)
     147                 :            :   {
     148                 :          0 :     ArithVar b = *i;
     149         [ -  - ]:          0 :     if (!d_tableau.isBasic(b))
     150                 :            :     {
     151                 :          0 :       needsToBeAdded.add(b);
     152                 :            :     }
     153                 :            :   }
     154                 :            : 
     155         [ -  - ]:          0 :   while (!needsToBeAdded.empty())
     156                 :            :   {
     157                 :          0 :     ArithVar toRemove = ARITHVAR_SENTINEL;
     158                 :          0 :     ArithVar toAdd = ARITHVAR_SENTINEL;
     159                 :          0 :     DenseSet::const_iterator i = needsToBeAdded.begin(),
     160                 :          0 :                              i_end = needsToBeAdded.end();
     161 [ -  - ][ -  - ]:          0 :     for (; toAdd == ARITHVAR_SENTINEL && i != i_end; ++i)
                 [ -  - ]
     162                 :            :     {
     163                 :          0 :       ArithVar v = *i;
     164                 :            : 
     165                 :          0 :       Tableau::ColIterator colIter = d_tableau.colIterator(v);
     166         [ -  - ]:          0 :       for (; !colIter.atEnd(); ++colIter)
     167                 :            :       {
     168                 :          0 :         const Tableau::Entry& entry = *colIter;
     169                 :          0 :         Assert(entry.getColVar() == v);
     170                 :          0 :         ArithVar b = d_tableau.rowIndexToBasic(entry.getRowIndex());
     171         [ -  - ]:          0 :         if (!newBasis.isMember(b))
     172                 :            :         {
     173                 :          0 :           toAdd = v;
     174                 :          0 :           if (toRemove == ARITHVAR_SENTINEL
     175                 :          0 :               || d_tableau.basicRowLength(toRemove)
     176         [ -  - ]:          0 :                      > d_tableau.basicRowLength(b))
     177                 :            :           {
     178                 :          0 :             toRemove = b;
     179                 :            :           }
     180                 :            :         }
     181                 :            :       }
     182                 :            :     }
     183                 :          0 :     Assert(toRemove != ARITHVAR_SENTINEL);
     184                 :          0 :     Assert(toAdd != ARITHVAR_SENTINEL);
     185                 :            : 
     186         [ -  - ]:          0 :     Trace("arith::forceNewBasis") << toRemove << " " << toAdd << endl;
     187                 :          0 :     d_tableau.pivot(toRemove, toAdd, d_trackCallback);
     188                 :          0 :     d_basicVariableUpdates(toAdd);
     189                 :            : 
     190         [ -  - ]:          0 :     Trace("arith::forceNewBasis") << needsToBeAdded.size() << "to go" << endl;
     191                 :          0 :     needsToBeAdded.remove(toAdd);
     192                 :            :   }
     193                 :          0 : }
     194                 :            : 
     195                 :     305673 : void LinearEqualityModule::updateUntracked(ArithVar x_i, const DeltaRational& v)
     196                 :            : {
     197 [ -  + ][ -  + ]:     305673 :   Assert(!d_tableau.isBasic(x_i));
                 [ -  - ]
     198 [ -  + ][ -  + ]:     305673 :   Assert(!d_areTracking);
                 [ -  - ]
     199                 :     305673 :   const DeltaRational& assignment_x_i = d_variables.getAssignment(x_i);
     200                 :     305673 :   ++(d_statistics.d_statUpdates);
     201                 :            : 
     202         [ +  - ]:     611346 :   Trace("arith") << "update " << x_i << ": " << assignment_x_i << "|-> " << v
     203                 :     305673 :                  << endl;
     204                 :     305673 :   DeltaRational diff = v - assignment_x_i;
     205                 :            : 
     206                 :     305673 :   Tableau::ColIterator colIter = d_tableau.colIterator(x_i);
     207         [ +  + ]:    3314178 :   for (; !colIter.atEnd(); ++colIter)
     208                 :            :   {
     209                 :    3008505 :     const Tableau::Entry& entry = *colIter;
     210 [ -  + ][ -  + ]:    3008505 :     Assert(entry.getColVar() == x_i);
                 [ -  - ]
     211                 :            : 
     212                 :    3008505 :     ArithVar x_j = d_tableau.rowIndexToBasic(entry.getRowIndex());
     213                 :    3008505 :     const Rational& a_ji = entry.getCoefficient();
     214                 :            : 
     215                 :    3008505 :     const DeltaRational& assignment = d_variables.getAssignment(x_j);
     216                 :    3008505 :     DeltaRational nAssignment = assignment + (diff * a_ji);
     217                 :    3008505 :     d_variables.setAssignment(x_j, nAssignment);
     218                 :            : 
     219                 :    3008505 :     d_basicVariableUpdates(x_j);
     220                 :    3008505 :   }
     221                 :            : 
     222                 :     305673 :   d_variables.setAssignment(x_i, v);
     223                 :            : 
     224         [ -  + ]:     305673 :   if (TraceIsOn("paranoid:check_tableau"))
     225                 :            :   {
     226                 :          0 :     debugCheckTableau();
     227                 :            :   }
     228                 :     305673 : }
     229                 :            : 
     230                 :     341437 : void LinearEqualityModule::updateTracked(ArithVar x_i, const DeltaRational& v)
     231                 :            : {
     232                 :     341437 :   TimerStat::CodeTimer codeTimer(d_statistics.d_adjTime);
     233                 :            : 
     234 [ -  + ][ -  + ]:     341437 :   Assert(!d_tableau.isBasic(x_i));
                 [ -  - ]
     235 [ -  + ][ -  + ]:     341437 :   Assert(d_areTracking);
                 [ -  - ]
     236                 :            : 
     237                 :     341437 :   ++(d_statistics.d_statUpdates);
     238                 :            : 
     239                 :     341437 :   DeltaRational diff = v - d_variables.getAssignment(x_i);
     240         [ +  - ]:     682874 :   Trace("arith") << "update " << x_i << ": " << d_variables.getAssignment(x_i)
     241                 :     341437 :                  << "|-> " << v << endl;
     242                 :            : 
     243                 :     341437 :   BoundCounts before = d_variables.atBoundCounts(x_i);
     244                 :     341437 :   d_variables.setAssignment(x_i, v);
     245                 :     341437 :   BoundCounts after = d_variables.atBoundCounts(x_i);
     246                 :            : 
     247                 :     341437 :   bool anyChange = before != after;
     248                 :            : 
     249                 :     341437 :   Tableau::ColIterator colIter = d_tableau.colIterator(x_i);
     250         [ +  + ]:    6960642 :   for (; !colIter.atEnd(); ++colIter)
     251                 :            :   {
     252                 :    6619205 :     const Tableau::Entry& entry = *colIter;
     253 [ -  + ][ -  + ]:    6619205 :     Assert(entry.getColVar() == x_i);
                 [ -  - ]
     254                 :            : 
     255                 :    6619205 :     RowIndex ridx = entry.getRowIndex();
     256                 :    6619205 :     ArithVar x_j = d_tableau.rowIndexToBasic(ridx);
     257                 :    6619205 :     const Rational& a_ji = entry.getCoefficient();
     258                 :            : 
     259                 :    6619205 :     const DeltaRational& assignment = d_variables.getAssignment(x_j);
     260                 :    6619205 :     DeltaRational nAssignment = assignment + (diff * a_ji);
     261         [ +  - ]:   13238410 :     Trace("update") << x_j << " " << a_ji << assignment << " -> " << nAssignment
     262                 :    6619205 :                     << endl;
     263                 :    6619205 :     BoundCounts xjBefore = d_variables.atBoundCounts(x_j);
     264                 :    6619205 :     d_variables.setAssignment(x_j, nAssignment);
     265                 :    6619205 :     BoundCounts xjAfter = d_variables.atBoundCounts(x_j);
     266                 :            : 
     267 [ -  + ][ -  + ]:    6619205 :     Assert(rowIndexIsTracked(ridx));
                 [ -  - ]
     268                 :    6619205 :     BoundsInfo& next_bc_k = d_btracking.get(ridx);
     269         [ +  + ]:    6619205 :     if (anyChange)
     270                 :            :     {
     271                 :    4561076 :       next_bc_k.addInAtBoundChange(a_ji.sgn(), before, after);
     272                 :            :     }
     273         [ +  + ]:    6619205 :     if (xjBefore != xjAfter)
     274                 :            :     {
     275                 :     816702 :       next_bc_k.addInAtBoundChange(-1, xjBefore, xjAfter);
     276                 :            :     }
     277                 :            : 
     278                 :    6619205 :     d_basicVariableUpdates(x_j);
     279                 :    6619205 :   }
     280                 :            : 
     281         [ -  + ]:     341437 :   if (TraceIsOn("paranoid:check_tableau"))
     282                 :            :   {
     283                 :          0 :     debugCheckTableau();
     284                 :            :   }
     285                 :     341437 : }
     286                 :            : 
     287                 :     341292 : void LinearEqualityModule::pivotAndUpdate(ArithVar x_i,
     288                 :            :                                           ArithVar x_j,
     289                 :            :                                           const DeltaRational& x_i_value)
     290                 :            : {
     291 [ -  + ][ -  + ]:     341292 :   Assert(x_i != x_j);
                 [ -  - ]
     292                 :            : 
     293                 :     341292 :   TimerStat::CodeTimer codeTimer(d_statistics.d_pivotTime);
     294                 :            : 
     295         [ -  + ]:     341292 :   if (TraceIsOn("arith::tracking::pre"))
     296                 :            :   {
     297         [ -  - ]:          0 :     Trace("arith::tracking") << "pre update" << endl;
     298                 :          0 :     debugCheckTracking();
     299                 :            :   }
     300                 :            : 
     301         [ -  + ]:     341292 :   if (TraceIsOn("arith::simplex:row"))
     302                 :            :   {
     303                 :          0 :     debugPivot(x_i, x_j);
     304                 :            :   }
     305                 :            : 
     306                 :     341292 :   RowIndex ridx = d_tableau.basicToRowIndex(x_i);
     307                 :     341292 :   const Tableau::Entry& entry_ij = d_tableau.findEntry(ridx, x_j);
     308 [ -  + ][ -  + ]:     341292 :   Assert(!entry_ij.blank());
                 [ -  - ]
     309                 :            : 
     310                 :     341292 :   const Rational& a_ij = entry_ij.getCoefficient();
     311                 :     341292 :   const DeltaRational& betaX_i = d_variables.getAssignment(x_i);
     312                 :     341292 :   DeltaRational theta = (x_i_value - betaX_i) / a_ij;
     313                 :     341292 :   DeltaRational x_j_value = d_variables.getAssignment(x_j) + theta;
     314                 :            : 
     315                 :     341292 :   updateTracked(x_j, x_j_value);
     316                 :            : 
     317         [ -  + ]:     341292 :   if (TraceIsOn("arith::tracking::mid"))
     318                 :            :   {
     319         [ -  - ]:          0 :     Trace("arith::tracking") << "postupdate prepivot" << endl;
     320                 :          0 :     debugCheckTracking();
     321                 :            :   }
     322                 :            : 
     323                 :            :   // Pivots
     324                 :     341292 :   ++(d_statistics.d_statPivots);
     325                 :            : 
     326                 :     341292 :   d_tableau.pivot(x_i, x_j, d_trackCallback);
     327                 :            : 
     328         [ -  + ]:     341292 :   if (TraceIsOn("arith::tracking::post"))
     329                 :            :   {
     330         [ -  - ]:          0 :     Trace("arith::tracking") << "postpivot" << endl;
     331                 :          0 :     debugCheckTracking();
     332                 :            :   }
     333                 :            : 
     334                 :     341292 :   d_basicVariableUpdates(x_j);
     335                 :            : 
     336         [ -  + ]:     341292 :   if (TraceIsOn("matrix"))
     337                 :            :   {
     338                 :          0 :     d_tableau.printMatrix();
     339                 :            :   }
     340                 :     341292 : }
     341                 :            : 
     342                 :     108256 : uint32_t LinearEqualityModule::updateProduct(const UpdateInfo& inf) const
     343                 :            : {
     344                 :     108256 :   uint32_t colLen = d_tableau.getColLength(inf.nonbasic());
     345         [ +  + ]:     108256 :   if (inf.describesPivot())
     346                 :            :   {
     347 [ -  + ][ -  + ]:     106696 :     Assert(inf.leaving() != inf.nonbasic());
                 [ -  - ]
     348                 :     106696 :     return colLen + d_tableau.basicRowLength(inf.leaving());
     349                 :            :   }
     350                 :            :   else
     351                 :            :   {
     352                 :       1560 :     return colLen;
     353                 :            :   }
     354                 :            : }
     355                 :            : 
     356                 :          0 : void LinearEqualityModule::debugCheckTracking()
     357                 :            : {
     358                 :          0 :   Tableau::BasicIterator basicIter = d_tableau.beginBasic(),
     359                 :          0 :                          endIter = d_tableau.endBasic();
     360         [ -  - ]:          0 :   for (; basicIter != endIter; ++basicIter)
     361                 :            :   {
     362                 :          0 :     ArithVar basic = *basicIter;
     363         [ -  - ]:          0 :     Trace("arith::tracking") << "arith::tracking row basic: " << basic << endl;
     364                 :            : 
     365                 :          0 :     for (Tableau::RowIterator iter = d_tableau.basicRowIterator(basic);
     366                 :          0 :          !iter.atEnd() && TraceIsOn("arith::tracking");
     367                 :          0 :          ++iter)
     368                 :            :     {
     369                 :          0 :       const Tableau::Entry& entry = *iter;
     370                 :            : 
     371                 :          0 :       ArithVar var = entry.getColVar();
     372                 :          0 :       const Rational& coeff = entry.getCoefficient();
     373                 :          0 :       DeltaRational beta = d_variables.getAssignment(var);
     374         [ -  - ]:          0 :       Trace("arith::tracking")
     375                 :          0 :           << var << " " << d_variables.boundsInfo(var) << " " << beta << coeff;
     376         [ -  - ]:          0 :       if (d_variables.hasLowerBound(var))
     377                 :            :       {
     378         [ -  - ]:          0 :         Trace("arith::tracking")
     379                 :          0 :             << "(lb " << d_variables.getLowerBound(var) << ")";
     380                 :            :       }
     381         [ -  - ]:          0 :       if (d_variables.hasUpperBound(var))
     382                 :            :       {
     383         [ -  - ]:          0 :         Trace("arith::tracking")
     384                 :          0 :             << "(up " << d_variables.getUpperBound(var) << ")";
     385                 :            :       }
     386         [ -  - ]:          0 :       Trace("arith::tracking") << endl;
     387                 :          0 :     }
     388         [ -  - ]:          0 :     Trace("arith::tracking") << "end row" << endl;
     389                 :            : 
     390         [ -  - ]:          0 :     if (basicIsTracked(basic))
     391                 :            :     {
     392                 :          0 :       RowIndex ridx = d_tableau.basicToRowIndex(basic);
     393                 :          0 :       BoundsInfo computed = computeRowBoundInfo(ridx, false);
     394         [ -  - ]:          0 :       Trace("arith::tracking") << "computed " << computed << " tracking "
     395                 :          0 :                                << d_btracking[ridx] << endl;
     396                 :          0 :       Assert(computed == d_btracking[ridx]);
     397                 :            :     }
     398                 :            :   }
     399                 :          0 : }
     400                 :            : 
     401                 :          0 : void LinearEqualityModule::debugPivot(ArithVar x_i, ArithVar x_j)
     402                 :            : {
     403         [ -  - ]:          0 :   Trace("arith::pivot") << "debugPivot(" << x_i << "|->" << x_j << ")" << endl;
     404                 :            : 
     405                 :          0 :   for (Tableau::RowIterator iter = d_tableau.basicRowIterator(x_i);
     406         [ -  - ]:          0 :        !iter.atEnd();
     407                 :          0 :        ++iter)
     408                 :            :   {
     409                 :          0 :     const Tableau::Entry& entry = *iter;
     410                 :            : 
     411                 :          0 :     ArithVar var = entry.getColVar();
     412                 :          0 :     const Rational& coeff = entry.getCoefficient();
     413                 :          0 :     DeltaRational beta = d_variables.getAssignment(var);
     414         [ -  - ]:          0 :     Trace("arith::pivot") << var << beta << coeff;
     415         [ -  - ]:          0 :     if (d_variables.hasLowerBound(var))
     416                 :            :     {
     417         [ -  - ]:          0 :       Trace("arith::pivot") << "(lb " << d_variables.getLowerBound(var) << ")";
     418                 :            :     }
     419         [ -  - ]:          0 :     if (d_variables.hasUpperBound(var))
     420                 :            :     {
     421         [ -  - ]:          0 :       Trace("arith::pivot") << "(up " << d_variables.getUpperBound(var) << ")";
     422                 :            :     }
     423         [ -  - ]:          0 :     Trace("arith::pivot") << endl;
     424                 :          0 :   }
     425         [ -  - ]:          0 :   Trace("arith::pivot") << "end row" << endl;
     426                 :          0 : }
     427                 :            : 
     428                 :            : /**
     429                 :            :  * This check is quite expensive.
     430                 :            :  * It should be wrapped in a TraceIsOn() guard.
     431                 :            :  *   if(TraceIsOn("paranoid:check_tableau")){
     432                 :            :  *      checkTableau();
     433                 :            :  *   }
     434                 :            :  */
     435                 :          0 : void LinearEqualityModule::debugCheckTableau()
     436                 :            : {
     437                 :          0 :   Tableau::BasicIterator basicIter = d_tableau.beginBasic(),
     438                 :          0 :                          endIter = d_tableau.endBasic();
     439         [ -  - ]:          0 :   for (; basicIter != endIter; ++basicIter)
     440                 :            :   {
     441                 :          0 :     ArithVar basic = *basicIter;
     442                 :          0 :     DeltaRational sum;
     443         [ -  - ]:          0 :     Trace("paranoid:check_tableau") << "starting row" << basic << endl;
     444                 :          0 :     Tableau::RowIterator nonbasicIter = d_tableau.basicRowIterator(basic);
     445         [ -  - ]:          0 :     for (; !nonbasicIter.atEnd(); ++nonbasicIter)
     446                 :            :     {
     447                 :          0 :       const Tableau::Entry& entry = *nonbasicIter;
     448                 :          0 :       ArithVar nonbasic = entry.getColVar();
     449         [ -  - ]:          0 :       if (basic == nonbasic) continue;
     450                 :            : 
     451                 :          0 :       const Rational& coeff = entry.getCoefficient();
     452                 :          0 :       DeltaRational beta = d_variables.getAssignment(nonbasic);
     453         [ -  - ]:          0 :       Trace("paranoid:check_tableau") << nonbasic << beta << coeff << endl;
     454                 :          0 :       sum = sum + (beta * coeff);
     455                 :          0 :     }
     456                 :          0 :     DeltaRational shouldBe = d_variables.getAssignment(basic);
     457         [ -  - ]:          0 :     Trace("paranoid:check_tableau")
     458                 :          0 :         << "ending row" << sum << "," << shouldBe << endl;
     459                 :            : 
     460                 :          0 :     Assert(sum == shouldBe);
     461                 :          0 :   }
     462                 :          0 : }
     463                 :            : 
     464                 :     813028 : DeltaRational LinearEqualityModule::computeRowBound(RowIndex ridx,
     465                 :            :                                                     bool rowUb,
     466                 :            :                                                     ArithVar skip) const
     467                 :            : {
     468                 :    1626056 :   DeltaRational sum(0, 0);
     469         [ +  + ]:    5426419 :   for (Tableau::RowIterator i = d_tableau.ridRowIterator(ridx); !i.atEnd(); ++i)
     470                 :            :   {
     471                 :    4613391 :     const Tableau::Entry& entry = (*i);
     472                 :    4613391 :     ArithVar v = entry.getColVar();
     473         [ +  + ]:    4613391 :     if (v == skip)
     474                 :            :     {
     475                 :     600763 :       continue;
     476                 :            :     }
     477                 :            : 
     478                 :    4012628 :     const Rational& coeff = entry.getCoefficient();
     479                 :    4012628 :     bool vUb = (rowUb == (coeff.sgn() > 0));
     480                 :            : 
     481                 :            :     const DeltaRational& bound =
     482         [ +  + ]:    4012628 :         vUb ? d_variables.getUpperBound(v) : d_variables.getLowerBound(v);
     483                 :            : 
     484                 :    4012628 :     DeltaRational diff = bound * coeff;
     485                 :    4012628 :     sum = sum + diff;
     486                 :    4012628 :   }
     487                 :     813028 :   return sum;
     488                 :          0 : }
     489                 :            : 
     490                 :            : /**
     491                 :            :  * Computes the value of a basic variable using the current assignment.
     492                 :            :  */
     493                 :     398398 : DeltaRational LinearEqualityModule::computeRowValue(ArithVar x,
     494                 :            :                                                     bool useSafe) const
     495                 :            : {
     496 [ -  + ][ -  + ]:     398398 :   Assert(d_tableau.isBasic(x));
                 [ -  - ]
     497                 :     398398 :   DeltaRational sum(0);
     498                 :            : 
     499         [ +  + ]:    2378714 :   for (Tableau::RowIterator i = d_tableau.basicRowIterator(x); !i.atEnd(); ++i)
     500                 :            :   {
     501                 :    1980316 :     const Tableau::Entry& entry = (*i);
     502                 :    1980316 :     ArithVar nonbasic = entry.getColVar();
     503         [ +  + ]:    1980316 :     if (nonbasic == x) continue;
     504                 :    1581918 :     const Rational& coeff = entry.getCoefficient();
     505                 :            : 
     506                 :            :     const DeltaRational& assignment =
     507                 :    1581918 :         d_variables.getAssignment(nonbasic, useSafe);
     508                 :    1581918 :     sum = sum + (assignment * coeff);
     509                 :            :   }
     510                 :     398398 :   return sum;
     511                 :          0 : }
     512                 :            : 
     513                 :    7945179 : const Tableau::Entry* LinearEqualityModule::rowLacksBound(RowIndex ridx,
     514                 :            :                                                           bool rowUb,
     515                 :            :                                                           ArithVar skip)
     516                 :            : {
     517                 :    7945179 :   Tableau::RowIterator iter = d_tableau.ridRowIterator(ridx);
     518         [ +  + ]:   42228659 :   for (; !iter.atEnd(); ++iter)
     519                 :            :   {
     520                 :   42228051 :     const Tableau::Entry& entry = *iter;
     521                 :            : 
     522                 :   42228051 :     ArithVar var = entry.getColVar();
     523         [ +  + ]:   42228051 :     if (var == skip)
     524                 :            :     {
     525                 :        906 :       continue;
     526                 :            :     }
     527                 :            : 
     528                 :   42227145 :     int sgn = entry.getCoefficient().sgn();
     529                 :   42227145 :     bool selectUb = (rowUb == (sgn > 0));
     530         [ +  + ]:   42227145 :     bool hasBound = selectUb ? d_variables.hasUpperBound(var)
     531                 :   20832814 :                              : d_variables.hasLowerBound(var);
     532         [ +  + ]:   42227145 :     if (!hasBound)
     533                 :            :     {
     534                 :    7944571 :       return &entry;
     535                 :            :     }
     536                 :            :   }
     537                 :        608 :   return nullptr;
     538                 :            : }
     539                 :            : 
     540                 :        106 : void LinearEqualityModule::propagateBasicFromRow(NodeManager* nm,
     541                 :            :                                                  ConstraintP c,
     542                 :            :                                                  bool produceProofs)
     543                 :            : {
     544 [ -  + ][ -  + ]:        106 :   Assert(c != NullConstraint);
                 [ -  - ]
     545 [ +  + ][ +  - ]:        106 :   Assert(c->isUpperBound() || c->isLowerBound());
         [ -  + ][ -  + ]
                 [ -  - ]
     546 [ -  + ][ -  + ]:        106 :   Assert(!c->assertedToTheTheory());
                 [ -  - ]
     547 [ -  + ][ -  + ]:        106 :   Assert(!c->hasProof());
                 [ -  - ]
     548                 :            : 
     549                 :        106 :   bool upperBound = c->isUpperBound();
     550                 :        106 :   ArithVar basic = c->getVariable();
     551                 :        106 :   RowIndex ridx = d_tableau.basicToRowIndex(basic);
     552                 :            : 
     553                 :        106 :   ConstraintCPVec bounds;
     554         [ -  + ]:        106 :   RationalVectorP coeffs = produceProofs ? new RationalVector() : nullptr;
     555                 :        106 :   propagateRow(bounds, ridx, upperBound, c, coeffs);
     556                 :        106 :   c->impliedByFarkas(nm, bounds, coeffs, false);
     557                 :        106 :   c->tryToPropagate();
     558                 :            : 
     559         [ -  + ]:        106 :   if (coeffs != RationalVectorPSentinel)
     560                 :            :   {
     561         [ -  - ]:          0 :     delete coeffs;
     562                 :            :   }
     563                 :        106 : }
     564                 :            : 
     565                 :            : /* An explanation of the farkas coefficients.
     566                 :            :  *
     567                 :            :  * We are proving c using the other variables on the row.
     568                 :            :  * The proof is in terms of the other constraints and the negation of c, ~c.
     569                 :            :  *
     570                 :            :  * A row has the form:
     571                 :            :  *   sum a_i * x_i  = 0
     572                 :            :  * or
     573                 :            :  *   sx + sum r y + sum q z = 0
     574                 :            :  * where r > 0 and q < 0.
     575                 :            :  *
     576                 :            :  * If rowUp, we are proving c
     577                 :            :  *   g = sum r u_y + sum q l_z
     578                 :            :  *   and c is entailed by -sx <= g
     579                 :            :  * If !rowUp, we are proving c
     580                 :            :  *   g = sum r l_y + sum q u_z
     581                 :            :  *   and c is entailed by -sx >= g
     582                 :            :  *
     583                 :            :  *             | s     | c         | ~c       | u_i     | l_i
     584                 :            :  *   if  rowUp | s > 0 | x >= -g/s | x < -g/s | a_i > 0 | a_i < 0
     585                 :            :  *   if  rowUp | s < 0 | x <= -g/s | x > -g/s | a_i > 0 | a_i < 0
     586                 :            :  *   if !rowUp | s > 0 | x <= -g/s | x > -g/s | a_i < 0 | a_i > 0
     587                 :            :  *   if !rowUp | s < 0 | x >= -g/s | x < -g/s | a_i < 0 | a_i > 0
     588                 :            :  *
     589                 :            :  *
     590                 :            :  * Thus we treat !rowUp as multiplying the row by -1 and rowUp as 1
     591                 :            :  * for the entire row.
     592                 :            :  */
     593                 :     232985 : void LinearEqualityModule::propagateRow(ConstraintCPVec& into,
     594                 :            :                                         RowIndex ridx,
     595                 :            :                                         bool rowUp,
     596                 :            :                                         ConstraintP c,
     597                 :            :                                         RationalVectorP farkas)
     598                 :            : {
     599 [ -  + ][ -  + ]:     232985 :   Assert(!c->assertedToTheTheory());
                 [ -  - ]
     600 [ -  + ][ -  + ]:     232985 :   Assert(c->canBePropagated());
                 [ -  - ]
     601 [ -  + ][ -  + ]:     232985 :   Assert(!c->hasProof());
                 [ -  - ]
     602                 :            : 
     603         [ +  + ]:     232985 :   if (farkas != RationalVectorPSentinel)
     604                 :            :   {
     605 [ -  + ][ -  + ]:     157701 :     Assert(farkas->empty());
                 [ -  - ]
     606                 :     157701 :     farkas->push_back(Rational(0));
     607                 :            :   }
     608                 :            : 
     609                 :     232985 :   ArithVar v = c->getVariable();
     610         [ +  - ]:     465970 :   Trace("arith::propagateRow")
     611                 :          0 :       << "LinearEqualityModule::propagateRow(" << ridx << ", " << rowUp << ", "
     612                 :     232985 :       << v << ") start" << endl;
     613                 :            : 
     614         [ +  + ]:     232985 :   const Rational& multiple = rowUp ? d_one : d_negOne;
     615                 :            : 
     616         [ +  - ]:     232985 :   Trace("arith::propagateRow") << "multiple: " << multiple << endl;
     617                 :            : 
     618                 :     232985 :   Tableau::RowIterator iter = d_tableau.ridRowIterator(ridx);
     619         [ +  + ]:    1844219 :   for (; !iter.atEnd(); ++iter)
     620                 :            :   {
     621                 :    1611234 :     const Tableau::Entry& entry = *iter;
     622                 :    1611234 :     ArithVar nonbasic = entry.getColVar();
     623                 :    1611234 :     const Rational& a_ij = entry.getCoefficient();
     624                 :    1611234 :     int sgn = a_ij.sgn();
     625 [ -  + ][ -  + ]:    1611234 :     Assert(sgn != 0);
                 [ -  - ]
     626         [ +  + ]:    1611234 :     bool selectUb = rowUp ? (sgn > 0) : (sgn < 0);
     627                 :            : 
     628 [ +  + ][ +  + ]:    1611234 :     Assert(nonbasic != v || (rowUp && a_ij.sgn() > 0 && c->isLowerBound())
         [ +  + ][ +  + ]
         [ +  - ][ +  + ]
         [ +  + ][ +  + ]
         [ +  - ][ +  + ]
         [ +  - ][ +  + ]
         [ +  + ][ +  - ]
         [ +  + ][ +  + ]
         [ +  - ][ +  + ]
         [ +  + ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ -  + ][ -  + ]
                 [ -  - ]
     629                 :            :            || (rowUp && a_ij.sgn() < 0 && c->isUpperBound())
     630                 :            :            || (!rowUp && a_ij.sgn() > 0 && c->isUpperBound())
     631                 :            :            || (!rowUp && a_ij.sgn() < 0 && c->isLowerBound()));
     632                 :            : 
     633         [ -  + ]:    1611234 :     if (TraceIsOn("arith::propagateRow"))
     634                 :            :     {
     635         [ -  - ]:          0 :       if (nonbasic == v)
     636                 :            :       {
     637         [ -  - ]:          0 :         Trace("arith::propagateRow")
     638                 :          0 :             << "(target) " << rowUp << " " << a_ij.sgn() << " "
     639                 :          0 :             << c->isLowerBound() << " " << c->isUpperBound() << endl;
     640                 :            : 
     641         [ -  - ]:          0 :         Trace("arith::propagateRow") << "(target) ";
     642                 :            :       }
     643         [ -  - ]:          0 :       Trace("arith::propagateRow")
     644                 :          0 :           << "propagateRow " << a_ij << " * " << nonbasic;
     645                 :            :     }
     646                 :            : 
     647         [ +  + ]:    1611234 :     if (nonbasic == v)
     648                 :            :     {
     649         [ +  + ]:     232985 :       if (farkas != RationalVectorPSentinel)
     650                 :            :       {
     651 [ -  + ][ -  + ]:     157701 :         Assert(farkas->front().isZero());
                 [ -  - ]
     652                 :     157701 :         Rational multAij = multiple * a_ij;
     653         [ +  - ]:     157701 :         Trace("arith::propagateRow") << "(" << multAij << ") ";
     654                 :     157701 :         farkas->front() = multAij;
     655                 :     157701 :       }
     656                 :            : 
     657         [ +  - ]:     232985 :       Trace("arith::propagateRow") << c << endl;
     658                 :            :     }
     659                 :            :     else
     660                 :            :     {
     661                 :            :       ConstraintCP bound = selectUb
     662                 :     647567 :                                ? d_variables.getUpperBoundConstraint(nonbasic)
     663         [ +  + ]:    1378249 :                                : d_variables.getLowerBoundConstraint(nonbasic);
     664                 :            : 
     665         [ +  + ]:    1378249 :       if (farkas != RationalVectorPSentinel)
     666                 :            :       {
     667                 :     937118 :         Rational multAij = multiple * a_ij;
     668         [ +  - ]:     937118 :         Trace("arith::propagateRow") << "(" << multAij << ") ";
     669                 :     937118 :         farkas->push_back(multAij);
     670                 :     937118 :       }
     671 [ -  + ][ -  + ]:    1378249 :       Assert(bound != NullConstraint);
                 [ -  - ]
     672         [ +  - ]:    1378249 :       Trace("arith::propagateRow") << bound << endl;
     673                 :    1378249 :       into.push_back(bound);
     674                 :            :     }
     675                 :            :   }
     676         [ +  - ]:     465970 :   Trace("arith::propagateRow")
     677                 :          0 :       << "LinearEqualityModule::propagateRow(" << ridx << ", " << rowUp << ", "
     678                 :     232985 :       << v << ") done" << endl;
     679                 :     232985 : }
     680                 :            : 
     681                 :    1158800 : ConstraintP LinearEqualityModule::weakestExplanation(bool aboveUpper,
     682                 :            :                                                      DeltaRational& surplus,
     683                 :            :                                                      ArithVar v,
     684                 :            :                                                      const Rational& coeff,
     685                 :            :                                                      bool& anyWeakening,
     686                 :            :                                                      ArithVar basic) const
     687                 :            : {
     688                 :    1158800 :   int sgn = coeff.sgn();
     689         [ +  + ]:    1158800 :   bool ub = aboveUpper ? (sgn < 0) : (sgn > 0);
     690                 :            : 
     691         [ +  + ]:    1158800 :   ConstraintP c = ub ? d_variables.getUpperBoundConstraint(v)
     692                 :    1158800 :                      : d_variables.getLowerBoundConstraint(v);
     693                 :            : 
     694                 :            :   bool weakened;
     695         [ +  + ]:    1339023 :   do
     696                 :            :   {
     697                 :    1339023 :     const DeltaRational& bound = c->getValue();
     698                 :            : 
     699                 :    1339023 :     weakened = false;
     700                 :            : 
     701         [ +  + ]:    1339023 :     ConstraintP weaker = ub ? c->getStrictlyWeakerUpperBound(true, true)
     702                 :     793222 :                             : c->getStrictlyWeakerLowerBound(true, true);
     703                 :            : 
     704         [ +  + ]:    1339023 :     if (weaker != NullConstraint)
     705                 :            :     {
     706                 :     356114 :       const DeltaRational& weakerBound = weaker->getValue();
     707                 :            : 
     708                 :            :       DeltaRational diff =
     709         [ +  + ]:     356114 :           aboveUpper ? bound - weakerBound : weakerBound - bound;
     710                 :            :       // if var == basic,
     711                 :            :       //   if aboveUpper, weakerBound > bound, multiply by -1
     712                 :            :       //   if !aboveUpper, weakerBound < bound, multiply by -1
     713                 :     356114 :       diff = diff * coeff;
     714         [ +  + ]:     356114 :       if (surplus > diff)
     715                 :            :       {
     716                 :     180223 :         ++d_statistics.d_weakenings;
     717                 :     180223 :         weakened = true;
     718                 :     180223 :         anyWeakening = true;
     719                 :     180223 :         surplus = surplus - diff;
     720                 :            : 
     721         [ +  - ]:     180223 :         Trace("arith::weak") << "found:" << endl;
     722         [ +  + ]:     180223 :         if (v == basic)
     723                 :            :         {
     724         [ +  - ]:      17705 :           Trace("arith::weak") << "  basic: ";
     725                 :            :         }
     726         [ +  - ]:     360446 :         Trace("arith::weak") << "  " << surplus << " " << diff << endl
     727                 :          0 :                              << "  " << bound << c << endl
     728                 :     180223 :                              << "  " << weakerBound << weaker << endl;
     729                 :            : 
     730 [ -  + ][ -  + ]:     180223 :         Assert(diff.sgn() > 0);
                 [ -  - ]
     731                 :     180223 :         c = weaker;
     732                 :            :       }
     733                 :     356114 :     }
     734                 :            :   } while (weakened);
     735                 :            : 
     736                 :    1158800 :   return c;
     737                 :            : }
     738                 :            : 
     739                 :            : /* An explanation of the farkas coefficients.
     740                 :            :  *
     741                 :            :  * We are proving a conflict on the basic variable x_b.
     742                 :            :  * If aboveUpper, then the conflict is with the constraint c : x_b <= u_b.
     743                 :            :  * If !aboveUpper, then the conflict is with the constraint c : x_b >= l_b.
     744                 :            :  *
     745                 :            :  * A row has the form:
     746                 :            :  *   -x_b sum a_i * x_i  = 0
     747                 :            :  * or
     748                 :            :  *   -x_b + sum r y + sum q z = 0,
     749                 :            :  *    x_b = sum r y + sum q z
     750                 :            :  * where r > 0 and q < 0.
     751                 :            :  *
     752                 :            :  *
     753                 :            :  * If !aboveUp, we are proving ~c: x_b < l_b
     754                 :            :  *   g = sum r u_y + sum q l_z
     755                 :            :  *   x_b <= g < l_b
     756                 :            :  *   and ~c is entailed by x_b <= g
     757                 :            :  *
     758                 :            :  * If aboveUp, we are proving ~c : x_b > u_b
     759                 :            :  *   g = sum r l_y + sum q u_z
     760                 :            :  *   x_b >= g > u_b
     761                 :            :  *   and ~c is entailed by x_b >= g
     762                 :            :  *
     763                 :            :  *
     764                 :            :  *               | s     | c         | ~c       | u_i     | l_i
     765                 :            :  *   if !aboveUp | s > 0 | x >= -g/s | x < -g/s | a_i > 0 | a_i < 0
     766                 :            :  *   if !aboveUp | s < 0 | x <= -g/s | x > -g/s | a_i > 0 | a_i < 0
     767                 :            :  *   if  aboveUp | s > 0 | x <= -g/s | x > -g/s | a_i < 0 | a_i > 0
     768                 :            :  *   if  aboveUp | s < 0 | x >= -g/s | x < -g/s | a_i < 0 | a_i > 0
     769                 :            :  *
     770                 :            :  * Thus we treat aboveUp as multiplying the row by -1 and !aboveUp as 1
     771                 :            :  * for the entire row.
     772                 :            :  */
     773                 :     104031 : ConstraintCP LinearEqualityModule::minimallyWeakConflict(
     774                 :            :     NodeManager* nm,
     775                 :            :     bool aboveUpper,
     776                 :            :     ArithVar basicVar,
     777                 :            :     FarkasConflictBuilder& fcs) const
     778                 :            : {
     779 [ -  + ][ -  + ]:     104031 :   Assert(!fcs.underConstruction());
                 [ -  - ]
     780                 :     104031 :   TimerStat::CodeTimer codeTimer(d_statistics.d_weakenTime);
     781                 :            : 
     782         [ +  - ]:     208062 :   Trace("arith::weak") << "LinearEqualityModule::minimallyWeakConflict("
     783                 :          0 :                        << aboveUpper << ", " << basicVar << ", ...) start"
     784                 :     104031 :                        << endl;
     785                 :            : 
     786         [ +  + ]:     104031 :   const Rational& adjustSgn = aboveUpper ? d_negOne : d_one;
     787                 :     104031 :   const DeltaRational& assignment = d_variables.getAssignment(basicVar);
     788                 :     104031 :   DeltaRational surplus;
     789         [ +  + ]:     104031 :   if (aboveUpper)
     790                 :            :   {
     791 [ -  + ][ -  + ]:      50328 :     Assert(d_variables.hasUpperBound(basicVar));
                 [ -  - ]
     792 [ -  + ][ -  + ]:      50328 :     Assert(assignment > d_variables.getUpperBound(basicVar));
                 [ -  - ]
     793                 :      50328 :     surplus = assignment - d_variables.getUpperBound(basicVar);
     794                 :            :   }
     795                 :            :   else
     796                 :            :   {
     797 [ -  + ][ -  + ]:      53703 :     Assert(d_variables.hasLowerBound(basicVar));
                 [ -  - ]
     798 [ -  + ][ -  + ]:      53703 :     Assert(assignment < d_variables.getLowerBound(basicVar));
                 [ -  - ]
     799                 :      53703 :     surplus = d_variables.getLowerBound(basicVar) - assignment;
     800                 :            :   }
     801                 :            : 
     802                 :     104031 :   bool anyWeakenings = false;
     803                 :     104031 :   for (Tableau::RowIterator i = d_tableau.basicRowIterator(basicVar);
     804         [ +  + ]:    1262831 :        !i.atEnd();
     805                 :    1158800 :        ++i)
     806                 :            :   {
     807                 :    1158800 :     const Tableau::Entry& entry = *i;
     808                 :    1158800 :     ArithVar v = entry.getColVar();
     809                 :    1158800 :     const Rational& coeff = entry.getCoefficient();
     810                 :    1158800 :     bool weakening = false;
     811                 :            :     ConstraintP c =
     812                 :    1158800 :         weakestExplanation(aboveUpper, surplus, v, coeff, weakening, basicVar);
     813         [ +  - ]:    2317600 :     Trace("arith::weak") << "weak : " << weakening << " "
     814                 :    1158800 :                          << c->assertedToTheTheory() << " "
     815                 :    1158800 :                          << d_variables.getAssignment(v) << " " << c << endl;
     816 [ +  + ][ +  + ]:    1158800 :     anyWeakenings = anyWeakenings || weakening;
     817                 :            : 
     818                 :    1158800 :     fcs.addConstraint(c, coeff, adjustSgn);
     819         [ +  + ]:    1158800 :     if (basicVar == v)
     820                 :            :     {
     821 [ -  + ][ -  + ]:     104031 :       Assert(!c->negationHasProof());
                 [ -  - ]
     822                 :     104031 :       fcs.makeLastConsequent();
     823                 :            :     }
     824                 :            :   }
     825 [ -  + ][ -  + ]:     104031 :   Assert(fcs.consequentIsSet());
                 [ -  - ]
     826                 :            : 
     827                 :     104031 :   ConstraintCP conflicted = fcs.commitConflict(nm);
     828                 :            : 
     829                 :     104031 :   ++d_statistics.d_weakeningAttempts;
     830         [ +  + ]:     104031 :   if (anyWeakenings)
     831                 :            :   {
     832                 :      81577 :     ++d_statistics.d_weakeningSuccesses;
     833                 :            :   }
     834         [ +  - ]:     208062 :   Trace("arith::weak") << "LinearEqualityModule::minimallyWeakConflict("
     835                 :          0 :                        << aboveUpper << ", " << basicVar << ", ...) done"
     836                 :     104031 :                        << endl;
     837                 :     104031 :   return conflicted;
     838                 :     104031 : }
     839                 :            : 
     840                 :     154058 : ArithVar LinearEqualityModule::minVarOrder(ArithVar x, ArithVar y) const
     841                 :            : {
     842 [ -  + ][ -  + ]:     154058 :   Assert(x != ARITHVAR_SENTINEL);
                 [ -  - ]
     843 [ -  + ][ -  + ]:     154058 :   Assert(y != ARITHVAR_SENTINEL);
                 [ -  - ]
     844         [ +  + ]:     154058 :   if (x <= y)
     845                 :            :   {
     846                 :      90144 :     return x;
     847                 :            :   }
     848                 :            :   else
     849                 :            :   {
     850                 :      63914 :     return y;
     851                 :            :   }
     852                 :            : }
     853                 :            : 
     854                 :     983055 : ArithVar LinearEqualityModule::minColLength(ArithVar x, ArithVar y) const
     855                 :            : {
     856 [ -  + ][ -  + ]:     983055 :   Assert(x != ARITHVAR_SENTINEL);
                 [ -  - ]
     857 [ -  + ][ -  + ]:     983055 :   Assert(y != ARITHVAR_SENTINEL);
                 [ -  - ]
     858 [ -  + ][ -  + ]:     983055 :   Assert(!d_tableau.isBasic(x));
                 [ -  - ]
     859 [ -  + ][ -  + ]:     983055 :   Assert(!d_tableau.isBasic(y));
                 [ -  - ]
     860                 :     983055 :   uint32_t xLen = d_tableau.getColLength(x);
     861                 :     983055 :   uint32_t yLen = d_tableau.getColLength(y);
     862         [ +  + ]:     983055 :   if (xLen > yLen)
     863                 :            :   {
     864                 :     180908 :     return y;
     865                 :            :   }
     866         [ +  + ]:     802147 :   else if (xLen == yLen)
     867                 :            :   {
     868                 :     152736 :     return minVarOrder(x, y);
     869                 :            :   }
     870                 :            :   else
     871                 :            :   {
     872                 :     649411 :     return x;
     873                 :            :   }
     874                 :            : }
     875                 :            : 
     876                 :          0 : ArithVar LinearEqualityModule::minRowLength(ArithVar x, ArithVar y) const
     877                 :            : {
     878                 :          0 :   Assert(x != ARITHVAR_SENTINEL);
     879                 :          0 :   Assert(y != ARITHVAR_SENTINEL);
     880                 :          0 :   Assert(d_tableau.isBasic(x));
     881                 :          0 :   Assert(d_tableau.isBasic(y));
     882                 :          0 :   uint32_t xLen = d_tableau.basicRowLength(x);
     883                 :          0 :   uint32_t yLen = d_tableau.basicRowLength(y);
     884         [ -  - ]:          0 :   if (xLen > yLen)
     885                 :            :   {
     886                 :          0 :     return y;
     887                 :            :   }
     888         [ -  - ]:          0 :   else if (xLen == yLen)
     889                 :            :   {
     890                 :          0 :     return minVarOrder(x, y);
     891                 :            :   }
     892                 :            :   else
     893                 :            :   {
     894                 :          0 :     return x;
     895                 :            :   }
     896                 :            : }
     897                 :            : 
     898                 :    1061906 : ArithVar LinearEqualityModule::minBoundAndColLength(ArithVar x,
     899                 :            :                                                     ArithVar y) const
     900                 :            : {
     901 [ -  + ][ -  + ]:    1061906 :   Assert(x != ARITHVAR_SENTINEL);
                 [ -  - ]
     902 [ -  + ][ -  + ]:    1061906 :   Assert(y != ARITHVAR_SENTINEL);
                 [ -  - ]
     903 [ -  + ][ -  + ]:    1061906 :   Assert(!d_tableau.isBasic(x));
                 [ -  - ]
     904 [ -  + ][ -  + ]:    1061906 :   Assert(!d_tableau.isBasic(y));
                 [ -  - ]
     905 [ +  + ][ +  + ]:    1061906 :   if (d_variables.hasEitherBound(x) && !d_variables.hasEitherBound(y))
                 [ +  + ]
     906                 :            :   {
     907                 :      33173 :     return y;
     908                 :            :   }
     909 [ +  + ][ +  + ]:    1028733 :   else if (!d_variables.hasEitherBound(x) && d_variables.hasEitherBound(y))
                 [ +  + ]
     910                 :            :   {
     911                 :      45678 :     return x;
     912                 :            :   }
     913                 :            :   else
     914                 :            :   {
     915                 :     983055 :     return minColLength(x, y);
     916                 :            :   }
     917                 :            : }
     918                 :            : 
     919                 :            : template <bool above>
     920                 :     333513 : ArithVar LinearEqualityModule::selectSlack(ArithVar x_i,
     921                 :            :                                            VarPreferenceFunction pref) const
     922                 :            : {
     923                 :     333513 :   ArithVar slack = ARITHVAR_SENTINEL;
     924                 :            : 
     925                 :     333513 :   for (Tableau::RowIterator iter = d_tableau.basicRowIterator(x_i);
     926         [ +  + ]:    6082196 :        !iter.atEnd();
     927                 :    5748683 :        ++iter)
     928                 :            :   {
     929                 :    5748683 :     const Tableau::Entry& entry = *iter;
     930                 :    5748683 :     ArithVar nonbasic = entry.getColVar();
     931         [ +  + ]:    5748683 :     if (nonbasic == x_i) continue;
     932                 :            : 
     933                 :    5415170 :     const Rational& a_ij = entry.getCoefficient();
     934                 :    5415170 :     int sgn = a_ij.sgn();
     935         [ +  + ]:    5415170 :     if (isAcceptableSlack<above>(sgn, nonbasic))
     936                 :            :     {
     937                 :            :       // If one of the above conditions is met, we have found an acceptable
     938                 :            :       // nonbasic variable to pivot x_i with.  We can now choose which one we
     939                 :            :       // prefer the most.
     940         [ +  + ]:    2345351 :       slack = (slack == ARITHVAR_SENTINEL) ? nonbasic
     941         [ -  + ]:    1005919 :                                            : (this->*pref)(slack, nonbasic);
     942                 :            :     }
     943                 :            :   }
     944                 :            : 
     945                 :     333513 :   return slack;
     946                 :            : }
     947                 :            : 
     948                 :          0 : const Tableau::Entry* LinearEqualityModule::selectSlackEntry(ArithVar x_i,
     949                 :            :                                                              bool above) const
     950                 :            : {
     951                 :          0 :   for (Tableau::RowIterator iter = d_tableau.basicRowIterator(x_i);
     952         [ -  - ]:          0 :        !iter.atEnd();
     953                 :          0 :        ++iter)
     954                 :            :   {
     955                 :          0 :     const Tableau::Entry& entry = *iter;
     956                 :          0 :     ArithVar nonbasic = entry.getColVar();
     957         [ -  - ]:          0 :     if (nonbasic == x_i) continue;
     958                 :            : 
     959                 :          0 :     const Rational& a_ij = entry.getCoefficient();
     960                 :          0 :     int sgn = a_ij.sgn();
     961                 :          0 :     if (above && isAcceptableSlack<true>(sgn, nonbasic))
     962                 :            :     {
     963                 :            :       // If one of the above conditions is met, we have found an acceptable
     964                 :            :       // nonbasic variable to pivot x_i with.  We can now choose which one we
     965                 :            :       // prefer the most.
     966                 :          0 :       return &entry;
     967                 :            :     }
     968                 :          0 :     else if (!above && isAcceptableSlack<false>(sgn, nonbasic))
     969                 :            :     {
     970                 :          0 :       return &entry;
     971                 :            :     }
     972                 :            :   }
     973                 :            : 
     974                 :          0 :   return nullptr;
     975                 :            : }
     976                 :            : 
     977                 :    3258671 : void LinearEqualityModule::startTrackingBoundCounts()
     978                 :            : {
     979 [ -  + ][ -  + ]:    3258671 :   Assert(!d_areTracking);
                 [ -  - ]
     980                 :    3258671 :   d_areTracking = true;
     981         [ -  + ]:    3258671 :   if (TraceIsOn("arith::tracking"))
     982                 :            :   {
     983                 :          0 :     debugCheckTracking();
     984                 :            :   }
     985 [ -  + ][ -  + ]:    3258671 :   Assert(d_areTracking);
                 [ -  - ]
     986                 :    3258671 : }
     987                 :            : 
     988                 :    3258671 : void LinearEqualityModule::stopTrackingBoundCounts()
     989                 :            : {
     990 [ -  + ][ -  + ]:    3258671 :   Assert(d_areTracking);
                 [ -  - ]
     991                 :    3258671 :   d_areTracking = false;
     992         [ -  + ]:    3258671 :   if (TraceIsOn("arith::tracking"))
     993                 :            :   {
     994                 :          0 :     debugCheckTracking();
     995                 :            :   }
     996 [ -  + ][ -  + ]:    3258671 :   Assert(!d_areTracking);
                 [ -  - ]
     997                 :    3258671 : }
     998                 :            : 
     999                 :     201247 : void LinearEqualityModule::trackRowIndex(RowIndex ridx)
    1000                 :            : {
    1001 [ -  + ][ -  + ]:     201247 :   Assert(!rowIndexIsTracked(ridx));
                 [ -  - ]
    1002                 :     201247 :   BoundsInfo bi = computeRowBoundInfo(ridx, true);
    1003                 :     201247 :   d_btracking.set(ridx, bi);
    1004                 :     201247 : }
    1005                 :            : 
    1006                 :     201247 : BoundsInfo LinearEqualityModule::computeRowBoundInfo(RowIndex ridx,
    1007                 :            :                                                      bool inQueue) const
    1008                 :            : {
    1009                 :     201247 :   BoundsInfo bi;
    1010                 :            : 
    1011                 :     201247 :   Tableau::RowIterator iter = d_tableau.ridRowIterator(ridx);
    1012         [ +  + ]:    1219310 :   for (; !iter.atEnd(); ++iter)
    1013                 :            :   {
    1014                 :    1018063 :     const Tableau::Entry& entry = *iter;
    1015                 :    1018063 :     ArithVar v = entry.getColVar();
    1016                 :    1018063 :     const Rational& a_ij = entry.getCoefficient();
    1017                 :    1018063 :     bi += (d_variables.selectBoundsInfo(v, inQueue)).multiplyBySgn(a_ij.sgn());
    1018                 :            :   }
    1019                 :     201247 :   return bi;
    1020                 :            : }
    1021                 :            : 
    1022                 :          0 : BoundCounts LinearEqualityModule::debugBasicAtBoundCount(ArithVar x_i) const
    1023                 :            : {
    1024                 :          0 :   return d_btracking[d_tableau.basicToRowIndex(x_i)].atBounds();
    1025                 :            : }
    1026                 :            : 
    1027                 :            : /**
    1028                 :            :  * If the pivot described in u were performed,
    1029                 :            :  * then the row would qualify as being either at the minimum/maximum
    1030                 :            :  * to the non-basics being at their bounds.
    1031                 :            :  * The minimum/maximum is determined by the direction the non-basic is changing.
    1032                 :            :  */
    1033                 :     106452 : bool LinearEqualityModule::basicsAtBounds(const UpdateInfo& u) const
    1034                 :            : {
    1035 [ -  + ][ -  + ]:     106452 :   Assert(u.describesPivot());
                 [ -  - ]
    1036                 :            : 
    1037                 :     106452 :   ArithVar nonbasic = u.nonbasic();
    1038                 :     106452 :   ArithVar basic = u.leaving();
    1039 [ -  + ][ -  + ]:     106452 :   Assert(basicIsTracked(basic));
                 [ -  - ]
    1040                 :     106452 :   int coeffSgn = u.getCoefficient().sgn();
    1041                 :     106452 :   int nbdir = u.nonbasicDirection();
    1042                 :            : 
    1043                 :     106452 :   ConstraintP c = u.limiting();
    1044 [ +  + ][ +  + ]:     106452 :   int toUB = (c->getType() == UpperBound || c->getType() == Equality) ? 1 : 0;
    1045 [ +  + ][ +  + ]:     106452 :   int toLB = (c->getType() == LowerBound || c->getType() == Equality) ? 1 : 0;
    1046                 :            : 
    1047                 :     106452 :   RowIndex ridx = d_tableau.basicToRowIndex(basic);
    1048                 :            : 
    1049                 :     106452 :   BoundCounts bcs = d_btracking[ridx].atBounds();
    1050                 :            :   // x = c*n + \sum d*m
    1051                 :            :   // 0 = -x + c*n + \sum d*m
    1052                 :            :   // n = 1/c * x + -1/c * (\sum d*m)
    1053                 :            :   BoundCounts nonb =
    1054                 :     106452 :       bcs - d_variables.atBoundCounts(nonbasic).multiplyBySgn(coeffSgn);
    1055                 :     212904 :   nonb.addInChange(
    1056                 :     106452 :       -1, d_variables.atBoundCounts(basic), BoundCounts(toLB, toUB));
    1057                 :     106452 :   nonb = nonb.multiplyBySgn(-coeffSgn);
    1058                 :            : 
    1059                 :     106452 :   uint32_t length = d_tableau.basicRowLength(basic);
    1060         [ +  - ]:     212904 :   Trace("basicsAtBounds") << "bcs " << bcs << "nonb " << nonb << "length "
    1061                 :     106452 :                           << length << endl;
    1062                 :            :   // nonb has nb excluded.
    1063         [ +  + ]:     106452 :   if (nbdir < 0)
    1064                 :            :   {
    1065                 :      51312 :     return nonb.lowerBoundCount() + 1 == length;
    1066                 :            :   }
    1067                 :            :   else
    1068                 :            :   {
    1069 [ -  + ][ -  + ]:      55140 :     Assert(nbdir > 0);
                 [ -  - ]
    1070                 :      55140 :     return nonb.upperBoundCount() + 1 == length;
    1071                 :            :   }
    1072                 :            : }
    1073                 :            : 
    1074                 :     681358 : bool LinearEqualityModule::nonbasicsAtLowerBounds(ArithVar basic) const
    1075                 :            : {
    1076 [ -  + ][ -  + ]:     681358 :   Assert(basicIsTracked(basic));
                 [ -  - ]
    1077                 :     681358 :   RowIndex ridx = d_tableau.basicToRowIndex(basic);
    1078                 :            : 
    1079                 :     681358 :   BoundCounts bcs = d_btracking[ridx].atBounds();
    1080                 :     681358 :   uint32_t length = d_tableau.basicRowLength(basic);
    1081                 :            : 
    1082                 :            :   // return true if excluding the basic is every element is at its "lowerbound"
    1083                 :            :   // The psuedo code is:
    1084                 :            :   //   bcs -= basic.count(basic, basic's sgn)
    1085                 :            :   //   return bcs.lowerBoundCount() + 1 == length
    1086                 :            :   // As basic's sign is always -1, we can pull out the pieces of the count:
    1087                 :            :   //   bcs.lowerBoundCount() - basic.atUpperBoundInd() + 1 == length
    1088                 :            :   // basic.atUpperBoundInd() is either 0 or 1
    1089                 :     681358 :   uint32_t lbc = bcs.lowerBoundCount();
    1090                 :            :   return (lbc == length)
    1091 [ +  - ][ +  + ]:     882670 :          || (lbc + 1 == length
    1092         [ +  - ]:     882670 :              && d_variables.cmpAssignmentUpperBound(basic) != 0);
    1093                 :            : }
    1094                 :            : 
    1095                 :     699669 : bool LinearEqualityModule::nonbasicsAtUpperBounds(ArithVar basic) const
    1096                 :            : {
    1097 [ -  + ][ -  + ]:     699669 :   Assert(basicIsTracked(basic));
                 [ -  - ]
    1098                 :     699669 :   RowIndex ridx = d_tableau.basicToRowIndex(basic);
    1099                 :     699669 :   BoundCounts bcs = d_btracking[ridx].atBounds();
    1100                 :     699669 :   uint32_t length = d_tableau.basicRowLength(basic);
    1101                 :     699669 :   uint32_t ubc = bcs.upperBoundCount();
    1102                 :            :   // See the comment for nonbasicsAtLowerBounds()
    1103                 :            : 
    1104                 :            :   return (ubc == length)
    1105 [ +  - ][ +  + ]:     914481 :          || (ubc + 1 == length
    1106         [ +  - ]:     914481 :              && d_variables.cmpAssignmentLowerBound(basic) != 0);
    1107                 :            : }
    1108                 :            : 
    1109                 :     341292 : void LinearEqualityModule::trackingMultiplyRow(RowIndex ridx, int sgn)
    1110                 :            : {
    1111 [ -  + ][ -  + ]:     341292 :   Assert(rowIndexIsTracked(ridx));
                 [ -  - ]
    1112 [ -  + ][ -  + ]:     341292 :   Assert(sgn != 0);
                 [ -  - ]
    1113         [ +  + ]:     341292 :   if (sgn < 0)
    1114                 :            :   {
    1115                 :     186764 :     BoundsInfo& bi = d_btracking.get(ridx);
    1116                 :     186764 :     bi = bi.multiplyBySgn(sgn);
    1117                 :            :   }
    1118                 :     341292 : }
    1119                 :            : 
    1120                 :   71710684 : void LinearEqualityModule::trackingCoefficientChange(RowIndex ridx,
    1121                 :            :                                                      ArithVar nb,
    1122                 :            :                                                      int oldSgn,
    1123                 :            :                                                      int currSgn)
    1124                 :            : {
    1125 [ -  + ][ -  + ]:   71710684 :   Assert(oldSgn != currSgn);
                 [ -  - ]
    1126                 :   71710684 :   BoundsInfo nb_inf = d_variables.boundsInfo(nb);
    1127                 :            : 
    1128 [ -  + ][ -  + ]:   71710684 :   Assert(rowIndexIsTracked(ridx));
                 [ -  - ]
    1129                 :            : 
    1130                 :   71710684 :   BoundsInfo& row_bi = d_btracking.get(ridx);
    1131                 :   71710684 :   row_bi.addInSgn(nb_inf, oldSgn, currSgn);
    1132                 :   71710684 : }
    1133                 :            : 
    1134                 :          0 : ArithVar LinearEqualityModule::minBy(const ArithVarVec& vec,
    1135                 :            :                                      VarPreferenceFunction pf) const
    1136                 :            : {
    1137         [ -  - ]:          0 :   if (vec.empty())
    1138                 :            :   {
    1139                 :          0 :     return ARITHVAR_SENTINEL;
    1140                 :            :   }
    1141                 :            :   else
    1142                 :            :   {
    1143                 :          0 :     ArithVar sel = vec.front();
    1144                 :          0 :     ArithVarVec::const_iterator i = vec.begin() + 1;
    1145                 :          0 :     ArithVarVec::const_iterator i_end = vec.end();
    1146         [ -  - ]:          0 :     for (; i != i_end; ++i)
    1147                 :            :     {
    1148         [ -  - ]:          0 :       sel = (this->*pf)(sel, *i);
    1149                 :            :     }
    1150                 :          0 :     return sel;
    1151                 :            :   }
    1152                 :            : }
    1153                 :            : 
    1154                 :    2190489 : bool LinearEqualityModule::accumulateBorder(const Tableau::Entry& entry,
    1155                 :            :                                             bool ub)
    1156                 :            : {
    1157                 :    2190489 :   ArithVar currBasic = d_tableau.rowIndexToBasic(entry.getRowIndex());
    1158                 :            : 
    1159 [ -  + ][ -  + ]:    2190489 :   Assert(basicIsTracked(currBasic));
                 [ -  - ]
    1160                 :            : 
    1161         [ +  + ]:    2190489 :   ConstraintP bound = ub ? d_variables.getUpperBoundConstraint(currBasic)
    1162                 :    1095237 :                          : d_variables.getLowerBoundConstraint(currBasic);
    1163                 :            : 
    1164         [ +  + ]:    2190489 :   if (bound == NullConstraint)
    1165                 :            :   {
    1166                 :    1937551 :     return false;
    1167                 :            :   }
    1168 [ -  + ][ -  + ]:     252938 :   Assert(bound != NullConstraint);
                 [ -  - ]
    1169                 :            : 
    1170                 :     252938 :   const Rational& coeff = entry.getCoefficient();
    1171                 :            : 
    1172                 :     252938 :   const DeltaRational& assignment = d_variables.getAssignment(currBasic);
    1173                 :     252938 :   DeltaRational toBound = bound->getValue() - assignment;
    1174                 :     252938 :   DeltaRational nbDiff = toBound / coeff;
    1175                 :            : 
    1176                 :            :   // if ub
    1177                 :            :   // if toUB >= 0
    1178                 :            :   // then ub >= currBasic
    1179                 :            :   //   if sgn > 0,
    1180                 :            :   //   then diff >= 0, so nb must increase for G
    1181                 :            :   //   else diff <= 0, so nb must decrease for G
    1182                 :            :   // else ub < currBasic
    1183                 :            :   //   if sgn > 0,
    1184                 :            :   //   then diff < 0, so nb must decrease for G
    1185                 :            :   //   else diff > 0, so nb must increase for G
    1186                 :            : 
    1187                 :     252938 :   int diffSgn = nbDiff.sgn();
    1188                 :            : 
    1189 [ +  + ][ +  + ]:     252938 :   if (diffSgn != 0 && willBeInConflictAfterPivot(entry, nbDiff, ub))
                 [ +  + ]
    1190                 :            :   {
    1191                 :         27 :     return true;
    1192                 :            :   }
    1193                 :            :   else
    1194                 :            :   {
    1195         [ +  + ]:     252911 :     bool areFixing = ub ? (toBound.sgn() < 0) : (toBound.sgn() > 0);
    1196                 :     252911 :     Border border(bound, nbDiff, areFixing, &entry, ub);
    1197                 :            :     bool increasing =
    1198 [ +  + ][ +  + ]:     252911 :         (diffSgn > 0) || (diffSgn == 0 && ((coeff.sgn() > 0) == ub));
                 [ +  + ]
    1199                 :            : 
    1200                 :            :     // assume diffSgn == 0
    1201                 :            :     // if coeff > 0,
    1202                 :            :     //   if ub, inc
    1203                 :            :     //   else, dec
    1204                 :            :     // else coeff < 0
    1205                 :            :     //   if ub, dec
    1206                 :            :     //   else, inc
    1207                 :            : 
    1208         [ +  + ]:     252911 :     if (increasing)
    1209                 :            :     {
    1210         [ +  - ]:     128732 :       Trace("handleBorders") << "push back increasing " << border << endl;
    1211                 :     128732 :       d_increasing.push_back(border);
    1212                 :            :     }
    1213                 :            :     else
    1214                 :            :     {
    1215         [ +  - ]:     124179 :       Trace("handleBorders") << "push back decreasing " << border << endl;
    1216                 :     124179 :       d_decreasing.push_back(border);
    1217                 :            :     }
    1218                 :     252911 :     return false;
    1219                 :     252911 :   }
    1220                 :     252938 : }
    1221                 :            : 
    1222                 :     167528 : bool LinearEqualityModule::willBeInConflictAfterPivot(
    1223                 :            :     const Tableau::Entry& entry, const DeltaRational& nbDiff, bool bToUB) const
    1224                 :            : {
    1225                 :     167528 :   int nbSgn = nbDiff.sgn();
    1226 [ -  + ][ -  + ]:     167528 :   Assert(nbSgn != 0);
                 [ -  - ]
    1227                 :            : 
    1228         [ +  + ]:     167528 :   if (nbSgn > 0)
    1229                 :            :   {
    1230 [ +  + ][ +  + ]:      87619 :     if (!d_upperBoundDifference || nbDiff <= *d_upperBoundDifference)
                 [ +  + ]
    1231                 :            :     {
    1232                 :      69367 :       return false;
    1233                 :            :     }
    1234                 :            :   }
    1235                 :            :   else
    1236                 :            :   {
    1237 [ +  + ][ +  + ]:      79909 :     if (!d_lowerBoundDifference || nbDiff >= *d_lowerBoundDifference)
                 [ +  + ]
    1238                 :            :     {
    1239                 :      62665 :       return false;
    1240                 :            :     }
    1241                 :            :   }
    1242                 :            : 
    1243                 :            :   // Assume past this point, nb will be in error if this pivot is done
    1244                 :      35496 :   ArithVar nb = entry.getColVar();
    1245                 :      35496 :   RowIndex ridx = entry.getRowIndex();
    1246                 :      35496 :   ArithVar basic = d_tableau.rowIndexToBasic(ridx);
    1247 [ -  + ][ -  + ]:      35496 :   Assert(rowIndexIsTracked(ridx));
                 [ -  - ]
    1248                 :      35496 :   int coeffSgn = entry.getCoefficient().sgn();
    1249                 :            : 
    1250                 :            :   // if bToUB, then basic is going to be set to its upperbound
    1251                 :            :   // if not bToUB, then basic is going to be set to its lowerbound
    1252                 :            : 
    1253                 :            :   // Different steps of solving for this:
    1254                 :            :   // 1) y = a * x + \sum b * z
    1255                 :            :   // 2) -a * x = -y + \sum b * z
    1256                 :            :   // 3) x = (-1/a) * ( -y + \sum b * z)
    1257                 :            : 
    1258                 :      35496 :   BoundCounts bc = d_btracking[ridx].atBounds();
    1259                 :            : 
    1260                 :            :   // 1) y = a * x + \sum b * z
    1261                 :            :   // Get bc(\sum b * z)
    1262                 :            :   BoundCounts sumOnly =
    1263                 :      35496 :       bc - d_variables.atBoundCounts(nb).multiplyBySgn(coeffSgn);
    1264                 :            : 
    1265                 :            :   // y's bounds in the proposed model
    1266 [ +  + ][ +  + ]:      35496 :   int yWillBeAtUb = (bToUB || d_variables.boundsAreEqual(basic)) ? 1 : 0;
    1267 [ +  + ][ +  + ]:      35496 :   int yWillBeAtLb = (!bToUB || d_variables.boundsAreEqual(basic)) ? 1 : 0;
    1268                 :      35496 :   BoundCounts ysBounds(yWillBeAtLb, yWillBeAtUb);
    1269                 :            : 
    1270                 :            :   // 2) -a * x = -y + \sum b * z
    1271                 :            :   // Get bc(-y + \sum b * z)
    1272                 :      35496 :   sumOnly.addInChange(-1, d_variables.atBoundCounts(basic), ysBounds);
    1273                 :            : 
    1274                 :            :   // 3) x = (-1/a) * ( -y + \sum b * z)
    1275                 :            :   // Get bc((-1/a) * ( -y + \sum b * z))
    1276                 :      35496 :   BoundCounts xsBoundsAfterPivot = sumOnly.multiplyBySgn(-coeffSgn);
    1277                 :            : 
    1278                 :      35496 :   uint32_t length = d_tableau.basicRowLength(basic);
    1279         [ +  + ]:      35496 :   if (nbSgn > 0)
    1280                 :            :   {
    1281                 :            :     // Only check for the upper bound being violated
    1282                 :      18252 :     return xsBoundsAfterPivot.lowerBoundCount() + 1 == length;
    1283                 :            :   }
    1284                 :            :   else
    1285                 :            :   {
    1286                 :            :     // Only check for the lower bound being violated
    1287                 :      17244 :     return xsBoundsAfterPivot.upperBoundCount() + 1 == length;
    1288                 :            :   }
    1289                 :            : }
    1290                 :            : 
    1291                 :         27 : UpdateInfo LinearEqualityModule::mkConflictUpdate(const Tableau::Entry& entry,
    1292                 :            :                                                   bool ub) const
    1293                 :            : {
    1294                 :         27 :   ArithVar currBasic = d_tableau.rowIndexToBasic(entry.getRowIndex());
    1295                 :         27 :   ArithVar nb = entry.getColVar();
    1296                 :            : 
    1297         [ +  + ]:         27 :   ConstraintP bound = ub ? d_variables.getUpperBoundConstraint(currBasic)
    1298                 :         12 :                          : d_variables.getLowerBoundConstraint(currBasic);
    1299                 :            : 
    1300                 :         27 :   const Rational& coeff = entry.getCoefficient();
    1301                 :         27 :   const DeltaRational& assignment = d_variables.getAssignment(currBasic);
    1302                 :         27 :   DeltaRational toBound = bound->getValue() - assignment;
    1303                 :         27 :   DeltaRational nbDiff = toBound / coeff;
    1304                 :            : 
    1305                 :         54 :   return UpdateInfo::conflict(nb, nbDiff, coeff, bound);
    1306                 :         27 : }
    1307                 :            : 
    1308                 :      28349 : UpdateInfo LinearEqualityModule::speculativeUpdate(
    1309                 :            :     ArithVar nb, const Rational& focusCoeff, UpdatePreferenceFunction pref)
    1310                 :            : {
    1311 [ -  + ][ -  + ]:      28349 :   Assert(d_increasing.empty());
                 [ -  - ]
    1312 [ -  + ][ -  + ]:      28349 :   Assert(d_decreasing.empty());
                 [ -  - ]
    1313 [ -  + ][ -  + ]:      28349 :   Assert(!d_lowerBoundDifference);
                 [ -  - ]
    1314 [ -  + ][ -  + ]:      28349 :   Assert(!d_upperBoundDifference);
                 [ -  - ]
    1315                 :            : 
    1316                 :      28349 :   int focusCoeffSgn = focusCoeff.sgn();
    1317                 :            : 
    1318         [ +  - ]:      28349 :   Trace("speculativeUpdate") << "speculativeUpdate" << endl;
    1319         [ +  - ]:      28349 :   Trace("speculativeUpdate") << "nb " << nb << endl;
    1320         [ +  - ]:      28349 :   Trace("speculativeUpdate") << "focusCoeff " << focusCoeff << endl;
    1321                 :            : 
    1322         [ +  + ]:      28349 :   if (d_variables.hasUpperBound(nb))
    1323                 :            :   {
    1324                 :       5886 :     ConstraintP ub = d_variables.getUpperBoundConstraint(nb);
    1325                 :       5886 :     d_upperBoundDifference = ub->getValue() - d_variables.getAssignment(nb);
    1326                 :       5886 :     Border border(ub, *d_upperBoundDifference, false, nullptr, true);
    1327         [ +  - ]:       5886 :     Trace("handleBorders") << "push back increasing " << border << endl;
    1328                 :       5886 :     d_increasing.push_back(border);
    1329                 :       5886 :   }
    1330         [ +  + ]:      28349 :   if (d_variables.hasLowerBound(nb))
    1331                 :            :   {
    1332                 :       7088 :     ConstraintP lb = d_variables.getLowerBoundConstraint(nb);
    1333                 :       7088 :     d_lowerBoundDifference = lb->getValue() - d_variables.getAssignment(nb);
    1334                 :       7088 :     Border border(lb, *d_lowerBoundDifference, false, nullptr, false);
    1335         [ +  - ]:       7088 :     Trace("handleBorders") << "push back decreasing " << border << endl;
    1336                 :       7088 :     d_decreasing.push_back(border);
    1337                 :       7088 :   }
    1338                 :            : 
    1339                 :      28349 :   Tableau::ColIterator colIter = d_tableau.colIterator(nb);
    1340         [ +  + ]:    1123574 :   for (; !colIter.atEnd(); ++colIter)
    1341                 :            :   {
    1342                 :    1095252 :     const Tableau::Entry& entry = *colIter;
    1343 [ -  + ][ -  + ]:    1095252 :     Assert(entry.getColVar() == nb);
                 [ -  - ]
    1344                 :            : 
    1345         [ +  + ]:    1095252 :     if (accumulateBorder(entry, true))
    1346                 :            :     {
    1347                 :         15 :       clearSpeculative();
    1348                 :         15 :       return mkConflictUpdate(entry, true);
    1349                 :            :     }
    1350         [ +  + ]:    1095237 :     if (accumulateBorder(entry, false))
    1351                 :            :     {
    1352                 :         12 :       clearSpeculative();
    1353                 :         12 :       return mkConflictUpdate(entry, false);
    1354                 :            :     }
    1355                 :            :   }
    1356                 :            : 
    1357                 :      28322 :   UpdateInfo selected;
    1358         [ +  + ]:      28322 :   BorderHeap& withSgn = focusCoeffSgn > 0 ? d_increasing : d_decreasing;
    1359         [ +  + ]:      28322 :   BorderHeap& againstSgn = focusCoeffSgn > 0 ? d_decreasing : d_increasing;
    1360                 :            : 
    1361                 :      28322 :   handleBorders(selected, nb, focusCoeff, withSgn, 0, pref);
    1362                 :      28322 :   int m = 1 - selected.errorsChangeSafe(0);
    1363                 :      28322 :   handleBorders(selected, nb, focusCoeff, againstSgn, m, pref);
    1364                 :            : 
    1365                 :      28322 :   clearSpeculative();
    1366                 :      28322 :   return selected;
    1367                 :      28322 : }
    1368                 :            : 
    1369                 :      28349 : void LinearEqualityModule::clearSpeculative()
    1370                 :            : {
    1371                 :            :   // clear everything away
    1372                 :      28349 :   d_increasing.clear();
    1373                 :      28349 :   d_decreasing.clear();
    1374                 :      28349 :   d_lowerBoundDifference.reset();
    1375                 :      28349 :   d_upperBoundDifference.reset();
    1376                 :      28349 : }
    1377                 :            : 
    1378                 :      56644 : void LinearEqualityModule::handleBorders(UpdateInfo& selected,
    1379                 :            :                                          ArithVar nb,
    1380                 :            :                                          const Rational& focusCoeff,
    1381                 :            :                                          BorderHeap& heap,
    1382                 :            :                                          int minimumFixes,
    1383                 :            :                                          UpdatePreferenceFunction pref)
    1384                 :            : {
    1385 [ -  + ][ -  + ]:      56644 :   Assert(minimumFixes >= 0);
                 [ -  - ]
    1386                 :            : 
    1387                 :            :   // The values popped off of the heap
    1388                 :            :   // should be popped with the values closest to 0
    1389                 :            :   // being first and larger in absolute value last
    1390                 :            : 
    1391                 :      56644 :   int fixesRemaining = heap.possibleFixes();
    1392                 :            : 
    1393         [ +  - ]:     113288 :   Trace("handleBorders") << "handleBorders "
    1394                 :          0 :                          << "nb " << nb << "fc " << focusCoeff << "h.e "
    1395                 :          0 :                          << heap.empty() << "h.dir " << heap.direction()
    1396                 :          0 :                          << "h.rem " << fixesRemaining << "h.0s "
    1397                 :      56644 :                          << heap.numZeroes() << "min " << minimumFixes << endl;
    1398                 :            : 
    1399         [ +  + ]:      56644 :   if (heap.empty())
    1400                 :            :   {
    1401                 :            :     // if the heap is empty, return
    1402                 :      28265 :     return;
    1403                 :            :   }
    1404                 :            : 
    1405                 :      45060 :   bool zeroesWillDominate = fixesRemaining - heap.numZeroes() < minimumFixes;
    1406                 :            : 
    1407                 :            :   // can the number of fixes ever exceed the minimum?
    1408                 :            :   // no more than the number of possible fixes can be fixed in total
    1409                 :            :   // nothing can be fixed before the zeroes are taken care of
    1410 [ +  + ][ +  + ]:      45060 :   if (minimumFixes > 0 && zeroesWillDominate)
    1411                 :            :   {
    1412                 :      16681 :     return;
    1413                 :            :   }
    1414                 :            : 
    1415                 :      28379 :   int negErrorChange = 0;
    1416                 :      28379 :   int nbDir = heap.direction();
    1417                 :            : 
    1418                 :            :   // points at the beginning of the heap
    1419         [ +  + ]:      28379 :   if (zeroesWillDominate)
    1420                 :            :   {
    1421                 :       6976 :     heap.dropNonZeroes();
    1422                 :            :   }
    1423                 :      28379 :   heap.make_heap();
    1424                 :            : 
    1425                 :            :   // pretend like the previous block had a value of zero.
    1426                 :            :   // The block that actually has a value of 0 must handle this.
    1427                 :      28379 :   const DeltaRational zero(0);
    1428                 :      28379 :   const DeltaRational* prevBlockValue = &zero;
    1429                 :            : 
    1430                 :            :   /** The coefficient changes as the value crosses border. */
    1431                 :      28379 :   Rational effectiveCoefficient = focusCoeff;
    1432                 :            : 
    1433                 :            :   /* Keeps track of the change to the value of the focus function.*/
    1434                 :      28379 :   DeltaRational totalFocusChange(0);
    1435                 :            : 
    1436                 :      28379 :   const int focusCoeffSgn = focusCoeff.sgn();
    1437                 :            : 
    1438                 :      62968 :   while (heap.more()
    1439 [ +  + ][ +  + ]:      73327 :          && (fixesRemaining + negErrorChange > minimumFixes
                 [ +  + ]
    1440         [ +  + ]:      10359 :              || (fixesRemaining + negErrorChange == minimumFixes
    1441         [ +  + ]:       7140 :                  && effectiveCoefficient.sgn() == focusCoeffSgn)))
    1442                 :            :   {
    1443                 :            :     // There are more elements &&
    1444                 :            :     // we can either fix at least 1 more variable in the error function
    1445                 :            :     // or we can improve the error function
    1446                 :            : 
    1447                 :      34589 :     int brokenInBlock = 0;
    1448                 :      34589 :     BorderVec::const_iterator endBlock = heap.end();
    1449                 :            : 
    1450                 :      34589 :     pop_block(heap, brokenInBlock, fixesRemaining, negErrorChange);
    1451                 :            : 
    1452                 :            :     // if endVec == beginVec, block starts there
    1453                 :            :     // other wise, block starts at endVec
    1454                 :            :     BorderVec::const_iterator startBlock =
    1455         [ +  + ]:      34589 :         heap.more() ? heap.end() : heap.begin();
    1456                 :            : 
    1457                 :      34589 :     const DeltaRational& blockValue = (*startBlock).d_diff;
    1458                 :            : 
    1459                 :            :     // if decreasing
    1460                 :            :     // blockValue < prevBlockValue
    1461                 :            :     // diff.sgn() = -1
    1462                 :      34589 :     DeltaRational diff = blockValue - (*prevBlockValue);
    1463                 :      34589 :     DeltaRational blockChangeToFocus = diff * effectiveCoefficient;
    1464                 :      34589 :     totalFocusChange += blockChangeToFocus;
    1465                 :            : 
    1466         [ +  - ]:      69178 :     Trace("handleBorders") << "blockValue " << (blockValue) << "diff " << diff
    1467                 :          0 :                            << "blockChangeToFocus " << totalFocusChange
    1468                 :          0 :                            << "blockChangeToFocus " << totalFocusChange
    1469                 :          0 :                            << "negErrorChange " << negErrorChange
    1470                 :          0 :                            << "brokenInBlock " << brokenInBlock
    1471                 :      34589 :                            << "fixesRemaining " << fixesRemaining << endl;
    1472                 :            : 
    1473                 :      34589 :     int currFocusChangeSgn = totalFocusChange.sgn();
    1474         [ +  + ]:     130954 :     for (BorderVec::const_iterator i = startBlock; i != endBlock; ++i)
    1475                 :            :     {
    1476                 :      96365 :       const Border& b = *i;
    1477                 :            : 
    1478         [ +  - ]:      96365 :       Trace("handleBorders") << b << endl;
    1479                 :            : 
    1480                 :      96365 :       bool makesImprovement =
    1481 [ +  + ][ +  + ]:      96365 :           negErrorChange > 0 || (negErrorChange == 0 && currFocusChangeSgn > 0);
                 [ +  + ]
    1482                 :            : 
    1483         [ +  + ]:      96365 :       if (!makesImprovement)
    1484                 :            :       {
    1485 [ +  + ][ +  + ]:      42809 :         if (b.ownBorder() || minimumFixes > 0)
                 [ +  + ]
    1486                 :            :         {
    1487                 :         90 :           continue;
    1488                 :            :         }
    1489                 :            :       }
    1490                 :            : 
    1491                 :      96275 :       UpdateInfo proposal(nb, nbDir);
    1492         [ +  + ]:      96275 :       if (b.ownBorder())
    1493                 :            :       {
    1494                 :        721 :         proposal.witnessedUpdate(
    1495                 :        721 :             b.d_diff, b.d_bound, -negErrorChange, currFocusChangeSgn);
    1496                 :            :       }
    1497                 :            :       else
    1498                 :            :       {
    1499                 :      95554 :         proposal.update(b.d_diff,
    1500                 :            :                         b.getCoefficient(),
    1501                 :      95554 :                         b.d_bound,
    1502                 :            :                         -negErrorChange,
    1503                 :            :                         currFocusChangeSgn);
    1504                 :            :       }
    1505                 :            : 
    1506 [ +  + ][ -  + ]:      96275 :       if (selected.unbounded() || (this->*pref)(selected, proposal))
         [ +  + ][ +  + ]
    1507                 :            :       {
    1508                 :      57715 :         selected = proposal;
    1509                 :            :       }
    1510                 :      96275 :     }
    1511                 :            : 
    1512                 :      34589 :     effectiveCoefficient += updateCoefficient(startBlock, endBlock);
    1513                 :      34589 :     prevBlockValue = &blockValue;
    1514                 :      34589 :     negErrorChange -= brokenInBlock;
    1515                 :      34589 :   }
    1516                 :      28379 : }
    1517                 :            : 
    1518                 :      34589 : Rational LinearEqualityModule::updateCoefficient(
    1519                 :            :     BorderVec::const_iterator startBlock, BorderVec::const_iterator endBlock)
    1520                 :            : {
    1521                 :            :   // update coefficient
    1522                 :      34589 :   Rational changeToCoefficient(0);
    1523         [ +  + ]:     130954 :   for (BorderVec::const_iterator i = startBlock; i != endBlock; ++i)
    1524                 :            :   {
    1525                 :      96365 :     const Border& curr = *i;
    1526         [ +  + ]:      96365 :     if (curr.ownBorder())
    1527                 :            :     {  // breaking its own bound
    1528         [ +  + ]:        776 :       if (curr.d_upperbound)
    1529                 :            :       {
    1530                 :        604 :         changeToCoefficient -= 1;
    1531                 :            :       }
    1532                 :            :       else
    1533                 :            :       {
    1534                 :        172 :         changeToCoefficient += 1;
    1535                 :            :       }
    1536                 :            :     }
    1537                 :            :     else
    1538                 :            :     {
    1539                 :      95589 :       const Rational& coeff = curr.d_entry->getCoefficient();
    1540         [ +  + ]:      95589 :       if (curr.d_areFixing)
    1541                 :            :       {
    1542         [ +  + ]:      24280 :         if (curr.d_upperbound)
    1543                 :            :         {  // fixing an upper bound
    1544                 :      11107 :           changeToCoefficient += coeff;
    1545                 :            :         }
    1546                 :            :         else
    1547                 :            :         {  // fixing a lower bound
    1548                 :      13173 :           changeToCoefficient -= coeff;
    1549                 :            :         }
    1550                 :            :       }
    1551                 :            :       else
    1552                 :            :       {
    1553         [ +  + ]:      71309 :         if (curr.d_upperbound)
    1554                 :            :         {  // breaking an upper bound
    1555                 :      29614 :           changeToCoefficient -= coeff;
    1556                 :            :         }
    1557                 :            :         else
    1558                 :            :         {
    1559                 :            :           // breaking a lower bound
    1560                 :      41695 :           changeToCoefficient += coeff;
    1561                 :            :         }
    1562                 :            :       }
    1563                 :            :     }
    1564                 :            :   }
    1565                 :      34589 :   return changeToCoefficient;
    1566                 :          0 : }
    1567                 :            : 
    1568                 :      34589 : void LinearEqualityModule::pop_block(BorderHeap& heap,
    1569                 :            :                                      int& brokenInBlock,
    1570                 :            :                                      int& fixesRemaining,
    1571                 :            :                                      int& negErrorChange)
    1572                 :            : {
    1573 [ -  + ][ -  + ]:      34589 :   Assert(heap.more());
                 [ -  - ]
    1574                 :            : 
    1575         [ +  + ]:      34589 :   if (heap.top().d_areFixing)
    1576                 :            :   {
    1577                 :      11965 :     fixesRemaining--;
    1578                 :      11965 :     negErrorChange++;
    1579                 :            :   }
    1580                 :            :   else
    1581                 :            :   {
    1582                 :      22624 :     brokenInBlock++;
    1583                 :            :   }
    1584                 :      34589 :   heap.pop_heap();
    1585                 :      34589 :   const DeltaRational& blockValue = (*heap.end()).d_diff;
    1586                 :            : 
    1587         [ +  + ]:      96365 :   while (heap.more())
    1588                 :            :   {
    1589                 :      77633 :     const Border& top = heap.top();
    1590         [ +  + ]:      77633 :     if (blockValue == top.d_diff)
    1591                 :            :     {
    1592                 :            :       // belongs to the block
    1593         [ +  + ]:      61776 :       if (top.d_areFixing)
    1594                 :            :       {
    1595                 :      12315 :         fixesRemaining--;
    1596                 :      12315 :         negErrorChange++;
    1597                 :            :       }
    1598                 :            :       else
    1599                 :            :       {
    1600                 :      49461 :         brokenInBlock++;
    1601                 :            :       }
    1602                 :      61776 :       heap.pop_heap();
    1603                 :            :     }
    1604                 :            :     else
    1605                 :            :     {
    1606                 :            :       // does not belong to the block
    1607 [ +  + ][ -  + ]:      15857 :       Assert((heap.direction() > 0) ? (blockValue < top.d_diff)
         [ -  + ][ -  - ]
    1608                 :            :                                     : (blockValue > top.d_diff));
    1609                 :      15857 :       break;
    1610                 :            :     }
    1611                 :            :   }
    1612                 :      34589 : }
    1613                 :            : 
    1614                 :       5039 : void LinearEqualityModule::substitutePlusTimesConstant(ArithVar to,
    1615                 :            :                                                        ArithVar from,
    1616                 :            :                                                        const Rational& mult)
    1617                 :            : {
    1618                 :       5039 :   d_tableau.substitutePlusTimesConstant(to, from, mult, d_trackCallback);
    1619                 :       5039 : }
    1620                 :       4541 : void LinearEqualityModule::directlyAddToCoefficient(ArithVar row,
    1621                 :            :                                                     ArithVar col,
    1622                 :            :                                                     const Rational& mult)
    1623                 :            : {
    1624                 :       4541 :   d_tableau.directlyAddToCoefficient(row, col, mult, d_trackCallback);
    1625                 :       4541 : }
    1626                 :            : 
    1627                 :            : }  // namespace arith::linear
    1628                 :            : }  // namespace theory
    1629                 :            : }  // namespace cvc5::internal

Generated by: LCOV version 1.14