00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035 #ifndef DecompAlgo_h_
00036 #define DecompAlgo_h_
00037
00038
00044
00045
00046
00047 #include "Decomp.h"
00048 #include "DecompApp.h"
00049 #include "DecompParam.h"
00050 #include "DecompStats.h"
00051 #include "DecompVarPool.h"
00052 #include "DecompCutPool.h"
00053 #include "DecompMemPool.h"
00054 #include "DecompSolution.h"
00055 #include "DecompAlgoCGL.h"
00056 #include "AlpsDecompTreeNode.h"
00057 #include "OsiClpSolverInterface.hpp"
00058 class OsiSolverInterface;
00059 class DecompConstraintSet;
00060 class DecompSolverResult;
00061
00062
00063 class DecompAlgo {
00064
00065 protected:
00066
00067
00072
00076 std::string m_classTag;
00077
00081 DecompParam m_param;
00082
00086 DecompAlgoType m_algo;
00087
00091 DecompStatus m_status;
00092
00096 DecompPhase m_phase;
00097 DecompPhase m_phaseLast;
00098 DecompPhase m_phaseForce;
00099
00103 DecompApp* m_app;
00104
00108 DecompStats m_stats;
00109 DecompNodeStats m_nodeStats;
00110
00114 DecompMemPool m_memPool;
00115
00119 std::ostream* m_osLog;
00120
00121 DecompAlgoCGL* m_cgl;
00122
00128 std::vector<double> m_origColLB;
00129 std::vector<double> m_origColUB;
00130
00134
00135
00142 OsiSolverInterface* m_masterSI;
00143
00144 #ifdef __DECOMP_IP_SYMPHONY__
00145 OsiSymSolverInterface* osi_Sym;
00146 CoinWarmStart* ws;
00147 #endif
00148
00154 OsiClpSolverInterface* m_cutgenSI;
00155 int m_cutgenObjCutInd;
00156 OsiSolverInterface* m_auxSI;
00157
00158
00159 const double* m_objective;
00160 DecompAlgoModel m_modelCore;
00161 std::map<int, DecompAlgoModel> m_modelRelax;
00162 std::map<int, std::vector<DecompAlgoModel> > m_modelRelaxNest;
00163
00164
00168 DecompVarList m_vars;
00169 DecompVarPool m_varpool;
00170
00174 DecompCutList m_cuts;
00175 DecompCutPool m_cutpool;
00176
00180 double* m_xhat;
00181
00186 double m_cutoffUB;
00187
00188 std::vector<DecompSolution*> m_xhatIPFeas;
00189 DecompSolution* m_xhatIPBest;
00190
00191
00192
00193 std::vector<double> m_primSolution;
00194 std::vector<double> m_dualSolution;
00195 std::vector<double> m_reducedCost;
00196 int m_numCols;
00197
00198 bool m_isColGenExact;
00199
00200 UtilParameters* m_utilParam;
00201
00202 int m_numConvexCon;
00203
00204
00205 int m_rrLastBlock;
00206 int m_rrIterSinceAll;
00207
00208
00209 int m_nArtCols;
00210
00211
00212 int m_nRowsOrig;
00213 int m_nRowsBranch;
00214 int m_nRowsConvex;
00215 int m_nRowsCuts;
00216 std::vector<DecompRowType> m_masterRowType;
00217 std::vector<DecompColType> m_masterColType;
00218 std::vector<int> m_masterArtCols;
00219
00220
00221 double* m_colLBNode;
00222 double* m_colUBNode;
00223
00224 int m_compressColsLastPrice;
00225 int m_compressColsLastNumCols;
00226
00230 double m_relGap;
00231
00232 DecompAlgoStop m_stopCriteria;
00233 int m_colIndexUnique;
00234 double m_masterObjLast;
00235 bool m_objNoChange;
00236
00237
00238 double m_stabEpsilon;
00239 bool m_useInitLpDuals;
00240 std::map<int, int> m_artColIndToRowInd;
00241
00242 double m_globalLB;
00243 double m_globalUB;
00244
00245 std::vector<double> m_phaseIObj;
00246
00247 int m_function;
00248 bool m_firstPhase2Call;
00249 bool m_isStrongBranch;
00250
00251 const AlpsDecompTreeNode* m_curNode;
00252
00253 std:: vector<int> m_masterOnlyCols;
00257 std::map<int, int> m_masterOnlyColsMap;
00258
00259
00260 double tempTimeLimit;
00261
00262
00263
00264
00265 DecompBranchingImplementation m_branchingImplementation;
00266
00267
00268
00269 public:
00273
00278
00282
00283 virtual void createMasterProblem(DecompVarList& initVars);
00284 void loadSIFromModel(OsiSolverInterface* si,
00285
00286
00287
00288 bool doInt = false);
00289
00290
00296
00297 virtual void recomposeSolution(const double* solution,
00298 double* rsolution);
00303
00308
00312 virtual DecompStatus processNode(const AlpsDecompTreeNode* node,
00313 const double globalLB = -DecompInf,
00314 const double globalUB = DecompInf);
00315
00320 const AlpsDecompTreeNode* getCurrentNode() const {
00321 return m_curNode;
00322 };
00323
00329 virtual void postProcessNode(DecompStatus decompStatus) {};
00330
00336 virtual void postProcessBranch(DecompStatus decompStatus) {};
00337
00342
00343 virtual int generateInitVars(DecompVarList& initVars);
00344
00348 virtual DecompStatus
00349 solutionUpdate(const DecompPhase phase,
00350 const bool resolve = true,
00351 const int maxInnerIter = COIN_INT_MAX,
00352 const int maxOuterIter = COIN_INT_MAX);
00353
00357 virtual void phaseUpdate(DecompPhase& phase,
00358 DecompStatus& status);
00359
00363 virtual void phaseInit(DecompPhase& phase) {
00364 if (getNodeIndex() == 0) {
00365 phase = PHASE_PRICE1;
00366 }
00367 }
00368
00372 virtual void phaseDone() {};
00373
00377 virtual bool updateObjBound(const double mostNegRC = -DecompBigNum);
00378
00379
00380 virtual void solutionUpdateAsIP() {}
00381
00382 virtual int adjustColumnsEffCnt() {
00383 return DecompStatOk;
00384 };
00385 virtual int compressColumns () {
00386 return DecompStatOk;
00387 };
00391 bool isGapTight() {
00392
00393 double tightGap = m_param.MasterGapLimit;
00394
00395
00396 if (m_param.LogDebugLevel >= 2) {
00397 (*m_osLog) << "DW GAP = " << UtilDblToStr(m_relGap)
00398 << " isTight = " << (m_relGap <= tightGap)
00399 << "\n";
00400 }
00401
00402 if (m_relGap <= tightGap) {
00403 return true;
00404 } else {
00405 return false;
00406 }
00407 }
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417
00418 virtual bool isDone() {
00419 if ((m_nodeStats.cutsThisCall + m_nodeStats.varsThisCall) > 0) {
00420 return false;
00421 } else {
00422 return true;
00423 }
00424 }
00425
00426
00427
00428 std::vector<double*> getDualRays(int maxNumRays);
00429 virtual int generateVarsFea(DecompVarList& newVars,
00430 double& mostNegReducedCost);
00431
00432 virtual int generateVars(const DecompStatus stat,
00433 DecompVarList& newVars,
00434 double& mostNegReducedCost);
00435 virtual int generateCuts(double* xhat,
00436 DecompCutList& newCuts);
00437
00438 virtual void addVarsToPool(DecompVarList& newVars);
00439 virtual void addVarsFromPool();
00440 virtual void addCutsToPool(const double* x,
00441 DecompCutList& newCuts,
00442 int& m_cutsThisCall);
00443 virtual int addCutsFromPool();
00444
00445 bool isIPFeasible(const double* x,
00446 const bool isXSparse = false,
00447 const double feasVarTol = 1.0e-6,
00448 const double feasConTol = 1.0e-5,
00449 const double intTol = 1.0e-5);
00450
00451 bool isLPFeasible(const double* x,
00452 const bool isXSparse = false,
00453 const double feasVarTol = 1.0e-6,
00454 const double feasConTol = 1.0e-5);
00455
00456
00457 DecompStatus solveRelaxed(const double* redCostX,
00458 const double* origCost,
00459 const double alpha,
00460 const int n_origCols,
00461 const bool isNested,
00462 DecompAlgoModel& algoModel,
00463 DecompSolverResult* solveResult,
00464 std::list<DecompVar*>& vars);
00465
00466
00467 inline void appendVars(DecompVar* var) {
00468 m_vars.push_back(var);
00469 }
00470 inline void appendVars(DecompVarList& varList) {
00471 copy(varList.begin(), varList.end(), back_inserter(m_vars));
00472 }
00473 virtual void setMasterBounds(const double* lbs,
00474 const double* ubs);
00475 virtual void setSubProbBounds(const double* lbs,
00476 const double* ubs);
00477
00478
00479
00480 virtual bool
00481 chooseBranchSet(std::vector< std::pair<int, double> >& downBranchLb,
00482 std::vector< std::pair<int, double> >& downBranchUb,
00483 std::vector< std::pair<int, double> >& upBranchLb,
00484 std::vector< std::pair<int, double> >& upBranchUb);
00485
00486
00487
00488
00489
00494
00498 void initSetup(UtilParameters* utilParam,
00499 std::string& sectionParam);
00500 void getModelsFromApp();
00501 void createOsiSubProblem(DecompAlgoModel& algoModel);
00502
00506
00507
00508
00509
00510
00511
00512
00513
00514
00515
00516
00517
00518
00522 void coreMatrixAppendColBounds();
00523 void checkMasterDualObj();
00524 bool checkPointFeasible(const DecompConstraintSet* modelCore,
00525 const double* x);
00526 bool isDualRayInfProof(const double* dualRay,
00527 const CoinPackedMatrix* rowMatrix,
00528 const double* colLB,
00529 const double* colUB,
00530 const double* rowRhs,
00531 std::ostream* os);
00532 bool isDualRayInfProofCpx(const double* dualRay,
00533 const CoinPackedMatrix* rowMatrix,
00534 const double* colLB,
00535 const double* colUB,
00536 const double* rowRhs,
00537 std::ostream* os);
00538
00539 void printBasisInfo(OsiSolverInterface* si,
00540 std::ostream* os);
00541
00542
00546 void printCurrentProblemDual(OsiSolverInterface* si,
00547 const std::string baseName,
00548 const int nodeIndex,
00549 const int cutPass,
00550 const int pricePass);
00551
00552 void printCurrentProblem(const OsiSolverInterface* si,
00553 const std::string baseName,
00554 const int nodeIndex,
00555 const int cutPass,
00556 const int pricePass,
00557 const int blockId = -1,
00558 const bool printMps = true,
00559 const bool printLp = true);
00563 void printCurrentProblem(const OsiSolverInterface* si,
00564 const std::string fileName,
00565 const bool printMps = true,
00566 const bool printLp = true);
00567
00571 void printVars(std::ostream* os);
00572 void printCuts(std::ostream* os);
00573
00577 void createFullMps(const std::string fileName);
00578
00582 virtual DecompSolverResult*
00583 solveDirect(const DecompSolution* startSol = NULL) {
00584 return NULL;
00585 }
00586
00587
00588 void masterMatrixAddMOCols(CoinPackedMatrix* masterM,
00589 double* colLB,
00590 double* colUB,
00591 double* objCoeff,
00592 std::vector<std::string>& colNames);
00593
00594 void masterMatrixAddArtCol(std::vector<CoinBigIndex>& colBeg,
00595 std::vector<int >& colInd,
00596 std::vector<double >& colVal,
00597 char LorG,
00598 int rowIndex,
00599 int colIndex,
00600 DecompColType colType,
00601 double& colLB,
00602 double& colUB,
00603 double& objCoeff);
00604
00605 virtual void masterMatrixAddArtCols(CoinPackedMatrix* masterM,
00606 double* colLB,
00607 double* colUB,
00608 double* objCoeff,
00609 std::vector<std::string>& colNames,
00610 int startRow,
00611 int endRow,
00612 DecompRowType rowType);
00613 void masterPhaseItoII();
00614 void masterPhaseIItoI();
00615
00616 bool isMasterColMasterOnly(const int index) const {
00617 return (m_masterColType[index] == DecompCol_MasterOnly);
00618 }
00619 bool isMasterColStructural(const int index) const {
00620 return (m_masterColType[index] == DecompCol_Structural ||
00621 m_masterColType[index] == DecompCol_Structural_NoDelete);
00622 }
00623 bool isMasterColArtificial(const int index) const {
00624 return (m_masterColType[index] == DecompCol_ArtForRowL ||
00625 m_masterColType[index] == DecompCol_ArtForRowG ||
00626 m_masterColType[index] == DecompCol_ArtForBranchL ||
00627 m_masterColType[index] == DecompCol_ArtForBranchG ||
00628 m_masterColType[index] == DecompCol_ArtForConvexL ||
00629 m_masterColType[index] == DecompCol_ArtForConvexG ||
00630 m_masterColType[index] == DecompCol_ArtForCutL ||
00631 m_masterColType[index] == DecompCol_ArtForCutG);
00632 }
00633
00634 void breakOutPartial(const double* xHat,
00635 DecompVarList& newVars,
00636 const double intTol = 1.0e-5);
00637
00642 void generateVarsAdjustDuals(const double* uOld,
00643 double* uNew);
00648 void generateVarsCalcRedCost(const double* u,
00649 double* redCostX);
00650
00651
00652
00653
00659
00664
00665 inline const double* getColLBNode() const {
00666 return m_colLBNode;
00667 }
00668 inline const double* getColUBNode() const {
00669 return m_colUBNode;
00670 }
00671
00672
00673
00674
00675 inline DecompStats& getStats() {
00676 return m_stats;
00677 }
00678
00679 inline const double* getOrigObjective() const {
00680 return m_app->m_objective;
00681 }
00682 inline const DecompAlgoModel& getModelCore() const {
00683 return m_modelCore;
00684 }
00685
00686 inline const int getAlgo() const {
00687 return m_algo;
00688 }
00689
00690 inline const DecompParam& getParam() const {
00691 return m_param;
00692 }
00693
00694 inline DecompParam& getMutableParam() {
00695 return m_param;
00696 }
00697
00698 inline OsiSolverInterface* getMasterOSI() {
00699 return m_masterSI;
00700 }
00701
00702 inline DecompAlgoModel& getModelRelax(const int blockId) {
00703 std::map<int, DecompAlgoModel>::iterator mit;
00704 mit = m_modelRelax.find(blockId);
00705 assert(mit != m_modelRelax.end());
00706 return (*mit).second;
00707 }
00708
00709
00713 inline const double* getXhat() const {
00714 return m_xhat;
00715 }
00716
00717 inline void setCutoffUB(const double thisBound) {
00718 m_cutoffUB = thisBound;
00719 setObjBoundIP(thisBound);
00720 }
00721
00722
00723 inline const DecompSolution* getXhatIPBest() const {
00724 return m_xhatIPBest;
00725 }
00726
00727 inline const std::vector<DecompSolution*>& getXhatIPFeas() const {
00728 return m_xhatIPFeas;
00729 }
00730
00731 inline const double getCutoffUB() const {
00732 return m_cutoffUB;
00733 }
00734
00735 inline DecompStats& getDecompStats() {
00736 return m_stats;
00737 }
00738
00739 inline const DecompParam& getDecompParam() const {
00740 return m_param;
00741 }
00742
00743 inline const DecompApp* getDecompApp() const {
00744 return m_app;
00745 }
00746 inline DecompApp* getDecompAppMutable() {
00747 return m_app;
00748 }
00749
00750 inline const int getNodeIndex() const {
00751 return m_nodeStats.nodeIndex;
00752 }
00753
00754 inline const int getCutCallsTotal() const {
00755 return m_nodeStats.cutCallsTotal;
00756 }
00757
00758 inline const int getPriceCallsTotal() const {
00759 return m_nodeStats.priceCallsTotal;
00760 }
00761
00765 inline const double* getMasterPrimalSolution() const {
00766 return &m_primSolution[0];
00767 }
00768
00769 inline const double* getMasterColReducedCost() const {
00770 return &m_reducedCost[0];
00771 }
00775 virtual const double* getMasterDualSolution() const {
00776 return &m_dualSolution[0];
00777 }
00778
00782 virtual void adjustMasterDualSolution() {};
00783
00784
00785 inline double getMasterObjValue() const {
00786 if (!m_masterSI) {
00787 return -DecompInf;
00788 }
00789
00790
00791 int nc = static_cast<int>(m_primSolution.size());
00792 const double* objCoef = m_masterSI->getObjCoefficients();
00793 const double* primSol = getMasterPrimalSolution();
00794 double retVal = 0.0;
00795
00796 for ( int i = 0 ; i < nc ; i++ ) {
00797 retVal += objCoef[i] * primSol[i];
00798 }
00799
00800 return retVal;
00801 }
00802
00803 inline const int getStopCriteria() const {
00804 return m_stopCriteria;
00805 }
00806
00810 inline const double getGlobalGap() const {
00811 return UtilCalculateGap(m_globalLB, m_globalUB);
00812 }
00813
00817 inline const double getNodeIPGap() const {
00818 return UtilCalculateGap(getObjBestBoundLB(), getObjBestBoundUB());
00819 }
00820
00824 inline const double getNodeLPGap() const {
00825 int nHistorySize
00826 = static_cast<int>(m_nodeStats.objHistoryBound.size());
00827
00828 if (nHistorySize > 0) {
00829 const DecompObjBound& objBound
00830 = m_nodeStats.objHistoryBound[nHistorySize - 1];
00831 return UtilCalculateGap(getObjBestBoundLB(), objBound.thisBoundUB);
00832 } else {
00833 return DecompInf;
00834 }
00835 }
00836
00840 inline const double getObjBestBoundLB() const {
00841 return m_nodeStats.objBest.first;
00842 }
00843
00847 inline const void setStrongBranchIter(bool isStrongBranch = true) {
00848 m_isStrongBranch = isStrongBranch;
00849 }
00850
00854 inline const double getObjBestBoundUB() const {
00855 return m_nodeStats.objBest.second;
00856 }
00857
00861 inline const double getMasterRowType(int row) const {
00862 return m_masterRowType[row];
00863 }
00864
00868 virtual void setObjBound(const double thisBound,
00869 const double thisBoundUB) {
00870 UtilPrintFuncBegin(m_osLog, m_classTag,
00871 "setObjBound()", m_param.LogDebugLevel, 2);
00872
00873 if (thisBound > m_nodeStats.objBest.first) {
00874 m_nodeStats.objBest.first = thisBound;
00875
00876 if (getNodeIndex() == 0) {
00877 m_globalLB = thisBound;
00878 }
00879 }
00880
00881 DecompObjBound objBound;
00882 objBound.phase = m_phase == PHASE_PRICE1 ? 1 : 2;
00883 objBound.cutPass = m_nodeStats.cutCallsTotal;
00884 objBound.pricePass = m_nodeStats.priceCallsTotal;
00885 objBound.thisBound = thisBound;
00886 objBound.thisBoundUB = thisBoundUB;
00887 objBound.bestBound = m_nodeStats.objBest.first;
00888 objBound.bestBoundIP = m_nodeStats.objBest.second;
00889 #ifdef UTIL_USE_TIMERS
00890 objBound.timeStamp = globalTimer.getRealTime();
00891 #else
00892 objBound.timeStamp = -1;
00893 #endif
00894 m_nodeStats.objHistoryBound.push_back(objBound);
00895 UtilPrintFuncEnd(m_osLog, m_classTag,
00896 "setObjBound()", m_param.LogDebugLevel, 2);
00897 }
00898
00902 virtual inline void setObjBoundIP(const double thisBound) {
00903 UtilPrintFuncBegin(m_osLog, m_classTag,
00904 "setObjBoundIP()", m_param.LogDebugLevel, 2);
00905
00906 if (thisBound < m_nodeStats.objBest.second) {
00907 UTIL_MSG(m_app->m_param.LogDebugLevel, 3,
00908 (*m_osLog) << "New Global UB = "
00909 << UtilDblToStr(thisBound) << std::endl;);
00910 m_nodeStats.objBest.second = thisBound;
00911 }
00912
00913
00914
00915
00916 DecompObjBound objBoundIP;
00917 DecompObjBound* objBoundLP = m_nodeStats.getLastBound();
00918
00919 if (objBoundLP) {
00920 objBoundIP = *objBoundLP;
00921 }
00922
00923 objBoundIP.thisBoundIP = thisBound;
00924 objBoundIP.bestBoundIP = m_nodeStats.objBest.second;
00925 #ifdef UTIL_USE_TIMERS
00926 objBoundIP.timeStamp = globalTimer.getRealTime();
00927 #else
00928 objBoundIP.timeStamp = -1;
00929 #endif
00930 m_nodeStats.objHistoryBound.push_back(objBoundIP);
00931 UtilPrintFuncEnd(m_osLog, m_classTag,
00932 "setObjBoundIP()", m_param.LogDebugLevel, 2);
00933 }
00934
00935
00936 bool isTailoffLB(const int changeLen = 10,
00937 const double changePerLimit = 0.1);
00938
00939
00940 inline int getNumRowType(DecompRowType rowType) {
00941 int nRowsType = 0;
00942 std::vector<DecompRowType>::iterator vi;
00943
00944 for (vi = m_masterRowType.begin(); vi != m_masterRowType.end(); vi++) {
00945 if (*vi == rowType) {
00946 nRowsType++;
00947 }
00948 }
00949
00950 return nRowsType;
00951 }
00952
00953 void checkBlocksColumns();
00954
00955
00960
00961
00962
00963
00964
00965
00966
00967
00972
00973 public:
00977 DecompAlgo(const DecompAlgoType algo,
00978 DecompApp* app,
00979 UtilParameters* utilParam):
00980 m_classTag ("D-ALGO"),
00981 m_param (),
00982 m_algo (algo),
00983 m_status (STAT_UNKNOWN),
00984 m_phase (PHASE_UNKNOWN),
00985 m_phaseLast (PHASE_UNKNOWN),
00986 m_phaseForce (PHASE_UNKNOWN),
00987 m_app (app),
00988 m_stats (),
00989 m_nodeStats (),
00990 m_memPool (),
00991 m_osLog (&std::cout),
00992 m_cgl (0),
00993 m_origColLB (),
00994 m_origColUB (),
00995 m_masterSI (0),
00996 m_cutgenSI (NULL),
00997 m_cutgenObjCutInd(-1),
00998 m_auxSI (NULL),
00999 m_vars (),
01000 m_varpool (),
01001 m_cuts (),
01002 m_cutpool (),
01003 m_xhat (0),
01004 m_cutoffUB (DecompInf),
01005 m_xhatIPFeas (),
01006 m_xhatIPBest (NULL),
01007 m_isColGenExact(false),
01008 m_utilParam (utilParam),
01009 m_numConvexCon (1),
01010 m_rrLastBlock (-1),
01011 m_rrIterSinceAll(0),
01012
01013 m_colLBNode(NULL),
01014 m_colUBNode(NULL),
01015 m_relGap(DecompInf),
01016 m_stopCriteria(DecompStopNo),
01017 m_masterObjLast(DecompInf),
01018 m_firstPhase2Call(false),
01019 m_isStrongBranch(false),
01020 m_masterOnlyCols(),
01021 tempTimeLimit(0),
01022 m_branchingImplementation(DecompBranchInSubproblem) {
01023 m_app->m_decompAlgo = this;
01024 }
01025
01026
01030 virtual ~DecompAlgo() {
01031
01032 UTIL_DELPTR(m_masterSI);
01033 UTIL_DELPTR(m_cutgenSI);
01034 UTIL_DELPTR(m_auxSI);
01035 UTIL_DELARR(m_xhat);
01036 UTIL_DELPTR(m_cgl);
01037 UtilDeleteVectorPtr(m_xhatIPFeas);
01038 UtilDeleteListPtr(m_vars);
01039 UtilDeleteListPtr(m_cuts);
01040 UTIL_DELARR(m_colLBNode);
01041 UTIL_DELARR(m_colUBNode);
01042 }
01049 };
01050
01051 #endif