//------------------------------------------------------------------------------ // 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; }
// 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; }