// Copyright (C) 2004, International Business Machines // Corporation and others. All Rights Reserved. #include #include "CoinPragma.hpp" #include "CoinIndexedVector.hpp" #include "CoinHelperFunctions.hpp" #include "ClpSimplex.hpp" #include "ClpFactorization.hpp" #include "ClpQuadraticObjective.hpp" #include "ClpNonLinearCost.hpp" // at end to get min/max! #include "ClpDynamicMatrix.hpp" #include "ClpMessage.hpp" //#define CLP_DEBUG //#define CLP_DEBUG_PRINT //############################################################################# // Constructors / Destructor / Assignment //############################################################################# //------------------------------------------------------------------- // Default Constructor //------------------------------------------------------------------- ClpDynamicMatrix::ClpDynamicMatrix () : ClpPackedMatrix(), sumDualInfeasibilities_(0.0), sumPrimalInfeasibilities_(0.0), sumOfRelaxedDualInfeasibilities_(0.0), sumOfRelaxedPrimalInfeasibilities_(0.0), savedBestGubDual_(0.0), savedBestSet_(0), backToPivotRow_(NULL), keyVariable_(NULL), toIndex_(NULL), fromIndex_(NULL), numberSets_(0), numberActiveSets_(0), objectiveOffset_(0.0), lowerSet_(NULL), upperSet_(NULL), status_(NULL), model_(NULL), firstAvailable_(0), firstAvailableBefore_(0), firstDynamic_(0), lastDynamic_(0), numberStaticRows_(0), numberElements_(0), numberDualInfeasibilities_(0), numberPrimalInfeasibilities_(0), noCheck_(-1), infeasibilityWeight_(0.0), numberGubColumns_(0), maximumGubColumns_(0), maximumElements_(0), startSet_(NULL), next_(NULL), startColumn_(NULL), row_(NULL), element_(NULL), cost_(NULL), id_(NULL), dynamicStatus_(NULL), columnLower_(NULL), columnUpper_(NULL) { setType(15); } //------------------------------------------------------------------- // Copy constructor //------------------------------------------------------------------- ClpDynamicMatrix::ClpDynamicMatrix (const ClpDynamicMatrix & rhs) : ClpPackedMatrix(rhs) { objectiveOffset_ = rhs.objectiveOffset_; numberSets_ = rhs.numberSets_; numberActiveSets_ = rhs.numberActiveSets_; firstAvailable_ = rhs.firstAvailable_; firstAvailableBefore_ = rhs.firstAvailableBefore_; firstDynamic_ = rhs.firstDynamic_; lastDynamic_ = rhs.lastDynamic_; numberStaticRows_ = rhs.numberStaticRows_; numberElements_ = rhs.numberElements_; backToPivotRow_ = ClpCopyOfArray(rhs.backToPivotRow_,lastDynamic_); keyVariable_ = ClpCopyOfArray(rhs.keyVariable_,numberSets_); toIndex_ = ClpCopyOfArray(rhs.toIndex_,numberSets_); fromIndex_ = ClpCopyOfArray(rhs.fromIndex_,getNumRows()+1-numberStaticRows_); lowerSet_ = ClpCopyOfArray(rhs.lowerSet_,numberSets_); upperSet_ = ClpCopyOfArray(rhs.upperSet_,numberSets_); status_ = ClpCopyOfArray(rhs.status_,numberSets_); model_ = rhs.model_; sumDualInfeasibilities_ = rhs. sumDualInfeasibilities_; sumPrimalInfeasibilities_ = rhs.sumPrimalInfeasibilities_; sumOfRelaxedDualInfeasibilities_ = rhs.sumOfRelaxedDualInfeasibilities_; sumOfRelaxedPrimalInfeasibilities_ = rhs.sumOfRelaxedPrimalInfeasibilities_; numberDualInfeasibilities_ = rhs.numberDualInfeasibilities_; numberPrimalInfeasibilities_ = rhs.numberPrimalInfeasibilities_; savedBestGubDual_=rhs.savedBestGubDual_; savedBestSet_=rhs.savedBestSet_; noCheck_ = rhs.noCheck_; infeasibilityWeight_=rhs.infeasibilityWeight_; // Now secondary data numberGubColumns_ = rhs.numberGubColumns_; maximumGubColumns_=rhs.maximumGubColumns_; maximumElements_ = rhs.maximumElements_; startSet_ = ClpCopyOfArray(rhs.startSet_,numberSets_); next_ = ClpCopyOfArray(rhs.next_,maximumGubColumns_); startColumn_ = ClpCopyOfArray(rhs.startColumn_,maximumGubColumns_+1); row_ = ClpCopyOfArray(rhs.row_,maximumElements_); element_ = ClpCopyOfArray(rhs.element_,maximumElements_); cost_ = ClpCopyOfArray(rhs.cost_,maximumGubColumns_); id_ = ClpCopyOfArray(rhs.id_,lastDynamic_-firstDynamic_); columnLower_ = ClpCopyOfArray(rhs.columnLower_,maximumGubColumns_); columnUpper_ = ClpCopyOfArray(rhs.columnUpper_,maximumGubColumns_); dynamicStatus_ = ClpCopyOfArray(rhs.dynamicStatus_,maximumGubColumns_); } /* This is the real constructor*/ ClpDynamicMatrix::ClpDynamicMatrix(ClpSimplex * model, int numberSets, int numberGubColumns, const int * starts, const double * lower, const double * upper, const CoinBigIndex * startColumn, const int * row, const double * element, const double * cost, const double * columnLower, const double * columnUpper, const unsigned char * status, const unsigned char * dynamicStatus) : ClpPackedMatrix() { setType(15); objectiveOffset_ = model->objectiveOffset(); model_ = model; numberSets_ = numberSets; numberGubColumns_ = numberGubColumns; maximumGubColumns_=numberGubColumns_; if (numberGubColumns_) maximumElements_ = startColumn[numberGubColumns_]; else maximumElements_ = 0; startSet_ = new int [numberSets_]; next_ = new int [maximumGubColumns_]; // fill in startSet and next int iSet; if (numberGubColumns_) { for (iSet=0;iSetnumberColumns(); int numberRows = model->numberRows(); numberStaticRows_ = numberRows; savedBestGubDual_=0.0; savedBestSet_=0; // Number of columns needed int frequency = model->factorizationFrequency(); int numberGubInSmall = numberRows + frequency + CoinMin(frequency,numberSets_)+4; // for small problems this could be too big //numberGubInSmall = CoinMin(numberGubInSmall,numberGubColumns_); int numberNeeded = numberGubInSmall + numberColumns; firstAvailable_ = numberColumns; firstAvailableBefore_ = firstAvailable_; firstDynamic_ = numberColumns; lastDynamic_ = numberNeeded; startColumn_ = ClpCopyOfArray(startColumn,numberGubColumns_+1); if (!numberGubColumns_) { startColumn_ = new CoinBigIndex [1]; startColumn_[0]=0; } CoinBigIndex numberElements = startColumn_[numberGubColumns_]; row_ = ClpCopyOfArray(row,numberElements); element_ = new double[numberElements]; CoinBigIndex i; for (i=0;i-1.0e20) lowerSet_[i]=lower[i]; else lowerSet_[i] = -1.0e30; } upperSet_ = new double[numberSets_]; for (i=0;i(model->clpMatrix()); assert (originalMatrixA); CoinPackedMatrix * originalMatrix = originalMatrixA->getPackedMatrix(); originalMatrixA->setMatrixNull(); // so can be deleted safely // guess how much space needed double guess = numberElements; guess /= (double) numberColumns; guess *= 2*numberGubInSmall; numberElements_ = (int) guess; numberElements_ = CoinMin(numberElements_,numberElements)+originalMatrix->getNumElements(); matrix_ = originalMatrix; flags_ &= ~1; // resize model (matrix stays same) int newRowSize = numberRows+CoinMin(numberSets_,CoinMax(frequency,numberRows))+1; model->resize(newRowSize,numberNeeded); for (i=numberRows;isetRowStatus(i,ClpSimplex::basic); if (columnUpper_) { // set all upper bounds so we have enough space double * columnUpper = model->columnUpper(); for(i=firstDynamic_;ireserve(numberNeeded,numberElements_,true); originalMatrix->reserve(numberNeeded+1,numberElements_,false); originalMatrix->getMutableVectorStarts()[numberColumns]=originalMatrix->getNumElements(); originalMatrix->setDimensions(newRowSize,-1); numberActiveColumns_=firstDynamic_; // redo number of columns numberColumns = matrix_->getNumCols(); backToPivotRow_ = new int[numberNeeded]; keyVariable_ = new int[numberSets_]; if (status) { status_ = ClpCopyOfArray(status,numberSets_); assert (dynamicStatus); dynamicStatus_ = ClpCopyOfArray(dynamicStatus,numberGubColumns_); } else { status_= new unsigned char [numberSets_]; memset(status_,0,numberSets_); int i; for (i=0;irowScale()); if (numberSets_) { // Do packed part before gub // always??? //printf("normal packed price - start %d end %d (passed end %d, first %d)\n", ClpPackedMatrix::partialPricing(model,startFraction,endFraction,bestSequence,numberWanted); } else { // no gub ClpPackedMatrix::partialPricing(model,startFraction,endFraction,bestSequence,numberWanted); return; } if (numberWanted>0) { // and do some proportion of full set int startG2 = (int) (startFraction*numberSets_); int endG2 = (int) (endFraction*numberSets_+0.1); endG2 = CoinMin(endG2,numberSets_); //printf("gub price - set start %d end %d\n", // startG2,endG2); double tolerance=model->currentDualTolerance(); double * reducedCost = model->djRegion(); const double * duals = model->dualRowSolution(); double bestDj; int numberRows = model->numberRows(); int slackOffset = lastDynamic_+numberRows; int structuralOffset = slackOffset+numberSets_; // If nothing found yet can go all the way to end int endAll = endG2; if (bestSequence<0&&!startG2) endAll = numberSets_; if (bestSequence>=0) { if (bestSequence!=savedBestSequence_) bestDj = fabs(reducedCost[bestSequence]); // dj from slacks or permanent else bestDj = savedBestDj_; } else { bestDj=tolerance; } int saveSequence = bestSequence; double djMod=0.0; double bestDjMod=0.0; //printf("iteration %d start %d end %d - wanted %d\n",model->numberIterations(), // startG2,endG2,numberWanted); int bestSet=-1; #if 0 // make sure first available is clean (in case last iteration rejected) cost[firstAvailable_]=0.0; length[firstAvailable_]=0; model->nonLinearCost()->setOne(firstAvailable_,0.0,0.0,COIN_DBL_MAX,0.0); model->setStatus(firstAvailable_,ClpSimplex::atLowerBound); { for (int i=firstAvailable_;istartG2+minSet) { // give up numberWanted=0; break; } else if (iSet==endG2&&bestSequence>=0) { break; } int gubRow = toIndex_[iSet]; if (gubRow>=0) { djMod = duals[gubRow+numberStaticRows_]; // have I got sign right? } else { int iBasic = keyVariable_[iSet]; if (iBasic>=maximumGubColumns_) { djMod = 0.0; // set not in } else { // get dj without djMod=0.0; for (CoinBigIndex j=startColumn_[iBasic]; jtolerance) { numberWanted--; if (value>bestDj) { // check flagged variable and correct dj if (!flagged(iSet)) { bestDj=value; bestSequence = slackOffset+iSet; bestDjMod = djMod; bestSet = iSet; } else { // just to make sure we don't exit before got something numberWanted++; abort(); } } } } else if (getStatus(iSet)==ClpSimplex::atUpperBound) { double value = djMod; if (value>tolerance) { numberWanted--; if (value>bestDj) { // check flagged variable and correct dj if (!flagged(iSet)) { bestDj=value; bestSequence = slackOffset+iSet; bestDjMod = djMod; bestSet = iSet; } else { // just to make sure we don't exit before got something numberWanted++; abort(); } } } } } } int iSequence= startSet_[iSet]; while (iSequence>=0) { DynamicStatus status = getDynamicStatus(iSequence); if (status==atLowerBound||status==atUpperBound) { double value=cost_[iSequence]-djMod; for (CoinBigIndex j=startColumn_[iSequence]; jtolerance) { numberWanted--; if (value>bestDj) { // check flagged variable and correct dj if (!flagged(iSequence)) { bestDj=value; bestSequence = structuralOffset+iSequence; bestDjMod = djMod; bestSet = iSet; } else { // just to make sure we don't exit before got something numberWanted++; } } } } iSequence = next_[iSequence]; //onto next in set } if (numberWanted<=0) { numberWanted=0; break; } } if (bestSequence!=saveSequence) { savedBestGubDual_ = bestDjMod; savedBestDj_ = bestDj; savedBestSequence_ = bestSequence; savedBestSet_ = bestSet; } // See if may be finished if (!startG2&&bestSequence<0) infeasibilityWeight_=model_->infeasibilityCost(); else if (bestSequence>=0) infeasibilityWeight_=-1.0; } currentWanted_=numberWanted; } /* Returns effective RHS if it is being used. This is used for long problems or big gub or anywhere where going through full columns is expensive. This may re-compute */ double * ClpDynamicMatrix::rhsOffset(ClpSimplex * model,bool forceRefresh, bool check) { //forceRefresh=true; if (!model_->numberIterations()) forceRefresh=true; //check=false; #ifdef CLP_DEBUG double * saveE=NULL; if (rhsOffset_&&check) { int numberRows = model->numberRows(); saveE = new double[numberRows]; } #endif if (rhsOffset_) { #ifdef CLP_DEBUG if (check) { // no need - but check anyway int numberRows = model->numberRows(); double * rhs = new double[numberRows]; int iRow; int iSet; CoinZeroN(rhs,numberRows); // do ones at bounds before gub const double * smallSolution = model->solutionRegion(); const double * element =matrix_->getElements(); const int * row = matrix_->getIndices(); const CoinBigIndex * startColumn = matrix_->getVectorStarts(); const int * length = matrix_->getVectorLengths(); int iColumn; double objectiveOffset=0.0; for (iColumn=0;iColumngetStatus(iColumn)!=ClpSimplex::basic) { double value = smallSolution[iColumn]; for (CoinBigIndex j=startColumn[iColumn]; j=0) { double value=0.0; if (getDynamicStatus(j)!=inSmall) { if (getDynamicStatus(j)==atLowerBound) { if (columnLower_) value= columnLower_[j]; } else if (getDynamicStatus(j)==atUpperBound) { value= columnUpper_[j]; } else if (getDynamicStatus(j)==soloKey) { value =keyValue(iSet); } objectiveOffset += value*cost_[j]; } solution[j]=value; j = next_[j]; //onto next in set } } // ones in gub and in small problem for (iColumn=firstDynamic_;iColumngetStatus(iColumn)!=ClpSimplex::basic) { int jFull = id_[iColumn-firstDynamic_]; solution[jFull]=smallSolution[iColumn]; } } for (iSet=0;iSet=0) kRow += numberStaticRows_; int j= startSet_[iSet]; while (j>=0) { double value = solution[j]; if (value) { for (CoinBigIndex k= startColumn_[j];k=0) rhs[kRow] -= value; } j = next_[j]; //onto next in set } } delete [] solution; } else { // bounds ClpSimplex::Status iStatus; for (int iSet=0;iSetobjectiveOffset()-objectiveOffset_-objectiveOffset)>1.0e-1) printf("old offset %g, true %g\n",model->objectiveOffset(), objectiveOffset_-objectiveOffset); for (iRow=0;iRow1.0e-3) printf("** bad effective %d - true %g old %g\n",iRow,rhs[iRow],rhsOffset_[iRow]); } memcpy(saveE,rhs,numberRows*sizeof(double)); delete [] rhs; } #endif if (forceRefresh||(refreshFrequency_&&model->numberIterations()>= lastRefresh_+refreshFrequency_)) { int numberRows = model->numberRows(); int iSet; CoinZeroN(rhsOffset_,numberRows); // do ones at bounds before gub const double * smallSolution = model->solutionRegion(); const double * element =matrix_->getElements(); const int * row = matrix_->getIndices(); const CoinBigIndex * startColumn = matrix_->getVectorStarts(); const int * length = matrix_->getVectorLengths(); int iColumn; double objectiveOffset=0.0; for (iColumn=0;iColumngetStatus(iColumn)!=ClpSimplex::basic) { double value = smallSolution[iColumn]; for (CoinBigIndex j=startColumn[iColumn]; j=0) { double value=0.0; if (getDynamicStatus(j)!=inSmall) { if (getDynamicStatus(j)==atLowerBound) { if (columnLower_) value= columnLower_[j]; } else if (getDynamicStatus(j)==atUpperBound) { value= columnUpper_[j]; } else if (getDynamicStatus(j)==soloKey) { value =keyValue(iSet); } objectiveOffset += value*cost_[j]; } solution[j]=value; j = next_[j]; //onto next in set } } // ones in gub and in small problem for (iColumn=firstDynamic_;iColumngetStatus(iColumn)!=ClpSimplex::basic) { int jFull = id_[iColumn-firstDynamic_]; solution[jFull]=smallSolution[iColumn]; } } for (iSet=0;iSet=0) kRow += numberStaticRows_; int j= startSet_[iSet]; while (j>=0) { double value = solution[j]; if (value) { for (CoinBigIndex k= startColumn_[j];k=0) rhsOffset_[kRow] -= value; } j = next_[j]; //onto next in set } } delete [] solution; } else { // bounds ClpSimplex::Status iStatus; for (int iSet=0;iSetsetObjectiveOffset(objectiveOffset_-objectiveOffset); #ifdef CLP_DEBUG if (saveE) { int iRow; for (iRow=0;iRow1.0e-3) printf("** %d - old eff %g new %g\n",iRow,saveE[iRow],rhsOffset_[iRow]); } delete [] saveE; } #endif lastRefresh_ = model->numberIterations(); } } return rhsOffset_; } /* update information for a pivot (and effective rhs) */ int ClpDynamicMatrix::updatePivot(ClpSimplex * model,double oldInValue, double oldOutValue) { // now update working model int sequenceIn = model->sequenceIn(); int sequenceOut = model->sequenceOut(); int numberColumns = model->numberColumns(); if (sequenceIn!=sequenceOut&&sequenceInpivotRow(); if (sequenceIn>=firstDynamic_&&sequenceIn=numberColumns+numberStaticRows_) { int iDynamic = sequenceIn-numberColumns-numberStaticRows_; int iSet = fromIndex_[iDynamic]; setStatus(iSet,model->getStatus(sequenceIn)); } if (sequenceOut>=numberColumns+numberStaticRows_) { int iDynamic = sequenceOut-numberColumns-numberStaticRows_; int iSet = fromIndex_[iDynamic]; // out may have gone through barrier - so check double valueOut = model->lowerRegion()[sequenceOut]; if (fabs(valueOut -(double) lowerSet_[iSet])< fabs(valueOut -(double) upperSet_[iSet])) setStatus(iSet,ClpSimplex::atLowerBound); else setStatus(iSet,ClpSimplex::atUpperBound); if (lowerSet_[iSet]==upperSet_[iSet]) setStatus(iSet,ClpSimplex::isFixed); if (getStatus(iSet)!=model->getStatus(sequenceOut)) printf("** set %d status %d, var status %d\n",iSet, getStatus(iSet),model->getStatus(sequenceOut)); } ClpMatrixBase::updatePivot(model,oldInValue,oldOutValue); #ifdef CLP_DEBUG char * inSmall = new char [numberGubColumns_]; memset(inSmall,0,numberGubColumns_); const double * solution = model->solutionRegion(); for (int i=0;i=23289&&k<23357&&solution[i]) //printf("var %d (in small %d) has value %g\n",k,i,solution[i]); } for (int i=0;igetRowStatus(i+numberStaticRows_)) //printf("*** set %d status %d, var status %d\n",iSet, // getStatus(iSet),model->getRowStatus(i+numberStaticRows_)); //assert (model->getRowStatus(i+numberStaticRows_)==getStatus(iSet)); //if (iSet==1035) { //printf("rhs for set %d (%d) is %g %g - cost %g\n",iSet,i,model->lowerRegion(0)[i+numberStaticRows_], // model->upperRegion(0)[i+numberStaticRows_],model->costRegion(0)[i+numberStaticRows_]); //} } #endif #endif return 0; } /* utility dual function for dealing with dynamic constraints mode=n see ClpGubMatrix.hpp for definition Remember to update here when settled down */ void ClpDynamicMatrix::dualExpanded(ClpSimplex * model, CoinIndexedVector * array, double * other,int mode) { switch (mode) { // modify costs before transposeUpdate case 0: break; // create duals for key variables (without check on dual infeasible) case 1: break; // as 1 but check slacks and compute djs case 2: { // do pivots int * pivotVariable = model->pivotVariable(); int numberRows=numberStaticRows_+numberActiveSets_; int numberColumns = model->numberColumns(); for (int iRow=0;iRow=0) { if (infeasibilityWeight_!=model_->infeasibilityCost()) { // don't bother checking sumDualInfeasibilities_=100.0; numberDualInfeasibilities_=1; sumOfRelaxedDualInfeasibilities_ =100.0; return; } } // In theory we should subtract out ones we have done but .... // If key slack then dual 0.0 // If not then slack could be dual infeasible // dj for key is zero so that defines dual on set int i; double * dual = model->dualRowSolution(); double dualTolerance = model->dualTolerance(); double relaxedTolerance=dualTolerance; // we can't really trust infeasibilities if there is dual error double error = CoinMin(1.0e-2,model->largestDualError()); // allow tolerance at least slightly bigger than standard relaxedTolerance = relaxedTolerance + error; // but we will be using difference relaxedTolerance -= dualTolerance; sumDualInfeasibilities_=0.0; numberDualInfeasibilities_=0; sumOfRelaxedDualInfeasibilities_ =0.0; for (i=0;idualTolerance) infeasibility=-value-dualTolerance; } else if (getStatus(i)==ClpSimplex::atUpperBound) { if (value>dualTolerance) infeasibility=value-dualTolerance; } if (infeasibility>0.0) { sumDualInfeasibilities_ += infeasibility; if (infeasibility>relaxedTolerance) sumOfRelaxedDualInfeasibilities_ += infeasibility; numberDualInfeasibilities_ ++; } } } else { value = dual[gubRow+numberStaticRows_]; } // Now subtract out from all int k= startSet_[i]; while (k>=0) { if (getDynamicStatus(k)!=inSmall) { double djValue = cost_[k]-value; for (CoinBigIndex j=startColumn_[k]; jdualTolerance) infeasibility=djValue-dualTolerance; } if (infeasibility>0.0) { sumDualInfeasibilities_ += infeasibility; if (infeasibility>relaxedTolerance) sumOfRelaxedDualInfeasibilities_ += infeasibility; numberDualInfeasibilities_ ++; } } k = next_[k]; //onto next in set } } } infeasibilityWeight_=-1.0; break; // Report on infeasibilities of key variables case 3: { model->setSumDualInfeasibilities(model->sumDualInfeasibilities()+ sumDualInfeasibilities_); model->setNumberDualInfeasibilities(model->numberDualInfeasibilities()+ numberDualInfeasibilities_); model->setSumOfRelaxedDualInfeasibilities(model->sumOfRelaxedDualInfeasibilities()+ sumOfRelaxedDualInfeasibilities_); } break; // modify costs before transposeUpdate for partial pricing case 4: break; } } /* general utility function for dealing with dynamic constraints mode=n see ClpGubMatrix.hpp for definition Remember to update here when settled down */ int ClpDynamicMatrix::generalExpanded(ClpSimplex * model,int mode,int &number) { int returnCode=0; switch (mode) { // Fill in pivotVariable case 0: { // If no effective rhs - form it if (!rhsOffset_) { rhsOffset_ = new double[model->numberRows()]; rhsOffset(model,true); } int i; int numberBasic=number; int numberColumns = model->numberColumns(); // Use different array so can build from true pivotVariable_ //int * pivotVariable = model->pivotVariable(); int * pivotVariable = model->rowArray(0)->getIndices(); for (i=0;igetColumnStatus(i) == ClpSimplex::basic) pivotVariable[numberBasic++]=i; } number = numberBasic; } break; // Do initial extra rows + maximum basic case 2: { number = model->numberRows(); } break; // Before normal replaceColumn case 3: { if (numberActiveSets_+numberStaticRows_==model_->numberRows()) { // no space - re-factorize returnCode=4; number=-1; // say no need for normal replaceColumn } } break; // To see if can dual or primal case 4: { returnCode= 1; } break; // save status case 5: { } break; // restore status case 6: { // maybe mismatch - redo all in small model //for (int i=firstDynamic_;icostRegion(); double * solution = model->solutionRegion(); double * columnLower = model->lowerRegion(); double * columnUpper = model->upperRegion(); int i; bool doCosts = (number&4)!=0; bool doBounds = (number&1)!=0; for ( i=firstDynamic_;inonLinearCost()) model->nonLinearCost()->setOne(i,solution[i], this->columnLower(jColumn), this->columnUpper(jColumn),cost_[jColumn]); } } // and active sets for (i=0;i-1.0e20) columnLower[iSequence] = lowerSet_[iSet]; else columnLower[iSequence]=-COIN_DBL_MAX; if (upperSet_[iSet]<1.0e20) columnUpper[iSequence] = upperSet_[iSet]; else columnUpper[iSequence]=COIN_DBL_MAX; } if (doCosts) { if (model->nonLinearCost()) { double trueLower; if (lowerSet_[iSet]>-1.0e20) trueLower = lowerSet_[iSet]; else trueLower=-COIN_DBL_MAX; double trueUpper; if (upperSet_[iSet]<1.0e20) trueUpper = upperSet_[iSet]; else trueUpper=COIN_DBL_MAX; model->nonLinearCost()->setOne(iSequence,solution[iSequence], trueLower,trueUpper,0.0); } } } } break; // return 1 if there may be changing bounds on variable (column generation) case 10: { // return 1 as bounds on rhs will change returnCode = 1; } break; // make sure set is clean case 7: { // first flag if (number>=firstDynamic_&&numbersequenceIn()); // id will be sitting at firstAvailable int sequence = id_[firstAvailable_-firstDynamic_]; setFlagged(sequence); model->clearFlagged(firstAvailable_); } } case 11: { int sequenceIn = model->sequenceIn(); if (sequenceIn>=firstDynamic_&&sequenceInsequenceIn()); // take out variable (but leave key) double * cost = model->costRegion(); double * columnLower = model->lowerRegion(); double * columnUpper = model->upperRegion(); double * solution = model->solutionRegion(); int * length = matrix_->getMutableVectorLengths(); #ifndef NDEBUG if (length[sequenceIn]) { int * row = matrix_->getMutableIndices(); CoinBigIndex * startColumn = matrix_->getMutableVectorStarts(); int iRow = row[startColumn[sequenceIn]+length[sequenceIn]-1]; int which = iRow-numberStaticRows_; assert (which>=0); int iSet = fromIndex_[which]; assert (toIndex_[iSet]==which); } #endif // no need firstAvailable_--; solution[firstAvailable_]=0.0; cost[firstAvailable_]=0.0; length[firstAvailable_]=0; model->nonLinearCost()->setOne(firstAvailable_,0.0,0.0,COIN_DBL_MAX,0.0); model->setStatus(firstAvailable_,ClpSimplex::atLowerBound); columnLower[firstAvailable_]=0.0; columnUpper[firstAvailable_]=COIN_DBL_MAX; // not really in small problem int iBig=id_[sequenceIn-firstDynamic_]; if (model->getStatus(sequenceIn)==ClpSimplex::atLowerBound) { setDynamicStatus(iBig,atLowerBound); if (columnLower_) modifyOffset(sequenceIn,columnLower_[iBig]); } else { setDynamicStatus(iBig,atUpperBound); modifyOffset(sequenceIn,columnUpper_[iBig]); } } } break; default: break; } return returnCode; } /* Purely for column generation and similar ideas. Allows matrix and any bounds or costs to be updated (sensibly). Returns non-zero if any changes. */ int ClpDynamicMatrix::refresh(ClpSimplex * model) { // If at beginning then create initial problem if (firstDynamic_==firstAvailable_) { initialProblem(); return 1; } else if (!model->nonLinearCost()) { // will be same as last time return 1; } // lookup array int * active = new int [numberActiveSets_]; CoinZeroN(active,numberActiveSets_); int iColumn; int numberColumns = model->numberColumns(); double * element = matrix_->getMutableElements(); int * row = matrix_->getMutableIndices(); CoinBigIndex * startColumn = matrix_->getMutableVectorStarts(); int * length = matrix_->getMutableVectorLengths(); double * cost = model->costRegion(); double * columnLower = model->lowerRegion(); double * columnUpper = model->upperRegion(); CoinBigIndex numberElements=startColumn[firstDynamic_]; // first just do lookup and basic stuff int currentNumber = firstAvailable_; firstAvailable_ = firstDynamic_; double objectiveChange=0.0; double * solution = model->solutionRegion(); int currentNumberActiveSets=numberActiveSets_; for (iColumn=firstDynamic_;iColumn=0); int iSet = fromIndex_[which]; assert (toIndex_[iSet]==which); if (model->getStatus(iColumn)==ClpSimplex::basic) { active[which]++; // may as well make key keyVariable_[iSet]=id_[iColumn-firstDynamic_]; } } int i; numberActiveSets_=0; int numberDeleted=0; for (i=0;igetRowStatus(iRow)==ClpSimplex::basic) { numberActive++; // may as well make key keyVariable_[iSet]=maximumGubColumns_+iSet; } if (numberActive>1) { // keep active[i]=numberActiveSets_; numberActiveSets_++; } else { active[i]=-1; } } for (iColumn=firstDynamic_;iColumngetStatus(iColumn)==ClpSimplex::atLowerBound|| model->getStatus(iColumn)==ClpSimplex::atUpperBound) { double value = solution[iColumn]; bool toLowerBound=true; if (columnUpper_) { if (!columnLower_) { if (fabs(value-columnUpper_[jColumn])getStatus(iColumn)!=ClpSimplex::superBasic); // deal with later int iPut = active[which]; if (iPut>=0) { // move id_[firstAvailable_-firstDynamic_] = jColumn; int numberThis = startColumn_[jColumn+1]-startColumn_[jColumn]+1; length[firstAvailable_]=numberThis; cost[firstAvailable_]=cost[iColumn]; columnLower[firstAvailable_]=columnLower[iColumn]; columnUpper[firstAvailable_]=columnUpper[iColumn]; model->nonLinearCost()->setOne(firstAvailable_,solution[iColumn],0.0,COIN_DBL_MAX, cost_[jColumn]); CoinBigIndex base = startColumn_[jColumn]; for (int j=0;jsetStatus(firstAvailable_,model->getStatus(iColumn)); solution[firstAvailable_] = solution[iColumn]; firstAvailable_++; startColumn[firstAvailable_]=numberElements; } } } // zero solution CoinZeroN(solution+firstAvailable_,currentNumber-firstAvailable_); // zero cost CoinZeroN(cost+firstAvailable_,currentNumber-firstAvailable_); // zero lengths CoinZeroN(length+firstAvailable_,currentNumber-firstAvailable_); for ( iColumn=firstAvailable_;iColumnnonLinearCost()->setOne(iColumn,0.0,0.0,COIN_DBL_MAX,0.0); model->setStatus(iColumn,ClpSimplex::atLowerBound); columnLower[iColumn]=0.0; columnUpper[iColumn]=COIN_DBL_MAX; } // move rhs and set rest to infinite numberActiveSets_=0; for (i=0;i=0) { int in = iRow+numberColumns; int out = iPut+numberColumns+numberStaticRows_; solution[out]=solution[in]; columnLower[out]=columnLower[in]; columnUpper[out]=columnUpper[in]; cost[out]=cost[in]; double trueLower; if (lowerSet_[iSet]>-1.0e20) trueLower = lowerSet_[iSet]; else trueLower=-COIN_DBL_MAX; double trueUpper; if (upperSet_[iSet]<1.0e20) trueUpper = upperSet_[iSet]; else trueUpper=COIN_DBL_MAX; model->nonLinearCost()->setOne(out,solution[out], trueLower,trueUpper,0.0); model->setStatus(out,model->getStatus(in)); toIndex_[iSet]=numberActiveSets_; rhsOffset_[numberActiveSets_+numberStaticRows_]= rhsOffset_[i+numberStaticRows_]; fromIndex_[numberActiveSets_++]=fromIndex_[i]; } else { // adjust offset // put out as key int jColumn = keyVariable_[iSet]; toIndex_[iSet]=-1; if (jColumnsetObjectiveOffset(model->objectiveOffset()-objectiveChange); delete [] active; for (i=numberActiveSets_;inonLinearCost()->setOne(iSequence,solution[iSequence], columnLower[iSequence], columnUpper[iSequence],0.0); model->setStatus(iSequence,ClpSimplex::basic); rhsOffset_[i+numberStaticRows_]=0.0; } if (currentNumberActiveSets!=numberActiveSets_||numberDeleted) { // deal with pivotVariable int * pivotVariable = model->pivotVariable(); int sequence=firstDynamic_; int iRow=0; int base1 = firstDynamic_; int base2 = lastDynamic_; int base3 = numberColumns+numberStaticRows_; int numberRows = numberStaticRows_+currentNumberActiveSets; while (sequence=base2&&iPivot=base2&&iPivotgetRowStatus(i+numberStaticRows_)==ClpSimplex::basic) { pivotVariable[iPut++]=i+base3; } } for (i=numberActiveSets_;i=0) { printf("var %d status %d ",jj,dynamicStatus_[jj]); jj=next_[jj]; } printf("\n"); #endif #ifdef CLP_DEBUG { // debug coding to analyze set int i; int kSet=-6; if (kSet>=0) { int * back = new int [numberGubColumns_]; for (i=0;i=0) { printf("( %d status %d ) ",sequence,getDynamicStatus(sequence)); sequence = next_[sequence]; } } else { int iRow=numberStaticRows_+toIndex_[kSet]; printf("In - Set %d - slack status %d, key %d offset %g slack %g\n",kSet,status_[kSet],keyVariable_[kSet], rhsOffset_[iRow],model->solutionRegion(0)[iRow]); while (sequence>=0) { int iBack = back[sequence]; printf("( %d status %d value %g) ",sequence,getDynamicStatus(sequence),model->solutionRegion()[iBack]); sequence = next_[sequence]; } } printf("\n"); delete [] back; } } #endif int n=numberActiveSets_; for (i=0;i=lowerSet_[i]&&keyValue(i)<=upperSet_[i]); n++; } } assert (n==numberSets_); #endif return 1; } void ClpDynamicMatrix::times(double scalar, const double * x, double * y) const { if (model_->specialOptions()!=16) { ClpPackedMatrix::times(scalar,x,y); } else { int iRow; const double * element = matrix_->getElements(); const int * row = matrix_->getIndices(); const CoinBigIndex * startColumn = matrix_->getVectorStarts(); const int * length = matrix_->getVectorLengths(); int * pivotVariable = model_->pivotVariable(); for (iRow=0;iRow=0) { DynamicStatus status = getDynamicStatus(j); assert (status!=inSmall); if (status==soloKey) { numberKey++; } else if (status==atUpperBound) { value -= columnUpper_[j]; } else if (columnLower_) { value -= columnLower_[j]; } j = next_[j]; //onto next in set } assert (numberKey==1); } else { int j= startSet_[iSet]; while (j>=0) { DynamicStatus status = getDynamicStatus(j); assert (status!=inSmall); assert (status!=soloKey); if (status==atUpperBound) { value += columnUpper_[j]; } else if (columnLower_) { value += columnLower_[j]; } j = next_[j]; //onto next in set } } } return value; } // Switches off dj checking each factorization (for BIG models) void ClpDynamicMatrix::switchOffCheck() { noCheck_=0; infeasibilityWeight_=0.0; } /* Creates a variable. This is called after partial pricing and may modify matrix. May update bestSequence. */ void ClpDynamicMatrix::createVariable(ClpSimplex * model, int & bestSequence) { int numberRows = model->numberRows(); int slackOffset = lastDynamic_+numberRows; int structuralOffset = slackOffset+numberSets_; int bestSequence2=savedBestSequence_-structuralOffset; if (bestSequence>=slackOffset) { double * columnLower = model->lowerRegion(); double * columnUpper = model->upperRegion(); double * solution = model->solutionRegion(); double * reducedCost = model->djRegion(); const double * duals = model->dualRowSolution(); if (toIndex_[savedBestSet_]<0) { // need to put key into basis int newRow = numberActiveSets_+numberStaticRows_; model->dualRowSolution()[newRow]=savedBestGubDual_; double valueOfKey = keyValue(savedBestSet_); // done before toIndex_ set toIndex_[savedBestSet_]=numberActiveSets_; fromIndex_[numberActiveSets_++]=savedBestSet_; int iSequence=lastDynamic_+newRow; // we need to get lower and upper correct double shift=0.0; int j= startSet_[savedBestSet_]; while (j>=0) { if (getDynamicStatus(j)==atUpperBound) shift += columnUpper_[j]; else if (getDynamicStatus(j)==atLowerBound&&columnLower_) shift += columnLower_[j]; j = next_[j]; //onto next in set } if (lowerSet_[savedBestSet_]>-1.0e20) columnLower[iSequence] = lowerSet_[savedBestSet_]; else columnLower[iSequence]=-COIN_DBL_MAX; if (upperSet_[savedBestSet_]<1.0e20) columnUpper[iSequence] = upperSet_[savedBestSet_]; else columnUpper[iSequence]=COIN_DBL_MAX; #ifdef CLP_DEBUG if (model_->logLevel()==63) { printf("%d in in set %d, key is %d rhs %g %g - keyvalue %g\n", bestSequence2,savedBestSet_,keyVariable_[savedBestSet_], columnLower[iSequence],columnUpper[iSequence],valueOfKey); int j= startSet_[savedBestSet_]; while (j>=0) { if (getDynamicStatus(j)==atUpperBound) printf("%d atup ",j); else if (getDynamicStatus(j)==atLowerBound) printf("%d atlo ",j); else if (getDynamicStatus(j)==soloKey) printf("%d solo ",j); else abort(); j = next_[j]; //onto next in set } printf("\n"); } #endif if (keyVariable_[savedBestSet_]pivotVariable()[newRow]=firstAvailable_; backToPivotRow_[firstAvailable_]=newRow; model->setStatus(iSequence,getStatus(savedBestSet_)); model->djRegion()[iSequence] = savedBestGubDual_; if (getStatus(savedBestSet_)==ClpSimplex::atUpperBound) solution[iSequence] = columnUpper[iSequence]; else solution[iSequence] = columnLower[iSequence]; // create variable and pivot in int key=keyVariable_[savedBestSet_]; setDynamicStatus(key,inSmall); double * element = matrix_->getMutableElements(); int * row = matrix_->getMutableIndices(); CoinBigIndex * startColumn = matrix_->getMutableVectorStarts(); int * length = matrix_->getMutableVectorLengths(); CoinBigIndex numberElements = startColumn[firstAvailable_]; int numberThis = startColumn_[key+1]-startColumn_[key]+1; if (numberElements+numberThis>numberElements_) { // need to redo numberElements_ = CoinMax(3*numberElements_/2,numberElements+numberThis); matrix_->reserve(lastDynamic_,numberElements_); element = matrix_->getMutableElements(); row = matrix_->getMutableIndices(); // these probably okay but be safe startColumn = matrix_->getMutableVectorStarts(); length = matrix_->getMutableVectorLengths(); } // already set startColumn[firstAvailable_]=numberElements; length[firstAvailable_]=numberThis; model->costRegion()[firstAvailable_]=cost_[key]; CoinBigIndex base = startColumn_[key]; for (int j=0;jsetObjectiveOffset(model->objectiveOffset()+cost_[key]* valueOfKey); model->solutionRegion()[firstAvailable_]= valueOfKey; model->setStatus(firstAvailable_,ClpSimplex::basic); // ***** need to adjust effective rhs if (!columnLower_&&!columnUpper_) { columnLower[firstAvailable_] = 0.0; columnUpper[firstAvailable_] = COIN_DBL_MAX; } else { if (columnLower_) columnLower[firstAvailable_] = columnLower_[key]; else columnLower[firstAvailable_] = 0.0; if (columnUpper_) columnUpper[firstAvailable_] = columnUpper_[key]; else columnUpper[firstAvailable_] = COIN_DBL_MAX; } model->nonLinearCost()->setOne(firstAvailable_,solution[firstAvailable_], columnLower[firstAvailable_], columnUpper[firstAvailable_],cost_[key]); startColumn[firstAvailable_+1]=numberElements; reducedCost[firstAvailable_] = 0.0; modifyOffset(key,valueOfKey); rhsOffset_[newRow] = -shift; // sign? #ifdef CLP_DEBUG model->rowArray(1)->checkClear(); #endif // now pivot in unpack(model,model->rowArray(1),firstAvailable_); model->factorization()->updateColumnFT(model->rowArray(2),model->rowArray(1)); double alpha = model->rowArray(1)->denseVector()[newRow]; int updateStatus = model->factorization()->replaceColumn(model, model->rowArray(2), model->rowArray(1), newRow, alpha); model->rowArray(1)->clear(); if (updateStatus) { if (updateStatus==3) { // out of memory // increase space if not many iterations if (model->factorization()->pivots()< 0.5*model->factorization()->maximumPivots()&& model->factorization()->pivots()<400) model->factorization()->areaFactor( model->factorization()->areaFactor() * 1.1); } else { printf("Bad returncode %d from replaceColumn\n",updateStatus); } bestSequence=-1; return; } // firstAvailable_ only finally updated if good pivot (in updatePivot) // otherwise it reverts to firstAvailableBefore_ firstAvailable_++; } else { // slack key model->setStatus(iSequence,ClpSimplex::basic); model->djRegion()[iSequence]=0.0; solution[iSequence]=shift; rhsOffset_[newRow] = -shift; // sign? } // correct slack model->costRegion()[iSequence] = 0.0; model->nonLinearCost()->setOne(iSequence,solution[iSequence],columnLower[iSequence], columnUpper[iSequence],0.0); } if (savedBestSequence_>=structuralOffset) { // recompute dj and create double value=cost_[bestSequence2]-savedBestGubDual_; for (CoinBigIndex jBigIndex=startColumn_[bestSequence2]; jBigIndexgetMutableElements(); int * row = matrix_->getMutableIndices(); CoinBigIndex * startColumn = matrix_->getMutableVectorStarts(); int * length = matrix_->getMutableVectorLengths(); CoinBigIndex numberElements = startColumn[firstAvailable_]; int numberThis = startColumn_[bestSequence2+1]-startColumn_[bestSequence2]+1; if (numberElements+numberThis>numberElements_) { // need to redo numberElements_ = CoinMax(3*numberElements_/2,numberElements+numberThis); matrix_->reserve(lastDynamic_,numberElements_); element = matrix_->getMutableElements(); row = matrix_->getMutableIndices(); // these probably okay but be safe startColumn = matrix_->getMutableVectorStarts(); length = matrix_->getMutableVectorLengths(); } // already set startColumn[firstAvailable_]=numberElements; length[firstAvailable_]=numberThis; model->costRegion()[firstAvailable_]=cost_[bestSequence2]; CoinBigIndex base = startColumn_[bestSequence2]; for (int j=0;jsolutionRegion()[firstAvailable_]=0.0; if (!columnLower_&&!columnUpper_) { model->setStatus(firstAvailable_,ClpSimplex::atLowerBound); columnLower[firstAvailable_] = 0.0; columnUpper[firstAvailable_] = COIN_DBL_MAX; } else { DynamicStatus status = getDynamicStatus(bestSequence2); if (columnLower_) columnLower[firstAvailable_] = columnLower_[bestSequence2]; else columnLower[firstAvailable_] = 0.0; if (columnUpper_) columnUpper[firstAvailable_] = columnUpper_[bestSequence2]; else columnUpper[firstAvailable_] = COIN_DBL_MAX; if (status==atLowerBound) { solution[firstAvailable_]=columnLower[firstAvailable_]; model->setStatus(firstAvailable_,ClpSimplex::atLowerBound); } else { solution[firstAvailable_]=columnUpper[firstAvailable_]; model->setStatus(firstAvailable_,ClpSimplex::atUpperBound); } } model->setObjectiveOffset(model->objectiveOffset()+cost_[bestSequence2]* solution[firstAvailable_]); model->nonLinearCost()->setOne(firstAvailable_,solution[firstAvailable_], columnLower[firstAvailable_], columnUpper[firstAvailable_],cost_[bestSequence2]); bestSequence=firstAvailable_; // firstAvailable_ only updated if good pivot (in updatePivot) startColumn[firstAvailable_+1]=numberElements; //printf("price struct %d - dj %g gubpi %g\n",bestSequence,value,savedBestGubDual_); reducedCost[bestSequence] = value; } else { // slack - row must just have been created assert (toIndex_[savedBestSet_]==numberActiveSets_-1); int newRow = numberStaticRows_+numberActiveSets_-1; bestSequence = lastDynamic_ + newRow; reducedCost[bestSequence] = savedBestGubDual_; } } // clear for next iteration savedBestSequence_=-1; } // Returns reduced cost of a variable double ClpDynamicMatrix::reducedCost(ClpSimplex * model,int sequence) const { int numberRows = model->numberRows(); int slackOffset = lastDynamic_+numberRows; if (sequencedjRegion()[sequence]; else return savedBestDj_; } // Does gub crash void ClpDynamicMatrix::gubCrash() { // Do basis - cheapest or slack if feasible int longestSet=0; int iSet; for (iSet=0;iSet=0) { n++; j=next_[j]; } longestSet = CoinMax(longestSet,n); } double * upper = new double[longestSet+1]; double * cost = new double[longestSet+1]; double * lower = new double[longestSet+1]; double * solution = new double[longestSet+1]; int * back = new int[longestSet+1]; double tolerance = model_->primalTolerance(); double objectiveOffset = 0.0; for (iSet=0;iSet=0) { if (!columnLower_) lower[numberInSet]=0.0; else lower[numberInSet]= columnLower_[j]; if (!columnUpper_) upper[numberInSet]=COIN_DBL_MAX; else upper[numberInSet]= columnUpper_[j]; back[numberInSet++]=j; j = next_[j]; } CoinFillN(solution,numberInSet,0.0); // and slack iBasic=numberInSet; solution[iBasic]=-value; lower[iBasic]=-upperSet_[iSet]; upper[iBasic]=-lowerSet_[iSet]; int kphase; if (valueupperSet_[iSet]+tolerance) { // infeasible kphase=0; // remember bounds are flipped so opposite to natural if (valuedualTolerance(); for (int iphase =kphase;iphase<2;iphase++) { if (iphase) { cost[numberInSet]=0.0; for (int j=0;j=lower[i]&&solution[i]<=upper[i]); if (dj>dualTolerance) improvement = dj*(solution[i]-lower[i]); else if (dj<-dualTolerance) improvement = dj*(solution[i]-upper[i]); if (improvement>best) { best=improvement; chosen=i; if (dj<0.0) { way = 1; distance = upper[i]-solution[i]; } else { way = -1; distance = solution[i]-lower[i]; } } } if (chosen>=0) { improve=true; // now see how far if (way>0) { // incoming increasing so basic decreasing // if phase 0 then go to nearest bound double distance=upper[chosen]-solution[chosen]; double basicDistance; if (!iphase) { assert (iBasic==numberInSet); assert (solution[iBasic]>upper[iBasic]); basicDistance = solution[iBasic]-upper[iBasic]; } else { basicDistance = solution[iBasic]-lower[iBasic]; } // need extra coding for unbounded assert (CoinMin(distance,basicDistance)<1.0e20); if (distance>basicDistance) { // incoming becomes basic solution[chosen] += basicDistance; if (!iphase) solution[iBasic]=upper[iBasic]; else solution[iBasic]=lower[iBasic]; iBasic = chosen; } else { // flip solution[chosen]=upper[chosen]; solution[iBasic] -= distance; } } else { // incoming decreasing so basic increasing // if phase 0 then go to nearest bound double distance=solution[chosen]-lower[chosen]; double basicDistance; if (!iphase) { assert (iBasic==numberInSet); assert (solution[iBasic]1.0e20) { printf("unbounded on set %d\n",iSet); iphase=1; iBasic=numberInSet; break; } if (distance>basicDistance) { // incoming becomes basic solution[chosen] -= basicDistance; if (!iphase) solution[iBasic]=lower[iBasic]; else solution[iBasic]=upper[iBasic]; iBasic = chosen; } else { // flip solution[chosen]=lower[chosen]; solution[iBasic] += distance; } } if (!iphase) { if(iBasic=lower[iBasic]&& solution[iBasic]<=upper[iBasic]) break; // feasible (on flip) } } } } } // do solution i.e. bounds if (columnLower_||columnUpper_) { for (int j=0;j fabs(solution[j]-columnUpper_[back[j]])) setDynamicStatus(back[j],atUpperBound); } else if (columnUpper_&&solution[j]>0.0) { setDynamicStatus(back[j],atUpperBound); } else { setDynamicStatus(back[j],atLowerBound); assert(!solution[j]); } } } } // convert iBasic back and do bounds if (iBasic==numberInSet) { // slack basic setStatus(iSet,ClpSimplex::basic); iBasic=iSet+maximumGubColumns_; } else { iBasic = back[iBasic]; setDynamicStatus(iBasic,soloKey); // remember bounds flipped if (upper[numberInSet]==lower[numberInSet]) setStatus(iSet,ClpSimplex::isFixed); else if (solution[numberInSet]==upper[numberInSet]) setStatus(iSet,ClpSimplex::atLowerBound); else if (solution[numberInSet]==lower[numberInSet]) setStatus(iSet,ClpSimplex::atUpperBound); else abort(); } keyVariable_[iSet]=iBasic; } model_->setObjectiveOffset(objectiveOffset_-objectiveOffset); delete [] lower; delete [] solution; delete [] upper; delete [] cost; delete [] back; // make sure matrix is in good shape matrix_->orderMatrix(); } // Populates initial matrix from dynamic status void ClpDynamicMatrix::initialProblem() { int iSet; double * element = matrix_->getMutableElements(); int * row = matrix_->getMutableIndices(); CoinBigIndex * startColumn = matrix_->getMutableVectorStarts(); int * length = matrix_->getMutableVectorLengths(); double * cost = model_->objective(); double * solution = model_->primalColumnSolution(); double * columnLower = model_->columnLower(); double * columnUpper = model_->columnUpper(); double * rowSolution = model_->primalRowSolution(); double * rowLower = model_->rowLower(); double * rowUpper = model_->rowUpper(); CoinBigIndex numberElements=startColumn[firstDynamic_]; firstAvailable_ = firstDynamic_; numberActiveSets_=0; for (iSet=0;iSet=0) { assert (getDynamicStatus(j)!=soloKey||whichKey==-1); if (getDynamicStatus(j)==inSmall) numberActive++; else if (getDynamicStatus(j)==soloKey) whichKey=j; j = next_[j]; //onto next in set } if (getStatus(iSet)==ClpSimplex::basic&&numberActive) numberActive++; if (numberActive) { assert (numberActive>1); int iRow = numberActiveSets_+numberStaticRows_; rowSolution[iRow]=0.0; double lowerValue; if (lowerSet_[iSet]>-1.0e20) lowerValue = lowerSet_[iSet]; else lowerValue=-COIN_DBL_MAX; double upperValue; if (upperSet_[iSet]<1.0e20) upperValue = upperSet_[iSet]; else upperValue=COIN_DBL_MAX; rowLower[iRow]=lowerValue; rowUpper[iRow]=upperValue; if (getStatus(iSet)==ClpSimplex::basic) { model_->setRowStatus(iRow,ClpSimplex::basic); rowSolution[iRow]=0.0; } else if (getStatus(iSet)==ClpSimplex::atLowerBound) { model_->setRowStatus(iRow,ClpSimplex::atLowerBound); rowSolution[iRow]=lowerValue; } else { model_->setRowStatus(iRow,ClpSimplex::atUpperBound); rowSolution[iRow]=upperValue; } j= startSet_[iSet]; while (j>=0) { DynamicStatus status = getDynamicStatus(j); if (status==inSmall) { int numberThis = startColumn_[j+1]-startColumn_[j]+1; if (numberElements+numberThis>numberElements_) { // need to redo numberElements_ = CoinMax(3*numberElements_/2,numberElements+numberThis); matrix_->reserve(lastDynamic_,numberElements_); element = matrix_->getMutableElements(); row = matrix_->getMutableIndices(); // these probably okay but be safe startColumn = matrix_->getMutableVectorStarts(); length = matrix_->getMutableVectorLengths(); } length[firstAvailable_]=numberThis; cost[firstAvailable_]=cost_[j]; CoinBigIndex base = startColumn_[j]; for (int k=0;ksetStatus(firstAvailable_,ClpSimplex::basic); if (!columnLower_&&!columnUpper_) { columnLower[firstAvailable_] = 0.0; columnUpper[firstAvailable_] = COIN_DBL_MAX; } else { if (columnLower_) columnLower[firstAvailable_] = columnLower_[j]; else columnLower[firstAvailable_] = 0.0; if (columnUpper_) columnUpper[firstAvailable_] = columnUpper_[j]; else columnUpper[firstAvailable_] = COIN_DBL_MAX; if (status==atLowerBound) { solution[firstAvailable_]=columnLower[firstAvailable_]; } else { solution[firstAvailable_]=columnUpper[firstAvailable_]; } } firstAvailable_++; startColumn[firstAvailable_]=numberElements; } j = next_[j]; //onto next in set } model_->setRowStatus(numberActiveSets_+numberStaticRows_,getStatus(iSet)); toIndex_[iSet]=numberActiveSets_; fromIndex_[numberActiveSets_++]=iSet; } assert (toIndex_[iSet]>=0||whichKey>=0); keyVariable_[iSet]=whichKey; } return; } // Adds in a column to gub structure (called from descendant) int ClpDynamicMatrix::addColumn(int numberEntries,const int * row, const double * element, double cost, double lower, double upper,int iSet, DynamicStatus status) { // check if already in int j=startSet_[iSet]; while (j>=0) { if (startColumn_[j+1]-startColumn_[j]==numberEntries) { const int * row2 = row_+startColumn_[j]; const double * element2 = element_ + startColumn_[j]; bool same=true; for (int k=0;kmaximumElements_) { CoinBigIndex j; int i; int put=0; int numberElements=0; CoinBigIndex start=0; // compress - leave ones at ub and basic int * which = new int [numberGubColumns_]; for (i=0;i=0); sequence=next_[sequence]; } startSet_[jSet]=which[sequence]; int last = which[sequence]; while (next_[sequence]>=0) { sequence = next_[sequence]; if(which[sequence]>=0) { // keep newNext[last]=which[sequence]; last=which[sequence]; } } newNext[last]=-jSet-1; } delete [] next_; next_=newNext; delete [] which; abort(); } CoinBigIndex start = startColumn_[numberGubColumns_]; memcpy(row_+start,row,numberEntries*sizeof(int)); memcpy(element_+start,element,numberEntries*sizeof(float)); startColumn_[numberGubColumns_+1]=start+numberEntries; cost_[numberGubColumns_]=cost; if (columnLower_) columnLower_[numberGubColumns_]=lower; else assert (!lower); if (columnUpper_) columnUpper_[numberGubColumns_]=upper; else assert (upper>1.0e20); setDynamicStatus(numberGubColumns_,status); // Do next_ j=startSet_[iSet]; startSet_[iSet]=numberGubColumns_; next_[numberGubColumns_]=j; numberGubColumns_++; return numberGubColumns_-1; } // Returns which set a variable is in int ClpDynamicMatrix::whichSet (int sequence) const { while (next_[sequence]>=0) sequence = next_[sequence]; int iSet = - next_[sequence]-1; return iSet; }