Example #1
0
//------------------------------------------------------------------------------
// Invert
//------------------------------------------------------------------------------
bool Matrix::invert()
{
   bool ok = mda != nullptr && rows > 0 && cols > 0 && isSquare();

   if (ok) {
      Matrix m(rows, cols);
      m.makeIdent();
      unsigned int origCols = cols;  // 'cols' is changed after augment()
      augment(m);

      for (unsigned int k = 0; k < origCols; k++) {
         pivotRow(k,k);
         mulRow(k, 1.0/getElem(k,k));
         for (unsigned int i=0; i<rows; i++) {
            if (i != k) {
               addRow(i, k, -getElem(i,k));
            }
         }
      }

      remCols(0, origCols-1);
   }
   return ok;
}
Example #2
0
// Returns pivot row, -1 if none
int
ClpDualRowSteepest::pivotRow()
{
     assert(model_);
     int i, iRow;
     double * infeas = infeasible_->denseVector();
     double largest = 0.0;
     int * index = infeasible_->getIndices();
     int number = infeasible_->getNumElements();
     const int * pivotVariable = model_->pivotVariable();
     int chosenRow = -1;
     int lastPivotRow = model_->pivotRow();
     assert (lastPivotRow < model_->numberRows());
     double tolerance = model_->currentPrimalTolerance();
     // we can't really trust infeasibilities if there is primal error
     // this coding has to mimic coding in checkPrimalSolution
     double error = CoinMin(1.0e-2, model_->largestPrimalError());
     // allow tolerance at least slightly bigger than standard
     tolerance = tolerance +  error;
     // But cap
     tolerance = CoinMin(1000.0, tolerance);
     tolerance *= tolerance; // as we are using squares
     bool toleranceChanged = false;
     double * solution = model_->solutionRegion();
     double * lower = model_->lowerRegion();
     double * upper = model_->upperRegion();
     // do last pivot row one here
     //#define CLP_DUAL_FIXED_COLUMN_MULTIPLIER 10.0
     if (lastPivotRow >= 0 && lastPivotRow < model_->numberRows()) {
#ifdef CLP_DUAL_COLUMN_MULTIPLIER
          int numberColumns = model_->numberColumns();
#endif
          int iPivot = pivotVariable[lastPivotRow];
          double value = solution[iPivot];
          double lower = model_->lower(iPivot);
          double upper = model_->upper(iPivot);
          if (value > upper + tolerance) {
               value -= upper;
               value *= value;
#ifdef CLP_DUAL_COLUMN_MULTIPLIER
               if (iPivot < numberColumns)
                    value *= CLP_DUAL_COLUMN_MULTIPLIER; // bias towards columns
#endif
               // store square in list
               if (infeas[lastPivotRow])
                    infeas[lastPivotRow] = value; // already there
               else
                    infeasible_->quickAdd(lastPivotRow, value);
          } else if (value < lower - tolerance) {
               value -= lower;
               value *= value;
#ifdef CLP_DUAL_COLUMN_MULTIPLIER
               if (iPivot < numberColumns)
                    value *= CLP_DUAL_COLUMN_MULTIPLIER; // bias towards columns
#endif
               // store square in list
               if (infeas[lastPivotRow])
                    infeas[lastPivotRow] = value; // already there
               else
                    infeasible_->add(lastPivotRow, value);
          } else {
               // feasible - was it infeasible - if so set tiny
               if (infeas[lastPivotRow])
                    infeas[lastPivotRow] = COIN_INDEXED_REALLY_TINY_ELEMENT;
          }
          number = infeasible_->getNumElements();
     }
     if(model_->numberIterations() < model_->lastBadIteration() + 200) {
          // we can't really trust infeasibilities if there is dual error
          if (model_->largestDualError() > model_->largestPrimalError()) {
               tolerance *= CoinMin(model_->largestDualError() / model_->largestPrimalError(), 1000.0);
               toleranceChanged = true;
          }
     }
     int numberWanted;
     if (mode_ < 2 ) {
          numberWanted = number + 1;
     } else if (mode_ == 2) {
          numberWanted = CoinMax(2000, number / 8);
     } else {
          int numberElements = model_->factorization()->numberElements();
          double ratio = static_cast<double> (numberElements) /
                         static_cast<double> (model_->numberRows());
          numberWanted = CoinMax(2000, number / 8);
          if (ratio < 1.0) {
               numberWanted = CoinMax(2000, number / 20);
          } else if (ratio > 10.0) {
               ratio = number * (ratio / 80.0);
               if (ratio > number)
                    numberWanted = number + 1;
               else
                    numberWanted = CoinMax(2000, static_cast<int> (ratio));
          }
     }
     if (model_->largestPrimalError() > 1.0e-3)
          numberWanted = number + 1; // be safe
     int iPass;
     // Setup two passes
     int start[4];
     start[1] = number;
     start[2] = 0;
     double dstart = static_cast<double> (number) * model_->randomNumberGenerator()->randomDouble();
     start[0] = static_cast<int> (dstart);
     start[3] = start[0];
     //double largestWeight=0.0;
     //double smallestWeight=1.0e100;
     for (iPass = 0; iPass < 2; iPass++) {
          int end = start[2*iPass+1];
          for (i = start[2*iPass]; i < end; i++) {
               iRow = index[i];
               double value = infeas[iRow];
               if (value > tolerance) {
                    //#define OUT_EQ
#ifdef OUT_EQ
                    {
                         int iSequence = pivotVariable[iRow];
                         if (upper[iSequence] == lower[iSequence])
                              value *= 2.0;
                    }
#endif
                    double weight = CoinMin(weights_[iRow], 1.0e50);
                    //largestWeight = CoinMax(largestWeight,weight);
                    //smallestWeight = CoinMin(smallestWeight,weight);
                    //double dubious = dubiousWeights_[iRow];
                    //weight *= dubious;
                    //if (value>2.0*largest*weight||(value>0.5*largest*weight&&value*largestWeight>dubious*largest*weight)) {
                    if (value > largest * weight) {
                         // make last pivot row last resort choice
                         if (iRow == lastPivotRow) {
                              if (value * 1.0e-10 < largest * weight)
                                   continue;
                              else
                                   value *= 1.0e-10;
                         }
                         int iSequence = pivotVariable[iRow];
                         if (!model_->flagged(iSequence)) {
                              //#define CLP_DEBUG 3
#ifdef CLP_DEBUG
                              double value2 = 0.0;
                              if (solution[iSequence] > upper[iSequence] + tolerance)
                                   value2 = solution[iSequence] - upper[iSequence];
                              else if (solution[iSequence] < lower[iSequence] - tolerance)
                                   value2 = solution[iSequence] - lower[iSequence];
                              assert(fabs(value2 * value2 - infeas[iRow]) < 1.0e-8 * CoinMin(value2 * value2, infeas[iRow]));
#endif
                              if (solution[iSequence] > upper[iSequence] + tolerance ||
                                        solution[iSequence] < lower[iSequence] - tolerance) {
                                   chosenRow = iRow;
                                   largest = value / weight;
                                   //largestWeight = dubious;
                              }
                         } else {
                              // just to make sure we don't exit before got something
                              numberWanted++;
                         }
                    }
                    numberWanted--;
                    if (!numberWanted)
                         break;
               }
          }
          if (!numberWanted)
               break;
     }
     //printf("smallest %g largest %g\n",smallestWeight,largestWeight);
     if (chosenRow < 0 && toleranceChanged) {
          // won't line up with checkPrimalSolution - do again
          double saveError = model_->largestDualError();
          model_->setLargestDualError(0.0);
          // can't loop
          chosenRow = pivotRow();
          model_->setLargestDualError(saveError);
     }
     if (chosenRow < 0 && lastPivotRow < 0) {
          int nLeft = 0;
          for (int i = 0; i < number; i++) {
               int iRow = index[i];
               if (fabs(infeas[iRow]) > 1.0e-50) {
                    index[nLeft++] = iRow;
               } else {
                    infeas[iRow] = 0.0;
               }
          }
          infeasible_->setNumElements(nLeft);
          model_->setNumberPrimalInfeasibilities(nLeft);
     }
     return chosenRow;
}