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: 620 820 75.6 %
Date: 2026-03-11 10:41:32 Functions: 38 49 77.6 %
Branches: 474 930 51.0 %

           Branch data     Line data    Source code
       1                 :            : /******************************************************************************
       2                 :            :  * This file is part of the cvc5 project.
       3                 :            :  *
       4                 :            :  * Copyright (c) 2009-2026 by the authors listed in the file AUTHORS
       5                 :            :  * in the top-level source directory and their institutional affiliations.
       6                 :            :  * All rights reserved.  See the file COPYING in the top-level source
       7                 :            :  * directory for licensing information.
       8                 :            :  * ****************************************************************************
       9                 :            :  *
      10                 :            :  * 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>(ArithVar x_i, VarPreferenceFunction pf) const;
      27                 :            : template ArithVar LinearEqualityModule::selectSlack<false>(ArithVar x_i, VarPreferenceFunction pf) const;
      28                 :            : 
      29                 :            : template bool LinearEqualityModule::preferWitness<true>(const UpdateInfo& a, const UpdateInfo& b) const;
      30                 :            : template bool LinearEqualityModule::preferWitness<false>(const UpdateInfo& a, const UpdateInfo& b) const;
      31                 :            : 
      32                 :            : 
      33                 :          0 : void Border::output(std::ostream& out) const{
      34                 :            :   out << "{Border"
      35                 :          0 :       << ", " << d_bound->getVariable()
      36                 :          0 :       << ", " << d_bound->getValue()
      37                 :          0 :       << ", " << d_diff
      38                 :          0 :       << ", " << d_areFixing
      39                 :          0 :       << ", " << d_upperbound;
      40         [ -  - ]:          0 :   if(ownBorder()){
      41                 :          0 :     out << ", ownBorder";
      42                 :            :   }else{
      43                 :          0 :     out << ", " << d_entry->getCoefficient();
      44                 :            :   }
      45                 :          0 :   out << ", " << d_bound
      46                 :          0 :       << "}";
      47                 :          0 : }
      48                 :            : 
      49                 :      49981 : LinearEqualityModule::LinearEqualityModule(StatisticsRegistry& sr,
      50                 :            :                                            ArithVariables& vars,
      51                 :            :                                            Tableau& t,
      52                 :            :                                            BoundInfoMap& boundsTracking,
      53                 :      49981 :                                            BasicVarModelUpdateCallBack f)
      54                 :      49981 :     : d_variables(vars),
      55                 :      49981 :       d_tableau(t),
      56                 :      49981 :       d_basicVariableUpdates(f),
      57                 :      49981 :       d_increasing(1),
      58                 :      49981 :       d_decreasing(-1),
      59                 :      49981 :       d_upperBoundDifference(),
      60                 :      49981 :       d_lowerBoundDifference(),
      61                 :      49981 :       d_one(1),
      62                 :      49981 :       d_negOne(-1),
      63                 :      49981 :       d_btracking(boundsTracking),
      64                 :      49981 :       d_areTracking(false),
      65                 :      49981 :       d_trackCallback(this),
      66                 :      49981 :       d_statistics(sr)
      67                 :      49981 : {}
      68                 :            : 
      69                 :      49981 : LinearEqualityModule::Statistics::Statistics(StatisticsRegistry& sr)
      70                 :      49981 :     : d_statPivots(sr.registerInt("theory::arith::pivots")),
      71                 :      49981 :       d_statUpdates(sr.registerInt("theory::arith::updates")),
      72                 :      49981 :       d_pivotTime(sr.registerTimer("theory::arith::pivotTime")),
      73                 :      49981 :       d_adjTime(sr.registerTimer("theory::arith::adjTime")),
      74                 :      49981 :       d_weakeningAttempts(sr.registerInt("theory::arith::weakening::attempts")),
      75                 :      49981 :       d_weakeningSuccesses(sr.registerInt("theory::arith::weakening::success")),
      76                 :      49981 :       d_weakenings(sr.registerInt("theory::arith::weakening::total")),
      77                 :      49981 :       d_weakenTime(sr.registerTimer("theory::arith::weakening::time")),
      78                 :      49981 :       d_forceTime(sr.registerTimer("theory::arith::forcing::time"))
      79                 :            : {
      80                 :      49981 : }
      81                 :            : 
      82                 :    9246350 : void LinearEqualityModule::includeBoundUpdate(ArithVar v, const BoundsInfo& prev){
      83 [ -  + ][ -  + ]:    9246350 :   Assert(!d_areTracking);
                 [ -  - ]
      84                 :            : 
      85                 :    9246350 :   BoundsInfo curr = d_variables.boundsInfo(v);
      86                 :            : 
      87 [ -  + ][ -  + ]:    9246350 :   Assert(prev != curr);
                 [ -  - ]
      88                 :    9246350 :   Tableau::ColIterator basicIter = d_tableau.colIterator(v);
      89         [ +  + ]:   56465840 :   for(; !basicIter.atEnd(); ++basicIter){
      90                 :   47219490 :     const Tableau::Entry& entry = *basicIter;
      91 [ -  + ][ -  + ]:   47219490 :     Assert(entry.getColVar() == v);
                 [ -  - ]
      92                 :   47219490 :     int a_ijSgn = entry.getCoefficient().sgn();
      93                 :            : 
      94                 :   47219490 :     RowIndex ridx = entry.getRowIndex();
      95                 :   47219490 :     BoundsInfo& counts = d_btracking.get(ridx);
      96         [ +  - ]:   47219490 :     Trace("includeBoundUpdate") << d_tableau.rowIndexToBasic(ridx) << " " << counts << " to " ;
      97                 :   47219490 :     counts.addInChange(a_ijSgn, prev, curr);
      98         [ +  - ]:   47219490 :     Trace("includeBoundUpdate") << counts << " " << a_ijSgn << std::endl;
      99                 :            :   }
     100                 :    9246350 : }
     101                 :            : 
     102                 :          0 : void LinearEqualityModule::updateMany(const DenseMap<DeltaRational>& many){
     103         [ -  - ]:          0 :   for(DenseMap<DeltaRational>::const_iterator i = many.begin(), i_end = many.end(); i != i_end; ++i){
     104                 :          0 :     ArithVar nb = *i;
     105         [ -  - ]:          0 :     if(!d_tableau.isBasic(nb)){
     106                 :          0 :       Assert(!d_tableau.isBasic(nb));
     107                 :          0 :       const DeltaRational& newValue = many[nb];
     108         [ -  - ]:          0 :       if(newValue != d_variables.getAssignment(nb)){
     109         [ -  - ]:          0 :         Trace("arith::updateMany")
     110                 :          0 :           << "updateMany:" << nb << " "
     111                 :          0 :           << d_variables.getAssignment(nb) << " to "<< newValue << endl;
     112                 :          0 :         update(nb, newValue);
     113                 :            :       }
     114                 :            :     }
     115                 :            :   }
     116                 :          0 : }
     117                 :            : 
     118                 :            : 
     119                 :            : 
     120                 :            : 
     121                 :          0 : void LinearEqualityModule::applySolution(const DenseSet& newBasis, const DenseMap<DeltaRational>& newValues){
     122                 :          0 :   forceNewBasis(newBasis);
     123                 :          0 :   updateMany(newValues);
     124                 :          0 : }
     125                 :            : 
     126                 :          0 : void LinearEqualityModule::forceNewBasis(const DenseSet& newBasis){
     127                 :          0 :   TimerStat::CodeTimer codeTimer(d_statistics.d_forceTime);
     128                 :          0 :   cout << "force begin" << endl;
     129                 :          0 :   DenseSet needsToBeAdded;
     130         [ -  - ]:          0 :   for(DenseSet::const_iterator i = newBasis.begin(), i_end = newBasis.end(); i != i_end; ++i){
     131                 :          0 :     ArithVar b = *i;
     132         [ -  - ]:          0 :     if(!d_tableau.isBasic(b)){
     133                 :          0 :       needsToBeAdded.add(b);
     134                 :            :     }
     135                 :            :   }
     136                 :            : 
     137         [ -  - ]:          0 :   while(!needsToBeAdded.empty()){
     138                 :          0 :     ArithVar toRemove = ARITHVAR_SENTINEL;
     139                 :          0 :     ArithVar toAdd = ARITHVAR_SENTINEL;
     140                 :          0 :     DenseSet::const_iterator i = needsToBeAdded.begin(), i_end = needsToBeAdded.end();
     141 [ -  - ][ -  - ]:          0 :     for(; toAdd == ARITHVAR_SENTINEL && i != i_end; ++i){
                 [ -  - ]
     142                 :          0 :       ArithVar v = *i;
     143                 :            : 
     144                 :          0 :       Tableau::ColIterator colIter = d_tableau.colIterator(v);
     145         [ -  - ]:          0 :       for(; !colIter.atEnd(); ++colIter){
     146                 :          0 :         const Tableau::Entry& entry = *colIter;
     147                 :          0 :         Assert(entry.getColVar() == v);
     148                 :          0 :         ArithVar b = d_tableau.rowIndexToBasic(entry.getRowIndex());
     149         [ -  - ]:          0 :         if(!newBasis.isMember(b)){
     150                 :          0 :           toAdd = v;
     151 [ -  - ][ -  - ]:          0 :           if(toRemove == ARITHVAR_SENTINEL ||
     152         [ -  - ]:          0 :              d_tableau.basicRowLength(toRemove) > d_tableau.basicRowLength(b)){
     153                 :          0 :             toRemove = b;
     154                 :            :           }
     155                 :            :         }
     156                 :            :       }
     157                 :            :     }
     158                 :          0 :     Assert(toRemove != ARITHVAR_SENTINEL);
     159                 :          0 :     Assert(toAdd != ARITHVAR_SENTINEL);
     160                 :            : 
     161         [ -  - ]:          0 :     Trace("arith::forceNewBasis") << toRemove << " " << toAdd << endl;
     162                 :          0 :     d_tableau.pivot(toRemove, toAdd, d_trackCallback);
     163                 :          0 :     d_basicVariableUpdates(toAdd);
     164                 :            : 
     165         [ -  - ]:          0 :     Trace("arith::forceNewBasis") << needsToBeAdded.size() << "to go" << endl;
     166                 :          0 :     needsToBeAdded.remove(toAdd);
     167                 :            :   }
     168                 :          0 : }
     169                 :            : 
     170                 :     311760 : void LinearEqualityModule::updateUntracked(ArithVar x_i, const DeltaRational& v){
     171 [ -  + ][ -  + ]:     311760 :   Assert(!d_tableau.isBasic(x_i));
                 [ -  - ]
     172 [ -  + ][ -  + ]:     311760 :   Assert(!d_areTracking);
                 [ -  - ]
     173                 :     311760 :   const DeltaRational& assignment_x_i = d_variables.getAssignment(x_i);
     174                 :     311760 :   ++(d_statistics.d_statUpdates);
     175                 :            : 
     176                 :            : 
     177         [ +  - ]:     623520 :   Trace("arith") <<"update " << x_i << ": "
     178                 :     311760 :                  << assignment_x_i << "|-> " << v << endl;
     179                 :     311760 :   DeltaRational diff = v - assignment_x_i;
     180                 :            : 
     181                 :     311760 :   Tableau::ColIterator colIter = d_tableau.colIterator(x_i);
     182         [ +  + ]:    3457834 :   for(; !colIter.atEnd(); ++colIter){
     183                 :    3146074 :     const Tableau::Entry& entry = *colIter;
     184 [ -  + ][ -  + ]:    3146074 :     Assert(entry.getColVar() == x_i);
                 [ -  - ]
     185                 :            : 
     186                 :    3146074 :     ArithVar x_j = d_tableau.rowIndexToBasic(entry.getRowIndex());
     187                 :    3146074 :     const Rational& a_ji = entry.getCoefficient();
     188                 :            : 
     189                 :    3146074 :     const DeltaRational& assignment = d_variables.getAssignment(x_j);
     190                 :    3146074 :     DeltaRational  nAssignment = assignment+(diff * a_ji);
     191                 :    3146074 :     d_variables.setAssignment(x_j, nAssignment);
     192                 :            : 
     193                 :    3146074 :     d_basicVariableUpdates(x_j);
     194                 :    3146074 :   }
     195                 :            : 
     196                 :     311760 :   d_variables.setAssignment(x_i, v);
     197                 :            : 
     198         [ -  + ]:     311760 :   if(TraceIsOn("paranoid:check_tableau")){  debugCheckTableau(); }
     199                 :     311760 : }
     200                 :            : 
     201                 :     364608 : void LinearEqualityModule::updateTracked(ArithVar x_i, const DeltaRational& v){
     202                 :     364608 :   TimerStat::CodeTimer codeTimer(d_statistics.d_adjTime);
     203                 :            : 
     204 [ -  + ][ -  + ]:     364608 :   Assert(!d_tableau.isBasic(x_i));
                 [ -  - ]
     205 [ -  + ][ -  + ]:     364608 :   Assert(d_areTracking);
                 [ -  - ]
     206                 :            : 
     207                 :     364608 :   ++(d_statistics.d_statUpdates);
     208                 :            : 
     209                 :     364608 :   DeltaRational diff =  v - d_variables.getAssignment(x_i);
     210         [ +  - ]:     729216 :   Trace("arith") <<"update " << x_i << ": "
     211                 :     364608 :                  << d_variables.getAssignment(x_i) << "|-> " << v << endl;
     212                 :            : 
     213                 :            : 
     214                 :     364608 :   BoundCounts before = d_variables.atBoundCounts(x_i);
     215                 :     364608 :   d_variables.setAssignment(x_i, v);
     216                 :     364608 :   BoundCounts after = d_variables.atBoundCounts(x_i);
     217                 :            : 
     218                 :     364608 :   bool anyChange = before != after;
     219                 :            : 
     220                 :     364608 :   Tableau::ColIterator colIter = d_tableau.colIterator(x_i);
     221         [ +  + ]:    7216115 :   for(; !colIter.atEnd(); ++colIter){
     222                 :    6851507 :     const Tableau::Entry& entry = *colIter;
     223 [ -  + ][ -  + ]:    6851507 :     Assert(entry.getColVar() == x_i);
                 [ -  - ]
     224                 :            : 
     225                 :    6851507 :     RowIndex ridx = entry.getRowIndex();
     226                 :    6851507 :     ArithVar x_j = d_tableau.rowIndexToBasic(ridx);
     227                 :    6851507 :     const Rational& a_ji = entry.getCoefficient();
     228                 :            : 
     229                 :    6851507 :     const DeltaRational& assignment = d_variables.getAssignment(x_j);
     230                 :    6851507 :     DeltaRational  nAssignment = assignment+(diff * a_ji);
     231         [ +  - ]:    6851507 :     Trace("update") << x_j << " " << a_ji << assignment << " -> " << nAssignment << endl;
     232                 :    6851507 :     BoundCounts xjBefore = d_variables.atBoundCounts(x_j);
     233                 :    6851507 :     d_variables.setAssignment(x_j, nAssignment);
     234                 :    6851507 :     BoundCounts xjAfter = d_variables.atBoundCounts(x_j);
     235                 :            : 
     236 [ -  + ][ -  + ]:    6851507 :     Assert(rowIndexIsTracked(ridx));
                 [ -  - ]
     237                 :    6851507 :     BoundsInfo& next_bc_k = d_btracking.get(ridx);
     238         [ +  + ]:    6851507 :     if(anyChange){
     239                 :    4763064 :       next_bc_k.addInAtBoundChange(a_ji.sgn(), before, after);
     240                 :            :     }
     241         [ +  + ]:    6851507 :     if(xjBefore != xjAfter){
     242                 :     862032 :       next_bc_k.addInAtBoundChange(-1, xjBefore, xjAfter);
     243                 :            :     }
     244                 :            : 
     245                 :    6851507 :     d_basicVariableUpdates(x_j);
     246                 :    6851507 :   }
     247                 :            : 
     248         [ -  + ]:     364608 :   if(TraceIsOn("paranoid:check_tableau")){  debugCheckTableau(); }
     249                 :     364608 : }
     250                 :            : 
     251                 :     364468 : void LinearEqualityModule::pivotAndUpdate(ArithVar x_i, ArithVar x_j, const DeltaRational& x_i_value){
     252 [ -  + ][ -  + ]:     364468 :   Assert(x_i != x_j);
                 [ -  - ]
     253                 :            : 
     254                 :     364468 :   TimerStat::CodeTimer codeTimer(d_statistics.d_pivotTime);
     255                 :            : 
     256         [ -  + ]:     364468 :   if(TraceIsOn("arith::tracking::pre")){
     257         [ -  - ]:          0 :     Trace("arith::tracking") << "pre update" << endl;
     258                 :          0 :     debugCheckTracking();
     259                 :            :   }
     260                 :            : 
     261         [ -  + ]:     364468 :   if(TraceIsOn("arith::simplex:row")){ debugPivot(x_i, x_j); }
     262                 :            : 
     263                 :     364468 :   RowIndex ridx = d_tableau.basicToRowIndex(x_i);
     264                 :     364468 :   const Tableau::Entry& entry_ij =  d_tableau.findEntry(ridx, x_j);
     265 [ -  + ][ -  + ]:     364468 :   Assert(!entry_ij.blank());
                 [ -  - ]
     266                 :            : 
     267                 :     364468 :   const Rational& a_ij = entry_ij.getCoefficient();
     268                 :     364468 :   const DeltaRational& betaX_i = d_variables.getAssignment(x_i);
     269                 :     364468 :   DeltaRational theta = (x_i_value - betaX_i)/a_ij;
     270                 :     364468 :   DeltaRational x_j_value = d_variables.getAssignment(x_j) + theta;
     271                 :            : 
     272                 :     364468 :   updateTracked(x_j, x_j_value);
     273                 :            : 
     274         [ -  + ]:     364468 :   if(TraceIsOn("arith::tracking::mid")){
     275         [ -  - ]:          0 :     Trace("arith::tracking") << "postupdate prepivot" << endl;
     276                 :          0 :     debugCheckTracking();
     277                 :            :   }
     278                 :            : 
     279                 :            :   // Pivots
     280                 :     364468 :   ++(d_statistics.d_statPivots);
     281                 :            : 
     282                 :     364468 :   d_tableau.pivot(x_i, x_j, d_trackCallback);
     283                 :            : 
     284         [ -  + ]:     364468 :   if(TraceIsOn("arith::tracking::post")){
     285         [ -  - ]:          0 :     Trace("arith::tracking") << "postpivot" << endl;
     286                 :          0 :     debugCheckTracking();
     287                 :            :   }
     288                 :            : 
     289                 :     364468 :   d_basicVariableUpdates(x_j);
     290                 :            : 
     291         [ -  + ]:     364468 :   if(TraceIsOn("matrix")){
     292                 :          0 :     d_tableau.printMatrix();
     293                 :            :   }
     294                 :     364468 : }
     295                 :            : 
     296                 :      90190 : uint32_t LinearEqualityModule::updateProduct(const UpdateInfo& inf) const {
     297                 :      90190 :   uint32_t colLen = d_tableau.getColLength(inf.nonbasic());
     298         [ +  + ]:      90190 :   if(inf.describesPivot()){
     299 [ -  + ][ -  + ]:      87950 :     Assert(inf.leaving() != inf.nonbasic());
                 [ -  - ]
     300                 :      87950 :     return colLen + d_tableau.basicRowLength(inf.leaving());
     301                 :            :   }else{
     302                 :       2240 :     return colLen;
     303                 :            :   }
     304                 :            : }
     305                 :            : 
     306                 :          0 : void LinearEqualityModule::debugCheckTracking(){
     307                 :          0 :   Tableau::BasicIterator basicIter = d_tableau.beginBasic(),
     308                 :          0 :     endIter = d_tableau.endBasic();
     309         [ -  - ]:          0 :   for(; basicIter != endIter; ++basicIter){
     310                 :          0 :     ArithVar basic = *basicIter;
     311         [ -  - ]:          0 :     Trace("arith::tracking") << "arith::tracking row basic: " << basic << endl;
     312                 :            : 
     313                 :          0 :     for(Tableau::RowIterator iter = d_tableau.basicRowIterator(basic); !iter.atEnd() && TraceIsOn("arith::tracking"); ++iter){
     314                 :          0 :       const Tableau::Entry& entry = *iter;
     315                 :            : 
     316                 :          0 :       ArithVar var = entry.getColVar();
     317                 :          0 :       const Rational& coeff = entry.getCoefficient();
     318                 :          0 :       DeltaRational beta = d_variables.getAssignment(var);
     319         [ -  - ]:          0 :       Trace("arith::tracking") << var << " " << d_variables.boundsInfo(var)
     320                 :          0 :                                << " " << beta << coeff;
     321         [ -  - ]:          0 :       if(d_variables.hasLowerBound(var)){
     322         [ -  - ]:          0 :         Trace("arith::tracking") << "(lb " << d_variables.getLowerBound(var) << ")";
     323                 :            :       }
     324         [ -  - ]:          0 :       if(d_variables.hasUpperBound(var)){
     325         [ -  - ]:          0 :         Trace("arith::tracking") << "(up " << d_variables.getUpperBound(var) << ")";
     326                 :            :       }
     327         [ -  - ]:          0 :       Trace("arith::tracking") << endl;
     328                 :          0 :     }
     329         [ -  - ]:          0 :     Trace("arith::tracking") << "end row"<< endl;
     330                 :            : 
     331         [ -  - ]:          0 :     if(basicIsTracked(basic)){
     332                 :          0 :       RowIndex ridx = d_tableau.basicToRowIndex(basic);
     333                 :          0 :       BoundsInfo computed = computeRowBoundInfo(ridx, false);
     334         [ -  - ]:          0 :       Trace("arith::tracking")
     335                 :          0 :         << "computed " << computed
     336                 :          0 :         << " tracking " << d_btracking[ridx] << endl;
     337                 :          0 :       Assert(computed == d_btracking[ridx]);
     338                 :            :     }
     339                 :            :   }
     340                 :          0 : }
     341                 :            : 
     342                 :          0 : void LinearEqualityModule::debugPivot(ArithVar x_i, ArithVar x_j){
     343         [ -  - ]:          0 :   Trace("arith::pivot") << "debugPivot("<< x_i  <<"|->"<< x_j << ")" << endl;
     344                 :            : 
     345         [ -  - ]:          0 :   for(Tableau::RowIterator iter = d_tableau.basicRowIterator(x_i); !iter.atEnd(); ++iter){
     346                 :          0 :     const Tableau::Entry& entry = *iter;
     347                 :            : 
     348                 :          0 :     ArithVar var = entry.getColVar();
     349                 :          0 :     const Rational& coeff = entry.getCoefficient();
     350                 :          0 :     DeltaRational beta = d_variables.getAssignment(var);
     351         [ -  - ]:          0 :     Trace("arith::pivot") << var << beta << coeff;
     352         [ -  - ]:          0 :     if(d_variables.hasLowerBound(var)){
     353         [ -  - ]:          0 :       Trace("arith::pivot") << "(lb " << d_variables.getLowerBound(var) << ")";
     354                 :            :     }
     355         [ -  - ]:          0 :     if(d_variables.hasUpperBound(var)){
     356         [ -  - ]:          0 :       Trace("arith::pivot") << "(up " << d_variables.getUpperBound(var) << ")";
     357                 :            :     }
     358         [ -  - ]:          0 :     Trace("arith::pivot") << endl;
     359                 :          0 :   }
     360         [ -  - ]:          0 :   Trace("arith::pivot") << "end row"<< endl;
     361                 :          0 : }
     362                 :            : 
     363                 :            : /**
     364                 :            :  * This check is quite expensive.
     365                 :            :  * It should be wrapped in a TraceIsOn() guard.
     366                 :            :  *   if(TraceIsOn("paranoid:check_tableau")){
     367                 :            :  *      checkTableau();
     368                 :            :  *   }
     369                 :            :  */
     370                 :          0 : void LinearEqualityModule::debugCheckTableau(){
     371                 :          0 :   Tableau::BasicIterator basicIter = d_tableau.beginBasic(),
     372                 :          0 :     endIter = d_tableau.endBasic();
     373         [ -  - ]:          0 :   for(; basicIter != endIter; ++basicIter){
     374                 :          0 :     ArithVar basic = *basicIter;
     375                 :          0 :     DeltaRational sum;
     376         [ -  - ]:          0 :     Trace("paranoid:check_tableau") << "starting row" << basic << endl;
     377                 :          0 :     Tableau::RowIterator nonbasicIter = d_tableau.basicRowIterator(basic);
     378         [ -  - ]:          0 :     for(; !nonbasicIter.atEnd(); ++nonbasicIter){
     379                 :          0 :       const Tableau::Entry& entry = *nonbasicIter;
     380                 :          0 :       ArithVar nonbasic = entry.getColVar();
     381         [ -  - ]:          0 :       if(basic == nonbasic) continue;
     382                 :            : 
     383                 :          0 :       const Rational& coeff = entry.getCoefficient();
     384                 :          0 :       DeltaRational beta = d_variables.getAssignment(nonbasic);
     385         [ -  - ]:          0 :       Trace("paranoid:check_tableau") << nonbasic << beta << coeff<<endl;
     386                 :          0 :       sum = sum + (beta*coeff);
     387                 :          0 :     }
     388                 :          0 :     DeltaRational shouldBe = d_variables.getAssignment(basic);
     389         [ -  - ]:          0 :     Trace("paranoid:check_tableau") << "ending row" << sum
     390                 :          0 :                                     << "," << shouldBe << endl;
     391                 :            : 
     392                 :          0 :     Assert(sum == shouldBe);
     393                 :          0 :   }
     394                 :          0 : }
     395                 :            : 
     396                 :     820176 : DeltaRational LinearEqualityModule::computeRowBound(RowIndex ridx, bool rowUb, ArithVar skip) const {
     397                 :    1640352 :   DeltaRational sum(0,0);
     398         [ +  + ]:    5312192 :   for(Tableau::RowIterator i = d_tableau.ridRowIterator(ridx); !i.atEnd(); ++i){
     399                 :    4492016 :     const Tableau::Entry& entry = (*i);
     400                 :    4492016 :     ArithVar v = entry.getColVar();
     401         [ +  + ]:    4492016 :     if(v == skip){ continue; }
     402                 :            : 
     403                 :    3892838 :     const Rational& coeff =  entry.getCoefficient();
     404                 :    3892838 :     bool vUb = (rowUb == (coeff.sgn() > 0));
     405                 :            : 
     406         [ +  + ]:    3892838 :     const DeltaRational& bound = vUb ?
     407                 :    1939339 :       d_variables.getUpperBound(v):
     408                 :    1953499 :       d_variables.getLowerBound(v);
     409                 :            : 
     410                 :    3892838 :     DeltaRational diff = bound * coeff;
     411                 :    3892838 :     sum = sum + diff;
     412                 :    3892838 :   }
     413                 :     820176 :   return sum;
     414                 :          0 : }
     415                 :            : 
     416                 :            : /**
     417                 :            :  * Computes the value of a basic variable using the current assignment.
     418                 :            :  */
     419                 :     396233 : DeltaRational LinearEqualityModule::computeRowValue(ArithVar x, bool useSafe) const{
     420 [ -  + ][ -  + ]:     396233 :   Assert(d_tableau.isBasic(x));
                 [ -  - ]
     421                 :     396233 :   DeltaRational sum(0);
     422                 :            : 
     423         [ +  + ]:    2351650 :   for(Tableau::RowIterator i = d_tableau.basicRowIterator(x); !i.atEnd(); ++i){
     424                 :    1955417 :     const Tableau::Entry& entry = (*i);
     425                 :    1955417 :     ArithVar nonbasic = entry.getColVar();
     426         [ +  + ]:    1955417 :     if(nonbasic == x) continue;
     427                 :    1559184 :     const Rational& coeff = entry.getCoefficient();
     428                 :            : 
     429                 :    1559184 :     const DeltaRational& assignment = d_variables.getAssignment(nonbasic, useSafe);
     430                 :    1559184 :     sum = sum + (assignment * coeff);
     431                 :            :   }
     432                 :     396233 :   return sum;
     433                 :          0 : }
     434                 :            : 
     435                 :    8107063 : const Tableau::Entry* LinearEqualityModule::rowLacksBound(RowIndex ridx, bool rowUb, ArithVar skip){
     436                 :    8107063 :   Tableau::RowIterator iter = d_tableau.ridRowIterator(ridx);
     437         [ +  + ]:   43027502 :   for(; !iter.atEnd(); ++iter){
     438                 :   43026894 :     const Tableau::Entry& entry = *iter;
     439                 :            : 
     440                 :   43026894 :     ArithVar var = entry.getColVar();
     441         [ +  + ]:   43026894 :     if(var == skip) { continue; }
     442                 :            : 
     443                 :   43025988 :     int sgn = entry.getCoefficient().sgn();
     444                 :   43025988 :     bool selectUb = (rowUb == (sgn > 0));
     445         [ +  + ]:   43025988 :     bool hasBound = selectUb ?
     446                 :   21722556 :       d_variables.hasUpperBound(var):
     447                 :   21303432 :       d_variables.hasLowerBound(var);
     448         [ +  + ]:   43025988 :     if(!hasBound){
     449                 :    8106455 :       return &entry;
     450                 :            :     }
     451                 :            :   }
     452                 :        608 :   return NULL;
     453                 :            : }
     454                 :            : 
     455                 :        106 : void LinearEqualityModule::propagateBasicFromRow(NodeManager* nm,
     456                 :            :                                                  ConstraintP c,
     457                 :            :                                                  bool produceProofs)
     458                 :            : {
     459 [ -  + ][ -  + ]:        106 :   Assert(c != NullConstraint);
                 [ -  - ]
     460 [ +  + ][ +  - ]:        106 :   Assert(c->isUpperBound() || c->isLowerBound());
         [ -  + ][ -  + ]
                 [ -  - ]
     461 [ -  + ][ -  + ]:        106 :   Assert(!c->assertedToTheTheory());
                 [ -  - ]
     462 [ -  + ][ -  + ]:        106 :   Assert(!c->hasProof());
                 [ -  - ]
     463                 :            : 
     464                 :        106 :   bool upperBound = c->isUpperBound();
     465                 :        106 :   ArithVar basic = c->getVariable();
     466                 :        106 :   RowIndex ridx = d_tableau.basicToRowIndex(basic);
     467                 :            : 
     468                 :        106 :   ConstraintCPVec bounds;
     469         [ -  + ]:        106 :   RationalVectorP coeffs = produceProofs ? new RationalVector() : nullptr;
     470                 :        106 :   propagateRow(bounds, ridx, upperBound, c, coeffs);
     471                 :        106 :   c->impliedByFarkas(nm, bounds, coeffs, false);
     472                 :        106 :   c->tryToPropagate();
     473                 :            : 
     474 [ -  + ][ -  - ]:        106 :   if(coeffs != RationalVectorPSentinel) { delete coeffs; }
     475                 :        106 : }
     476                 :            : 
     477                 :            : /* An explanation of the farkas coefficients.
     478                 :            :  *
     479                 :            :  * We are proving c using the other variables on the row.
     480                 :            :  * The proof is in terms of the other constraints and the negation of c, ~c.
     481                 :            :  *
     482                 :            :  * A row has the form:
     483                 :            :  *   sum a_i * x_i  = 0
     484                 :            :  * or
     485                 :            :  *   sx + sum r y + sum q z = 0
     486                 :            :  * where r > 0 and q < 0.
     487                 :            :  *
     488                 :            :  * If rowUp, we are proving c
     489                 :            :  *   g = sum r u_y + sum q l_z
     490                 :            :  *   and c is entailed by -sx <= g
     491                 :            :  * If !rowUp, we are proving c
     492                 :            :  *   g = sum r l_y + sum q u_z
     493                 :            :  *   and c is entailed by -sx >= g
     494                 :            :  *
     495                 :            :  *             | s     | c         | ~c       | u_i     | l_i
     496                 :            :  *   if  rowUp | s > 0 | x >= -g/s | x < -g/s | a_i > 0 | a_i < 0
     497                 :            :  *   if  rowUp | s < 0 | x <= -g/s | x > -g/s | a_i > 0 | a_i < 0
     498                 :            :  *   if !rowUp | s > 0 | x <= -g/s | x > -g/s | a_i < 0 | a_i > 0
     499                 :            :  *   if !rowUp | s < 0 | x >= -g/s | x < -g/s | a_i < 0 | a_i > 0
     500                 :            :  *
     501                 :            :  *
     502                 :            :  * Thus we treat !rowUp as multiplying the row by -1 and rowUp as 1
     503                 :            :  * for the entire row.
     504                 :            :  */
     505                 :     238536 : void LinearEqualityModule::propagateRow(ConstraintCPVec& into, RowIndex ridx, bool rowUp, ConstraintP c, RationalVectorP farkas){
     506 [ -  + ][ -  + ]:     238536 :   Assert(!c->assertedToTheTheory());
                 [ -  - ]
     507 [ -  + ][ -  + ]:     238536 :   Assert(c->canBePropagated());
                 [ -  - ]
     508 [ -  + ][ -  + ]:     238536 :   Assert(!c->hasProof());
                 [ -  - ]
     509                 :            : 
     510         [ +  + ]:     238536 :   if(farkas != RationalVectorPSentinel){
     511 [ -  + ][ -  + ]:     163063 :     Assert(farkas->empty());
                 [ -  - ]
     512                 :     163063 :     farkas->push_back(Rational(0));
     513                 :            :   }
     514                 :            : 
     515                 :     238536 :   ArithVar v = c->getVariable();
     516         [ +  - ]:     477072 :   Trace("arith::propagateRow") << "LinearEqualityModule::propagateRow("
     517                 :     238536 :                                    << ridx << ", " << rowUp << ", " << v << ") start" << endl;
     518                 :            : 
     519         [ +  + ]:     238536 :   const Rational& multiple = rowUp ? d_one : d_negOne;
     520                 :            : 
     521         [ +  - ]:     238536 :   Trace("arith::propagateRow") << "multiple: " << multiple << endl;
     522                 :            : 
     523                 :     238536 :   Tableau::RowIterator iter = d_tableau.ridRowIterator(ridx);
     524         [ +  + ]:    1913683 :   for(; !iter.atEnd(); ++iter){
     525                 :    1675147 :     const Tableau::Entry& entry = *iter;
     526                 :    1675147 :     ArithVar nonbasic = entry.getColVar();
     527                 :    1675147 :     const Rational& a_ij = entry.getCoefficient();
     528                 :    1675147 :     int sgn = a_ij.sgn();
     529 [ -  + ][ -  + ]:    1675147 :     Assert(sgn != 0);
                 [ -  - ]
     530         [ +  + ]:    1675147 :     bool selectUb = rowUp ? (sgn > 0) : (sgn < 0);
     531                 :            : 
     532 [ +  + ][ +  + ]:    1675147 :     Assert(nonbasic != v || (rowUp && a_ij.sgn() > 0 && c->isLowerBound())
         [ +  + ][ +  + ]
         [ +  - ][ +  + ]
         [ +  + ][ +  + ]
         [ +  - ][ +  + ]
         [ +  - ][ +  + ]
         [ +  + ][ +  - ]
         [ +  + ][ +  + ]
         [ +  - ][ +  + ]
         [ +  + ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ -  + ][ -  + ]
                 [ -  - ]
     533                 :            :            || (rowUp && a_ij.sgn() < 0 && c->isUpperBound())
     534                 :            :            || (!rowUp && a_ij.sgn() > 0 && c->isUpperBound())
     535                 :            :            || (!rowUp && a_ij.sgn() < 0 && c->isLowerBound()));
     536                 :            : 
     537         [ -  + ]:    1675147 :     if(TraceIsOn("arith::propagateRow")){
     538         [ -  - ]:          0 :       if(nonbasic == v){
     539         [ -  - ]:          0 :         Trace("arith::propagateRow") << "(target) "
     540                 :          0 :                                      << rowUp << " "
     541                 :          0 :                                      << a_ij.sgn() << " "
     542                 :          0 :                                      << c->isLowerBound() << " "
     543                 :          0 :                                      << c->isUpperBound() << endl;
     544                 :            : 
     545         [ -  - ]:          0 :         Trace("arith::propagateRow") << "(target) ";
     546                 :            :       }
     547         [ -  - ]:          0 :       Trace("arith::propagateRow") << "propagateRow " << a_ij << " * " << nonbasic ;
     548                 :            :     }
     549                 :            : 
     550         [ +  + ]:    1675147 :     if(nonbasic == v){
     551         [ +  + ]:     238536 :       if(farkas != RationalVectorPSentinel){
     552 [ -  + ][ -  + ]:     163063 :         Assert(farkas->front().isZero());
                 [ -  - ]
     553                 :     163063 :         Rational multAij = multiple * a_ij;
     554         [ +  - ]:     163063 :         Trace("arith::propagateRow") << "(" << multAij << ") ";
     555                 :     163063 :         farkas->front() = multAij;
     556                 :     163063 :       }
     557                 :            : 
     558         [ +  - ]:     238536 :       Trace("arith::propagateRow") << c << endl;
     559                 :            :     }else{
     560                 :            : 
     561                 :            :       ConstraintCP bound = selectUb
     562                 :     664419 :         ? d_variables.getUpperBoundConstraint(nonbasic)
     563         [ +  + ]:    1436611 :         : d_variables.getLowerBoundConstraint(nonbasic);
     564                 :            : 
     565         [ +  + ]:    1436611 :       if(farkas != RationalVectorPSentinel){
     566                 :     967880 :         Rational multAij = multiple * a_ij;
     567         [ +  - ]:     967880 :         Trace("arith::propagateRow") << "(" << multAij << ") ";
     568                 :     967880 :         farkas->push_back(multAij);
     569                 :     967880 :       }
     570 [ -  + ][ -  + ]:    1436611 :       Assert(bound != NullConstraint);
                 [ -  - ]
     571         [ +  - ]:    1436611 :       Trace("arith::propagateRow") << bound << endl;
     572                 :    1436611 :       into.push_back(bound);
     573                 :            :     }
     574                 :            :   }
     575         [ +  - ]:     477072 :   Trace("arith::propagateRow") << "LinearEqualityModule::propagateRow("
     576                 :     238536 :                                    << ridx << ", " << rowUp << ", " << v << ") done" << endl;
     577                 :            : 
     578                 :     238536 : }
     579                 :            : 
     580                 :    1287170 : ConstraintP LinearEqualityModule::weakestExplanation(bool aboveUpper, DeltaRational& surplus, ArithVar v, const Rational& coeff, bool& anyWeakening, ArithVar basic) const {
     581                 :            : 
     582                 :    1287170 :   int sgn = coeff.sgn();
     583         [ +  + ]:    1287170 :   bool ub = aboveUpper?(sgn < 0) : (sgn > 0);
     584                 :            : 
     585         [ +  + ]:    1287170 :   ConstraintP c = ub ?
     586                 :     433974 :     d_variables.getUpperBoundConstraint(v) :
     587                 :    1287170 :     d_variables.getLowerBoundConstraint(v);
     588                 :            : 
     589                 :            :   bool weakened;
     590         [ +  + ]:    1459978 :   do{
     591                 :    1459978 :     const DeltaRational& bound = c->getValue();
     592                 :            : 
     593                 :    1459978 :     weakened = false;
     594                 :            : 
     595         [ +  + ]:    1459978 :     ConstraintP weaker = ub?
     596                 :     546289 :       c->getStrictlyWeakerUpperBound(true, true):
     597                 :     913689 :       c->getStrictlyWeakerLowerBound(true, true);
     598                 :            : 
     599         [ +  + ]:    1459978 :     if(weaker != NullConstraint){
     600                 :     354797 :       const DeltaRational& weakerBound = weaker->getValue();
     601                 :            : 
     602         [ +  + ]:     354797 :       DeltaRational diff = aboveUpper ? bound - weakerBound : weakerBound - bound;
     603                 :            :       //if var == basic,
     604                 :            :       //  if aboveUpper, weakerBound > bound, multiply by -1
     605                 :            :       //  if !aboveUpper, weakerBound < bound, multiply by -1
     606                 :     354797 :       diff = diff * coeff;
     607         [ +  + ]:     354797 :       if(surplus > diff){
     608                 :     172808 :         ++d_statistics.d_weakenings;
     609                 :     172808 :         weakened = true;
     610                 :     172808 :         anyWeakening = true;
     611                 :     172808 :         surplus = surplus - diff;
     612                 :            : 
     613         [ +  - ]:     172808 :         Trace("arith::weak") << "found:" << endl;
     614         [ +  + ]:     172808 :         if(v == basic){
     615         [ +  - ]:      18454 :           Trace("arith::weak") << "  basic: ";
     616                 :            :         }
     617         [ +  - ]:     345616 :         Trace("arith::weak") << "  " << surplus << " "<< diff  << endl
     618                 :          0 :                              << "  " << bound << c << endl
     619                 :     172808 :                              << "  " << weakerBound << weaker << endl;
     620                 :            : 
     621 [ -  + ][ -  + ]:     172808 :         Assert(diff.sgn() > 0);
                 [ -  - ]
     622                 :     172808 :         c = weaker;
     623                 :            :       }
     624                 :     354797 :     }
     625                 :            :   }while(weakened);
     626                 :            : 
     627                 :    1287170 :   return c;
     628                 :            : }
     629                 :            : 
     630                 :            : /* An explanation of the farkas coefficients.
     631                 :            :  *
     632                 :            :  * We are proving a conflict on the basic variable x_b.
     633                 :            :  * If aboveUpper, then the conflict is with the constraint c : x_b <= u_b.
     634                 :            :  * If !aboveUpper, then the conflict is with the constraint c : x_b >= l_b.
     635                 :            :  *
     636                 :            :  * A row has the form:
     637                 :            :  *   -x_b sum a_i * x_i  = 0
     638                 :            :  * or
     639                 :            :  *   -x_b + sum r y + sum q z = 0,
     640                 :            :  *    x_b = sum r y + sum q z
     641                 :            :  * where r > 0 and q < 0.
     642                 :            :  *
     643                 :            :  *
     644                 :            :  * If !aboveUp, we are proving ~c: x_b < l_b
     645                 :            :  *   g = sum r u_y + sum q l_z
     646                 :            :  *   x_b <= g < l_b
     647                 :            :  *   and ~c is entailed by x_b <= g
     648                 :            :  *
     649                 :            :  * If aboveUp, we are proving ~c : x_b > u_b
     650                 :            :  *   g = sum r l_y + sum q u_z
     651                 :            :  *   x_b >= g > u_b
     652                 :            :  *   and ~c is entailed by x_b >= g
     653                 :            :  *
     654                 :            :  *
     655                 :            :  *               | s     | c         | ~c       | u_i     | l_i
     656                 :            :  *   if !aboveUp | s > 0 | x >= -g/s | x < -g/s | a_i > 0 | a_i < 0
     657                 :            :  *   if !aboveUp | s < 0 | x <= -g/s | x > -g/s | a_i > 0 | a_i < 0
     658                 :            :  *   if  aboveUp | s > 0 | x <= -g/s | x > -g/s | a_i < 0 | a_i > 0
     659                 :            :  *   if  aboveUp | s < 0 | x >= -g/s | x < -g/s | a_i < 0 | a_i > 0
     660                 :            :  *
     661                 :            :  * Thus we treat aboveUp as multiplying the row by -1 and !aboveUp as 1
     662                 :            :  * for the entire row.
     663                 :            :  */
     664                 :     103498 : ConstraintCP LinearEqualityModule::minimallyWeakConflict(
     665                 :            :     NodeManager* nm,
     666                 :            :     bool aboveUpper,
     667                 :            :     ArithVar basicVar,
     668                 :            :     FarkasConflictBuilder& fcs) const
     669                 :            : {
     670 [ -  + ][ -  + ]:     103498 :   Assert(!fcs.underConstruction());
                 [ -  - ]
     671                 :     103498 :   TimerStat::CodeTimer codeTimer(d_statistics.d_weakenTime);
     672                 :            : 
     673         [ +  - ]:     206996 :   Trace("arith::weak") << "LinearEqualityModule::minimallyWeakConflict("
     674                 :     103498 :                        << aboveUpper <<", "<< basicVar << ", ...) start" << endl;
     675                 :            : 
     676         [ +  + ]:     103498 :   const Rational& adjustSgn = aboveUpper ? d_negOne : d_one;
     677                 :     103498 :   const DeltaRational& assignment = d_variables.getAssignment(basicVar);
     678                 :     103498 :   DeltaRational surplus;
     679         [ +  + ]:     103498 :   if(aboveUpper){
     680 [ -  + ][ -  + ]:      49852 :     Assert(d_variables.hasUpperBound(basicVar));
                 [ -  - ]
     681 [ -  + ][ -  + ]:      49852 :     Assert(assignment > d_variables.getUpperBound(basicVar));
                 [ -  - ]
     682                 :      49852 :     surplus = assignment - d_variables.getUpperBound(basicVar);
     683                 :            :   }else{
     684 [ -  + ][ -  + ]:      53646 :     Assert(d_variables.hasLowerBound(basicVar));
                 [ -  - ]
     685 [ -  + ][ -  + ]:      53646 :     Assert(assignment < d_variables.getLowerBound(basicVar));
                 [ -  - ]
     686                 :      53646 :     surplus = d_variables.getLowerBound(basicVar) - assignment;
     687                 :            :   }
     688                 :            : 
     689                 :     103498 :   bool anyWeakenings = false;
     690         [ +  + ]:    1390668 :   for(Tableau::RowIterator i = d_tableau.basicRowIterator(basicVar); !i.atEnd(); ++i){
     691                 :    1287170 :     const Tableau::Entry& entry = *i;
     692                 :    1287170 :     ArithVar v = entry.getColVar();
     693                 :    1287170 :     const Rational& coeff = entry.getCoefficient();
     694                 :    1287170 :     bool weakening = false;
     695                 :    1287170 :     ConstraintP c = weakestExplanation(aboveUpper, surplus, v, coeff, weakening, basicVar);
     696         [ +  - ]:    2574340 :     Trace("arith::weak") << "weak : " << weakening << " "
     697                 :    1287170 :                          << c->assertedToTheTheory() << " "
     698                 :          0 :                          << d_variables.getAssignment(v) << " "
     699                 :    1287170 :                          << c << endl;
     700 [ +  + ][ +  + ]:    1287170 :     anyWeakenings = anyWeakenings || weakening;
     701                 :            : 
     702                 :    1287170 :     fcs.addConstraint(c, coeff, adjustSgn);
     703         [ +  + ]:    1287170 :     if(basicVar == v){
     704 [ -  + ][ -  + ]:     103498 :       Assert(!c->negationHasProof());
                 [ -  - ]
     705                 :     103498 :       fcs.makeLastConsequent();
     706                 :            :     }
     707                 :            :   }
     708 [ -  + ][ -  + ]:     103498 :   Assert(fcs.consequentIsSet());
                 [ -  - ]
     709                 :            : 
     710                 :     103498 :   ConstraintCP conflicted = fcs.commitConflict(nm);
     711                 :            : 
     712                 :     103498 :   ++d_statistics.d_weakeningAttempts;
     713         [ +  + ]:     103498 :   if(anyWeakenings){
     714                 :      79715 :     ++d_statistics.d_weakeningSuccesses;
     715                 :            :   }
     716         [ +  - ]:     206996 :   Trace("arith::weak") << "LinearEqualityModule::minimallyWeakConflict("
     717                 :     103498 :                        << aboveUpper <<", "<< basicVar << ", ...) done" << endl;
     718                 :     103498 :   return conflicted;
     719                 :     103498 : }
     720                 :            : 
     721                 :     219954 : ArithVar LinearEqualityModule::minVarOrder(ArithVar x, ArithVar y) const {
     722 [ -  + ][ -  + ]:     219954 :   Assert(x != ARITHVAR_SENTINEL);
                 [ -  - ]
     723 [ -  + ][ -  + ]:     219954 :   Assert(y != ARITHVAR_SENTINEL);
                 [ -  - ]
     724         [ +  + ]:     219954 :   if(x <= y){
     725                 :     130860 :     return x;
     726                 :            :   } else {
     727                 :      89094 :     return y;
     728                 :            :   }
     729                 :            : }
     730                 :            : 
     731                 :    1337448 : ArithVar LinearEqualityModule::minColLength(ArithVar x, ArithVar y) const {
     732 [ -  + ][ -  + ]:    1337448 :   Assert(x != ARITHVAR_SENTINEL);
                 [ -  - ]
     733 [ -  + ][ -  + ]:    1337448 :   Assert(y != ARITHVAR_SENTINEL);
                 [ -  - ]
     734 [ -  + ][ -  + ]:    1337448 :   Assert(!d_tableau.isBasic(x));
                 [ -  - ]
     735 [ -  + ][ -  + ]:    1337448 :   Assert(!d_tableau.isBasic(y));
                 [ -  - ]
     736                 :    1337448 :   uint32_t xLen = d_tableau.getColLength(x);
     737                 :    1337448 :   uint32_t yLen = d_tableau.getColLength(y);
     738         [ +  + ]:    1337448 :   if( xLen > yLen){
     739                 :     214338 :      return y;
     740         [ +  + ]:    1123110 :   } else if( xLen== yLen ){
     741                 :     218596 :     return minVarOrder(x,y);
     742                 :            :   }else{
     743                 :     904514 :     return x;
     744                 :            :   }
     745                 :            : }
     746                 :            : 
     747                 :          0 : ArithVar LinearEqualityModule::minRowLength(ArithVar x, ArithVar y) const {
     748                 :          0 :   Assert(x != ARITHVAR_SENTINEL);
     749                 :          0 :   Assert(y != ARITHVAR_SENTINEL);
     750                 :          0 :   Assert(d_tableau.isBasic(x));
     751                 :          0 :   Assert(d_tableau.isBasic(y));
     752                 :          0 :   uint32_t xLen = d_tableau.basicRowLength(x);
     753                 :          0 :   uint32_t yLen = d_tableau.basicRowLength(y);
     754         [ -  - ]:          0 :   if( xLen > yLen){
     755                 :          0 :      return y;
     756         [ -  - ]:          0 :   } else if( xLen== yLen ){
     757                 :          0 :     return minVarOrder(x,y);
     758                 :            :   }else{
     759                 :          0 :     return x;
     760                 :            :   }
     761                 :            : }
     762                 :            : 
     763                 :    1420543 : ArithVar LinearEqualityModule::minBoundAndColLength(ArithVar x, ArithVar y) const{
     764 [ -  + ][ -  + ]:    1420543 :   Assert(x != ARITHVAR_SENTINEL);
                 [ -  - ]
     765 [ -  + ][ -  + ]:    1420543 :   Assert(y != ARITHVAR_SENTINEL);
                 [ -  - ]
     766 [ -  + ][ -  + ]:    1420543 :   Assert(!d_tableau.isBasic(x));
                 [ -  - ]
     767 [ -  + ][ -  + ]:    1420543 :   Assert(!d_tableau.isBasic(y));
                 [ -  - ]
     768 [ +  + ][ +  + ]:    1420543 :   if(d_variables.hasEitherBound(x) && !d_variables.hasEitherBound(y)){
                 [ +  + ]
     769                 :      33116 :     return y;
     770 [ +  + ][ +  + ]:    1387427 :   }else if(!d_variables.hasEitherBound(x) && d_variables.hasEitherBound(y)){
                 [ +  + ]
     771                 :      49979 :     return x;
     772                 :            :   }else {
     773                 :    1337448 :     return minColLength(x, y);
     774                 :            :   }
     775                 :            : }
     776                 :            : 
     777                 :            : template <bool above>
     778                 :     357192 : ArithVar LinearEqualityModule::selectSlack(ArithVar x_i, VarPreferenceFunction pref) const{
     779                 :     357192 :   ArithVar slack = ARITHVAR_SENTINEL;
     780                 :            : 
     781         [ +  + ]:    8020985 :   for(Tableau::RowIterator iter = d_tableau.basicRowIterator(x_i); !iter.atEnd();  ++iter){
     782                 :    7663793 :     const Tableau::Entry& entry = *iter;
     783                 :    7663793 :     ArithVar nonbasic = entry.getColVar();
     784         [ +  + ]:    7663793 :     if(nonbasic == x_i) continue;
     785                 :            : 
     786                 :    7306601 :     const Rational& a_ij = entry.getCoefficient();
     787                 :    7306601 :     int sgn = a_ij.sgn();
     788         [ +  + ]:    7306601 :     if(isAcceptableSlack<above>(sgn, nonbasic)){
     789                 :            :       //If one of the above conditions is met, we have found an acceptable
     790                 :            :       //nonbasic variable to pivot x_i with.  We can now choose which one we
     791                 :            :       //prefer the most.
     792 [ +  + ][ -  + ]:    1727035 :       slack = (slack == ARITHVAR_SENTINEL) ? nonbasic : (this->*pref)(slack, nonbasic);
     793                 :            :     }
     794                 :            :   }
     795                 :            : 
     796                 :     357192 :   return slack;
     797                 :            : }
     798                 :            : 
     799                 :          0 : const Tableau::Entry* LinearEqualityModule::selectSlackEntry(ArithVar x_i, bool above) const{
     800         [ -  - ]:          0 :   for(Tableau::RowIterator iter = d_tableau.basicRowIterator(x_i); !iter.atEnd();  ++iter){
     801                 :          0 :     const Tableau::Entry& entry = *iter;
     802                 :          0 :     ArithVar nonbasic = entry.getColVar();
     803         [ -  - ]:          0 :     if(nonbasic == x_i) continue;
     804                 :            : 
     805                 :          0 :     const Rational& a_ij = entry.getCoefficient();
     806                 :          0 :     int sgn = a_ij.sgn();
     807                 :          0 :     if(above && isAcceptableSlack<true>(sgn, nonbasic)){
     808                 :            :       //If one of the above conditions is met, we have found an acceptable
     809                 :            :       //nonbasic variable to pivot x_i with.  We can now choose which one we
     810                 :            :       //prefer the most.
     811                 :          0 :       return &entry;
     812                 :          0 :     }else if(!above && isAcceptableSlack<false>(sgn, nonbasic)){
     813                 :          0 :       return &entry;
     814                 :            :     }
     815                 :            :   }
     816                 :            : 
     817                 :          0 :   return NULL;
     818                 :            : }
     819                 :            : 
     820                 :    3259788 : void LinearEqualityModule::startTrackingBoundCounts(){
     821 [ -  + ][ -  + ]:    3259788 :   Assert(!d_areTracking);
                 [ -  - ]
     822                 :    3259788 :   d_areTracking = true;
     823         [ -  + ]:    3259788 :   if(TraceIsOn("arith::tracking")){
     824                 :          0 :     debugCheckTracking();
     825                 :            :   }
     826 [ -  + ][ -  + ]:    3259788 :   Assert(d_areTracking);
                 [ -  - ]
     827                 :    3259788 : }
     828                 :            : 
     829                 :    3259788 : void LinearEqualityModule::stopTrackingBoundCounts(){
     830 [ -  + ][ -  + ]:    3259788 :   Assert(d_areTracking);
                 [ -  - ]
     831                 :    3259788 :   d_areTracking = false;
     832         [ -  + ]:    3259788 :   if(TraceIsOn("arith::tracking")){
     833                 :          0 :     debugCheckTracking();
     834                 :            :   }
     835 [ -  + ][ -  + ]:    3259788 :   Assert(!d_areTracking);
                 [ -  - ]
     836                 :    3259788 : }
     837                 :            : 
     838                 :            : 
     839                 :     200088 : void LinearEqualityModule::trackRowIndex(RowIndex ridx){
     840 [ -  + ][ -  + ]:     200088 :   Assert(!rowIndexIsTracked(ridx));
                 [ -  - ]
     841                 :     200088 :   BoundsInfo bi = computeRowBoundInfo(ridx, true);
     842                 :     200088 :   d_btracking.set(ridx, bi);
     843                 :     200088 : }
     844                 :            : 
     845                 :     200088 : BoundsInfo LinearEqualityModule::computeRowBoundInfo(RowIndex ridx, bool inQueue) const{
     846                 :     200088 :   BoundsInfo bi;
     847                 :            : 
     848                 :     200088 :   Tableau::RowIterator iter = d_tableau.ridRowIterator(ridx);
     849         [ +  + ]:    1204362 :   for(; !iter.atEnd();  ++iter){
     850                 :    1004274 :     const Tableau::Entry& entry = *iter;
     851                 :    1004274 :     ArithVar v = entry.getColVar();
     852                 :    1004274 :     const Rational& a_ij = entry.getCoefficient();
     853                 :    1004274 :     bi += (d_variables.selectBoundsInfo(v, inQueue)).multiplyBySgn(a_ij.sgn());
     854                 :            :   }
     855                 :     200088 :   return bi;
     856                 :            : }
     857                 :            : 
     858                 :          0 : BoundCounts LinearEqualityModule::debugBasicAtBoundCount(ArithVar x_i) const {
     859                 :          0 :   return d_btracking[d_tableau.basicToRowIndex(x_i)].atBounds();
     860                 :            : }
     861                 :            : 
     862                 :            : /**
     863                 :            :  * If the pivot described in u were performed,
     864                 :            :  * then the row would qualify as being either at the minimum/maximum
     865                 :            :  * to the non-basics being at their bounds.
     866                 :            :  * The minimum/maximum is determined by the direction the non-basic is changing.
     867                 :            :  */
     868                 :      87236 : bool LinearEqualityModule::basicsAtBounds(const UpdateInfo& u) const {
     869 [ -  + ][ -  + ]:      87236 :   Assert(u.describesPivot());
                 [ -  - ]
     870                 :            : 
     871                 :      87236 :   ArithVar nonbasic = u.nonbasic();
     872                 :      87236 :   ArithVar basic = u.leaving();
     873 [ -  + ][ -  + ]:      87236 :   Assert(basicIsTracked(basic));
                 [ -  - ]
     874                 :      87236 :   int coeffSgn = u.getCoefficient().sgn();
     875                 :      87236 :   int nbdir = u.nonbasicDirection();
     876                 :            : 
     877                 :      87236 :   ConstraintP c = u.limiting();
     878         [ +  + ]:     145259 :   int toUB = (c->getType() == UpperBound ||
     879         [ +  + ]:     145259 :               c->getType() == Equality) ? 1 : 0;
     880         [ +  + ]:     122963 :   int toLB = (c->getType() == LowerBound ||
     881         [ +  + ]:     122963 :               c->getType() == Equality) ? 1 : 0;
     882                 :            : 
     883                 :      87236 :   RowIndex ridx = d_tableau.basicToRowIndex(basic);
     884                 :            : 
     885                 :      87236 :   BoundCounts bcs = d_btracking[ridx].atBounds();
     886                 :            :   // x = c*n + \sum d*m
     887                 :            :   // 0 = -x + c*n + \sum d*m
     888                 :            :   // n = 1/c * x + -1/c * (\sum d*m)
     889                 :      87236 :   BoundCounts nonb = bcs - d_variables.atBoundCounts(nonbasic).multiplyBySgn(coeffSgn);
     890                 :      87236 :   nonb.addInChange(-1, d_variables.atBoundCounts(basic), BoundCounts(toLB, toUB));
     891                 :      87236 :   nonb = nonb.multiplyBySgn(-coeffSgn);
     892                 :            : 
     893                 :      87236 :   uint32_t length = d_tableau.basicRowLength(basic);
     894         [ +  - ]:     174472 :   Trace("basicsAtBounds")
     895                 :          0 :     << "bcs " << bcs
     896                 :          0 :     << "nonb " << nonb
     897                 :      87236 :     << "length " << length << endl;
     898                 :            :   // nonb has nb excluded.
     899         [ +  + ]:      87236 :   if(nbdir < 0){
     900                 :      44684 :     return nonb.lowerBoundCount() + 1 == length;
     901                 :            :   }else{
     902 [ -  + ][ -  + ]:      42552 :     Assert(nbdir > 0);
                 [ -  - ]
     903                 :      42552 :     return nonb.upperBoundCount() + 1 == length;
     904                 :            :   }
     905                 :            : }
     906                 :            : 
     907                 :     702777 : bool LinearEqualityModule::nonbasicsAtLowerBounds(ArithVar basic) const {
     908 [ -  + ][ -  + ]:     702777 :   Assert(basicIsTracked(basic));
                 [ -  - ]
     909                 :     702777 :   RowIndex ridx = d_tableau.basicToRowIndex(basic);
     910                 :            : 
     911                 :     702777 :   BoundCounts bcs = d_btracking[ridx].atBounds();
     912                 :     702777 :   uint32_t length = d_tableau.basicRowLength(basic);
     913                 :            : 
     914                 :            :   // return true if excluding the basic is every element is at its "lowerbound"
     915                 :            :   // The psuedo code is:
     916                 :            :   //   bcs -= basic.count(basic, basic's sgn)
     917                 :            :   //   return bcs.lowerBoundCount() + 1 == length
     918                 :            :   // As basic's sign is always -1, we can pull out the pieces of the count:
     919                 :            :   //   bcs.lowerBoundCount() - basic.atUpperBoundInd() + 1 == length
     920                 :            :   // basic.atUpperBoundInd() is either 0 or 1
     921                 :     702777 :   uint32_t lbc = bcs.lowerBoundCount();
     922         [ +  - ]:    1405554 :   return  (lbc == length) ||
     923 [ +  + ][ +  - ]:    1405554 :     (lbc + 1 == length && d_variables.cmpAssignmentUpperBound(basic) != 0);
     924                 :            : }
     925                 :            : 
     926                 :     729246 : bool LinearEqualityModule::nonbasicsAtUpperBounds(ArithVar basic) const {
     927 [ -  + ][ -  + ]:     729246 :   Assert(basicIsTracked(basic));
                 [ -  - ]
     928                 :     729246 :   RowIndex ridx = d_tableau.basicToRowIndex(basic);
     929                 :     729246 :   BoundCounts bcs = d_btracking[ridx].atBounds();
     930                 :     729246 :   uint32_t length = d_tableau.basicRowLength(basic);
     931                 :     729246 :   uint32_t ubc = bcs.upperBoundCount();
     932                 :            :   // See the comment for nonbasicsAtLowerBounds()
     933                 :            : 
     934         [ +  - ]:    1458492 :   return (ubc == length) ||
     935 [ +  + ][ +  - ]:    1458492 :     (ubc + 1 == length && d_variables.cmpAssignmentLowerBound(basic) != 0);
     936                 :            : }
     937                 :            : 
     938                 :     364468 : void LinearEqualityModule::trackingMultiplyRow(RowIndex ridx, int sgn) {
     939 [ -  + ][ -  + ]:     364468 :   Assert(rowIndexIsTracked(ridx));
                 [ -  - ]
     940 [ -  + ][ -  + ]:     364468 :   Assert(sgn != 0);
                 [ -  - ]
     941         [ +  + ]:     364468 :   if(sgn < 0){
     942                 :     205138 :     BoundsInfo& bi = d_btracking.get(ridx);
     943                 :     205138 :     bi = bi.multiplyBySgn(sgn);
     944                 :            :   }
     945                 :     364468 : }
     946                 :            : 
     947                 :   87719333 : void LinearEqualityModule::trackingCoefficientChange(RowIndex ridx, ArithVar nb, int oldSgn, int currSgn){
     948 [ -  + ][ -  + ]:   87719333 :   Assert(oldSgn != currSgn);
                 [ -  - ]
     949                 :   87719333 :   BoundsInfo nb_inf = d_variables.boundsInfo(nb);
     950                 :            : 
     951 [ -  + ][ -  + ]:   87719333 :   Assert(rowIndexIsTracked(ridx));
                 [ -  - ]
     952                 :            : 
     953                 :   87719333 :   BoundsInfo& row_bi = d_btracking.get(ridx);
     954                 :   87719333 :   row_bi.addInSgn(nb_inf, oldSgn, currSgn);
     955                 :   87719333 : }
     956                 :            : 
     957                 :          0 : ArithVar LinearEqualityModule::minBy(const ArithVarVec& vec, VarPreferenceFunction pf) const{
     958         [ -  - ]:          0 :   if(vec.empty()) {
     959                 :          0 :     return ARITHVAR_SENTINEL;
     960                 :            :   }else {
     961                 :          0 :     ArithVar sel = vec.front();
     962                 :          0 :     ArithVarVec::const_iterator i = vec.begin() + 1;
     963                 :          0 :     ArithVarVec::const_iterator i_end = vec.end();
     964         [ -  - ]:          0 :     for(; i != i_end; ++i){
     965         [ -  - ]:          0 :       sel = (this->*pf)(sel, *i);
     966                 :            :     }
     967                 :          0 :     return sel;
     968                 :            :   }
     969                 :            : }
     970                 :            : 
     971                 :    1976401 : bool LinearEqualityModule::accumulateBorder(const Tableau::Entry& entry, bool ub){
     972                 :    1976401 :   ArithVar currBasic = d_tableau.rowIndexToBasic(entry.getRowIndex());
     973                 :            : 
     974 [ -  + ][ -  + ]:    1976401 :   Assert(basicIsTracked(currBasic));
                 [ -  - ]
     975                 :            : 
     976         [ +  + ]:    1976401 :   ConstraintP bound = ub ?
     977                 :     988218 :     d_variables.getUpperBoundConstraint(currBasic):
     978                 :     988183 :     d_variables.getLowerBoundConstraint(currBasic);
     979                 :            : 
     980         [ +  + ]:    1976401 :   if(bound == NullConstraint){ return false; }
     981 [ -  + ][ -  + ]:     231277 :   Assert(bound != NullConstraint);
                 [ -  - ]
     982                 :            : 
     983                 :     231277 :   const Rational& coeff = entry.getCoefficient();
     984                 :            : 
     985                 :     231277 :   const DeltaRational& assignment = d_variables.getAssignment(currBasic);
     986                 :     231277 :   DeltaRational toBound = bound->getValue() - assignment;
     987                 :     231277 :   DeltaRational nbDiff = toBound/coeff;
     988                 :            : 
     989                 :            :   // if ub
     990                 :            :   // if toUB >= 0
     991                 :            :   // then ub >= currBasic
     992                 :            :   //   if sgn > 0,
     993                 :            :   //   then diff >= 0, so nb must increase for G
     994                 :            :   //   else diff <= 0, so nb must decrease for G
     995                 :            :   // else ub < currBasic
     996                 :            :   //   if sgn > 0,
     997                 :            :   //   then diff < 0, so nb must decrease for G
     998                 :            :   //   else diff > 0, so nb must increase for G
     999                 :            : 
    1000                 :     231277 :   int diffSgn = nbDiff.sgn();
    1001                 :            : 
    1002 [ +  + ][ +  + ]:     231277 :   if(diffSgn != 0 && willBeInConflictAfterPivot(entry, nbDiff, ub)){
                 [ +  + ]
    1003                 :         67 :     return true;
    1004                 :            :   }else{
    1005         [ +  + ]:     231210 :     bool areFixing = ub ? (toBound.sgn() < 0 ) : (toBound.sgn() > 0);
    1006                 :     231210 :     Border border(bound, nbDiff, areFixing, &entry, ub);
    1007                 :            :     bool increasing =
    1008 [ +  + ][ +  + ]:     300228 :       (diffSgn > 0) ||
    1009         [ +  + ]:      69018 :       (diffSgn == 0 && ((coeff.sgn() > 0) == ub));
    1010                 :            : 
    1011                 :            :     // assume diffSgn == 0
    1012                 :            :     // if coeff > 0,
    1013                 :            :     //   if ub, inc
    1014                 :            :     //   else, dec
    1015                 :            :     // else coeff < 0
    1016                 :            :     //   if ub, dec
    1017                 :            :     //   else, inc
    1018                 :            : 
    1019         [ +  + ]:     231210 :     if(increasing){
    1020         [ +  - ]:     113535 :       Trace("handleBorders") << "push back increasing " << border << endl;
    1021                 :     113535 :       d_increasing.push_back(border);
    1022                 :            :     }else{
    1023         [ +  - ]:     117675 :       Trace("handleBorders") << "push back decreasing " << border << endl;
    1024                 :     117675 :       d_decreasing.push_back(border);
    1025                 :            :     }
    1026                 :     231210 :     return false;
    1027                 :     231210 :   }
    1028                 :     231277 : }
    1029                 :            : 
    1030                 :     162259 : bool LinearEqualityModule::willBeInConflictAfterPivot(const Tableau::Entry& entry, const DeltaRational& nbDiff, bool bToUB) const{
    1031                 :     162259 :   int nbSgn = nbDiff.sgn();
    1032 [ -  + ][ -  + ]:     162259 :   Assert(nbSgn != 0);
                 [ -  - ]
    1033                 :            : 
    1034         [ +  + ]:     162259 :   if(nbSgn > 0){
    1035 [ +  + ][ +  + ]:      81174 :     if (!d_upperBoundDifference || nbDiff <= *d_upperBoundDifference)
                 [ +  + ]
    1036                 :            :     {
    1037                 :      63727 :       return false;
    1038                 :            :     }
    1039                 :            :   }else{
    1040 [ +  + ][ +  + ]:      81085 :     if (!d_lowerBoundDifference || nbDiff >= *d_lowerBoundDifference)
                 [ +  + ]
    1041                 :            :     {
    1042                 :      60798 :       return false;
    1043                 :            :     }
    1044                 :            :   }
    1045                 :            : 
    1046                 :            :   // Assume past this point, nb will be in error if this pivot is done
    1047                 :      37734 :   ArithVar nb = entry.getColVar();
    1048                 :      37734 :   RowIndex ridx = entry.getRowIndex();
    1049                 :      37734 :   ArithVar basic = d_tableau.rowIndexToBasic(ridx);
    1050 [ -  + ][ -  + ]:      37734 :   Assert(rowIndexIsTracked(ridx));
                 [ -  - ]
    1051                 :      37734 :   int coeffSgn = entry.getCoefficient().sgn();
    1052                 :            : 
    1053                 :            : 
    1054                 :            :   // if bToUB, then basic is going to be set to its upperbound
    1055                 :            :   // if not bToUB, then basic is going to be set to its lowerbound
    1056                 :            : 
    1057                 :            :   // Different steps of solving for this:
    1058                 :            :   // 1) y = a * x + \sum b * z
    1059                 :            :   // 2) -a * x = -y + \sum b * z
    1060                 :            :   // 3) x = (-1/a) * ( -y + \sum b * z)
    1061                 :            : 
    1062                 :      37734 :   BoundCounts bc = d_btracking[ridx].atBounds();
    1063                 :            : 
    1064                 :            :   // 1) y = a * x + \sum b * z
    1065                 :            :   // Get bc(\sum b * z)
    1066                 :      37734 :   BoundCounts sumOnly = bc - d_variables.atBoundCounts(nb).multiplyBySgn(coeffSgn);
    1067                 :            : 
    1068                 :            :   // y's bounds in the proposed model
    1069 [ +  + ][ +  + ]:      37734 :   int yWillBeAtUb = (bToUB || d_variables.boundsAreEqual(basic)) ? 1 : 0;
    1070 [ +  + ][ +  + ]:      37734 :   int yWillBeAtLb = (!bToUB || d_variables.boundsAreEqual(basic)) ? 1 : 0;
    1071                 :      37734 :   BoundCounts ysBounds(yWillBeAtLb, yWillBeAtUb);
    1072                 :            : 
    1073                 :            :   // 2) -a * x = -y + \sum b * z
    1074                 :            :   // Get bc(-y + \sum b * z)
    1075                 :      37734 :   sumOnly.addInChange(-1, d_variables.atBoundCounts(basic), ysBounds);
    1076                 :            : 
    1077                 :            :   // 3) x = (-1/a) * ( -y + \sum b * z)
    1078                 :            :   // Get bc((-1/a) * ( -y + \sum b * z))
    1079                 :      37734 :   BoundCounts xsBoundsAfterPivot = sumOnly.multiplyBySgn(-coeffSgn);
    1080                 :            : 
    1081                 :      37734 :   uint32_t length = d_tableau.basicRowLength(basic);
    1082         [ +  + ]:      37734 :   if(nbSgn > 0){
    1083                 :            :     // Only check for the upper bound being violated
    1084                 :      17447 :     return xsBoundsAfterPivot.lowerBoundCount() + 1 == length;
    1085                 :            :   }else{
    1086                 :            :     // Only check for the lower bound being violated
    1087                 :      20287 :     return xsBoundsAfterPivot.upperBoundCount() + 1 == length;
    1088                 :            :   }
    1089                 :            : }
    1090                 :            : 
    1091                 :         67 : UpdateInfo LinearEqualityModule::mkConflictUpdate(const Tableau::Entry& entry, bool ub) const{
    1092                 :         67 :   ArithVar currBasic = d_tableau.rowIndexToBasic(entry.getRowIndex());
    1093                 :         67 :   ArithVar nb = entry.getColVar();
    1094                 :            : 
    1095         [ +  + ]:         67 :   ConstraintP bound = ub ?
    1096                 :         35 :     d_variables.getUpperBoundConstraint(currBasic):
    1097                 :         32 :     d_variables.getLowerBoundConstraint(currBasic);
    1098                 :            : 
    1099                 :            : 
    1100                 :         67 :   const Rational& coeff = entry.getCoefficient();
    1101                 :         67 :   const DeltaRational& assignment = d_variables.getAssignment(currBasic);
    1102                 :         67 :   DeltaRational toBound = bound->getValue() - assignment;
    1103                 :         67 :   DeltaRational nbDiff = toBound/coeff;
    1104                 :            : 
    1105                 :        134 :   return UpdateInfo::conflict(nb, nbDiff, coeff, bound);
    1106                 :         67 : }
    1107                 :            : 
    1108                 :      25935 : UpdateInfo LinearEqualityModule::speculativeUpdate(ArithVar nb, const Rational& focusCoeff, UpdatePreferenceFunction pref){
    1109 [ -  + ][ -  + ]:      25935 :   Assert(d_increasing.empty());
                 [ -  - ]
    1110 [ -  + ][ -  + ]:      25935 :   Assert(d_decreasing.empty());
                 [ -  - ]
    1111 [ -  + ][ -  + ]:      25935 :   Assert(!d_lowerBoundDifference);
                 [ -  - ]
    1112 [ -  + ][ -  + ]:      25935 :   Assert(!d_upperBoundDifference);
                 [ -  - ]
    1113                 :            : 
    1114                 :      25935 :   int focusCoeffSgn = focusCoeff.sgn();
    1115                 :            : 
    1116         [ +  - ]:      25935 :   Trace("speculativeUpdate") << "speculativeUpdate" << endl;
    1117         [ +  - ]:      25935 :   Trace("speculativeUpdate") << "nb " << nb << endl;
    1118         [ +  - ]:      25935 :   Trace("speculativeUpdate") << "focusCoeff " << focusCoeff << endl;
    1119                 :            : 
    1120         [ +  + ]:      25935 :   if(d_variables.hasUpperBound(nb)){
    1121                 :       5395 :     ConstraintP ub = d_variables.getUpperBoundConstraint(nb);
    1122                 :       5395 :     d_upperBoundDifference = ub->getValue() - d_variables.getAssignment(nb);
    1123                 :       5395 :     Border border(ub, *d_upperBoundDifference, false, NULL, true);
    1124         [ +  - ]:       5395 :     Trace("handleBorders") << "push back increasing " << border << endl;
    1125                 :       5395 :     d_increasing.push_back(border);
    1126                 :       5395 :   }
    1127         [ +  + ]:      25935 :   if(d_variables.hasLowerBound(nb)){
    1128                 :       6966 :     ConstraintP lb = d_variables.getLowerBoundConstraint(nb);
    1129                 :       6966 :     d_lowerBoundDifference = lb->getValue() - d_variables.getAssignment(nb);
    1130                 :       6966 :     Border border(lb, *d_lowerBoundDifference, false, NULL, false);
    1131         [ +  - ]:       6966 :     Trace("handleBorders") << "push back decreasing " << border << endl;
    1132                 :       6966 :     d_decreasing.push_back(border);
    1133                 :       6966 :   }
    1134                 :            : 
    1135                 :      25935 :   Tableau::ColIterator colIter = d_tableau.colIterator(nb);
    1136         [ +  + ]:    1014086 :   for(; !colIter.atEnd(); ++colIter){
    1137                 :     988218 :     const Tableau::Entry& entry = *colIter;
    1138 [ -  + ][ -  + ]:     988218 :     Assert(entry.getColVar() == nb);
                 [ -  - ]
    1139                 :            : 
    1140         [ +  + ]:     988218 :     if(accumulateBorder(entry, true)){
    1141                 :         35 :       clearSpeculative();
    1142                 :         35 :       return mkConflictUpdate(entry, true);
    1143                 :            :     }
    1144         [ +  + ]:     988183 :     if(accumulateBorder(entry, false)){
    1145                 :         32 :       clearSpeculative();
    1146                 :         32 :       return mkConflictUpdate(entry, false);
    1147                 :            :     }
    1148                 :            :   }
    1149                 :            : 
    1150                 :      25868 :   UpdateInfo selected;
    1151         [ +  + ]:      25868 :   BorderHeap& withSgn = focusCoeffSgn > 0 ? d_increasing : d_decreasing;
    1152         [ +  + ]:      25868 :   BorderHeap& againstSgn = focusCoeffSgn > 0 ? d_decreasing : d_increasing;
    1153                 :            : 
    1154                 :      25868 :   handleBorders(selected, nb, focusCoeff, withSgn, 0, pref);
    1155                 :      25868 :   int m = 1 - selected.errorsChangeSafe(0);
    1156                 :      25868 :   handleBorders(selected, nb, focusCoeff, againstSgn, m, pref);
    1157                 :            : 
    1158                 :      25868 :   clearSpeculative();
    1159                 :      25868 :   return selected;
    1160                 :      25868 : }
    1161                 :            : 
    1162                 :      25935 : void LinearEqualityModule::clearSpeculative(){
    1163                 :            :   // clear everything away
    1164                 :      25935 :   d_increasing.clear();
    1165                 :      25935 :   d_decreasing.clear();
    1166                 :      25935 :   d_lowerBoundDifference.reset();
    1167                 :      25935 :   d_upperBoundDifference.reset();
    1168                 :      25935 : }
    1169                 :            : 
    1170                 :      51736 : void LinearEqualityModule::handleBorders(UpdateInfo& selected, ArithVar nb, const Rational& focusCoeff, BorderHeap& heap, int minimumFixes, UpdatePreferenceFunction pref){
    1171 [ -  + ][ -  + ]:      51736 :   Assert(minimumFixes >= 0);
                 [ -  - ]
    1172                 :            : 
    1173                 :            :   // The values popped off of the heap
    1174                 :            :   // should be popped with the values closest to 0
    1175                 :            :   // being first and larger in absolute value last
    1176                 :            : 
    1177                 :            : 
    1178                 :      51736 :   int fixesRemaining = heap.possibleFixes();
    1179                 :            : 
    1180         [ +  - ]:     103472 :   Trace("handleBorders")
    1181                 :          0 :     << "handleBorders "
    1182                 :          0 :     << "nb " << nb
    1183                 :          0 :     << "fc " << focusCoeff
    1184                 :          0 :     << "h.e " << heap.empty()
    1185                 :          0 :     << "h.dir " << heap.direction()
    1186                 :          0 :     << "h.rem " << fixesRemaining
    1187                 :      51736 :     << "h.0s " << heap.numZeroes()
    1188                 :          0 :     << "min " << minimumFixes
    1189                 :      51736 :     << endl;
    1190                 :            : 
    1191         [ +  + ]:      51736 :   if(heap.empty()){
    1192                 :            :     // if the heap is empty, return
    1193                 :      25816 :     return;
    1194                 :            :   }
    1195                 :            : 
    1196                 :      41353 :   bool zeroesWillDominate = fixesRemaining - heap.numZeroes() < minimumFixes;
    1197                 :            : 
    1198                 :            :   // can the number of fixes ever exceed the minimum?
    1199                 :            :   // no more than the number of possible fixes can be fixed in total
    1200                 :            :   // nothing can be fixed before the zeroes are taken care of
    1201 [ +  + ][ +  + ]:      41353 :   if(minimumFixes > 0 && zeroesWillDominate){
    1202                 :      15433 :     return;
    1203                 :            :   }
    1204                 :            : 
    1205                 :            : 
    1206                 :      25920 :   int negErrorChange = 0;
    1207                 :      25920 :   int nbDir = heap.direction();
    1208                 :            : 
    1209                 :            :   // points at the beginning of the heap
    1210         [ +  + ]:      25920 :   if(zeroesWillDominate){
    1211                 :       5581 :     heap.dropNonZeroes();
    1212                 :            :   }
    1213                 :      25920 :   heap.make_heap();
    1214                 :            : 
    1215                 :            : 
    1216                 :            :   // pretend like the previous block had a value of zero.
    1217                 :            :   // The block that actually has a value of 0 must handle this.
    1218                 :      25920 :   const DeltaRational zero(0);
    1219                 :      25920 :   const DeltaRational* prevBlockValue = &zero;
    1220                 :            : 
    1221                 :            :   /** The coefficient changes as the value crosses border. */
    1222                 :      25920 :   Rational effectiveCoefficient = focusCoeff;
    1223                 :            : 
    1224                 :            :   /* Keeps track of the change to the value of the focus function.*/
    1225                 :      25920 :   DeltaRational totalFocusChange(0);
    1226                 :            : 
    1227                 :      25920 :   const int focusCoeffSgn = focusCoeff.sgn();
    1228                 :            : 
    1229 [ +  + ][ +  + ]:      99109 :   while(heap.more()  &&
    1230         [ +  + ]:      41274 :         (fixesRemaining + negErrorChange > minimumFixes ||
    1231         [ +  + ]:      10111 :          (fixesRemaining + negErrorChange == minimumFixes &&
    1232         [ +  + ]:       6977 :           effectiveCoefficient.sgn() == focusCoeffSgn))){
    1233                 :            :     // There are more elements &&
    1234                 :            :     // we can either fix at least 1 more variable in the error function
    1235                 :            :     // or we can improve the error function
    1236                 :            : 
    1237                 :            : 
    1238                 :      31915 :     int brokenInBlock = 0;
    1239                 :      31915 :     BorderVec::const_iterator endBlock = heap.end();
    1240                 :            : 
    1241                 :      31915 :     pop_block(heap, brokenInBlock, fixesRemaining, negErrorChange);
    1242                 :            : 
    1243                 :            :     // if endVec == beginVec, block starts there
    1244                 :            :     // other wise, block starts at endVec
    1245                 :            :     BorderVec::const_iterator startBlock
    1246         [ +  + ]:      31915 :       = heap.more() ? heap.end() : heap.begin();
    1247                 :            : 
    1248                 :      31915 :     const DeltaRational& blockValue = (*startBlock).d_diff;
    1249                 :            : 
    1250                 :            :     // if decreasing
    1251                 :            :     // blockValue < prevBlockValue
    1252                 :            :     // diff.sgn() = -1
    1253                 :      31915 :     DeltaRational diff = blockValue - (*prevBlockValue);
    1254                 :      31915 :     DeltaRational blockChangeToFocus =  diff * effectiveCoefficient;
    1255                 :      31915 :     totalFocusChange += blockChangeToFocus;
    1256                 :            : 
    1257         [ +  - ]:      63830 :     Trace("handleBorders")
    1258                 :          0 :       << "blockValue " << (blockValue)
    1259                 :          0 :       << "diff " << diff
    1260                 :          0 :       << "blockChangeToFocus " << totalFocusChange
    1261                 :          0 :       << "blockChangeToFocus " << totalFocusChange
    1262                 :          0 :       << "negErrorChange " << negErrorChange
    1263                 :          0 :       << "brokenInBlock " << brokenInBlock
    1264                 :          0 :       << "fixesRemaining " << fixesRemaining
    1265                 :      31915 :       << endl;
    1266                 :            : 
    1267                 :      31915 :     int currFocusChangeSgn = totalFocusChange.sgn();
    1268         [ +  + ]:     114941 :     for(BorderVec::const_iterator i = startBlock; i != endBlock; ++i){
    1269                 :      83026 :       const Border& b = *i;
    1270                 :            : 
    1271         [ +  - ]:      83026 :       Trace("handleBorders") << b << endl;
    1272                 :            : 
    1273         [ +  + ]:     128826 :       bool makesImprovement = negErrorChange > 0 ||
    1274 [ +  + ][ +  + ]:      45800 :         (negErrorChange == 0  && currFocusChangeSgn > 0);
    1275                 :            : 
    1276         [ +  + ]:      83026 :       if(!makesImprovement){
    1277 [ +  + ][ +  + ]:      34344 :         if(b.ownBorder() || minimumFixes > 0){
                 [ +  + ]
    1278                 :         95 :           continue;
    1279                 :            :         }
    1280                 :            :       }
    1281                 :            : 
    1282                 :      82931 :       UpdateInfo proposal(nb, nbDir);
    1283         [ +  + ]:      82931 :       if(b.ownBorder()){
    1284                 :        946 :         proposal.witnessedUpdate(b.d_diff, b.d_bound, -negErrorChange, currFocusChangeSgn);
    1285                 :            :       }else{
    1286                 :      81985 :         proposal.update(b.d_diff, b.getCoefficient(), b.d_bound, -negErrorChange, currFocusChangeSgn);
    1287                 :            :       }
    1288                 :            : 
    1289 [ +  + ][ -  + ]:      82931 :       if(selected.unbounded() || (this->*pref)(selected, proposal)){
         [ +  + ][ +  + ]
    1290                 :      50705 :         selected = proposal;
    1291                 :            :       }
    1292                 :      82931 :     }
    1293                 :            : 
    1294                 :      31915 :     effectiveCoefficient += updateCoefficient(startBlock, endBlock);
    1295                 :      31915 :     prevBlockValue = &blockValue;
    1296                 :      31915 :     negErrorChange -= brokenInBlock;
    1297                 :      31915 :   }
    1298                 :      25920 : }
    1299                 :            : 
    1300                 :      31915 : Rational LinearEqualityModule::updateCoefficient(BorderVec::const_iterator startBlock, BorderVec::const_iterator endBlock){
    1301                 :            :   //update coefficient
    1302                 :      31915 :   Rational changeToCoefficient(0);
    1303         [ +  + ]:     114941 :   for(BorderVec::const_iterator i = startBlock; i != endBlock; ++i){
    1304                 :      83026 :     const Border& curr = *i;
    1305         [ +  + ]:      83026 :     if(curr.ownBorder()){// breaking its own bound
    1306         [ +  + ]:        991 :       if(curr.d_upperbound){
    1307                 :        504 :         changeToCoefficient -= 1;
    1308                 :            :       }else{
    1309                 :        487 :         changeToCoefficient += 1;
    1310                 :            :       }
    1311                 :            :     }else{
    1312                 :      82035 :       const Rational& coeff = curr.d_entry->getCoefficient();
    1313         [ +  + ]:      82035 :       if(curr.d_areFixing){
    1314         [ +  + ]:      22419 :         if(curr.d_upperbound){// fixing an upper bound
    1315                 :      10508 :           changeToCoefficient += coeff;
    1316                 :            :         }else{// fixing a lower bound
    1317                 :      11911 :           changeToCoefficient -= coeff;
    1318                 :            :         }
    1319                 :            :       }else{
    1320         [ +  + ]:      59616 :         if(curr.d_upperbound){// breaking an upper bound
    1321                 :      25498 :           changeToCoefficient -= coeff;
    1322                 :            :         }else{
    1323                 :            :           // breaking a lower bound
    1324                 :      34118 :           changeToCoefficient += coeff;
    1325                 :            :         }
    1326                 :            :       }
    1327                 :            :     }
    1328                 :            :   }
    1329                 :      31915 :   return changeToCoefficient;
    1330                 :          0 : }
    1331                 :            : 
    1332                 :      31915 : void LinearEqualityModule::pop_block(BorderHeap& heap, int& brokenInBlock, int& fixesRemaining, int& negErrorChange){
    1333 [ -  + ][ -  + ]:      31915 :   Assert(heap.more());
                 [ -  - ]
    1334                 :            : 
    1335         [ +  + ]:      31915 :   if(heap.top().d_areFixing){
    1336                 :      11323 :     fixesRemaining--;
    1337                 :      11323 :     negErrorChange++;
    1338                 :            :   }else{
    1339                 :      20592 :     brokenInBlock++;
    1340                 :            :   }
    1341                 :      31915 :   heap.pop_heap();
    1342                 :      31915 :   const DeltaRational& blockValue = (*heap.end()).d_diff;
    1343                 :            : 
    1344         [ +  + ]:      83026 :   while(heap.more()){
    1345                 :      66465 :     const Border& top = heap.top();
    1346         [ +  + ]:      66465 :     if(blockValue == top.d_diff){
    1347                 :            :       // belongs to the block
    1348         [ +  + ]:      51111 :       if(top.d_areFixing){
    1349                 :      11096 :         fixesRemaining--;
    1350                 :      11096 :         negErrorChange++;
    1351                 :            :       }else{
    1352                 :      40015 :         brokenInBlock++;
    1353                 :            :       }
    1354                 :      51111 :       heap.pop_heap();
    1355                 :            :     }else{
    1356                 :            :       // does not belong to the block
    1357 [ +  + ][ -  + ]:      15354 :       Assert((heap.direction() > 0) ? (blockValue < top.d_diff)
         [ -  + ][ -  - ]
    1358                 :            :                                     : (blockValue > top.d_diff));
    1359                 :      15354 :       break;
    1360                 :            :     }
    1361                 :            :   }
    1362                 :      31915 : }
    1363                 :            : 
    1364                 :       4914 : void LinearEqualityModule::substitutePlusTimesConstant(ArithVar to, ArithVar from, const Rational& mult){
    1365                 :       4914 :   d_tableau.substitutePlusTimesConstant(to, from, mult, d_trackCallback);
    1366                 :       4914 : }
    1367                 :       4343 : void LinearEqualityModule::directlyAddToCoefficient(ArithVar row, ArithVar col, const Rational& mult){
    1368                 :       4343 :   d_tableau.directlyAddToCoefficient(row, col, mult, d_trackCallback);
    1369                 :       4343 : }
    1370                 :            : 
    1371                 :            : }  // namespace arith
    1372                 :            : }  // namespace theory
    1373                 :            : }  // namespace cvc5::internal

Generated by: LCOV version 1.14