/* $Id$ */ // Copyright (C) 2000, International Business Machines // Corporation and others, Copyright (C) 2012, FasterCoin. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). #include "ClpConfig.h" #include "CoinPragma.hpp" #include //#define ABC_DEBUG 2 #if SLIM_CLP == 2 #define SLIM_NOIO #endif #include "CoinHelperFunctions.hpp" #include "CoinFloatEqual.hpp" #include "ClpSimplex.hpp" #include "AbcSimplex.hpp" #include "AbcSimplexDual.hpp" #include "AbcSimplexFactorization.hpp" #include "AbcNonLinearCost.hpp" #include "CoinAbcCommon.hpp" #include "AbcMatrix.hpp" #include "CoinIndexedVector.hpp" #include "AbcDualRowDantzig.hpp" #include "AbcDualRowSteepest.hpp" #include "AbcPrimalColumnDantzig.hpp" #include "AbcPrimalColumnSteepest.hpp" #include "ClpMessage.hpp" #include "ClpEventHandler.hpp" #include "ClpLinearObjective.hpp" #include "CoinAbcHelperFunctions.hpp" #include "CoinModel.hpp" #include "CoinLpIO.hpp" #include #include #include #include //############################################################################# AbcSimplex::AbcSimplex(bool emptyMessages) : ClpSimplex(emptyMessages) { gutsOfDelete(0); gutsOfInitialize(0, 0, true); assert(maximumAbcNumberRows_ >= 0); //printf("XX %x AbcSimplex constructor\n",this); } //----------------------------------------------------------------------------- AbcSimplex::~AbcSimplex() { //printf("XX %x AbcSimplex destructor\n",this); gutsOfDelete(1); } // Copy constructor. AbcSimplex::AbcSimplex(const AbcSimplex &rhs) : ClpSimplex(rhs) { //printf("XX %x AbcSimplex constructor from %x\n",this,&rhs); gutsOfDelete(0); gutsOfInitialize(numberRows_, numberColumns_, false); gutsOfCopy(rhs); assert(maximumAbcNumberRows_ >= 0); } #include "ClpDualRowSteepest.hpp" #include "ClpPrimalColumnSteepest.hpp" #include "ClpFactorization.hpp" // Copy constructor from model AbcSimplex::AbcSimplex(const ClpSimplex &rhs) : ClpSimplex(rhs) { //printf("XX %x AbcSimplex constructor from ClpSimplex\n",this); gutsOfDelete(0); gutsOfInitialize(numberRows_, numberColumns_, true); gutsOfResize(numberRows_, numberColumns_); // Set up row/column selection and factorization type ClpDualRowSteepest *pivot = dynamic_cast< ClpDualRowSteepest * >(rhs.dualRowPivot()); if (pivot) { AbcDualRowSteepest steep(pivot->mode()); setDualRowPivotAlgorithm(steep); } else { AbcDualRowDantzig dantzig; setDualRowPivotAlgorithm(dantzig); } ClpPrimalColumnSteepest *pivotColumn = dynamic_cast< ClpPrimalColumnSteepest * >(rhs.primalColumnPivot()); if (pivotColumn) { AbcPrimalColumnSteepest steep(pivotColumn->mode()); setPrimalColumnPivotAlgorithm(steep); } else { AbcPrimalColumnDantzig dantzig; setPrimalColumnPivotAlgorithm(dantzig); } //if (rhs.factorization()->) //factorization_->forceOtherFactorization(); factorization()->synchronize(rhs.factorization(), this); //factorization_->setGoDenseThreshold(rhs.factorization()->goDenseThreshold()); //factorization_->setGoSmallThreshold(rhs.factorization()->goSmallThreshold()); translate(DO_SCALE_AND_MATRIX | DO_BASIS_AND_ORDER | DO_STATUS | DO_SOLUTION); assert(maximumAbcNumberRows_ >= 0); } // Assignment operator. This copies the data AbcSimplex & AbcSimplex::operator=(const AbcSimplex &rhs) { if (this != &rhs) { gutsOfDelete(1); ClpSimplex::operator=(rhs); gutsOfCopy(rhs); assert(maximumAbcNumberRows_ >= 0); } return *this; } // fills in perturbationSaved_ from start with 0.5+random void AbcSimplex::fillPerturbation(int start, int number) { double *array = perturbationSaved_ + start; for (int i = 0; i < number; i++) array[i] = 0.5 + 0.5 * randomNumberGenerator_.randomDouble(); } // Sets up all extra pointers void AbcSimplex::setupPointers(int maxRows, int maxColumns) { int numberTotal = maxRows + maxColumns; scaleToExternal_ = scaleFromExternal_ + numberTotal; tempArray_ = offset_ + numberTotal; lowerSaved_ = abcLower_ + numberTotal; upperSaved_ = abcUpper_ + numberTotal; costSaved_ = abcCost_ + numberTotal; solutionSaved_ = abcSolution_ + numberTotal; djSaved_ = abcDj_ + numberTotal; internalStatusSaved_ = internalStatus_ + numberTotal; perturbationSaved_ = abcPerturbation_ + numberTotal; offsetRhs_ = tempArray_ + numberTotal; lowerBasic_ = lowerSaved_ + numberTotal; upperBasic_ = upperSaved_ + numberTotal; costBasic_ = costSaved_ + 2 * numberTotal; solutionBasic_ = solutionSaved_ + numberTotal; djBasic_ = djSaved_ + numberTotal; perturbationBasic_ = perturbationSaved_ + numberTotal; columnUseScale_ = scaleToExternal_ + maxRows; inverseColumnUseScale_ = scaleFromExternal_ + maxRows; } // Copies all saved versions to working versions and may do something for perturbation void AbcSimplex::copyFromSaved(int which) { if ((which & 1) != 0) CoinAbcMemcpy(abcSolution_, solutionSaved_, maximumNumberTotal_); if ((which & 2) != 0) CoinAbcMemcpy(abcCost_, costSaved_, maximumNumberTotal_); if ((which & 4) != 0) CoinAbcMemcpy(abcLower_, lowerSaved_, maximumNumberTotal_); if ((which & 8) != 0) CoinAbcMemcpy(abcUpper_, upperSaved_, maximumNumberTotal_); if ((which & 16) != 0) CoinAbcMemcpy(abcDj_, djSaved_, maximumNumberTotal_); if ((which & 32) != 0) { CoinAbcMemcpy(abcLower_, abcPerturbation_, numberTotal_); CoinAbcMemcpy(abcUpper_, abcPerturbation_ + numberTotal_, numberTotal_); } } void AbcSimplex::gutsOfCopy(const AbcSimplex &rhs) { #ifdef ABC_INHERIT abcSimplex_ = this; #endif assert(numberRows_ == rhs.numberRows_); assert(numberColumns_ == rhs.numberColumns_); numberTotal_ = rhs.numberTotal_; maximumNumberTotal_ = rhs.maximumNumberTotal_; // special options here to be safe specialOptions_ = rhs.specialOptions_; //assert (maximumInternalRows_ >= numberRows_); //assert (maximumInternalColumns_ >= numberColumns_); // Copy all scalars CoinAbcMemcpy(reinterpret_cast< int * >(&sumNonBasicCosts_), reinterpret_cast< const int * >(&rhs.sumNonBasicCosts_), (&swappedAlgorithm_ - reinterpret_cast< int * >(&sumNonBasicCosts_)) + 1); // could add 2 so can go off end int sizeArray = 2 * maximumNumberTotal_ + maximumAbcNumberRows_; internalStatus_ = ClpCopyOfArray(rhs.internalStatus_, sizeArray + maximumNumberTotal_); abcLower_ = ClpCopyOfArray(rhs.abcLower_, sizeArray); abcUpper_ = ClpCopyOfArray(rhs.abcUpper_, sizeArray); abcCost_ = ClpCopyOfArray(rhs.abcCost_, sizeArray + maximumNumberTotal_); abcDj_ = ClpCopyOfArray(rhs.abcDj_, sizeArray); abcSolution_ = ClpCopyOfArray(rhs.abcSolution_, sizeArray + maximumNumberTotal_); abcPerturbation_ = ClpCopyOfArray(rhs.abcPerturbation_, sizeArray); abcPivotVariable_ = ClpCopyOfArray(rhs.abcPivotVariable_, maximumAbcNumberRows_); //fromExternal_ = ClpCopyOfArray(rhs.fromExternal_,sizeArray); //toExternal_ = ClpCopyOfArray(rhs.toExternal_,sizeArray); scaleFromExternal_ = ClpCopyOfArray(rhs.scaleFromExternal_, sizeArray); offset_ = ClpCopyOfArray(rhs.offset_, sizeArray); setupPointers(maximumAbcNumberRows_, maximumAbcNumberColumns_); if (rhs.abcMatrix_) abcMatrix_ = new AbcMatrix(*rhs.abcMatrix_); else abcMatrix_ = NULL; for (int i = 0; i < ABC_NUMBER_USEFUL; i++) { usefulArray_[i] = rhs.usefulArray_[i]; } if (rhs.abcFactorization_) { setFactorization(*rhs.abcFactorization_); } else { delete abcFactorization_; abcFactorization_ = NULL; } #ifdef EARLY_FACTORIZE delete abcEarlyFactorization_; if (rhs.abcEarlyFactorization_) { abcEarlyFactorization_ = new AbcSimplexFactorization(*rhs.abcEarlyFactorization_); } else { abcEarlyFactorization_ = NULL; } #endif abcDualRowPivot_ = rhs.abcDualRowPivot_->clone(true); abcDualRowPivot_->setModel(this); abcPrimalColumnPivot_ = rhs.abcPrimalColumnPivot_->clone(true); abcPrimalColumnPivot_->setModel(this); if (rhs.abcBaseModel_) { abcBaseModel_ = new AbcSimplex(*rhs.abcBaseModel_); } else { abcBaseModel_ = NULL; } if (rhs.clpModel_) { clpModel_ = new ClpSimplex(*rhs.clpModel_); } else { clpModel_ = NULL; } abcProgress_ = rhs.abcProgress_; solveType_ = rhs.solveType_; } // type == 0 nullify, 1 also delete void AbcSimplex::gutsOfDelete(int type) { if (type) { delete[] abcLower_; delete[] abcUpper_; delete[] abcCost_; delete[] abcDj_; delete[] abcSolution_; //delete [] fromExternal_ ; //delete [] toExternal_ ; delete[] scaleFromExternal_; //delete [] scaleToExternal_ ; delete[] offset_; delete[] internalStatus_; delete[] abcPerturbation_; delete abcMatrix_; delete abcFactorization_; #ifdef EARLY_FACTORIZE delete abcEarlyFactorization_; #endif delete[] abcPivotVariable_; delete abcDualRowPivot_; delete abcPrimalColumnPivot_; delete abcBaseModel_; delete clpModel_; delete abcNonLinearCost_; } CoinAbcMemset0(reinterpret_cast< char * >(&scaleToExternal_), reinterpret_cast< char * >(&usefulArray_[0]) - reinterpret_cast< char * >(&scaleToExternal_)); } template < class T > T *newArray(T * /*nullArray*/, int size) { if (size) { T *arrayNew = new T[size]; #ifndef NDEBUG memset(arrayNew, 'A', (size) * sizeof(T)); #endif return arrayNew; } else { return NULL; } } template < class T > T *resizeArray(T *array, int oldSize1, int oldSize2, int newSize1, int newSize2, int extra) { if ((array || !oldSize1) && (newSize1 != oldSize1 || newSize2 != oldSize2)) { int newTotal = newSize1 + newSize2; int oldTotal = oldSize1 + oldSize2; T *arrayNew; if (newSize1 > oldSize1 || newSize2 > oldSize2) { arrayNew = new T[2 * newTotal + newSize1 + extra]; #ifndef NDEBUG memset(arrayNew, 'A', (2 * newTotal + newSize1 + extra) * sizeof(T)); #endif CoinAbcMemcpy(arrayNew, array, oldSize1); CoinAbcMemcpy(arrayNew + newSize1, array + oldSize1, oldSize2); // and second half CoinAbcMemcpy(arrayNew + newTotal, array, oldSize1 + oldTotal); CoinAbcMemcpy(arrayNew + newSize1 + newTotal, array + oldSize1 + oldTotal, oldSize2); delete[] array; } else { arrayNew = array; for (int i = 0; i < newSize2; i++) array[newSize1 + i] = array[oldSize1 + i]; for (int i = 0; i < newSize1; i++) array[newTotal + i] = array[oldTotal + i]; for (int i = 0; i < newSize2; i++) array[newSize1 + newTotal + i] = array[oldSize1 + oldTotal + i]; } return arrayNew; } else { return array; } } // Initializes arrays void AbcSimplex::gutsOfInitialize(int numberRows, int numberColumns, bool doMore) { #ifdef ABC_INHERIT abcSimplex_ = this; #endif // Zero all CoinAbcMemset0(&sumNonBasicCosts_, (reinterpret_cast< double * >(&usefulArray_[0]) - &sumNonBasicCosts_)); zeroTolerance_ = 1.0e-13; bestObjectiveValue_ = -COIN_DBL_MAX; primalToleranceToGetOptimal_ = -1.0; primalTolerance_ = 1.0e-6; //dualTolerance_ = 1.0e-6; alphaAccuracy_ = -1.0; upperIn_ = -COIN_DBL_MAX; lowerOut_ = -1; valueOut_ = -1; upperOut_ = -1; dualOut_ = -1; acceptablePivot_ = 1.0e-8; //dualBound_=1.0e9; sequenceIn_ = -1; directionIn_ = -1; sequenceOut_ = -1; directionOut_ = -1; pivotRow_ = -1; lastGoodIteration_ = -100; numberPrimalInfeasibilities_ = 100; numberRefinements_ = 1; changeMade_ = 1; forceFactorization_ = -1; if (perturbation_ < 50 || (perturbation_ > 60 && perturbation_ < 100)) perturbation_ = 50; lastBadIteration_ = -999999; lastFlaggedIteration_ = -999999; // doesn't seem to be used firstFree_ = -1; incomingInfeasibility_ = 1.0; allowedInfeasibility_ = 10.0; solveType_ = 1; // say simplex based life form //specialOptions_|=65536; //ClpModel::startPermanentArrays(); maximumInternalRows_ = 0; maximumInternalColumns_ = 0; numberRows_ = numberRows; numberColumns_ = numberColumns; numberTotal_ = numberRows_ + numberColumns_; maximumAbcNumberRows_ = numberRows; maximumAbcNumberColumns_ = numberColumns; maximumNumberTotal_ = numberTotal_; int sizeArray = 2 * maximumNumberTotal_ + maximumAbcNumberRows_; if (doMore) { // say Steepest pricing abcDualRowPivot_ = new AbcDualRowSteepest(); abcPrimalColumnPivot_ = new AbcPrimalColumnSteepest(); internalStatus_ = newArray((unsigned char *)NULL, sizeArray + maximumNumberTotal_); abcLower_ = newArray((double *)NULL, sizeArray); abcUpper_ = newArray((double *)NULL, sizeArray); abcCost_ = newArray((double *)NULL, sizeArray + maximumNumberTotal_); abcDj_ = newArray((double *)NULL, sizeArray); abcSolution_ = newArray((double *)NULL, sizeArray + maximumNumberTotal_); //fromExternal_ = newArray((int *)NULL,sizeArray); //toExternal_ = newArray((int *)NULL,sizeArray); scaleFromExternal_ = newArray((double *)NULL, sizeArray); offset_ = newArray((double *)NULL, sizeArray); abcPerturbation_ = newArray((double *)NULL, sizeArray); abcPivotVariable_ = newArray((int *)NULL, maximumAbcNumberRows_); // Fill perturbation array setupPointers(maximumAbcNumberRows_, maximumAbcNumberColumns_); fillPerturbation(0, maximumNumberTotal_); } // get an empty factorization so we can set tolerances etc getEmptyFactorization(); for (int i = 0; i < ABC_NUMBER_USEFUL; i++) usefulArray_[i].reserve(CoinMax(CoinMax(numberTotal_, maximumAbcNumberRows_ + 200), 2 * numberRows_)); //savedStatus_ = internalStatus_+maximumNumberTotal_; //startPermanentArrays(); } // resizes arrays void AbcSimplex::gutsOfResize(int numberRows, int numberColumns) { if (!abcSolution_) { numberRows_ = 0; numberColumns_ = 0; numberTotal_ = 0; maximumAbcNumberRows_ = 0; maximumAbcNumberColumns_ = 0; maximumNumberTotal_ = 0; } if (numberRows == numberRows_ && numberColumns == numberColumns_) return; // can do on state bit int newSize1 = CoinMax(numberRows, maximumAbcNumberRows_); if ((stateOfProblem_ & ADD_A_BIT) != 0 && numberRows > maximumAbcNumberRows_) newSize1 = CoinMax(numberRows, maximumAbcNumberRows_ + CoinMin(100, numberRows_ / 10)); int newSize2 = CoinMax(numberColumns, maximumAbcNumberColumns_); numberRows_ = numberRows; numberColumns_ = numberColumns; numberTotal_ = numberRows_ + numberColumns_; //fromExternal_ = resizeArray(fromExternal_,maximumAbcNumberRows_,maximumAbcNumberColumns_,newSize1,newSize2,1); //toExternal_ = resizeArray(toExternal_,maximumAbcNumberRows_,maximumAbcNumberColumns_,newSize1,newSize2,1,0); scaleFromExternal_ = resizeArray(scaleFromExternal_, maximumAbcNumberRows_, maximumAbcNumberColumns_, newSize1, newSize2, 0); //scaleToExternal_ = resizeArray(scaleToExternal_,maximumAbcNumberRows_,maximumAbcNumberColumns_,newSize1,newSize2,1,0); internalStatus_ = resizeArray(internalStatus_, maximumAbcNumberRows_, maximumAbcNumberColumns_, newSize1, newSize2, numberTotal_); abcLower_ = resizeArray(abcLower_, maximumAbcNumberRows_, maximumAbcNumberColumns_, newSize1, newSize2, 0); abcUpper_ = resizeArray(abcUpper_, maximumAbcNumberRows_, maximumAbcNumberColumns_, newSize1, newSize2, 0); abcCost_ = resizeArray(abcCost_, maximumAbcNumberRows_, maximumAbcNumberColumns_, newSize1, newSize2, numberTotal_); abcDj_ = resizeArray(abcDj_, maximumAbcNumberRows_, maximumAbcNumberColumns_, newSize1, newSize2, 0); abcSolution_ = resizeArray(abcSolution_, maximumAbcNumberRows_, maximumAbcNumberColumns_, newSize1, newSize2, numberTotal_); abcPerturbation_ = resizeArray(abcPerturbation_, maximumAbcNumberRows_, maximumAbcNumberColumns_, newSize1, newSize2, 0); offset_ = resizeArray(offset_, maximumAbcNumberRows_, maximumAbcNumberColumns_, newSize1, newSize2, 0); setupPointers(newSize1, newSize2); // Fill gaps in perturbation array fillPerturbation(maximumAbcNumberRows_, newSize1 - maximumAbcNumberRows_); fillPerturbation(newSize1 + maximumAbcNumberColumns_, newSize2 - maximumAbcNumberColumns_); // Clean gap //CoinIotaN(fromExternal_+maximumAbcNumberRows_,newSize1-maximumAbcNumberRows_,maximumAbcNumberRows_); //CoinIotaN(toExternal_+maximumAbcNumberRows_,newSize1-maximumAbcNumberRows_,maximumAbcNumberRows_); CoinFillN(scaleFromExternal_ + maximumAbcNumberRows_, newSize1 - maximumAbcNumberRows_, 1.0); CoinFillN(scaleToExternal_ + maximumAbcNumberRows_, newSize1 - maximumAbcNumberRows_, 1.0); CoinFillN(internalStatusSaved_ + maximumAbcNumberRows_, newSize1 - maximumAbcNumberRows_, static_cast< unsigned char >(1)); CoinFillN(lowerSaved_ + maximumAbcNumberRows_, newSize1 - maximumAbcNumberRows_, -COIN_DBL_MAX); CoinFillN(upperSaved_ + maximumAbcNumberRows_, newSize1 - maximumAbcNumberRows_, COIN_DBL_MAX); CoinFillN(costSaved_ + maximumAbcNumberRows_, newSize1 - maximumAbcNumberRows_, 0.0); CoinFillN(djSaved_ + maximumAbcNumberRows_, newSize1 - maximumAbcNumberRows_, 0.0); CoinFillN(solutionSaved_ + maximumAbcNumberRows_, newSize1 - maximumAbcNumberRows_, 0.0); CoinFillN(offset_ + maximumAbcNumberRows_, newSize1 - maximumAbcNumberRows_, 0.0); maximumAbcNumberRows_ = newSize1; maximumAbcNumberColumns_ = newSize2; maximumNumberTotal_ = newSize1 + newSize2; delete[] abcPivotVariable_; abcPivotVariable_ = new int[maximumAbcNumberRows_]; for (int i = 0; i < ABC_NUMBER_USEFUL; i++) usefulArray_[i].reserve(CoinMax(numberTotal_, maximumAbcNumberRows_ + 200)); } void AbcSimplex::translate(int type) { // clear bottom bits stateOfProblem_ &= ~(VALUES_PASS - 1); if ((type & DO_SCALE_AND_MATRIX) != 0) { //stateOfProblem_ |= DO_SCALE_AND_MATRIX; stateOfProblem_ |= DO_SCALE_AND_MATRIX; delete abcMatrix_; abcMatrix_ = new AbcMatrix(*matrix()); abcMatrix_->setModel(this); abcMatrix_->scale(scalingFlag_ ? 0 : -1); } if ((type & DO_STATUS) != 0 && (type & DO_BASIS_AND_ORDER) == 0) { // from Clp enum to Abc enum (and bound flip) unsigned char lookupToAbcSlack[6] = { 4, 6, 0 /*1*/, 1 /*0*/, 5, 7 }; unsigned char *COIN_RESTRICT statusAbc = internalStatus_; const unsigned char *COIN_RESTRICT statusClp = status_; int i; for (i = numberRows_ - 1; i >= 0; i--) { unsigned char status = statusClp[i] & 7; bool basicClp = status == 1; bool basicAbc = (statusAbc[i] & 7) == 4; if (basicClp == basicAbc) statusAbc[i] = lookupToAbcSlack[status]; else break; } if (!i) { // from Clp enum to Abc enum unsigned char lookupToAbc[6] = { 4, 6, 1, 0, 5, 7 }; statusAbc += maximumAbcNumberRows_; statusClp += maximumAbcNumberRows_; for (i = numberColumns_ - 1; i >= 0; i--) { unsigned char status = statusClp[i] & 7; bool basicClp = status == 1; bool basicAbc = (statusAbc[i] & 7) == 4; if (basicClp == basicAbc) statusAbc[i] = lookupToAbc[status]; else break; } if (i) type |= DO_BASIS_AND_ORDER; } else { type |= DO_BASIS_AND_ORDER; } stateOfProblem_ |= DO_STATUS; } if ((type & DO_BASIS_AND_ORDER) != 0) { permuteIn(); permuteBasis(); stateOfProblem_ |= DO_BASIS_AND_ORDER; type &= ~DO_SOLUTION; } if ((type & DO_SOLUTION) != 0) { permuteBasis(); stateOfProblem_ |= DO_SOLUTION; } if ((type & DO_JUST_BOUNDS) != 0) { stateOfProblem_ |= DO_JUST_BOUNDS; } if (!type) { // just move stuff down CoinAbcMemcpy(abcLower_, abcLower_ + maximumNumberTotal_, numberTotal_); CoinAbcMemcpy(abcUpper_, abcUpper_ + maximumNumberTotal_, numberTotal_); CoinAbcMemcpy(abcCost_, abcCost_ + maximumNumberTotal_, numberTotal_); } } #ifdef ABC_SPRINT // Overwrite to create sub problem (just internal arrays) - save full stuff AbcSimplex * AbcSimplex::createSubProblem(int numberColumns, const int *whichColumn) { int numberFullColumns = numberColumns_; numberColumns_ = numberColumns; AbcSimplex *subProblem = this; AbcSimplex *fullProblem = reinterpret_cast< AbcSimplex * >(new char[sizeof(AbcSimplex)]); memset(fullProblem, 0, sizeof(AbcSimplex)); fullProblem->maximumAbcNumberRows_ = maximumAbcNumberRows_; fullProblem->numberColumns_ = numberFullColumns; fullProblem->numberTotal_ = numberTotal_; fullProblem->maximumNumberTotal_ = maximumNumberTotal_; fullProblem->numberTotalWithoutFixed_ = numberTotalWithoutFixed_; fullProblem->abcPrimalColumnPivot_ = abcPrimalColumnPivot_; fullProblem->internalStatus_ = internalStatus_; fullProblem->abcLower_ = abcLower_; fullProblem->abcUpper_ = abcUpper_; fullProblem->abcCost_ = abcCost_; fullProblem->abcDj_ = abcDj_; fullProblem->abcSolution_ = abcSolution_; fullProblem->scaleFromExternal_ = scaleFromExternal_; fullProblem->offset_ = offset_; fullProblem->abcPerturbation_ = abcPerturbation_; fullProblem->abcPivotVariable_ = abcPivotVariable_; fullProblem->abcMatrix_ = abcMatrix_; fullProblem->abcNonLinearCost_ = abcNonLinearCost_; fullProblem->setupPointers(maximumAbcNumberRows_, numberFullColumns); subProblem->numberTotal_ = maximumAbcNumberRows_ + numberColumns; subProblem->maximumNumberTotal_ = maximumAbcNumberRows_ + numberColumns; subProblem->numberTotalWithoutFixed_ = subProblem->numberTotal_; int sizeArray = 2 * subProblem->maximumNumberTotal_ + maximumAbcNumberRows_; subProblem->internalStatus_ = newArray((unsigned char *)NULL, sizeArray + subProblem->maximumNumberTotal_); subProblem->abcLower_ = newArray((double *)NULL, sizeArray); subProblem->abcUpper_ = newArray((double *)NULL, sizeArray); subProblem->abcCost_ = newArray((double *)NULL, sizeArray + subProblem->maximumNumberTotal_); subProblem->abcDj_ = newArray((double *)NULL, sizeArray); subProblem->abcSolution_ = newArray((double *)NULL, sizeArray + subProblem->maximumNumberTotal_); //fromExternal_ = newArray((int *)NULL,sizeArray); //toExternal_ = newArray((int *)NULL,sizeArray); subProblem->scaleFromExternal_ = newArray((double *)NULL, sizeArray); subProblem->offset_ = newArray((double *)NULL, sizeArray); subProblem->abcPerturbation_ = newArray((double *)NULL, sizeArray); subProblem->abcPivotVariable_ = newArray((int *)NULL, maximumAbcNumberRows_); subProblem->setupPointers(maximumAbcNumberRows_, numberColumns); // could use arrays - but for now be safe int *backward = new int[numberFullColumns + numberRows_]; int *whichRow = backward + numberFullColumns; for (int i = 0; i < numberFullColumns; i++) backward[i] = -1; for (int i = 0; i < numberColumns; i++) backward[whichColumn[i]] = i + numberRows_; for (int i = 0; i < numberRows_; i++) { whichRow[i] = i; int iPivot = fullProblem->abcPivotVariable_[i]; if (iPivot < numberRows_) { subProblem->abcPivotVariable_[i] = iPivot; } else { assert(backward[iPivot - numberRows_] >= 0); subProblem->abcPivotVariable_[i] = backward[iPivot - numberRows_]; } subProblem->internalStatus_[i] = fullProblem->internalStatus_[i]; subProblem->abcLower_[i] = fullProblem->abcLower_[i]; subProblem->abcUpper_[i] = fullProblem->abcUpper_[i]; subProblem->abcCost_[i] = fullProblem->abcCost_[i]; subProblem->abcDj_[i] = fullProblem->abcDj_[i]; subProblem->abcSolution_[i] = fullProblem->abcSolution_[i]; subProblem->abcPerturbation_[i] = fullProblem->abcPerturbation_[i]; subProblem->internalStatusSaved_[i] = fullProblem->internalStatusSaved_[i]; subProblem->perturbationSaved_[i] = fullProblem->perturbationSaved_[i]; subProblem->lowerSaved_[i] = fullProblem->lowerSaved_[i]; subProblem->upperSaved_[i] = fullProblem->upperSaved_[i]; subProblem->costSaved_[i] = fullProblem->costSaved_[i]; subProblem->djSaved_[i] = fullProblem->djSaved_[i]; subProblem->solutionSaved_[i] = fullProblem->solutionSaved_[i]; subProblem->offset_[i] = fullProblem->offset_[i]; subProblem->lowerBasic_[i] = fullProblem->lowerBasic_[i]; subProblem->upperBasic_[i] = fullProblem->upperBasic_[i]; subProblem->costBasic_[i] = fullProblem->costBasic_[i]; subProblem->solutionBasic_[i] = fullProblem->solutionBasic_[i]; subProblem->djBasic_[i] = fullProblem->djBasic_[i]; } for (int i = 0; i < numberColumns; i++) { int k = whichColumn[i]; subProblem->internalStatus_[maximumAbcNumberRows_ + i] = fullProblem->internalStatus_[maximumAbcNumberRows_ + k]; subProblem->internalStatus_[maximumAbcNumberRows_ + i] = fullProblem->internalStatus_[maximumAbcNumberRows_ + k]; subProblem->abcLower_[maximumAbcNumberRows_ + i] = fullProblem->abcLower_[maximumAbcNumberRows_ + k]; subProblem->abcUpper_[maximumAbcNumberRows_ + i] = fullProblem->abcUpper_[maximumAbcNumberRows_ + k]; subProblem->abcCost_[maximumAbcNumberRows_ + i] = fullProblem->abcCost_[maximumAbcNumberRows_ + k]; subProblem->abcDj_[maximumAbcNumberRows_ + i] = fullProblem->abcDj_[maximumAbcNumberRows_ + k]; subProblem->abcSolution_[maximumAbcNumberRows_ + i] = fullProblem->abcSolution_[maximumAbcNumberRows_ + k]; subProblem->abcPerturbation_[maximumAbcNumberRows_ + i] = fullProblem->abcPerturbation_[maximumAbcNumberRows_ + k]; subProblem->internalStatusSaved_[maximumAbcNumberRows_ + i] = fullProblem->internalStatusSaved_[maximumAbcNumberRows_ + k]; subProblem->perturbationSaved_[maximumAbcNumberRows_ + i] = fullProblem->perturbationSaved_[maximumAbcNumberRows_ + k]; subProblem->lowerSaved_[maximumAbcNumberRows_ + i] = fullProblem->lowerSaved_[maximumAbcNumberRows_ + k]; subProblem->upperSaved_[maximumAbcNumberRows_ + i] = fullProblem->upperSaved_[maximumAbcNumberRows_ + k]; subProblem->costSaved_[maximumAbcNumberRows_ + i] = fullProblem->costSaved_[maximumAbcNumberRows_ + k]; subProblem->djSaved_[maximumAbcNumberRows_ + i] = fullProblem->djSaved_[maximumAbcNumberRows_ + k]; subProblem->solutionSaved_[maximumAbcNumberRows_ + i] = fullProblem->solutionSaved_[maximumAbcNumberRows_ + k]; subProblem->offset_[maximumAbcNumberRows_ + i] = fullProblem->offset_[maximumAbcNumberRows_ + k]; } subProblem->abcNonLinearCost_ = new AbcNonLinearCost(subProblem); subProblem->abcNonLinearCost_->checkInfeasibilities(0.0); subProblem->abcMatrix_ = new AbcMatrix(*fullProblem->abcMatrix_, numberRows_, whichRow, numberColumns, whichColumn); subProblem->abcMatrix_->setModel(subProblem); subProblem->abcMatrix_->rebalance(); subProblem->abcPrimalColumnPivot_ = new AbcPrimalColumnSteepest(); subProblem->abcPrimalColumnPivot_->saveWeights(subProblem, 2); delete[] backward; // swap return fullProblem; } // Restore stuff from sub problem (and delete sub problem) void AbcSimplex::restoreFromSubProblem(AbcSimplex *fullProblem, const int *whichColumn) { AbcSimplex *subProblem = this; for (int i = 0; i < numberRows_; i++) { int iPivot = subProblem->abcPivotVariable_[i]; if (iPivot < numberRows_) { fullProblem->abcPivotVariable_[i] = iPivot; } else { fullProblem->abcPivotVariable_[i] = whichColumn[iPivot - numberRows_] + numberRows_; } fullProblem->internalStatus_[i] = subProblem->internalStatus_[i]; fullProblem->abcLower_[i] = subProblem->abcLower_[i]; fullProblem->abcUpper_[i] = subProblem->abcUpper_[i]; fullProblem->abcCost_[i] = subProblem->abcCost_[i]; fullProblem->abcDj_[i] = subProblem->abcDj_[i]; fullProblem->abcSolution_[i] = subProblem->abcSolution_[i]; fullProblem->abcPerturbation_[i] = subProblem->abcPerturbation_[i]; fullProblem->internalStatusSaved_[i] = subProblem->internalStatusSaved_[i]; fullProblem->perturbationSaved_[i] = subProblem->perturbationSaved_[i]; fullProblem->lowerSaved_[i] = subProblem->lowerSaved_[i]; fullProblem->upperSaved_[i] = subProblem->upperSaved_[i]; fullProblem->costSaved_[i] = subProblem->costSaved_[i]; fullProblem->djSaved_[i] = subProblem->djSaved_[i]; fullProblem->solutionSaved_[i] = subProblem->solutionSaved_[i]; fullProblem->offset_[i] = subProblem->offset_[i]; fullProblem->lowerBasic_[i] = subProblem->lowerBasic_[i]; fullProblem->upperBasic_[i] = subProblem->upperBasic_[i]; fullProblem->costBasic_[i] = subProblem->costBasic_[i]; fullProblem->solutionBasic_[i] = subProblem->solutionBasic_[i]; fullProblem->djBasic_[i] = subProblem->djBasic_[i]; } int numberColumns = subProblem->numberColumns_; for (int i = 0; i < numberColumns; i++) { int k = whichColumn[i]; fullProblem->internalStatus_[maximumAbcNumberRows_ + k] = subProblem->internalStatus_[maximumAbcNumberRows_ + i]; fullProblem->abcLower_[maximumAbcNumberRows_ + k] = subProblem->abcLower_[maximumAbcNumberRows_ + i]; fullProblem->abcUpper_[maximumAbcNumberRows_ + k] = subProblem->abcUpper_[maximumAbcNumberRows_ + i]; fullProblem->abcCost_[maximumAbcNumberRows_ + k] = subProblem->abcCost_[maximumAbcNumberRows_ + i]; fullProblem->abcDj_[maximumAbcNumberRows_ + k] = subProblem->abcDj_[maximumAbcNumberRows_ + i]; fullProblem->abcSolution_[maximumAbcNumberRows_ + k] = subProblem->abcSolution_[maximumAbcNumberRows_ + i]; fullProblem->abcPerturbation_[maximumAbcNumberRows_ + k] = subProblem->abcPerturbation_[maximumAbcNumberRows_ + i]; fullProblem->internalStatusSaved_[maximumAbcNumberRows_ + k] = subProblem->internalStatusSaved_[maximumAbcNumberRows_ + i]; fullProblem->perturbationSaved_[maximumAbcNumberRows_ + k] = subProblem->perturbationSaved_[maximumAbcNumberRows_ + i]; fullProblem->lowerSaved_[maximumAbcNumberRows_ + k] = subProblem->lowerSaved_[maximumAbcNumberRows_ + i]; fullProblem->upperSaved_[maximumAbcNumberRows_ + k] = subProblem->upperSaved_[maximumAbcNumberRows_ + i]; fullProblem->costSaved_[maximumAbcNumberRows_ + k] = subProblem->costSaved_[maximumAbcNumberRows_ + i]; fullProblem->djSaved_[maximumAbcNumberRows_ + k] = subProblem->djSaved_[maximumAbcNumberRows_ + i]; fullProblem->solutionSaved_[maximumAbcNumberRows_ + k] = subProblem->solutionSaved_[maximumAbcNumberRows_ + i]; fullProblem->offset_[maximumAbcNumberRows_ + k] = subProblem->offset_[maximumAbcNumberRows_ + i]; } delete[] subProblem->internalStatus_; delete[] subProblem->abcPerturbation_; delete subProblem->abcMatrix_; delete[] subProblem->abcLower_; delete[] subProblem->abcUpper_; delete[] subProblem->abcCost_; delete[] subProblem->abcSolution_; delete[] subProblem->abcDj_; delete subProblem->abcPrimalColumnPivot_; delete[] subProblem->scaleFromExternal_; delete[] subProblem->offset_; delete[] subProblem->abcPivotVariable_; delete[] subProblem->reversePivotVariable_; delete subProblem->abcNonLinearCost_; numberColumns_ = fullProblem->numberColumns_; numberTotal_ = fullProblem->numberTotal_; maximumNumberTotal_ = fullProblem->maximumNumberTotal_; numberTotalWithoutFixed_ = fullProblem->numberTotalWithoutFixed_; abcPrimalColumnPivot_ = fullProblem->abcPrimalColumnPivot_; internalStatus_ = fullProblem->internalStatus_; abcLower_ = fullProblem->abcLower_; abcUpper_ = fullProblem->abcUpper_; abcCost_ = fullProblem->abcCost_; abcDj_ = fullProblem->abcDj_; abcSolution_ = fullProblem->abcSolution_; scaleFromExternal_ = fullProblem->scaleFromExternal_; offset_ = fullProblem->offset_; abcPerturbation_ = fullProblem->abcPerturbation_; abcPivotVariable_ = fullProblem->abcPivotVariable_; abcMatrix_ = fullProblem->abcMatrix_; setupPointers(maximumAbcNumberRows_, numberColumns); // ? redo nonlinearcost abcNonLinearCost_ = fullProblem->abcNonLinearCost_; abcNonLinearCost_->refresh(); delete[] reinterpret_cast< char * >(fullProblem); } #endif /* Sets dual values pass djs using unscaled duals type 1 - values pass type 2 - just use as infeasibility weights type 3 - as 2 but crash */ void AbcSimplex::setupDualValuesPass(const double *fakeDuals, const double *fakePrimals, int type) { // allslack basis memset(internalStatus_, 6, numberRows_); // temp if (type == 1) { bool allEqual = true; for (int i = 0; i < numberRows_; i++) { if (rowUpper_[i] > rowLower_[i]) { allEqual = false; break; } } if (allEqual) { // just modify costs transposeTimes(-1.0, fakeDuals, objective()); return; } } // compute unscaled djs CoinAbcMemcpy(djSaved_ + maximumAbcNumberRows_, objective(), numberColumns_); matrix_->transposeTimes(-1.0, fakeDuals, djSaved_ + maximumAbcNumberRows_); // save fake solution assert(solution_); //solution_ = new double[numberTotal_]; CoinAbcMemset0(solution_, numberRows_); CoinAbcMemcpy(solution_ + maximumAbcNumberRows_, fakePrimals, numberColumns_); // adjust for (int iSequence = maximumAbcNumberRows_; iSequence < numberTotal_; iSequence++) solution_[iSequence] -= offset_[iSequence]; matrix_->times(-1.0, solution_ + maximumAbcNumberRows_, solution_); double direction = optimizationDirection_; const double *COIN_RESTRICT rowScale = scaleFromExternal_; const double *COIN_RESTRICT inverseRowScale = scaleToExternal_; for (int iRow = 0; iRow < numberRows_; iRow++) { djSaved_[iRow] = direction * fakeDuals[iRow] * inverseRowScale[iRow]; solution_[iRow] *= rowScale[iRow]; } const double *COIN_RESTRICT columnScale = scaleToExternal_; for (int iColumn = maximumAbcNumberRows_; iColumn < numberTotal_; iColumn++) djSaved_[iColumn] *= direction * columnScale[iColumn]; // Set solution values const double *lower = abcLower_ + maximumAbcNumberRows_; const double *upper = abcUpper_ + maximumAbcNumberRows_; double *solution = abcSolution_ + maximumAbcNumberRows_; const double *djs = djSaved_ + maximumAbcNumberRows_; const double *inverseColumnScale = scaleFromExternal_ + maximumAbcNumberRows_; for (int iColumn = 0; iColumn < numberColumns_; iColumn++) { double thisValue = fakePrimals[iColumn]; double thisLower = columnLower_[iColumn]; double thisUpper = columnUpper_[iColumn]; double thisDj = djs[iColumn]; solution_[iColumn + maximumAbcNumberRows_] = solution_[iColumn + maximumAbcNumberRows_] * inverseColumnScale[iColumn]; if (thisLower > -1.0e30) { if (thisUpper < 1.0e30) { double gapUp = thisUpper - thisValue; double gapDown = thisValue - thisLower; bool goUp; if (gapUp > gapDown && thisDj > -dualTolerance_) { goUp = false; } else if (gapUp < gapDown && thisDj < dualTolerance_) { goUp = true; } else { // wild guess double badUp; double badDown; if (gapUp > gapDown) { badUp = gapUp * dualTolerance_; badDown = -gapDown * thisDj; } else { badUp = gapUp * thisDj; badDown = gapDown * dualTolerance_; } goUp = badDown > badUp; } if (goUp) { solution[iColumn] = upper[iColumn]; setInternalStatus(iColumn + maximumAbcNumberRows_, atUpperBound); setStatus(iColumn, ClpSimplex::atUpperBound); } else { solution[iColumn] = lower[iColumn]; setInternalStatus(iColumn + maximumAbcNumberRows_, atLowerBound); setStatus(iColumn, ClpSimplex::atLowerBound); } } else { solution[iColumn] = lower[iColumn]; setInternalStatus(iColumn + maximumAbcNumberRows_, atLowerBound); setStatus(iColumn, ClpSimplex::atLowerBound); } } else if (thisUpper < 1.0e30) { solution[iColumn] = upper[iColumn]; setInternalStatus(iColumn + maximumAbcNumberRows_, atUpperBound); setStatus(iColumn, ClpSimplex::atUpperBound); } else { // free solution[iColumn] = thisValue * inverseColumnScale[iColumn]; setInternalStatus(iColumn + maximumAbcNumberRows_, isFree); setStatus(iColumn, ClpSimplex::isFree); } } switch (type) { case 1: stateOfProblem_ |= VALUES_PASS; break; case 2: stateOfProblem_ |= VALUES_PASS2; delete[] solution_; solution_ = NULL; break; case 3: stateOfProblem_ |= VALUES_PASS2; break; } } //############################################################################# int AbcSimplex::computePrimals(CoinIndexedVector *arrayVector, CoinIndexedVector *previousVector) { arrayVector->clear(); previousVector->clear(); // accumulate non basic stuff double *COIN_RESTRICT array = arrayVector->denseVector(); CoinAbcScatterZeroTo(abcSolution_, abcPivotVariable_, numberRows_); abcMatrix_->timesIncludingSlacks(-1.0, abcSolution_, array); #if 0 static int xxxxxx=0; if (xxxxxx==0) for (int i=0;iscan(0,numberRows_,zeroTolerance_); // Ftran adjusted RHS and iterate to improve accuracy double lastError = COIN_DBL_MAX; CoinIndexedVector *thisVector = arrayVector; CoinIndexedVector *lastVector = previousVector; //if (arrayVector->getNumElements()) #if 0 double largest=0.0; int iLargest=-1; for (int i=0;ilargest) { largest=array[i]; iLargest=i; } } printf("largest %g at row %d\n",array[iLargest],iLargest); #endif abcFactorization_->updateFullColumn(*thisVector); #if 0 largest=0.0; iLargest=-1; for (int i=0;ilargest) { largest=array[i]; iLargest=i; } } printf("after largest %g at row %d\n",array[iLargest],iLargest); #endif #if 0 if (xxxxxx==0) for (int i=0;i300) exit(0); #endif int numberRefinements = 0; for (int iRefine = 0; iRefine < numberRefinements_ + 1; iRefine++) { int numberIn = thisVector->getNumElements(); const int *COIN_RESTRICT indexIn = thisVector->getIndices(); const double *COIN_RESTRICT arrayIn = thisVector->denseVector(); CoinAbcScatterToList(arrayIn, abcSolution_, indexIn, abcPivotVariable_, numberIn); // check Ax == b (for all) abcMatrix_->timesIncludingSlacks(-1.0, abcSolution_, solutionBasic_); #if 0 if (xxxxxx==0) for (int i=0;i maxValue) { #if 0 if (xxxxxx==0) printf("larger %.19gg at row %d\n",value,i); maxValue=value; #endif } } if (largestPrimalError_ >= lastError) { // restore CoinIndexedVector *temp = thisVector; thisVector = lastVector; lastVector = temp; //goodSolution = false; break; } if (iRefine < numberRefinements_ && largestPrimalError_ > 1.0e-10) { // try and make better numberRefinements++; // save this CoinIndexedVector *temp = thisVector; thisVector = lastVector; lastVector = temp; int *COIN_RESTRICT indexOut = thisVector->getIndices(); int number = 0; array = thisVector->denseVector(); thisVector->clear(); for (int iRow = 0; iRow < numberRows_; iRow++) { double value = solutionBasic_[iRow]; if (value) { array[iRow] = value; indexOut[number++] = iRow; solutionBasic_[iRow] = 0.0; } } thisVector->setNumElements(number); lastError = largestPrimalError_; abcFactorization_->updateFullColumn(*thisVector); double *previous = lastVector->denseVector(); number = 0; multiplier = 1.0 / multiplier; for (int iRow = 0; iRow < numberRows_; iRow++) { double value = previous[iRow] + multiplier * array[iRow]; if (value) { array[iRow] = value; indexOut[number++] = iRow; } else { array[iRow] = 0.0; } } thisVector->setNumElements(number); } else { break; } } // solution as accurate as we are going to get //if (!goodSolution) { CoinAbcMemcpy(solutionBasic_, thisVector->denseVector(), numberRows_); CoinAbcScatterTo(solutionBasic_, abcSolution_, abcPivotVariable_, numberRows_); arrayVector->clear(); previousVector->clear(); return numberRefinements; } // Moves basic stuff to basic area void AbcSimplex::moveToBasic(int which) { if ((which & 1) != 0) CoinAbcGatherFrom(abcSolution_, solutionBasic_, abcPivotVariable_, numberRows_); if ((which & 2) != 0) CoinAbcGatherFrom(abcCost_, costBasic_, abcPivotVariable_, numberRows_); if ((which & 4) != 0) CoinAbcGatherFrom(abcLower_, lowerBasic_, abcPivotVariable_, numberRows_); if ((which & 8) != 0) CoinAbcGatherFrom(abcUpper_, upperBasic_, abcPivotVariable_, numberRows_); } // now dual side int AbcSimplex::computeDuals(double *givenDjs, CoinIndexedVector *arrayVector, CoinIndexedVector *previousVector) { double *COIN_RESTRICT array = arrayVector->denseVector(); int *COIN_RESTRICT index = arrayVector->getIndices(); int number = 0; if (!givenDjs) { for (int iRow = 0; iRow < numberRows_; iRow++) { double value = costBasic_[iRow]; if (value) { array[iRow] = value; index[number++] = iRow; } } } else { // dual values pass - djs may not be zero for (int iRow = 0; iRow < numberRows_; iRow++) { int iPivot = abcPivotVariable_[iRow]; // make sure zero if done if (!pivoted(iPivot)) givenDjs[iPivot] = 0.0; double value = abcCost_[iPivot] - givenDjs[iPivot]; if (value) { array[iRow] = value; index[number++] = iRow; } } } arrayVector->setNumElements(number); // Btran basic costs and get as accurate as possible double lastError = COIN_DBL_MAX; CoinIndexedVector *thisVector = arrayVector; CoinIndexedVector *lastVector = previousVector; abcFactorization_->updateFullColumnTranspose(*thisVector); int numberRefinements = 0; for (int iRefine = 0; iRefine < numberRefinements_ + 1; iRefine++) { // check basic reduced costs zero // put reduced cost of basic into djBasic_ CoinAbcMemcpy(djBasic_, costBasic_, numberRows_); abcMatrix_->transposeTimesBasic(-1.0, thisVector->denseVector(), djBasic_); largestDualError_ = CoinAbcMaximumAbsElement(djBasic_, numberRows_); if (largestDualError_ >= lastError) { // restore CoinIndexedVector *temp = thisVector; thisVector = lastVector; lastVector = temp; break; } if (iRefine < numberRefinements_ && largestDualError_ > 1.0e-10 && !givenDjs) { numberRefinements++; // try and make better // save this CoinIndexedVector *temp = thisVector; thisVector = lastVector; lastVector = temp; array = thisVector->denseVector(); double multiplier = 131072.0; //array=djBasic_*multiplier CoinAbcMultiplyAdd(djBasic_, numberRows_, multiplier, array, 0.0); lastError = largestDualError_; abcFactorization_->updateFullColumnTranspose(*thisVector); #if ABC_DEBUG thisVector->checkClean(); #endif multiplier = 1.0 / multiplier; double *COIN_RESTRICT previous = lastVector->denseVector(); // array = array*multiplier+previous CoinAbcMultiplyAdd(previous, numberRows_, 1.0, array, multiplier); } else { break; } } // now look at dual solution CoinAbcMemcpy(dual_, thisVector->denseVector(), numberRows_); CoinAbcMemset0(thisVector->denseVector(), numberRows_); thisVector->setNumElements(0); if (numberRefinements) { CoinAbcMemset0(lastVector->denseVector(), numberRows_); lastVector->setNumElements(0); } CoinAbcMemcpy(abcDj_, abcCost_, numberTotal_); abcMatrix_->transposeTimesNonBasic(-1.0, dual_, abcDj_); // If necessary - override results if (givenDjs) { // restore accurate duals CoinMemcpyN(abcDj_, numberTotal_, givenDjs); } //arrayVector->clear(); //previousVector->clear(); #if ABC_DEBUG arrayVector->checkClean(); previousVector->checkClean(); #endif return numberRefinements; } /* Factorizes using current basis. solveType - 1 iterating, 0 initial, -1 external - 2 then iterating but can throw out of basis If 10 added then in primal values pass Return codes are as from AbcSimplexFactorization unless initial factorization when total number of singularities is returned. Special case is numberRows_+1 -> all slack basis. */ int AbcSimplex::internalFactorize(int solveType) { assert(status_); bool valuesPass = false; if (solveType >= 10) { valuesPass = true; solveType -= 10; } #if 0 // Make sure everything is clean for (int iSequence = 0; iSequence < numberTotal_; iSequence++) { if(getInternalStatus(iSequence) == isFixed) { // double check fixed assert (abcUpper_[iSequence] == abcLower_[iSequence]); assert (fabs(abcSolution_[iSequence]-abcLower_[iSequence])<100.0*primalTolerance_); } else if (getInternalStatus(iSequence) == isFree) { assert (abcUpper_[iSequence] == COIN_DBL_MAX && abcLower_[iSequence]==-COIN_DBL_MAX); } else if (getInternalStatus(iSequence) == atLowerBound) { assert (fabs(abcSolution_[iSequence]-abcLower_[iSequence])<1000.0*primalTolerance_); } else if (getInternalStatus(iSequence) == atUpperBound) { assert (fabs(abcSolution_[iSequence]-abcUpper_[iSequence])<1000.0*primalTolerance_); } else if (getInternalStatus(iSequence) == superBasic) { assert (!valuesPass); } } #endif #if 0 //ndef NDEBUG // Make sure everything is clean double sumOutside=0.0; int numberOutside=0; //double sumOutsideLarge=0.0; int numberOutsideLarge=0; double sumInside=0.0; int numberInside=0; //double sumInsideLarge=0.0; int numberInsideLarge=0; char rowcol[] = {'R', 'C'}; for (int iSequence = 0; iSequence < numberTotal_; iSequence++) { if(getInternalStatus(iSequence) == isFixed) { // double check fixed assert (abcUpper_[iSequence] == abcLower_[iSequence]); assert (fabs(abcSolution_[iSequence]-abcLower_[iSequence]) 1 if (handler_->logLevel()==63) printf("%c%d below by %g\n",rowcol[isColumn(iSequence)],sequenceWithin(iSequence), abcLower_[iSequence]-abcSolution_[iSequence]); #endif sumOutside-=abcSolution_[iSequence]-abcLower_[iSequence]; if (abcSolution_[iSequence]abcLower_[iSequence]) { numberInside++; sumInside+=abcSolution_[iSequence]-abcLower_[iSequence]; if (abcSolution_[iSequence]>abcLower_[iSequence]+primalTolerance_) numberInsideLarge++; } } else if (getInternalStatus(iSequence) == atUpperBound) { assert (fabs(abcSolution_[iSequence]-abcUpper_[iSequence])<1000.0*primalTolerance_); if (abcSolution_[iSequence]>abcUpper_[iSequence]) { numberOutside++; #if ABC_NORMAL_DEBUG > 0 if (handler_->logLevel()==63) printf("%c%d above by %g\n",rowcol[isColumn(iSequence)],sequenceWithin(iSequence), -(abcUpper_[iSequence]-abcSolution_[iSequence])); #endif sumOutside+=abcSolution_[iSequence]-abcUpper_[iSequence]; if (abcSolution_[iSequence]>abcUpper_[iSequence]+primalTolerance_) numberOutsideLarge++; } else if (abcSolution_[iSequence] 0 if (numberInside+numberOutside) printf("%d outside summing to %g (%d large), %d inside summing to %g (%d large)\n", numberOutside,sumOutside,numberOutsideLarge, numberInside,sumInside,numberInsideLarge); #endif #endif // *** replace below by cleanStatus for (int iSequence = 0; iSequence < numberTotal_; iSequence++) { AbcSimplex::Status status = getInternalStatus(iSequence); if (status != basic && status != isFixed && abcUpper_[iSequence] == abcLower_[iSequence]) setInternalStatus(iSequence, isFixed); } if (numberIterations_ == baseIteration_ && !valuesPass) { double largeValue = this->largeValue(); double *COIN_RESTRICT solution = abcSolution_; for (int iSequence = 0; iSequence < numberTotal_; iSequence++) { AbcSimplex::Status status = getInternalStatus(iSequence); if (status == superBasic) { double lower = abcLower_[iSequence]; double upper = abcUpper_[iSequence]; double value = solution[iSequence]; AbcSimplex::Status thisStatus = isFree; if (lower > -largeValue || upper < largeValue) { if (lower != upper) { if (fabs(value - lower) < fabs(value - upper)) { thisStatus = AbcSimplex::atLowerBound; solution[iSequence] = lower; } else { thisStatus = AbcSimplex::atUpperBound; solution[iSequence] = upper; } } else { thisStatus = AbcSimplex::isFixed; solution[iSequence] = upper; } setInternalStatus(iSequence, thisStatus); } } } } int status = abcFactorization_->factorize(this, solveType, valuesPass); if (status) { handler_->message(CLP_SIMPLEX_BADFACTOR, messages_) << status << CoinMessageEol; return -1; } else if (!solveType) { // Initial basis - return number of singularities int numberSlacks = 0; for (int iRow = 0; iRow < numberRows_; iRow++) { if (getInternalStatus(iRow) == basic) numberSlacks++; } status = CoinMax(numberSlacks - numberRows_, 0); if (status) printf("%d singularities\n", status); // special case if all slack if (numberSlacks == numberRows_) { status = numberRows_ + 1; } } #ifdef ABC_USE_COIN_FACTORIZATION // sparse methods abcFactorization_->goSparse(); #endif return status; } // Make sure no superbasic etc void AbcSimplex::cleanStatus(bool valuesPass) { for (int iSequence = 0; iSequence < numberTotal_; iSequence++) { AbcSimplex::Status status = getInternalStatus(iSequence); if (status != basic && status != isFixed && abcUpper_[iSequence] == abcLower_[iSequence]) setInternalStatus(iSequence, isFixed); } if (numberIterations_ == baseIteration_ && !valuesPass) { double largeValue = this->largeValue(); double *COIN_RESTRICT solution = abcSolution_; for (int iSequence = 0; iSequence < numberTotal_; iSequence++) { AbcSimplex::Status status = getInternalStatus(iSequence); if (status == superBasic) { double lower = abcLower_[iSequence]; double upper = abcUpper_[iSequence]; double value = solution[iSequence]; AbcSimplex::Status thisStatus = isFree; if (lower > -largeValue || upper < largeValue) { if (lower != upper) { if (fabs(value - lower) < fabs(value - upper)) { thisStatus = AbcSimplex::atLowerBound; solution[iSequence] = lower; } else { thisStatus = AbcSimplex::atUpperBound; solution[iSequence] = upper; } } else { thisStatus = AbcSimplex::isFixed; solution[iSequence] = upper; } setInternalStatus(iSequence, thisStatus); } } } } } // Sets objectiveValue_ from rawObjectiveValue_ void AbcSimplex::setClpSimplexObjectiveValue() { objectiveValue_ = rawObjectiveValue_ / (objectiveScale_ * rhsScale_); objectiveValue_ += objectiveOffset_; } /* This does basis housekeeping and does values for in/out variables. Can also decide to re-factorize */ int AbcSimplex::housekeeping() { #define DELAYED_UPDATE #ifdef DELAYED_UPDATE if (algorithm_ < 0) { // modify dualout dualOut_ /= alpha_; dualOut_ *= -directionOut_; //double oldValue = valueIn_; if (directionIn_ == -1) { // as if from upper bound valueIn_ = upperIn_ + dualOut_; #if 0 //def ABC_DEBUG printf("In from upper dualout_ %g movement %g (old %g) valueIn_ %g using movement %g\n", dualOut_,movement_,movementOld,valueIn_,upperIn_+movement_); #endif } else { // as if from lower bound valueIn_ = lowerIn_ + dualOut_; #if 0 //def ABC_DEBUG printf("In from lower dualout_ %g movement %g (old %g) valueIn_ %g using movement %g\n", dualOut_,movement_,movementOld,valueIn_,lowerIn_+movement_); #endif } // outgoing if (directionOut_ > 0) { valueOut_ = lowerOut_; } else { valueOut_ = upperOut_; } #if ABC_NORMAL_DEBUG > 3 if (rawObjectiveValue_ < oldobj - 1.0e-5 && (handler_->logLevel() & 16)) printf("obj backwards %g %g\n", rawObjectiveValue_, oldobj); #endif } #endif #if 0 //ndef NDEBUG { int numberFlagged=0; for (int iRow = 0; iRow < numberRows_; iRow++) { int iPivot = abcPivotVariable_[iRow]; if (flagged(iPivot)) numberFlagged++; } assert (numberFlagged==numberFlagged_); } #endif // save value of incoming and outgoing numberIterations_++; changeMade_++; // something has happened // incoming variable if (handler_->logLevel() > 7) { //if (handler_->detail(CLP_SIMPLEX_HOUSE1,messages_)<100) { handler_->message(CLP_SIMPLEX_HOUSE1, messages_) << directionOut_ << directionIn_ << theta_ << dualOut_ << dualIn_ << alpha_ << CoinMessageEol; if (getInternalStatus(sequenceIn_) == isFree) { handler_->message(CLP_SIMPLEX_FREEIN, messages_) << sequenceIn_ << CoinMessageEol; } } // change of incoming char rowcol[] = { 'R', 'C' }; if (abcUpper_[sequenceIn_] > 1.0e20 && abcLower_[sequenceIn_] < -1.0e20) progressFlag_ |= 2; // making real progress #ifndef DELAYED_UPDATE abcSolution_[sequenceIn_] = valueIn_; #endif if (abcUpper_[sequenceOut_] - abcLower_[sequenceOut_] < 1.0e-12) progressFlag_ |= 1; // making real progress if (sequenceIn_ != sequenceOut_) { if (alphaAccuracy_ > 0.0) { double value = fabs(alpha_); if (value > 1.0) alphaAccuracy_ *= value; else alphaAccuracy_ /= value; } setInternalStatus(sequenceIn_, basic); if (abcUpper_[sequenceOut_] - abcLower_[sequenceOut_] > 0) { // As Nonlinear costs may have moved bounds (to more feasible) // Redo using value if (fabs(valueOut_ - abcLower_[sequenceOut_]) < fabs(valueOut_ - abcUpper_[sequenceOut_])) { // going to lower setInternalStatus(sequenceOut_, atLowerBound); } else { // going to upper setInternalStatus(sequenceOut_, atUpperBound); } } else { // fixed setInternalStatus(sequenceOut_, isFixed); } #ifndef DELAYED_UPDATE abcSolution_[sequenceOut_] = valueOut_; #endif #if PARTITION_ROW_COPY == 1 // move in row copy abcMatrix_->inOutUseful(sequenceIn_, sequenceOut_); #endif } else { //if (objective_->type()<2) //assert (fabs(theta_)>1.0e-13); // flip from bound to bound // As Nonlinear costs may have moved bounds (to more feasible) // Redo using value if (fabs(valueIn_ - abcLower_[sequenceIn_]) < fabs(valueIn_ - abcUpper_[sequenceIn_])) { // as if from upper bound setInternalStatus(sequenceIn_, atLowerBound); } else { // as if from lower bound setInternalStatus(sequenceIn_, atUpperBound); } } setClpSimplexObjectiveValue(); if (handler_->logLevel() > 7) { //if (handler_->detail(CLP_SIMPLEX_HOUSE2,messages_)<100) { handler_->message(CLP_SIMPLEX_HOUSE2, messages_) << numberIterations_ << objectiveValue() << rowcol[isColumn(sequenceIn_)] << sequenceWithin(sequenceIn_) << rowcol[isColumn(sequenceOut_)] << sequenceWithin(sequenceOut_); handler_->printing(algorithm_ < 0) << dualOut_ << theta_; handler_->printing(algorithm_ > 0) << dualIn_ << theta_; handler_->message() << CoinMessageEol; } #if 0 if (numberIterations_ > 10000) printf(" it %d %g %c%d %c%d\n" , numberIterations_, objectiveValue() , rowcol[isColumn(sequenceIn_)], sequenceWithin(sequenceIn_) , rowcol[isColumn(sequenceOut_)], sequenceWithin(sequenceOut_)); #endif if (hitMaximumIterations()) return 2; // check for small cycles int in = sequenceIn_; int out = sequenceOut_; int cycle = abcProgress_.cycle(in, out, directionIn_, directionOut_); if (cycle > 0) { #if ABC_NORMAL_DEBUG > 0 if (handler_->logLevel() >= 63) printf("Cycle of %d\n", cycle); #endif // reset abcProgress_.startCheck(); double random = randomNumberGenerator_.randomDouble(); int extra = static_cast< int >(9.999 * random); int off[] = { 1, 1, 1, 1, 2, 2, 2, 3, 3, 4 }; if (abcFactorization_->pivots() > cycle) { forceFactorization_ = CoinMax(1, cycle - off[extra]); } else { // need to reject something int iSequence; if (algorithm_ < 0) { iSequence = sequenceIn_; } else { /* should be better if don't reject incoming as it is in basis */ iSequence = sequenceOut_; // so can't happen immediately again sequenceOut_ = -1; } char x = isColumn(iSequence) ? 'C' : 'R'; if (handler_->logLevel() >= 63) handler_->message(CLP_SIMPLEX_FLAG, messages_) << x << sequenceWithin(iSequence) << CoinMessageEol; setFlagged(iSequence); //printf("flagging %d\n",iSequence); } return 1; } int invertNow = 0; // only time to re-factorize if one before real time // this is so user won't be surprised that maximumPivots has exact meaning int numberPivots = abcFactorization_->pivots(); if (algorithm_ < 0) numberPivots++; // allow for update not done int maximumPivots = abcFactorization_->maximumPivots(); int numberDense = 0; //abcFactorization_->numberDense(); bool dontInvert = ((specialOptions_ & 16384) != 0 && numberIterations_ * 3 > 2 * maximumIterations()); if (numberPivots == maximumPivots || maximumPivots < 2) { // If dense then increase if (maximumPivots > 100 && numberDense > 1.5 * maximumPivots && false) { abcFactorization_->maximumPivots(numberDense); } //printf("ZZ maxpivots %d its %d\n",numberPivots,maximumPivots); #if CLP_FACTORIZATION_NEW_TIMING > 1 abcFactorization_->statsRefactor('M'); #endif return 1; } else if ((abcFactorization_->timeToRefactorize() && !dontInvert) || invertNow) { //printf("ZZ time invertNow %s its %d\n",invertNow ? "yes":"no",numberPivots); #if CLP_FACTORIZATION_NEW_TIMING > 1 abcFactorization_->statsRefactor('T'); #endif return 1; } else if (forceFactorization_ > 0 && #ifndef DELAYED_UPDATE abcFactorization_->pivots() #else abcFactorization_->pivots() + 1 #endif >= forceFactorization_) { // relax forceFactorization_ = (3 + 5 * forceFactorization_) / 4; if (forceFactorization_ > abcFactorization_->maximumPivots()) forceFactorization_ = -1; //off //printf("ZZ forceFactor %d its %d\n",forceFactorization_,numberPivots); #if CLP_FACTORIZATION_NEW_TIMING > 1 abcFactorization_->statsRefactor('F'); #endif return 1; } else if (numberIterations_ > 1000 + 10 * (numberRows_ + (numberColumns_ >> 2))) { // A bit worried problem may be cycling - lets factorize at random intervals for a short period int numberTooManyIterations = numberIterations_ - 10 * (numberRows_ + (numberColumns_ >> 2)); double random = randomNumberGenerator_.randomDouble(); int window = numberTooManyIterations % 5000; if (window < 2 * maximumPivots) random = 0.2 * random + 0.8; // randomly re-factorize but not too soon else random = 1.0; // switch off if not in window of opportunity int maxNumber = (forceFactorization_ < 0) ? maximumPivots : CoinMin(forceFactorization_, maximumPivots); if (abcFactorization_->pivots() >= random * maxNumber) { //printf("ZZ cycling a %d\n",numberPivots); return 1; } else if (numberIterations_ > 1000000 + 10 * (numberRows_ + (numberColumns_ >> 2)) && numberIterations_ < 1000010 + 10 * (numberRows_ + (numberColumns_ >> 2))) { //printf("ZZ cycling b %d\n",numberPivots); return 1; } else { // carry on iterating return 0; } } else { // carry on iterating return 0; } } // Swaps primal stuff void AbcSimplex::swapPrimalStuff() { if (sequenceOut_ < 0) return; assert(sequenceIn_ >= 0); abcSolution_[sequenceOut_] = valueOut_; abcSolution_[sequenceIn_] = valueIn_; solutionBasic_[pivotRow_] = valueIn_; if (algorithm_ < 0) { // and set bounds correctly static_cast< AbcSimplexDual * >(this)->originalBound(sequenceIn_); static_cast< AbcSimplexDual * >(this)->changeBound(sequenceOut_); } else { #if ABC_NORMAL_DEBUG > 2 if (handler_->logLevel() == 63) printf("Code swapPrimalStuff for primal\n"); #endif } if (pivotRow_ >= 0) { // may be flip in primal lowerBasic_[pivotRow_] = abcLower_[sequenceIn_]; upperBasic_[pivotRow_] = abcUpper_[sequenceIn_]; costBasic_[pivotRow_] = abcCost_[sequenceIn_]; abcPivotVariable_[pivotRow_] = sequenceIn_; } } // Swaps dual stuff void AbcSimplex::swapDualStuff(int lastSequenceOut, int lastDirectionOut) { // outgoing // set dj to zero unless values pass if (lastSequenceOut >= 0) { if ((stateOfProblem_ & VALUES_PASS) == 0) { if (lastDirectionOut > 0) { abcDj_[lastSequenceOut] = theta_; } else { abcDj_[lastSequenceOut] = -theta_; } } else { if (lastDirectionOut > 0) { abcDj_[lastSequenceOut] -= theta_; } else { abcDj_[lastSequenceOut] += theta_; } } } if (sequenceIn_ >= 0) { abcDj_[sequenceIn_] = 0.0; //costBasic_[pivotRow_]=abcCost_[sequenceIn_]; } } static void solveMany(int number, ClpSimplex **simplex) { for (int i = 0; i < number - 1; i++) cilk_spawn simplex[i]->dual(0); simplex[number - 1]->dual(0); cilk_sync; } void AbcSimplex::crash(int type) { int i; for (i = 0; i < numberRows_; i++) { if (getInternalStatus(i) != basic) break; } if (i < numberRows_) return; // all slack if (type == 3) { // decomposition crash if (!abcMatrix_->gotRowCopy()) abcMatrix_->createRowCopy(); //const double * element = abcMatrix_->getPackedMatrix()->getElements(); const CoinBigIndex *columnStart = abcMatrix_->getPackedMatrix()->getVectorStarts(); const int *row = abcMatrix_->getPackedMatrix()->getIndices(); //const double * elementByRow = abcMatrix_->rowElements(); const CoinBigIndex *rowStart = abcMatrix_->rowStart(); const CoinBigIndex *rowEnd = abcMatrix_->rowEnd(); const int *column = abcMatrix_->rowColumns(); int *blockStart = usefulArray_[0].getIndices(); int *columnBlock = blockStart + numberRows_; int *nextColumn = usefulArray_[1].getIndices(); int *blockCount = nextColumn + numberColumns_; int direction[2] = { -1, 1 }; int bestBreak = -1; double bestValue = 0.0; int iPass = 0; int halfway = (numberRows_ + 1) / 2; int firstMaster = -1; int lastMaster = -2; int numberBlocks = 0; int largestRows = 0; int largestColumns = 0; int numberEmpty = 0; int numberMaster = 0; int numberEmptyColumns = 0; int numberMasterColumns = 0; while (iPass < 2) { int increment = direction[iPass]; int start = increment > 0 ? 0 : numberRows_ - 1; int stop = increment > 0 ? numberRows_ : -1; numberBlocks = 0; int thisBestBreak = -1; double thisBestValue = COIN_DBL_MAX; int numberRowsDone = 0; int numberMarkedColumns = 0; int maximumBlockSize = 0; for (int i = 0; i < numberRows_; i++) { blockStart[i] = -1; blockCount[i] = 0; } for (int i = 0; i < numberColumns_; i++) { columnBlock[i] = -1; nextColumn[i] = -1; } for (int iRow = start; iRow != stop; iRow += increment) { int iBlock = -1; for (CoinBigIndex j = rowStart[iRow]; j < rowEnd[iRow]; j++) { int iColumn = column[j] - maximumAbcNumberRows_; int whichColumnBlock = columnBlock[iColumn]; if (whichColumnBlock >= 0) { // column marked if (iBlock < 0) { // put row in that block iBlock = whichColumnBlock; } else if (iBlock != whichColumnBlock) { // merge blockCount[iBlock] += blockCount[whichColumnBlock]; blockCount[whichColumnBlock] = 0; int jColumn = blockStart[whichColumnBlock]; #ifndef NDEBUG int iiColumn = iColumn; #endif while (jColumn >= 0) { assert(columnBlock[jColumn] == whichColumnBlock); columnBlock[jColumn] = iBlock; #ifndef NDEBUG if (jColumn == iiColumn) iiColumn = -1; #endif iColumn = jColumn; jColumn = nextColumn[jColumn]; } #ifndef NDEBUG assert(iiColumn == -1); #endif nextColumn[iColumn] = blockStart[iBlock]; blockStart[iBlock] = blockStart[whichColumnBlock]; blockStart[whichColumnBlock] = -1; } } } int n = numberMarkedColumns; if (iBlock < 0) { //new block if (rowEnd[iRow] > rowStart[iRow]) { numberBlocks++; iBlock = numberBlocks; int jColumn = column[rowStart[iRow]] - maximumAbcNumberRows_; columnBlock[jColumn] = iBlock; blockStart[iBlock] = jColumn; numberMarkedColumns++; for (CoinBigIndex j = rowStart[iRow] + 1; j < rowEnd[iRow]; j++) { int iColumn = column[j] - maximumAbcNumberRows_; columnBlock[iColumn] = iBlock; numberMarkedColumns++; nextColumn[jColumn] = iColumn; jColumn = iColumn; } blockCount[iBlock] = numberMarkedColumns - n; } else { // empty } } else { // put in existing block int jColumn = blockStart[iBlock]; for (CoinBigIndex j = rowStart[iRow]; j < rowEnd[iRow]; j++) { int iColumn = column[j] - maximumAbcNumberRows_; assert(columnBlock[iColumn] < 0 || columnBlock[iColumn] == iBlock); if (columnBlock[iColumn] < 0) { columnBlock[iColumn] = iBlock; numberMarkedColumns++; nextColumn[iColumn] = jColumn; jColumn = iColumn; } } blockStart[iBlock] = jColumn; blockCount[iBlock] += numberMarkedColumns - n; } if (iBlock >= 0) maximumBlockSize = CoinMax(maximumBlockSize, blockCount[iBlock]); numberRowsDone++; if (thisBestValue * numberRowsDone > maximumBlockSize && numberRowsDone > halfway) { thisBestBreak = iRow; thisBestValue = static_cast< double >(maximumBlockSize) / static_cast< double >(numberRowsDone); } } if (thisBestBreak == stop) thisBestValue = COIN_DBL_MAX; iPass++; if (iPass == 1) { bestBreak = thisBestBreak; bestValue = thisBestValue; } else { if (bestValue < thisBestValue) { firstMaster = 0; lastMaster = bestBreak; } else { firstMaster = thisBestBreak; // ? +1 lastMaster = numberRows_; } } } bool useful = false; if (firstMaster < lastMaster) { for (int i = 0; i < numberRows_; i++) blockStart[i] = -1; for (int i = firstMaster; i < lastMaster; i++) blockStart[i] = -2; for (int i = 0; i < numberColumns_; i++) columnBlock[i] = -1; int firstRow = 0; numberBlocks = -1; while (true) { for (; firstRow < numberRows_; firstRow++) { if (blockStart[firstRow] == -1) break; } if (firstRow == numberRows_) break; int nRows = 0; numberBlocks++; int numberStack = 1; blockCount[0] = firstRow; while (numberStack) { int iRow = blockCount[--numberStack]; for (CoinBigIndex j = rowStart[iRow]; j < rowEnd[iRow]; j++) { int iColumn = column[j] - maximumAbcNumberRows_; int iBlock = columnBlock[iColumn]; if (iBlock < 0) { columnBlock[iColumn] = numberBlocks; for (CoinBigIndex k = columnStart[iColumn]; k < columnStart[iColumn + 1]; k++) { int jRow = row[k]; int rowBlock = blockStart[jRow]; if (rowBlock == -1) { nRows++; blockStart[jRow] = numberBlocks; blockCount[numberStack++] = jRow; } } } } } if (!nRows) { // empty!! numberBlocks--; } firstRow++; } // adjust numberBlocks++; for (int i = 0; i < numberBlocks; i++) { blockCount[i] = 0; nextColumn[i] = 0; } for (int iRow = 0; iRow < numberRows_; iRow++) { int iBlock = blockStart[iRow]; if (iBlock >= 0) { blockCount[iBlock]++; } else { if (iBlock == -2) numberMaster++; else numberEmpty++; } } for (int iColumn = 0; iColumn < numberColumns_; iColumn++) { int iBlock = columnBlock[iColumn]; if (iBlock >= 0) { nextColumn[iBlock]++; } else { if (columnStart[iColumn + 1] > columnStart[iColumn]) numberMasterColumns++; else numberEmptyColumns++; } } for (int i = 0; i < numberBlocks; i++) { if (blockCount[i] + nextColumn[i] > largestRows + largestColumns) { largestRows = blockCount[i]; largestColumns = nextColumn[i]; } } useful = true; if (numberMaster > halfway || largestRows * 3 > numberRows_) useful = false; } if (useful) { #if ABC_NORMAL_DEBUG > 0 if (logLevel() >= 2) printf("%d master rows %d <= < %d\n", lastMaster - firstMaster, firstMaster, lastMaster); printf("%s %d blocks (largest %d,%d), %d master rows (%d empty) out of %d, %d master columns (%d empty) out of %d\n", useful ? "**Useful" : "NoGood", numberBlocks, largestRows, largestColumns, numberMaster, numberEmpty, numberRows_, numberMasterColumns, numberEmptyColumns, numberColumns_); if (logLevel() >= 2) { for (int i = 0; i < numberBlocks; i++) printf("Block %d has %d rows and %d columns\n", i, blockCount[i], nextColumn[i]); } #endif #define NUMBER_DW_BLOCKS 20 int minSize1 = (numberRows_ - numberMaster + NUMBER_DW_BLOCKS - 1) / NUMBER_DW_BLOCKS; int minSize2 = (numberRows_ - numberMaster + 2 * NUMBER_DW_BLOCKS - 1) / (2 * NUMBER_DW_BLOCKS); int *backRow = usefulArray_[1].getIndices(); // first sort for (int i = 0; i < numberBlocks; i++) { backRow[i] = -(3 * blockCount[i] + 0 * nextColumn[i]); nextColumn[i] = i; } CoinSort_2(backRow, backRow + numberBlocks, nextColumn); // keep if >minSize2 or sum >minSize1; int n = 0; for (int i = 0; i < numberBlocks; i++) { int originalBlock = nextColumn[i]; if (blockCount[originalBlock] < minSize2) break; n++; } int size = minSize1; for (int i = n; i < numberBlocks; i++) { int originalBlock = nextColumn[i]; size -= blockCount[originalBlock]; if (size > 0 && i < numberBlocks - 1) { blockCount[originalBlock] = -1; } else { size = minSize1; n++; } } int n2 = numberBlocks; numberBlocks = n; for (int i = n2 - 1; i >= 0; i--) { int originalBlock = nextColumn[i]; if (blockCount[originalBlock] > 0) n--; blockCount[originalBlock] = n; } assert(!n); for (int iRow = 0; iRow < numberRows_; iRow++) { int iBlock = blockStart[iRow]; if (iBlock >= 0) blockStart[iRow] = blockCount[iBlock]; } for (int iColumn = 0; iColumn < numberColumns_; iColumn++) { int iBlock = columnBlock[iColumn]; if (iBlock >= 0) columnBlock[iColumn] = blockCount[iBlock]; } // stick to Clp for now ClpSimplex **simplex = new ClpSimplex *[numberBlocks]; for (int iBlock = 0; iBlock < numberBlocks; iBlock++) { int nRow = 0; int nColumn = 0; for (int iRow = 0; iRow < numberRows_; iRow++) { if (blockStart[iRow] == iBlock) blockCount[nRow++] = iRow; } for (int iColumn = 0; iColumn < numberColumns_; iColumn++) { if (columnBlock[iColumn] == iBlock) nextColumn[nColumn++] = iColumn; } simplex[iBlock] = new ClpSimplex(this, nRow, blockCount, nColumn, nextColumn); simplex[iBlock]->setSpecialOptions(simplex[iBlock]->specialOptions() & (~65536)); if (logLevel() < 2) simplex[iBlock]->setLogLevel(0); } solveMany(numberBlocks, simplex); int numberBasic = numberMaster; int numberStructurals = 0; for (int i = 0; i < numberMaster; i++) abcPivotVariable_[i] = i + firstMaster; for (int iBlock = 0; iBlock < numberBlocks; iBlock++) { int nRow = 0; int nColumn = 0; // from Clp enum to Abc enum (and bound flip) unsigned char lookupToAbcSlack[6] = { 4, 6, 0 /*1*/, 1 /*0*/, 5, 7 }; unsigned char *COIN_RESTRICT getStatus = simplex[iBlock]->statusArray() + simplex[iBlock]->numberColumns(); double *COIN_RESTRICT solutionSaved = solutionSaved_; double *COIN_RESTRICT lowerSaved = lowerSaved_; double *COIN_RESTRICT upperSaved = upperSaved_; for (int iRow = 0; iRow < numberRows_; iRow++) { if (blockStart[iRow] == iBlock) { unsigned char status = getStatus[nRow++] & 7; AbcSimplex::Status abcStatus = static_cast< AbcSimplex::Status >(lookupToAbcSlack[status]); if (status != ClpSimplex::basic) { double lowerValue = lowerSaved[iRow]; double upperValue = upperSaved[iRow]; if (lowerValue == -COIN_DBL_MAX) { if (upperValue == COIN_DBL_MAX) { // free abcStatus = isFree; } else { abcStatus = atUpperBound; } } else if (upperValue == COIN_DBL_MAX) { abcStatus = atLowerBound; } else if (lowerValue == upperValue) { abcStatus = isFixed; } switch (abcStatus) { case isFixed: case atLowerBound: solutionSaved[iRow] = lowerValue; break; case atUpperBound: solutionSaved[iRow] = upperValue; break; default: break; } } else { // basic abcPivotVariable_[numberBasic++] = iRow; } internalStatus_[iRow] = abcStatus; } } // from Clp enum to Abc enum unsigned char lookupToAbc[6] = { 4, 6, 1, 0, 5, 7 }; unsigned char *COIN_RESTRICT putStatus = internalStatus_ + maximumAbcNumberRows_; getStatus = simplex[iBlock]->statusArray(); solutionSaved += maximumAbcNumberRows_; lowerSaved += maximumAbcNumberRows_; upperSaved += maximumAbcNumberRows_; int numberSaved = numberBasic; for (int iColumn = 0; iColumn < numberColumns_; iColumn++) { if (columnBlock[iColumn] == iBlock) { unsigned char status = getStatus[nColumn++] & 7; AbcSimplex::Status abcStatus = static_cast< AbcSimplex::Status >(lookupToAbc[status]); if (status != ClpSimplex::basic) { double lowerValue = lowerSaved[iColumn]; double upperValue = upperSaved[iColumn]; if (lowerValue == -COIN_DBL_MAX) { if (upperValue == COIN_DBL_MAX) { // free abcStatus = isFree; } else { abcStatus = atUpperBound; } } else if (upperValue == COIN_DBL_MAX) { abcStatus = atLowerBound; } else if (lowerValue == upperValue) { abcStatus = isFixed; } else if (abcStatus == isFree) { abcStatus = superBasic; } switch (abcStatus) { case isFixed: case atLowerBound: solutionSaved[iColumn] = lowerValue; break; case atUpperBound: solutionSaved[iColumn] = upperValue; break; default: break; } } else { // basic if (numberBasic < numberRows_) abcPivotVariable_[numberBasic++] = iColumn + maximumAbcNumberRows_; else abcStatus = superBasic; } putStatus[iColumn] = abcStatus; } } numberStructurals += numberBasic - numberSaved; delete simplex[iBlock]; } #if ABC_NORMAL_DEBUG > 0 printf("%d structurals put into basis\n", numberStructurals); #endif if (numberBasic < numberRows_) { for (int iRow = 0; iRow < numberRows_; iRow++) { AbcSimplex::Status status = getInternalStatus(iRow); if (status != AbcSimplex::basic) { abcPivotVariable_[numberBasic++] = iRow; setInternalStatus(iRow, basic); if (numberBasic == numberRows_) break; } } } assert(numberBasic == numberRows_); #if 0 int n2=0; for (int i=0;in2); n2=abcPivotVariable_[i]; } #endif delete[] simplex; return; } else { // try another type = 2; } } if (type == 1) { const double *linearObjective = abcCost_ + maximumAbcNumberRows_; double gamma = 0.0; int numberTotal = numberRows_ + numberColumns_; double *q = new double[numberTotal]; double *v = q + numberColumns_; int *which = new int[numberTotal + 3 * numberRows_]; int *ii = which + numberColumns_; int *r = ii + numberRows_; int *pivoted = r + numberRows_; for (int iColumn = 0; iColumn < numberColumns_; iColumn++) { gamma = CoinMax(gamma, linearObjective[iColumn]); } for (int iRow = 0; iRow < numberRows_; iRow++) { double lowerBound = abcLower_[iRow]; double upperBound = abcUpper_[iRow]; pivoted[iRow] = -1; ii[iRow] = 0; r[iRow] = 0; v[iRow] = COIN_DBL_MAX; if (lowerBound == upperBound) continue; if (lowerBound <= 0.0 && upperBound >= 0.0) { pivoted[iRow] = iRow; ii[iRow] = 1; r[iRow] = 1; } } int nPossible = 0; int lastPossible = 0; double cMaxDiv; if (gamma) cMaxDiv = 1.0 / (1000.0 * gamma); else cMaxDiv = 1.0; const double *columnLower = abcLower_ + maximumAbcNumberRows_; const double *columnUpper = abcUpper_ + maximumAbcNumberRows_; for (int iPass = 0; iPass < 3; iPass++) { for (int iColumn = 0; iColumn < numberColumns_; iColumn++) { double lowerBound = columnLower[iColumn]; double upperBound = columnUpper[iColumn]; if (lowerBound == upperBound) continue; double qValue; if (lowerBound > -1.0e20) { if (upperBound < 1.0e20) { // both qValue = lowerBound - upperBound; if (iPass != 2) qValue = COIN_DBL_MAX; } else { // just lower qValue = lowerBound; if (iPass != 1) qValue = COIN_DBL_MAX; } } else { if (upperBound < 1.0e20) { // just upper qValue = -upperBound; if (iPass != 1) qValue = COIN_DBL_MAX; } else { // free qValue = 0.0; if (iPass != 0) qValue = COIN_DBL_MAX; } } if (qValue != COIN_DBL_MAX) { which[nPossible] = iColumn; q[nPossible++] = qValue + linearObjective[iColumn] * cMaxDiv; ; } } CoinSort_2(q + lastPossible, q + nPossible, which + lastPossible); lastPossible = nPossible; } const double *element = abcMatrix_->getPackedMatrix()->getElements(); const CoinBigIndex *columnStart = abcMatrix_->getPackedMatrix()->getVectorStarts(); //const int * columnLength = abcMatrix_->getPackedMatrix()->getVectorLengths(); const int *row = abcMatrix_->getPackedMatrix()->getIndices(); int nPut = 0; for (int i = 0; i < nPossible; i++) { int iColumn = which[i]; double maxAlpha = 0.0; int kRow = -1; double alternativeAlpha = 0.0; int jRow = -1; bool canTake = true; for (CoinBigIndex j = columnStart[iColumn]; j < columnStart[iColumn + 1]; j++) { int iRow = row[j]; double alpha = fabs(element[j]); if (alpha > 0.01 * v[iRow]) { canTake = false; } else if (!ii[iRow] && alpha > alternativeAlpha) { alternativeAlpha = alpha; jRow = iRow; } if (!r[iRow] && alpha > maxAlpha) { maxAlpha = alpha; kRow = iRow; } } // only really works if scaled if (maxAlpha > 0.99) { pivoted[kRow] = iColumn + maximumAbcNumberRows_; v[kRow] = maxAlpha; ii[kRow] = 1; for (CoinBigIndex j = columnStart[iColumn]; j < columnStart[iColumn + 1]; j++) { int iRow = row[j]; r[iRow]++; } nPut++; } else if (canTake && jRow >= 0) { pivoted[jRow] = iColumn + maximumAbcNumberRows_; v[jRow] = maxAlpha; ii[jRow] = 1; for (CoinBigIndex j = columnStart[iColumn]; j < columnStart[iColumn + 1]; j++) { int iRow = row[j]; r[iRow]++; } nPut++; } } for (int iRow = 0; iRow < numberRows_; iRow++) { int iSequence = pivoted[iRow]; if (iSequence >= 0 && iSequence < numberColumns_) { abcPivotVariable_[iRow] = iSequence; if (fabs(abcLower_[iRow]) < fabs(abcUpper_[iRow])) { setInternalStatus(iRow, atLowerBound); abcSolution_[iRow] = abcLower_[iRow]; solutionSaved_[iRow] = abcLower_[iRow]; } else { setInternalStatus(iRow, atUpperBound); abcSolution_[iRow] = abcUpper_[iRow]; solutionSaved_[iRow] = abcUpper_[iRow]; } setInternalStatus(iSequence, basic); } } #if ABC_NORMAL_DEBUG > 0 printf("%d put into basis\n", nPut); #endif delete[] q; delete[] which; } else if (type == 2) { //return; int numberBad = 0; CoinAbcMemcpy(abcDj_, abcCost_, numberTotal_); // Work on savedSolution and current int iVector = getAvailableArray(); #define ALLOW_BAD_DJS #ifdef ALLOW_BAD_DJS double *modDj = usefulArray_[iVector].denseVector(); #endif for (int iSequence = maximumAbcNumberRows_; iSequence < numberTotal_; iSequence++) { double dj = abcDj_[iSequence]; modDj[iSequence] = 0.0; if (getInternalStatus(iSequence) == atLowerBound) { if (dj < -dualTolerance_) { double costThru = -dj * (abcUpper_[iSequence] - abcLower_[iSequence]); if (costThru < dualBound_) { // flip setInternalStatus(iSequence, atUpperBound); solutionSaved_[iSequence] = abcUpper_[iSequence]; abcSolution_[iSequence] = abcUpper_[iSequence]; } else { numberBad++; #ifdef ALLOW_BAD_DJS modDj[iSequence] = dj; dj = 0.0; #else break; #endif } } else { dj = CoinMax(dj, 0.0); } } else if (getInternalStatus(iSequence) == atLowerBound) { if (dj > dualTolerance_) { double costThru = dj * (abcUpper_[iSequence] - abcLower_[iSequence]); if (costThru < dualBound_) { assert(abcUpper_[iSequence] - abcLower_[iSequence] < 1.0e10); // flip setInternalStatus(iSequence, atLowerBound); solutionSaved_[iSequence] = abcLower_[iSequence]; abcSolution_[iSequence] = abcLower_[iSequence]; } else { numberBad++; #ifdef ALLOW_BAD_DJS modDj[iSequence] = dj; dj = 0.0; #else break; #endif } } else { dj = CoinMin(dj, 0.0); } } else { if (fabs(dj) < dualTolerance_) { dj = 0.0; } else { numberBad++; #ifdef ALLOW_BAD_DJS modDj[iSequence] = dj; dj = 0.0; #else break; #endif } } abcDj_[iSequence] = dj; } #ifndef ALLOW_BAD_DJS if (numberBad) { //CoinAbcMemset0(modDj+maximumAbcNumberRows_,numberColumns_); return; } #endif if (!abcMatrix_->gotRowCopy()) abcMatrix_->createRowCopy(); //const double * element = abcMatrix_->getPackedMatrix()->getElements(); const CoinBigIndex *columnStart = abcMatrix_->getPackedMatrix()->getVectorStarts() - maximumAbcNumberRows_; const int *row = abcMatrix_->getPackedMatrix()->getIndices(); const double *elementByRow = abcMatrix_->rowElements(); const CoinBigIndex *rowStart = abcMatrix_->rowStart(); const CoinBigIndex *rowEnd = abcMatrix_->rowEnd(); const int *column = abcMatrix_->rowColumns(); CoinAbcMemset0(solutionBasic_, numberRows_); CoinAbcMemcpy(lowerBasic_, abcLower_, numberRows_); CoinAbcMemcpy(upperBasic_, abcUpper_, numberRows_); abcMatrix_->timesIncludingSlacks(-1.0, solutionSaved_, solutionBasic_); const double multiplier[] = { 1.0, -1.0 }; int nBasic = 0; int *index = usefulArray_[iVector].getIndices(); int iVector2 = getAvailableArray(); int *index2 = usefulArray_[iVector2].getIndices(); double *sort = usefulArray_[iVector2].denseVector(); int average = CoinMax(5, rowEnd[numberRows_ - 1] / (8 * numberRows_)); int nPossible = 0; if (numberRows_ > 10000) { // allow more for (int iRow = 0; iRow < numberRows_; iRow++) { double solutionValue = solutionBasic_[iRow]; double infeasibility = 0.0; double lowerValue = lowerBasic_[iRow]; double upperValue = upperBasic_[iRow]; if (solutionValue < lowerValue - primalTolerance_) { infeasibility = -(lowerValue - solutionValue); } else if (solutionValue > upperValue + primalTolerance_) { infeasibility = upperValue - solutionValue; } int length = rowEnd[iRow] - rowStart[iRow]; if (infeasibility) index2[nPossible++] = length; } std::sort(index2, index2 + nPossible); // see how much we need to get numberRows/10 or nPossible/3 average = CoinMax(average, index2[CoinMin(numberRows_ / 10, nPossible / 3)]); nPossible = 0; } for (int iRow = 0; iRow < numberRows_; iRow++) { double solutionValue = solutionBasic_[iRow]; double infeasibility = 0.0; double lowerValue = lowerBasic_[iRow]; double upperValue = upperBasic_[iRow]; if (solutionValue < lowerValue - primalTolerance_) { infeasibility = -(lowerValue - solutionValue); } else if (solutionValue > upperValue + primalTolerance_) { infeasibility = upperValue - solutionValue; } int length = rowEnd[iRow] - rowStart[iRow]; if (infeasibility && length < average) { index2[nPossible] = iRow; sort[nPossible++] = 1.0e5 * infeasibility - iRow; //sort[nPossible++]=1.0e9*length-iRow;//infeasibility; } } CoinSort_2(sort, sort + nPossible, index2); for (int iWhich = 0; iWhich < nPossible; iWhich++) { int iRow = index2[iWhich]; sort[iWhich] = 0.0; if (abcDj_[iRow]) continue; // marked as invalid double solutionValue = solutionBasic_[iRow]; double infeasibility = 0.0; double lowerValue = lowerBasic_[iRow]; double upperValue = upperBasic_[iRow]; if (solutionValue < lowerValue - primalTolerance_) { infeasibility = lowerValue - solutionValue; } else if (solutionValue > upperValue + primalTolerance_) { infeasibility = upperValue - solutionValue; } assert(infeasibility); double direction = infeasibility > 0 ? 1.0 : -1.0; infeasibility *= direction; int whichColumn = -1; double upperTheta = 1.0e30; int whichColumn2 = -1; double upperTheta2 = 1.0e30; double costThru = 0.0; int nThru = 0; for (CoinBigIndex j = rowStart[iRow]; j < rowEnd[iRow]; j++) { int iSequence = column[j]; assert(iSequence >= maximumAbcNumberRows_); double dj = abcDj_[iSequence]; double tableauValue = -elementByRow[j] * direction; unsigned char iStatus = internalStatus_[iSequence] & 7; if ((iStatus & 4) == 0) { double mult = multiplier[iStatus]; double alpha = tableauValue * mult; double oldValue = dj * mult; assert(oldValue > -1.0e-2); double value = oldValue - upperTheta * alpha; if (value < 0.0) { upperTheta2 = upperTheta; whichColumn2 = whichColumn; costThru = alpha * (abcUpper_[iSequence] - abcLower_[iSequence]); nThru = 0; upperTheta = oldValue / alpha; whichColumn = iSequence; } else if (oldValue - upperTheta2 * alpha < 0.0) { costThru += alpha * (abcUpper_[iSequence] - abcLower_[iSequence]); index[nThru++] = iSequence; } } else if (iStatus < 6) { upperTheta = -1.0; upperTheta2 = elementByRow[j]; whichColumn = iSequence; break; } } if (whichColumn < 0) continue; if (upperTheta != -1.0) { assert(upperTheta >= 0.0); if (costThru < infeasibility && whichColumn2 >= 0) { index[nThru++] = whichColumn; for (int i = 0; i < nThru; i++) { int iSequence = index[i]; assert(abcUpper_[iSequence] - abcLower_[iSequence] < 1.0e10); // flip and use previous if (getInternalStatus(iSequence) == atLowerBound) { setInternalStatus(iSequence, atUpperBound); solutionSaved_[iSequence] = abcUpper_[iSequence]; abcSolution_[iSequence] = abcUpper_[iSequence]; } else { setInternalStatus(iSequence, atLowerBound); solutionSaved_[iSequence] = abcLower_[iSequence]; abcSolution_[iSequence] = abcLower_[iSequence]; } } whichColumn = whichColumn2; upperTheta = upperTheta2; } } else { // free coming in upperTheta = (abcDj_[whichColumn] * direction) / upperTheta2; } // update djs upperTheta *= -direction; for (CoinBigIndex j = rowStart[iRow]; j < rowEnd[iRow]; j++) { int iSequence = column[j]; double dj = abcDj_[iSequence]; double tableauValue = elementByRow[j]; dj -= upperTheta * tableauValue; unsigned char iStatus = internalStatus_[iSequence] & 7; if ((iStatus & 4) == 0) { if (!iStatus) { assert(dj > -1.0e-2); dj = CoinMax(dj, 0.0); #ifdef ALLOW_BAD_DJS if (numberBad && modDj[iSequence]) { double bad = modDj[iSequence]; if (dj + bad >= 0.0) { numberBad--; modDj[iSequence] = 0.0; dj += bad; } else { modDj[iSequence] += dj; dj = 0.0; } } #endif } else { assert(dj < 1.0e-2); dj = CoinMin(dj, 0.0); #ifdef ALLOW_BAD_DJS if (numberBad && modDj[iSequence]) { double bad = modDj[iSequence]; if (dj + bad <= 0.0) { numberBad--; modDj[iSequence] = 0.0; dj += bad; } else { modDj[iSequence] += dj; dj = 0.0; } } #endif } } else if (iStatus < 6) { assert(fabs(dj) < 1.0e-4); dj = 0.0; } abcDj_[iSequence] = dj; } // do basis if (direction > 0.0) { if (upperBasic_[iRow] > lowerBasic_[iRow]) setInternalStatus(iRow, atLowerBound); else setInternalStatus(iRow, isFixed); solutionSaved_[iRow] = abcLower_[iRow]; abcSolution_[iRow] = abcLower_[iRow]; } else { if (upperBasic_[iRow] > lowerBasic_[iRow]) setInternalStatus(iRow, atUpperBound); else setInternalStatus(iRow, isFixed); solutionSaved_[iRow] = abcUpper_[iRow]; abcSolution_[iRow] = abcUpper_[iRow]; } setInternalStatus(whichColumn, basic); abcPivotVariable_[iRow] = whichColumn; nBasic++; // mark rows for (CoinBigIndex j = columnStart[whichColumn]; j < columnStart[whichColumn + 1]; j++) { int jRow = row[j]; abcDj_[jRow] = 1.0; } } #ifdef ALLOW_BAD_DJS CoinAbcMemset0(modDj + maximumAbcNumberRows_, numberColumns_); #endif setAvailableArray(iVector); setAvailableArray(iVector2); #if ABC_NORMAL_DEBUG > 0 printf("dual crash put %d in basis\n", nBasic); #endif } else { assert((stateOfProblem_ & VALUES_PASS2) != 0); // The idea is to put as many likely variables into basis as possible int n = 0; int iVector = getAvailableArray(); int *index = usefulArray_[iVector].getIndices(); double *array = usefulArray_[iVector].denseVector(); int iVector2 = getAvailableArray(); int *index2 = usefulArray_[iVector].getIndices(); for (int iSequence = 0; iSequence < numberTotal_; iSequence++) { double dj = djSaved_[iSequence]; double value = solution_[iSequence]; double lower = abcLower_[iSequence]; double upper = abcUpper_[iSequence]; double gapUp = CoinMin(1.0e3, upper - value); assert(gapUp >= -1.0e-3); gapUp = CoinMax(gapUp, 0.0); double gapDown = CoinMin(1.0e3, value - lower); assert(gapDown >= -1.0e-3); gapDown = CoinMax(gapDown, 0.0); double measure = (CoinMin(gapUp, gapDown) + 1.0e-6) / (fabs(dj) + 1.0e-6); if (gapUp < primalTolerance_ * 10.0 && dj < dualTolerance_) { // set to ub setInternalStatus(iSequence, atUpperBound); solutionSaved_[iSequence] = abcUpper_[iSequence]; abcSolution_[iSequence] = abcUpper_[iSequence]; } else if (gapDown < primalTolerance_ * 10.0 && dj > -dualTolerance_) { // set to lb setInternalStatus(iSequence, atLowerBound); solutionSaved_[iSequence] = abcLower_[iSequence]; abcSolution_[iSequence] = abcLower_[iSequence]; } else if (upper > lower) { // set to nearest if (gapUp < gapDown) { // set to ub setInternalStatus(iSequence, atUpperBound); solutionSaved_[iSequence] = abcUpper_[iSequence]; abcSolution_[iSequence] = abcUpper_[iSequence]; } else { // set to lb setInternalStatus(iSequence, atLowerBound); solutionSaved_[iSequence] = abcLower_[iSequence]; abcSolution_[iSequence] = abcLower_[iSequence]; } array[n] = -measure; index[n++] = iSequence; } } // set slacks basic memset(internalStatus_, 6, numberRows_); CoinSort_2(solution_, solution_ + n, index); CoinAbcMemset0(array, n); for (int i = 0; i < numberRows_; i++) index2[i] = 0; // first put all possible slacks in int n2 = 0; for (int i = 0; i < n; i++) { int iSequence = index[i]; if (iSequence < numberRows_) { index2[iSequence] = numberRows_; } else { index[n2++] = iSequence; } } n = n2; int numberIn = 0; const CoinBigIndex *columnStart = abcMatrix_->getPackedMatrix()->getVectorStarts() - maximumAbcNumberRows_; //const int * columnLength = abcMatrix_->getPackedMatrix()->getVectorLengths(); const int *row = abcMatrix_->getPackedMatrix()->getIndices(); if (!abcMatrix_->gotRowCopy()) abcMatrix_->createRowCopy(); //const CoinBigIndex * rowStart = abcMatrix_->rowStart(); //const CoinBigIndex * rowEnd = abcMatrix_->rowEnd(); for (int i = 0; i < n; i++) { int iSequence = index[i]; int bestRow = -1; int bestCount = numberRows_ + 1; for (CoinBigIndex j = columnStart[iSequence]; j < columnStart[iSequence + 1]; j++) { int iRow = row[j]; if (!abcMatrix_->gotRowCopy()) abcMatrix_->createRowCopy(); const CoinBigIndex *rowStart = abcMatrix_->rowStart(); const CoinBigIndex *rowEnd = abcMatrix_->rowEnd(); if (!index2[iRow]) { int length = rowEnd[iRow] - rowStart[iRow]; if (length < bestCount) { bestCount = length; bestRow = iRow; } } } if (bestRow >= 0) { numberIn++; for (CoinBigIndex j = columnStart[iSequence]; j < columnStart[iSequence + 1]; j++) { int iRow = row[j]; index2[iRow]++; } setInternalStatus(iSequence, basic); abcPivotVariable_[bestRow] = iSequence; double dj = djSaved_[bestRow]; double value = solution_[bestRow]; double lower = abcLower_[bestRow]; double upper = abcUpper_[bestRow]; double gapUp = CoinMax(CoinMin(1.0e3, upper - value), 0.0); double gapDown = CoinMax(CoinMin(1.0e3, value - lower), 0.0); //double measure = (CoinMin(gapUp,gapDown)+1.0e-6)/(fabs(dj)+1.0e-6); if (gapUp < primalTolerance_ * 10.0 && dj < dualTolerance_) { // set to ub setInternalStatus(bestRow, atUpperBound); solutionSaved_[bestRow] = abcUpper_[bestRow]; abcSolution_[bestRow] = abcUpper_[bestRow]; } else if (gapDown < primalTolerance_ * 10.0 && dj > -dualTolerance_) { // set to lb setInternalStatus(bestRow, atLowerBound); solutionSaved_[bestRow] = abcLower_[bestRow]; abcSolution_[bestRow] = abcLower_[bestRow]; } else if (upper > lower) { // set to nearest if (gapUp < gapDown) { // set to ub setInternalStatus(bestRow, atUpperBound); solutionSaved_[bestRow] = abcUpper_[bestRow]; abcSolution_[bestRow] = abcUpper_[bestRow]; } else { // set to lb setInternalStatus(bestRow, atLowerBound); solutionSaved_[bestRow] = abcLower_[bestRow]; abcSolution_[bestRow] = abcLower_[bestRow]; } } } } #if ABC_NORMAL_DEBUG > 0 printf("Idiot crash put %d in basis\n", numberIn); #endif setAvailableArray(iVector); setAvailableArray(iVector2); delete[] solution_; solution_ = NULL; } } /* Puts more stuff in basis 1 bit set - do even if basis exists 2 bit set - don't bother staying triangular */ void AbcSimplex::putStuffInBasis(int type) { int i; for (i = 0; i < numberRows_; i++) { if (getInternalStatus(i) != basic) break; } if (i < numberRows_ && (type & 1) == 0) return; int iVector = getAvailableArray(); // Column part is mustColumnIn int *COIN_RESTRICT mustRowOut = usefulArray_[iVector].getIndices(); if (!abcMatrix_->gotRowCopy()) abcMatrix_->createRowCopy(); const double *elementByRow = abcMatrix_->rowElements(); const CoinBigIndex *rowStart = abcMatrix_->rowStart(); const CoinBigIndex *rowEnd = abcMatrix_->rowEnd(); const int *column = abcMatrix_->rowColumns(); for (int i = 0; i < numberTotal_; i++) mustRowOut[i] = -1; int nPossible = 0; // find equality rows with effective nonzero rhs for (int iRow = 0; iRow < numberRows_; iRow++) { if (abcUpper_[iRow] > abcLower_[iRow] || getInternalStatus(iRow) != basic) { mustRowOut[iRow] = -2; continue; } int chooseColumn[2] = { -1, -1 }; for (CoinBigIndex j = rowStart[iRow]; j < rowEnd[iRow]; j++) { int iColumn = column[j]; if (elementByRow[j] > 0.0) { if (chooseColumn[0] == -1) chooseColumn[0] = iColumn; else chooseColumn[0] = -2; } else { if (chooseColumn[1] == -1) chooseColumn[1] = iColumn; else chooseColumn[1] = -2; } } for (int iTry = 0; iTry < 2; iTry++) { int jColumn = chooseColumn[iTry]; if (jColumn >= 0 && getInternalStatus(jColumn) != basic) { // see if has to be basic double lowerValue = -abcUpper_[iRow]; // check swap double upperValue = -abcLower_[iRow]; int lowerInf = 0; int upperInf = 0; double alpha = 0.0; for (CoinBigIndex j = rowStart[iRow]; j < rowEnd[iRow]; j++) { int iColumn = column[j]; if (iColumn != jColumn) { if (abcLower_[iColumn] > -1.0e20) lowerValue -= abcLower_[iColumn] * elementByRow[j]; else lowerInf++; if (abcUpper_[iColumn] < 1.0e20) upperValue -= abcUpper_[iColumn] * elementByRow[j]; else upperInf++; } else { alpha = elementByRow[j]; } } // find values column must lie between (signs again) if (upperInf) upperValue = COIN_DBL_MAX; else upperValue /= alpha; if (lowerInf) lowerValue = -COIN_DBL_MAX; else lowerValue /= alpha; if (iTry) { // swap double temp = lowerValue; lowerValue = upperValue; upperValue = temp; } if (lowerValue > abcLower_[jColumn] + 10.0 * primalTolerance_ && upperValue < abcUpper_[jColumn] - 10.0 * primalTolerance_) { nPossible++; if (mustRowOut[jColumn] >= 0) { // choose one ??? //printf("Column %d already selected on row %d now on %d\n", // jColumn,mustRowOut[jColumn],iRow); continue; } mustRowOut[jColumn] = iRow; mustRowOut[iRow] = jColumn; } } } } if (nPossible) { #if ABC_NORMAL_DEBUG > 0 printf("%d possible candidates\n", nPossible); #endif if ((type & 2) == 0) { // triangular int iVector2 = getAvailableArray(); int *COIN_RESTRICT counts = usefulArray_[iVector2].getIndices(); CoinAbcMemset0(counts, numberRows_); for (int iRow = 0; iRow < numberRows_; iRow++) { int n = 0; for (CoinBigIndex j = rowStart[iRow]; j < rowEnd[iRow]; j++) { int iColumn = column[j]; if (getInternalStatus(iColumn) == basic) n++; } counts[iRow] = n; } const CoinBigIndex *columnStart = abcMatrix_->getPackedMatrix()->getVectorStarts() - maximumAbcNumberRows_; const int *row = abcMatrix_->getPackedMatrix()->getIndices(); for (int iRow = 0; iRow < numberRows_; iRow++) { if (!counts[iRow]) { int iColumn = mustRowOut[iRow]; if (iColumn >= 0) { setInternalStatus(iRow, isFixed); solutionSaved_[iRow] = abcLower_[iRow]; setInternalStatus(iColumn, basic); for (CoinBigIndex j = columnStart[iColumn]; j < columnStart[iColumn + 1]; j++) { int jRow = row[j]; counts[jRow]++; } } } } setAvailableArray(iVector2); } else { // all for (int iRow = 0; iRow < numberRows_; iRow++) { int iColumn = mustRowOut[iRow]; if (iColumn >= 0) { setInternalStatus(iRow, isFixed); solutionSaved_[iRow] = abcLower_[iRow]; setInternalStatus(iColumn, basic); } } } // redo pivot array int numberBasic = 0; for (int iSequence = 0; iSequence < numberTotal_; iSequence++) { if (getInternalStatus(iSequence) == basic) abcPivotVariable_[numberBasic++] = iSequence; } assert(numberBasic == numberRows_); } setAvailableArray(iVector); } // Computes nonbasic cost and total cost void AbcSimplex::computeObjective() { sumNonBasicCosts_ = 0.0; rawObjectiveValue_ = 0.0; for (int iSequence = 0; iSequence < numberTotal_; iSequence++) { double value = abcSolution_[iSequence] * abcCost_[iSequence]; rawObjectiveValue_ += value; if (getInternalStatus(iSequence) != basic) sumNonBasicCosts_ += value; } setClpSimplexObjectiveValue(); } // This sets largest infeasibility and most infeasible void AbcSimplex::checkPrimalSolution(bool justBasic) { rawObjectiveValue_ = CoinAbcInnerProduct(costBasic_, numberRows_, solutionBasic_); //rawObjectiveValue_ += sumNonBasicCosts_; setClpSimplexObjectiveValue(); // now look at primal solution sumPrimalInfeasibilities_ = 0.0; numberPrimalInfeasibilities_ = 0; double primalTolerance = primalTolerance_; double relaxedTolerance = primalTolerance_; // we can't really trust infeasibilities if there is primal error double error = CoinMin(1.0e-2, CoinMax(largestPrimalError_, 5.0 * primalTolerance_)); // allow tolerance at least slightly bigger than standard relaxedTolerance = relaxedTolerance + error; sumOfRelaxedPrimalInfeasibilities_ = 0.0; const double *COIN_RESTRICT lowerBasic = lowerBasic_; const double *COIN_RESTRICT upperBasic = upperBasic_; const double *COIN_RESTRICT solutionBasic = solutionBasic_; if (justBasic) { for (int iRow = 0; iRow < numberRows_; iRow++) { double infeasibility = 0.0; if (solutionBasic[iRow] > upperBasic[iRow]) { infeasibility = solutionBasic[iRow] - upperBasic[iRow]; } else if (solutionBasic[iRow] < lowerBasic[iRow]) { infeasibility = lowerBasic[iRow] - solutionBasic[iRow]; } if (infeasibility > primalTolerance) { sumPrimalInfeasibilities_ += infeasibility - primalTolerance_; if (infeasibility > relaxedTolerance) sumOfRelaxedPrimalInfeasibilities_ += infeasibility - relaxedTolerance; numberPrimalInfeasibilities_++; } } } else { for (int iSequence = 0; iSequence < numberTotal_; iSequence++) { double infeasibility = 0.0; if (abcSolution_[iSequence] > abcUpper_[iSequence]) { infeasibility = abcSolution_[iSequence] - abcUpper_[iSequence]; } else if (abcSolution_[iSequence] < abcLower_[iSequence]) { infeasibility = abcLower_[iSequence] - abcSolution_[iSequence]; } if (infeasibility > primalTolerance) { //assert (getInternalStatus(iSequence)==basic); sumPrimalInfeasibilities_ += infeasibility - primalTolerance_; if (infeasibility > relaxedTolerance) sumOfRelaxedPrimalInfeasibilities_ += infeasibility - relaxedTolerance; numberPrimalInfeasibilities_++; } } } } void AbcSimplex::checkDualSolution() { sumDualInfeasibilities_ = 0.0; numberDualInfeasibilities_ = 0; int firstFreePrimal = -1; int firstFreeDual = -1; int numberSuperBasicWithDj = 0; bestPossibleImprovement_ = 0.0; // we can't really trust infeasibilities if there is dual error double error = CoinMin(1.0e-2, CoinMax(largestDualError_, 5.0 * dualTolerance_)); // allow tolerance at least slightly bigger than standard double relaxedTolerance = currentDualTolerance_ + error; // allow bigger tolerance for possible improvement double possTolerance = 5.0 * relaxedTolerance; sumOfRelaxedDualInfeasibilities_ = 0.0; int numberNeedToMove = 0; for (int iSequence = 0; iSequence < numberTotal_; iSequence++) { if (getInternalStatus(iSequence) != basic && !flagged(iSequence)) { // not basic double distanceUp = abcUpper_[iSequence] - abcSolution_[iSequence]; double distanceDown = abcSolution_[iSequence] - abcLower_[iSequence]; double value = abcDj_[iSequence]; if (distanceUp > primalTolerance_) { // Check if "free" if (distanceDown <= primalTolerance_) { // should not be negative if (value < 0.0) { value = -value; if (value > currentDualTolerance_) { sumDualInfeasibilities_ += value - currentDualTolerance_; if (value > possTolerance) bestPossibleImprovement_ += CoinMin(distanceUp, 1.0e10) * value; if (value > relaxedTolerance) sumOfRelaxedDualInfeasibilities_ += value - relaxedTolerance; numberDualInfeasibilities_++; } } } else { // free value = fabs(value); if (value > 1.0 * relaxedTolerance) { numberSuperBasicWithDj++; if (firstFreeDual < 0) firstFreeDual = iSequence; } if (value > currentDualTolerance_ || getInternalStatus(iSequence) != AbcSimplex::isFree) { numberNeedToMove++; if (firstFreePrimal < 0) firstFreePrimal = iSequence; sumDualInfeasibilities_ += value - currentDualTolerance_; if (value > possTolerance) bestPossibleImprovement_ += CoinMin(distanceUp, 1.0e10) * value; if (value > relaxedTolerance) sumOfRelaxedDualInfeasibilities_ += value - relaxedTolerance; numberDualInfeasibilities_++; } } } else if (distanceDown > primalTolerance_) { // should not be positive if (value > 0.0) { if (value > currentDualTolerance_) { sumDualInfeasibilities_ += value - currentDualTolerance_; if (value > possTolerance) bestPossibleImprovement_ += value * CoinMin(distanceDown, 1.0e10); if (value > relaxedTolerance) sumOfRelaxedDualInfeasibilities_ += value - relaxedTolerance; numberDualInfeasibilities_++; } } } } } numberDualInfeasibilitiesWithoutFree_ = numberDualInfeasibilities_ - numberSuperBasicWithDj; if (algorithm_ < 0 && firstFreeDual >= 0) { // dual firstFree_ = firstFreeDual; } else if (numberSuperBasicWithDj || numberNeedToMove) { //(abcProgress_.lastIterationNumber(0) <= 0)) { firstFree_ = firstFreePrimal; if (!sumDualInfeasibilities_) sumDualInfeasibilities_ = 1.0e-8; } } /* This sets sum and number of infeasibilities (Dual and Primal) */ void AbcSimplex::checkBothSolutions() { // old way checkPrimalSolution(true); checkDualSolution(); } /* Unpacks one column of the matrix into indexed array */ void AbcSimplex::unpack(CoinIndexedVector &rowArray, int sequence) const { abcMatrix_->unpack(rowArray, sequence); } // Sets row pivot choice algorithm in dual void AbcSimplex::setDualRowPivotAlgorithm(AbcDualRowPivot &choice) { delete abcDualRowPivot_; abcDualRowPivot_ = choice.clone(true); abcDualRowPivot_->setModel(this); } // Sets column pivot choice algorithm in primal void AbcSimplex::setPrimalColumnPivotAlgorithm(AbcPrimalColumnPivot &choice) { delete abcPrimalColumnPivot_; abcPrimalColumnPivot_ = choice.clone(true); abcPrimalColumnPivot_->setModel(this); } void AbcSimplex::setFactorization(AbcSimplexFactorization &factorization) { if (abcFactorization_) abcFactorization_->setFactorization(factorization); else abcFactorization_ = new AbcSimplexFactorization(factorization, numberRows_); } // Swaps factorization AbcSimplexFactorization * AbcSimplex::swapFactorization(AbcSimplexFactorization *factorization) { AbcSimplexFactorization *swap = abcFactorization_; abcFactorization_ = factorization; return swap; } /* Tightens primal bounds to make dual faster. Unless fixed, bounds are slightly looser than they could be. This is to make dual go faster and is probably not needed with a presolve. Returns non-zero if problem infeasible */ int AbcSimplex::tightenPrimalBounds() { int tightenType = 1; if (maximumIterations() >= 1000000 && maximumIterations() < 1000010) tightenType = maximumIterations() - 1000000; if (!tightenType) return 0; if (integerType_) { #if ABC_NORMAL_DEBUG > 0 printf("Redo tighten to relax by 1 for integers (and don't be shocked by infeasibility)\n"); #endif return 0; } // This needs to work on scaled matrix - then replace // Get a row copy in standard format CoinPackedMatrix copy; copy.setExtraGap(0.0); copy.setExtraMajor(0.0); copy.reverseOrderedCopyOf(*abcMatrix_->matrix()); // get matrix data pointers const int *COIN_RESTRICT column = copy.getIndices(); const CoinBigIndex *COIN_RESTRICT rowStart = copy.getVectorStarts(); const int *COIN_RESTRICT rowLength = copy.getVectorLengths(); const double *COIN_RESTRICT element = copy.getElements(); int numberChanged = 1, iPass = 0; double large = largeValue(); // treat bounds > this as infinite #ifndef NDEBUG double large2 = 1.0e10 * large; #endif int numberInfeasible = 0; int totalTightened = 0; double tolerance = primalTolerance(); // A copy of bounds is up at top translate(0); // move down #define MAXPASS 10 // Loop round seeing if we can tighten bounds // Would be faster to have a stack of possible rows // and we put altered rows back on stack int numberCheck = -1; // temp swap signs so can use existing code double *COIN_RESTRICT rowLower = abcLower_; double *COIN_RESTRICT rowUpper = abcUpper_; for (int iRow = 0; iRow < numberRows_; iRow++) { double value = -rowLower[iRow]; rowLower[iRow] = -rowUpper[iRow]; rowUpper[iRow] = value; } // Keep lower and upper for rows int whichArray[5]; for (int i = 0; i < 5; i++) whichArray[i] = getAvailableArray(); double *COIN_RESTRICT minRhs = usefulArray_[whichArray[0]].denseVector(); double *COIN_RESTRICT maxRhs = usefulArray_[whichArray[1]].denseVector(); int *COIN_RESTRICT changedList = usefulArray_[whichArray[0]].getIndices(); int *COIN_RESTRICT changedListNext = usefulArray_[whichArray[1]].getIndices(); char *COIN_RESTRICT changed = reinterpret_cast< char * >(usefulArray_[whichArray[2]].getIndices()); // -1 no infinite, -2 more than one infinite >=0 column int *COIN_RESTRICT whichInfiniteDown = usefulArray_[whichArray[3]].getIndices(); int *COIN_RESTRICT whichInfiniteUp = usefulArray_[whichArray[3]].getIndices(); int numberToDoNext = 0; for (int iRow = 0; iRow < numberRows_; iRow++) { if (rowLower[iRow] > -large || rowUpper[iRow] < large) { changedListNext[numberToDoNext++] = iRow; whichInfiniteDown[iRow] = -1; whichInfiniteUp[iRow] = -1; } else { minRhs[iRow] = -COIN_DBL_MAX; maxRhs[iRow] = COIN_DBL_MAX; whichInfiniteDown[iRow] = -2; whichInfiniteUp[iRow] = -2; } } const int *COIN_RESTRICT row = abcMatrix_->matrix()->getIndices(); const CoinBigIndex *COIN_RESTRICT columnStart = abcMatrix_->matrix()->getVectorStarts(); const double *COIN_RESTRICT elementByColumn = abcMatrix_->matrix()->getElements(); double *COIN_RESTRICT columnLower = abcLower_ + maximumAbcNumberRows_; double *COIN_RESTRICT columnUpper = abcUpper_ + maximumAbcNumberRows_; while (numberChanged > numberCheck) { int numberToDo = numberToDoNext; numberToDoNext = 0; int *COIN_RESTRICT temp = changedList; changedList = changedListNext; changedListNext = temp; CoinAbcMemset0(changed, numberRows_); numberChanged = 0; // Bounds tightened this pass if (iPass == MAXPASS) break; iPass++; for (int k = 0; k < numberToDo; k++) { int iRow = changedList[k]; // possible row int infiniteUpper = 0; int infiniteLower = 0; int firstInfiniteUpper = -1; int firstInfiniteLower = -1; double maximumUp = 0.0; double maximumDown = 0.0; double newBound; CoinBigIndex rStart = rowStart[iRow]; CoinBigIndex rEnd = rowStart[iRow] + rowLength[iRow]; CoinBigIndex j; // Compute possible lower and upper ranges for (j = rStart; j < rEnd; ++j) { double value = element[j]; int iColumn = column[j]; if (value > 0.0) { if (columnUpper[iColumn] >= large) { firstInfiniteUpper = iColumn; ++infiniteUpper; } else { maximumUp += columnUpper[iColumn] * value; } if (columnLower[iColumn] <= -large) { firstInfiniteLower = iColumn; ++infiniteLower; } else { maximumDown += columnLower[iColumn] * value; } } else if (value < 0.0) { if (columnUpper[iColumn] >= large) { firstInfiniteLower = iColumn; ++infiniteLower; } else { maximumDown += columnUpper[iColumn] * value; } if (columnLower[iColumn] <= -large) { firstInfiniteUpper = iColumn; ++infiniteUpper; } else { maximumUp += columnLower[iColumn] * value; } } } // Build in a margin of error maximumUp += 1.0e-8 * fabs(maximumUp); maximumDown -= 1.0e-8 * fabs(maximumDown); double maxUp = maximumUp + infiniteUpper * 1.0e31; double maxDown = maximumDown - infiniteLower * 1.0e31; minRhs[iRow] = infiniteLower ? -COIN_DBL_MAX : maximumDown; maxRhs[iRow] = infiniteUpper ? COIN_DBL_MAX : maximumUp; if (infiniteLower == 0) whichInfiniteDown[iRow] = -1; else if (infiniteLower == 1) whichInfiniteDown[iRow] = firstInfiniteLower; else whichInfiniteDown[iRow] = -2; if (infiniteUpper == 0) whichInfiniteUp[iRow] = -1; else if (infiniteUpper == 1) whichInfiniteUp[iRow] = firstInfiniteUpper; else whichInfiniteUp[iRow] = -2; if (maxUp <= rowUpper[iRow] + tolerance && maxDown >= rowLower[iRow] - tolerance) { // Row is redundant - make totally free // NO - can't do this for postsolve // rowLower[iRow]=-COIN_DBL_MAX; // rowUpper[iRow]=COIN_DBL_MAX; //printf("Redundant row in presolveX %d\n",iRow); } else { if (maxUp < rowLower[iRow] - 100.0 * tolerance || maxDown > rowUpper[iRow] + 100.0 * tolerance) { // problem is infeasible - exit at once numberInfeasible++; break; } double lower = rowLower[iRow]; double upper = rowUpper[iRow]; for (j = rStart; j < rEnd; ++j) { double value = element[j]; int iColumn = column[j]; double nowLower = columnLower[iColumn]; double nowUpper = columnUpper[iColumn]; if (value > 0.0) { // positive value if (lower > -large) { if (!infiniteUpper) { assert(nowUpper < large2); newBound = nowUpper + (lower - maximumUp) / value; // relax if original was large if (fabs(maximumUp) > 1.0e8) newBound -= 1.0e-12 * fabs(maximumUp); } else if (infiniteUpper == 1 && nowUpper > large) { newBound = (lower - maximumUp) / value; // relax if original was large if (fabs(maximumUp) > 1.0e8) newBound -= 1.0e-12 * fabs(maximumUp); } else { newBound = -COIN_DBL_MAX; } if (newBound > nowLower + 1.0e-12 && newBound > -large) { // Tighten the lower bound numberChanged++; // check infeasible (relaxed) if (nowUpper < newBound) { if (nowUpper - newBound < -100.0 * tolerance) numberInfeasible++; else newBound = nowUpper; } columnLower[iColumn] = newBound; for (CoinBigIndex j1 = columnStart[iColumn]; j1 < columnStart[iColumn + 1]; j1++) { int jRow = row[j1]; if (!changed[jRow]) { changed[jRow] = 1; changedListNext[numberToDoNext++] = jRow; } } // adjust double now; if (nowLower < -large) { now = 0.0; infiniteLower--; } else { now = nowLower; } maximumDown += (newBound - now) * value; nowLower = newBound; } } if (upper < large) { if (!infiniteLower) { assert(nowLower > -large2); newBound = nowLower + (upper - maximumDown) / value; // relax if original was large if (fabs(maximumDown) > 1.0e8) newBound += 1.0e-12 * fabs(maximumDown); } else if (infiniteLower == 1 && nowLower < -large) { newBound = (upper - maximumDown) / value; // relax if original was large if (fabs(maximumDown) > 1.0e8) newBound += 1.0e-12 * fabs(maximumDown); } else { newBound = COIN_DBL_MAX; } if (newBound < nowUpper - 1.0e-12 && newBound < large) { // Tighten the upper bound numberChanged++; // check infeasible (relaxed) if (nowLower > newBound) { if (newBound - nowLower < -100.0 * tolerance) numberInfeasible++; else newBound = nowLower; } columnUpper[iColumn] = newBound; for (CoinBigIndex j1 = columnStart[iColumn]; j1 < columnStart[iColumn + 1]; j1++) { int jRow = row[j1]; if (!changed[jRow]) { changed[jRow] = 1; changedListNext[numberToDoNext++] = jRow; } } // adjust double now; if (nowUpper > large) { now = 0.0; infiniteUpper--; } else { now = nowUpper; } maximumUp += (newBound - now) * value; nowUpper = newBound; } } } else { // negative value if (lower > -large) { if (!infiniteUpper) { assert(nowLower < large2); newBound = nowLower + (lower - maximumUp) / value; // relax if original was large if (fabs(maximumUp) > 1.0e8) newBound += 1.0e-12 * fabs(maximumUp); } else if (infiniteUpper == 1 && nowLower < -large) { newBound = (lower - maximumUp) / value; // relax if original was large if (fabs(maximumUp) > 1.0e8) newBound += 1.0e-12 * fabs(maximumUp); } else { newBound = COIN_DBL_MAX; } if (newBound < nowUpper - 1.0e-12 && newBound < large) { // Tighten the upper bound numberChanged++; // check infeasible (relaxed) if (nowLower > newBound) { if (newBound - nowLower < -100.0 * tolerance) numberInfeasible++; else newBound = nowLower; } columnUpper[iColumn] = newBound; for (CoinBigIndex j1 = columnStart[iColumn]; j1 < columnStart[iColumn + 1]; j1++) { int jRow = row[j1]; if (!changed[jRow]) { changed[jRow] = 1; changedListNext[numberToDoNext++] = jRow; } } // adjust double now; if (nowUpper > large) { now = 0.0; infiniteLower--; } else { now = nowUpper; } maximumDown += (newBound - now) * value; nowUpper = newBound; } } if (upper < large) { if (!infiniteLower) { assert(nowUpper < large2); newBound = nowUpper + (upper - maximumDown) / value; // relax if original was large if (fabs(maximumDown) > 1.0e8) newBound -= 1.0e-12 * fabs(maximumDown); } else if (infiniteLower == 1 && nowUpper > large) { newBound = (upper - maximumDown) / value; // relax if original was large if (fabs(maximumDown) > 1.0e8) newBound -= 1.0e-12 * fabs(maximumDown); } else { newBound = -COIN_DBL_MAX; } if (newBound > nowLower + 1.0e-12 && newBound > -large) { // Tighten the lower bound numberChanged++; // check infeasible (relaxed) if (nowUpper < newBound) { if (nowUpper - newBound < -100.0 * tolerance) numberInfeasible++; else newBound = nowUpper; } columnLower[iColumn] = newBound; for (CoinBigIndex j1 = columnStart[iColumn]; j1 < columnStart[iColumn + 1]; j1++) { int jRow = row[j1]; if (!changed[jRow]) { changed[jRow] = 1; changedListNext[numberToDoNext++] = jRow; } } // adjust double now; if (nowLower < -large) { now = 0.0; infiniteUpper--; } else { now = nowLower; } maximumUp += (newBound - now) * value; nowLower = newBound; } } } } } } #if 0 // see if we can tighten doubletons with infinite bounds if (iPass==1) { const double * COIN_RESTRICT elementByColumn = abcMatrix_->matrix()->getElements(); for (int iColumn=0;iColumn> 4; if (numberInfeasible) break; } const double *COIN_RESTRICT saveLower = abcLower_ + maximumNumberTotal_ + maximumAbcNumberRows_; const double *COIN_RESTRICT saveUpper = abcUpper_ + maximumNumberTotal_ + maximumAbcNumberRows_; if (!numberInfeasible) { handler_->message(CLP_SIMPLEX_BOUNDTIGHTEN, messages_) << totalTightened << CoinMessageEol; int numberLowerChanged = 0; int numberUpperChanged = 0; if (!integerType_) { // Set bounds slightly loose // tighten rows as well //#define PRINT_TIGHTEN_PROGRESS 0 for (int iRow = 0; iRow < numberRows_; iRow++) { assert(maxRhs[iRow] >= rowLower[iRow]); assert(minRhs[iRow] <= rowUpper[iRow]); rowLower[iRow] = CoinMax(rowLower[iRow], minRhs[iRow]); rowUpper[iRow] = CoinMin(rowUpper[iRow], maxRhs[iRow]); #if PRINT_TIGHTEN_PROGRESS > 3 if (handler_->logLevel() > 5) printf("Row %d min %g max %g lower %g upper %g\n", iRow, minRhs[iRow], maxRhs[iRow], rowLower[iRow], rowUpper[iRow]); #endif } #if 0 double useTolerance = 1.0e-4; double multiplier = 100.0; // To do this we need to compute min and max JUST for no costs? const double * COIN_RESTRICT cost = abcCost_+maximumAbcNumberRows_; for (int iColumn = 0; iColumn < numberColumns_; iColumn++) { if (saveUpper[iColumn] > saveLower[iColumn] + useTolerance) { double awayFromLower=0.0; double awayFromUpper=0.0; //double gap=columnUpper[iColumn]-columnLower[iColumn]; for (CoinBigIndex j=columnStart[iColumn];j 3 if (handler_->logLevel()>5) printf("row %d element %g\n",iRow,value); #endif if (value>0.0) { if (minRhs[iRow]+value*awayFromLower-1.0e10&&awayFromLower<1.0e10) awayFromLower = CoinMax(awayFromLower,(rowLower[iRow]-minRhs[iRow])/value); else awayFromLower=COIN_DBL_MAX; } if (maxRhs[iRow]-value*awayFromUpper>rowUpper[iRow]) { if (maxRhs[iRow]<1.0e10&&awayFromUpper<1.0e10) awayFromUpper = CoinMax(awayFromUpper,(maxRhs[iRow]-rowUpper[iRow])/value); else awayFromUpper=COIN_DBL_MAX; } } else { if (maxRhs[iRow]+value*awayFromLower>rowUpper[iRow]) { if (maxRhs[iRow]<1.0e10&&awayFromLower<1.0e10) awayFromLower = CoinMax(awayFromLower,(rowUpper[iRow]-maxRhs[iRow])/value); else awayFromLower=COIN_DBL_MAX; } if (minRhs[iRow]-value*awayFromUpper-1.0e10&&awayFromUpper<1.0e10) awayFromUpper = CoinMin(awayFromUpper,(minRhs[iRow]-rowLower[iRow])/value); else awayFromUpper=COIN_DBL_MAX; } } } // Might have to go as high as double upper = CoinMin(columnLower[iColumn]+awayFromLower,columnUpper[iColumn]); // and as low as double lower = CoinMax(columnUpper[iColumn]-awayFromUpper,columnLower[iColumn]); // but be sensible double gap=0.999*(CoinMin(columnUpper[iColumn]-columnLower[iColumn],1.0e10)); if (awayFromLower>gap||awayFromUpper>gap) { if (fabs(columnUpper[iColumn]-upper)>1.0e-5) { #if PRINT_TIGHTEN_PROGRESS > 1 printf("YYchange upper bound on %d from %g (original %g) to %g (awayFromLower %g) - cost %g\n",iColumn, columnUpper[iColumn],saveUpper[iColumn],upper,awayFromLower,cost[iColumn]); #endif upper=columnUpper[iColumn]; } if (fabs(columnLower[iColumn]-lower)>1.0e-5) { #if PRINT_TIGHTEN_PROGRESS > 1 printf("YYchange lower bound on %d from %g (original %g) to %g (awayFromUpper %g) - cost %g\n",iColumn, columnLower[iColumn],saveLower[iColumn],lower,awayFromUpper,cost[iColumn]); #endif lower=columnLower[iColumn]; } } if (lower>upper) { #if PRINT_TIGHTEN_PROGRESS printf("XXchange upper bound on %d from %g (original %g) to %g (awayFromLower %g) - cost %g\n",iColumn, columnUpper[iColumn],saveUpper[iColumn],upper,awayFromLower,cost[iColumn]); printf("XXchange lower bound on %d from %g (original %g) to %g (awayFromUpper %g) - cost %g\n",iColumn, columnLower[iColumn],saveLower[iColumn],lower,awayFromUpper,cost[iColumn]); #endif lower=columnLower[iColumn]; upper=columnUpper[iColumn]; } //upper=CoinMax(upper,0.0); //upper=CoinMax(upper,0.0); if (cost[iColumn]>=0.0&&awayFromLower<1.0e10&&columnLower[iColumn]>-1.0e10) { // doesn't want to be too positive if (fabs(columnUpper[iColumn]-upper)>1.0e-5) { #if PRINT_TIGHTEN_PROGRESS > 2 if (handler_->logLevel()>1) printf("change upper bound on %d from %g (original %g) to %g (awayFromLower %g) - cost %g\n",iColumn, columnUpper[iColumn],saveUpper[iColumn],upper,awayFromLower,cost[iColumn]); #endif double difference=columnUpper[iColumn]-upper; for (CoinBigIndex j=columnStart[iColumn];j0.0) { assert (difference*value>=0.0); maxRhs[iRow]-=difference*value; } else { assert (difference*value<=0.0); minRhs[iRow]-=difference*value; } } columnUpper[iColumn]=upper; numberUpperChanged++; } } if (cost[iColumn]<=0.0&&awayFromUpper<1.0e10&&columnUpper[iColumn]<1.0e10) { // doesn't want to be too negative if (fabs(columnLower[iColumn]-lower)>1.0e-5) { #if PRINT_TIGHTEN_PROGRESS > 2 if (handler_->logLevel()>1) printf("change lower bound on %d from %g (original %g) to %g (awayFromUpper %g) - cost %g\n",iColumn, columnLower[iColumn],saveLower[iColumn],lower,awayFromUpper,cost[iColumn]); #endif double difference=columnLower[iColumn]-lower; for (CoinBigIndex j=columnStart[iColumn];j0.0) { assert (difference*value<=0.0); minRhs[iRow]-=difference*value; } else { assert (difference*value>=0.0); maxRhs[iRow]-=difference*value; } } columnLower[iColumn]=lower; numberLowerChanged++; } } // Make large bounds stay infinite if (saveUpper[iColumn] > 1.0e30 && columnUpper[iColumn] > 1.0e10) { columnUpper[iColumn] = COIN_DBL_MAX; } if (saveLower[iColumn] < -1.0e30 && columnLower[iColumn] < -1.0e10) { columnLower[iColumn] = -COIN_DBL_MAX; } if (columnUpper[iColumn] - columnLower[iColumn] < useTolerance + 1.0e-8) { // relax enough so will have correct dj columnLower[iColumn] = CoinMax(saveLower[iColumn], columnLower[iColumn] - multiplier * useTolerance); columnUpper[iColumn] = CoinMin(saveUpper[iColumn], columnUpper[iColumn] + multiplier * useTolerance); } else { if (columnUpper[iColumn] < saveUpper[iColumn]) { // relax a bit columnUpper[iColumn] = CoinMin(columnUpper[iColumn] + multiplier * useTolerance, saveUpper[iColumn]); } if (columnLower[iColumn] > saveLower[iColumn]) { // relax a bit columnLower[iColumn] = CoinMax(columnLower[iColumn] - multiplier * useTolerance, saveLower[iColumn]); } } if (0) { // debug // tighten rows as well for (int iRow = 0; iRow < numberRows_; iRow++) { if (rowLower[iRow] > -large || rowUpper[iRow] < large) { // possible row int infiniteUpper = 0; int infiniteLower = 0; double maximumUp = 0.0; double maximumDown = 0.0; CoinBigIndex rStart = rowStart[iRow]; CoinBigIndex rEnd = rowStart[iRow] + rowLength[iRow]; CoinBigIndex j; // Compute possible lower and upper ranges for (j = rStart; j < rEnd; ++j) { double value = element[j]; int iColumn = column[j]; if (value > 0.0) { if (columnUpper[iColumn] >= large) { ++infiniteUpper; } else { maximumUp += columnUpper[iColumn] * value; } if (columnLower[iColumn] <= -large) { ++infiniteLower; } else { maximumDown += columnLower[iColumn] * value; } } else if (value < 0.0) { if (columnUpper[iColumn] >= large) { ++infiniteLower; } else { maximumDown += columnUpper[iColumn] * value; } if (columnLower[iColumn] <= -large) { ++infiniteUpper; } else { maximumUp += columnLower[iColumn] * value; } } } // Build in a margin of error double maxUp = maximumUp+1.0e-8 * fabs(maximumUp); double maxDown = maximumDown-1.0e-8 * fabs(maximumDown); double rLower=rowLower[iRow]; double rUpper=rowUpper[iRow]; if (!infiniteUpper&&maxUp < rUpper - tolerance) { if (rUpper!=COIN_DBL_MAX||maximumUp<1.0e5) rUpper=maximumUp; } if (!infiniteLower&&maxDown > rLower + tolerance) { if (rLower!=-COIN_DBL_MAX||maximumDown>-1.0e5) rLower=maximumDown; } if (infiniteUpper) maxUp=COIN_DBL_MAX; if (fabs(maxUp-maxRhs[iRow])>1.0e-3*(1.0+fabs(maxUp))) printf("bad Maxup row %d maxUp %g maxRhs %g\n",iRow,maxUp,maxRhs[iRow]); maxRhs[iRow]=maxUp; if (infiniteLower) maxDown=-COIN_DBL_MAX; if (fabs(maxDown-minRhs[iRow])>1.0e-3*(1.0+fabs(maxDown))) printf("bad Maxdown row %d maxDown %g minRhs %g\n",iRow,maxDown,minRhs[iRow]); minRhs[iRow]=maxDown; assert(rLower<=rUpper); } } // end debug } } } if (tightenType>1) { // relax for (int iColumn = 0; iColumn < numberColumns_; iColumn++) { // relax enough so will have correct dj double lower=saveLower[iColumn]; double upper=saveUpper[iColumn]; columnLower[iColumn] = CoinMax(lower,columnLower[iColumn] - multiplier); columnUpper[iColumn] = CoinMin(upper,columnUpper[iColumn] + multiplier); } } #endif } else { #if ABC_NORMAL_DEBUG > 0 printf("Redo tighten to relax by 1 for integers\n"); #endif } #if ABC_NORMAL_DEBUG > 0 printf("Tighten - phase1 %d bounds changed, phase2 %d lower, %d upper\n", totalTightened, numberLowerChanged, numberUpperChanged); #endif if (integerType_) { const double *columnScale = scaleToExternal_ + maximumAbcNumberRows_; const double *inverseColumnScale = scaleFromExternal_ + maximumAbcNumberRows_; for (int iColumn = 0; iColumn < numberColumns_; iColumn++) { if (integerType_[iColumn]) { double value; double lower = columnLower[iColumn] * inverseColumnScale[iColumn]; double upper = columnUpper[iColumn] * inverseColumnScale[iColumn]; value = floor(lower + 0.5); if (fabs(value - lower) > primalTolerance_) value = ceil(lower); columnLower_[iColumn] = value; columnLower[iColumn] = value * columnScale[iColumn]; value = floor(upper + 0.5); if (fabs(value - upper) > primalTolerance_) value = floor(upper); columnUpper_[iColumn] = value; columnUpper[iColumn] = value * columnScale[iColumn]; if (columnLower_[iColumn] > columnUpper_[iColumn]) numberInfeasible++; } } if (numberInfeasible) { handler_->message(CLP_SIMPLEX_INFEASIBILITIES, messages_) << numberInfeasible << CoinMessageEol; // restore column bounds CoinMemcpyN(saveLower, numberColumns_, columnLower_); CoinMemcpyN(saveUpper, numberColumns_, columnUpper_); } } } else { handler_->message(CLP_SIMPLEX_INFEASIBILITIES, messages_) << numberInfeasible << CoinMessageEol; // restore column bounds CoinMemcpyN(saveLower, numberColumns_, columnLower_); CoinMemcpyN(saveUpper, numberColumns_, columnUpper_); } if (!numberInfeasible) { // tighten rows as well for (int iRow = 0; iRow < numberRows_; iRow++) { if (rowLower[iRow] > -large || rowUpper[iRow] < large) { // possible row int infiniteUpper = 0; int infiniteLower = 0; double maximumUp = 0.0; double maximumDown = 0.0; CoinBigIndex rStart = rowStart[iRow]; CoinBigIndex rEnd = rowStart[iRow] + rowLength[iRow]; CoinBigIndex j; // Compute possible lower and upper ranges for (j = rStart; j < rEnd; ++j) { double value = element[j]; int iColumn = column[j]; if (value > 0.0) { if (columnUpper[iColumn] >= large) { ++infiniteUpper; } else { maximumUp += columnUpper[iColumn] * value; } if (columnLower[iColumn] <= -large) { ++infiniteLower; } else { maximumDown += columnLower[iColumn] * value; } } else if (value < 0.0) { if (columnUpper[iColumn] >= large) { ++infiniteLower; } else { maximumDown += columnUpper[iColumn] * value; } if (columnLower[iColumn] <= -large) { ++infiniteUpper; } else { maximumUp += columnLower[iColumn] * value; } } } // Build in a margin of error double maxUp = maximumUp + 1.0e-8 * fabs(maximumUp); double maxDown = maximumDown - 1.0e-8 * fabs(maximumDown); if (!infiniteUpper && maxUp < rowUpper[iRow] - tolerance) { if (rowUpper[iRow] != COIN_DBL_MAX || maximumUp < 1.0e5) rowUpper[iRow] = maximumUp; } if (!infiniteLower && maxDown > rowLower[iRow] + tolerance) { if (rowLower[iRow] != -COIN_DBL_MAX || maximumDown > -1.0e5) rowLower[iRow] = maximumDown; } assert(rowLower[iRow] <= rowUpper[iRow]); if (rowUpper[iRow] - rowLower[iRow] < 1.0e-12) { if (fabs(rowLower[iRow]) > fabs(rowUpper[iRow])) rowLower[iRow] = rowUpper[iRow]; else rowUpper[iRow] = rowLower[iRow]; } } } // flip back for (int iRow = 0; iRow < numberRows_; iRow++) { double value = -rowLower[iRow]; rowLower[iRow] = -rowUpper[iRow]; rowUpper[iRow] = value; } // move back - relaxed unless integer if (!integerType_) { double *COIN_RESTRICT lowerSaved = abcLower_ + maximumNumberTotal_; double *COIN_RESTRICT upperSaved = abcUpper_ + maximumNumberTotal_; double tolerance = 2.0 * primalTolerance_; for (int i = 0; i < numberTotal_; i++) { double lower = abcLower_[i]; double upper = abcUpper_[i]; if (lower != upper) { lower = CoinMax(lower - tolerance, lowerSaved[i]); upper = CoinMin(upper + tolerance, upperSaved[i]); } abcLower_[i] = lower; lowerSaved[i] = lower; abcUpper_[i] = upper; upperSaved[i] = upper; } } else { CoinAbcMemcpy(abcLower_ + maximumNumberTotal_, abcLower_, numberTotal_); CoinAbcMemcpy(abcUpper_ + maximumNumberTotal_, abcUpper_, numberTotal_); } #if 0 for (int i=0;iabcUpper_[i+maximumNumberTotal_]+1.0e-5) printf ("above %d %g %g\n",i, abcSolution_[i+maximumNumberTotal_],abcUpper_[i+maximumNumberTotal_]); if (abcSolution_[i+maximumNumberTotal_]> 8) & 7; if (crashState && crashState < 4) { switch (crashState) { case 1: crash(1000.0, 1); break; case 2: crash(abcSimplex_->dualBound(), 0); break; case 3: crash(0.0, 3); break; } } // this and abcSimplex_ are approximately same pointer if ((abcState_ & CLP_ABC_FULL_DONE) == 0) { abcSimplex_->gutsOfResize(numberRows_, numberColumns_); abcSimplex_->translate(DO_SCALE_AND_MATRIX | DO_BASIS_AND_ORDER | DO_STATUS | DO_SOLUTION); //abcSimplex_->permuteIn(); int maximumPivotsAbc = CoinMin(abcSimplex_->factorization()->maximumPivots(), numberColumns_ + 200); abcSimplex_->factorization()->maximumPivots(maximumPivotsAbc); if (numberColumns_) abcSimplex_->tightenPrimalBounds(); } if ((abcSimplex_->stateOfProblem() & VALUES_PASS2) != 0) { if (solution_) crashState = 6; } if (crashState && crashState > 3) { abcSimplex_->crash(crashState - 2); } if (crashState && crashState < 4) { abcSimplex_->putStuffInBasis(1 + 2); } int returnCode = abcSimplex_->doAbcDual(); //set to force crossover test returnCode=1; abcSimplex_->permuteOut(ROW_PRIMAL_OK | ROW_DUAL_OK | COLUMN_PRIMAL_OK | COLUMN_DUAL_OK | ALL_STATUS_OK); if (returnCode) { // fix as this model is all messed up e.g. scaling scalingFlag_ = abs(scalingFlag_); //delete [] rowScale_; //delete [] columnScale_; rowScale_ = NULL; columnScale_ = NULL; #if 0 delete [] savedRowScale_; delete [] savedColumnScale_; savedRowScale_ = NULL; savedColumnScale_ = NULL; inverseRowScale_ = NULL; inverseColumnScale_ = NULL; #endif if (perturbation_ == 50) perturbation_ = 51; //perturbation_=100; #if ABC_NORMAL_DEBUG > 0 printf("Bad exit with status of %d\n", problemStatus_); #endif //problemStatus_=10; int status = problemStatus_; //problemStatus_=-1; if (status != 10) { dual(); // Do ClpSimplexDual } else { moreSpecialOptions_ |= 256; primal(1); } } else { // double check objective //printf("%g %g\n",objectiveValue(),abcSimplex_->objectiveValue()); perturbation_ = 100; moreSpecialOptions_ |= 256; //primal(1); } return returnCode; } } #endif #include "AbcSimplexPrimal.hpp" // Do dual (return 1 if cleanup needed) int AbcSimplex::doAbcDual() { if (objective_) { objective_->setActivated(0); } else { // create dummy stuff assert(!numberColumns_); if (!numberRows_) problemStatus_ = 0; // say optimal return 0; } /* Note use of "down casting". The only class the user sees is AbcSimplex. Classes AbcSimplexDual, AbcSimplexPrimal, (AbcSimplexNonlinear) and AbcSimplexOther all exist and inherit from AbcSimplex but have no additional data and have no destructor or (non-default) constructor. This is to stop classes becoming too unwieldy and so I (JJHF) can use e.g. "perturb" in primal and dual. As far as I can see this is perfectly safe. */ algorithm_ = -1; baseIteration_ = numberIterations_; if (!abcMatrix_->gotRowCopy()) abcMatrix_->createRowCopy(); #ifdef EARLY_FACTORIZE if (maximumIterations() > 1000000 && maximumIterations() < 1000999) { numberEarly_ = maximumIterations() - 1000000; #if ABC_NORMAL_DEBUG > 0 printf("Setting numberEarly_ to %d\n", numberEarly_); #endif numberEarly_ += numberEarly_ << 16; } #endif minimumThetaMovement_ = 1.0e-10; if (fabs(infeasibilityCost_ - 1.0e10) < 1.1e9 && fabs(infeasibilityCost_ - 1.0e10) > 1.0e5 && false) { minimumThetaMovement_ = 1.0e-3 / fabs(infeasibilityCost_ - 1.0e10); printf("trying minimum theta movement of %g\n", minimumThetaMovement_); infeasibilityCost_ = 1.0e10; } int savePerturbation = perturbation_; static_cast< AbcSimplexDual * >(this)->dual(); minimumThetaMovement_ = 1.0e-10; if ((specialOptions_ & 2048) != 0 && problemStatus_ == 10 && !numberPrimalInfeasibilities_ && sumDualInfeasibilities_ < 1000.0 * dualTolerance_) problemStatus_ = 0; // ignore onStopped(); // set secondary status if stopped if (problemStatus_ == 1 && numberFlagged_) { problemStatus_ = 10; static_cast< AbcSimplexPrimal * >(this)->unflag(); } if (perturbation_ < 101) { //printf("Perturbed djs?\n"); double *save = abcCost_; abcCost_ = costSaved_; computeInternalObjectiveValue(); abcCost_ = save; } int totalNumberIterations = numberIterations_; if (problemStatus_ == 10 && (moreSpecialOptions_ & 32768) != 0 && sumDualInfeasibilities_ < 0.1) { problemStatus_ = 0; } #ifndef TRY_ABC_GUS if (problemStatus_ == 10) { int savePerturbation = perturbation_; perturbation_ = 100; copyFromSaved(2); minimumThetaMovement_ = 1.0e-12; baseIteration_ = numberIterations_; static_cast< AbcSimplexPrimal * >(this)->primal(0); totalNumberIterations += numberIterations_ - baseIteration_; perturbation_ = savePerturbation; } #else int iPass = 0; while (problemStatus_ == 10 && minimumThetaMovement_ > 0.99999e-12) { iPass++; if (initialSumInfeasibilities_ >= 0.0) { if (savePerturbation >= 100) { perturbation_ = 100; } else { if (savePerturbation == 50) perturbation_ = CoinMax(51, HEAVY_PERTURBATION - 4 - iPass); //smaller else perturbation_ = CoinMax(51, savePerturbation - 1 - iPass); //smaller } } else { perturbation_ = savePerturbation; abcFactorization_->setPivots(100000); // force factorization initialSumInfeasibilities_ = 1.23456789e-5; // clean pivots int numberBasic = 0; int *pivot = pivotVariable(); for (int i = 0; i < numberTotal_; i++) { if (getInternalStatus(i) == basic) pivot[numberBasic++] = i; } assert(numberBasic == numberRows_); } copyFromSaved(14); // Say second call if (iPass > 3) moreSpecialOptions_ |= 256; if (iPass > 2) perturbation_ = 101; baseIteration_ = numberIterations_; static_cast< AbcSimplexPrimal * >(this)->primal(0); totalNumberIterations += numberIterations_ - baseIteration_; if (problemStatus_ == 10) { // reduce minimumThetaMovement_ *= 1.0e-1; copyFromSaved(14); baseIteration_ = numberIterations_; static_cast< AbcSimplexDual * >(this)->dual(); totalNumberIterations += numberIterations_ - baseIteration_; } perturbation_ = savePerturbation; } #endif numberIterations_ = totalNumberIterations; return (problemStatus_ < 0 || problemStatus_ == 4 || problemStatus_ == 10) ? 1 : 0; } int AbcSimplex::dual() { if (!abcMatrix_->gotRowCopy()) abcMatrix_->createRowCopy(); assert(!numberFlagged_); baseIteration_ = numberIterations_; //double savedPivotTolerance = abcFactorization_->pivotTolerance(); if (objective_) { objective_->setActivated(0); } else { // create dummy stuff assert(!numberColumns_); if (!numberRows_) problemStatus_ = 0; // say optimal return 0; } /* Note use of "down casting". The only class the user sees is AbcSimplex. Classes AbcSimplexDual, AbcSimplexPrimal, (AbcSimplexNonlinear) and AbcSimplexOther all exist and inherit from AbcSimplex but have no additional data and have no destructor or (non-default) constructor. This is to stop classes becoming too unwieldy and so I (JJF) can use e.g. "perturb" in primal and dual. As far as I can see this is perfectly safe. */ minimumThetaMovement_ = 1.0e-12; int returnCode = static_cast< AbcSimplexDual * >(this)->dual(); if ((specialOptions_ & 2048) != 0 && problemStatus_ == 10 && !numberPrimalInfeasibilities_ && sumDualInfeasibilities_ < 1000.0 * dualTolerance_ && perturbation_ >= 100) problemStatus_ = 0; // ignore if (problemStatus_ == 10) { #if 1 //ABC_NORMAL_DEBUG>0 printf("return and use ClpSimplexPrimal\n"); abort(); #else //printf("Cleaning up with primal\n"); //lastAlgorithm=1; int savePerturbation = perturbation_; int saveLog = handler_->logLevel(); //handler_->setLogLevel(63); perturbation_ = 101; bool denseFactorization = initialDenseFactorization(); // It will be safe to allow dense setInitialDenseFactorization(true); // Allow for catastrophe int saveMax = intParam_[ClpMaxNumIteration]; if (numberIterations_) { // normal if (intParam_[ClpMaxNumIteration] > 100000 + numberIterations_) intParam_[ClpMaxNumIteration] = numberIterations_ + 1000 + 2 * numberRows_ + numberColumns_; } else { // Not normal allow more baseIteration_ += 2 * (numberRows_ + numberColumns_); } // check which algorithms allowed int dummy; if (problemStatus_ == 10 && saveObjective == objective_) startFinishOptions |= 2; baseIteration_ = numberIterations_; // Say second call moreSpecialOptions_ |= 256; minimumThetaMovement_ = 1.0e-12; returnCode = static_cast< AbcSimplexPrimal * >(this)->primal(1, startFinishOptions); // Say not second call moreSpecialOptions_ &= ~256; baseIteration_ = 0; if (saveObjective != objective_) { // We changed objective to see if infeasible delete objective_; objective_ = saveObjective; if (!problemStatus_) { // carry on returnCode = static_cast< AbcSimplexPrimal * >(this)->primal(1, startFinishOptions); } } if (problemStatus_ == 3 && numberIterations_ < saveMax) { // flatten solution and try again for (int iSequence = 0; iSequence < numberTotal_; iSequence++) { if (getInternalStatus(iSequence) != basic) { setInternalStatus(iSequence, superBasic); // but put to bound if close if (fabs(rowActivity_[iSequence] - rowLower_[iSequence]) <= primalTolerance_) { abcSolution_[iSequence] = abcLower_[iSequence]; setInternalStatus(iSequence, atLowerBound); } else if (fabs(rowActivity_[iSequence] - rowUpper_[iSequence]) <= primalTolerance_) { abcSolution_[iSequence] = abcUpper_[iSequence]; setInternalStatus(iSequence, atUpperBound); } } } problemStatus_ = -1; intParam_[ClpMaxNumIteration] = CoinMin(numberIterations_ + 1000 + 2 * numberRows_ + numberColumns_, saveMax); perturbation_ = savePerturbation; baseIteration_ = numberIterations_; // Say second call moreSpecialOptions_ |= 256; returnCode = static_cast< AbcSimplexPrimal * >(this)->primal(0, startFinishOptions); // Say not second call moreSpecialOptions_ &= ~256; baseIteration_ = 0; computeObjectiveValue(); // can't rely on djs either memset(reducedCost_, 0, numberColumns_ * sizeof(double)); } intParam_[ClpMaxNumIteration] = saveMax; setInitialDenseFactorization(denseFactorization); perturbation_ = savePerturbation; if (problemStatus_ == 10) { if (!numberPrimalInfeasibilities_) problemStatus_ = 0; else problemStatus_ = 4; } handler_->setLogLevel(saveLog); #endif } onStopped(); // set secondary status if stopped return returnCode; } #ifdef ABC_INHERIT // primal // Returns 0 if primal can be skipped int ClpSimplex::doAbcPrimal(int ifValuesPass) { if ((abcState_ & CLP_ABC_WANTED) == 0) { return 1; // not wanted } else { assert(abcSimplex_); if (ifValuesPass) abcSimplex_->setStateOfProblem(abcSimplex_->stateOfProblem() | VALUES_PASS); int crashState = (abcState_ >> 8) & 7; if (crashState && crashState < 4) { switch (crashState) { case 1: crash(1000.0, 1); break; case 2: crash(abcSimplex_->dualBound(), 0); break; case 3: crash(0.0, 3); break; } } // this and abcSimplex_ are approximately same pointer if ((abcState_ & CLP_ABC_FULL_DONE) == 0) { abcSimplex_->gutsOfResize(numberRows_, numberColumns_); abcSimplex_->translate(DO_SCALE_AND_MATRIX | DO_BASIS_AND_ORDER | DO_STATUS | DO_SOLUTION); //abcSimplex_->permuteIn(); int maximumPivotsAbc = CoinMin(abcSimplex_->factorization()->maximumPivots(), numberColumns_ + 200); abcSimplex_->factorization()->maximumPivots(maximumPivotsAbc); abcSimplex_->copyFromSaved(1); } if ((abcSimplex_->stateOfProblem() & VALUES_PASS2) != 0) { if (solution_) crashState = 6; } if (crashState && crashState > 3) { abcSimplex_->crash(crashState - 2); } if (crashState && crashState < 4) { abcSimplex_->putStuffInBasis(1 + 2); } int returnCode = abcSimplex_->doAbcPrimal(ifValuesPass); //set to force crossover test returnCode=1; abcSimplex_->permuteOut(ROW_PRIMAL_OK | ROW_DUAL_OK | COLUMN_PRIMAL_OK | COLUMN_DUAL_OK | ALL_STATUS_OK); if (returnCode && problemStatus_ < 3) { // fix as this model is all messed up e.g. scaling scalingFlag_ = abs(scalingFlag_); //delete [] rowScale_; //delete [] columnScale_; rowScale_ = NULL; columnScale_ = NULL; #if 0 delete [] savedRowScale_; delete [] savedColumnScale_; savedRowScale_ = NULL; savedColumnScale_ = NULL; inverseRowScale_ = NULL; inverseColumnScale_ = NULL; #endif if (perturbation_ == 50) perturbation_ = 51; //perturbation_=100; #if ABC_NORMAL_DEBUG > 0 if (problemStatus_) printf("Bad exit with status of %d\n", problemStatus_); #endif //problemStatus_=10; int status = problemStatus_; // should not be using for (int i = 0; i < 6; i++) { if (rowArray_[i]) rowArray_[i]->clear(); if (columnArray_[i]) columnArray_[i]->clear(); } //problemStatus_=-1; if (status < 3 && status != 0) { if (status != 10) { primal(); // Do ClpSimplexPrimal } else { moreSpecialOptions_ |= 256; dual(); } } } else { // double check objective //printf("%g %g\n",objectiveValue(),abcSimplex_->objectiveValue()); } numberIterations_ = abcSimplex_->numberIterations(); return returnCode; } } #endif // Do primal (return 1 if cleanup needed) int AbcSimplex::doAbcPrimal(int ifValuesPass) { if (objective_) { objective_->setActivated(0); } else { // create dummy stuff assert(!numberColumns_); if (!numberRows_) problemStatus_ = 0; // say optimal return 0; } /* Note use of "down casting". The only class the user sees is AbcSimplex. Classes AbcSimplexDual, AbcSimplexPrimal, (AbcSimplexNonlinear) and AbcSimplexOther all exist and inherit from AbcSimplex but have no additional data and have no destructor or (non-default) constructor. This is to stop classes becoming too unwieldy and so I (JJHF) can use e.g. "perturb" in primal and dual. As far as I can see this is perfectly safe. */ algorithm_ = -1; int savePerturbation = perturbation_; baseIteration_ = numberIterations_; if (!abcMatrix_->gotRowCopy()) abcMatrix_->createRowCopy(); #ifdef EARLY_FACTORIZE if (maximumIterations() > 1000000 && maximumIterations() < 1000999) { numberEarly_ = maximumIterations() - 1000000; #if ABC_NORMAL_DEBUG > 0 printf("Setting numberEarly_ to %d\n", numberEarly_); #endif numberEarly_ += numberEarly_ << 16; } #endif // add values pass options minimumThetaMovement_ = 1.0e-12; if ((specialOptions_ & 8192) != 0) minimumThetaMovement_ = 1.0e-15; int returnCode = static_cast< AbcSimplexPrimal * >(this)->primal(ifValuesPass); stateOfProblem_ &= ~VALUES_PASS; #ifndef TRY_ABC_GUS if (returnCode == 10) { copyFromSaved(14); int savePerturbation = perturbation_; perturbation_ = 51; minimumThetaMovement_ = 1.0e-12; returnCode = static_cast< AbcSimplexDual * >(this)->dual(); perturbation_ = savePerturbation; } #else minimumThetaMovement_ = 1.0e-12; int iPass = 0; while (problemStatus_ == 10 && minimumThetaMovement_ > 1.0e-15) { iPass++; if (minimumThetaMovement_ == 1.0e-12) perturbation_ = CoinMin(savePerturbation, 55); else perturbation_ = 100; copyFromSaved(14); // reduce ? // Say second call // Say second call if (iPass > 3) moreSpecialOptions_ |= 256; if (iPass > 2) perturbation_ = 101; baseIteration_ = numberIterations_; // make sure no superbasic cleanStatus(); if ((specialOptions_ & 8192) == 0) static_cast< AbcSimplexDual * >(this)->dual(); baseIteration_ = numberIterations_; if (problemStatus_ == 10) { if (initialSumInfeasibilities_ >= 0.0) { if (savePerturbation >= 100) { perturbation_ = 100; } else { if (savePerturbation == 50) perturbation_ = CoinMax(51, HEAVY_PERTURBATION - 4 - iPass); //smaller else perturbation_ = CoinMax(51, savePerturbation - 1 - iPass); //smaller } } else { specialOptions_ |= 8192; // stop going to dual perturbation_ = savePerturbation; abcFactorization_->setPivots(100000); // force factorization initialSumInfeasibilities_ = 1.23456789e-5; // clean pivots int numberBasic = 0; int *pivot = pivotVariable(); for (int i = 0; i < numberTotal_; i++) { if (getInternalStatus(i) == basic) pivot[numberBasic++] = i; } assert(numberBasic == numberRows_); } if (iPass > 2) perturbation_ = 100; copyFromSaved(14); baseIteration_ = numberIterations_; static_cast< AbcSimplexPrimal * >(this)->primal(0); } minimumThetaMovement_ *= 0.5; perturbation_ = savePerturbation; } #endif return returnCode; } /* Sets up all slack basis and resets solution to as it was after initial load or readMps */ void AbcSimplex::allSlackBasis() { // set column status to one nearest zero CoinFillN(internalStatus_, numberRows_, static_cast< unsigned char >(basic)); const double *COIN_RESTRICT lower = abcLower_; const double *COIN_RESTRICT upper = abcUpper_; double *COIN_RESTRICT solution = abcSolution_; // But set value to zero if lb <0.0 and ub>0.0 for (int i = maximumAbcNumberRows_; i < numberTotal_; i++) { if (lower[i] >= 0.0) { solution[i] = lower[i]; setInternalStatus(i, atLowerBound); } else if (upper[i] <= 0.0) { solution[i] = upper[i]; setInternalStatus(i, atUpperBound); } else if (lower[i] < -1.0e20 && upper[i] > 1.0e20) { // free solution[i] = 0.0; setInternalStatus(i, isFree); } else if (fabs(lower[i]) < fabs(upper[i])) { solution[i] = 0.0; setInternalStatus(i, atLowerBound); } else { solution[i] = 0.0; setInternalStatus(i, atUpperBound); } } } #if 0 //ndef SLIM_NOIO // Read an mps file from the given filename int AbcSimplex::readMps(const char *filename, bool keepNames, bool ignoreErrors) { int status = ClpSimplex::readMps(filename, keepNames, ignoreErrors); ClpSimplex * thisModel=this; gutsOfResize(thisModel->numberRows(),thisModel->numberColumns()); translate(DO_SCALE_AND_MATRIX|DO_BASIS_AND_ORDER|DO_STATUS|DO_SOLUTION); return status; } // Read GMPL files from the given filenames int AbcSimplex::readGMPL(const char *filename, const char * dataName, bool keepNames) { int status = ClpSimplex::readGMPL(filename, dataName, keepNames); translate(DO_SCALE_AND_MATRIX|DO_BASIS_AND_ORDER|DO_STATUS|DO_SOLUTION); return status; } // Read file in LP format from file with name filename. int AbcSimplex::readLp(const char *filename, const double epsilon ) { FILE *fp = fopen(filename, "r"); if(!fp) { printf("### ERROR: AbcSimplex::readLp(): Unable to open file %s for reading\n", filename); return(1); } CoinLpIO m; m.readLp(fp, epsilon); fclose(fp); // set problem name setStrParam(ClpProbName, m.getProblemName()); // no errors loadProblem(*m.getMatrixByRow(), m.getColLower(), m.getColUpper(), m.getObjCoefficients(), m.getRowLower(), m.getRowUpper()); if (m.integerColumns()) { integerType_ = new char[numberColumns_]; CoinMemcpyN(m.integerColumns(), numberColumns_, integerType_); } else { integerType_ = NULL; } translate(DO_SCALE_AND_MATRIX|DO_BASIS_AND_ORDER|DO_STATUS|DO_SOLUTION); unsigned int maxLength = 0; int iRow; rowNames_ = std::vector (); columnNames_ = std::vector (); rowNames_.reserve(numberRows_); for (iRow = 0; iRow < numberRows_; iRow++) { const char * name = m.rowName(iRow); if (name) { maxLength = CoinMax(maxLength, static_cast (strlen(name))); rowNames_.push_back(name); } else { rowNames_.push_back(""); } } int iColumn; columnNames_.reserve(numberColumns_); for (iColumn = 0; iColumn < numberColumns_; iColumn++) { const char * name = m.columnName(iColumn); if (name) { maxLength = CoinMax(maxLength, static_cast (strlen(name))); columnNames_.push_back(name); } else { columnNames_.push_back(""); } } lengthNames_ = static_cast (maxLength); return 0; } #endif // Factorization frequency int AbcSimplex::factorizationFrequency() const { if (abcFactorization_) return abcFactorization_->maximumPivots(); else return -1; } void AbcSimplex::setFactorizationFrequency(int value) { if (abcFactorization_) abcFactorization_->maximumPivots(value); } /* Get a clean factorization - i.e. throw out singularities may do more later */ int AbcSimplex::cleanFactorization(int ifValuesPass) { int status = internalFactorize(ifValuesPass ? 10 : 0); if (status < 0) { return 1; // some error } else { firstFree_ = 0; return 0; } } // Save data ClpDataSave AbcSimplex::saveData() { ClpDataSave saved; saved.dualBound_ = dualBound_; saved.infeasibilityCost_ = infeasibilityCost_; saved.pivotTolerance_ = abcFactorization_->pivotTolerance(); saved.zeroFactorizationTolerance_ = abcFactorization_->zeroTolerance(); saved.zeroSimplexTolerance_ = zeroTolerance_; saved.perturbation_ = perturbation_; saved.forceFactorization_ = forceFactorization_; saved.acceptablePivot_ = acceptablePivot_; saved.objectiveScale_ = objectiveScale_; // Progress indicator abcProgress_.fillFromModel(this); return saved; } // Restore data void AbcSimplex::restoreData(ClpDataSave saved) { //abcFactorization_->sparseThreshold(saved.sparseThreshold_); abcFactorization_->pivotTolerance(saved.pivotTolerance_); abcFactorization_->zeroTolerance(saved.zeroFactorizationTolerance_); zeroTolerance_ = saved.zeroSimplexTolerance_; perturbation_ = saved.perturbation_; infeasibilityCost_ = saved.infeasibilityCost_; dualBound_ = saved.dualBound_; forceFactorization_ = saved.forceFactorization_; objectiveScale_ = saved.objectiveScale_; acceptablePivot_ = saved.acceptablePivot_; } // To flag a variable void AbcSimplex::setFlagged(int sequence) { assert(sequence >= 0 && sequence < numberTotal_); if (sequence >= 0) { internalStatus_[sequence] |= 64; // use for real disaster lastFlaggedIteration_ = numberIterations_; numberFlagged_++; } } #ifndef NDEBUG // For errors to make sure print to screen // only called in debug mode static void indexError(int index, std::string methodName) { std::cerr << "Illegal index " << index << " in AbcSimplex::" << methodName << std::endl; throw CoinError("Illegal index", methodName, "AbcSimplex"); } #endif // After modifying first copy refreshes second copy and marks as updated void AbcSimplex::refreshCosts() { whatsChanged_ &= ~OBJECTIVE_SAME; CoinAbcMemcpy(abcCost_, costSaved_, numberTotal_); } void AbcSimplex::refreshLower(unsigned int type) { if (type) whatsChanged_ &= type; CoinAbcMemcpy(abcLower_, lowerSaved_, numberTotal_); } void AbcSimplex::refreshUpper(unsigned int type) { if (type) whatsChanged_ &= type; CoinAbcMemcpy(abcUpper_, upperSaved_, numberTotal_); } /* Set an objective function coefficient */ void AbcSimplex::setObjectiveCoefficient(int elementIndex, double elementValue) { #ifndef NDEBUG if (elementIndex < 0 || elementIndex >= numberColumns_) { indexError(elementIndex, "setObjectiveCoefficient"); } #endif if (objective()[elementIndex] != elementValue) { objective()[elementIndex] = elementValue; // work arrays exist - update as well whatsChanged_ &= ~OBJECTIVE_SAME; double direction = optimizationDirection_ * objectiveScale_; costSaved_[elementIndex + maximumAbcNumberRows_] = direction * elementValue * columnUseScale_[elementIndex + maximumAbcNumberRows_]; } } /* Set a single row lower bound
Use -DBL_MAX for -infinity. */ void AbcSimplex::setRowLower(int elementIndex, double elementValue) { #ifndef NDEBUG int n = numberRows_; if (elementIndex < 0 || elementIndex >= n) { indexError(elementIndex, "setRowLower"); } #endif if (elementValue < -1.0e27) elementValue = -COIN_DBL_MAX; if (rowLower_[elementIndex] != elementValue) { rowLower_[elementIndex] = elementValue; // work arrays exist - update as well whatsChanged_ &= ~ROW_LOWER_SAME; if (rowLower_[elementIndex] == -COIN_DBL_MAX) { lowerSaved_[elementIndex] = -COIN_DBL_MAX; } else { lowerSaved_[elementIndex] = elementValue * rhsScale_ * rowUseScale_[elementIndex]; } } } /* Set a single row upper bound
Use DBL_MAX for infinity. */ void AbcSimplex::setRowUpper(int elementIndex, double elementValue) { #ifndef NDEBUG int n = numberRows_; if (elementIndex < 0 || elementIndex >= n) { indexError(elementIndex, "setRowUpper"); } #endif if (elementValue > 1.0e27) elementValue = COIN_DBL_MAX; if (rowUpper_[elementIndex] != elementValue) { rowUpper_[elementIndex] = elementValue; // work arrays exist - update as well whatsChanged_ &= ~ROW_UPPER_SAME; if (rowUpper_[elementIndex] == COIN_DBL_MAX) { upperSaved_[elementIndex] = COIN_DBL_MAX; } else { upperSaved_[elementIndex] = elementValue * rhsScale_ * rowUseScale_[elementIndex]; } } } /* Set a single row lower and upper bound */ void AbcSimplex::setRowBounds(int elementIndex, double lowerValue, double upperValue) { #ifndef NDEBUG int n = numberRows_; if (elementIndex < 0 || elementIndex >= n) { indexError(elementIndex, "setRowBounds"); } #endif if (lowerValue < -1.0e27) lowerValue = -COIN_DBL_MAX; if (upperValue > 1.0e27) upperValue = COIN_DBL_MAX; //CoinAssert (upperValue>=lowerValue); if (rowLower_[elementIndex] != lowerValue) { rowLower_[elementIndex] = lowerValue; // work arrays exist - update as well whatsChanged_ &= ~ROW_LOWER_SAME; if (rowLower_[elementIndex] == -COIN_DBL_MAX) { lowerSaved_[elementIndex] = -COIN_DBL_MAX; } else { lowerSaved_[elementIndex] = lowerValue * rhsScale_ * rowUseScale_[elementIndex]; } } if (rowUpper_[elementIndex] != upperValue) { rowUpper_[elementIndex] = upperValue; // work arrays exist - update as well whatsChanged_ &= ~ROW_UPPER_SAME; if (rowUpper_[elementIndex] == COIN_DBL_MAX) { upperSaved_[elementIndex] = COIN_DBL_MAX; } else { upperSaved_[elementIndex] = upperValue * rhsScale_ * rowUseScale_[elementIndex]; } } } void AbcSimplex::setRowSetBounds(const int *indexFirst, const int *indexLast, const double *boundList) { #ifndef NDEBUG int n = numberRows_; #endif int numberChanged = 0; const int *saveFirst = indexFirst; while (indexFirst != indexLast) { const int iRow = *indexFirst++; #ifndef NDEBUG if (iRow < 0 || iRow >= n) { indexError(iRow, "setRowSetBounds"); } #endif double lowerValue = *boundList++; double upperValue = *boundList++; if (lowerValue < -1.0e27) lowerValue = -COIN_DBL_MAX; if (upperValue > 1.0e27) upperValue = COIN_DBL_MAX; //CoinAssert (upperValue>=lowerValue); if (rowLower_[iRow] != lowerValue) { rowLower_[iRow] = lowerValue; whatsChanged_ &= ~ROW_LOWER_SAME; numberChanged++; } if (rowUpper_[iRow] != upperValue) { rowUpper_[iRow] = upperValue; whatsChanged_ &= ~ROW_UPPER_SAME; numberChanged++; } } if (numberChanged) { indexFirst = saveFirst; while (indexFirst != indexLast) { const int iRow = *indexFirst++; if (rowLower_[iRow] == -COIN_DBL_MAX) { lowerSaved_[iRow] = -COIN_DBL_MAX; } else { lowerSaved_[iRow] = rowLower_[iRow] * rhsScale_ * rowUseScale_[iRow]; } if (rowUpper_[iRow] == COIN_DBL_MAX) { upperSaved_[iRow] = COIN_DBL_MAX; } else { upperSaved_[iRow] = rowUpper_[iRow] * rhsScale_ * rowUseScale_[iRow]; } } } } //----------------------------------------------------------------------------- /* Set a single column lower bound
Use -DBL_MAX for -infinity. */ void AbcSimplex::setColumnLower(int elementIndex, double elementValue) { #ifndef NDEBUG int n = numberColumns_; if (elementIndex < 0 || elementIndex >= n) { indexError(elementIndex, "setColumnLower"); } #endif if (elementValue < -1.0e27) elementValue = -COIN_DBL_MAX; if (columnLower_[elementIndex] != elementValue) { columnLower_[elementIndex] = elementValue; // work arrays exist - update as well whatsChanged_ &= ~COLUMN_LOWER_SAME; double value; if (columnLower_[elementIndex] == -COIN_DBL_MAX) { value = -COIN_DBL_MAX; } else { value = elementValue * rhsScale_ * inverseColumnUseScale_[elementIndex]; } lowerSaved_[elementIndex + maximumAbcNumberRows_] = value; } } /* Set a single column upper bound
Use DBL_MAX for infinity. */ void AbcSimplex::setColumnUpper(int elementIndex, double elementValue) { #ifndef NDEBUG int n = numberColumns_; if (elementIndex < 0 || elementIndex >= n) { indexError(elementIndex, "setColumnUpper"); } #endif if (elementValue > 1.0e27) elementValue = COIN_DBL_MAX; if (columnUpper_[elementIndex] != elementValue) { columnUpper_[elementIndex] = elementValue; // work arrays exist - update as well whatsChanged_ &= ~COLUMN_UPPER_SAME; double value; if (columnUpper_[elementIndex] == COIN_DBL_MAX) { value = COIN_DBL_MAX; } else { value = elementValue * rhsScale_ * inverseColumnUseScale_[elementIndex]; } upperSaved_[elementIndex + maximumAbcNumberRows_] = value; } } /* Set a single column lower and upper bound */ void AbcSimplex::setColumnBounds(int elementIndex, double lowerValue, double upperValue) { #ifndef NDEBUG int n = numberColumns_; if (elementIndex < 0 || elementIndex >= n) { indexError(elementIndex, "setColumnBounds"); } #endif if (lowerValue < -1.0e27) lowerValue = -COIN_DBL_MAX; if (columnLower_[elementIndex] != lowerValue) { columnLower_[elementIndex] = lowerValue; // work arrays exist - update as well whatsChanged_ &= ~COLUMN_LOWER_SAME; if (columnLower_[elementIndex] == -COIN_DBL_MAX) { lowerSaved_[elementIndex + maximumAbcNumberRows_] = -COIN_DBL_MAX; } else { lowerSaved_[elementIndex + maximumAbcNumberRows_] = lowerValue * rhsScale_ * inverseColumnUseScale_[elementIndex]; } } if (upperValue > 1.0e27) upperValue = COIN_DBL_MAX; if (columnUpper_[elementIndex] != upperValue) { columnUpper_[elementIndex] = upperValue; // work arrays exist - update as well whatsChanged_ &= ~COLUMN_UPPER_SAME; if (columnUpper_[elementIndex] == COIN_DBL_MAX) { upperSaved_[elementIndex + maximumAbcNumberRows_] = COIN_DBL_MAX; } else { upperSaved_[elementIndex + maximumAbcNumberRows_] = upperValue * rhsScale_ * inverseColumnUseScale_[elementIndex]; } } } void AbcSimplex::setColumnSetBounds(const int *indexFirst, const int *indexLast, const double *boundList) { #ifndef NDEBUG int n = numberColumns_; #endif int numberChanged = 0; const int *saveFirst = indexFirst; while (indexFirst != indexLast) { const int iColumn = *indexFirst++; #ifndef NDEBUG if (iColumn < 0 || iColumn >= n) { indexError(iColumn, "setColumnSetBounds"); } #endif double lowerValue = *boundList++; double upperValue = *boundList++; if (lowerValue < -1.0e27) lowerValue = -COIN_DBL_MAX; if (upperValue > 1.0e27) upperValue = COIN_DBL_MAX; //CoinAssert (upperValue>=lowerValue); if (columnLower_[iColumn] != lowerValue) { columnLower_[iColumn] = lowerValue; whatsChanged_ &= ~COLUMN_LOWER_SAME; numberChanged++; } if (columnUpper_[iColumn] != upperValue) { columnUpper_[iColumn] = upperValue; whatsChanged_ &= ~COLUMN_UPPER_SAME; numberChanged++; } } if (numberChanged) { indexFirst = saveFirst; while (indexFirst != indexLast) { const int iColumn = *indexFirst++; if (columnLower_[iColumn] == -COIN_DBL_MAX) { lowerSaved_[iColumn + maximumAbcNumberRows_] = -COIN_DBL_MAX; } else { lowerSaved_[iColumn + maximumAbcNumberRows_] = columnLower_[iColumn] * rhsScale_ * inverseColumnUseScale_[iColumn]; } if (columnUpper_[iColumn] == COIN_DBL_MAX) { upperSaved_[iColumn + maximumAbcNumberRows_] = COIN_DBL_MAX; } else { upperSaved_[iColumn + maximumAbcNumberRows_] = columnUpper_[iColumn] * rhsScale_ * inverseColumnUseScale_[iColumn]; } } } } #ifndef SLIM_CLP #include "CoinWarmStartBasis.hpp" // Returns a basis (to be deleted by user) CoinWarmStartBasis * AbcSimplex::getBasis() const { CoinWarmStartBasis *basis = new CoinWarmStartBasis(); basis->setSize(numberColumns_, numberRows_); unsigned char lookup[8] = { 2, 3, 255, 255, 0, 0, 1, 3 }; for (int iRow = 0; iRow < numberRows_; iRow++) { int iStatus = getInternalStatus(iRow); iStatus = lookup[iStatus]; basis->setArtifStatus(iRow, static_cast< CoinWarmStartBasis::Status >(iStatus)); } for (int iColumn = 0; iColumn < numberColumns_; iColumn++) { int iStatus = getInternalStatus(iColumn + maximumAbcNumberRows_); iStatus = lookup[iStatus]; basis->setStructStatus(iColumn, static_cast< CoinWarmStartBasis::Status >(iStatus)); } return basis; } #endif // Compute objective value from solution void AbcSimplex::computeObjectiveValue(bool useInternalArrays) { const double *obj = objective(); if (!useInternalArrays) { objectiveValue_ = 0.0; for (int iSequence = 0; iSequence < numberColumns_; iSequence++) { double value = columnActivity_[iSequence]; objectiveValue_ += value * obj[iSequence]; } // But remember direction as we are using external objective objectiveValue_ *= optimizationDirection_; } else { rawObjectiveValue_ = 0.0; for (int iSequence = maximumAbcNumberRows_; iSequence < numberTotal_; iSequence++) { double value = abcSolution_[iSequence]; rawObjectiveValue_ += value * abcCost_[iSequence]; } setClpSimplexObjectiveValue(); } } // Compute minimization objective value from internal solution double AbcSimplex::computeInternalObjectiveValue() { rawObjectiveValue_ = 0.0; for (int iSequence = maximumAbcNumberRows_; iSequence < numberTotal_; iSequence++) { double value = abcSolution_[iSequence]; rawObjectiveValue_ += value * abcCost_[iSequence]; } setClpSimplexObjectiveValue(); return objectiveValue_ - dblParam_[ClpObjOffset]; } // If user left factorization frequency then compute void AbcSimplex::defaultFactorizationFrequency() { if (factorizationFrequency() == 200) { // User did not touch preset const int cutoff1 = 10000; const int cutoff2 = 100000; const int base = 75; const int freq0 = 50; const int freq1 = 150; const int maximum = 10000; int frequency; if (numberRows_ < cutoff1) frequency = base + numberRows_ / freq0; else frequency = base + cutoff1 / freq0 + (numberRows_ - cutoff1) / freq1; setFactorizationFrequency(CoinMin(maximum, frequency)); } } // Gets clean and emptyish factorization AbcSimplexFactorization * AbcSimplex::getEmptyFactorization() { if ((specialOptions_ & 65536) == 0) { assert(!abcFactorization_); abcFactorization_ = new AbcSimplexFactorization(); } else if (!abcFactorization_) { abcFactorization_ = new AbcSimplexFactorization(); } return abcFactorization_; } // Resizes rim part of model void AbcSimplex::resize(int newNumberRows, int newNumberColumns) { assert(maximumAbcNumberRows_ >= 0); // save int numberRows = numberRows_; int numberColumns = numberColumns_; ClpSimplex::resize(newNumberRows, newNumberColumns); // back out numberRows_ = numberRows; numberColumns_ = numberColumns; gutsOfResize(newNumberRows, newNumberColumns); } // Return true if the objective limit test can be relied upon bool AbcSimplex::isObjectiveLimitTestValid() const { if (problemStatus_ == 0) { return true; } else if (problemStatus_ == 1) { // ok if dual return (algorithm_ < 0); } else if (problemStatus_ == 2) { // ok if primal return (algorithm_ > 0); } else { return false; } } /* Permutes in from ClpModel data - assumes scale factors done and AbcMatrix exists but is in original order (including slacks) For now just add basicArray at end == But could partition into normal (i.e. reasonable lower/upper) abnormal - free, odd bounds fixed == sets a valid pivotVariable Slacks always shifted by offset Fixed variables always shifted by offset Recode to allow row objective so can use pi from idiot etc */ void AbcSimplex::permuteIn() { // for now only if maximumAbcNumberRows_==numberRows_ //assert(maximumAbcNumberRows_==numberRows_); numberTotal_ = maximumAbcNumberRows_ + numberColumns_; double direction = optimizationDirection_; // all this could use cilk // move primal stuff to end const double *COIN_RESTRICT rowScale = scaleFromExternal_; const double *COIN_RESTRICT inverseRowScale = scaleToExternal_; const double *COIN_RESTRICT columnScale = scaleToExternal_ + maximumAbcNumberRows_; const double *COIN_RESTRICT inverseColumnScale = scaleFromExternal_ + maximumAbcNumberRows_; double *COIN_RESTRICT offsetRhs = offsetRhs_; double *COIN_RESTRICT saveLower = lowerSaved_ + maximumAbcNumberRows_; double *COIN_RESTRICT saveUpper = upperSaved_ + maximumAbcNumberRows_; double *COIN_RESTRICT saveCost = costSaved_ + maximumAbcNumberRows_; double *COIN_RESTRICT saveSolution = solutionSaved_ + maximumAbcNumberRows_; CoinAbcMemset0(offsetRhs, maximumAbcNumberRows_); const double *COIN_RESTRICT objective = this->objective(); objectiveOffset_ = 0.0; double *COIN_RESTRICT offset = offset_ + maximumAbcNumberRows_; const int *COIN_RESTRICT row = abcMatrix_->matrix()->getIndices(); const CoinBigIndex *COIN_RESTRICT columnStart = abcMatrix_->matrix()->getVectorStarts(); const double *COIN_RESTRICT elementByColumn = abcMatrix_->matrix()->getElements(); largestGap_ = 1.0e-12; for (int iColumn = 0; iColumn < numberColumns_; iColumn++) { double scale = inverseColumnScale[iColumn]; double lowerValue = columnLower_[iColumn]; double upperValue = columnUpper_[iColumn]; double thisOffset = 0.0; #if 1 //ndef CLP_USER_DRIVEN double lowerValue2 = fabs(lowerValue); double upperValue2 = fabs(upperValue); if (CoinMin(lowerValue2, upperValue2) < 1000.0) { // move to zero if (lowerValue2 > upperValue2) thisOffset = upperValue; else thisOffset = lowerValue; } #endif offset[iColumn] = thisOffset; if (thisOffset) { objectiveOffset_ += thisOffset * objective[iColumn] * optimizationDirection_; double scaledOffset = thisOffset * scale; for (CoinBigIndex j = columnStart[iColumn]; j < columnStart[iColumn + 1]; j++) { int iRow = row[j]; offsetRhs[iRow] += scaledOffset * elementByColumn[j]; } } lowerValue -= thisOffset; if (lowerValue > -1.0e30) lowerValue *= scale; saveLower[iColumn] = lowerValue; upperValue -= thisOffset; if (upperValue < 1.0e30) upperValue *= scale; saveUpper[iColumn] = upperValue; largestGap_ = CoinMax(largestGap_, upperValue - lowerValue); saveSolution[iColumn] = scale * (columnActivity_[iColumn] - thisOffset); saveCost[iColumn] = objective[iColumn] * direction * columnScale[iColumn]; } CoinAbcMemset0(offset_, maximumAbcNumberRows_); saveLower -= maximumAbcNumberRows_; saveUpper -= maximumAbcNumberRows_; saveCost -= maximumAbcNumberRows_; saveSolution -= maximumAbcNumberRows_; for (int iRow = 0; iRow < numberRows_; iRow++) { // note switch of lower to upper double upperValue = -rowLower_[iRow]; double lowerValue = -rowUpper_[iRow]; double thisOffset = offsetRhs_[iRow]; double scale = rowScale[iRow]; if (lowerValue > -1.0e30) lowerValue = lowerValue * scale + thisOffset; saveLower[iRow] = lowerValue; if (upperValue < 1.0e30) upperValue = upperValue * scale + thisOffset; saveUpper[iRow] = upperValue; largestGap_ = CoinMax(largestGap_, upperValue - lowerValue); saveCost[iRow] = 0.0; dual_[iRow] *= direction * inverseRowScale[iRow]; saveSolution[iRow] = 0.0; // not necessary } dualBound_ = CoinMin(dualBound_, largestGap_); // Compute rhsScale_ and objectiveScale_ double minValue = COIN_DBL_MAX; double maxValue = 0.0; CoinAbcMinMaxAbsNormalValues(costSaved_ + maximumAbcNumberRows_, numberTotal_ - maximumAbcNumberRows_, minValue, maxValue); // scale to 1000.0 ? if (minValue && false) { objectiveScale_ = 1000.0 / sqrt(minValue * maxValue); objectiveScale_ = CoinMin(1.0, 1000.0 / maxValue); #ifndef NDEBUG double smallestNormal = COIN_DBL_MAX; double smallestAny = COIN_DBL_MAX; double largestAny = 0.0; for (int i = 0; i < numberTotal_; i++) { double value = fabs(costSaved_[i]); if (value) { if (value > 1.0e-8) smallestNormal = CoinMin(smallestNormal, value); smallestAny = CoinMin(smallestAny, value); largestAny = CoinMax(largestAny, value); } } printf("objectiveScale_ %g min_used %g (min_reasonable %g, min_any %g) max_used %g (max_any %g)\n", objectiveScale_, minValue, smallestNormal, smallestAny, maxValue, largestAny); #endif } else { //objectiveScale_=1.0; } CoinAbcScale(costSaved_, objectiveScale_, numberTotal_); minValue = COIN_DBL_MAX; maxValue = 0.0; CoinAbcMinMaxAbsNormalValues(lowerSaved_, numberTotal_, minValue, maxValue); CoinAbcMinMaxAbsNormalValues(upperSaved_, numberTotal_, minValue, maxValue); // scale to 100.0 ? if (minValue && false) { rhsScale_ = 100.0 / sqrt(minValue * maxValue); #ifndef NDEBUG double smallestNormal = COIN_DBL_MAX; double smallestAny = COIN_DBL_MAX; double largestAny = 0.0; for (int i = 0; i < numberTotal_; i++) { double value = fabs(lowerSaved_[i]); if (value && value != COIN_DBL_MAX) { if (value > 1.0e-8) smallestNormal = CoinMin(smallestNormal, value); smallestAny = CoinMin(smallestAny, value); largestAny = CoinMax(largestAny, value); } } for (int i = 0; i < numberTotal_; i++) { double value = fabs(upperSaved_[i]); if (value && value != COIN_DBL_MAX) { if (value > 1.0e-8) smallestNormal = CoinMin(smallestNormal, value); smallestAny = CoinMin(smallestAny, value); largestAny = CoinMax(largestAny, value); } } printf("rhsScale_ %g min_used %g (min_reasonable %g, min_any %g) max_used %g (max_any %g)\n", rhsScale_, minValue, smallestNormal, smallestAny, maxValue, largestAny); #endif } else { rhsScale_ = 1.0; } CoinAbcScaleNormalValues(lowerSaved_, rhsScale_, 1.0e-13, numberTotal_); CoinAbcScaleNormalValues(upperSaved_, rhsScale_, 1.0e-13, numberTotal_); // copy CoinAbcMemcpy(abcLower_, abcLower_ + maximumNumberTotal_, numberTotal_); CoinAbcMemcpy(abcUpper_, abcUpper_ + maximumNumberTotal_, numberTotal_); CoinAbcMemcpy(abcSolution_, abcSolution_ + maximumNumberTotal_, numberTotal_); CoinAbcMemcpy(abcCost_, abcCost_ + maximumNumberTotal_, numberTotal_); } void AbcSimplex::permuteBasis() { assert(abcPivotVariable_ || (!numberRows_ && !numberColumns_)); int numberBasic = 0; // from Clp enum to Abc enum (and bound flip) unsigned char lookupToAbcSlack[6] = { 4, 6, 0 /*1*/, 1 /*0*/, 5, 7 }; unsigned char *COIN_RESTRICT getStatus = status_ + numberColumns_; double *COIN_RESTRICT solutionSaved = solutionSaved_; double *COIN_RESTRICT lowerSaved = lowerSaved_; double *COIN_RESTRICT upperSaved = upperSaved_; bool ordinaryVariables = true; bool valuesPass = (stateOfProblem_ & VALUES_PASS) != 0; if (valuesPass) { // get solution CoinAbcMemset0(abcSolution_, numberRows_); abcMatrix_->timesIncludingSlacks(-1.0, abcSolution_, abcSolution_); //double * temp = new double[numberRows_]; //memset(temp,0,numberRows_*sizeof(double)); //matrix_->times(1.0,columnActivity_,temp); CoinAbcMemcpy(solutionSaved_, abcSolution_, numberRows_); int n = 0; for (int i = 0; i < numberTotal_; i++) { if (solutionSaved_[i] > upperSaved_[i] + 1.0e-5) n++; else if (solutionSaved_[i] < lowerSaved_[i] - 1.0e-5) n++; } #if ABC_NORMAL_DEBUG > 0 if (n) printf("%d infeasibilities\n", n); #endif } // dual at present does not like superbasic for (int iRow = 0; iRow < numberRows_; iRow++) { unsigned char status = getStatus[iRow] & 7; AbcSimplex::Status abcStatus = static_cast< AbcSimplex::Status >(lookupToAbcSlack[status]); if (status != ClpSimplex::basic) { double lowerValue = lowerSaved[iRow]; double upperValue = upperSaved[iRow]; if (lowerValue == -COIN_DBL_MAX) { if (upperValue == COIN_DBL_MAX) { // free abcStatus = isFree; ordinaryVariables = false; } else { abcStatus = atUpperBound; } } else if (upperValue == COIN_DBL_MAX) { abcStatus = atLowerBound; } else if (lowerValue == upperValue) { abcStatus = isFixed; } else if (abcStatus == isFixed) { double value = solutionSaved[iRow]; if (value - lowerValue < upperValue - value) abcStatus = atLowerBound; else abcStatus = atUpperBound; } if (valuesPass) { double value = solutionSaved[iRow]; if (value > lowerValue + primalTolerance_ && value < upperValue - primalTolerance_ && (abcStatus == atLowerBound || abcStatus == atUpperBound)) abcStatus = superBasic; } switch (abcStatus) { case isFixed: case atLowerBound: solutionSaved[iRow] = lowerValue; break; case atUpperBound: solutionSaved[iRow] = upperValue; break; default: ordinaryVariables = false; break; } } else { // basic abcPivotVariable_[numberBasic++] = iRow; } internalStatus_[iRow] = abcStatus; } // from Clp enum to Abc enum unsigned char lookupToAbc[6] = { 4, 6, 1, 0, 5, 7 }; unsigned char *COIN_RESTRICT putStatus = internalStatus_ + maximumAbcNumberRows_; getStatus = status_; solutionSaved += maximumAbcNumberRows_; lowerSaved += maximumAbcNumberRows_; upperSaved += maximumAbcNumberRows_; for (int iColumn = 0; iColumn < numberColumns_; iColumn++) { unsigned char status = getStatus[iColumn] & 7; AbcSimplex::Status abcStatus = static_cast< AbcSimplex::Status >(lookupToAbc[status]); if (status != ClpSimplex::basic) { double lowerValue = lowerSaved[iColumn]; double upperValue = upperSaved[iColumn]; if (lowerValue == -COIN_DBL_MAX) { if (upperValue == COIN_DBL_MAX) { // free abcStatus = isFree; ordinaryVariables = false; } else { abcStatus = atUpperBound; } } else if (upperValue == COIN_DBL_MAX) { abcStatus = atLowerBound; } else if (lowerValue == upperValue) { abcStatus = isFixed; } else if (abcStatus == isFixed) { double value = solutionSaved[iColumn]; if (value - lowerValue < upperValue - value) abcStatus = atLowerBound; else abcStatus = atUpperBound; } else if (abcStatus == isFree) { abcStatus = superBasic; } if (valuesPass && (abcStatus == atLowerBound || abcStatus == atUpperBound)) { double value = solutionSaved[iColumn]; if (value > lowerValue + primalTolerance_) { if (value < upperValue - primalTolerance_) { abcStatus = superBasic; } else { abcStatus = atUpperBound; } } else { abcStatus = atLowerBound; } } switch (abcStatus) { case isFixed: case atLowerBound: solutionSaved[iColumn] = lowerValue; break; case atUpperBound: solutionSaved[iColumn] = upperValue; break; default: ordinaryVariables = false; break; } } else { // basic if (numberBasic < numberRows_) abcPivotVariable_[numberBasic++] = iColumn + maximumAbcNumberRows_; else abcStatus = superBasic; } putStatus[iColumn] = abcStatus; } ordinaryVariables_ = ordinaryVariables ? 1 : 0; if (numberBasic < numberRows_) { for (int iRow = 0; iRow < numberRows_; iRow++) { AbcSimplex::Status status = getInternalStatus(iRow); if (status != AbcSimplex::basic) { abcPivotVariable_[numberBasic++] = iRow; setInternalStatus(iRow, basic); if (numberBasic == numberRows_) break; } } } // copy CoinAbcMemcpy(internalStatus_ + maximumNumberTotal_, internalStatus_, numberTotal_); } // Permutes out - bit settings same as stateOfProblem void AbcSimplex::permuteOut(int whatsWanted) { assert(whatsWanted); if ((whatsWanted & ALL_STATUS_OK) != 0 && (stateOfProblem_ & ALL_STATUS_OK) == 0) { stateOfProblem_ |= ALL_STATUS_OK; // from Abc enum to Clp enum (and bound flip) unsigned char lookupToClpSlack[8] = { 2, 3, 255, 255, 0, 0, 1, 5 }; unsigned char *COIN_RESTRICT putStatus = status_ + numberColumns_; const unsigned char *COIN_RESTRICT getStatus = internalStatus_; for (int iRow = 0; iRow < numberRows_; iRow++) { putStatus[iRow] = lookupToClpSlack[getStatus[iRow] & 7]; } // from Abc enum to Clp enum unsigned char lookupToClp[8] = { 3, 2, 255, 255, 0, 0, 1, 5 }; putStatus = status_; getStatus = internalStatus_ + maximumAbcNumberRows_; for (int iColumn = 0; iColumn < numberColumns_; iColumn++) { putStatus[iColumn] = lookupToClp[getStatus[iColumn] & 7]; } } const double *COIN_RESTRICT rowScale = scaleFromExternal_; const double *COIN_RESTRICT inverseRowScale = scaleToExternal_; const double *COIN_RESTRICT columnScale = scaleToExternal_; // allow for offset in loop +maximumAbcNumberRows_; const double *COIN_RESTRICT inverseColumnScale = scaleFromExternal_; // allow for offset in loop +maximumAbcNumberRows_; double scaleC = 1.0 / objectiveScale_; double scaleR = 1.0 / rhsScale_; int numberPrimalScaled = 0; int numberPrimalUnscaled = 0; int numberDualScaled = 0; int numberDualUnscaled = 0; bool filledInSolution = false; if ((whatsWanted & ROW_PRIMAL_OK) != 0 && (stateOfProblem_ & ROW_PRIMAL_OK) == 0) { stateOfProblem_ |= ROW_PRIMAL_OK; if (!filledInSolution) { filledInSolution = true; CoinAbcScatterTo(solutionBasic_, abcSolution_, abcPivotVariable_, numberRows_); CoinAbcScatterZeroTo(abcDj_, abcPivotVariable_, numberRows_); } // Collect infeasibilities double *COIN_RESTRICT putSolution = rowActivity_; const double *COIN_RESTRICT rowLower = rowLower_; const double *COIN_RESTRICT rowUpper = rowUpper_; const double *COIN_RESTRICT abcLower = abcLower_; const double *COIN_RESTRICT abcUpper = abcUpper_; const double *COIN_RESTRICT abcSolution = abcSolution_; const double *COIN_RESTRICT offsetRhs = offsetRhs_; for (int i = 0; i < numberRows_; i++) { double scaleFactor = inverseRowScale[i]; double valueScaled = abcSolution[i]; double lowerScaled = abcLower[i]; double upperScaled = abcUpper[i]; if (lowerScaled > -1.0e20 || upperScaled < 1.0e20) { if (valueScaled < lowerScaled - primalTolerance_ || valueScaled > upperScaled + primalTolerance_) numberPrimalScaled++; else upperOut_ = CoinMax(upperOut_, CoinMin(valueScaled - lowerScaled, upperScaled - valueScaled)); } double value = (offsetRhs[i] - valueScaled * scaleR) * scaleFactor; putSolution[i] = value; if (value < rowLower[i] - primalTolerance_) numberPrimalUnscaled++; else if (value > rowUpper[i] + primalTolerance_) numberPrimalUnscaled++; } } if ((whatsWanted & COLUMN_PRIMAL_OK) != 0 && (stateOfProblem_ & COLUMN_PRIMAL_OK) == 0) { stateOfProblem_ |= COLUMN_PRIMAL_OK; // Collect infeasibilities if (!filledInSolution) { filledInSolution = true; CoinAbcScatterTo(solutionBasic_, abcSolution_, abcPivotVariable_, numberRows_); CoinAbcScatterZeroTo(abcDj_, abcPivotVariable_, numberRows_); } // Collect infeasibilities double *COIN_RESTRICT putSolution = columnActivity_ - maximumAbcNumberRows_; const double *COIN_RESTRICT columnLower = columnLower_ - maximumAbcNumberRows_; const double *COIN_RESTRICT columnUpper = columnUpper_ - maximumAbcNumberRows_; for (int i = maximumAbcNumberRows_; i < numberTotal_; i++) { double scaleFactor = columnScale[i]; double valueScaled = abcSolution_[i]; double lowerScaled = abcLower_[i]; double upperScaled = abcUpper_[i]; if (lowerScaled > -1.0e20 || upperScaled < 1.0e20) { if (valueScaled < lowerScaled - primalTolerance_ || valueScaled > upperScaled + primalTolerance_) numberPrimalScaled++; else upperOut_ = CoinMax(upperOut_, CoinMin(valueScaled - lowerScaled, upperScaled - valueScaled)); } double value = (valueScaled * scaleR) * scaleFactor + offset_[i]; putSolution[i] = value; if (value < columnLower[i] - primalTolerance_) numberPrimalUnscaled++; else if (value > columnUpper[i] + primalTolerance_) numberPrimalUnscaled++; } } if ((whatsWanted & COLUMN_DUAL_OK) != 0 && (stateOfProblem_ & COLUMN_DUAL_OK) == 0) { // Get fixed djs CoinAbcMemcpy(abcDj_, abcCost_, numberTotal_); abcMatrix_->transposeTimesAll(dual_, abcDj_); stateOfProblem_ |= COLUMN_DUAL_OK; // Collect infeasibilities double *COIN_RESTRICT putDj = reducedCost_ - maximumAbcNumberRows_; for (int i = maximumAbcNumberRows_; i < numberTotal_; i++) { double scaleFactor = inverseColumnScale[i]; double valueDual = abcDj_[i]; double value = abcSolution_[i]; bool aboveLower = value > abcLower_[i] + primalTolerance_; bool belowUpper = value < abcUpper_[i] - primalTolerance_; if (aboveLower && valueDual > dualTolerance_) numberDualScaled++; if (belowUpper && valueDual < -dualTolerance_) numberDualScaled++; valueDual *= scaleFactor * scaleC; putDj[i] = valueDual; if (aboveLower && valueDual > dualTolerance_) numberDualUnscaled++; if (belowUpper && valueDual < -dualTolerance_) numberDualUnscaled++; } } if ((whatsWanted & ROW_DUAL_OK) != 0 && (stateOfProblem_ & ROW_DUAL_OK) == 0) { stateOfProblem_ |= ROW_DUAL_OK; // Collect infeasibilities for (int i = 0; i < numberRows_; i++) { double scaleFactor = rowScale[i]; double valueDual = abcDj_[i]; // ? +- and direction double value = abcSolution_[i]; bool aboveLower = value > abcLower_[i] + primalTolerance_; bool belowUpper = value < abcUpper_[i] - primalTolerance_; if (aboveLower && valueDual > dualTolerance_) numberDualScaled++; if (belowUpper && valueDual < -dualTolerance_) numberDualScaled++; valueDual *= scaleFactor * scaleC; dual_[i] = -(valueDual - abcCost_[i]); // sign if (aboveLower && valueDual > dualTolerance_) numberDualUnscaled++; if (belowUpper && valueDual < -dualTolerance_) numberDualUnscaled++; } } // do after djs if (!problemStatus_ && (!secondaryStatus_ || secondaryStatus_ == 2 || secondaryStatus_ == 3)) { // See if we need to set secondary status if (numberPrimalUnscaled) { if (numberDualUnscaled || secondaryStatus_ == 3) secondaryStatus_ = 4; else secondaryStatus_ = 2; } else if (numberDualUnscaled) { if (secondaryStatus_ == 0) secondaryStatus_ = 3; else secondaryStatus_ = 4; } } if (scalingFlag_) { if (problemStatus_ == 2) { for (int i = 0; i < numberColumns_; i++) { ray_[i] *= columnScale[i]; } } else if (problemStatus_ == 1 && ray_) { for (int i = 0; i < numberRows_; i++) { ray_[i] *= rowScale[i]; } } } } #if ABC_DEBUG > 1 // For debug - moves solution back to external and computes stuff void AbcSimplex::checkMoveBack(bool checkDuals) { stateOfProblem_ &= ~(ROW_PRIMAL_OK | ROW_DUAL_OK | COLUMN_PRIMAL_OK | COLUMN_DUAL_OK | ALL_STATUS_OK); permuteOut(ROW_PRIMAL_OK | ROW_DUAL_OK | COLUMN_PRIMAL_OK | COLUMN_DUAL_OK | ALL_STATUS_OK); ClpSimplex::computeObjectiveValue(false); #if ABC_NORMAL_DEBUG > 0 printf("Check objective %g\n", objectiveValue() - objectiveOffset_); #endif double *region = new double[numberRows_ + numberColumns_]; CoinAbcMemset0(region, numberRows_); ClpModel::times(1.0, columnActivity_, region); int numberInf; double sumInf; numberInf = 0; sumInf = 0.0; for (int i = 0; i < numberColumns_; i++) { if (columnActivity_[i] > columnUpper_[i] + 1.0e-7) { numberInf++; sumInf += columnActivity_[i] - columnUpper_[i]; } else if (columnActivity_[i] < columnLower_[i] - 1.0e-7) { numberInf++; sumInf -= columnActivity_[i] - columnLower_[i]; } } #if ABC_NORMAL_DEBUG > 0 if (numberInf) printf("Check column infeasibilities %d sum %g\n", numberInf, sumInf); #endif numberInf = 0; sumInf = 0.0; for (int i = 0; i < numberRows_; i++) { if (rowActivity_[i] > rowUpper_[i] + 1.0e-7) { numberInf++; sumInf += rowActivity_[i] - rowUpper_[i]; } else if (rowActivity_[i] < rowLower_[i] - 1.0e-7) { numberInf++; sumInf -= rowActivity_[i] - rowLower_[i]; } } #if ABC_NORMAL_DEBUG > 0 if (numberInf) printf("Check row infeasibilities %d sum %g\n", numberInf, sumInf); #endif CoinAbcMemcpy(region, objective(), numberColumns_); ClpModel::transposeTimes(-1.0, dual_, region); numberInf = 0; sumInf = 0.0; for (int i = 0; i < numberColumns_; i++) { if (columnUpper_[i] > columnLower_[i]) { if (getColumnStatus(i) == ClpSimplex::atLowerBound) { if (region[i] < -1.0e-7) { numberInf++; sumInf -= region[i]; } } else if (getColumnStatus(i) == ClpSimplex::atUpperBound) { if (region[i] > 1.0e-7) { numberInf++; sumInf += region[i]; } } } } #if ABC_NORMAL_DEBUG > 0 if (numberInf) printf("Check column dj infeasibilities %d sum %g\n", numberInf, sumInf); #endif if (checkDuals) { numberInf = 0; sumInf = 0.0; for (int i = 0; i < numberRows_; i++) { if (rowUpper_[i] > rowLower_[i]) { if (getRowStatus(i) == ClpSimplex::atLowerBound) { if (dual_[i] < -1.0e-7) { numberInf++; sumInf -= region[i]; } } else if (getRowStatus(i) == ClpSimplex::atUpperBound) { if (dual_[i] > 1.0e-7) { numberInf++; sumInf += region[i]; } } } } #if ABC_NORMAL_DEBUG > 0 if (numberInf) printf("Check row dual infeasibilities %d sum %g\n", numberInf, sumInf); #endif } delete[] region; } #if 0 void xxxxxx(const char * where) { printf("xxxxx %s\n",where); } #endif // For debug - checks solutionBasic void AbcSimplex::checkSolutionBasic() const { //work space int whichArray[2]; for (int i = 0; i < 2; i++) whichArray[i] = getAvailableArray(); CoinIndexedVector *arrayVector = &usefulArray_[whichArray[0]]; double *solution = usefulArray_[whichArray[1]].denseVector(); CoinAbcMemcpy(solution, abcSolution_, numberTotal_); // accumulate non basic stuff double *array = arrayVector->denseVector(); CoinAbcScatterZeroTo(solution, abcPivotVariable_, numberRows_); abcMatrix_->timesIncludingSlacks(-1.0, solution, array); //arrayVector->scan(0,numberRows_,zeroTolerance_); // Ftran adjusted RHS //if (arrayVector->getNumElements()) abcFactorization_->updateFullColumn(*arrayVector); CoinAbcScatterTo(array, solution, abcPivotVariable_, numberRows_); double largestDifference = 0.0; int whichDifference = -1; for (int i = 0; i < numberRows_; i++) { double difference = fabs(solutionBasic_[i] - array[i]); if (difference > 1.0e-5 && numberRows_ < 100) printf("solutionBasic difference is %g on row %d solutionBasic_ %g computed %g\n", difference, i, solutionBasic_[i], array[i]); if (difference > largestDifference) { largestDifference = difference; whichDifference = i; } } if (largestDifference > 1.0e-9) printf("Debug largest solutionBasic difference is %g on row %d solutionBasic_ %g computed %g\n", largestDifference, whichDifference, solutionBasic_[whichDifference], array[whichDifference]); arrayVector->clear(); CoinAbcMemset0(solution, numberTotal_); for (int i = 0; i < 2; i++) setAvailableArray(whichArray[i]); } // For debug - summarizes dj situation void AbcSimplex::checkDjs(int type) const { if (type) { //work space int whichArrays[2]; for (int i = 0; i < 2; i++) whichArrays[i] = getAvailableArray(); CoinIndexedVector *arrayVector = &usefulArray_[whichArrays[0]]; double *array = arrayVector->denseVector(); int *index = arrayVector->getIndices(); int number = 0; for (int iRow = 0; iRow < numberRows_; iRow++) { double value = costBasic_[iRow]; if (value) { array[iRow] = value; index[number++] = iRow; } } arrayVector->setNumElements(number); // Btran basic costs abcFactorization_->updateFullColumnTranspose(*arrayVector); double largestDifference = 0.0; int whichDifference = -1; if (type == 2) { for (int i = 0; i < numberRows_; i++) { double difference = fabs(dual_[i] - array[i]); if (difference > largestDifference) { largestDifference = difference; whichDifference = i; } } if (largestDifference > 1.0e-9) printf("Debug largest dual difference is %g on row %d dual_ %g computed %g\n", largestDifference, whichDifference, dual_[whichDifference], array[whichDifference]); } // now look at djs double *djs = usefulArray_[whichArrays[1]].denseVector(); CoinAbcMemcpy(djs, abcCost_, numberTotal_); abcMatrix_->transposeTimesNonBasic(-1.0, array, djs); largestDifference = 0.0; whichDifference = -1; for (int i = 0; i < numberTotal_; i++) { Status status = getInternalStatus(i); double difference = fabs(abcDj_[i] - djs[i]); switch (status) { case basic: // probably not an error break; case AbcSimplex::isFixed: break; case isFree: case superBasic: case atUpperBound: case atLowerBound: if (difference > 1.0e-5 && numberTotal_ < 200) printf("Debug dj difference is %g on column %d abcDj_ %g computed %g\n", difference, i, abcDj_[i], djs[i]); if (difference > largestDifference) { largestDifference = difference; whichDifference = i; } break; } } if (largestDifference > 1.0e-9) printf("Debug largest dj difference is %g on column %d abcDj_ %g computed %g\n", largestDifference, whichDifference, abcDj_[whichDifference], djs[whichDifference]); CoinAbcMemset0(djs, numberTotal_); arrayVector->clear(); for (int i = 0; i < 2; i++) setAvailableArray(whichArrays[i]); } int state[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; int badT[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; //int badP[8]={0,0,0,0,0,0,0,0}; int numberInfeasibilities = 0; for (int i = 0; i < numberTotal_; i++) { int iStatus = internalStatus_[i] & 7; state[iStatus]++; Status status = getInternalStatus(i); double djValue = abcDj_[i]; double value = abcSolution_[i]; double lowerValue = abcLower_[i]; double upperValue = abcUpper_[i]; //double perturbationValue=abcPerturbation_[i]; switch (status) { case basic: // probably not an error if (fabs(djValue) > currentDualTolerance_) badT[iStatus]++; //if(fabs(djValue)>perturbationValue) //badP[iStatus]++; break; case AbcSimplex::isFixed: break; case isFree: case superBasic: if (fabs(djValue) > currentDualTolerance_) badT[iStatus]++; //if(fabs(djValue)>perturbationValue) //badP[iStatus]++; break; case atUpperBound: if (fabs(value - upperValue) > primalTolerance_) numberInfeasibilities++; if (djValue > currentDualTolerance_) badT[iStatus]++; //if(djValue>perturbationValue) //badP[iStatus]++; break; case atLowerBound: if (fabs(value - lowerValue) > primalTolerance_) numberInfeasibilities++; if (-djValue > currentDualTolerance_) badT[iStatus]++; //if(-djValue>perturbationValue) //badP[iStatus]++; break; } } if (numberInfeasibilities) printf("Debug %d variables away from bound when should be\n", numberInfeasibilities); int numberBad = 0; for (int i = 0; i < 8; i++) { numberBad += badT[i] /*+badP[i]*/; } if (numberBad) { const char *type[] = { "atLowerBound", "atUpperBound", "??", "??", "isFree", "superBasic", "basic", "isFixed" }; for (int i = 0; i < 8; i++) { if (state[i]) printf("Debug - %s %d total %d bad with tolerance %d bad with perturbation\n", type[i], state[i], badT[i], 0 /*badP[i]*/); } } } #else // For debug - moves solution back to external and computes stuff void AbcSimplex::checkMoveBack(bool) { } // For debug - checks solutionBasic void AbcSimplex::checkSolutionBasic() const { } // For debug - summarizes dj situation void AbcSimplex::checkDjs(int) const { } #endif #ifndef EARLY_FACTORIZE #define ABC_NUMBER_USEFUL_NORMAL ABC_NUMBER_USEFUL #else #define ABC_NUMBER_USEFUL_NORMAL ABC_NUMBER_USEFUL - 1 #endif static double *elAddress[ABC_NUMBER_USEFUL_NORMAL]; // For debug - prints summary of arrays which are out of kilter void AbcSimplex::checkArrays(int ignoreEmpty) const { if (!numberIterations_ || !elAddress[0]) { for (int i = 0; i < ABC_NUMBER_USEFUL_NORMAL; i++) elAddress[i] = usefulArray_[i].denseVector(); } else { if (elAddress[0] != usefulArray_[0].denseVector()) { printf("elAddress not zero and does not match??\n"); for (int i = 0; i < ABC_NUMBER_USEFUL_NORMAL; i++) elAddress[i] = usefulArray_[i].denseVector(); } for (int i = 0; i < ABC_NUMBER_USEFUL_NORMAL; i++) assert(elAddress[i] == usefulArray_[i].denseVector()); } for (int i = 0; i < ABC_NUMBER_USEFUL_NORMAL; i++) { int check = 1 << i; if (usefulArray_[i].getNumElements()) { if ((stateOfProblem_ & check) == 0) printf("Array %d has %d elements but says it is available!\n", i, usefulArray_[i].getNumElements()); if (usefulArray_[i].getNumPartitions()) usefulArray_[i].checkClean(); else usefulArray_[i].CoinIndexedVector::checkClean(); } else { if ((stateOfProblem_ & check) != 0 && (ignoreEmpty & check) == 0) printf("Array %d has no elements but says it is not available\n", i); if (usefulArray_[i].getNumPartitions()) usefulArray_[i].checkClear(); else usefulArray_[i].CoinIndexedVector::checkClear(); } } } #include "CoinAbcCommon.hpp" #if 0 #include "ClpFactorization.hpp" // Loads tolerances etc void ClpSimplex::loadTolerancesEtc(const AbcTolerancesEtc & data) { zeroTolerance_ = data.zeroTolerance_; primalToleranceToGetOptimal_ = data.primalToleranceToGetOptimal_; largeValue_ = data.largeValue_; alphaAccuracy_ = data.alphaAccuracy_; dualBound_ = data.dualBound_; dualTolerance_ = data.dualTolerance_; primalTolerance_ = data.primalTolerance_; infeasibilityCost_ = data.infeasibilityCost_; incomingInfeasibility_ = data.incomingInfeasibility_; allowedInfeasibility_ = data.allowedInfeasibility_; baseIteration_ = data.baseIteration_; numberRefinements_ = data.numberRefinements_; forceFactorization_ = data.forceFactorization_; perturbation_ = data.perturbation_; dontFactorizePivots_ = data.dontFactorizePivots_; /// For factorization abcFactorization_->maximumPivots(data.maximumPivots_); } // Loads tolerances etc void ClpSimplex::unloadTolerancesEtc(AbcTolerancesEtc & data) { data.zeroTolerance_ = zeroTolerance_; data.primalToleranceToGetOptimal_ = primalToleranceToGetOptimal_; data.largeValue_ = largeValue_; data.alphaAccuracy_ = alphaAccuracy_; data.dualBound_ = dualBound_; data.dualTolerance_ = dualTolerance_; data.primalTolerance_ = primalTolerance_; data.infeasibilityCost_ = infeasibilityCost_; data.incomingInfeasibility_ = incomingInfeasibility_; data.allowedInfeasibility_ = allowedInfeasibility_; data.baseIteration_ = baseIteration_; data.numberRefinements_ = numberRefinements_; data.forceFactorization_ = forceFactorization_; data.perturbation_ = perturbation_; data.dontFactorizePivots_ = dontFactorizePivots_; /// For factorization data.maximumPivots_ = abcFactorization_->maximumPivots(); } // Loads tolerances etc void AbcSimplex::loadTolerancesEtc(const AbcTolerancesEtc & data) { zeroTolerance_ = data.zeroTolerance_; primalToleranceToGetOptimal_ = data.primalToleranceToGetOptimal_; largeValue_ = data.largeValue_; alphaAccuracy_ = data.alphaAccuracy_; dualBound_ = data.dualBound_; dualTolerance_ = data.dualTolerance_; primalTolerance_ = data.primalTolerance_; infeasibilityCost_ = data.infeasibilityCost_; incomingInfeasibility_ = data.incomingInfeasibility_; allowedInfeasibility_ = data.allowedInfeasibility_; baseIteration_ = data.baseIteration_; numberRefinements_ = data.numberRefinements_; forceFactorization_ = data.forceFactorization_; perturbation_ = data.perturbation_; dontFactorizePivots_ = data.dontFactorizePivots_; /// For factorization abcFactorization_->maximumPivots(data.maximumPivots_); } // Loads tolerances etc void AbcSimplex::unloadTolerancesEtc(AbcTolerancesEtc & data) { data.zeroTolerance_ = zeroTolerance_; data.primalToleranceToGetOptimal_ = primalToleranceToGetOptimal_; data.largeValue_ = largeValue_; data.alphaAccuracy_ = alphaAccuracy_; data.dualBound_ = dualBound_; data.dualTolerance_ = dualTolerance_; data.primalTolerance_ = primalTolerance_; data.infeasibilityCost_ = infeasibilityCost_; data.incomingInfeasibility_ = incomingInfeasibility_; data.allowedInfeasibility_ = allowedInfeasibility_; data.baseIteration_ = baseIteration_; data.numberRefinements_ = numberRefinements_; data.forceFactorization_ = forceFactorization_; data.perturbation_ = perturbation_; data.dontFactorizePivots_ = dontFactorizePivots_; /// For factorization data.maximumPivots_ = abcFactorization_->maximumPivots(); } #endif // Swaps two variables (for now just updates basic list) and sets status void AbcSimplex::swap(int pivotRow, int nonBasicPosition, Status newStatus) { // set status setInternalStatus(nonBasicPosition, newStatus); solutionBasic_[pivotRow] = abcSolution_[nonBasicPosition]; lowerBasic_[pivotRow] = abcLower_[nonBasicPosition]; upperBasic_[pivotRow] = abcUpper_[nonBasicPosition]; costBasic_[pivotRow] = abcCost_[nonBasicPosition]; } // Swaps two variables (for now just updates basic list) void AbcSimplex::swap(int pivotRow, int nonBasicPosition) { solutionBasic_[pivotRow] = abcSolution_[nonBasicPosition]; lowerBasic_[pivotRow] = lowerSaved_[nonBasicPosition]; upperBasic_[pivotRow] = upperSaved_[nonBasicPosition]; costBasic_[pivotRow] = abcCost_[nonBasicPosition]; } // Move status and solution to ClpSimplex void AbcSimplex::moveStatusToClp(ClpSimplex *clpModel) { assert(clpModel); if (algorithm_ < 0) clpModel->setObjectiveValue(clpObjectiveValue()); else clpModel->setObjectiveValue(objectiveValue()); clpModel->setProblemStatus(problemStatus_); clpModel->setSecondaryStatus(secondaryStatus_); clpModel->setNumberIterations(numberIterations_); clpModel->setSumDualInfeasibilities(sumDualInfeasibilities_); clpModel->setSumOfRelaxedDualInfeasibilities(sumOfRelaxedDualInfeasibilities_); clpModel->setNumberDualInfeasibilities(numberDualInfeasibilities_); clpModel->setSumPrimalInfeasibilities(sumPrimalInfeasibilities_); clpModel->setSumOfRelaxedPrimalInfeasibilities(sumOfRelaxedPrimalInfeasibilities_); clpModel->setNumberPrimalInfeasibilities(numberPrimalInfeasibilities_); permuteOut(ROW_PRIMAL_OK | ROW_DUAL_OK | COLUMN_PRIMAL_OK | COLUMN_DUAL_OK | ALL_STATUS_OK); CoinAbcMemcpy(clpModel->primalColumnSolution(), primalColumnSolution(), numberColumns_); CoinAbcMemcpy(clpModel->dualColumnSolution(), dualColumnSolution(), numberColumns_); CoinAbcMemcpy(clpModel->primalRowSolution(), primalRowSolution(), numberRows_); CoinAbcMemcpy(clpModel->dualRowSolution(), dualRowSolution(), numberRows_); CoinAbcMemcpy(clpModel->statusArray(), statusArray(), numberTotal_); } // Move status and solution from ClpSimplex void AbcSimplex::moveStatusFromClp(ClpSimplex *clpModel) { assert(clpModel); problemStatus_ = clpModel->problemStatus(); secondaryStatus_ = clpModel->secondaryStatus(); numberIterations_ = clpModel->numberIterations(); sumDualInfeasibilities_ = clpModel->sumDualInfeasibilities(); sumOfRelaxedDualInfeasibilities_ = clpModel->sumOfRelaxedDualInfeasibilities(); numberDualInfeasibilities_ = clpModel->numberDualInfeasibilities(); sumPrimalInfeasibilities_ = clpModel->sumPrimalInfeasibilities(); sumOfRelaxedPrimalInfeasibilities_ = clpModel->sumOfRelaxedPrimalInfeasibilities(); numberPrimalInfeasibilities_ = clpModel->numberPrimalInfeasibilities(); CoinAbcMemcpy(primalColumnSolution(), clpModel->primalColumnSolution(), numberColumns_); CoinAbcMemcpy(dualColumnSolution(), clpModel->dualColumnSolution(), numberColumns_); CoinAbcMemcpy(primalRowSolution(), clpModel->primalRowSolution(), numberRows_); CoinAbcMemcpy(dualRowSolution(), clpModel->dualRowSolution(), numberRows_); CoinAbcMemcpy(statusArray(), clpModel->statusArray(), numberTotal_); translate(DO_SCALE_AND_MATRIX | DO_BASIS_AND_ORDER | DO_STATUS | DO_SOLUTION); } // Clears an array and says available (-1 does all) void AbcSimplex::clearArrays(int which) { if (which >= 0) { if (usefulArray_[which].getNumElements()) usefulArray_[which].clear(); int check = 1 << which; stateOfProblem_ &= ~check; } else if (which == -1) { for (int i = 0; i < ABC_NUMBER_USEFUL_NORMAL; i++) { if (usefulArray_[i].getNumElements()) { usefulArray_[i].clear(); usefulArray_[i].clearAndReset(); } } stateOfProblem_ &= ~255; } else { for (int i = 0; i < ABC_NUMBER_USEFUL_NORMAL; i++) { usefulArray_[i].clearAndReset(); } stateOfProblem_ &= ~255; } } // Clears an array and says available void AbcSimplex::clearArrays(CoinPartitionedVector *which) { int check = 1; int i; for (i = 0; i < ABC_NUMBER_USEFUL_NORMAL; i++) { if (&usefulArray_[i] == which) { usefulArray_[i].clear(); stateOfProblem_ &= ~check; break; } check = check << 1; } assert(i < ABC_NUMBER_USEFUL_NORMAL); } // set multiple sequence in void AbcSimplex::setMultipleSequenceIn(int sequenceIn[4]) { memcpy(multipleSequenceIn_, sequenceIn, sizeof(multipleSequenceIn_)); } // Returns first available empty array (and sets flag) int AbcSimplex::getAvailableArray() const { int which; int status = 1; for (which = 0; which < ABC_NUMBER_USEFUL_NORMAL; which++) { if ((stateOfProblem_ & status) == 0) break; status = status << 1; } assert(which < ABC_NUMBER_USEFUL_NORMAL); assert(!usefulArray_[which].getNumElements()); stateOfProblem_ |= status; return which; } bool AbcSimplex::atFakeBound(int sequence) const { FakeBound status = getFakeBound(sequence); bool atBound = false; switch (status) { case noFake: break; case lowerFake: atBound = (getInternalStatus(sequence) == atLowerBound); break; case upperFake: atBound = (getInternalStatus(sequence) == atUpperBound); break; case bothFake: atBound = true; break; } return atBound; } AbcSimplexProgress::AbcSimplexProgress() : ClpSimplexProgress() { } //----------------------------------------------------------------------------- AbcSimplexProgress::~AbcSimplexProgress() { } // Copy constructor from model AbcSimplexProgress::AbcSimplexProgress(ClpSimplex *rhs) : ClpSimplexProgress(rhs) { } // Assignment operator. This copies the data AbcSimplexProgress & AbcSimplexProgress::operator=(const AbcSimplexProgress &rhs) { if (this != &rhs) { ClpSimplexProgress::operator=(rhs); } return *this; } int AbcSimplexProgress::looping() { if (!model_) return -1; #ifdef ABC_INHERIT AbcSimplex *model = model_->abcSimplex(); #else AbcSimplex *model; return -1; #endif double objective; if (model_->algorithm() < 0) { objective = model_->rawObjectiveValue(); objective -= model_->bestPossibleImprovement(); } else { objective = model->abcNonLinearCost()->feasibleReportCost(); } double infeasibility; double realInfeasibility = 0.0; int numberInfeasibilities; int iterationNumber = model->numberIterations(); //numberTimesFlagged_ = 0; if (model->algorithm() < 0) { // dual infeasibility = model->sumPrimalInfeasibilities(); numberInfeasibilities = model->numberPrimalInfeasibilities(); } else { //primal infeasibility = model->sumDualInfeasibilities(); realInfeasibility = model->abcNonLinearCost()->sumInfeasibilities(); numberInfeasibilities = model->numberDualInfeasibilities(); } int i; int numberMatched = 0; int matched = 0; int nsame = 0; for (i = 0; i < CLP_PROGRESS; i++) { bool matchedOnObjective = objective == objective_[i]; bool matchedOnInfeasibility = infeasibility == infeasibility_[i]; bool matchedOnInfeasibilities = (numberInfeasibilities == numberInfeasibilities_[i]); if (matchedOnObjective && matchedOnInfeasibility && matchedOnInfeasibilities) { matched |= (1 << i); // Check not same iteration if (iterationNumber != iterationNumber_[i]) { numberMatched++; #if ABC_NORMAL_DEBUG > 0 // here mainly to get over compiler bug? if (model->messageHandler()->logLevel() > 10) printf("%d %d %d %d %d loop check\n", i, numberMatched, matchedOnObjective, matchedOnInfeasibility, matchedOnInfeasibilities); #endif } else { // stuck but code should notice nsame++; } } if (i) { objective_[i - 1] = objective_[i]; infeasibility_[i - 1] = infeasibility_[i]; realInfeasibility_[i - 1] = realInfeasibility_[i]; numberInfeasibilities_[i - 1] = numberInfeasibilities_[i]; iterationNumber_[i - 1] = iterationNumber_[i]; } } objective_[CLP_PROGRESS - 1] = objective; infeasibility_[CLP_PROGRESS - 1] = infeasibility; realInfeasibility_[CLP_PROGRESS - 1] = realInfeasibility; numberInfeasibilities_[CLP_PROGRESS - 1] = numberInfeasibilities; iterationNumber_[CLP_PROGRESS - 1] = iterationNumber; if (nsame == CLP_PROGRESS) numberMatched = CLP_PROGRESS; // really stuck if (model->progressFlag()) numberMatched = 0; numberTimes_++; if (numberTimes_ < 10) numberMatched = 0; // skip if just last time as may be checking something if (matched == (1 << (CLP_PROGRESS - 1))) numberMatched = 0; if (numberMatched) { model->messageHandler()->message(CLP_POSSIBLELOOP, model->messages()) << numberMatched << matched << numberTimes_ << CoinMessageEol; printf("loop detected %d times out of %d\n", numberBadTimes_, numberTimes_); numberBadTimes_++; if (numberBadTimes_ < 10) { // make factorize every iteration model->forceFactorization(1); if (numberBadTimes_ < 2) { startCheck(); // clear other loop check if (model->algorithm() < 0) { // dual - change tolerance model->setCurrentDualTolerance(model->currentDualTolerance() * 1.05); // if infeasible increase dual bound if (model->currentDualBound() < 1.0e17) { model->setDualBound(model->currentDualBound() * 1.1); static_cast< AbcSimplexDual * >(model)->bounceTolerances(100); } } else { // primal - change tolerance if (numberBadTimes_ > 3) model->setCurrentPrimalTolerance(model->currentPrimalTolerance() * 1.05); // if infeasible increase infeasibility cost //if (model->nonLinearCost()->numberInfeasibilities() && // model->infeasibilityCost() < 1.0e17) { // model->setInfeasibilityCost(model->infeasibilityCost() * 1.1); //} } } else { // flag int iSequence; if (model->algorithm() < 0) { // dual if (model->currentDualBound() > 1.0e14) model->setDualBound(1.0e14); iSequence = in_[CLP_CYCLE - 1]; } else { // primal if (model->infeasibilityCost() > 1.0e14) model->setInfeasibilityCost(1.0e14); iSequence = out_[CLP_CYCLE - 1]; } if (iSequence >= 0) { char x = model->isColumn(iSequence) ? 'C' : 'R'; if (model->messageHandler()->logLevel() >= 63) model->messageHandler()->message(CLP_SIMPLEX_FLAG, model->messages()) << x << model->sequenceWithin(iSequence) << CoinMessageEol; // if Gub then needs to be sequenceIn_ int save = model->sequenceIn(); model->setSequenceIn(iSequence); model->setFlagged(iSequence); model->setLastBadIteration(model->numberIterations()); model->setSequenceIn(save); //printf("flagging %d from loop\n",iSequence); startCheck(); } else { // Give up #if ABC_NORMAL_DEBUG > 0 if (model->messageHandler()->logLevel() >= 63) printf("***** All flagged?\n"); #endif return 4; } // reset numberBadTimes_ = 2; } return -2; } else { // look at solution and maybe declare victory if (infeasibility < 1.0e-4) { return 0; } else { model->messageHandler()->message(CLP_LOOP, model->messages()) << CoinMessageEol; #ifndef NDEBUG printf("debug loop AbcSimplex A\n"); abort(); #endif return 3; } } } return -1; } #if 0 void AbcSimplex::loadProblem ( const CoinPackedMatrix& matrix, const double* collb, const double* colub, const double* obj, const double* rowlb, const double* rowub, const double * rowObjective) { ClpSimplex::loadProblem(matrix, collb, colub, obj, rowlb, rowub, rowObjective); translate(DO_SCALE_AND_MATRIX|DO_BASIS_AND_ORDER|DO_STATUS|DO_SOLUTION); } #endif // For debug - check pivotVariable consistent void AbcSimplex::checkConsistentPivots() const { unsigned char *copyStatus = CoinCopyOfArray(internalStatus_, numberTotal_); int nBad = 0; for (int i = 0; i < numberRows_; i++) { int k = abcPivotVariable_[i]; if (k >= 0 && k < numberTotal_) { if ((copyStatus[k] & 7) != 6) { nBad++; printf("%d pivoting on row %d is not basic - status %d\n", k, i, copyStatus[k] & 7); } copyStatus[k] = 16; } else { nBad++; printf("%d pivoting on row %d is bad\n", k, i); } } for (int i = 0; i < numberTotal_; i++) { if ((copyStatus[i] & 7) == 6) { nBad++; printf("%d without pivot is basic\n", i); } } assert(!nBad); delete[] copyStatus; } // Print stuff void AbcSimplex::printStuff() const { if (numberIterations_ != 2821) return; printf("XXStart\n"); for (int i = 0; i < this->numberTotal(); i++) { if (this->getInternalStatus(i) != AbcSimplex::basic) printf("%d status %d primal %g dual %g lb %g ub %g\n", i, this->getInternalStatus(i), this->solutionRegion()[i], this->djRegion()[i], this->lowerRegion()[i], this->upperRegion()[i]); } for (int i = 0; i < this->numberRows(); i++) { printf("%d %g <= %g <= %g -pivot %d cost %g\n", i, this->lowerBasic()[i], this->solutionBasic()[i], this->upperBasic()[i], this->pivotVariable()[i], this->costBasic()[i]); } printf("XXend\n"); } #if ABC_PARALLEL == 1 // so thread can find out which one it is int AbcSimplex::whichThread() const { pthread_t thisThread = pthread_self(); int whichThread; for (whichThread = 0; whichThread < NUMBER_THREADS; whichThread++) { if (pthread_equal(thisThread, abcThread_[whichThread])) break; } assert(whichThread < NUMBER_THREADS); return whichThread; } #endif /* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 */