// Copyright (C) 2000, International Business Machines // Corporation and others. All Rights Reserved. #if defined(_MSC_VER) // Turn off compiler warning about long names # pragma warning(disable:4786) #endif #include #include "CoinPackedMatrix.hpp" #include "OsiFmpSolverInterface.hpp" #include "OsiCuts.hpp" #include "OsiRowCut.hpp" #include "OsiColCut.hpp" //############################################################################# // A helper function that converts a packed matrix into a columnordered // gap-free matrix. //############################################################################# static const CoinPackedMatrix * toColumnOrderedGapFree(const CoinPackedMatrix& matrix) { CoinPackedMatrix * m = 0; if (matrix.isColOrdered()) { const CoinBigIndex * start = matrix.getVectorStarts(); const int * length = matrix.getVectorLengths(); int i; for (i = matrix.getNumCols() - 1; i >= 0; --i) if (start[i+1] - start[i] != length[i]) break; if (i >= 0) { // got to get rid of the gaps m = new CoinPackedMatrix(); m->setExtraGap(0.0); m->setExtraMajor(0.0); m->operator=(matrix); } } else { // must create a column ordered copy without gaps m = new CoinPackedMatrix(); m->setExtraGap(0.0); m->setExtraMajor(0.0); m->reverseOrderedCopyOf(matrix); } return m ? m : &matrix; } //############################################################################# // Solve methods //############################################################################# void OsiFmpSolverInterface::initialSolve() { int tctn=0; char loglev[5]; char scmd[80]; // Switch off printing if asked to bool takeHint; OsiHintStrength strength; bool gotHint = getHintParam(OsiDoReducePrint,takeHint,strength); assert(gotHint); // Set the appropriate FortMP log level if (strength!=OsiHintIgnore&&takeHint) { itoa(messageHandler()->logLevel(),loglev,10); strcpy(scmd,"LOG DISPLAY LEVEL "); strcat(scmd,loglev); SPECMDC(scmd,&tctn); } char tmpname[128]; strcpy(tmpname,modelname_.c_str()); // Set direction of the optimisation... if(isMax_) { strcpy(scmd,"MAX"); SPECMDC(scmd,&tctn); } else { strcpy(scmd,"MIN"); SPECMDC(scmd,&tctn); } strcpy(scmd,"MIP OFF"); SPECMDC(scmd,&tctn); //PAT removed it temporarily // strcpy(scmd,"PRESOLVE ON"); // SPECMDC(scmd,&tctn); // if there is no basis, allocates and use crash start if(basis_==NULL) { basis_=new int[nc_+nr_+1]; strcpy(scmd,"SIMPLEX START CRASH"); SPECMDC(scmd,&tctn); } // Call the solver SUBLP2C(&nr_, &nc_, &nz_, &ns_, tmpname,"NOSPECS ", aij_, rowin_, colin_, upb_, lob_, rhs_, lhs_, cost_, mitype_, sref_, sfun_, sbeg_, send_, &objconstant_, &obj_, sol_, dsl_, basis_, &stsl_, &tctn); // If presolve fails, try without /* if (tctn==550) { tctn=0; strcpy(scmd,"PRESOLVE OFF"); SPECMDC(scmd,&tctn); // Call the solver SUBLP2C(&nr_, &nc_, &nz_, &ns_, tmpname,"NOSPECS ", aij_, rowin_, colin_, upb_, lob_, rhs_, lhs_, cost_, mitype_, sref_, sfun_, sbeg_, send_, &objconstant_, &obj_, sol_, dsl_, basis_, &stsl_, &tctn); } */ // If an error occoured, set stsl to -1, used as abandoned state if (tctn!=0) stsl_=-1; } //----------------------------------------------------------------------------- void OsiFmpSolverInterface::resolve() { int tctn=0; char loglev[5]; char scmd[80]; // Switch off printing if asked to bool takeHint; OsiHintStrength strength; bool gotHint = getHintParam(OsiDoReducePrint,takeHint,strength); assert(gotHint); if (strength!=OsiHintIgnore&&takeHint) { itoa(messageHandler()->logLevel(),loglev,10); strcpy(scmd,"LOG DISPLAY LEVEL "); strcat(scmd,loglev); SPECMDC(scmd,&tctn); } char tmpname[128]; strcpy(tmpname,modelname_.c_str()); // Set direction of the optimisation... if(isMax_) { strcpy(scmd,"MAX"); SPECMDC(scmd,&tctn); } else { strcpy(scmd,"MIN"); SPECMDC(scmd,&tctn); } strcpy(scmd,"MIP OFF"); SPECMDC(scmd,&tctn); if(basis_==NULL) basis_=new int[nc_+nr_+1]; else { strcpy(scmd,"SIMPLEX START INPUT BASIS"); SPECMDC(scmd,&tctn); } SUBLP2C(&nr_, &nc_, &nz_, &ns_, tmpname,"NOSPECS ", aij_, rowin_, colin_, upb_, lob_, rhs_, lhs_, cost_, mitype_, sref_, sfun_, sbeg_, send_, &objconstant_, cost_, sol_, dsl_ , basis_, &stsl_, &tctn); // If an error occoured, set stsl to -1, used as abandoned state if (tctn!=0) stsl_=-1; } //----------------------------------------------------------------------------- void OsiFmpSolverInterface::branchAndBound() { int tctn=0; char loglev[5]; char scmd[80]; // Switch off printing if asked to bool takeHint; OsiHintStrength strength; bool gotHint = getHintParam(OsiDoReducePrint,takeHint,strength); assert(gotHint); if (strength!=OsiHintIgnore&&takeHint) { itoa(messageHandler()->logLevel(),loglev,10); strcpy(scmd,"LOG DISPLAY LEVEL "); strcat(scmd,loglev); SPECMDC(scmd,&tctn); } char tmpname[128]; strcpy(tmpname,modelname_.c_str()); // Set direction of the optimisation... if(isMax_) { strcpy(scmd,"MAX"); SPECMDC(scmd,&tctn); } else { strcpy(scmd,"MIN"); SPECMDC(scmd,&tctn); } // Enable branch and bound strcpy(scmd,"MIP ON"); SPECMDC(scmd,&tctn); if(basis_==NULL) basis_=new int[nc_+nr_+1]; else { strcpy(scmd,"SIMPLEX START INPUT BASIS"); SPECMDC(scmd,&tctn); } SUBLP2C(&nr_, &nc_, &nz_, &ns_, tmpname,"NOSPECS ", aij_, rowin_, colin_, upb_, lob_, rhs_, lhs_, cost_, mitype_, sref_, sfun_, sbeg_, send_, &objconstant_, cost_, sol_, dsl_ , basis_, &stsl_, &tctn); // If an error occoured, set stsl to -1, used as abandoned state if (tctn!=0) stsl_=-1; } //############################################################################# // Parameter related methods //############################################################################# bool OsiFmpSolverInterface::setIntParam(OsiIntParam key, int value) { int tctn; char scmd[80]; char val[20]; // transforms the argument into a string itoa(value,val,10); switch (key) { case OsiMaxNumIteration: if (value < 0) return false; // send SPEC command to FortMP strcpy(scmd,"MAXIMUM SIMPLEX ITERATIONS = "); strcat(scmd,val); SPECMDC(scmd,&tctn); // also store the value for retrival OsiSolverInterface::setIntParam(key, value); return tctn == 0; break; case OsiMaxNumIterationHotStart: if (value < 0) return false; OsiSolverInterface::setIntParam(key, value); break; case OsiLastIntParam: return false; } return true; } //----------------------------------------------------------------------------- bool OsiFmpSolverInterface::setDblParam(OsiDblParam key, double value) { int tctn=0; char scmd[80]; char val[20]; // transform the argument into a string gcvt(value,15,val); switch (key) { case OsiDualObjectiveLimit: return OsiSolverInterface::setDblParam(key, value); case OsiPrimalObjectiveLimit: return OsiSolverInterface::setDblParam(key, value); case OsiDualTolerance: // send spec command to FortMP strcpy(scmd,"DUAL PIVOT ZERO TOLERANCE = "); strcat(scmd,val); SPECMDC(scmd,&tctn); // only store the value if successful if(tctn==0) OsiSolverInterface::setDblParam(key, value); return tctn == 0; case OsiPrimalTolerance: // Primal tolerance fixed in FortMP if(value==1e-35) return true; else return false; case OsiObjOffset: objconstant_=value; return true; case OsiLastDblParam: return false; } return true; } //----------------------------------------------------------------------------- bool OsiFmpSolverInterface::setStrParam(OsiStrParam key, const std::string & value) { switch (key) { case OsiProbName: modelname_=value.c_str(); return true; case OsiSolverName: return false; case OsiLastStrParam: return false; } return false; } //----------------------------------------------------------------------------- bool OsiFmpSolverInterface::getIntParam(OsiIntParam key, int& value) const { switch (key) { case OsiMaxNumIteration: ;//PAT value = ekk_getImaxiter(getMutableModelPtr()); break; case OsiMaxNumIterationHotStart: OsiSolverInterface::getIntParam(key, value); break; case OsiLastIntParam: return false; } return true; } //----------------------------------------------------------------------------- bool OsiFmpSolverInterface::getDblParam(OsiDblParam key, double& value) const { // *THINK* : how to set opt limits for OSL? switch (key) { case OsiDualObjectiveLimit: OsiSolverInterface::getDblParam(key, value); break; case OsiPrimalObjectiveLimit: OsiSolverInterface::getDblParam(key, value); break; case OsiDualTolerance: OsiSolverInterface::getDblParam(key, value); ;//PAT value = ekk_getRtoldinf(getMutableModelPtr()); break; case OsiPrimalTolerance: value=1e-35; // OsiSolverInterface::getDblParam(key, value); ;//PAT value = ekk_getRtolpinf(getMutableModelPtr()); break; case OsiObjOffset: value=objconstant_; break; case OsiLastDblParam: return false; } return true; } //----------------------------------------------------------------------------- bool OsiFmpSolverInterface::getStrParam(OsiStrParam key, std::string & value) const { switch (key) { case OsiProbName: ;//PAT value = ekk_getCname(getMutableModelPtr()); break; case OsiSolverName: value = "FortMP"; break; case OsiLastStrParam: return false; } return true; } //############################################################################# // Methods returning info on how the solution process terminated //############################################################################# bool OsiFmpSolverInterface::isAbandoned() const { ;//PAT EKKModel* model = getMutableModelPtr(); ;//PAT return (ekk_getIprobstat(model)==6); return true; } bool OsiFmpSolverInterface::isProvenOptimal() const { return (stsl_ == 3 || stsl_==5); } bool OsiFmpSolverInterface::isProvenPrimalInfeasible() const { return (stsl_ == 1); } bool OsiFmpSolverInterface::isProvenDualInfeasible() const { return (stsl_ == 2); } bool OsiFmpSolverInterface::isPrimalObjectiveLimitReached() const { // *TEST* double limit = 0.0; getDblParam(OsiPrimalObjectiveLimit, limit); if (limit > 1e30) { // was not ever set return false; } ;//PAT EKKModel* model = getMutableModelPtr(); ;//PAT if (ekk_getIprobstat(model)==6) ;//PAT return false; ;//PAT const int lastalgo = ekk_lastAlgorithm(model); ;//PAT const double obj = ekk_getRobjvalue(model); ;//PAT const double maxmin = ekk_getRmaxmin(model); ;//PAT switch (lastalgo) { ;//PAT case 0: // no simplex was needed ;//PAT return maxmin > 0 ? (obj < limit) /*minim*/ : (obj > limit) /*maxim*/; ;//PAT case 2: // dual simplex ;//PAT if (ekk_getIprobstat(model) == 0) // optimal ;//PAT return maxmin > 0 ? (obj < limit) /*minim*/ : (obj > limit) /*maxim*/; ;//PAT return false; ;//PAT case 1: // primal simplex ;//PAT return maxmin > 0 ? (obj < limit) /*minim*/ : (obj > limit) /*maxim*/; ;//PAT } return false; // fake return } bool OsiFmpSolverInterface::isDualObjectiveLimitReached() const { // *TEST* double limit = 0.0; getDblParam(OsiDualObjectiveLimit, limit); if (limit > 1e30) { // was not ever set return false; } ;//PAT EKKModel* model = getMutableModelPtr(); ;//PAT if (ekk_getIprobstat(model)==6) ;//PAT return false; ;//PAT const int lastalgo = ekk_lastAlgorithm(model); ;//PAT const double obj = ekk_getRobjvalue(model); ;//PAT const double maxmin = ekk_getRmaxmin(model); ;//PAT switch (lastalgo) { ;//PAT case 0: // no simplex was needed ;//PAT return maxmin > 0 ? (obj > limit) /*minim*/ : (obj < limit) /*maxim*/; ;//PAT case 1: // primal simplex ;//PAT if (ekk_getIprobstat(model) == 0) // optimal ;//PAT return maxmin > 0 ? (obj > limit) /*minim*/ : (obj < limit) /*maxim*/; ;//PAT return false; ;//PAT case 2: // dual simplex ;//PAT if (ekk_getIprobstat(model) != 0 && ekk_getIprobstat2(model) == 11) // over dual limit ;//PAT return true; ;//PAT return maxmin > 0 ? (obj > limit) /*minim*/ : (obj < limit) /*maxim*/; ;//PAT } return false; // fake return } bool OsiFmpSolverInterface::isIterationLimitReached() const { // *TEST* ;//PAT EKKModel* model = getMutableModelPtr(); ;//PAT if (ekk_getIprobstat(model)==6) ;//PAT return false; ;//PAT const int stat = ekk_getIprobstat(model); ;//PAT return (stat == 3); return true; } //############################################################################# // WarmStart related methods //############################################################################# CoinWarmStart* OsiFmpSolverInterface::getWarmStart() const { // *TEST* ;//PAT EKKModel* model = getMutableModelPtr(); const int numcols = getNumCols(); const int numrows = getNumRows(); CoinWarmStartBasis* ws = new CoinWarmStartBasis; if(basis_==NULL) { return ws; } ws->setSize(numcols, numrows); int i; for (i = 0; i < numrows; ++i) { switch(basis_[i+1]) { case 0: ws->setArtifStatus(i, CoinWarmStartBasis::basic); break; case -1: ws->setArtifStatus(i, CoinWarmStartBasis::atLowerBound); break; case 1: ws->setArtifStatus(i, CoinWarmStartBasis::atUpperBound); break; } } for (i = 0; i < numcols; ++i) { switch(basis_[numrows+i+1]) { case 0: ws->setStructStatus(i, CoinWarmStartBasis::basic); break; case -1: ws->setStructStatus(i, CoinWarmStartBasis::atLowerBound); break; case 1: ws->setStructStatus(i, CoinWarmStartBasis::atUpperBound); break; } } return ws; } //----------------------------------------------------------------------------- bool OsiFmpSolverInterface::setWarmStart(const CoinWarmStart* warmstart) { // *TEST* const CoinWarmStartBasis* ws = dynamic_cast(warmstart); if (! ws) return false; const int numcols = ws->getNumStructural(); const int numrows = ws->getNumArtificial(); // The number of structural and artificial // must be consistent with the current model if(numcols!=nc_ || numrows!=nr_) return false; if(nc_ ==0 && nr_==0) return true; // Allocates a new basis vector if it isn't there if(basis_==NULL) basis_=new int[1+nc_+nr_]; int i; basis_[0]=0; // The first row represents the objective for (i = 0; i < numrows; ++i) { switch (ws->getArtifStatus(i)) { case CoinWarmStartBasis::atUpperBound: basis_[i+1]=1; break; case CoinWarmStartBasis::atLowerBound: basis_[i+1]=-1; break; case CoinWarmStartBasis::basic: basis_[i+1]=0; break; case CoinWarmStartBasis::isFree: // FortMP cannot distinguish them basis_[i+1]=-1; break; } } for (i = 0; i < numcols; ++i) { switch (ws->getStructStatus(i)) { case CoinWarmStartBasis::atUpperBound: basis_[nr_+i+1]=1; break; case CoinWarmStartBasis::atLowerBound: basis_[nr_+i+1]=-1; break; case CoinWarmStartBasis::basic: basis_[nr_+i+1]=0; break; case CoinWarmStartBasis::isFree: // superbasic basis_[nr_+i+1]=-1; break; } } return true; } //############################################################################# // Hotstart related methods (primarily used in strong branching) //############################################################################# void OsiFmpSolverInterface::markHotStart() { // PAT todo delete ws_; ws_ = dynamic_cast(getWarmStart()); // ekk_startFastDualSimplex(model, itlim); } void OsiFmpSolverInterface::solveFromHotStart() { ;//PAT EKKModel* model = getMutableModelPtr(); // *TEST* ;//PAT ekk_setIiternum(model, 0); setWarmStart(ws_); // ekk_fastDualSimplex(model); ;//PAT itlimOrig_ = ekk_getImaxiter(model); int itlim; OsiSolverInterface::getIntParam(OsiMaxNumIterationHotStart, itlim); ;//PAT ekk_setImaxiter(model, itlim); resolve(); ;//PAT ekk_setImaxiter(model, itlimOrig_); } void OsiFmpSolverInterface::unmarkHotStart() { // *TEST* ;//PAT EKKModel* model = getMutableModelPtr(); // ekk_stopFastDualSimplex(model); ;//PAT ekk_setImaxiter(model, itlimOrig_); delete ws_; ws_ = NULL; } //############################################################################# // Problem information methods (original data) //############################################################################# //------------------------------------------------------------------ // Get number of rows, columns and elements //------------------------------------------------------------------ int OsiFmpSolverInterface::getNumCols() const { return nc_; } int OsiFmpSolverInterface::getNumRows() const { return nr_; } int OsiFmpSolverInterface::getNumElements() const { return nz_; } //------------------------------------------------------------------ // Get pointer to rim vectors //------------------------------------------------------------------ const double * OsiFmpSolverInterface::getColLower() const { return lob_; } //------------------------------------------------------------------ const double * OsiFmpSolverInterface::getColUpper() const { return upb_; } //------------------------------------------------------------------ const char * OsiFmpSolverInterface::getRowSense() const { extractSenseRhsRange(); return rowsense_; } //------------------------------------------------------------------ const double * OsiFmpSolverInterface::getRightHandSide() const { extractSenseRhsRange(); return rowrhs_; } //------------------------------------------------------------------ const double * OsiFmpSolverInterface::getRowRange() const { extractSenseRhsRange(); return rowrange_; } //------------------------------------------------------------------ const double * OsiFmpSolverInterface::getRowLower() const { return lhs_; } //------------------------------------------------------------------ const double * OsiFmpSolverInterface::getRowUpper() const { return rhs_; } //------------------------------------------------------------------ const double * OsiFmpSolverInterface::getObjCoefficients() const { return cost_; } //------------------------------------------------------------------ double OsiFmpSolverInterface::getObjSense() const { if(isMax_) return -1; else return 1; } //------------------------------------------------------------------ // Return information on integrality //------------------------------------------------------------------ bool OsiFmpSolverInterface::isContinuous(int colNumber) const { if(mitype_[colNumber]!=0) return false; return true; } //------------------------------------------------------------------ #if 0 bool OsiFmpSolverInterface::isInteger( int columnNumber ) const { return !(isContinuous(columnNumber)); } //------------------------------------------------------------------ bool OsiFmpSolverInterface::isBinary( int columnNumber ) const { //PAT check... if(mitype_[columnNumber]==1) return true; return false; } //------------------------------------------------------------------ bool OsiFmpSolverInterface::isIntegerNonBinary( int columnNumber ) const { if(mitype_[columnNumber]==2) return true; return false; } //------------------------------------------------------------------ bool OsiFmpSolverInterface::isFreeBinary( int columnNumber ) const { if ( isContinuous(columnNumber)) return false; if ((upb_[columnNumber]== 1) && (lob_[columnNumber]== 0)) return true; else return false; } #endif //------------------------------------------------------------------ // Row and column copies of the matrix ... //------------------------------------------------------------------ const CoinPackedMatrix * OsiFmpSolverInterface::getMatrixByRow() const { if ( matrixByRow_ == NULL ) { int i,p; CoinBigIndex *starts=new CoinBigIndex[nr_+1]; int *counts=new int[nr_]; int *indices=new int[nz_]; double *values=new double[nz_]; CoinFillN(indices,nz_,0); CoinFillN(counts,nr_,0); // counts the non zeroes for each row for(i=0;icopyOf(false, getNumCols(), getNumRows(), getNumElements(), values,indices,starts, NULL); delete[] starts; delete[] indices; delete[] counts; delete[] values; } return matrixByRow_; } //------------------------------------------------------------------ const CoinPackedMatrix * OsiFmpSolverInterface::getMatrixByCol() const { if ( matrixByColumn_ == NULL ) { int i,p; CoinBigIndex *starts=new CoinBigIndex[nc_+1]; int *counts=new int[nc_]; int *indices=new int[nz_]; double *values=new double[nz_]; CoinFillN(indices,nz_,0); CoinFillN(counts,nc_,0); // counts the non zeroes for each column for(i=0;icopyOf(true, getNumRows(),getNumCols(), getNumElements(), values,indices,starts, NULL); delete[] starts; delete[] indices; delete[] counts; delete[] values; } return matrixByColumn_; } //------------------------------------------------------------------ // Get solver's value for infinity //------------------------------------------------------------------ double OsiFmpSolverInterface::getInfinity() const { ;//PAT return 1e30; } //############################################################################# // Problem information methods (results) //############################################################################# const double * OsiFmpSolverInterface::getColSolution() const { if(sol_) return &sol_[nr_+1]; else return NULL; } //------------------------------------------------------------------ const double * OsiFmpSolverInterface::getRowPrice() const { if(dsl_) return &dsl_[1]; else return NULL; } //------------------------------------------------------------------ const double * OsiFmpSolverInterface::getReducedCost() const { if(dsl_) return &dsl_[nr_+1]; else return NULL; } //------------------------------------------------------------------ const double * OsiFmpSolverInterface::getRowActivity() const { if(sol_) return &sol_[1]; else return NULL; } //------------------------------------------------------------------ double OsiFmpSolverInterface::getObjValue() const { if(stsl_!=0) { return obj_; } else return OsiSolverInterface::getObjValue(); } //------------------------------------------------------------------ int OsiFmpSolverInterface::getIterationCount() const { int ssxiter, ipmiter, mipnode; double ssxtim, ipmtim, xovtim, miptim; GTVALS(&ssxiter, &ipmiter, &mipnode, &ssxtim, &ipmtim, &xovtim, &miptim); return ssxiter; } //------------------------------------------------------------------ std::vector OsiFmpSolverInterface::getDualRays(int maxNumRays) const { const int m = getNumRows(); double* ray = new double[m]; ;//PAT const double* negray = ekk_rowaux(getMutableModelPtr()); ;//PAT for (int i = 0; i < m; ++i) { ;//PAT ray[i] = -negray[i]; ;//PAT } return std::vector(1, ray); } //------------------------------------------------------------------ std::vector OsiFmpSolverInterface::getPrimalRays(int maxNumRays) const { const int n = getNumCols(); double* ray = new double[n]; ;//PAT CoinDisjointCopyN(ekk_colaux(getMutableModelPtr()), n, ray); return std::vector(1, ray); } //------------------------------------------------------------------ #if 0 OsiVectorInt OsiFmpSolverInterface::getFractionalIndices(const double etol) const { OsiVectorInt retVal; EKKModel * m = getMutableModelPtr(); int numInts = ekk_getInumints(m); int * intInx = ekk_listOfIntegers(m); const double * colSolVec = ekk_colsol(m); OsiAbsFltEq eq(etol); for ( int i=0; i=0 && index0); } //----------------------------------------------------------------------------- void OsiFmpSolverInterface::setColSolution(const double * cs) { int i; if(sol_==NULL) { sol_=new double[1+nr_+nc_]; CoinFillN(sol_,1+nr_+nc_,0.0); } for(i=0;igetNumElements(); // allocates new vectors nrowin= new int[nz_+nz]; ncolin= new int[nz_+nz]; naij= new double[nz_+nz]; nlob=new double[nc_+numcols]; nupb=new double[nc_+numcols]; nobj=new double[nc_+numcols]; nmitype=new int[nc_+numcols]; // copy old problem into new vectors memcpy(nrowin,rowin_,sizeof(int)*nz_); memcpy(ncolin,colin_,sizeof(int)*nz_); memcpy(naij,aij_,sizeof(double)*nz_); memcpy(nlob,lob_,sizeof(double)*nc_); memcpy(nupb,upb_,sizeof(double)*nc_); memcpy(nobj,cost_,sizeof(double)*nc_); memcpy(nmitype,mitype_,sizeof(int)*nc_); // release old copy delete[] rowin_; delete[] colin_; delete[] aij_; delete[] lob_; delete[] upb_; delete[] mitype_; delete[] cost_; // Set pointers to new vectors rowin_=nrowin; colin_=ncolin; aij_=naij; lob_=nlob; upb_=nupb; mitype_=nmitype; cost_=nobj; // Finally, copy contents // NOTE: The internal matrix is no longer column ordered... CoinDisjointCopyN(collb,numcols,lob_ + nc_); CoinDisjointCopyN(colub,numcols,upb_ + nc_); CoinDisjointCopyN(obj,numcols,cost_ + nc_); CoinFillN(mitype_ + nc_,numcols,0); nz = 0; for (i = 0; i < numcols; ++i) { const CoinPackedVectorBase* col = cols[i]; const int len = col->getNumElements(); // copy the column indices CoinDisjointCopyN(col->getIndices(), len, rowin_ + nz_ +nz); // copy the non zero values for(j=0;jgetElements(), len, aij_ + nz_ +nz); CoinFillN(colin_ + nz_ + nz, len, nc_ + i +1); nz += len; } // Update dimensions.. nz_+=nz; nc_+=numcols; // Allocate solution space... AllocSolutionSpace(); } //----------------------------------------------------------------------------- void OsiFmpSolverInterface::deleteCols(const int num, const int * columnIndices) { // *TEST* // ekk_deleteColumns(getModelPtr(), num, columnIndices); } //----------------------------------------------------------------------------- void OsiFmpSolverInterface::addRow(const CoinPackedVectorBase& vec, const double rowlb, const double rowub) { const CoinPackedVectorBase *pvec = &vec; addRows(1,&pvec,&rowlb,&rowub); } //----------------------------------------------------------------------------- void OsiFmpSolverInterface::addRow(const CoinPackedVectorBase& vec, const char rowsen, const double rowrhs, const double rowrng) { const CoinPackedVectorBase *pvec = &vec; addRows(1,&pvec,&rowsen,&rowrhs,&rowrng); } //----------------------------------------------------------------------------- void OsiFmpSolverInterface::addRows(const int numrows, const CoinPackedVectorBase * const * rows, const double* rowlb, const double* rowub) { freeCachedResults(); double *naij,*nlhs,*nrhs; int *nrowin,*ncolin; int i,j; int nz = 0; for (i = 0; i < numrows; ++i) nz += rows[i]->getNumElements(); // allocates new vectors nrowin= new int[nz_+nz]; ncolin= new int[nz_+nz]; naij= new double[nz_+nz]; nlhs=new double[nr_+numrows]; nrhs=new double[nr_+numrows]; // copy old problem into new vectors memcpy(nrowin,rowin_,sizeof(int)*nz_); memcpy(ncolin,colin_,sizeof(int)*nz_); memcpy(naij,aij_,sizeof(double)*nz_); memcpy(nlhs,lhs_,sizeof(double)*nr_); memcpy(nrhs,rhs_,sizeof(double)*nr_); // release old copy delete[] rowin_; delete[] colin_; delete[] aij_; delete[] lhs_; delete[] rhs_; // Set pointers to new vectors rowin_=nrowin; colin_=ncolin; aij_=naij; lhs_=nlhs; rhs_=nrhs; // Finally, copy contents // NOTE: The matrix is no longer column ordered... nz = 0; for (i = 0; i < numrows; ++i) { rhs_[nr_ + i]=rowub[i]; lhs_[nr_ + i]=rowlb[i]; const CoinPackedVectorBase* row = rows[i]; const int len = row->getNumElements(); // copy the column indices CoinDisjointCopyN(row->getIndices(), len, colin_ + nz_ +nz); // Add offset of 1 used by FortMP for(j=0;jgetElements(), len, aij_ + nz_ +nz); CoinFillN(rowin_ + nz_ + nz, len, nr_ + i + 1); nz += len; } // Update dimensions.. nz_+=nz; nr_+=numrows; AllocSolutionSpace(); } //----------------------------------------------------------------------------- void OsiFmpSolverInterface::addRows(const int numrows, const CoinPackedVectorBase * const * rows, const char* rowsen, const double* rowrhs, const double* rowrng) { freeCachedResults(); double *naij,*nlhs,*nrhs; int *nrowin,*ncolin; int i,j; int nz = 0; for (i = 0; i < numrows; ++i) nz += rows[i]->getNumElements(); // allocates new vectors nrowin= new int[nz_+nz]; ncolin= new int[nz_+nz]; naij= new double[nz_+nz]; nlhs=new double[nr_+numrows]; nrhs=new double[nr_+numrows]; // copy old problem into new vectors memcpy(nrowin,rowin_,sizeof(int)*nz_); memcpy(ncolin,colin_,sizeof(int)*nz_); memcpy(naij,aij_,sizeof(double)*nz_); memcpy(nlhs,lhs_,sizeof(double)*nr_); memcpy(nrhs,rhs_,sizeof(double)*nr_); // release old copy delete[] rowin_; delete[] colin_; delete[] aij_; delete[] lhs_; delete[] rhs_; // Set pointers to new vectors rowin_=nrowin; colin_=ncolin; aij_=naij; lhs_=nlhs; rhs_=nrhs; // Finally, copy contents // NOTE: The cached matrix is no longer column ordered... nz = 0; for (i = 0; i < numrows; ++i) { convertSenseToBound(rowsen[i], rowrhs[i], rowrng[i], rhs_[nr_ + i], lhs_[nr_ + i]); const CoinPackedVectorBase* row = rows[i]; const int len = row->getNumElements(); // copy the column indices CoinDisjointCopyN(row->getIndices(), len, colin_ + nz_ +nz); // Add offset of 1 used by FortMP for(j=0;jgetElements(), len, aij_ + nz_ +nz); CoinFillN(rowin_ + nz_ + nz, len, nr_ + i +1); nz += len; } // Update dimensions.. nz_+=nz; nr_+=numrows; AllocSolutionSpace(); } //----------------------------------------------------------------------------- void OsiFmpSolverInterface::deleteRows(const int num, const int * rowIndices) { /* This is going to be expensive! */ } //############################################################################# // Methods to input a problem //############################################################################# void OsiFmpSolverInterface::loadProblem(const CoinPackedMatrix& matrix, const double* collb, const double* colub, const double* obj, const double* rowlb, const double* rowub) { const CoinPackedMatrix * m = toColumnOrderedGapFree(matrix); loadProblem(m->getNumCols(), m->getNumRows(), m->getVectorStarts(), m->getIndices(), m->getElements(), collb, colub, obj, rowlb, rowub); if (m != &matrix) delete m; } //----------------------------------------------------------------------------- void OsiFmpSolverInterface::assignProblem(CoinPackedMatrix*& matrix, double*& collb, double*& colub, double*& obj, double*& rowlb, double*& rowub) { loadProblem(*matrix, collb, colub, obj, rowlb, rowub); delete matrix; matrix = 0; delete[] collb; collb = 0; delete[] colub; colub = 0; delete[] obj; obj = 0; delete[] rowlb; rowlb = 0; delete[] rowub; rowub = 0; } //----------------------------------------------------------------------------- void OsiFmpSolverInterface::loadProblem(const CoinPackedMatrix& matrix, const double* collb, const double* colub, const double* obj, const char* rowsen, const double* rowrhs, const double* rowrng) { const CoinPackedMatrix * m = toColumnOrderedGapFree(matrix); loadProblem(m->getNumCols(), m->getNumRows(), m->getVectorStarts(), m->getIndices(), m->getElements(), collb, colub, obj, rowsen, rowrhs, rowrng); if (m != &matrix) delete m; } //----------------------------------------------------------------------------- void OsiFmpSolverInterface::assignProblem(CoinPackedMatrix*& matrix, double*& collb, double*& colub, double*& obj, char*& rowsen, double*& rowrhs, double*& rowrng) { loadProblem(*matrix, collb, colub, obj, rowsen, rowrhs, rowrng); delete matrix; matrix = 0; delete[] collb; collb = 0; delete[] colub; colub = 0; delete[] obj; obj = 0; delete[] rowsen; rowsen = 0; delete[] rowrhs; rowrhs = 0; delete[] rowrng; rowrng = 0; } //----------------------------------------------------------------------------- void OsiFmpSolverInterface::loadProblem(const int numcols, const int numrows, const CoinBigIndex * start, const int* index, const double* value, const double* collb, const double* colub, const double* obj, const double* rowlb, const double* rowub) { int i; //freeCachedResults(); nc_=numcols; nr_=numrows; nz_= start[numcols]; //TEST // allocates memory if(nr_ && nc_ && nz_) { lhs_= new double[nr_]; rhs_= new double[nr_]; lob_= new double[nc_]; upb_= new double[nc_]; cost_= new double[nc_]; aij_= new double[nz_]; rowin_= new int[nz_]; colin_= new int[nz_]; mitype_= new int[nc_]; //all variables are continuous unless otherwise specified CoinFillN(mitype_,nc_,0); } else return; // copy column information if(collb!=NULL) CoinDisjointCopyN(collb,nc_,lob_); else CoinFillN(lob_,nc_,0.0); if(colub!=NULL) CoinDisjointCopyN(colub,nc_,upb_); else CoinFillN(upb_,nc_,getInfinity()); if(obj!=NULL) CoinDisjointCopyN(obj,nc_,cost_); else CoinFillN(cost_,nc_,0.0); // copy row information if(rowlb!=NULL) CoinDisjointCopyN(rowlb,nr_,lhs_); else CoinFillN(lhs_,nr_,-getInfinity()); if(rowub!=NULL) CoinDisjointCopyN(rowub,nr_,rhs_); else CoinFillN(rhs_,nr_,getInfinity()); int j=0; for(i=0;i=start[j+1]) j++; colin_[i]=j+1; rowin_[i]=index[i]+1; aij_[i]=value[i]; } AllocSolutionSpace(); } //----------------------------------------------------------------------------- void OsiFmpSolverInterface::loadProblem(const int numcols, const int numrows, const CoinBigIndex * start, const int* index, const double* value, const double* collb, const double* colub, const double* obj, const char* rowsen, const double* rowrhs, const double* rowrng) { assert( rowsen != NULL ); assert( rowrhs != NULL ); double * rowlb = new double[numrows]; double * rowub = new double[numrows]; for (int i = numrows-1; i >= 0; --i) { convertSenseToBound(rowsen[i],rowrhs[i],rowrng[i],rowlb[i],rowub[i]); } loadProblem(numcols, numrows, start, index, value, collb, colub, obj, rowlb, rowub); delete[] rowlb; delete[] rowub; } //----------------------------------------------------------------------------- // Read mps files //----------------------------------------------------------------------------- int OsiFmpSolverInterface::readMps(const char *filename, const char *extension) { return OsiSolverInterface::readMps(filename, extension); } //----------------------------------------------------------------------------- // Write mps files //----------------------------------------------------------------------------- void OsiFmpSolverInterface::writeMps(const char * filename, const char * extension, double objSense) const { std::string f(filename); std::string e(extension); std::string fullname; if (e!="") { fullname = f + "." + e; } else { fullname = f; } OsiFmpSolverInterface::writeMpsNative(fullname.c_str(),NULL,NULL); } //############################################################################# // OSL specific public interfaces //############################################################################# #if 0 EKKModel * OsiFmpSolverInterface::getModelPtr() { freeCachedResults(); return getMutableModelPtr(); } //------------------------------------------------------------------- void OsiFmpSolverInterface::incrementInstanceCounter() { if ( numInstances_ == 0 ) { contextPtr_ = ekk_initializeContext(); assert( contextPtr_ != NULL ); ekk_messagesPrintOff(ekk_baseModel(contextPtr_), 1, 5999); //FILE *oslMesgFILE = fopen("osl.log","a+"); //ekk_setLogfileFilePointer(ekk_baseModel(contextPtr_),stderr ); //ekk_messagesPrintOn(NULL ,1,2999); } numInstances_++; } //------------------------------------------------------------------- void OsiFmpSolverInterface::decrementInstanceCounter() { assert( getNumInstances() != 0 ); numInstances_--; if ( numInstances_ == 0 ) { //FILE * oslMesgFile = // ekk_getLogfileFilePointer(ekk_baseModel(contextPtr_)); //fclose(oslMesgFile); ekk_endContext(contextPtr_); contextPtr_ = NULL; } } //------------------------------------------------------------------- unsigned int OsiFmpSolverInterface::getNumInstances() { return numInstances_; } #endif //############################################################################# // Constructors, destructors clone and assignment //############################################################################# //------------------------------------------------------------------- // Default Constructor //------------------------------------------------------------------- OsiFmpSolverInterface::OsiFmpSolverInterface () : OsiSolverInterface() { stsl_=0; nr_=0; nc_=0; nz_=0; ns_=0; nq_=0; isMax_=0; objconstant_=0; obj_=0; // Reset pointers send_=NULL; sref_=NULL; sfun_=NULL; sbeg_=NULL; rowin_=NULL; colin_=NULL; aij_=NULL; mitype_=NULL; upb_=NULL; lob_=NULL; cost_=NULL; rhs_=NULL; lhs_=NULL; basis_=NULL; sol_=NULL; dsl_=NULL; modelname_=""; rowsense_=NULL; rowrhs_=NULL; rowrange_=NULL; matrixByRow_=NULL; matrixByColumn_=NULL; ws_ = NULL; int tctn; BLDFMPC(&tctn); // PAT: The following doesn't work... need to find out why //BFMPCBC(NULL,NULL,NULL,(Xph2cb) CBIterCountP2,NULL,NULL); } //------------------------------------------------------------------- // Clone //------------------------------------------------------------------- OsiSolverInterface * OsiFmpSolverInterface::clone(bool CopyData) const { if (CopyData) { return new OsiFmpSolverInterface(*this); } else { return new OsiFmpSolverInterface(); } } #if 0 //------------------------------------------------------------------- // Alternate Constructor //------------------------------------------------------------------- OsiFmpSolverInterface::OsiFmpSolverInterface (EKKModel * m) : OsiSolverInterface(), modelPtr_(m) { // nothing to do here } #endif //------------------------------------------------------------------- // Copy constructor //------------------------------------------------------------------- OsiFmpSolverInterface::OsiFmpSolverInterface ( const OsiFmpSolverInterface & source) : OsiSolverInterface(source) { stsl_=0; nr_=0; nc_=0; nz_=0; ns_=0; nq_=0; isMax_=0; objconstant_=0; obj_=0; // Reset pointers send_=NULL; sref_=NULL; sfun_=NULL; sbeg_=NULL; rowin_=NULL; colin_=NULL; aij_=NULL; mitype_=NULL; upb_=NULL; lob_=NULL; cost_=NULL; rhs_=NULL; lhs_=NULL; basis_=NULL; sol_=NULL; dsl_=NULL; modelname_=""; rowsense_=NULL; rowrhs_=NULL; rowrange_=NULL; matrixByRow_=NULL; matrixByColumn_=NULL; ws_ = NULL; nc_=source.nc_; nr_=source.nr_; nz_=source.nz_; ns_=source.ns_; nq_=source.nq_; isMax_=source.isMax_; objconstant_=source.objconstant_; if(nr_) { lhs_= new double[nr_]; rhs_= new double[nr_]; // copy row information CoinDisjointCopyN(source.lhs_,nr_,lhs_); CoinDisjointCopyN(source.rhs_,nr_,rhs_); } if(nc_) { lob_= new double[nc_]; upb_= new double[nc_]; cost_=new double[nc_]; mitype_= new int[nc_]; // copy column information CoinDisjointCopyN(source.lob_,nc_,lob_); CoinDisjointCopyN(source.upb_,nc_,upb_); CoinDisjointCopyN(source.cost_,nc_,cost_); CoinDisjointCopyN(source.mitype_,nc_,mitype_); } if(ns_) { send_= new int[ns_]; sbeg_= new int[ns_]; sfun_=new int[ns_]; sref_= new int[ns_]; // copy column information CoinDisjointCopyN(source.send_,ns_,send_); CoinDisjointCopyN(source.sref_,ns_,sref_); CoinDisjointCopyN(source.sbeg_,ns_,sbeg_); CoinDisjointCopyN(source.sfun_,ns_,sfun_); } if(nz_) { aij_= new double[nz_]; rowin_= new int[nz_]; colin_= new int[nz_]; // copy matrix CoinDisjointCopyN(source.colin_,nz_,colin_); CoinDisjointCopyN(source.rowin_,nz_,rowin_); CoinDisjointCopyN(source.aij_,nz_,aij_); } modelname_=source.modelname_; AllocSolutionSpace(); /* if(source.basis_!=NULL) { basis_=new int[1+nr_+nc_]; CoinDisjointCopyN(source.basis_,1+nr_+nc_,basis_); } if(source.sol_!=NULL) { sol_=new double[1+nr_+nc_]; CoinDisjointCopyN(source.sol_,1+nr_+nc_,sol_); } if(source.dsl_!=NULL) { dsl_=new double[1+nr_+nc_]; CoinDisjointCopyN(source.dsl_,1+nr_+nc_,dsl_); } if(source.rowsense_!=NULL) { rowsense_ = new char[nr_]; rowrhs_ = new double[nr_]; rowrange_ = new double[nr_]; CoinDisjointCopyN(source.rowsense_,nr_,rowsense_); CoinDisjointCopyN(source.rowrhs_,nr_,rowrhs_); CoinDisjointCopyN(source.rowrange_,nr_,rowrange_); } if(ws_!=NULL) setWarmStart(source.getWarmStart()); */ // PAT todo... } //------------------------------------------------------------------- // Destructor //------------------------------------------------------------------- OsiFmpSolverInterface::~OsiFmpSolverInterface () { int tctn; gutsOfDestructor(); ;//PAT decrementInstanceCounter(); UNBFMPC(&tctn); } //------------------------------------------------------------------- // Assignment operator //------------------------------------------------------------------- OsiFmpSolverInterface & OsiFmpSolverInterface::operator=(const OsiFmpSolverInterface& rhs) { if (this != &rhs) { OsiSolverInterface::operator=(rhs); gutsOfDestructor(); nc_=rhs.nc_; nr_=rhs.nr_; nz_=rhs.nz_; ns_=rhs.ns_; nq_=rhs.nq_; isMax_=rhs.isMax_; objconstant_=rhs.objconstant_; if(nr_) { lhs_= new double[nr_]; rhs_= new double[nr_]; // copy row information CoinDisjointCopyN(rhs.lhs_,nr_,lhs_); CoinDisjointCopyN(rhs.rhs_,nr_,rhs_); } if(nc_) { lob_= new double[nc_]; upb_= new double[nc_]; cost_=new double[nc_]; mitype_= new int[nc_]; // copy column information CoinDisjointCopyN(rhs.lob_,nc_,lob_); CoinDisjointCopyN(rhs.upb_,nc_,upb_); CoinDisjointCopyN(rhs.cost_,nc_,cost_); CoinDisjointCopyN(rhs.mitype_,nc_,mitype_); } if(ns_) { send_= new int[ns_]; sbeg_= new int[ns_]; sfun_=new int[ns_]; sref_= new int[ns_]; // copy column information CoinDisjointCopyN(rhs.send_,ns_,send_); CoinDisjointCopyN(rhs.sref_,ns_,sref_); CoinDisjointCopyN(rhs.sbeg_,ns_,sbeg_); CoinDisjointCopyN(rhs.sfun_,ns_,sfun_); } if(nz_) { aij_= new double[nz_]; rowin_= new int[nz_]; colin_= new int[nz_]; // copy matrix CoinDisjointCopyN(rhs.colin_,nz_,colin_); CoinDisjointCopyN(rhs.rowin_,nz_,rowin_); CoinDisjointCopyN(rhs.aij_,nz_,aij_); } modelname_=rhs.modelname_; AllocSolutionSpace(); /* should not copy cached information ... why? if(rhs.basis_!=NULL) { basis_=new int[1+nr_+nc_]; CoinDisjointCopyN(rhs.basis_,1+nr_+nc_,basis_); } if(rhs.sol_!=NULL) { sol_=new double[1+nr_+nc_]; CoinDisjointCopyN(rhs.sol_,1+nr_+nc_,sol_); } if(rhs.dsl_!=NULL) { dsl_=new double[1+nr_+nc_]; CoinDisjointCopyN(rhs.dsl_,1+nr_+nc_,dsl_); } if(rhs.rowsense_!=NULL) { rowsense_ = new char[nr_]; rowrhs_ = new double[nr_]; rowrange_ = new double[nr_]; CoinDisjointCopyN(rhs.rowsense_,nr_,rowsense_); CoinDisjointCopyN(rhs.rowrhs_,nr_,rowrhs_); CoinDisjointCopyN(rhs.rowrange_,nr_,rowrange_); } if(ws_!=NULL) setWarmStart(rhs.getWarmStart()); */ // PAT todo... } return *this; } //############################################################################# // Applying cuts //############################################################################# void OsiFmpSolverInterface::applyRowCut( const OsiRowCut & rowCut ) { freeCachedResults(); const CoinPackedVector & row=rowCut.row(); addRow(row,rowCut.lb(),rowCut.ub()); } //----------------------------------------------------------------------------- void OsiFmpSolverInterface::applyColCut( const OsiColCut & cc ) { const CoinPackedVector lbs = cc.lbs(); const CoinPackedVector ubs = cc.ubs(); int i; for ( i=0; i lob_[lbs.getIndices()[i]]) lob_[lbs.getIndices()[i]]=lbs.getElements()[i]; } for ( i=0; i0 || nr_>0) { sol_=new double[nc_+nr_+1]; dsl_=new double[nc_+nr_+1]; CoinFillN(dsl_,nc_+nr_+1,0.0); //sets variables to their lower bound CoinCopyN(lob_,nc_,&sol_[nr_+1]); } } int OsiFmpSolverInterface::CBIterCountP2(int iter,double obj) { return 1; }