Changeset 960


Ignore:
Timestamp:
Jan 13, 2011 10:17:30 PM (11 years ago)
Author:
lou
Message:

(nonworking) Code labelled MOVE_SINGLETON now a separate routine
singletonRows. Code that strengthened coefficients now a separate routine
strengthenCoeff. Nontrivial code motion in the code blocks that finish
off down feasible and down feasible, up feasible.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • branches/CglWorking101215/src/CglProbing/CglProbingProbe.cpp

    r957 r960  
    121121  probeDir should be coded using probeDown, probeUp.
    122122*/
    123 void disaggCuts (int nstackC, int probeDir,
     123void disaggCuts (int nstackC, unsigned int probeDir,
    124124                 double primalTolerance_, double disaggEffectiveness,
    125125                 const OsiSolverInterface &si,
     
    361361  return (feasible) ;
    362362}
    363 
    364363
    365364
     
    575574
    576575
     576
     577/*
     578  This method examines the rows on stackR looking for redundant rows that
     579  consist solely of singleton variables (i.e., variables that appear in just
     580  this constraint). It then looks to see if any of the variables in the row
     581  can be fixed at bound.
     582
     583  Consider the case where U<i> < b<i> and all unfixed variables in the row
     584  are singletons (occur in no other constraint). Given x<j> is a singleton,
     585  the reduced cost is c<j> - ya<j> = c<j> - ye<i> = c<j> - y<i>.  But if
     586  U<i> < b<i>, the constraint is loose by definition, hence y<i> = 0 and
     587  the reduced cost is c<j>. If a<ij> > 0, x<j> should be u<j> in U<i>. If
     588  c<j> < 0, minimising will tend to drive x<j> to u<j>. This cannot violate
     589  constraint i (U<i> < b<i>) and (since x<j> is a singleton) will have no
     590  effect elsewhere. Hence we can fix x<j> at u<j>.
     591
     592  Do the case analysis, and what you find is that against U<i> we want
     593    a<ij> > 0  ==>  c<j> < 0  ==>  push x<j> to u<j>
     594    a<ij> < 0  ==>  c<j> > 0  ==>  push x<j> to l<j>
     595  and against L<i> we want
     596    a<ij> > 0  ==>  c<j> > 0  ==>  push x<j> to l<j>
     597    a<ij> < 0  ==>  c<j> < 0  ==>  push x<j> to u<j>
     598
     599  Extend it one more time by taking the objective direction (max/min) into
     600  account (dir = 1.0 for min, -1.0 for max) and you have
     601    against U<i> ==> a<ij>*c<j>*dir < 0
     602    against L<i> ==> a<ij>*c<j>*dir > 0
     603
     604  John's original comment for this code was
     605    // also see if singletons can go to good objective
     606    // Taken out as should be found elsewhere
     607    // and has to be original column length
     608  but he reinstated it. Apparently there were cases where fixing the probing
     609  variable was required to satisfy the condition that all unfixed variables be
     610  singletons. Enough of them to justify reinstating this code.
     611*/
     612
     613void singletonRows (int jProbe, double primalTolerance_,
     614                    const OsiSolverInterface &si,
     615                    const CoinPackedMatrix *rowCopy,
     616                    int *const markC,
     617                    int &nstackC, int *const stackC,
     618                    double *const saveL, double *const saveU,
     619                    double *const colUpper, double *const colLower,
     620                    double *const colGap,
     621                    const int nstackR, const int *const stackR,
     622                    const double *const rowUpper,
     623                    const double *const rowLower,
     624                    const double *const maxR, const double *const minR)
     625{
     626/*
     627  Unpack a few vectors from the row-major matrix.
     628*/
     629  const CoinBigIndex *rowStart = rowCopy->getVectorStarts() ;
     630  const int *column = rowCopy->getIndices() ;
     631  const double *rowElements = rowCopy->getElements() ;
     632  const int nCols = rowCopy->getNumCols() ;
     633/*
     634  `Singleton' must be based on the column length in the original system.
     635*/
     636  const double *objective = si.getObjCoefficients() ;
     637  const int *columnLengths = si.getMatrixByCol()->getVectorLengths() ;
     638  const double objSense = si.getObjSense() ;
     639/*
     640  Open a loop to work through the rows on stackR.
     641*/
     642  for (int istackR = 0 ; istackR < nstackR ; istackR++) {
     643    int i = stackR[istackR] ;
     644/*
     645  Check the gaps. If the constraint is potentially tight in both directions,
     646  there's nothing more to do here.
     647*/
     648    const double uGap = rowUpper[i]-maxR[i] ;
     649    const double lGap = minR[i]-rowLower[i] ;
     650    if (uGap < primalTolerance_ && lGap < primalTolerance_) continue ;
     651/*
     652  Scan the row to see if it meets the `all singletons' condition. Again,
     653  if this fails, there's nothing more to be done.
     654
     655  Note that the original code didn't check the probing variable x<p>,
     656  because if you're probing a binary variable it's fixed. But for general
     657  integer variables a probe does not in general fix the variable.  So we
     658  check all variables.
     659
     660  We should not be executing this method if we have prima facie infeasibility.
     661*/
     662    bool canFix = true ;
     663    for (int kk = rowStart[i] ; kk < rowStart[i+1] ; kk++) {
     664      int j = column[kk] ;
     665      assert(colUpper[j]-colLower[j] > -primalTolerance_) ;
     666      if (colUpper[j] > colLower[j] && columnLengths[j] != 1) {
     667        canFix = false ;
     668        break ;
     669      }
     670    }
     671    if (!canFix) continue ;
     672/*
     673  If we've passed the tests, we can look for variables suitable to drive to
     674  bound. Work against U<i> first. We're looking for variables with a<ij> > 0
     675  that will be naturally driven to u<j>, or variables with a<ij> < 0 that will
     676  be naturally driven to l<j>.
     677 
     678  Don't overwrite the saved bounds if we've
     679  tightened this variable already!
     680*/
     681    if (uGap > primalTolerance_) {
     682      for (int kk = rowStart[i] ; kk < rowStart[i+1] ; kk++) {
     683        int j = column[kk] ;
     684        const double lj = colLower[j] ;
     685        const double uj = colUpper[j] ;
     686        if (uj > lj) {
     687          double value = rowElements[kk] ;
     688          if (objSense*objective[j]*value < 0.0)
     689          { assert(jProbe != j) ;
     690            if (!(markC[j]&(tightenLower|tightenUpper))) {
     691              stackC[nstackC] = j ;
     692              saveL[nstackC] = lj ;
     693              saveU[nstackC] = uj ;
     694            }
     695            assert(saveU[nstackC] > saveL[nstackC]) ;
     696            if (value > 0.0) {
     697              colLower[j] = uj ;
     698            } else {
     699              colUpper[j] = lj ;
     700            }
     701            markC[j] |= tightenLower|tightenUpper ;
     702            colGap[j] = -primalTolerance_ ;
     703            assert(nstackC < nCols) ;
     704            nstackC++ ;
     705          }
     706        }
     707      }
     708    }
     709/*
     710  And now the identical code, except that we're working against L<i>, hence
     711  the sense of the elibigility test is reversed and we want variables with
     712  a<ij> > 0 that will be naturally driven to l<j>, or variables with
     713  a<ij> < 0 that will be naturally driven to u<j>.
     714*/
     715    if (lGap > primalTolerance_) {
     716      for (int kk = rowStart[i] ; kk < rowStart[i+1] ; kk++) {
     717        int j = column[kk] ;
     718        const double lj = colLower[j] ;
     719        const double uj = colUpper[j] ;
     720        if (uj > lj) {
     721          double value = rowElements[kk] ;
     722          if (objSense*objective[j]*value > 0.0)
     723          { assert(jProbe != j) ;
     724            if (!(markC[j]&(tightenLower|tightenUpper))) {
     725              stackC[nstackC] = j ;
     726              saveL[nstackC] = lj ;
     727              saveU[nstackC] = uj ;
     728            }
     729            assert(saveU[nstackC] > saveL[nstackC]) ;
     730            if (value < 0.0) {
     731              colLower[j] = uj ;
     732            } else {
     733              colUpper[j] = lj ;
     734            }
     735            markC[j] |= tightenLower|tightenUpper ;
     736            colGap[j] = -primalTolerance_ ;
     737            assert(nstackC < nCols) ;
     738            nstackC++ ;
     739          }
     740        }
     741      }
     742    }
     743  }
     744  return ;
     745}
     746
     747
     748/*
     749  Generate coefficient strengthening cuts.
     750 
     751  Assume we have a binary probe variable x<p> with a<ip> > 0. This will
     752  be a down probe, so assume that U<i> > b<i> before the probe, but now
     753  U'<i> < b<i> (i.e., the constraint is redundant against b<i> after the
     754  down probe forces x<p> to 0 and reduces U<i> to U'<i>). We would like to
     755  have the following:
     756    * When x<p> = 0, b'<i> = U'<i>  (after all, the lhs can't be any larger)
     757    * When x<p> = 1, b'<i> = b<i>   (the original value)
     758  Define delta<i> = b<i> - U'<i>. Let b'<i> = b<i>-delta<i> and let
     759  a'<ip> = a<ip>-delta<i>. Then when x<p> = 1, the delta<i> on each side
     760  cancels and we're left with the original constraint. When x<p> = 0, the rhs
     761  becomes b'<i> = b<i>+delta<i> = U'<i>.
     762
     763  The usual case analysis applies; see the typeset documentation. It's not
     764  necessarily true that U'<i> = U<i> - a<ip>u<p>; additional propagation could
     765  have reduced it even further. That doesn't alter the reasoning above.
     766
     767  TODO: Figure out why goingToTrueBound is relevant here, other than it's
     768        set to zero if we're infeasible.  -- lh, 101127 --
     769
     770        I think that might be all there is to it.   -- lh, 101128 --
     771
     772        Well, maybe not. Check the math for the contained cuts to see if
     773        it's valid only for binary variables; when within distance 1 of
     774        the upper or lower bound of a general integer; or more generally.
     775        GoingToTrueBound indicates the first of these two. -- lh, 110105 --
     776
     777        After working the math a few times, it looks to me like the important
     778        aspect is that goingToTrueBound = 2 indicates binary variables. I
     779        can't get the math to agree with the code otherwise. See the problem
     780        noted below. I'm going to restrict this method to binary variables
     781        until I can resolve questions about general integers.  -- lh, 110113 --
     782*/
     783
     784#define STRENGTHEN_PRINT
     785void strengthenCoeff (
     786                      int jProbe,
     787                      double primalTolerance_,
     788                      bool justReplace, bool canReplace,
     789                      double needEffectiveness,
     790                      const OsiSolverInterface &si,
     791                      CglProbingRowCut &rowCut,
     792                      const CoinPackedMatrix *rowCopy,
     793                      double *const colUpper, double *const colLower,
     794                      const double *const colsol,
     795                      const int nstackR, const int *const stackR,
     796                      const double *const rowUpper,
     797                      const double *const rowLower,
     798                      const double *const maxR,
     799                      const double *const minR,
     800                      const int *const realRows,
     801                      double *const element,
     802                      int *const index,
     803                      CglTreeInfo *const info
     804                     )
     805{
     806# if CGL_DEBUG > 0
     807  std::cout
     808    << "Entering strengthenCoeff, probed variable "
     809    << si.getColName(jProbe) << "(" << jProbe << ")." << std::endl ;
     810  const OsiRowCutDebugger *debugger = si.getRowCutDebugger() ;
     811# endif
     812/*
     813  Unpack a few vectors from the row-major matrix.
     814*/
     815  const CoinBigIndex *rowStart = rowCopy->getVectorStarts() ;
     816  const int *column = rowCopy->getIndices() ;
     817  const double *rowElements = rowCopy->getElements() ;
     818/*
     819  Open up an outer loop to walk stackR and look for interesting constraints.
     820*/
     821  for (int istackR = 0 ; istackR < nstackR ; istackR++) {
     822    int irow = stackR[istackR] ;
     823/*
     824  We can't get anywhere unless probing has made one end or the other of the
     825  constraint redundant.
     826
     827  Really, we shouldn't be here if b<i> or blow<i> are not finite. Check with
     828  an assert.
     829*/
     830    double uGap = rowUpper[irow]-maxR[irow] ;
     831    assert(uGap < 1.0e8) ;
     832    double lGap = minR[irow]-rowLower[irow] ;
     833    assert(lGap < 1.0e8) ;
     834    if (uGap < primalTolerance_ && lGap < primalTolerance_) continue ;
     835/*
     836  We'll need the lhs activity to evaluate the effectiveness of the cut. Do a
     837  base calculation which we'll correct later.
     838 
     839  TODO: Sort out why anyColumnCuts is an obstacle. Theoretical or practical?
     840        Could we use the new bound instead?  -- lh, 101128 --
     841
     842        After working the math, looks to me like the only effect will be where
     843        a column cut cuts off the current solution, in which case the lhs
     844        value (sum) may be incorrect, affecting the calculation of
     845        effectiveness. We could correct for this, if it was worth the effort
     846        (a max or min when calculating the sum below). -- lh, 110113 --
     847*/
     848    double sum = 0.0 ;
     849    for (int kk = rowStart[irow] ; kk < rowStart[irow+1] ; kk++) {
     850      sum += rowElements[kk]*colsol[column[kk]] ;
     851    }
     852/*
     853  Start out by working against the row upper bound U(i).  We've calculated
     854  sum using the current a<ik>, so reduce it by (-a<ip>+a'<ip>)x*<p> =
     855  (-uGap)(x*<p>) to do the check.
     856
     857  We're not willing to generate a cut if it doesn't cut off the current
     858  solution, but we are willing to strengthen the existing constraint in place.
     859  Can't hurt, eh? Excluding range constraints in this case avoids the issue
     860  of conflicting a'<ij> if it turns out we can strengthen against b<i>
     861  and blow<i> in the same constraint.
     862*/
     863    if (uGap > primalTolerance_ &&
     864        (sum-uGap*colsol[jProbe] > maxR[irow]+primalTolerance_ ||
     865         (info->strengthenRow && rowLower[irow] < -1.0e20))) {
     866/*
     867  Generate the coefficients. For all except the probing variable, we just copy
     868  the coefficient. The probing variable becomes a'<ij> = (a<ij> - uGap). Allow
     869  for the possibility that a<ij> starts or ends as 0.
     870
     871  TODO: The value of sum2 calculated here should be precisely
     872        sum-uGap*colsol[j], unless my math is way wrong.  -- lh, 110107 --
     873*/
     874      int n = 0 ;
     875      bool saw_aip = false ;
     876      double sum2 = 0.0 ;
     877      for (int kk = rowStart[irow] ; kk < rowStart[irow+1] ; kk++) {
     878        int kColumn = column[kk] ;
     879        double el = rowElements[kk] ;
     880        if (kColumn != jProbe) {
     881          index[n] = kColumn ;
     882          element[n++] = el ;
     883        } else {
     884          el = el-uGap ;
     885          if (fabs(el) > 1.0e-12) {
     886            index[n] = kColumn ;
     887            element[n++] = el ;
     888          }
     889          saw_aip = true ;
     890        }
     891        sum2 += colsol[kColumn]*el ;
     892      }
     893      if (!saw_aip) {
     894        index[n] = jProbe ;
     895        element[n++] = -uGap ;
     896        sum2 -= colsol[jProbe]*uGap ;
     897      }
     898      assert(sum == sum2) ;
     899/*
     900  Check effectiveness. Add the cut only if it's sufficiently effective. (If
     901  we're strengthening existing constraints, needEffectiveness is quite low.)
     902
     903  TODO: (*) I can't justify colLower in uGap*(l<p>+1.0). When I work
     904        the math, b'<i> = b<i> - (b<i> - U'<i>) = b<i> - uGap. I'll keep
     905        trying, on the theory that it's some attempt at general integers, but
     906        I'm thinking it's wrong. Note that for binary variables, l<p> = 0 and
     907        there's no problem.   -- lh, 110113 --
     908
     909  TODO: I don't understand what's going on with the first two calculations
     910        for effectiveness. First off, sum2 and sum-uGap*colsol[j] should be
     911        exactly the same value (see notes with previous calculations). Then
     912        there's the question `Why divide by (b<i>-U<i>)?' in the second
     913        calculation. This inflates the effectiveness for a tiny uGap. A
     914        normalisation, perhaps?  -- lh, 110107 --
     915
     916  TODO: And why go through the effort of setting the row bounds and
     917        effectiveness in the OsiRowCut, before we've decided that the cut will
     918        be used?  -- lh, 110107 --
     919*/
     920      OsiRowCut rc ;
     921      rc.setLb(-DBL_MAX) ;
     922      // (*) double ub = rowUpper[irow]-uGap*(colLower[jProbe]+1.0) ;
     923      double ub = rowUpper[irow]-uGap ;
     924      rc.setUb(ub) ;
     925      double effectiveness = sum2-ub ;
     926      effectiveness =
     927          CoinMax(effectiveness,
     928                  (sum-uGap*colsol[jProbe]-maxR[irow])/uGap) ;
     929      if (!saw_aip)
     930        effectiveness = CoinMax(1.0e-7,effectiveness) ;
     931      rc.setEffectiveness(effectiveness) ;
     932      // rc.setEffectiveness((sum-uGap*colsol[jProbe]-maxR[irow])/uGap) ;
     933      if (rc.effectiveness() > needEffectiveness) {
     934        rc.setRow(n,index,element,false) ;
     935#       if CGL_DEBUG > 0
     936        if (debugger) assert(!debugger->invalidCut(rc));
     937#       endif
     938#       ifdef STRENGTHEN_PRINT
     939        if (canReplace && rowLower[irow] < -1.0e20) {
     940          printf("Strengthen Cut (1):\n") ;
     941          dump_row(irow,rc.lb(),rc.ub(),
     942                   nan(""),nan(""),&si,true,false,4,
     943                   n,index,element,
     944                   1.0e-10,colLower,colUpper) ;
     945          printf("Original Row:\n") ;
     946          int k = rowStart[irow] ;
     947          dump_row(irow,rowLower[irow],rowUpper[irow],
     948                   minR[irow],maxR[irow],&si,true,false,4,
     949                   rowStart[irow+1]-k,&column[k],&rowElements[k],
     950                   1.0e-10,colLower,colUpper) ;
     951        }
     952#       endif
     953/*
     954  If we're in preprocessing, we might try to simply replace the existing
     955  constraint (justReplace = true; preprocessing is the only place this will
     956  happen). Otherwise, drop the cut into the cut set.
     957
     958  realRows comes in as a parameter. This is the translation array created if
     959  we modified the constraint system during preprocessing in gutsOfGenerateCuts.
     960
     961  TODO: Seems a bit disingenuous to fail at replacement now, given that
     962        effectiveness is artificially low. Notice again the inconsistent use
     963        of finite infinities on the row lb.  -- lh, 101128 --
     964
     965  TODO: To elaborate on the above, it seems to me that we can get here with
     966        justReplace = true and canReplace = false, and this condition is
     967        constant over an iteration of the way loop. In other words, we've done
     968        all the work to generate this cut and we knew before we started that
     969        we would discard it here.  -- lh, 110107 --
     970*/
     971        int realRow = (canReplace && rowLower[irow] < -1.0e20)?(irow):(-1) ;
     972        if (realRows && realRow >= 0)
     973          realRow = realRows[realRow] ;
     974        if (!justReplace) {
     975          rowCut.addCutIfNotDuplicate(rc,realRow) ;
     976        } else if (realRow >= 0) {
     977          double effectiveness = 0.0 ;
     978          for (int i = 0 ; i < n ; i++)
     979            effectiveness += fabs(element[i]) ;
     980          if (!info->strengthenRow[realRow] ||
     981              info->strengthenRow[realRow]->effectiveness() > effectiveness) {
     982            delete info->strengthenRow[realRow] ;
     983            rc.setEffectiveness(effectiveness) ;
     984            info->strengthenRow[realRow]=rc.clone() ;
     985          }
     986        }
     987      }
     988    }
     989/*
     990  And repeat working against the lower bound L(i). As in so many other places
     991  in this code, it's the identical functionality, with some subtle edits that
     992  distinguish the L(i) math from the U(i) math.
     993*/
     994    if (lGap > primalTolerance_ &&
     995        (sum+lGap*colsol[jProbe] < minR[irow]-primalTolerance_ ||
     996         (info->strengthenRow && rowUpper[irow] > -1.0e20))) {
     997      int n = 0 ;
     998      bool saw_aip = false ;
     999      double sum2 = 0.0 ;
     1000      for (int kk = rowStart[irow] ; kk < rowStart[irow+1] ; kk++) {
     1001        int kColumn = column[kk] ;
     1002        double el = rowElements[kk] ;
     1003        if (kColumn != jProbe) {
     1004          index[n] = kColumn ;
     1005          element[n++] = el ;
     1006        } else {
     1007          el = el+lGap ;
     1008          if (fabs(el) > 1.0e-12) {
     1009            index[n] = kColumn ;
     1010            element[n++] = el ;
     1011          }
     1012          saw_aip = true ;
     1013        }
     1014        sum2 += colsol[kColumn]*el ;
     1015      }
     1016      if (!saw_aip) {
     1017        index[n] = jProbe ;
     1018        element[n++] = lGap ;
     1019        sum2 += colsol[jProbe]*lGap ;
     1020      }
     1021      OsiRowCut rc ;
     1022      double lb = rowLower[irow]+lGap*(colLower[jProbe]+1.0) ;
     1023      rc.setLb(lb) ;
     1024      rc.setUb(DBL_MAX) ;
     1025      // effectiveness
     1026      double effectiveness = lb-sum2 ;
     1027      effectiveness = CoinMax(effectiveness,
     1028                              (minR[irow]-sum-lGap*colsol[jProbe])/lGap) ;
     1029      if (!saw_aip)
     1030        effectiveness = CoinMax(1.0e-7,effectiveness) ;
     1031      rc.setEffectiveness(effectiveness) ;
     1032      if (rc.effectiveness() > needEffectiveness) {
     1033        rc.setRow(n,index,element,false) ;
     1034#       if CGL_DEBUG > 0
     1035        if (debugger) assert(!debugger->invalidCut(rc));
     1036#       endif
     1037#       ifdef STRENGTHEN_PRINT
     1038        if (canReplace && rowUpper[irow] > 1.0e20) {
     1039          printf("Strengthen Cut (2):\n") ;
     1040          dump_row(irow,rc.lb(),rc.ub(),
     1041                   nan(""),nan(""),&si,true,false,4,
     1042                   n,index,element,
     1043                   1.0e-10,colLower,colUpper) ;
     1044          printf("Original Row:\n") ;
     1045          int k = rowStart[irow] ;
     1046          dump_row(irow,rowLower[irow],rowUpper[irow],
     1047                   minR[irow],maxR[irow],&si,true,false,4,
     1048                   rowStart[irow+1]-k,&column[k],&rowElements[k],
     1049                   1.0e-10,colLower,colUpper) ;
     1050        }
     1051#       endif
     1052
     1053        int realRow = (canReplace&&rowUpper[irow]>1.0e20) ? irow : -1 ;
     1054        if (realRows && realRow >= 0)
     1055          realRow = realRows[realRow] ;
     1056        if (!justReplace) {
     1057          rowCut.addCutIfNotDuplicate(rc,realRow) ;
     1058        } else if (realRow >= 0) {
     1059          double effectiveness = 0.0 ;
     1060          for (int i = 0 ; i < n ; i++)
     1061            effectiveness += fabs(element[i]) ;
     1062          if (!info->strengthenRow[realRow] ||
     1063              info->strengthenRow[realRow]->effectiveness() > effectiveness) {
     1064            delete info->strengthenRow[realRow] ;
     1065            rc.setEffectiveness(effectiveness) ;
     1066            info->strengthenRow[realRow] = rc.clone() ;
     1067          }
     1068        }
     1069      }
     1070    }
     1071  }
     1072
     1073# if CGL_DEBUG > 0
     1074  std::cout
     1075    << "Leaving strengthenCoeff, "
     1076    << rowCut.numberCuts() << " cuts." << std::endl ;
     1077# endif
     1078  return ;
     1079}
     1080
     1081
     1082
     1083
    5771084// =========================================================
    5781085
     
    7051212
    7061213*/
    707 /*
    708   The #ifdef around the formal parameter apparently satisfies the method
    709   signature while clearly indicating the parameter is unused in the body of
    710   the method.
    711 */
    712 
    713 int CglProbing::probe( const OsiSolverInterface & si,
    714                        OsiCuts & cs,
    715                        double * colLower, double * colUpper,
     1214int CglProbing::probe( const OsiSolverInterface &si,
     1215                       OsiCuts &cs,
     1216                       double *colLower, double *colUpper,
    7161217                       CoinPackedMatrix *rowCopy,
    7171218                       CoinPackedMatrix *columnCopy,
    718                        const CoinBigIndex * rowStartPos,const int * realRows,
    719                        const double * rowLower, const double * rowUpper,
    720                        const char * intVar, double * minR, double * maxR,
    721                        int * markR,
    722                        CglTreeInfo * info) const
     1219                       const CoinBigIndex *rowStartPos, const int *realRows,
     1220                       const double *rowLower, const double *rowUpper,
     1221                       const char *intVar, double *minR, double *maxR,
     1222                       int *markR,
     1223                       CglTreeInfo *info) const
    7231224
    7241225{
    7251226# if CGL_DEBUG > 0
    7261227  std::cout << "Entering CglProbing::probe." << std::endl ;
    727 
    728   const OsiRowCutDebugger *debugger = si.getRowCutDebugger() ;
    7291228# endif
    7301229/*
     
    8391338
    8401339/*
    841   This won't be used until we're sorting out the results of propagating a probe
    842   (look for the next occurrence of columnLength2). We need to make sure the
    843   column we're looking at is a singleton in the original system.
    844 */
    845 #define MOVE_SINGLETONS
    846 #ifdef MOVE_SINGLETONS
    847   const double * objective = si.getObjCoefficients() ;
    848   const int * columnLength2 = si.getMatrixByCol()->getVectorLengths();
    849 #endif
    850 /*
    8511340  Grab the column solution and reduced costs and groom them.
    8521341*/
     
    9681457
    9691458  Major block #2: Main pass loop.
     1459
     1460  From CglProbingAnn: anyColumnCuts is set only in the case that we've
     1461  fixed a variable by probing (i.e., one of the up or down probe resulted
     1462  in infeasibility) and that probe entailed column cuts. Once set, it is
     1463  never rescinded. In the reworked code, it's set as the return value of
     1464  monotoneActions().
    9701465*/
    9711466  bool anyColumnCuts = false ;
     
    10921587  the tree, break from probing.
    10931588
    1094   JustFix < 0 says this is the first pass at the root, or (??). If it is the
    1095   first pass at the root, turn off row cuts, keep on fixing variables, and
    1096   stop at the end of this pass. If (??) and we haven't fixed any variables,
    1097   break.
     1589  JustFix < 0 says this is the first pass at the root; for any other
     1590  iteration of the pass loop, it'll be initialised to 0.  If it is the first
     1591  pass at the root, turn off row cuts, keep on fixing variables, and stop
     1592  at the end of this pass. Otherwise, if we haven't fixed any variables, break.
    10981593
    10991594  TODO: Otherwise keep going with no changes? That doesn't seem right. The
     
    11441639      if (columnGap[j] < 0.0) markC[j] = tightenUpper|tightenLower ;
    11451640      if ((markC[j]&(tightenUpper|tightenLower)) != 0 || !intVar[j]) continue ;
    1146       double saveSolval = solval ;
    11471641/*
    11481642  `Normalize' variables that are near (or past) their bounds.
     
    24482942  TODO: I'm coming to think forcing goingToTrueBound = 0 is really an overload
    24492943        to suppress various post-probe activities (cut generation, singleton
    2450         motion, etc). It might be that this is not the best approach.
     2944        motion, etc) that should not be performed when the probe shows
     2945        infeasible. It might be that this is not the best approach.
    24512946        -- lh, 101216 --
    24522947*/
     
    25353030  PROBE LOOP: ITERATE
    25363031
    2537   If we reach here, we will iterate the probe loop.
     3032  If we reach here, we may iterate the probe loop.
    25383033
    25393034  Cases remaining include
     
    25463041     iterate to restore the down feasible state.
    25473042
    2548   The next block deals with preparing to iterate at the end of the first down
    2549   probe.  Whatever the result, we'll need to go to the up probe. If the down
    2550   probe was feasible, save stackC and the new bounds.
    2551 
    25523043  TODO: Unless I miss my guess, large chunks of this block of code will be
    25533044        replicated in the code that handles case b), as we generate cuts
     
    25603051        stackC0 = stackC should do the trick.  -- lh, 101216 --
    25613052
    2562   jjf: is it worth seeing if can increase coefficients or maybe better see
    2563        if it is a cut
    2564 
     3053  TODO: As I get the control flow sorted out a bit better, I should try to
     3054        separate b) (which does not iterate) from a) and c).
     3055
     3056  The next block deals with the end of the first down probe. If the probe
     3057  is feasible, attempt to tighten column bounds with singletonRows, process
     3058  stackC to generate disaggregation cuts, and copy the tightened bounds
     3059  to stackC0, lo0, and up0 for use after the up probe.  Feasible or not,
     3060  we'll need to go on to the up probe, so restore the original bounds.
     3061
     3062  Note that GoingToTrueBound was set to 0 way back in initial setup unless
     3063  the user requested disaggregation cuts (rowCuts&0x01).
     3064
     3065  I've rearranged the control flow here, moving the call to singletonRows
     3066  ahead of the code that captures column bound changes to stackC0, et al.
     3067  This makes it possible to use the same code at the end of case b) (down and
     3068  up probe both feasible). Also, singletonRows is just another way to tighten
     3069  column bounds. In its original position, it was subject to the same
     3070  restrictions as coefficient strengthening (coefficient strengthening enabled
     3071  and goingToTrueBound for the probing variable). I don't see any reason to
     3072  keep them (but it might be good to add a separate control bit precisely for
     3073  singletonRows).  -- lh, 110113 --
    25653074*/
    25663075        if (iway == downProbe) {
    2567           nstackC0 = CoinMin(nstackC,maxStack) ;
    2568           if (notFeasible) {
    2569             nstackC0 = 0 ;
    2570           } else {
     3076          if (!notFeasible) {
     3077/*
     3078  Attempt to tighten singleton bounds and generate disaggregation cuts.
     3079*/
     3080            singletonRows(j,primalTolerance_,si,rowCopy,markC,
     3081                          nstackC,stackC,saveL,saveU,
     3082                          colUpper,colLower,columnGap,
     3083                          nstackR,stackR,rowUpper,rowLower,maxR,minR) ;
     3084            if (goingToTrueBound == 2 && !justReplace) {
     3085              disaggCuts(nstackC,probeDown,primalTolerance_,
     3086                         disaggEffectiveness,si,rowCut,stackC,colsol,
     3087                         colUpper,colLower,saveU,saveL,index,element) ;
     3088            }
     3089/*
     3090  Copy off the bound changes from the down probe -- we'll need them after the
     3091  up probe.
     3092*/
     3093            nstackC0 = CoinMin(nstackC,maxStack) ;
    25713094            for (istackC = 0 ; istackC < nstackC0 ; istackC++) {
    25723095              int icol = stackC[istackC] ;
     
    25753098              up0[istackC] = colUpper[icol] ;
    25763099            }
     3100          } else {
     3101            nstackC0 = 0 ;
    25773102          }
    25783103/*
    2579   Run through stackC and make disaggregation cuts, if possible. At the end of
    2580   each iteration, restore the bounds for the variable and reset markC.
    2581 
    2582   goingToTrueBound was set to 0 way back in initial setup unless the user
    2583   requested disagg cuts (rowCuts&0x01).
    2584 */
    2585           assert (iway == downProbe) ;
    2586           if (goingToTrueBound == 2 && !justReplace) {
    2587             disaggCuts(nstackC,probeDown,primalTolerance_,
    2588                        disaggEffectiveness,si,
    2589                        rowCut,stackC,colsol,colUpper,colLower,saveU,saveL,
    2590                        index,element) ;
    2591           }
     3104  Now reset column bounds to their original values in preparation for the
     3105  up probe.
     3106*/
    25923107          for (istackC = nstackC-1 ; istackC >= 0 ; istackC--) {
    25933108            int icol = stackC[istackC] ;
     
    26083123  (of about 300) actually restore the row bounds. The rest is cut generation.
    26093124*/
     3125          if ((rowCuts&0x02) != 0 && goingToTrueBound && !anyColumnCuts)
     3126            strengthenCoeff(j,primalTolerance_,justReplace,canReplace,
     3127                            needEffectiveness,si,rowCut,
     3128                            rowCopy,colUpper,colLower,colsol,nstackR,stackR,
     3129                            rowUpper,rowLower,maxR,minR,realRows,
     3130                            element,index,info) ;
     3131/*
     3132  Restore row bounds.
     3133*/
    26103134          for (istackR = 0 ; istackR < nstackR ; istackR++) {
    26113135            int irow = stackR[istackR] ;
    2612 /*
    2613   Generate coefficient strengthening cuts if the user has asked for them,
    2614   and move singletons if possible.
    2615 
    2616   TODO: It looks like `move singletons' amounts to this: If all variables
    2617         in the row except the probing variable are column singletons, we
    2618         should be able to simply transfer them into the objective and let
    2619         them bang against their implicit bounds. And now that I write that,
    2620         I'm suspicious. More investigation is required.  -- lh, 101127 --
    2621 
    2622   TODO: Figure out why goingToTrueBound is relevant here, other than it's
    2623         set to zero if we're infeasible.  -- lh, 101127 --
    2624         I think that might be all there is to it.   -- lh, 101128 --
    2625         Well, maybe not. Check the math for the contained cuts to see if
    2626         it's valid only for binary variables; when within distance 1 of
    2627         the upper or lower bound of a general integer; or more generally.
    2628         GoingToTrueBound indicates the first of these two. -- lh, 110105 --
    2629 
    2630   TODO: Figure out what the third and fourth comment lines below (`Taken out
    2631         ...') mean. Because MOVE_SINGLETONS is active. If I were to hazard
    2632         a guess, the problem would be that the constraint system being probed
    2633         may have been preprocessed from the original and a column that looks
    2634         like a singleton here may not be a singleton on the original system.
    2635         Which would explain columnLength2, and why this code is again active.
    2636 
    2637         But in the end, I'm inclined towards `should be found elsewhere', as
    2638         in `do this as a preprocessing step.'
    2639         -- lh, 101127 --
    2640 
    2641   generate coefficient strengthening cuts (1)
    2642 */
    2643             if ((rowCuts&2) != 0 && goingToTrueBound) {
    2644               bool ifCut = anyColumnCuts ;
    2645 /*
    2646   Start out by working against the row upper bound U(i). Note that we're
    2647   calculating row activity (sum) and will use it to decide on the viability of
    2648   generating a cut. So if we've generated column cuts (colsol now violates a
    2649   bound for some x<j>) then the calculation of row activity will be incorrect.
    2650 
    2651   TODO: Sort out why anyColumnCuts is an obstacle. Theoretical or practical?
    2652         Could we use the new bound instead? The guard predates the singleton
    2653         business.   -- lh, 101128 --
    2654 */
    2655               double gap = rowUpper[irow]-maxR[irow] ;
    2656               double sum = 0.0 ;
    2657               if (!ifCut && (gap > primalTolerance_ && gap < 1.0e8)) {
    2658                 // see if the strengthened row is a cut
    2659                 // also see if singletons can go to good objective
    2660                 // Taken out as should be found elsewhere
    2661                 // and has to be original column length
    2662 #ifdef MOVE_SINGLETONS
    2663                 bool moveSingletons = true ;
    2664 #endif
    2665                 for (int kk = rowStart[irow] ; kk < rowStart[irow+1] ; kk++) {
    2666                   int iColumn = column[kk] ;
    2667                   double value = rowElements[kk] ;
    2668                   sum += value*colsol[iColumn] ;
    2669 #ifdef MOVE_SINGLETONS
    2670                   if (moveSingletons && j != iColumn) {
    2671                     if (colUpper[iColumn] > colLower[iColumn]) {
    2672                       if (columnLength2[iColumn] != 1) {
    2673                         moveSingletons = false ;
    2674                       }
    2675                     }
    2676                   }
    2677 #endif
    2678                 }
    2679 #ifdef MOVE_SINGLETONS
    2680 /*
    2681   jjf: can fix any with good costs.
    2682 
    2683   And room on stackC0. Comparing with similar code in the segment where down
    2684   and up probes both show feasible, we're pretending that this was already
    2685   on stackC and hence was copied to stackC0 above.
    2686 
    2687   TODO: Seems to me that the checks here for column length and bounds are
    2688         unnecessary. If they passed above, they'll pass here. -- lh, 101127 --
    2689 
    2690   TODO: Work out the math for this. In my previous passes over this bit of
    2691         code, I keep coming to the same conclusion: the math is wrong. I
    2692         need to take a serious run at it. See notes in CglProbingAnn.
    2693         -- lh, 101128 --
    2694 */
    2695                 if (moveSingletons) {
    2696                   for (int kk = rowStart[irow] ;
    2697                        kk < rowStart[irow+1] ; kk++) {
    2698                     int iColumn = column[kk] ;
    2699                     if (j != iColumn) {
    2700                       if (colUpper[iColumn] > colLower[iColumn]) {
    2701                         if (columnLength2[iColumn] == 1) {
    2702                           double value = rowElements[kk] ;
    2703                           if (direction*objective[iColumn]*value < 0.0 &&
    2704                               !(markC[iColumn]&(tightenLower|tightenUpper))) {
    2705                             if (nstackC0+1 < maxStack) {
    2706                               stackC0[nstackC0] = iColumn ;
    2707                               if (value > 0.0) {
    2708                                 lo0[nstackC0] = colUpper[iColumn] ;
    2709                                 up0[nstackC0] = colUpper[iColumn] ;
    2710                               } else {
    2711                                 lo0[nstackC0] = colLower[iColumn] ;
    2712                                 up0[nstackC0] = colLower[iColumn] ;
    2713                               }
    2714                               nstackC0++ ;
    2715                             }
    2716                           }
    2717                         }
    2718                       }
    2719                     }
    2720                   }
    2721                 }
    2722 #endif
    2723 /*
    2724   jjf: can be a cut
    2725        subtract gap from upper and integer coefficient
    2726        saveU and saveL spare
    2727 
    2728   Given b<i> - U<i> > 0 as a result of probing x<j>, we can reduce the
    2729   coefficient of x<j> and reduce b<i>.
    2730 
    2731   Borrow saveU and saveL as working arrays; their usefulness ended when stackC
    2732   processing finished, above.
    2733 
    2734   TODO: Just what sort of cut are we making here? Look this up when next up
    2735         at SFU. Must be in the presentation notes.  -- lh, 101128 --
    2736 
    2737   TODO: Why are we borrowing saveU and saveL? There are method-global element
    2738         and index arrays used everywhere else.  -- lh, 101128 --
    2739 */
    2740                 if (sum-gap*colsol[j] > maxR[irow]+primalTolerance_ ||
    2741                     (info->strengthenRow && rowLower[irow] < -1.0e20)) {
    2742                   int *index = reinterpret_cast<int *>(saveL) ;
    2743                   double *element = saveU ;
    2744                   int n = 0 ;
    2745                   bool coefficientExists = false ;
    2746                   double sum2 = 0.0 ;
    2747 /*
    2748   Generate the coefficients.
    2749 */
    2750                   for (int kk = rowStart[irow] ;
    2751                        kk < rowStart[irow+1] ; kk++) {
    2752                     int kColumn = column[kk] ;
    2753                     double el = rowElements[kk] ;
    2754                     if (kColumn != j) {
    2755                       index[n] = kColumn ;
    2756                       element[n++] = el ;
    2757                     } else {
    2758                       el = el-gap ;
    2759                       if (fabs(el) > 1.0e-12) {
    2760                         index[n] = kColumn ;
    2761                         element[n++] = el ;
    2762                       }
    2763                       coefficientExists = true ;
    2764                     }
    2765                     sum2 += colsol[kColumn]*el ;
    2766                   }
    2767                   if (!coefficientExists) {
    2768                     index[n] = j ;
    2769                     element[n++] = -gap ;
    2770                     sum2 -= colsol[j]*gap ;
    2771                   }
    2772 /*
    2773   Check effectiveness. Add the cut only if it's sufficiently effective.
    2774 
    2775   If we're simply replacing an existing constraint, this is a little bit
    2776   misleading. Effectiveness is set extremely low.
    2777 */
    2778                   OsiRowCut rc ;
    2779                   rc.setLb(-DBL_MAX) ;
    2780                   double ub = rowUpper[irow]-gap*(colLower[j]+1.0) ;
    2781                   rc.setUb(ub) ;
    2782                   double effectiveness = sum2-ub ;
    2783                   effectiveness =
    2784                       CoinMax(effectiveness,
    2785                               (sum-gap*colsol[j]-maxR[irow])/gap) ;
    2786                   if (!coefficientExists)
    2787                     effectiveness = CoinMax(1.0e-7,effectiveness) ;
    2788                   rc.setEffectiveness(effectiveness) ;
    2789                   //rc.setEffectiveness((sum-gap*colsol[j]-maxR[irow])/gap) ;
    2790                   if (rc.effectiveness() > needEffectiveness) {
    2791                     rc.setRow(n,index,element,false) ;
    2792 #if CGL_DEBUG > 0
    2793                     if (debugger) assert(!debugger->invalidCut(rc));
    2794 #endif
    2795                     // If strengthenRow point to row
    2796                     //if(info->strengthenRow)
    2797                     //printf("a point to row %d\n",irow) ;
    2798 #define STRENGTHEN_PRINT
    2799 #                   ifdef STRENGTHEN_PRINT
    2800                     if (canReplace && rowLower[irow] < -1.0e20) {
    2801                       printf("Strengthen Cut (1):\n") ;
    2802                       dump_row(irow,rc.lb(),rc.ub(),
    2803                                nan(""),nan(""),&si,true,false,4,
    2804                                n,index,element,
    2805                                1.0e-10,colLower,colUpper) ;
    2806                       printf("Original Row:\n") ;
    2807                       int k = rowStart[irow] ;
    2808                       dump_row(irow,rowLower[irow],rowUpper[irow],
    2809                                minR[irow],maxR[irow],&si,true,false,4,
    2810                                rowStart[irow+1]-k,&column[k],&rowElements[k],
    2811                                1.0e-10,colLower,colUpper) ;
    2812                     }
    2813 #                   endif
    2814 /*
    2815 Can we simply replace the existing constraint?
    2816 
    2817 realRows comes in as a parameter. This is the translation array created if
    2818 we modified the constraint system during preprocessing in gutsOfGenerateCuts.
    2819 
    2820 TODO: Seems a bit disingenuous to fail at replacement now, given that
    2821 effectiveness is artificially low. Notice again the inconsistent use of
    2822 finite infinities on the row lb.  -- lh, 101128 --
    2823 */
    2824                     int realRow =
    2825                       (canReplace && rowLower[irow] < -1.0e20)?(irow):(-1) ;
    2826                     if (realRows && realRow >= 0)
    2827                       realRow = realRows[realRow] ;
    2828                     if (!justReplace) {
    2829                       rowCut.addCutIfNotDuplicate(rc,realRow) ;
    2830                     } else if (realRow >= 0) {
    2831                       double effectiveness = 0.0 ;
    2832                       for (int i = 0 ; i < n ; i++)
    2833                         effectiveness += fabs(element[i]) ;
    2834                       if (!info->strengthenRow[realRow] ||
    2835                           info->strengthenRow[realRow]->effectiveness() > effectiveness) {
    2836                         delete info->strengthenRow[realRow] ;
    2837                         rc.setEffectiveness(effectiveness) ;
    2838                         info->strengthenRow[realRow]=rc.clone() ;
    2839                       }
    2840                     }
    2841                   }
    2842                 }
    2843               }
    2844 /*
    2845 And repeat working against the lower bound L(i). As in so many other places
    2846 in this code, it's the identical functionality, with some subtle edits that
    2847 distinguish the L(i) math from the U(i) math.
    2848 */
    2849               gap = minR[irow]-rowLower[irow] ;
    2850               if (!ifCut&&(gap>primalTolerance_&&gap<1.0e8)) {
    2851                 // see if the strengthened row is a cut
    2852                 sum =0.0 ;
    2853                 // also see if singletons can go to good objective
    2854 #ifdef MOVE_SINGLETONS
    2855                 bool moveSingletons=true ;
    2856 #endif
    2857                 for (int kk =rowStart[irow];kk<rowStart[irow+1] ;
    2858                      kk++) {
    2859                   int iColumn = column[kk] ;
    2860                   double value = rowElements[kk] ;
    2861                   sum += value*colsol[iColumn] ;
    2862 #ifdef MOVE_SINGLETONS
    2863                   if (moveSingletons&&j!=iColumn) {
    2864                     if (colUpper[iColumn]>colLower[iColumn]) {
    2865                       if (columnLength2[iColumn]!=1) {
    2866                         moveSingletons=false ;
    2867                       }
    2868                     }
    2869                   }
    2870 #endif
    2871                 }
    2872 #ifdef MOVE_SINGLETONS
    2873                 if (moveSingletons) {
    2874                   // can fix any with good costs
    2875                   for (int kk =rowStart[irow];kk<rowStart[irow+1] ;
    2876                        kk++) {
    2877                     int iColumn = column[kk] ;
    2878                     if (j!=iColumn) {
    2879                       if (colUpper[iColumn]>colLower[iColumn]) {
    2880                         if (columnLength2[iColumn]==1) {
    2881                           double value = rowElements[kk] ;
    2882                           if
    2883                           (direction*objective[iColumn]*value>0.0&&!(markC[iColumn]&(tightenLower|tightenUpper))) {
    2884                             // Fix
    2885                             if (nstackC0+1<maxStack) {
    2886                               stackC0[nstackC0]=iColumn ;
    2887                               if (value<0.0) {
    2888                                 lo0[nstackC0]=colUpper[iColumn] ;
    2889                                 up0[nstackC0]=colUpper[iColumn] ;
    2890                               } else {
    2891                                 lo0[nstackC0]=colLower[iColumn] ;
    2892                                 up0[nstackC0]=colLower[iColumn] ;
    2893                               }
    2894                               nstackC0++ ;
    2895                             }
    2896                           }
    2897                         }
    2898                       }
    2899                     }
    2900                   }
    2901                 }
    2902 #endif
    2903                 if (sum+gap*colsol[j]<minR[irow]-primalTolerance_||(info->strengthenRow&&rowUpper[irow]>1.0e20)) {
    2904                   // can be a cut
    2905                   // add gap to lower and integer coefficient
    2906                   // saveU and saveL spare
    2907                   int * index = reinterpret_cast<int *>(saveL) ;
    2908                   double * element = saveU ;
    2909                   int n=0 ;
    2910                   bool coefficientExists=false ;
    2911                   double sum2=0.0 ;
    2912                   for (int kk =rowStart[irow];kk<rowStart[irow+1] ;
    2913                        kk++) {
    2914                     int kColumn = column[kk] ;
    2915                     double el = rowElements[kk] ;
    2916                     if (kColumn!=j) {
    2917                       index[n]=kColumn ;
    2918                       element[n++]=el ;
    2919                     } else {
    2920                       el=el+gap ;
    2921                       if (fabs(el)>1.0e-12) {
    2922                         index[n]=kColumn ;
    2923                         element[n++]=el ;
    2924                       }
    2925                       coefficientExists=true ;
    2926                     }
    2927                     sum2 += colsol[kColumn]*el ;
    2928                   }
    2929                   if (!coefficientExists) {
    2930                     index[n]=j ;
    2931                     element[n++]=gap ;
    2932                     sum2 += colsol[j]*gap ;
    2933                   }
    2934                   OsiRowCut rc ;
    2935                   double lb = rowLower[irow]+gap*(colLower[j]+1.0) ;
    2936                   rc.setLb(lb) ;
    2937                   rc.setUb(DBL_MAX) ;
    2938                   // effectiveness
    2939                   double effectiveness=lb-sum2 ;
    2940                   effectiveness = CoinMax(effectiveness,
    2941                                           (minR[irow]-
    2942                                            sum-gap*colsol[j])/gap) ;
    2943                   if (!coefficientExists)
    2944                     effectiveness=CoinMax(1.0e-7,
    2945                                           effectiveness) ;
    2946                   rc.setEffectiveness(effectiveness) ;
    2947                   if (rc.effectiveness()>needEffectiveness) {
    2948                     rc.setRow(n,index,element,false) ;
    2949 #if CGL_DEBUG > 0
    2950                     if (debugger) assert(!debugger->invalidCut(rc));
    2951 #endif
    2952                     //if(info->strengthenRow)
    2953                     //printf("b point to row %d\n",irow) ;
    2954 #                   ifdef STRENGTHEN_PRINT
    2955                     if (canReplace && rowUpper[irow] > 1.0e20) {
    2956                       printf("Strengthen Cut (2):\n") ;
    2957                       dump_row(irow,rc.lb(),rc.ub(),
    2958                                nan(""),nan(""),&si,true,false,4,
    2959                                n,index,element,
    2960                                1.0e-10,colLower,colUpper) ;
    2961                       printf("Original Row:\n") ;
    2962                       int k = rowStart[irow] ;
    2963                       dump_row(irow,rowLower[irow],rowUpper[irow],
    2964                                minR[irow],maxR[irow],&si,true,false,4,
    2965                                rowStart[irow+1]-k,&column[k],&rowElements[k],
    2966                                1.0e-10,colLower,colUpper) ;
    2967                     }
    2968 #                   endif
    2969 
    2970                     int realRow = (canReplace&&rowUpper[irow]>1.0e20) ? irow : -1 ;
    2971                     if (realRows&&realRow>=0)
    2972                       realRow=realRows[realRow] ;
    2973                     if (!justReplace) {
    2974                       rowCut.addCutIfNotDuplicate(rc,realRow) ;
    2975                     } else if (realRow>=0) {
    2976                       double effectiveness=0.0 ;
    2977                       for (int i=0;i<n;i++)
    2978                         effectiveness+=fabs(element[i]) ;
    2979                       if (!info->strengthenRow[realRow]||info->strengthenRow[realRow]->effectiveness()>effectiveness) {
    2980                         delete info->strengthenRow[realRow] ;
    2981                         rc.setEffectiveness(effectiveness) ;
    2982                         info->strengthenRow[realRow]=rc.clone() ;
    2983                       }
    2984                     }
    2985                   }
    2986                 }
    2987               }
    2988             }    // end generate coefficient strengthening cuts (1)
    2989 /*
    2990 Restore row bounds.
    2991 */
    29923136            minR[irow] = saveMin[istackR] ;
    29933137            maxR[irow] = saveMax[istackR] ;
     
    29963140        }    // end of code to iterate after first down pass
    29973141/*
    2998 PROBE LOOP: DOWN AND UP FEASIBLE
    2999 
    3000 Again, not quite the full story. Cases remaining:
    3001 b) End of up probe, up and down feasible; in this case we will not
    3002    iterate.
    3003 c) End of up probe, down feasible, up infeasible; in this case we will
    3004    iterate to restore the down feasible state.
    3005 
    3006 The next block deals with case b). We don't want to iterate the
    3007 down/up/down loop, so force iway to oneProbeTooMany. As usual, the move
    3008 singleton code consists of two nearly identical blocks, one working off
    3009 U(i), the next off L(i).
    3010 
    3011 TODO: The conditions guarding the move singleton code here are different than
    3012       those for pass 0: here there's an added guard using strengthenRow.
    3013       Just a failure to change all instances? Nor do I see how John's
    3014       comment (`just at root') is enforced here, unless it's from outside
    3015       via rowCuts or strengthenRow.
    3016 
    3017       The check for any column cuts is not present, so presumably we can
    3018       do singleton motion in the presence of column cuts. The check for gap
    3019       does not have the high end (gap < 1.0e8) test.
    3020 
    3021       Note also that here the test for cut generation is moved outside the
    3022       loop that iterates over rows. Presumably that's because in the
    3023       previous case, the loop also restored markR, etc.
    3024 
    3025       Note that the code that handles the bound change is considerably
    3026       different than the previous instance in pass 0. We're adding the
    3027       changes to stackC rather than stackC0.
    3028       -- lh, 101128 --
     3142  PROBE LOOP: DOWN AND UP FEASIBLE
     3143
     3144  Again, not quite the full story. Cases remaining:
     3145  b) End of up probe, up and down feasible; in this case we will not
     3146     iterate.
     3147  c) End of up probe, down feasible, up infeasible; in this case we will
     3148     iterate to restore the down feasible state.
     3149
     3150  The next block deals with case b). We don't want to iterate the
     3151  down/up/down loop, so force iway to oneProbeTooMany. As usual, the move
     3152  singleton code consists of two nearly identical blocks, one working off
     3153  U(i), the next off L(i).
     3154
     3155  TODO: The conditions guarding the move singleton code here are different than
     3156        those for pass 0: here there's an added guard using strengthenRow.
     3157        Just a failure to change all instances? Nor do I see how John's
     3158        comment (`just at root') is enforced here, unless it's from outside
     3159        via rowCuts or strengthenRow.
     3160
     3161        The check for any column cuts is not present, so presumably we can
     3162        do singleton motion in the presence of column cuts. The check for gap
     3163        does not have the high end (gap < 1.0e8) test.
     3164
     3165        Note also that here the test for cut generation is moved outside the
     3166        loop that iterates over rows. Presumably that's because in the
     3167        previous case, the loop also restored markR, etc.
     3168
     3169        Note that the code that handles the bound change is considerably
     3170        different than the previous instance in pass 0. We're adding the
     3171        changes to stackC rather than stackC0.
     3172        -- lh, 101128 --
     3173
     3174  Moved the call to disaggCuts up from the common code for b) and c), because
     3175  c) (up infeasible) sets goingToTrueBound to 0 and we can't execute
     3176  disaggCuts. Similarly for strengthenCoeff.
    30293177*/
    30303178          else {
     
    30323180              feasRecord == (downProbeFeas|upProbeFeas)) {
    30333181            iway = oneProbeTooMany ;
    3034 #ifdef MOVE_SINGLETONS
    3035             // look for singletons that can move (just at root)
    3036             if ((rowCuts&2) != 0 &&
    3037                  goingToTrueBound && info->strengthenRow) {
    3038               for (istackR = 0 ; istackR < nstackR ; istackR++) {
    3039                 int irow = stackR[istackR] ;
    3040                 double gap = rowUpper[irow]-maxR[irow] ;
    3041                 if (gap > primalTolerance_) {
    3042                   // also see if singletons can go to good objective
    3043                   bool moveSingletons = true ;
    3044                   for (int kk = rowStart[irow] ;
    3045                        kk < rowStart[irow+1] ; kk++) {
    3046                     int iColumn = column[kk] ;
    3047                     if (moveSingletons && j != iColumn) {
    3048                       if (colUpper[iColumn] > colLower[iColumn]) {
    3049                         if (columnLength2[iColumn] != 1) {
    3050                           moveSingletons = false ;
    3051                         }
    3052                       }
    3053                     }
    3054                   }
    3055                   if (moveSingletons) {
    3056                     // can fix any with good costs
    3057                     for (int kk = rowStart[irow] ;
    3058                          kk < rowStart[irow+1] ; kk++) {
    3059                       int iColumn = column[kk] ;
    3060                       if (j != iColumn) {
    3061                         if (colUpper[iColumn] > colLower[iColumn]) {
    3062                           if (columnLength2[iColumn] == 1) {
    3063                             double value = rowElements[kk] ;
    3064                             if (direction*objective[iColumn]*value < 0.0 &&
    3065                                 !(markC[iColumn]&(tightenLower|tightenUpper))) {
    3066                               stackC[nstackC] = iColumn ;
    3067                               saveL[nstackC] = colLower[iColumn] ;
    3068                               saveU[nstackC] = colUpper[iColumn] ;
    3069                               assert(saveU[nstackC] > saveL[nstackC]) ;
    3070                               if (value > 0.0) {
    3071                                 colLower[iColumn] = colUpper[iColumn] ;
    3072                               } else {
    3073                                 colUpper[iColumn] = colLower[iColumn] ;
    3074                               }
    3075                               columnGap[iColumn] = -primalTolerance_ ;
    3076                               assert (nstackC < nCols) ;
    3077                               nstackC++ ;
    3078                             }
    3079                           }
    3080                         }
    3081                       }
    3082                     }
    3083                   }
    3084                 }
    3085 /*
    3086 Repeat move singleton checks, against L(i).
    3087 */
    3088                 gap = minR[irow]-rowLower[irow] ;
    3089                 if (gap > primalTolerance_) {
    3090                   // also see if singletons can go to good objective
    3091                   bool moveSingletons=true ;
    3092                   for (int kk =rowStart[irow];kk<rowStart[irow+1] ;
    3093                        kk++) {
    3094                     int iColumn = column[kk] ;
    3095                     if (moveSingletons&&j!=iColumn) {
    3096                       if (colUpper[iColumn]>colLower[iColumn]) {
    3097                         if (columnLength2[iColumn]!=1) {
    3098                           moveSingletons=false ;
    3099                         }
    3100                       }
    3101                     }
    3102                   }
    3103                   if (moveSingletons) {
    3104                     // can fix any with good costs
    3105                     for (int kk =rowStart[irow];kk<rowStart[irow+1] ;
    3106                        kk++) {
    3107                       int iColumn = column[kk] ;
    3108                       if (j!=iColumn) {
    3109                         if (colUpper[iColumn]>colLower[iColumn]) {
    3110                           if (columnLength2[iColumn]==1) {
    3111                             double value = rowElements[kk] ;
    3112                             if
    3113                             (direction*objective[iColumn]*value>0.0&&!(markC[iColumn]&(tightenLower|tightenUpper))) {
    3114                               // Fix
    3115                               stackC[nstackC]=iColumn ;
    3116                               saveL[nstackC]=colLower[iColumn] ;
    3117                               saveU[nstackC]=colUpper[iColumn] ;
    3118                               assert (saveU[nstackC]>saveL[nstackC]) ;
    3119                               if (value<0.0) {
    3120                                 colLower[iColumn]=colUpper[iColumn] ;
    3121                               } else {
    3122                                 colUpper[iColumn]=colLower[iColumn] ;
    3123                               }
    3124                               columnGap[iColumn] = -primalTolerance_ ;
    3125                               assert (nstackC<nCols) ;
    3126                               nstackC++ ;
    3127                             }
    3128                           }
    3129                         }
    3130                       }
    3131                     }
    3132                   }
    3133                 }
    3134               }
     3182
     3183            singletonRows(j,primalTolerance_,si,rowCopy,markC,
     3184                          nstackC,stackC,saveL,saveU,
     3185                          colUpper,colLower,columnGap,
     3186                          nstackR,stackR,rowUpper,rowLower,maxR,minR) ;
     3187            if (goingToTrueBound == 2 && !justReplace) {
     3188              disaggCuts(nstackC,probeUp,primalTolerance_,
     3189                         disaggEffectiveness,si,
     3190                         rowCut,stackC,colsol,colUpper,colLower,saveU,saveL,
     3191                         index,element) ;
     3192            if ((rowCuts&0x02) != 0 && goingToTrueBound && !anyColumnCuts)
     3193              strengthenCoeff(j,primalTolerance_,justReplace,canReplace,
     3194                              needEffectiveness,si,rowCut,
     3195                              rowCopy,colUpper,colLower,colsol,nstackR,stackR,
     3196                              rowUpper,rowLower,maxR,minR,realRows,
     3197                              element,index,info) ;
    31353198            }
    3136 #endif
    3137 /*
    3138 jjf: point back to stack
    3139 
    3140 We're done playing with singletons. Get to the real work here. We don't need
    3141 markC any more; coopt it for a cross-reference, var index -> stackC index.
    3142 The +1000 offset allows us to distinguish invalid entries (not all variables
    3143 are on stackC).
     3199/*
     3200  jjf: point back to stack
     3201
     3202  We're done playing with singletons. Get to the real work here. We don't need
     3203  markC any more; coopt it for a cross-reference, var index -> stackC index.
     3204  The +1000 offset allows us to distinguish invalid entries (not all variables
     3205  are on stackC).
    31443206*/
    31453207            for (istackC = nstackC-1 ; istackC >= 0 ; istackC--) {
     
    31513213            bool ifCut = false ;
    31523214/*
    3153 See if we have bounds improvement. Given a lower bound ld<j> from the
    3154 down probe, a bound lu<j> from the up probe, and the original bound lo<j>,
    3155 the bound we want is max(min(ld<j>,lu<j>),lo<j>). Use a conservative
    3156 tolerance.
     3215  See if we have bounds improvement. Given a lower bound ld<j> from the
     3216  down probe, a bound lu<j> from the up probe, and the original bound lo<j>,
     3217  the bound we want is max(min(ld<j>,lu<j>),lo<j>). Use a conservative
     3218  tolerance.
    31573219*/
    31583220            for (istackC = 1 ; istackC < nstackC0 ; istackC++) {
     
    31803242            }
    31813243/*
    3182 Repeat for upper bounds. There's an odd bit of asymmetry here; this loop
    3183 tries to generate a cut if there's no bound improvement.
    3184 
    3185 TODO: What, pray tell, is a `two cut'?  Binary variables only, it seems.
    3186       Judging from the conditions, we're looking for a variable that's
    3187       fixed at 0 on a down probe and fixed at 1 on an up probe, or vice
    3188       versa.
    3189       -- lh, 101128 --
     3244  Repeat for upper bounds. There's an odd bit of asymmetry here; this loop
     3245  tries to generate a cut if there's no bound improvement.
     3246
     3247  TODO: What, pray tell, is a `two cut'?  Binary variables only, it seems.
     3248        Judging from the conditions, we're looking for a variable that's
     3249        fixed at 0 on a down probe and fixed at 1 on an up probe, or vice
     3250        versa.
     3251        -- lh, 101128 --
    31903252*/
    31913253            for (istackC = 1 ; istackC < nstackC0 ; istackC++) {
     
    32253287                    element[0] = -(upperOriginal-lowerOriginal) ;
    32263288/*
    3227 jjf: If zero then - must have been fixed without noticing!
    3228 
    3229 TODO: Uh, fixed without noticing?! That's an algorithm problem.
    3230       -- lh, 101128 --
     3289  jjf: If zero then - must have been fixed without noticing!
     3290
     3291  TODO: Uh, fixed without noticing?! That's an algorithm problem.
     3292        -- lh, 101128 --
    32313293*/
    32323294                    if (fabs(element[0]) > 1.0e-8) {
     
    32833345  PROBE LOOP: RESTORE
    32843346
    3285   And now the code to reset to the initial state. (But it seems to be doing a
    3286   bit more than that. Looks like some of the actions are related to
    3287   end-of-pass processing for the up probe, similar to end-of-pass processing
    3288   for the down probe.
    3289 */
    3290           if (goingToTrueBound == 2 && !justReplace) {
    3291             disaggCuts(nstackC,probeUp,primalTolerance_,
    3292                        disaggEffectiveness,si,
    3293                        rowCut,stackC,colsol,colUpper,colLower,saveU,saveL,
    3294                        index,element) ;
    3295           }
     3347  And now the code to reset to the initial state.
     3348*/
    32963349          /* restore all */
    32973350          for (istackC = nstackC-1 ; istackC >= 0 ; istackC--) {
     
    33003353            double oldL = saveL[istackC] ;
    33013354/*
    3302 TODO: This next bit differs in subtle ways from the restore at the end
    3303       of pass 0. Here we force markC to show fixed of the bounds are
    3304       within 1.0e-4 of one another, a fairly broad tolerance; code for
    3305       the pass 0 restore does not restore fixed status.  Also,
    3306       we're not distinguishing here between actions for down feasible,
    3307       up feasible, vs. down feasible, up infeasible.  -- lh, 101128 --
    3308 
     3355  TODO: This next bit differs in subtle ways from the restore at the end
     3356        of the down probe. Here we force markC to show fixed if the bounds are
     3357        within 1.0e-4 of one another, a fairly broad tolerance; code for
     3358        the pass 0 restore does not restore fixed status.  Also,
     3359        we're not distinguishing here between actions for down feasible,
     3360        up feasible, vs. down feasible, up infeasible.  -- lh, 101128 --
     3361
     3362        I still don't see any reason for the restore here to differ from
     3363        the restore after the down probe.  -- lh, 110113 --
    33093364*/
    33103365            colUpper[icol] = oldU ;
     
    33223377          }
    33233378/*
    3324 End of column restore. On to rows. Looks much like the end of pass 0 except
    3325 that the singleton stuff was done up in the down feasible, up feasible
    3326 block. Presumably we don't want to do it in the down feasible, up infeasible
    3327 case. And we won't generate cuts for up infeasible because goingToTrueBound
    3328 has been forced to zero.
    3329 
    3330 TODO: Note that here we run a separate loop to calculate sum, because we
    3331       can't piggyback on the singleton loop.  -- lh, 101128 --
    3332 
    3333 TODO: Again, subtle but important differences between this code and the code
    3334       that follows pass 0.   -- lh, 101128 --
    3335 
    3336 TODO: Recalculation of canReplace seems completely pointless here.
    3337       -- lh, 101128 --
    3338 
    3339 begin generate coefficient strengthening cuts (2)
     3379  End of column restore. On to rows.
    33403380*/
    33413381          for (istackR = 0 ; istackR < nstackR ; istackR++) {
    33423382            int irow = stackR[istackR] ;
    3343             // switch off strengthening if not wanted
    3344             if ((rowCuts&2) != 0 && goingToTrueBound) {
    3345               bool canReplace = info->strengthenRow && (goingToTrueBound==2) ;
    3346               bool ifCut = anyColumnCuts ;
    3347               double gap = rowUpper[irow]-maxR[irow] ;
    3348               double sum = 0.0 ;
    3349               if (!ifCut && (gap > primalTolerance_ && gap < 1.0e8)) {
    3350                 // see if the strengthened row is a cut
    3351                 for (int kk = rowStart[irow] ;
    3352                      kk < rowStart[irow+1] ; kk++) {
    3353                   sum += rowElements[kk]*colsol[column[kk]] ;
    3354                 }
    3355 /*
    3356 Same commentary as previous code in pass 0 finishing block.
    3357 
    3358 TODO: This condition differs from the pass 0 condition. canReplace replaces
    3359       a simple info->strengthenRow.  -- lh, 101128 --
    3360 */
    3361                 if (sum+gap*colsol[j] > rowUpper[irow]+primalTolerance_ ||
    3362                     (canReplace && rowLower[irow]<-1.e20)) {
    3363                   int * index = reinterpret_cast<int *>(saveL) ;
    3364                   double * element = saveU ;
    3365                   int n=0 ;
    3366                   bool coefficientExists=false ;
    3367                   double sum2=0.0 ;
    3368                   for (int kk =rowStart[irow];kk<rowStart[irow+1] ;
    3369                        kk++) {
    3370                     int kColumn = column[kk] ;
    3371                     double el = rowElements[kk] ;
    3372                     if (kColumn!=j) {
    3373                       index[n]=kColumn ;
    3374                       element[n++]=el ;
    3375                     } else {
    3376                       el=el+gap ;
    3377                       if (fabs(el)>1.0e-12) {
    3378                         index[n]=kColumn ;
    3379                         element[n++]=el ;
    3380                       }
    3381                       coefficientExists=true ;
    3382                     }
    3383                     sum2 += colsol[kColumn]*el ;
    3384                   }
    3385                   if (!coefficientExists) {
    3386                     index[n]=j ;
    3387                     element[n++]=gap ;
    3388                     sum2 += colsol[j]*gap ;
    3389                   }
    3390                   OsiRowCut rc ;
    3391                   rc.setLb(-DBL_MAX) ;
    3392                   double ub = rowUpper[irow]+gap*(colUpper[j]-1.0) ;
    3393                   rc.setUb(ub) ;
    3394                   // effectiveness
    3395                   double effectiveness=sum2-ub ;
    3396                   effectiveness = CoinMax(effectiveness,
    3397                                           (sum+gap*colsol[j]-
    3398                                            rowUpper[irow])/gap) ;
    3399                   if (!coefficientExists)
    3400                     effectiveness=CoinMax(1.0e-7,
    3401                                           effectiveness) ;
    3402                   rc.setEffectiveness(effectiveness) ;
    3403                   if (rc.effectiveness()>needEffectiveness) {
    3404                     rc.setRow(n,index,element,false) ;
    3405 #if CGL_DEBUG > 0
    3406                     if (debugger) assert(!debugger->invalidCut(rc));
    3407 #endif
    3408                     //if(canReplace)
    3409                     //printf("c point to row %d\n",irow) ;
    3410 #                   ifdef STRENGTHEN_PRINT
    3411                     if (canReplace && rowLower[irow] < -1.0e20) {
    3412                       printf("Strengthen Cut (3):\n") ;
    3413                       dump_row(irow,rc.lb(),rc.ub(),
    3414                                nan(""),nan(""),&si,true,false,4,
    3415                                n,index,element,
    3416                                1.0e-10,colLower,colUpper) ;
    3417                       printf("Original Row:\n") ;
    3418                       int k = rowStart[irow] ;
    3419                       dump_row(irow,rowLower[irow],rowUpper[irow],
    3420                                minR[irow],maxR[irow],&si,true,false,4,
    3421                                rowStart[irow+1]-k,&column[k],&rowElements[k],
    3422                                1.0e-10,colLower,colUpper) ;
    3423                     }
    3424 #                   endif
    3425                     int realRow = (canReplace&&rowLower[irow]<-1.0e20) ? irow : -1 ;
    3426                     if (realRows&&realRow>=0)
    3427                       realRow=realRows[realRow] ;
    3428                     if (!justReplace) {
    3429                       rowCut.addCutIfNotDuplicate(rc,realRow) ;
    3430                     } else if (realRow>=0) {
    3431                       double effectiveness=0.0 ;
    3432                       for (int i=0;i<n;i++)
    3433                         effectiveness+=fabs(element[i]) ;
    3434                       if (!info->strengthenRow[realRow]||info->strengthenRow[realRow]->effectiveness()>effectiveness) {
    3435                         delete info->strengthenRow[realRow] ;
    3436                         rc.setEffectiveness(effectiveness) ;
    3437                         info->strengthenRow[realRow]=rc.clone() ;
    3438                       }
    3439                     }
    3440                   }
    3441                 }
    3442               }
    3443 /*
    3444 As with pass 0 code, repeat working against row lower bound.
    3445 */
    3446               gap = minR[irow]-rowLower[irow] ;
    3447               if (!ifCut&&(gap>primalTolerance_&&gap<1.0e8)) {
    3448                 // see if the strengthened row is a cut
    3449                 if (!sum) {
    3450                   for (int kk =rowStart[irow];kk<rowStart[irow+1] ;
    3451                        kk++) {
    3452                     sum += rowElements[kk]*colsol[column[kk]] ;
    3453                   }
    3454                 }
    3455                 if (sum-gap*colsol[j]<rowLower[irow]-primalTolerance_||(canReplace&&rowUpper[irow]>1.0e20)) {
    3456                   // can be a cut
    3457                   // subtract gap from integer coefficient
    3458                   // saveU and saveL spare
    3459                   int * index = reinterpret_cast<int *>(saveL) ;
    3460                   double * element = saveU ;
    3461                   int n=0 ;
    3462                   bool coefficientExists=false ;
    3463                   double sum2=0.0 ;
    3464                   for (int kk =rowStart[irow];kk<rowStart[irow+1] ;
    3465                        kk++) {
    3466                     int kColumn = column[kk] ;
    3467                     double el = rowElements[kk] ;
    3468                     if (kColumn!=j) {
    3469                       index[n]=kColumn ;
    3470                       element[n++]=el ;
    3471                     } else {
    3472                       el=el-gap ;
    3473                       if (fabs(el)>1.0e-12) {
    3474                         index[n]=kColumn ;
    3475                         element[n++]=el ;
    3476                       }
    3477                       coefficientExists=true ;
    3478                     }
    3479                     sum2 += colsol[kColumn]*el ;
    3480                   }
    3481                   if (!coefficientExists) {
    3482                     index[n]=j ;
    3483                     element[n++]=-gap ;
    3484                     sum2 -= colsol[j]*gap ;
    3485                   }
    3486                   OsiRowCut rc ;
    3487                   double lb = rowLower[irow]-gap*(colUpper[j]-1) ;
    3488                   rc.setLb(lb) ;
    3489                   rc.setUb(DBL_MAX) ;
    3490                   double effectiveness=lb-sum2 ;
    3491                   effectiveness = CoinMax(effectiveness,
    3492                                           (rowLower[irow]-
    3493                                            sum+gap*colsol[j])/gap) ;
    3494                   if (!coefficientExists)
    3495                     effectiveness=CoinMax(1.0e-7,
    3496                                           effectiveness) ;
    3497                   rc.setEffectiveness(effectiveness) ;
    3498                   if (rc.effectiveness()>needEffectiveness) {
    3499                     rc.setRow(n,index,element,false) ;
    3500 #if CGL_DEBUG > 0
    3501                     if (debugger) assert(!debugger->invalidCut(rc));
    3502 #endif
    3503                     //if(canReplace)
    3504                     //printf("d point to row %d\n",irow) ;
    3505 #                   ifdef STRENGTHEN_PRINT
    3506                     if (canReplace && rowUpper[irow] > 1.0e20) {
    3507                       printf("Strengthen Cut (4):\n") ;
    3508                       dump_row(irow,rc.lb(),rc.ub(),
    3509                                nan(""),nan(""),&si,true,false,4,
    3510                                n,index,element,
    3511                                1.0e-10,colLower,colUpper) ;
    3512                       printf("Original Row:\n") ;
    3513                       int k = rowStart[irow] ;
    3514                       dump_row(irow,rowLower[irow],rowUpper[irow],
    3515                                minR[irow],maxR[irow],&si,true,false,4,
    3516                                rowStart[irow+1]-k,&column[k],&rowElements[k],
    3517                                1.0e-10,colLower,colUpper) ;
    3518                     }
    3519 #                   endif
    3520                     int realRow = (canReplace&&rowUpper[irow]>1.0e20) ? irow : -1 ;
    3521                     if (realRows&&realRow>=0)
    3522                       realRow=realRows[realRow] ;
    3523                     if (!justReplace) {
    3524                       rowCut.addCutIfNotDuplicate(rc,realRow) ;
    3525                     } else if (realRow>=0) {
    3526                       double effectiveness=0.0 ;
    3527                       for (int i=0;i<n;i++)
    3528                         effectiveness+=fabs(element[i]) ;
    3529                       if (!info->strengthenRow[realRow]||info->strengthenRow[realRow]->effectiveness()>effectiveness) {
    3530                         delete info->strengthenRow[realRow] ;
    3531                         rc.setEffectiveness(effectiveness) ;
    3532                         info->strengthenRow[realRow]=rc.clone() ;
    3533                       }
    3534                     }
    3535                   }
    3536                 }
    3537               }
    3538             }    // end generate coefficient strengthening cuts (2)
    3539             minR[irow]=saveMin[istackR] ;
    3540             maxR[irow]=saveMax[istackR] ;
    3541             markR[irow]=-1 ;
     3383            minR[irow] = saveMin[istackR] ;
     3384            maxR[irow] = saveMax[istackR] ;
     3385            markR[irow] = -1 ;
    35423386          }
    35433387        }       // end of PROBE: DOWN AND UP FEASIBLE
Note: See TracChangeset for help on using the changeset viewer.