// 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 "ClpDynamicExampleMatrix.hpp" #include "ClpMessage.hpp" //#define CLP_DEBUG //#define CLP_DEBUG_PRINT //############################################################################# // Constructors / Destructor / Assignment //############################################################################# //------------------------------------------------------------------- // Default Constructor //------------------------------------------------------------------- ClpDynamicExampleMatrix::ClpDynamicExampleMatrix () : ClpDynamicMatrix(), numberColumns_(0), startColumnGen_(NULL), rowGen_(NULL), elementGen_(NULL), costGen_(NULL), fullStartGen_(NULL), dynamicStatusGen_(NULL), idGen_(NULL), columnLowerGen_(NULL), columnUpperGen_(NULL) { setType(25); } //------------------------------------------------------------------- // Copy constructor //------------------------------------------------------------------- ClpDynamicExampleMatrix::ClpDynamicExampleMatrix (const ClpDynamicExampleMatrix & rhs) : ClpDynamicMatrix(rhs) { numberColumns_ = rhs.numberColumns_; startColumnGen_ = ClpCopyOfArray(rhs.startColumnGen_,numberColumns_+1); CoinBigIndex numberElements = startColumnGen_[numberColumns_]; rowGen_ = ClpCopyOfArray(rhs.rowGen_,numberElements);; elementGen_ = ClpCopyOfArray(rhs.elementGen_,numberElements);; costGen_ = ClpCopyOfArray(rhs.costGen_,numberColumns_); fullStartGen_ = ClpCopyOfArray(rhs.fullStartGen_,numberSets_+1); dynamicStatusGen_ = ClpCopyOfArray(rhs.dynamicStatusGen_,numberColumns_); idGen_ = ClpCopyOfArray(rhs.idGen_,maximumGubColumns_); columnLowerGen_ = ClpCopyOfArray(rhs.columnLowerGen_,numberColumns_); columnUpperGen_ = ClpCopyOfArray(rhs.columnUpperGen_,numberColumns_); } /* This is the real constructor*/ ClpDynamicExampleMatrix::ClpDynamicExampleMatrix(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, int numberIds,const int *ids) : ClpDynamicMatrix(model,numberSets,0,NULL,lower,upper,NULL,NULL,NULL,NULL,NULL,NULL, NULL,NULL) { setType(25); numberColumns_ = numberGubColumns; // start with safe values - then experiment maximumGubColumns_=numberColumns_; maximumElements_ = startColumn[numberColumns_]; // delete odd stuff created by ClpDynamicMatrix constructor delete [] startSet_; startSet_ = new int [numberSets_]; delete [] next_; next_ = new int [maximumGubColumns_]; delete [] row_; delete [] element_; delete [] startColumn_; delete [] cost_; delete [] columnLower_; delete [] columnUpper_; delete [] dynamicStatus_; delete [] status_; delete [] id_; // and size correctly row_ = new int [maximumElements_]; element_ = new double [maximumElements_]; startColumn_ = new CoinBigIndex [maximumGubColumns_+1]; // say no columns yet numberGubColumns_=0; startColumn_[0]=0; cost_ = new double[maximumGubColumns_]; dynamicStatus_ = new unsigned char [maximumGubColumns_]; memset(dynamicStatus_,0,maximumGubColumns_); id_ = new int[maximumGubColumns_]; if (columnLower) columnLower_ = new double[maximumGubColumns_]; else columnLower_ = NULL; if (columnUpper) columnUpper_ = new double[maximumGubColumns_]; else columnUpper_=NULL; // space for ids idGen_ = new int [maximumGubColumns_]; int iSet; for (iSet=0;iSetcolumnUpper(); for(i=firstDynamic_;icolumnUpper(); for(i=firstDynamic_;irowScale()); if (!numberSets_) { // no gub ClpPackedMatrix::partialPricing(model,startFraction,endFraction,bestSequence,numberWanted); } else { // 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_; int structuralOffset2 = structuralOffset+maximumGubColumns_; // 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; int minSet = minimumObjectsScan_<0 ? 5 : minimumObjectsScan_; int minNeg = minimumGoodReducedCosts_<0 ? 5 : minimumGoodReducedCosts_; for (int iSet = startG2;iSetstartG2+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>=numberColumns_) { 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(); } } } } } } // do ones in small 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 } // and now get best by column generation // If no upper bounds we may not need status test for (iSequence=fullStartGen_[iSet];iSequencetolerance) { numberWanted--; if (value>bestDj) { // check flagged variable and correct dj if (!flaggedGen(iSequence)) { bestDj=value; bestSequence = structuralOffset2+iSequence; bestDjMod = djMod; bestSet = iSet; } else { // just to make sure we don't exit before got something numberWanted++; } } } } } if (numberWanted<=0) { numberWanted=0; break; } } if (bestSequence!=saveSequence) { savedBestGubDual_ = bestDjMod; savedBestDj_ = bestDj; savedBestSequence_ = bestSequence; savedBestSet_ = bestSet; } // Do packed part before gub // always??? // Resize so just do to gub numberActiveColumns_=firstDynamic_; int saveMinNeg=minimumGoodReducedCosts_; if (bestSequence>=0) minimumGoodReducedCosts_=-2; currentWanted_=numberWanted; ClpPackedMatrix::partialPricing(model,startFraction,endFraction,bestSequence,numberWanted); numberActiveColumns_=matrix_->getNumCols(); minimumGoodReducedCosts_=saveMinNeg; // See if may be finished if (!startG2&&bestSequence<0) infeasibilityWeight_=model_->infeasibilityCost(); else if (bestSequence>=0) infeasibilityWeight_=-1.0; currentWanted_=numberWanted; } } /* Creates a variable. This is called after partial pricing and may modify matrix. May update bestSequence. */ void ClpDynamicExampleMatrix::createVariable(ClpSimplex * model, int & bestSequence) { int numberRows = model->numberRows(); int slackOffset = lastDynamic_+numberRows; int structuralOffset = slackOffset+numberSets_; int bestSequence2=savedBestSequence_-structuralOffset; if (bestSequence2>=0) { // See if needs new if (bestSequence2>=maximumGubColumns_) { bestSequence2 -= maximumGubColumns_; int sequence = addColumn(startColumnGen_[bestSequence2+1]-startColumnGen_[bestSequence2], rowGen_+startColumnGen_[bestSequence2], elementGen_+startColumnGen_[bestSequence2], costGen_[bestSequence2], columnLowerGen_ ? columnLowerGen_[bestSequence2] : 0, columnUpperGen_ ? columnUpperGen_[bestSequence2] : 1.0e30, savedBestSet_,getDynamicStatusGen(bestSequence2)); savedBestSequence_ = structuralOffset + sequence; idGen_[sequence]=bestSequence2; setDynamicStatusGen(bestSequence2,inSmall); } } ClpDynamicMatrix::createVariable(model,bestSequence); // clear for next iteration savedBestSequence_=-1; } /* If addColumn forces compression then this allows descendant to know what to do. If >=0 then entry stayed in, if -1 then entry went out to lower bound.of zero. Entries at upper bound (really nonzero) never go out (at present). */ void ClpDynamicExampleMatrix::packDown(const int * in, int numberToPack) { int put=0; for (int i=0;i=0) { // stays in assert (put==in[i]); // true for now idGen_[put++]=id; } else { // out to lower bound setDynamicStatusGen(id,atLowerBound); } } assert (put==numberGubColumns_); }