diff --git a/.clang-format b/.clang-format index 517168b4b..3c7203170 100644 --- a/.clang-format +++ b/.clang-format @@ -17,7 +17,7 @@ AllowShortLoopsOnASingleLine: false AlwaysBreakAfterDefinitionReturnType: None AlwaysBreakAfterReturnType: None AlwaysBreakBeforeMultilineStrings: false -AlwaysBreakTemplateDeclarations: MultiLine +AlwaysBreakTemplateDeclarations: false BinPackArguments: true BinPackParameters: true BraceWrapping: @@ -39,7 +39,7 @@ BraceWrapping: BreakBeforeBinaryOperators: All BreakBeforeBraces: WebKit BreakBeforeInheritanceComma: false -BreakInheritanceList: BeforeColon +#BreakInheritanceList: BeforeColon BreakBeforeTernaryOperators: true BreakConstructorInitializersBeforeComma: false BreakConstructorInitializers: BeforeComma @@ -85,7 +85,7 @@ PenaltyBreakBeforeFirstCallParameter: 19 PenaltyBreakComment: 300 PenaltyBreakFirstLessLess: 120 PenaltyBreakString: 1000 -PenaltyBreakTemplateDeclaration: 10 +#PenaltyBreakTemplateDeclaration: 10 PenaltyExcessCharacter: 1000000 PenaltyReturnTypeOnItsOwnLine: 60 PointerAlignment: Right @@ -97,7 +97,7 @@ SpaceAfterTemplateKeyword: true SpaceBeforeAssignmentOperators: true SpaceBeforeCpp11BracedList: true SpaceBeforeCtorInitializerColon: true -SpaceBeforeInheritanceColon: true +#SpaceBeforeInheritanceColon: true SpaceBeforeParens: ControlStatements SpaceBeforeRangeBasedForLoopColon: true SpaceInEmptyParentheses: false diff --git a/.github/workflows/windows-ci.yml b/.github/workflows/windows-ci.yml index 6615e41a6..765c74203 100644 --- a/.github/workflows/windows-ci.yml +++ b/.github/workflows/windows-ci.yml @@ -24,10 +24,8 @@ jobs: { os: windows-2019, arch: x86_64, msystem: mingw64, debug: false, suffix: "" }, { os: windows-2019, arch: i686, msystem: mingw32, debug: true, suffix: "-dbg" }, { os: windows-2019, arch: i686, msystem: mingw32, debug: false, suffix: "" }, - { os: windows-2019, arch: msvc, msystem: mingw64, debug: true, suffix: "-mdd" }, { os: windows-2019, arch: msvc, msystem: mingw64, debug: false, suffix: "-md" }, - { os: windows-2016, arch: msvc, msystem: mingw64, debug: true, suffix: "-mdd" }, - { os: windows-2016, arch: msvc, msystem: mingw64, debug: false, suffix: "-md" }, + { os: windows-2022, arch: msvc, msystem: mingw64, debug: false, suffix: "-md" }, ] steps: - name: Checkout source diff --git a/CbcSourceFilesTable.csv b/CbcSourceFilesTable.csv deleted file mode 100644 index ab4aa5bbf..000000000 --- a/CbcSourceFilesTable.csv +++ /dev/null @@ -1,61 +0,0 @@ -Filename,Group,Person,Status,Age,CPP Lines,HPP Lines,Total Lines,libCbc,cbcSolve,cbcGeneric,Other Projects,First Object,Other Objects,Comment -CbcBranchActual.cpp,Branch,Edwin,,8,5340,1823,7163,x,,,,Multiple,"CbcClique, CbcSos, CbcSimpleInteger, CbcIntegerBranchingObject, CbcSimpleIntegerPseudoCost, CbcIntegerPseudoCostBranchingObject, CbcCliqueBranchingObject, CbcLongCliqueBranchingObject, CbcSosBranchingObject, CbcBranchDefaultDecision, CbcFollowOn, CbcFixingBranchingObject, CbcNWay, CbcNWayBranchingObject, CbcFixVariable, CbcDummyBranchingObject, CbcGeneral, CbcGeneralDepth, CbcGeneralBranchingObject, CbcOneGeneralBranchingObject, CbcSubProblem", -CbcBranchBase.cpp,Branch,Edwin,,10,352,707,1059,x,,,,CbcObject,"CbcBranchingObject, CbcBranchDecision, CbcConsequence, CbcObjectUpdateData", -CbcBranchCut.cpp,Branch,Edwin,,10,1023,315,1338,x,,,,CbcBranchCut,"CbcCutBranchingObject, CbcBranchToFixLots, CbcBranchAllDifferent", -CbcBranchDynamic.cpp,Branch,Edwin,,8,1911,557,2468,x,,,,CbcSimpleIntegerDynamicPseudoCost,"CbcDynamicPseudoCostBranchingObject, CbcBranchDynamicDecision", -CbcBranchLotsize.cpp,Branch,Edwin,,15,809,250,1059,x,,,,CbcLotsize,CbcLotsizeBranchingObject, -CbcCbcParam.cpp,Solver,Bjarni,,24,1,,1,x,,,,"#include ""CbcOrClpParam.cpp""",, -CbcCompareActual.cpp,Compare,,,8,463,165,628,x,,,,CbcCompareDepth,"CbcCompareObjective, CbcCompareDefault, CbcCompareEstimate", -CbcCompareBase.hpp,Compare,,,24,,170,170,x,,,,CbcCompareBase,"CbcCompare, CbcChooseVariable", -CbcConfig.h,,,,20,,102,102,x,,,,#defines,, -CbcCountRowCut.cpp,,,,10,126,115,241,x,,,,CbcCountRowCut,, -CbcCutGenerator.cpp,,,,2,1223,510,1733,x,,,,CbcCutGenerator,"CbcCutModifier, CbcCutSubsetModifier", -CbcEventHandler.cpp,,,,36,101,221,322,x,,,,CbcEventHandler,, -CbcFathom.cpp,,,,19,106,126,232,x,,,,CbcFathom,CbcOsiSolver, -CbcFathomDynamicProgramming.cpp,,,,10,1051,166,1217,x,,,,CbcFathomDynamicProgramming,, -CbcFeasibilityBase.hpp,,,,24,,53,53,x,,,,CbcFeasibilityBase,, -CbcGenBaB.cpp,Generic,Lou,,14,886,,886,,,x,,namespace CbcGenParamUtils,namespace,The support functions for the main branch-and-cut action routine. -CbcGenCbcParam.cpp,Generic,Lou,,24,155,189,344,,,x,,CbcCbcParam,,Constructors and destructors for CbcCbcParam -CbcGenCbcParamUtils.cpp,Generic,Lou,,18,401,,401,,,x,,namespace CbcCbcParamUtils,,Implementation functions for CbcGenParam parameters. -CbcGenCtlBlk.cpp,Generic,Lou,,24,681,948,1629,x,,x,,CbcGenCtlBlk,,Constructor for cbc-generic control block. -CbcGeneric.cpp,Generic,Lou,,24,415,,415,,,x,,namespace CbcGenSolvers,namespace,Unnamed local namespace for cbc-generic support types and functions. -CbcGenMessages.cpp,Generic,Lou,,24,192,,192,x,,,,CbcGenCtlBlk,,Message definitions. -CbcGenOsiParam.cpp,Generic,Lou,,24,156,197,353,,,x,,CbcOsiParam,,Constructors and destructors for CbcOsiParam -CbcGenOsiParamUtils.cpp,Generic,Lou,,18,528,,528,,,x,,namespace CbcOsiParamUtils,,Implementation functions for CbcOsiParam parameters -CbcGenParam.cpp,Generic,Lou,,24,154,219,373,,,x,,CbcGenParam,,Constructors and destructors for CbcGenParam -CbcGenParamUtils.cpp,Generic,Lou,,18,1497,,1497,,,x,,namespace CbcGenParamUtils,"namespace CbcGenSolvers, ",Implementation functions for CbcGenParam parameters -CbcGenSolution.cpp,Generic,Lou,,22,584,,584,,,x,,CbcGenParamUtils,namespace,"Helper routine to generate masks for selecting names to print. Returns true if masks are generated without error, false otherwise." -CbcGenSolvers.cpp,Generic,Lou,,24,261,,261,,,x,,namespace CbcGenSolvers,namespace,This file contains routines related to handling Osi solvers. The technique is to maintain a map of OsiSolverInterface objects as prototypes of the available solvers. -CbcHeuristic.cpp,Heuristic,,,10,2901,650,3551,x,,,,CbcHeuristic,"CbcHeuristicNode, CbcHeuristicNodeList, CbcRounding, CbcHeuristicPartial, CbcSerendipity, CbcHeuristicJustOne", -CbcHeuristicDive.cpp,Heuristic,,,10,1068,160,1228,x,,,,CbcHeuristicDive,, -CbcHeuristicDiveCoefficient.cpp,Heuristic,,,12,128,49,177,x,,,,CbcHeuristicDiveCoefficient,, -CbcHeuristicDiveFractional.cpp,Heuristic,,,18,112,49,161,x,,,,CbcHeuristicDiveFractional,, -CbcHeuristicDiveGuided.cpp,Heuristic,,,18,123,52,175,x,,,,CbcHeuristicDiveGuided, -CbcHeuristicDiveLineSearch.cpp,Heuristic,,,18,120,49,169,x,,,,CbcHeuristicDiveLineSearch, -CbcHeuristicDivePseudoCost.cpp,Heuristic,,,18,227,57,284,x,,,,CbcHeuristicDivePseudoCost, -CbcHeuristicDiveVectorLength.cpp,Heuristic,,,10,123,49,172,x,,,,CbcHeuristicDiveVectorLength, -CbcHeuristicFPump.cpp,Heuristic,,,8,2764,319,3083,x,,,,CbcHeuristicFPump,CbcDisasterHandler -CbcHeuristicGreedy.cpp,Heuristic,,,17,861,189,1050,x,,,,CbcHeuristicGreedyCover,CbcHeuristicGreedyEquality -CbcHeuristicLocal.cpp,Heuristic,,,8,1104,208,1312,x,,,,CbcHeuristicLocal,CbcHeuristicNaive -CbcHeuristicPivotAndFix.cpp,Heuristic,,,14,537,55,592,x,,,,CbcHeuristicPivotAndFix, -CbcHeuristicRandRound.cpp,Heuristic,,,10,514,55,569,x,,,,CbcHeuristicRandRound, -CbcHeuristicRINS.cpp,Heuristic,,,10,1207,296,1503,x,,,,CbcHeuristicRINS,"CbcHeuristicRENS, CbcHeuristicDINS, CbcHeuristicVND" -CbcLinked.cpp,,,,10,8302,1403,9705,x,,,,OsiSolverLink,"OsiLinkedBound, OsiHeuristicDynamic3, OsiOldLink, OsiBiLinear*, OsiSimpleFixedInteger, Multiple" -CbcMain.cpp,,,,14,1651,,1651,,,,x,main,"CbcCompareUser, namespace" -CbcMessage.cpp,,,,13,104,87,191,x,,,,CbcMessage, -CbcModel.cpp,,,,0,16557,2622,19179,x,,,,CbcModel, -CbcNode.cpp,,,,0,5135,806,5941,x,,,,CbcNode,"CbcNodeInfo, CbcFullNodeInfo, CbcPartialNodeInfo, " -CbcParam.cpp,Solver,Bjarni,,24,502,237,739,x,,,,CbcParam, -CbcSolver.cpp,Solver,Bjarni,,0,11365,,11365,,x,,,CbcSolver,CbcMain -CbcStatistics.cpp,,,,21,136,98,234,x,,,,CbcStatistics, -CbcStrategy.cpp,,,,8,940,255,1195,x,,,,CbcStrategy,CbcStrategyDefault* -CbcTree.cpp,,,,8,1178,419,1597,x,,,,CbcTree,CbcTreeArray -CbcTreeLocal.cpp,,,,10,1747,369,2116,x,,,,CbcTreeLocal, -Cbc_ampl.cpp,Ampl,,,4,1504,65,1569,,,,x,global, -Cbc_C_Interface.cpp,Interface,Bjarni,,4,2554,658,3212,,,,x,global, -ClpAmplObjective.cpp,Ampl,,,14,750,110,860,,,,x,ClpAmplObjective, -ClpAmplStuff.cpp,Ampl,,,3,1370,,1370,x,,,,CbcAmpl,"CbcAmpl*, Multiple" -ClpConstraintAmpl.hpp,Ampl,,,24,,105,105,,,,,, -CoinSolve.cpp,Solver,,,8,342,,342,,x,,,MyMessageHandler2,main -unitTest.cpp,Test,,,8,418,,418,,,,x,global, -unitTestClp.cpp,Test,,,5,714,,714,,x,,,global, diff --git a/CbcSourceFilesTable.xls b/CbcSourceFilesTable.xls deleted file mode 100644 index df5873dad..000000000 Binary files a/CbcSourceFilesTable.xls and /dev/null differ diff --git a/CbcSourceFilesTable2.csv b/CbcSourceFilesTable2.csv deleted file mode 100644 index a7e0b9f24..000000000 --- a/CbcSourceFilesTable2.csv +++ /dev/null @@ -1,103 +0,0 @@ -Filename,,Group,Person,Inherits,Status,Age,CPP Lines,HPP Lines,Total Lines,libCbc,cbcSolve,cbcGeneric,Other Projects,First Object,Other Objects,Comment -CbcBranchActual.cpp,,Branch,Edwin,,,8,5340,1823,7163,x,,,,Multiple,"CbcClique, CbcSos, CbcSimpleInteger, CbcIntegerBranchingObject, CbcSimpleIntegerPseudoCost, CbcIntegerPseudoCostBranchingObject, CbcCliqueBranchingObject, CbcLongCliqueBranchingObject, CbcSosBranchingObject, CbcBranchDefaultDecision, CbcFollowOn, CbcFixingBranchingObject, CbcNWay, CbcNWayBranchingObject, CbcFixVariable, CbcDummyBranchingObject, CbcGeneral, CbcGeneralDepth, CbcGeneralBranchingObject, CbcOneGeneralBranchingObject, CbcSubProblem", -,CbcClique.cpp,Branch,Edwin,,,,,,,,,,,,, -,CbcSos.cpp,Branch,Edwin,,,,,,,,,,,,, -,CbcSimpleInteger,Branch,Edwin,,,,,,,,,,,,, -,CbcIntegerBranchingObject,Branch,Edwin,,,,,,,,,,,,, -,CbcSimpleIntegerPseudoCost,Branch,Edwin,,,,,,,,,,,,, -,CbcIntegerPseudoCostBranchingObject,Branch,Edwin,,,,,,,,,,,,, -,CbcCliqueBranchingObject,Branch,Edwin,,,,,,,,,,,,, -,CbcLongCliqueBranchingObject,Branch,Edwin,,,,,,,,,,,,, -,CbcSosBranchingObject,Branch,Edwin,,,,,,,,,,,,, -,CbcBranchDefaultDecision,Branch,Edwin,,,,,,,,,,,,, -,CbcFollowOn,Branch,Edwin,,,,,,,,,,,,, -,CbcFixingBranchingObject,Branch,Edwin,,,,,,,,,,,,, -,CbcNWay,Branch,Edwin,,,,,,,,,,,,, -,CbcNWayBranchingObject,Branch,Edwin,,,,,,,,,,,,, -,CbcFixVariable,Branch,Edwin,,,,,,,,,,,, -,CbcDummyBranchingObject,Branch,Edwin,,,,,,,,,,,, -,CbcGeneral,Branch,Edwin,,,,,,,,,,,, -,CbcGeneralDepth,Branch,Edwin,,,,,,,,,,,, -,CbcGeneralBranchingObject,Branch,Edwin,,,,,,,,,,,, -,CbcOneGeneralBranchingObject,Branch,Edwin,,,,,,,,,,,, -,CbcSubProblem,Branch,Edwin,,,,,,,,,,,, -CbcBranchBase.cpp,,Branch,Edwin,,,10,352,707,1059,x,,,,CbcObject,"CbcBranchingObject, CbcBranchDecision, CbcConsequence, CbcObjectUpdateData" -,CbcBranchDecision,Branch,Edwin,,,,,,,,,,,, -,CbcBranchObject,Branch,Edwin,,,,,,,,,,,, -,CbcConsequence,Branch,Edwin,,,,,,,,,,,, -,CbcObject,Branch,Edwin,,,,,,,,,,,, -,CbcObjectUpdateData,Branch,Edwin,,,,,,,,,,,, -CbcBranchCut.cpp,,Branch,Edwin,,,10,1023,315,1338,x,,,,CbcBranchCut,"CbcCutBranchingObject, CbcBranchToFixLots, CbcBranchAllDifferent" -,CbcBranchAllDifferent,Branch,Edwin,,,,,,,,,,,, -,CbcBranchToFixLots,Branch,Edwin,,,,,,,,,,,, -,CbcCutBranchingObject,Branch,Edwin,,,,,,,,,,,, -CbcBranchDynamic.cpp,,Branch,Edwin,,,8,1911,557,2468,x,,,,CbcSimpleIntegerDynamicPseudoCost,"CbcDynamicPseudoCostBranchingObject, CbcBranchDynamicDecision" -,CbcDynamicPseudoCostBranching,Branch,Edwin,,,,,,,,,,,, -,CbcSimpleIntegerDynamicPseudoCost,Branch,Edwin,,,,,,,,,,,, -CbcBranchLotsize.cpp,,Branch,Edwin,,,15,809,250,1059,x,,,,CbcLotsize,CbcLotsizeBranchingObject -CbcCbcParam.cpp,,API,Bjarni,,,24,1,,1,x,,,,"#include ""CbcOrClpParam.cpp""", -CbcCompareActual.cpp,,NodeStrat,Edwin,,,8,463,165,628,x,,,,CbcCompareDepth,"CbcCompareObjective, CbcCompareDefault, CbcCompareEstimate" -,CbcCompareDefault.cpp,NodeStrat,Edwin,,,,,,,,,,,, -,CbcCompareDepth.cpp,NodeStrat,Edwin,,,,,,,,,,,, -,CbcCompareEstimate.cpp,NodeStrat,Edwin,,,,,,,,,,,, -,CbcCompareObjective.cpp,NodeStrat,Edwin,,,,,,,,,,,, -CbcCompareBase.hpp,,NodeStrat,Edwin,,,24,,170,170,x,,,,CbcCompareBase,"CbcCompare, CbcChooseVariable" -,CbcCompare,NodeStrat,Edwin,,,,,,,,,,,, -,CbcChooseVariable,NodeStrat,Edwin,,,,,,,,,,,, -CbcConfig.h,,,,,,20,,102,102,x,,,,#defines, -CbcCountRowCut.cpp,,Cuts,,,,10,126,115,241,x,,,,CbcCountRowCut, -CbcCutGenerator.cpp,,Cuts,Edwin,,,2,1223,510,1733,x,,,,CbcCutGenerator,"CbcCutModifier, CbcCutSubsetModifier", -,CbcCutModifier.cp,Cuts,Edwin,,,,,,,,,,,,, -,CbcCutSubsetModifier.cpp,Cuts,Edwin,,,,,,,,,,,,, -CbcEventHandler.cpp,,API,,,,36,101,221,322,x,,,,CbcEventHandler,, -CbcFathom.cpp,,NodeStrat,Edwin,,,19,106,126,232,x,,,,CbcFathom,CbcOsiSolver, -CbcFathomDynamicProgramming.cpp,,NodeStrat,Edwin,,,10,1051,166,1217,x,,,,CbcFathomDynamicProgramming,, -CbcFeasibilityBase.hpp,,API?,,,,24,,53,53,x,,,,CbcFeasibilityBase,, -CbcGenBaB.cpp,,Generic,Lou,,,14,886,,886,,,x,,namespace CbcGenParamUtils,namespace,The support functions for the main branch-and-cut action routine. -CbcGenCbcParam.cpp,,Generic,Lou,,,24,155,189,344,,,x,,CbcCbcParam,,Constructors and destructors for CbcCbcParam -CbcGenCbcParamUtils.cpp,,Generic,Lou,,,18,401,,401,,,x,,namespace CbcCbcParamUtils,,Implementation functions for CbcGenParam parameters. -CbcGenCtlBlk.cpp,,Generic,Lou,,,24,681,948,1629,x,,x,,CbcGenCtlBlk,,Constructor for cbc-generic control block. -CbcGeneric.cpp,,Generic,Lou,,,24,415,,415,,,x,,namespace CbcGenSolvers,namespace,Unnamed local namespace for cbc-generic support types and functions. -CbcGenMessages.cpp,,Generic,Lou,,,24,192,,192,x,,,,CbcGenCtlBlk,,Message definitions. -CbcGenOsiParam.cpp,,Generic,Lou,,,24,156,197,353,,,x,,CbcOsiParam,,Constructors and destructors for CbcOsiParam -CbcGenOsiParamUtils.cpp,,Generic,Lou,,,18,528,,528,,,x,,namespace CbcOsiParamUtils,,Implementation functions for CbcOsiParam parameters -CbcGenParam.cpp,,Generic,Lou,,,24,154,219,373,,,x,,CbcGenParam,,Constructors and destructors for CbcGenParam -CbcGenParamUtils.cpp,,Generic,Lou,,,18,1497,,1497,,,x,,namespace CbcGenParamUtils,"namespace CbcGenSolvers, ",Implementation functions for CbcGenParam parameters -CbcGenSolution.cpp,,Generic,Lou,,,22,584,,584,,,x,,CbcGenParamUtils,namespace,"Helper routine to generate masks for selecting names to print. Returns true if masks are generated without error, false otherwise." -CbcGenSolvers.cpp,,Generic,Lou,,,24,261,,261,,,x,,namespace CbcGenSolvers,namespace,This file contains routines related to handling Osi solvers. The technique is to maintain a map of OsiSolverInterface objects as prototypes of the available solvers. -CbcHeuristic.cpp,,Heuristic,,,,10,2901,650,3551,x,,,,CbcHeuristic,"CbcHeuristicNode, CbcHeuristicNodeList, CbcRounding, CbcHeuristicPartial, CbcSerendipity, CbcHeuristicJustOne", -CbcHeuristicDive.cpp,,Heuristic,,,,10,1068,160,1228,x,,,,CbcHeuristicDive,, -CbcHeuristicDiveCoefficient.cpp,,Heuristic,,,,12,128,49,177,x,,,,CbcHeuristicDiveCoefficient,, -CbcHeuristicDiveFractional.cpp,,Heuristic,,,,18,112,49,161,x,,,,CbcHeuristicDiveFractional,, -CbcHeuristicDiveGuided.cpp,,Heuristic,,,,18,123,52,175,x,,,,CbcHeuristicDiveGuided,, -CbcHeuristicDiveLineSearch.cpp,,Heuristic,,,,18,120,49,169,x,,,,CbcHeuristicDiveLineSearch,, -CbcHeuristicDivePseudoCost.cpp,,Heuristic,,,,18,227,57,284,x,,,,CbcHeuristicDivePseudoCost,, -CbcHeuristicDiveVectorLength.cpp,,Heuristic,,,,10,123,49,172,x,,,,CbcHeuristicDiveVectorLength,, -CbcHeuristicFPump.cpp,,Heuristic,,,,8,2764,319,3083,x,,,,CbcHeuristicFPump,CbcDisasterHandler, -CbcHeuristicGreedy.cpp,,Heuristic,,,,17,861,189,1050,x,,,,CbcHeuristicGreedyCover,CbcHeuristicGreedyEquality, -CbcHeuristicLocal.cpp,,Heuristic,,,,8,1104,208,1312,x,,,,CbcHeuristicLocal,CbcHeuristicNaive, -CbcHeuristicPivotAndFix.cpp,,Heuristic,,,,14,537,55,592,x,,,,CbcHeuristicPivotAndFix,, -CbcHeuristicRandRound.cpp,,Heuristic,,,,10,514,55,569,x,,,,CbcHeuristicRandRound,, -CbcHeuristicRINS.cpp,,Heuristic,,,,10,1207,296,1503,x,,,,CbcHeuristicRINS,"CbcHeuristicRENS, CbcHeuristicDINS, CbcHeuristicVND" -CbcLinked.cpp,,Nonlinear/Osi,,,,10,8302,1403,9705,x,,,,OsiSolverLink,"OsiLinkedBound, OsiHeuristicDynamic3, OsiOldLink, OsiBiLinear*, OsiSimpleFixedInteger, Multiple" -CbcMain.cpp,,API,,,,14,1651,,1651,,,,x,main,"CbcCompareUser, namespace" -CbcMessage.cpp,,API,,,,13,104,87,191,x,,,,CbcMessage, -CbcModel.cpp,,Core,Edwin,,,0,16557,2622,19179,x,,,,CbcModel, -CbcNode.cpp,,Core,Dan,,,0,5135,806,5941,x,,,,CbcNode,"CbcNodeInfo, CbcFullNodeInfo, CbcPartialNodeInfo, " -,CbcFullNodeInfo.cpp,Core,Dan,,,,,,,,,,,, -,CbcNodeInfo.cpp,Core,Dan,,,,,,,,,,,, -,CbcPartialNodeInfo.cpp,Core,Dan,,,,,,,,,,,, -CbcParam.cpp,,API,Bjarni,,,24,502,237,739,x,,,,CbcParam, -CbcSolver.cpp,,API,Bjarni,,,0,11365,,11365,,x,,,CbcSolver,CbcMain -CbcStatistics.cpp,,API,,,,21,136,98,234,x,,,,CbcStatistics, -CbcStrategy.cpp,,Core,Dan/Edwin,,,8,940,255,1195,x,,,,CbcStrategy,CbcStrategyDefault* -CbcTree.cpp,,Core,Dan/Edwin,,,8,1178,419,1597,x,,,,CbcTree,CbcTreeArray -CbcTreeLocal.cpp,,Heuristic,,,,10,1747,369,2116,x,,,,CbcTreeLocal, -Cbc_ampl.cpp,,Ampl,,,,4,1504,65,1569,,,,x,global, -Cbc_C_Interface.cpp,,Interface,Bjarni,,,4,2554,658,3212,,,,x,global, -ClpAmplObjective.cpp,,Ampl,,,,14,750,110,860,,,,x,ClpAmplObjective, -ClpAmplStuff.cpp,,Ampl,,,,3,1370,,1370,x,,,,CbcAmpl,"CbcAmpl*, Multiple" -ClpConstraintAmpl.hpp,,Ampl,,,,24,,105,105,,,,,, -CoinSolve.cpp,,API,Bjarni,,,8,342,,342,,x,,,MyMessageHandler2,main -unitTest.cpp,,Test,,,,8,418,,418,,,,x,global, -unitTestClp.cpp,,Test,,,,5,714,,714,,x,,,global, diff --git a/CbcSourceFilesTable2.xls b/CbcSourceFilesTable2.xls deleted file mode 100644 index f2d7eed16..000000000 Binary files a/CbcSourceFilesTable2.xls and /dev/null differ diff --git a/CbcSourceFilesTable3.csv b/CbcSourceFilesTable3.csv deleted file mode 100644 index 218491e20..000000000 --- a/CbcSourceFilesTable3.csv +++ /dev/null @@ -1,92 +0,0 @@ -"Filename",,"Group","Person","Inherits","Status","Age","CPP Lines","HPP Lines","Total Lines","libCbc","cbcSolve","cbcGeneric","Other Projects","First Object","Other Objects","Comment" -"CbcBranchActual.cpp (broken up, no longer used)",,"Branch","Edwin",,,8,5340,1823,7163,"x",,,,"Multiple","CbcClique, CbcSos, CbcSimpleInteger, CbcIntegerBranchingObject, CbcSimpleIntegerPseudoCost, CbcIntegerPseudoCostBranchingObject, CbcCliqueBranchingObject, CbcLongCliqueBranchingObject, CbcSosBranchingObject, CbcBranchDefaultDecision, CbcFollowOn, CbcFixingBranchingObject, CbcNWay, CbcNWayBranchingObject, CbcFixVariable, CbcDummyBranchingObject, CbcGeneral, CbcGeneralDepth, CbcGeneralBranchingObject, CbcOneGeneralBranchingObject, CbcSubProblem", -,"CbcClique.cpp (CbcClique, CbcCliqueBranchingObject, CbcLongCliqueBranchingObject)","Branch","Edwin",,,,,,,,,,,,, -,"CbcSos.cpp (CbcSos, CbcSosBranchingObject)","Branch","Edwin",,,,,,,,,,,,, -,"CbcSimpleInteger.cpp (CbcSimpleInteger, CbcIntegerBranchingObject)","Branch","Edwin",,,,,,,,,,,,, -,"CbcSimpleIntegerPseudoCost.cpp (CbcSimpleIntegerPseudoCost, CbcIntegerPseudoCostBranchingObject)","Branch","Edwin",,,,,,,,,,,,, -,"CbcBranchDefaultDecision","Branch","Edwin",,,,,,,,,,,,, -,"CbcFollowOn.cpp (CbcFollowOn, CbcFixingBranchingObject)","Branch","Edwin",,,,,,,,,,,,, -,"CbcNWay.cpp (CbcNWay, CbcNWayBranchingObject)","Branch","Edwin",,,,,,,,,,,,, -,"CbcFixVariable","Branch","Edwin",,,,,,,,,,,,, -,"CbcDummyBranchingObject","Branch","Edwin",,,,,,,,,,,,, -,"CbcGeneral","Branch","Edwin",,,,,,,,,,,,, -,"CbcGeneralDepth.cpp (CbcGeneralDepth, CbcGeneralBranchingObject, CbcOneGeneralBranchingObject)","Branch","Edwin",,,,,,,,,,,,, -,"CbcSubProblem","Branch","Edwin",,,,,,,,,,,,, -"CbcBranchBase.cpp (broken up, no longer used)",,"Branch","Edwin",,,10,352,707,1059,"x",,,,"CbcObject","CbcBranchingObject, CbcBranchDecision, CbcConsequence, CbcObjectUpdateData", -,"CbcBranchDecision","Branch","Edwin",,,,,,,,,,,,, -,"CbcBranchObject","Branch","Edwin",,,,,,,,,,,,, -,"CbcConsequence","Branch","Edwin",,,,,,,,,,,,, -,"CbcObject","Branch","Edwin",,,,,,,,,,,,, -,"CbcObjectUpdateData","Branch","Edwin",,,,,,,,,,,,, -"CbcBranchCut.cpp (CbcBranchCut, CbcCutBranchingObject)",,"Branch","Edwin",,,10,1023,315,1338,"x",,,,"CbcBranchCut","CbcCutBranchingObject, CbcBranchToFixLots, CbcBranchAllDifferent", -,"CbcBranchAllDifferent","Branch","Edwin",,,,,,,,,,,,, -,"CbcBranchToFixLots","Branch","Edwin",,,,,,,,,,,,, -"CbcBranchDynamic.cpp (CbcBranchDynamic, CbcDynamicPseudoCostBranchingObject)",,"Branch","Edwin",,,8,1911,557,2468,"x",,,,"CbcSimpleIntegerDynamicPseudoCost","CbcDynamicPseudoCostBranchingObject, CbcBranchDynamicDecision", -,"CbcSimpleIntegerDynamicPseudoCost","Branch","Edwin",,,,,,,,,,,,, -"CbcLotsize.cpp (CbcLotsize, CbcLotsizeBranchingObject)",,"Branch","Edwin",,,,,,,,,,,,, -"CbcCbcParam.cpp",,"API","Bjarni",,,24,1,,1,"x",,,,"#include ""CbcOrClpParam.cpp""",, -"CbcCompareActual.cpp",,"NodeStrat","Dan",,"Reviewed",8,463,165,628,"x",,,,"CbcCompareDepth","CbcCompareObjective, CbcCompareDefault, CbcCompareEstimate", -,"CbcCompareDefault.cpp","NodeStrat","Dan",,"Reviewed",,,,,,,,,,, -,"CbcCompareDepth.cpp","NodeStrat","Dan",,"Reviewed",,,,,,,,,,, -,"CbcCompareEstimate.cpp","NodeStrat","Dan",,"Reviewed",,,,,,,,,,, -,"CbcCompareObjective.cpp","NodeStrat","Dan",,"Reviewed",,,,,,,,,,, -"CbcCompareBase.hpp",,"NodeStrat","Dan",,"Reviewed",24,,170,170,"x",,,,"CbcCompareBase","CbcCompare, CbcChooseVariable", -,"CbcCompare","NodeStrat","Dan",,"Reviewed",,,,,,,,,,, -,"CbcChooseVariable - class not used","NodeStrat","[Dan]",,"Reviewed",,,,,,,,,,, -"CbcConfig.h",,,,,,20,,102,102,"x",,,,"#defines",, -"CbcCountRowCut.cpp",,"Cuts",,,,10,126,115,241,"x",,,,"CbcCountRowCut",, -"CbcCutGenerator.cpp",,"Cuts","Dan",,"Reviewed",2,1223,510,1733,"x",,,,"CbcCutGenerator","CbcCutModifier, CbcCutSubsetModifier", -,"CbcCutModifier.cpp","Cuts","Dan",,"Reviewed",,,,,,,,,,, -,"CbcCutSubsetModifier.cpp","Cuts","Dan",,"Reviewed",,,,,,,,,,, -"CbcEventHandler.cpp",,"API",,,,36,101,221,322,"x",,,,"CbcEventHandler",, -"CbcFathom.cpp - not used currently",,"NodeStrat","[Dan]",,"Reviewed",19,106,126,232,"x",,,,"CbcFathom","CbcOsiSolver", -"CbcFathomDynamicProgramming.cpp - not used currently",,"NodeStrat","[Dan]",,"Reviewed",10,1051,166,1217,"x",,,,"CbcFathomDynamicProgramming",, -"CbcFeasibilityBase.hpp",,"API?",,,,24,,53,53,"x",,,,"CbcFeasibilityBase",, -"CbcGenBaB.cpp",,"Generic","Lou",,,14,886,,886,,,"x",,"namespace CbcGenParamUtils","namespace","The support functions for the main branch-and-cut action routine." -"CbcGenCbcParam.cpp",,"Generic","Lou",,,24,155,189,344,,,"x",,"CbcCbcParam",,"Constructors and destructors for CbcCbcParam" -"CbcGenCbcParamUtils.cpp",,"Generic","Lou",,,18,401,,401,,,"x",,"namespace CbcCbcParamUtils",,"Implementation functions for CbcGenParam parameters." -"CbcGenCtlBlk.cpp",,"Generic","Lou",,,24,681,948,1629,"x-not used",,"x",,"CbcGenCtlBlk",,"Constructor for cbc-generic control block." -"CbcGeneric.cpp",,"Generic","Lou",,,24,415,,415,,,"x",,"namespace CbcGenSolvers","namespace","Unnamed local namespace for cbc-generic support types and functions." -"CbcGenMessages.cpp",,"Generic","Lou",,,24,192,,192,"x-not used",,,,"CbcGenCtlBlk",,"Message definitions." -"CbcGenOsiParam.cpp",,"Generic","Lou",,,24,156,197,353,,,"x",,"CbcOsiParam",,"Constructors and destructors for CbcOsiParam" -"CbcGenOsiParamUtils.cpp",,"Generic","Lou",,,18,528,,528,,,"x",,"namespace CbcOsiParamUtils",,"Implementation functions for CbcOsiParam parameters" -"CbcGenParam.cpp",,"Generic","Lou",,,24,154,219,373,,,"x",,"CbcGenParam",,"Constructors and destructors for CbcGenParam" -"CbcGenParamUtils.cpp",,"Generic","Lou",,,18,1497,,1497,,,"x",,"namespace CbcGenParamUtils","namespace CbcGenSolvers, ","Implementation functions for CbcGenParam parameters" -"CbcGenSolution.cpp",,"Generic","Lou",,,22,584,,584,,,"x",,"CbcGenParamUtils","namespace","Helper routine to generate masks for selecting names to print. Returns true if masks are generated without error, false otherwise." -"CbcGenSolvers.cpp",,"Generic","Lou",,,24,261,,261,,,"x",,"namespace CbcGenSolvers","namespace","This file contains routines related to handling Osi solvers. The technique is to maintain a map of OsiSolverInterface objects as prototypes of the available solvers." -"CbcHeuristic.cpp",,"Heuristic",,,"Reviewed",10,2901,650,3551,"x",,,,"CbcHeuristic","CbcHeuristicNode, CbcHeuristicNodeList, CbcRounding, CbcHeuristicPartial, CbcSerendipity, CbcHeuristicJustOne", -"CbcHeuristicDive.cpp",,"Heuristic",,,"Reviewed",10,1068,160,1228,"x",,,,"CbcHeuristicDive",, -"CbcHeuristicDiveCoefficient.cpp",,"Heuristic",,,"Reviewed",12,128,49,177,"x",,,,"CbcHeuristicDiveCoefficient",, -"CbcHeuristicDiveFractional.cpp",,"Heuristic",,,"Reviewed",18,112,49,161,"x",,,,"CbcHeuristicDiveFractional",, -"CbcHeuristicDiveGuided.cpp",,"Heuristic",,,"Reviewed",18,123,52,175,"x",,,,"CbcHeuristicDiveGuided",, -"CbcHeuristicDiveLineSearch.cpp",,"Heuristic",,,"Reviewed",18,120,49,169,"x",,,,"CbcHeuristicDiveLineSearch",, -"CbcHeuristicDivePseudoCost.cpp",,"Heuristic",,,"Reviewed",18,227,57,284,"x",,,,"CbcHeuristicDivePseudoCost",, -"CbcHeuristicDiveVectorLength.cpp",,"Heuristic",,,"Reviewed",10,123,49,172,"x",,,,"CbcHeuristicDiveVectorLength",, -"CbcHeuristicFPump.cpp",,"Heuristic",,,"Reviewed",8,2764,319,3083,"x",,,,"CbcHeuristicFPump","CbcDisasterHandler", -"CbcHeuristicGreedy.cpp",,"Heuristic",,,"Reviewed",17,861,189,1050,"x",,,,"CbcHeuristicGreedyCover","CbcHeuristicGreedyEquality", -"CbcHeuristicLocal.cpp",,"Heuristic",,,"Reviewed",8,1104,208,1312,"x",,,,"CbcHeuristicLocal","CbcHeuristicNaive", -"CbcHeuristicPivotAndFix.cpp",,"Heuristic",,,"Reviewed",14,537,55,592,"x",,,,"CbcHeuristicPivotAndFix",, -"CbcHeuristicRandRound.cpp",,"Heuristic",,,"Reviewed",10,514,55,569,"x",,,,"CbcHeuristicRandRound",, -"CbcHeuristicRINS.cpp",,"Heuristic",,,"Reviewed",10,1207,296,1503,"x",,,,"CbcHeuristicRINS","CbcHeuristicRENS, CbcHeuristicDINS, CbcHeuristicVND", -"CbcLinked.cpp",,"Nonlinear/Osi",,,,10,8302,1403,9705,"x",,,,"OsiSolverLink","OsiLinkedBound, OsiHeuristicDynamic3, OsiOldLink, OsiBiLinear*, OsiSimpleFixedInteger, Multiple", -"CbcMain.cpp",,"API",,,"Deleted",14,1651,,1651,,,,"x","main","CbcCompareUser, namespace", -"CbcMessage.cpp",,"API",,,,13,104,87,191,"x",,,,"CbcMessage",, -"CbcModel.cpp",,"Core","Edwin",,"Updated",0,16557,2622,19179,"x",,,,"CbcModel",, -"CbcNode.cpp",,"Core","Dan",,"Reviewed",0,5135,806,5941,"x",,,,"CbcNode","CbcNodeInfo, CbcFullNodeInfo, CbcPartialNodeInfo, ", -,"CbcFullNodeInfo.cpp","Core","Dan",,"Reviewed",,,,,,,,,,, -,"CbcNodeInfo.cpp","Core","Dan",,"Reviewed",,,,,,,,,,, -,"CbcPartialNodeInfo.cpp","Core","Dan",,"Reviewed",,,,,,,,,,, -"CbcParam.cpp",,"API","Bjarni",,,24,502,237,739,"x",,,,"CbcParam",, -"CbcSolver.cpp",,"API","Bjarni",,,0,11365,,11365,,"x",,,"CbcSolver","CbcMain", -"CbcStatistics.cpp",,"API",,,,21,136,98,234,"x",,,,"CbcStatistics",, -"CbcStrategy.cpp",,"Core","Dan",,"Updated",8,940,255,1195,"x",,,,"CbcStrategy","CbcStrategyDefault*", -"CbcTree.cpp",,"Core","Dan",,"Reviewed",8,1178,419,1597,"x",,,,"CbcTree","CbcTreeArray", -"CbcTreeLocal.cpp",,"Heuristic",,,,10,1747,369,2116,"x",,,,"CbcTreeLocal",, -"Cbc_ampl.cpp",,"Ampl",,,,4,1504,65,1569,,,,"x","global",, -"Cbc_C_Interface.cpp",,"Interface","Bjarni",,,4,2554,658,3212,,,,"x","global",, -"ClpAmplObjective.cpp",,"Ampl",,,,14,750,110,860,,,,"x","ClpAmplObjective",, -"ClpAmplStuff.cpp",,"Ampl",,,,3,1370,,1370,"x",,,,"CbcAmpl","CbcAmpl*, Multiple", -"ClpConstraintAmpl.hpp",,"Ampl",,,,24,,105,105,,,,,,, -"CoinSolve.cpp",,"API",,,,8,342,,342,,"x",,,"MyMessageHandler2","main", -"unitTest.cpp",,"Test",,,,8,418,,418,,,,"x","global",, -"unitTestClp.cpp",,"Test",,,,5,714,,714,,"x",,,"global",, diff --git a/CbcSourceFilesTable3.xls b/CbcSourceFilesTable3.xls deleted file mode 100644 index d10f3f4a1..000000000 Binary files a/CbcSourceFilesTable3.xls and /dev/null differ diff --git a/Makefile.in b/Makefile.in index 7a11ef8f6..900a45f8e 100644 --- a/Makefile.in +++ b/Makefile.in @@ -104,7 +104,6 @@ am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \ mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/src/config.h \ $(top_builddir)/src/config_cbc.h \ - $(top_builddir)/src/config_cbcsolver.h \ $(top_builddir)/src/OsiCbc/config_osicbc.h CONFIG_CLEAN_FILES = examples/Makefile cbc.pc osi-cbc.pc \ doxydoc/doxygen.conf @@ -216,11 +215,8 @@ CBCLIB_CFLAGS_NOPC = @CBCLIB_CFLAGS_NOPC@ CBCLIB_LFLAGS = @CBCLIB_LFLAGS@ CBCLIB_LFLAGS_NOPC = @CBCLIB_LFLAGS_NOPC@ CBCLIB_PCFILES = @CBCLIB_PCFILES@ -CBCSOLVERLIB_CFLAGS = @CBCSOLVERLIB_CFLAGS@ CBCSOLVERLIB_CFLAGS_NOPC = @CBCSOLVERLIB_CFLAGS_NOPC@ -CBCSOLVERLIB_LFLAGS = @CBCSOLVERLIB_LFLAGS@ CBCSOLVERLIB_LFLAGS_NOPC = @CBCSOLVERLIB_LFLAGS_NOPC@ -CBCSOLVERLIB_PCFILES = @CBCSOLVERLIB_PCFILES@ CBCUNITTEST_CFLAGS = @CBCUNITTEST_CFLAGS@ CBCUNITTEST_CFLAGS_NOPC = @CBCUNITTEST_CFLAGS_NOPC@ CBCUNITTEST_LFLAGS = @CBCUNITTEST_LFLAGS@ diff --git a/cbc.pc.in b/cbc.pc.in index 6e42e02a7..dad01765b 100644 --- a/cbc.pc.in +++ b/cbc.pc.in @@ -9,7 +9,7 @@ Description: COIN-OR Branch and Cut URL: @PACKAGE_URL@ Version: @PACKAGE_VERSION@ Cflags: -I${includedir} -@COIN_STATIC_BUILD_FALSE@Libs: -L${libdir} -lCbcSolver -lCbc +@COIN_STATIC_BUILD_FALSE@Libs: -L${libdir} -lCbc @COIN_STATIC_BUILD_FALSE@Requires.private: @CBCLIB_PCFILES@ -@COIN_STATIC_BUILD_TRUE@Libs: -L${libdir} -lCbcSolver -lCbc @CBCLIB_LFLAGS_NOPC@ +@COIN_STATIC_BUILD_TRUE@Libs: -L${libdir} -lCbc @CBCLIB_LFLAGS_NOPC@ @COIN_STATIC_BUILD_TRUE@Requires: @CBCLIB_PCFILES@ diff --git a/configure b/configure index cac8f3b2f..529a902ca 100755 --- a/configure +++ b/configure @@ -669,16 +669,8 @@ ac_subst_vars='am__EXEEXT_FALSE am__EXEEXT_TRUE LTLIBOBJS LIBOBJS -CBCUNITTEST_CFLAGS_NOPC -CBCUNITTEST_LFLAGS_NOPC -OSICBCLIB_CFLAGS_NOPC -OSICBCLIB_LFLAGS_NOPC -CBCGENERIC_CFLAGS_NOPC -CBCGENERIC_LFLAGS_NOPC CBCSOLVERLIB_CFLAGS_NOPC CBCSOLVERLIB_LFLAGS_NOPC -CBCLIB_CFLAGS_NOPC -CBCLIB_LFLAGS_NOPC coin_doxy_tagfiles COIN_HAS_LATEX_FALSE COIN_HAS_LATEX_TRUE @@ -709,8 +701,14 @@ COIN_HAS_PTHREADSW32_FALSE COIN_HAS_PTHREADSW32_TRUE CBC_BUILD_CBC_GENERIC_FALSE CBC_BUILD_CBC_GENERIC_TRUE -COIN_HAS_GLPK_FALSE -COIN_HAS_GLPK_TRUE +CBCUNITTEST_CFLAGS_NOPC +CBCUNITTEST_LFLAGS_NOPC +OSICBCLIB_CFLAGS_NOPC +OSICBCLIB_LFLAGS_NOPC +CBCGENERIC_CFLAGS_NOPC +CBCGENERIC_LFLAGS_NOPC +CBCLIB_CFLAGS_NOPC +CBCLIB_LFLAGS_NOPC COIN_HAS_CPLEX_FALSE COIN_HAS_CPLEX_TRUE COIN_HAS_OSISPX_FALSE @@ -759,9 +757,6 @@ OSICBCLIB_LFLAGS CBCGENERIC_PCFILES CBCGENERIC_CFLAGS CBCGENERIC_LFLAGS -CBCSOLVERLIB_PCFILES -CBCSOLVERLIB_CFLAGS -CBCSOLVERLIB_LFLAGS CBCLIB_PCFILES CBCLIB_CFLAGS CBCLIB_LFLAGS @@ -968,9 +963,6 @@ with_osispx_cflags with_cplex with_cplex_lflags with_cplex_cflags -with_glpk -with_glpk_lflags -with_glpk_cflags enable_cbc_generic with_cbc_generic_solver enable_cbc_parallel @@ -1803,15 +1795,6 @@ Optional Packages: --with-cplex-cflags Compiler flags for Cplex appropriate for your environment. (Most often, -I specs for header file directories.) - --with-glpk Use Glpk. If an argument is given, 'yes' is - equivalent to --with-glpk, 'no' is - equivalent to --without-glpk. Any other argument is - applied as for --with-glpk-lflags - --with-glpk-lflags Linker flags for Glpk appropriate for your - environment. (Most often, -l specs for libraries.) - --with-glpk-cflags Compiler flags for Glpk appropriate for your - environment. (Most often, -I specs for header file - directories.) --with-cbc-generic-solver specify default solver for cbc-generic in lower case letters (if not given, clp is assumed) @@ -17893,9 +17876,6 @@ printf %s "checking for package CoinUtils... " >&6; } - - - coin_has_coinutils=noInfo if test x"$COIN_SKIP_PROJECTS" != x ; then for pkg in `echo $COIN_SKIP_PROJECTS | tr '[:upper:]' '[:lower:]'` ; do @@ -18116,9 +18096,6 @@ printf "%s\n" "#define CBC_HAS_COINUTILS 1" >>confdefs.h CBCLIB_PCFILES="$coinutils_pcfiles $CBCLIB_PCFILES" CBCLIB_LFLAGS="$coinutils_lflags $CBCLIB_LFLAGS" CBCLIB_CFLAGS="$coinutils_cflags $CBCLIB_CFLAGS" - CBCSOLVERLIB_PCFILES="$coinutils_pcfiles $CBCSOLVERLIB_PCFILES" - CBCSOLVERLIB_LFLAGS="$coinutils_lflags $CBCSOLVERLIB_LFLAGS" - CBCSOLVERLIB_CFLAGS="$coinutils_cflags $CBCSOLVERLIB_CFLAGS" CBCGENERIC_PCFILES="$coinutils_pcfiles $CBCGENERIC_PCFILES" CBCGENERIC_LFLAGS="$coinutils_lflags $CBCGENERIC_LFLAGS" CBCGENERIC_CFLAGS="$coinutils_cflags $CBCGENERIC_CFLAGS" @@ -18156,9 +18133,6 @@ printf %s "checking for package Osi... " >&6; } - - - coin_has_osi=noInfo if test x"$COIN_SKIP_PROJECTS" != x ; then for pkg in `echo $COIN_SKIP_PROJECTS | tr '[:upper:]' '[:lower:]'` ; do @@ -18379,9 +18353,6 @@ printf "%s\n" "#define CBC_HAS_OSI 1" >>confdefs.h CBCLIB_PCFILES="$osi_pcfiles $CBCLIB_PCFILES" CBCLIB_LFLAGS="$osi_lflags $CBCLIB_LFLAGS" CBCLIB_CFLAGS="$osi_cflags $CBCLIB_CFLAGS" - CBCSOLVERLIB_PCFILES="$osi_pcfiles $CBCSOLVERLIB_PCFILES" - CBCSOLVERLIB_LFLAGS="$osi_lflags $CBCSOLVERLIB_LFLAGS" - CBCSOLVERLIB_CFLAGS="$osi_cflags $CBCSOLVERLIB_CFLAGS" CBCGENERIC_PCFILES="$osi_pcfiles $CBCGENERIC_PCFILES" CBCGENERIC_LFLAGS="$osi_lflags $CBCGENERIC_LFLAGS" CBCGENERIC_CFLAGS="$osi_cflags $CBCGENERIC_CFLAGS" @@ -18419,9 +18390,6 @@ printf %s "checking for package Cgl... " >&6; } - - - coin_has_cgl=noInfo if test x"$COIN_SKIP_PROJECTS" != x ; then for pkg in `echo $COIN_SKIP_PROJECTS | tr '[:upper:]' '[:lower:]'` ; do @@ -18642,9 +18610,6 @@ printf "%s\n" "#define CBC_HAS_CGL 1" >>confdefs.h CBCLIB_PCFILES="$cgl_pcfiles $CBCLIB_PCFILES" CBCLIB_LFLAGS="$cgl_lflags $CBCLIB_LFLAGS" CBCLIB_CFLAGS="$cgl_cflags $CBCLIB_CFLAGS" - CBCSOLVERLIB_PCFILES="$cgl_pcfiles $CBCSOLVERLIB_PCFILES" - CBCSOLVERLIB_LFLAGS="$cgl_lflags $CBCSOLVERLIB_LFLAGS" - CBCSOLVERLIB_CFLAGS="$cgl_cflags $CBCSOLVERLIB_CFLAGS" CBCGENERIC_PCFILES="$cgl_pcfiles $CBCGENERIC_PCFILES" CBCGENERIC_LFLAGS="$cgl_lflags $CBCGENERIC_LFLAGS" CBCGENERIC_CFLAGS="$cgl_cflags $CBCGENERIC_CFLAGS" @@ -18682,9 +18647,6 @@ printf %s "checking for package Clp... " >&6; } - - - coin_has_clp=noInfo if test x"$COIN_SKIP_PROJECTS" != x ; then for pkg in `echo $COIN_SKIP_PROJECTS | tr '[:upper:]' '[:lower:]'` ; do @@ -18905,9 +18867,6 @@ printf "%s\n" "#define CBC_HAS_CLP 1" >>confdefs.h CBCLIB_PCFILES="$clp_pcfiles $CBCLIB_PCFILES" CBCLIB_LFLAGS="$clp_lflags $CBCLIB_LFLAGS" CBCLIB_CFLAGS="$clp_cflags $CBCLIB_CFLAGS" - CBCSOLVERLIB_PCFILES="$clp_pcfiles $CBCSOLVERLIB_PCFILES" - CBCSOLVERLIB_LFLAGS="$clp_lflags $CBCSOLVERLIB_LFLAGS" - CBCSOLVERLIB_CFLAGS="$clp_cflags $CBCSOLVERLIB_CFLAGS" CBCGENERIC_PCFILES="$clp_pcfiles $CBCGENERIC_PCFILES" CBCGENERIC_LFLAGS="$clp_lflags $CBCGENERIC_LFLAGS" CBCGENERIC_CFLAGS="$clp_cflags $CBCGENERIC_CFLAGS" @@ -18947,9 +18906,6 @@ printf %s "checking for package OsiClp... " >&6; } - - - coin_has_osiclp=noInfo if test x"$COIN_SKIP_PROJECTS" != x ; then for pkg in `echo $COIN_SKIP_PROJECTS | tr '[:upper:]' '[:lower:]'` ; do @@ -19170,9 +19126,6 @@ printf "%s\n" "#define CBC_HAS_OSICLP 1" >>confdefs.h CBCLIB_PCFILES="$osiclp_pcfiles $CBCLIB_PCFILES" CBCLIB_LFLAGS="$osiclp_lflags $CBCLIB_LFLAGS" CBCLIB_CFLAGS="$osiclp_cflags $CBCLIB_CFLAGS" - CBCSOLVERLIB_PCFILES="$osiclp_pcfiles $CBCSOLVERLIB_PCFILES" - CBCSOLVERLIB_LFLAGS="$osiclp_lflags $CBCSOLVERLIB_LFLAGS" - CBCSOLVERLIB_CFLAGS="$osiclp_cflags $CBCSOLVERLIB_CFLAGS" CBCGENERIC_PCFILES="$osiclp_pcfiles $CBCGENERIC_PCFILES" CBCGENERIC_LFLAGS="$osiclp_lflags $CBCGENERIC_LFLAGS" CBCGENERIC_CFLAGS="$osiclp_cflags $CBCGENERIC_CFLAGS" @@ -19585,9 +19538,9 @@ fi printf "%s\n" "#define CBC_HAS_ASL 1" >>confdefs.h - CBCSOLVERLIB_PCFILES="$asl_pcfiles $CBCSOLVERLIB_PCFILES" - CBCSOLVERLIB_LFLAGS="$asl_lflags $CBCSOLVERLIB_LFLAGS" - CBCSOLVERLIB_CFLAGS="$asl_cflags $CBCSOLVERLIB_CFLAGS" + CBCLIB_PCFILES="$asl_pcfiles $CBCLIB_PCFILES" + CBCLIB_LFLAGS="$asl_lflags $CBCLIB_LFLAGS" + CBCLIB_CFLAGS="$asl_cflags $CBCLIB_CFLAGS" @@ -19612,9 +19565,6 @@ printf %s "checking for package Nauty... " >&6; } - - - coin_has_nauty=noInfo if test x"$COIN_SKIP_PROJECTS" != x ; then for pkg in `echo $COIN_SKIP_PROJECTS | tr '[:upper:]' '[:lower:]'` ; do @@ -19835,9 +19785,6 @@ printf "%s\n" "#define CBC_HAS_NAUTY 1" >>confdefs.h CBCLIB_PCFILES="$nauty_pcfiles $CBCLIB_PCFILES" CBCLIB_LFLAGS="$nauty_lflags $CBCLIB_LFLAGS" CBCLIB_CFLAGS="$nauty_cflags $CBCLIB_CFLAGS" - CBCSOLVERLIB_PCFILES="$nauty_pcfiles $CBCSOLVERLIB_PCFILES" - CBCSOLVERLIB_LFLAGS="$nauty_lflags $CBCSOLVERLIB_LFLAGS" - CBCSOLVERLIB_CFLAGS="$nauty_cflags $CBCSOLVERLIB_CFLAGS" @@ -20998,9 +20945,6 @@ printf %s "checking for package OsiCpx... " >&6; } - - - coin_has_osicpx=noInfo if test x"$COIN_SKIP_PROJECTS" != x ; then for pkg in `echo $COIN_SKIP_PROJECTS | tr '[:upper:]' '[:lower:]'` ; do @@ -21224,9 +21168,6 @@ printf "%s\n" "#define CBC_HAS_OSICPX 1" >>confdefs.h CBCGENERIC_PCFILES="$osicpx_pcfiles $CBCGENERIC_PCFILES" CBCGENERIC_LFLAGS="$osicpx_lflags $CBCGENERIC_LFLAGS" CBCGENERIC_CFLAGS="$osicpx_cflags $CBCGENERIC_CFLAGS" - CBCSOLVERLIB_PCFILES="$osicpx_pcfiles $CBCSOLVERLIB_PCFILES" - CBCSOLVERLIB_LFLAGS="$osicpx_lflags $CBCSOLVERLIB_LFLAGS" - CBCSOLVERLIB_CFLAGS="$osicpx_cflags $CBCSOLVERLIB_CFLAGS" OSICBCLIB_PCFILES="$osicpx_pcfiles $OSICBCLIB_PCFILES" OSICBCLIB_LFLAGS="$osicpx_lflags $OSICBCLIB_LFLAGS" OSICBCLIB_CFLAGS="$osicpx_cflags $OSICBCLIB_CFLAGS" @@ -22219,245 +22160,195 @@ printf "%s\n" "#define CBC_HAS_CPLEX 1" >>confdefs.h - - - - - - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for package Glpk" >&5 -printf %s "checking for package Glpk... " >&6; } - - - - - - - - - coin_has_glpk=noInfo - if test x"$COIN_SKIP_PROJECTS" != x ; then - for pkg in `echo $COIN_SKIP_PROJECTS | tr '[:upper:]' '[:lower:]'` ; do - if test "$pkg" = "glpk" ; then - coin_has_glpk=skipping + if test "$BUILDTOOLS_DEBUG" = 1 ; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: FINALIZE_FLAGS for CbcLib:" >&5 +printf "%s\n" "$as_me: FINALIZE_FLAGS for CbcLib:" >&6;} fi - done - fi - - - if test "$coin_has_glpk" != skipping ; then - - - - -# Check whether --with-glpk was given. -if test ${with_glpk+y} -then : - withval=$with_glpk; -fi - - - -# Check whether --with-glpk-lflags was given. -if test ${with_glpk_lflags+y} -then : - withval=$with_glpk_lflags; -fi - - - -# Check whether --with-glpk-cflags was given. -if test ${with_glpk_cflags+y} -then : - withval=$with_glpk_cflags; -fi - - - - - - - - - - + CBCLIB_LFLAGS_NOPC=$CBCLIB_LFLAGS + CBCLIB_CFLAGS_NOPC=$CBCLIB_CFLAGS - coin_has_glpk=requested + if test -n "${CBCLIB_PCFILES}" ; then + temp_CFLAGS=`PKG_CONFIG_PATH="$COIN_PKG_CONFIG_PATH" $PKG_CONFIG --cflags ${CBCLIB_PCFILES}` + temp_LFLAGS=`PKG_CONFIG_PATH="$COIN_PKG_CONFIG_PATH" $PKG_CONFIG --libs $pkg_static ${CBCLIB_PCFILES}` + CBCLIB_CFLAGS="$temp_CFLAGS ${CBCLIB_CFLAGS}" + CBCLIB_LFLAGS="$temp_LFLAGS ${CBCLIB_LFLAGS}" + fi - glpk_lflags= - glpk_cflags= - glpk_data= - glpk_pcfiles="coinglpk" + # setup XYZ_EXPORT symbol for library users + libexport_attribute= + if test "$enable_shared" = yes ; then + case $build_os in + cygwin* | mingw* | msys* | cegcc* ) + libexport_attribute="__declspec(dllimport)" + if test "$enable_static" = yes ; then + as_fn_error $? "Cannot do DLL and static LIB builds simultaneously. Do not add --enable-static without --disable-shared." "$LINENO" 5 + fi + ;; + esac + fi +printf "%s\n" "#define CBCLIB_EXPORT $libexport_attribute" >>confdefs.h - withval="$with_glpk" - if test -n "$withval" ; then - case "$withval" in - no ) - coin_has_glpk=skipping - glpk_failmode='command line' - ;; - yes ) - coin_has_glpk=requested - glpk_failmode='' - ;; - build ) - coin_has_glpk=requested - glpk_build=yes - glpk_failmode='' - ;; - * ) - coin_has_glpk=requested - glpk_failmode='' - glpk_lflags="$withval" - glpk_pcfiles='' - ;; - esac - else - if test -n "$with_glpk_lflags" || - test -n "$with_glpk_cflags" || - test -n "$with_glpk_data" ; then - coin_has_glpk=requested - glpk_failmode='' - glpk_pcfiles='' - fi - fi + # add -DXYZ_BUILD to XYZ_CFLAGS + CBCLIB_CFLAGS="${CBCLIB_CFLAGS} -DCBCLIB_BUILD" - if test "$coin_has_glpk" != skipping ; then - withval="$with_glpk_lflags" - if test -n "$withval" ; then - case "$withval" in - build | no | yes ) - as_fn_error $? "\"$withval\" is not useful here; please specify link flags appropriate for your environment." "$LINENO" 5 - ;; - * ) - coin_has_glpk=yes - glpk_lflags="$withval" - glpk_pcfiles='' - ;; - esac - fi + # Define BUILDTOOLS_DEBUG to enable debugging output + if test "$BUILDTOOLS_DEBUG" = 1 ; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: CBCLIB_LFLAGS_NOPC: \"${CBCLIB_LFLAGS_NOPC}\"" >&5 +printf "%s\n" "$as_me: CBCLIB_LFLAGS_NOPC: \"${CBCLIB_LFLAGS_NOPC}\"" >&6;} + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: CBCLIB_CFLAGS_NOPC: \"${CBCLIB_CFLAGS_NOPC}\"" >&5 +printf "%s\n" "$as_me: CBCLIB_CFLAGS_NOPC: \"${CBCLIB_CFLAGS_NOPC}\"" >&6;} + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: adding \"${CBCLIB_PCFILES}\"" >&5 +printf "%s\n" "$as_me: adding \"${CBCLIB_PCFILES}\"" >&6;} + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: CBCLIB_LFLAGS: \"${CBCLIB_LFLAGS}\"" >&5 +printf "%s\n" "$as_me: CBCLIB_LFLAGS: \"${CBCLIB_LFLAGS}\"" >&6;} + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: CBCLIB_CFLAGS: \"${CBCLIB_CFLAGS}\"" >&5 +printf "%s\n" "$as_me: CBCLIB_CFLAGS: \"${CBCLIB_CFLAGS}\"" >&6;} + fi + if test "$BUILDTOOLS_DEBUG" = 1 ; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: FINALIZE_FLAGS for CbcGeneric:" >&5 +printf "%s\n" "$as_me: FINALIZE_FLAGS for CbcGeneric:" >&6;} + fi + CBCGENERIC_LFLAGS_NOPC=$CBCGENERIC_LFLAGS - withval="$with_glpk_cflags" - if test -n "$withval" ; then - case "$withval" in - build | no | yes ) - as_fn_error $? "\"$withval\" is not useful here; please specify compile flags appropriate for your environment." "$LINENO" 5 - ;; - * ) - coin_has_glpk=yes - glpk_cflags="$withval" - glpk_pcfiles='' - ;; - esac - fi - fi + CBCGENERIC_CFLAGS_NOPC=$CBCGENERIC_CFLAGS + if test -n "${CBCGENERIC_PCFILES}" ; then + temp_CFLAGS=`PKG_CONFIG_PATH="$COIN_PKG_CONFIG_PATH" $PKG_CONFIG --cflags ${CBCGENERIC_PCFILES}` + temp_LFLAGS=`PKG_CONFIG_PATH="$COIN_PKG_CONFIG_PATH" $PKG_CONFIG --libs $pkg_static ${CBCGENERIC_PCFILES}` + CBCGENERIC_CFLAGS="$temp_CFLAGS ${CBCGENERIC_CFLAGS}" + CBCGENERIC_LFLAGS="$temp_LFLAGS ${CBCGENERIC_LFLAGS}" + fi + # setup XYZ_EXPORT symbol for library users + libexport_attribute= + if test "$enable_shared" = yes ; then + case $build_os in + cygwin* | mingw* | msys* | cegcc* ) + libexport_attribute="__declspec(dllimport)" + if test "$enable_static" = yes ; then + as_fn_error $? "Cannot do DLL and static LIB builds simultaneously. Do not add --enable-static without --disable-shared." "$LINENO" 5 + fi + ;; + esac + fi +printf "%s\n" "#define CBCGENERIC_EXPORT $libexport_attribute" >>confdefs.h - if test $coin_has_glpk = requested ; then - if test -n "$PKG_CONFIG" ; then - if test x"$glpk_build" = xyes ; then - pcfile="coin$glpk_pcfiles" + # add -DXYZ_BUILD to XYZ_CFLAGS + CBCGENERIC_CFLAGS="${CBCGENERIC_CFLAGS} -DCBCGENERIC_BUILD" + # Define BUILDTOOLS_DEBUG to enable debugging output + if test "$BUILDTOOLS_DEBUG" = 1 ; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: CBCGENERIC_LFLAGS_NOPC: \"${CBCGENERIC_LFLAGS_NOPC}\"" >&5 +printf "%s\n" "$as_me: CBCGENERIC_LFLAGS_NOPC: \"${CBCGENERIC_LFLAGS_NOPC}\"" >&6;} + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: CBCGENERIC_CFLAGS_NOPC: \"${CBCGENERIC_CFLAGS_NOPC}\"" >&5 +printf "%s\n" "$as_me: CBCGENERIC_CFLAGS_NOPC: \"${CBCGENERIC_CFLAGS_NOPC}\"" >&6;} + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: adding \"${CBCGENERIC_PCFILES}\"" >&5 +printf "%s\n" "$as_me: adding \"${CBCGENERIC_PCFILES}\"" >&6;} + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: CBCGENERIC_LFLAGS: \"${CBCGENERIC_LFLAGS}\"" >&5 +printf "%s\n" "$as_me: CBCGENERIC_LFLAGS: \"${CBCGENERIC_LFLAGS}\"" >&6;} + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: CBCGENERIC_CFLAGS: \"${CBCGENERIC_CFLAGS}\"" >&5 +printf "%s\n" "$as_me: CBCGENERIC_CFLAGS: \"${CBCGENERIC_CFLAGS}\"" >&6;} + fi + if test "$BUILDTOOLS_DEBUG" = 1 ; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: FINALIZE_FLAGS for OsiCbcLib:" >&5 +printf "%s\n" "$as_me: FINALIZE_FLAGS for OsiCbcLib:" >&6;} + fi + OSICBCLIB_LFLAGS_NOPC=$OSICBCLIB_LFLAGS + OSICBCLIB_CFLAGS_NOPC=$OSICBCLIB_CFLAGS - if test -n "$PKG_CONFIG" ; then - if PKG_CONFIG_PATH="$COIN_PKG_CONFIG_PATH" $PKG_CONFIG --exists "$pcfile" ; then - GLPK_VERSIONS=`PKG_CONFIG_PATH="$COIN_PKG_CONFIG_PATH" $PKG_CONFIG --modversion "$pcfile" 2>/dev/null | tr '\n' ' '` - coin_has_glpk=yes - else - GLPK_PKG_ERRORS=`PKG_CONFIG_PATH="$COIN_PKG_CONFIG_PATH" $PKG_CONFIG $pkg_short_errors --errors-to-stdout --print-errors "$pcfile"` - coin_has_glpk=no - fi - else - as_fn_error $? "\"Cannot check for existence of module glpk without pkgconf\"" "$LINENO" 5 - fi + if test -n "${OSICBCLIB_PCFILES}" ; then + temp_CFLAGS=`PKG_CONFIG_PATH="$COIN_PKG_CONFIG_PATH" $PKG_CONFIG --cflags ${OSICBCLIB_PCFILES}` + temp_LFLAGS=`PKG_CONFIG_PATH="$COIN_PKG_CONFIG_PATH" $PKG_CONFIG --libs $pkg_static ${OSICBCLIB_PCFILES}` + OSICBCLIB_CFLAGS="$temp_CFLAGS ${OSICBCLIB_CFLAGS}" + OSICBCLIB_LFLAGS="$temp_LFLAGS ${OSICBCLIB_LFLAGS}" + fi + # setup XYZ_EXPORT symbol for library users + libexport_attribute= + if test "$enable_shared" = yes ; then + case $build_os in + cygwin* | mingw* | msys* | cegcc* ) + libexport_attribute="__declspec(dllimport)" + if test "$enable_static" = yes ; then + as_fn_error $? "Cannot do DLL and static LIB builds simultaneously. Do not add --enable-static without --disable-shared." "$LINENO" 5 + fi + ;; + esac fi - if ! test $coin_has_glpk = yes ; then - pcfile="$glpk_pcfiles" +printf "%s\n" "#define OSICBCLIB_EXPORT $libexport_attribute" >>confdefs.h - if test -n "$PKG_CONFIG" ; then - if PKG_CONFIG_PATH="$COIN_PKG_CONFIG_PATH" $PKG_CONFIG --exists "$pcfile" ; then - GLPK_VERSIONS=`PKG_CONFIG_PATH="$COIN_PKG_CONFIG_PATH" $PKG_CONFIG --modversion "$pcfile" 2>/dev/null | tr '\n' ' '` - coin_has_glpk=yes - else - GLPK_PKG_ERRORS=`PKG_CONFIG_PATH="$COIN_PKG_CONFIG_PATH" $PKG_CONFIG $pkg_short_errors --errors-to-stdout --print-errors "$pcfile"` - coin_has_glpk=no - fi - else - as_fn_error $? "\"Cannot check for existence of module glpk without pkgconf\"" "$LINENO" 5 - fi + # add -DXYZ_BUILD to XYZ_CFLAGS + OSICBCLIB_CFLAGS="${OSICBCLIB_CFLAGS} -DOSICBCLIB_BUILD" + # Define BUILDTOOLS_DEBUG to enable debugging output + if test "$BUILDTOOLS_DEBUG" = 1 ; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: OSICBCLIB_LFLAGS_NOPC: \"${OSICBCLIB_LFLAGS_NOPC}\"" >&5 +printf "%s\n" "$as_me: OSICBCLIB_LFLAGS_NOPC: \"${OSICBCLIB_LFLAGS_NOPC}\"" >&6;} + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: OSICBCLIB_CFLAGS_NOPC: \"${OSICBCLIB_CFLAGS_NOPC}\"" >&5 +printf "%s\n" "$as_me: OSICBCLIB_CFLAGS_NOPC: \"${OSICBCLIB_CFLAGS_NOPC}\"" >&6;} + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: adding \"${OSICBCLIB_PCFILES}\"" >&5 +printf "%s\n" "$as_me: adding \"${OSICBCLIB_PCFILES}\"" >&6;} + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: OSICBCLIB_LFLAGS: \"${OSICBCLIB_LFLAGS}\"" >&5 +printf "%s\n" "$as_me: OSICBCLIB_LFLAGS: \"${OSICBCLIB_LFLAGS}\"" >&6;} + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: OSICBCLIB_CFLAGS: \"${OSICBCLIB_CFLAGS}\"" >&5 +printf "%s\n" "$as_me: OSICBCLIB_CFLAGS: \"${OSICBCLIB_CFLAGS}\"" >&6;} fi - if test $coin_has_glpk = yes ; then - glpk_data=`PKG_CONFIG_PATH="$COIN_PKG_CONFIG_PATH" $PKG_CONFIG --variable=datadir "$pcfile" 2>/dev/null` - glpk_pcfiles="$pcfile" + if test "$BUILDTOOLS_DEBUG" = 1 ; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: FINALIZE_FLAGS for CbcUnitTest:" >&5 +printf "%s\n" "$as_me: FINALIZE_FLAGS for CbcUnitTest:" >&6;} fi - else - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: Check for glpk via pkg-config could not be performed as there is no pkg-config available. Consider installing pkg-config or provide appropriate values for --with-glpk-lflags and --with-glpk-cflags." >&5 -printf "%s\n" "$as_me: WARNING: Check for glpk via pkg-config could not be performed as there is no pkg-config available. Consider installing pkg-config or provide appropriate values for --with-glpk-lflags and --with-glpk-cflags." >&2;} - coin_has_glpk=no - fi - fi - - - if test "$BUILDTOOLS_DEBUG" = 1 ; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: FIND_PRIM_PKG result for glpk: \"$coin_has_glpk\"" >&5 -printf "%s\n" "$as_me: FIND_PRIM_PKG result for glpk: \"$coin_has_glpk\"" >&6;} - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: Collected values for package 'glpk'" >&5 -printf "%s\n" "$as_me: Collected values for package 'glpk'" >&6;} - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: glpk_lflags is \"$glpk_lflags\"" >&5 -printf "%s\n" "$as_me: glpk_lflags is \"$glpk_lflags\"" >&6;} - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: glpk_cflags is \"$glpk_cflags\"" >&5 -printf "%s\n" "$as_me: glpk_cflags is \"$glpk_cflags\"" >&6;} - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: glpk_data is \"$glpk_data\"" >&5 -printf "%s\n" "$as_me: glpk_data is \"$glpk_data\"" >&6;} - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: glpk_pcfiles is \"$glpk_pcfiles\"" >&5 -printf "%s\n" "$as_me: glpk_pcfiles is \"$glpk_pcfiles\"" >&6;} - fi - - - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $coin_has_glpk" >&5 -printf "%s\n" "$coin_has_glpk" >&6; } - else - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $coin_has_glpk (COIN_SKIP_PROJECTS)" >&5 -printf "%s\n" "$coin_has_glpk (COIN_SKIP_PROJECTS)" >&6; } - fi - - - if test "$coin_has_glpk" != yes ; then - coin_has_glpk=no - fi - - - if test $coin_has_glpk = yes; then - COIN_HAS_GLPK_TRUE= - COIN_HAS_GLPK_FALSE='#' -else - COIN_HAS_GLPK_TRUE='#' - COIN_HAS_GLPK_FALSE= -fi + CBCUNITTEST_LFLAGS_NOPC=$CBCUNITTEST_LFLAGS + CBCUNITTEST_CFLAGS_NOPC=$CBCUNITTEST_CFLAGS + if test -n "${CBCUNITTEST_PCFILES}" ; then + temp_CFLAGS=`PKG_CONFIG_PATH="$COIN_PKG_CONFIG_PATH" $PKG_CONFIG --cflags ${CBCUNITTEST_PCFILES}` + temp_LFLAGS=`PKG_CONFIG_PATH="$COIN_PKG_CONFIG_PATH" $PKG_CONFIG --libs $pkg_static ${CBCUNITTEST_PCFILES}` + CBCUNITTEST_CFLAGS="$temp_CFLAGS ${CBCUNITTEST_CFLAGS}" + CBCUNITTEST_LFLAGS="$temp_LFLAGS ${CBCUNITTEST_LFLAGS}" + fi - if test $coin_has_glpk = yes ; then + # setup XYZ_EXPORT symbol for library users + libexport_attribute= + if test "$enable_shared" = yes ; then + case $build_os in + cygwin* | mingw* | msys* | cegcc* ) + libexport_attribute="__declspec(dllimport)" + if test "$enable_static" = yes ; then + as_fn_error $? "Cannot do DLL and static LIB builds simultaneously. Do not add --enable-static without --disable-shared." "$LINENO" 5 + fi + ;; + esac + fi -printf "%s\n" "#define CBC_HAS_GLPK 1" >>confdefs.h +printf "%s\n" "#define CBCUNITTEST_EXPORT $libexport_attribute" >>confdefs.h - CBCSOLVERLIB_PCFILES="$glpk_pcfiles $CBCSOLVERLIB_PCFILES" - CBCSOLVERLIB_LFLAGS="$glpk_lflags $CBCSOLVERLIB_LFLAGS" - CBCSOLVERLIB_CFLAGS="$glpk_cflags $CBCSOLVERLIB_CFLAGS" + # add -DXYZ_BUILD to XYZ_CFLAGS + CBCUNITTEST_CFLAGS="${CBCUNITTEST_CFLAGS} -DCBCUNITTEST_BUILD" + # Define BUILDTOOLS_DEBUG to enable debugging output + if test "$BUILDTOOLS_DEBUG" = 1 ; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: CBCUNITTEST_LFLAGS_NOPC: \"${CBCUNITTEST_LFLAGS_NOPC}\"" >&5 +printf "%s\n" "$as_me: CBCUNITTEST_LFLAGS_NOPC: \"${CBCUNITTEST_LFLAGS_NOPC}\"" >&6;} + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: CBCUNITTEST_CFLAGS_NOPC: \"${CBCUNITTEST_CFLAGS_NOPC}\"" >&5 +printf "%s\n" "$as_me: CBCUNITTEST_CFLAGS_NOPC: \"${CBCUNITTEST_CFLAGS_NOPC}\"" >&6;} + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: adding \"${CBCUNITTEST_PCFILES}\"" >&5 +printf "%s\n" "$as_me: adding \"${CBCUNITTEST_PCFILES}\"" >&6;} + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: CBCUNITTEST_LFLAGS: \"${CBCUNITTEST_LFLAGS}\"" >&5 +printf "%s\n" "$as_me: CBCUNITTEST_LFLAGS: \"${CBCUNITTEST_LFLAGS}\"" >&6;} + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: CBCUNITTEST_CFLAGS: \"${CBCUNITTEST_CFLAGS}\"" >&5 +printf "%s\n" "$as_me: CBCUNITTEST_CFLAGS: \"${CBCUNITTEST_CFLAGS}\"" >&6;} + fi - fi ############################################################################# @@ -23315,7 +23206,7 @@ ac_config_files="$ac_config_files doxydoc/doxygen.conf" # Here put the location and name of the configuration header file -ac_config_headers="$ac_config_headers src/config.h src/config_cbc.h src/config_cbcsolver.h src/OsiCbc/config_osicbc.h" +ac_config_headers="$ac_config_headers src/config.h src/config_cbc.h src/OsiCbc/config_osicbc.h" @@ -23784,10 +23675,6 @@ if test -z "${COIN_HAS_CPLEX_TRUE}" && test -z "${COIN_HAS_CPLEX_FALSE}"; then as_fn_error $? "conditional \"COIN_HAS_CPLEX\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi -if test -z "${COIN_HAS_GLPK_TRUE}" && test -z "${COIN_HAS_GLPK_FALSE}"; then - as_fn_error $? "conditional \"COIN_HAS_GLPK\" was never defined. -Usually this means the macro was only invoked conditionally." "$LINENO" 5 -fi if test -z "${CBC_BUILD_CBC_GENERIC_TRUE}" && test -z "${CBC_BUILD_CBC_GENERIC_FALSE}"; then as_fn_error $? "conditional \"CBC_BUILD_CBC_GENERIC\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 @@ -24834,7 +24721,6 @@ do "doxydoc/doxygen.conf") CONFIG_FILES="$CONFIG_FILES doxydoc/doxygen.conf" ;; "src/config.h") CONFIG_HEADERS="$CONFIG_HEADERS src/config.h" ;; "src/config_cbc.h") CONFIG_HEADERS="$CONFIG_HEADERS src/config_cbc.h" ;; - "src/config_cbcsolver.h") CONFIG_HEADERS="$CONFIG_HEADERS src/config_cbcsolver.h" ;; "src/OsiCbc/config_osicbc.h") CONFIG_HEADERS="$CONFIG_HEADERS src/OsiCbc/config_osicbc.h" ;; *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;; diff --git a/configure.ac b/configure.ac index 17de59916..14146ecdd 100644 --- a/configure.ac +++ b/configure.ac @@ -57,29 +57,29 @@ AC_CHECK_HEADERS([signal.h]) ############################################################################# m4_foreach_w([myvar],[CoinUtils Osi Cgl Clp], - [ AC_COIN_CHK_PKG(myvar,[CbcLib CbcSolverLib CbcGeneric OsiCbcLib]) + [ AC_COIN_CHK_PKG(myvar,[CbcLib OsiCbcLib]) if test $coin_has_[]m4_tolower(myvar) != yes ; then AC_MSG_ERROR([Required package myvar is not available.]) fi ]) -AC_COIN_CHK_PKG(OsiClp,[CbcLib CbcSolverLib CbcGeneric OsiCbcLib],[osi-clp]) +AC_COIN_CHK_PKG(OsiClp,[CbcLib OsiCbcLib],[osi-clp]) if test $coin_has_osiclp != yes ; then AC_MSG_ERROR("Required package OsiClp unavailable.") fi # Optional package for command line edit support -AC_COIN_CHK_GNU_READLINE([CbcLib CbcGeneric]) +AC_COIN_CHK_GNU_READLINE([CbcLib]) ############################################################################# # Other third party software # ############################################################################# # Ampl Solver library -AC_COIN_CHK_PKG(ASL,[CbcSolverLib],[coinasl]) +AC_COIN_CHK_PKG(ASL,[CbcLib],[coinasl]) # Nauty library (for symmetry detection). -AC_COIN_CHK_PKG([Nauty],[CbcLib CbcSolverLib],[nauty]) +AC_COIN_CHK_PKG([Nauty],[CbcLib],[nauty]) ############################################################################# @@ -96,54 +96,55 @@ AC_COIN_CHK_PKG(Miplib3,,[coindatamiplib3],,dataonly) # Check which other LP solvers are available, some of them become a dependency # of CbcGeneric -AC_COIN_CHK_PKG(OsiDyLP,[CbcGeneric OsiCbcLib],[osi-dylp]) -AC_COIN_CHK_PKG(OsiCpx,[CbcLib CbcGeneric CbcSolverLib OsiCbcLib],[osi-cplex]) -AC_COIN_CHK_PKG(OsiGlpk,[CbcGeneric OsiCbcLib],[osi-glpk]) -#AC_COIN_CHK_PKG(OsiGrb,,[osi-gurobi]) -AC_COIN_CHK_PKG(OsiMsk,[CbcGeneric OsiCbcLib],[osi-mosek]) -AC_COIN_CHK_PKG(OsiSpx,[CbcGeneric OsiCbcLib],[osi-soplex]) +#AC_COIN_CHK_PKG(OsiDyLP,[CbcGeneric OsiCbcLib],[osi-dylp]) +#AC_COIN_CHK_PKG(OsiCpx,[CbcLib CbcGeneric OsiCbcLib],[osi-cplex]) +#AC_COIN_CHK_PKG(OsiGlpk,[CbcGeneric OsiCbcLib],[osi-glpk]) +##AC_COIN_CHK_PKG(OsiGrb,,[osi-gurobi]) +#AC_COIN_CHK_PKG(OsiMsk,[CbcGeneric OsiCbcLib],[osi-mosek]) +#AC_COIN_CHK_PKG(OsiSpx,[CbcGeneric OsiCbcLib],[osi-soplex]) #AC_COIN_CHK_PKG(OsiXpr,,[osi-xpress]) AC_COIN_CHK_LIB(Cplex,[CbcLib],[-lcplex -lpthread -lm -ldl],[],[],[CPXgetstat]) -AC_COIN_CHK_PKG(Glpk,[CbcSolverLib],[coinglpk]) + +AC_COIN_FINALIZE_FLAGS([CbcLib OsiCbcLib CbcUnitTest]) ############################################################################# # CbcGeneric configuration # ############################################################################# # Are we building cbc-generic? Default is no (false). -AC_ARG_ENABLE([cbc-generic], - AS_HELP_STRING([--enable-cbc-generic],[enables build of cbc-generic]), - [cbc_generic=$enableval], - [cbc_generic=no]) -AM_CONDITIONAL(CBC_BUILD_CBC_GENERIC, test "$cbc_generic" = yes) - -if test "$cbc_generic" = yes ; then - # Set the default solver for cbc-generic. In theory, any OsiXXX should work. - # In practice, only thoselisted below have had any testing long long ago or never. - AC_MSG_CHECKING(for cbc-generic default solver) - AC_ARG_WITH([cbc-generic-solver], - AS_HELP_STRING([--with-cbc-generic-solver],[specify default solver for cbc-generic in lower case letters (if not given, clp is assumed)]), - [cbc_default_solver=$withval], - [cbc_default_solver=clp]) - AC_MSG_RESULT($cbc_default_solver) - - case $cbc_default_solver in - clp) ;; - cplex) ;; - dylp) ;; - glpk) ;; - highs) ;; - mosek) ;; - soplex) ;; - *) AC_MSG_WARN([Unrecognised solver $cbc_default_solver chosen as cbc-generic default solver.]) - ;; - esac - AC_DEFINE_UNQUOTED([CBC_DEFAULT_SOLVER],"$cbc_default_solver", - [Define to the name of the default solver to be used in cbc-generic in small letters]) - - AC_MSG_NOTICE([building cbc-generic with default solver $cbc_default_solver]) -fi +dnl AC_ARG_ENABLE([cbc-generic], +dnl AS_HELP_STRING([--enable-cbc-generic],[enables build of cbc-generic]), +dnl [cbc_generic=$enableval], +dnl [cbc_generic=no]) +dnl AM_CONDITIONAL(CBC_BUILD_CBC_GENERIC, test "$cbc_generic" = yes) + +dnl if test "$cbc_generic" = yes ; then +dnl # Set the default solver for cbc-generic. In theory, any OsiXXX should work. +dnl # In practice, only thoselisted below have had any testing long long ago or never. +dnl AC_MSG_CHECKING(for cbc-generic default solver) +dnl AC_ARG_WITH([cbc-generic-solver], +dnl AS_HELP_STRING([--with-cbc-generic-solver],[specify default solver for cbc-generic in lower case letters (if not given, clp is assumed)]), +dnl [cbc_default_solver=$withval], +dnl [cbc_default_solver=clp]) +dnl AC_MSG_RESULT($cbc_default_solver) + +dnl case $cbc_default_solver in +dnl clp) ;; +dnl cplex) ;; +dnl dylp) ;; +dnl glpk) ;; +dnl highs) ;; +dnl mosek) ;; +dnl soplex) ;; +dnl *) AC_MSG_WARN([Unrecognised solver $cbc_default_solver chosen as cbc-generic default solver.]) +dnl ;; +dnl esac +dnl AC_DEFINE_UNQUOTED([CBC_DEFAULT_SOLVER],"$cbc_default_solver", +dnl [Define to the name of the default solver to be used in cbc-generic in small letters]) + +dnl AC_MSG_NOTICE([building cbc-generic with default solver $cbc_default_solver]) +dnl fi ############################################################################# # Cbc parallel configuration # @@ -358,7 +359,7 @@ AC_CONFIG_FILES([Makefile AC_CONFIG_FILES([doxydoc/doxygen.conf]) # Here put the location and name of the configuration header file -AC_CONFIG_HEADERS([src/config.h src/config_cbc.h src/config_cbcsolver.h src/OsiCbc/config_osicbc.h]) +AC_CONFIG_HEADERS([src/config.h src/config_cbc.h src/OsiCbc/config_osicbc.h]) AC_COIN_FINALIZE_FLAGS([CbcLib CbcSolverLib CbcGeneric OsiCbcLib CbcUnitTest]) diff --git a/src/CbcGenOsiParam.cpp b/src/Attic/CbcGenOsiParam.cpp similarity index 100% rename from src/CbcGenOsiParam.cpp rename to src/Attic/CbcGenOsiParam.cpp diff --git a/src/CbcGenOsiParam.hpp b/src/Attic/CbcGenOsiParam.hpp similarity index 84% rename from src/CbcGenOsiParam.hpp rename to src/Attic/CbcGenOsiParam.hpp index e6e88ac81..1ccab3f84 100644 --- a/src/CbcGenOsiParam.hpp +++ b/src/Attic/CbcGenOsiParam.hpp @@ -17,7 +17,7 @@ */ /* -*/ + */ /*! \class CbcOsiParam \brief Class for control parameters that act on a OsiSolverInterface object. @@ -40,7 +40,8 @@ class CbcOsiParam : public CoinParam { object. CBCOSI_FIRSTPARAM and CBCOSI_LASTPARAM are markers to allow convenient separation of parameter groups. */ - typedef enum { CBCOSI_FIRSTPARAM = CbcCbcParam::CBCCBC_LASTPARAM + 1, + typedef enum { + CBCOSI_FIRSTPARAM = CbcCbcParam::CBCCBC_LASTPARAM + 1, ALGORITHM, ALLSLACK, @@ -115,16 +116,15 @@ class CbcOsiParam : public CoinParam { constructor for an integer parameter. */ CbcOsiParam(CbcOsiParamCode code, std::string name, std::string help, - double lower, double upper, double dflt = 0.0, - bool display = true); + double lower, double upper, double dflt = 0.0, + bool display = true); /*! \brief Constructor for a parameter with an integer value The default value is 0. */ CbcOsiParam(CbcOsiParamCode code, std::string name, std::string help, - int lower, int upper, int dflt = 0, - bool display = true); + int lower, int upper, int dflt = 0, bool display = true); /*! \brief Constructor for a parameter with keyword values @@ -136,7 +136,7 @@ class CbcOsiParam : public CoinParam { constructors. */ CbcOsiParam(CbcOsiParamCode code, std::string name, std::string help, - std::string firstValue, int dflt, bool display = true); + std::string firstValue, int dflt, bool display = true); /*! \brief Constructor for a string parameter @@ -145,12 +145,12 @@ class CbcOsiParam : public CoinParam { */ CbcOsiParam(CbcOsiParamCode code, std::string name, std::string help, - std::string dflt, bool display = true); + std::string dflt, bool display = true); /*! \brief Constructor for an action parameter */ CbcOsiParam(CbcOsiParamCode code, std::string name, std::string help, - bool display = true); + bool display = true); /*! \brief Copy constructor */ @@ -175,31 +175,19 @@ class CbcOsiParam : public CoinParam { /*! \brief Get the parameter code */ - inline CbcOsiParamCode paramCode() const - { - return (paramCode_); - } + inline CbcOsiParamCode paramCode() const { return (paramCode_); } /*! \brief Set the parameter code */ - inline void setParamCode(CbcOsiParamCode code) - { - paramCode_ = code; - } + inline void setParamCode(CbcOsiParamCode code) { paramCode_ = code; } /*! \brief Get the underlying OsiSolverInterface object */ - inline OsiSolverInterface *obj() const - { - return (obj_); - } + inline OsiSolverInterface *obj() const { return (obj_); } /*! \brief Set the underlying OsiSolverInterace object */ - inline void setObj(OsiSolverInterface *obj) - { - obj_ = obj; - } + inline void setObj(OsiSolverInterface *obj) { obj_ = obj; } //@} @@ -222,9 +210,8 @@ class CbcOsiParam : public CoinParam { namespace CbcOsiParamUtils { void addCbcOsiParams(int &numParams, CoinParamVec ¶mVec, - OsiSolverInterface *osi); -void loadOsiParamObj(const CoinParamVec paramVec, - CbcGenCtlBlk *ctlBlk); + OsiSolverInterface *osi); +void loadOsiParamObj(const CoinParamVec paramVec, CbcGenCtlBlk *ctlBlk); void setOsiSolverInterfaceDefaults(OsiSolverInterface *osi); int pushCbcOsiLogLevel(CoinParam *param); @@ -232,9 +219,9 @@ int pushCbcOsiInt(CoinParam *param); int pushCbcOsiDbl(CoinParam *param); int pushCbcOsiKwd(CoinParam *param); int pushCbcOsiHint(CoinParam *param); -} +} // namespace CbcOsiParamUtils #endif /* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 -*/ + */ diff --git a/src/CbcGenOsiParamUtils.cpp b/src/Attic/CbcGenOsiParamUtils.cpp similarity index 100% rename from src/CbcGenOsiParamUtils.cpp rename to src/Attic/CbcGenOsiParamUtils.cpp diff --git a/src/Attic/CbcModelParam.cpp b/src/Attic/CbcModelParam.cpp new file mode 100644 index 000000000..1a5a3e3f4 --- /dev/null +++ b/src/Attic/CbcModelParam.cpp @@ -0,0 +1,160 @@ +/* + Copyright (C) 2007, Lou Hafer, International Business Machines Corporation + and others. All Rights Reserved. + + This code is licensed under the terms of the Eclipse Public License (EPL). + +*/ +/* + This file is part of cbc-generic. +*/ + +#if defined(_MSC_VER) +// Turn off compiler warning about long names +#pragma warning(disable : 4786) +#endif + +#include +#include + +#include "CoinFinite.hpp" +#include "CoinParam.hpp" + +#include "CbcModel.hpp" + +#include "CbcModelParam.hpp" +#include "CbcParam.hpp" + +/* + Constructors and destructors + + There's a generic constructor and one for integer, double, keyword, string, + and action parameters. +*/ + +/* + Default constructor. +*/ +CbcModelParam::CbcModelParam() + : CoinParam(), paramCode_(CbcModelParamCode(0)), obj_(0) { + /* Nothing to be done here */ +} + +//########################################################################### +//########################################################################### + +/* + Constructor for double parameter +*/ +CbcModelParam::CbcModelParam(CbcModelParamCode code, std::string name, + std::string help, double lower, double upper, + double defaultValue, std::string longHelp, + CoinDisplayPriority displayPriority) + : CoinParam(name, help, lower, upper, defaultValue, longHelp, + displayPriority), + paramCode_(code), obj_(0) { + /* Nothing to be done here */ +} + +//########################################################################### +//########################################################################### + +/* + Constructor for integer parameter +*/ +CbcModelParam::CbcModelParam(CbcModelParamCode code, std::string name, + std::string help, int lower, int upper, + int defaultValue, std::string longHelp, + CoinDisplayPriority displayPriority) + : CoinParam(name, help, lower, upper, defaultValue, longHelp, + displayPriority), + paramCode_(code), obj_(0) { + /* Nothing to be done here */ +} + +//########################################################################### +//########################################################################### + +/* + Constructor for keyword parameter. +*/ +CbcModelParam::CbcModelParam(CbcModelParamCode code, std::string name, + std::string help, std::string defaultKwd, + int defaultMode, std::string longHelp, + CoinDisplayPriority displayPriority) + : CoinParam(name, help, defaultKwd, defaultMode, longHelp, displayPriority), + paramCode_(code), obj_(0) { + /* Nothing to be done here */ +} + +//########################################################################### +//########################################################################### + +/* + Constructor for string parameter. +*/ +CbcModelParam::CbcModelParam(CbcModelParamCode code, std::string name, + std::string help, std::string defaultValue, + std::string longHelp, + CoinDisplayPriority displayPriority) + : CoinParam(name, help, defaultValue, longHelp, displayPriority), + paramCode_(code), obj_(0) { + /* Nothing to be done here */ +} + +//########################################################################### +//########################################################################### + +/* + Constructor for action parameter. +*/ +CbcModelParam::CbcModelParam(CbcModelParamCode code, std::string name, + std::string help, std::string longHelp, + CoinDisplayPriority displayPriority) + : CoinParam(name, help, longHelp, displayPriority), paramCode_(code), + obj_(0) { + /* Nothing to be done here */ +} + +//########################################################################### +//########################################################################### + +/* + Copy constructor. +*/ +CbcModelParam::CbcModelParam(const CbcModelParam &orig) + : CoinParam(orig), paramCode_(orig.paramCode_), obj_(orig.obj_) { + /* Nothing to be done here */ +} + +//########################################################################### +//########################################################################### + +/* + Clone +*/ + +CbcModelParam *CbcModelParam::clone() { return (new CbcModelParam(*this)); } + +CbcModelParam &CbcModelParam::operator=(const CbcModelParam &rhs) { + if (this != &rhs) { + CoinParam::operator=(rhs); + + paramCode_ = rhs.paramCode_; + obj_ = rhs.obj_; + } + + return *this; +} + +//########################################################################### +//########################################################################### + +/* + Destructor +*/ +CbcModelParam::~CbcModelParam() { /* Nothing more to do */ +} + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 + */ diff --git a/src/CbcGenCbcParam.hpp b/src/Attic/CbcModelParam.hpp similarity index 50% rename from src/CbcGenCbcParam.hpp rename to src/Attic/CbcModelParam.hpp index a411ce2ba..5622db21f 100644 --- a/src/CbcGenCbcParam.hpp +++ b/src/Attic/CbcModelParam.hpp @@ -5,67 +5,79 @@ This code is licensed under the terms of the Eclipse Public License (EPL). */ -/* - This file is part of cbc-generic. -*/ -#ifndef CbcCbcParam_H -#define CbcCbcParam_H +#ifndef CbcModelParam_H +#define CbcModelParam_H -/* \file CbcGenCbcParam.hpp +#include "CoinParam.hpp" +#include "CbcParam.hpp" + +/* \file CbcModelParam.hpp \brief Declarations for parameters that act on a CbcModel object. */ +enum CbcModelParamCode { + CBCMODEL_FIRSTPARAM = CBCSOLVER_LASTPARAM + 1, + + ALLOWABLEGAP, + COSTSTRATEGY, + //CUTDEPTH, + CUTOFF, + CUTPASS, + DIRECTION, + GAPRATIO, + INCREMENT, + INFEASIBILITYWEIGHT, + INTEGERTOLERANCE, + //LOGLEVEL, + MAXIMIZE, + MAXNODES, + MAXNODESNOTIMPROVING, // Added + MAXSECONDSNOTIMPROVING, // Added + MAXSOLS, // Added + MINIMIZE, + MIPOPTIONS, + MOREMIPOPTIONS, + NUMBERANALYZE, + NUMBERBEFORE, + REVERSE, + STRONGBRANCHING, + TIMELIMIT, + + CBCMODEL_LASTPARAM + +}; + /* -*/ + */ -/*! \class CbcCbcParam +/*! \class CbcModelParam \brief Class for control parameters that act on a CbcModel object. Adds parameter type codes and push/pull functions to the generic parameter object. */ -class CbcCbcParam : public CoinParam { +class CbcModelParam : public CoinParam { public: /*! \name Subtypes */ //@{ - /*! \enum CbcCbcParamCode + /*! \enum CbcModelParamCode \brief Enumeration for parameters that control a CbcModel object These are parameters that control the operation of a CbcModel object. CBCCBC_FIRSTPARAM and CBCCBC_LASTPARAM are markers to allow convenient separation of parameter groups. */ - typedef enum { CBCCBC_FIRSTPARAM = CbcGenParam::CBCGEN_LASTPARAM + 1, - - ALLOWABLEGAP, - COSTSTRATEGY, - CUTDEPTH, - CUTOFF, - CUTPASS, - DIRECTION, - GAPRATIO, - INCREMENT, - INFEASIBILITYWEIGHT, - INTEGERTOLERANCE, - LOGLEVEL, - MAXIMIZE, - MAXNODES, - MINIMIZE, - MIPOPTIONS, - MOREMIPOPTIONS, - NUMBERANALYZE, - NUMBERBEFORE, - NUMBERMINI, - STRONGBRANCHING, - TIMELIMIT_BAB, - - CBCCBC_LASTPARAM - - } CbcCbcParamCode; + + enum OptimizationDirection { + OptDirMaximize = 0, + OptDirMinimize, + OptDirZero, + OptDireEndMarker + }; //@} @@ -77,7 +89,7 @@ class CbcCbcParam : public CoinParam { //@{ /*! \brief Default constructor */ - CbcCbcParam(); + CbcModelParam(); /*! \brief Constructor for a parameter with a double value @@ -85,17 +97,19 @@ class CbcCbcParam : public CoinParam { \p upper are real (double) values to distinguish this constructor from the constructor for an integer parameter. */ - CbcCbcParam(CbcCbcParamCode code, std::string name, std::string help, - double lower, double upper, double dflt = 0.0, - bool display = true); + CbcModelParam(CbcModelParamCode code, std::string name, std::string help, + double lower = -COIN_DBL_MAX, double upper = COIN_DBL_MAX, + double defaultValue = 0.0, std::string longHelp = "", + CoinDisplayPriority displayPriority = displayPriorityHigh); /*! \brief Constructor for a parameter with an integer value The default value is 0. - */ - CbcCbcParam(CbcCbcParamCode code, std::string name, std::string help, - int lower, int upper, int dflt = 0, - bool display = true); + */ + CbcModelParam(CbcModelParamCode code, std::string name, std::string help, + int lower = -COIN_INT_MAX, int upper = COIN_INT_MAX, + int defaultValue = 0, std::string longHelp = "", + CoinDisplayPriority displayPriority = displayPriorityHigh); /*! \brief Constructor for a parameter with keyword values @@ -106,8 +120,10 @@ class CbcCbcParam : public CoinParam { distinguish this constructor from the string and action parameter constructors. */ - CbcCbcParam(CbcCbcParamCode code, std::string name, std::string help, - std::string firstValue, int dflt, bool display = true); + CbcModelParam(CbcModelParamCode code, std::string name, std::string help, + std::string defaultKwd, int defaultMode, + std::string longHelp = "", + CoinDisplayPriority displayPriority = displayPriorityHigh); /*! \brief Constructor for a string parameter @@ -115,29 +131,31 @@ class CbcCbcParam : public CoinParam { a string constructor from an action parameter constructor. */ - CbcCbcParam(CbcCbcParamCode code, std::string name, std::string help, - std::string dflt, bool display = true); + CbcModelParam(CbcModelParamCode code, std::string name, std::string help, + std::string defaultValue, std::string longHelp = "", + CoinDisplayPriority displayPriority = displayPriorityHigh); /*! \brief Constructor for an action parameter */ - CbcCbcParam(CbcCbcParamCode code, std::string name, std::string help, - bool display = true); + // No defaults to resolve ambiguity + CbcModelParam(CbcModelParamCode code, std::string name, std::string help, + std::string longHelp, CoinDisplayPriority displayPriority); /*! \brief Copy constructor */ - CbcCbcParam(const CbcCbcParam &orig); + CbcModelParam(const CbcModelParam &orig); /*! \brief Clone */ - CbcCbcParam *clone(); + CbcModelParam *clone(); /*! \brief Assignment */ - CbcCbcParam &operator=(const CbcCbcParam &rhs); + CbcModelParam &operator=(const CbcModelParam &rhs); /*! \brief Destructor */ - ~CbcCbcParam(); + ~CbcModelParam(); //@} @@ -146,31 +164,19 @@ class CbcCbcParam : public CoinParam { /*! \brief Get the parameter code */ - inline CbcCbcParamCode paramCode() const - { - return (paramCode_); - } + inline CbcModelParamCode paramCode() const { return (paramCode_); } /*! \brief Set the parameter code */ - inline void setParamCode(CbcCbcParamCode code) - { - paramCode_ = code; - } + inline void setParamCode(CbcModelParamCode code) { paramCode_ = code; } /*! \brief Get the underlying CbcModel object */ - inline CbcModel *obj() const - { - return (obj_); - } + inline CbcModel *obj() const { return (obj_); } /*! \brief Set the underlying CbcModel object */ - inline void setObj(CbcModel *obj) - { - obj_ = obj; - } + inline void setObj(CbcModel *obj) { obj_ = obj; } //@} @@ -179,7 +185,7 @@ class CbcCbcParam : public CoinParam { //@{ /// Parameter code - CbcCbcParamCode paramCode_; + CbcModelParamCode paramCode_; /// CbcModel object CbcModel *obj_; @@ -187,22 +193,7 @@ class CbcCbcParam : public CoinParam { //@} }; -/* - Declare the utility functions. -*/ - -namespace CbcCbcParamUtils { -void addCbcCbcParams(int &numParams, CoinParamVec ¶mVec, - CbcModel *model); -void loadCbcParamObj(const CoinParamVec paramVec, int first, int last, - CbcModel *model); -void setCbcModelDefaults(CbcModel *model); - -int pushCbcCbcDbl(CoinParam *param); -int pushCbcCbcInt(CoinParam *param); -} - #endif /* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 -*/ + */ diff --git a/src/Attic/CbcParam.cpp b/src/Attic/CbcParam.cpp new file mode 100644 index 000000000..40601cacc --- /dev/null +++ b/src/Attic/CbcParam.cpp @@ -0,0 +1,2675 @@ +// Copyright (C) 2002, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#if defined(_MSC_VER) +// Turn off compiler warning about long names +#pragma warning(disable : 4786) +#endif + +#include "CbcConfig.h" + +#include +#include +#include +#include + +#include "CoinParam.hpp" + +#include "ClpFactorization.hpp" + +#include "CbcParam.hpp" + +//############################################################################# +// Constructors / Destructor / Assignment +//############################################################################# + +//------------------------------------------------------------------- +// Default Constructor +//------------------------------------------------------------------- +CbcParam::CbcParam() + : type_(CBC_PARAM_NOTUSED_INVALID), lowerDoubleValue_(0.0), + upperDoubleValue_(0.0), lowerIntValue_(0), upperIntValue_(0), + lengthName_(0), lengthMatch_(0), definedKeyWords_(), name_(), + shortHelp_(), longHelp_(), action_(CBC_PARAM_NOTUSED_INVALID), + currentKeyWord_(-1), display_(0), intValue_(-1), doubleValue_(-1.0), + stringValue_(""), whereUsed_(7), fakeKeyWord_(-1), fakeValue_(0) {} +// Other constructors +CbcParam::CbcParam(std::string name, std::string help, double lower, + double upper, CbcParameterType type, int display) + : type_(type), lowerIntValue_(0), upperIntValue_(0), definedKeyWords_(), + name_(name), shortHelp_(help), longHelp_(), action_(type), + currentKeyWord_(-1), display_(display), intValue_(-1), doubleValue_(-1.0), + stringValue_(""), whereUsed_(7), fakeKeyWord_(-1), fakeValue_(0) { + lowerDoubleValue_ = lower; + upperDoubleValue_ = upper; + gutsOfConstructor(); +} +CbcParam::CbcParam(std::string name, std::string help, int lower, int upper, + CbcParameterType type, int display) + : type_(type), lowerDoubleValue_(0.0), upperDoubleValue_(0.0), + definedKeyWords_(), name_(name), shortHelp_(help), longHelp_(), + action_(type), currentKeyWord_(-1), display_(display), intValue_(-1), + doubleValue_(-1.0), stringValue_(""), whereUsed_(7), fakeKeyWord_(-1), + fakeValue_(0) { + gutsOfConstructor(); + lowerIntValue_ = lower; + upperIntValue_ = upper; +} +// Other strings will be added by append +CbcParam::CbcParam(std::string name, std::string help, std::string firstValue, + CbcParameterType type, int whereUsed, int display) + : type_(type), lowerDoubleValue_(0.0), upperDoubleValue_(0.0), + lowerIntValue_(0), upperIntValue_(0), definedKeyWords_(), name_(name), + shortHelp_(help), longHelp_(), action_(type), currentKeyWord_(0), + display_(display), intValue_(-1), doubleValue_(-1.0), stringValue_(""), + whereUsed_(whereUsed), fakeKeyWord_(-1), fakeValue_(0) { + gutsOfConstructor(); + definedKeyWords_.push_back(firstValue); +} +// Action +CbcParam::CbcParam(std::string name, std::string help, CbcParameterType type, + int whereUsed, int display) + : type_(type), lowerDoubleValue_(0.0), upperDoubleValue_(0.0), + lowerIntValue_(0), upperIntValue_(0), definedKeyWords_(), name_(name), + shortHelp_(help), longHelp_(), action_(type), currentKeyWord_(-1), + display_(display), intValue_(-1), doubleValue_(-1.0), stringValue_(""), + fakeKeyWord_(-1), fakeValue_(0) { + whereUsed_ = whereUsed; + gutsOfConstructor(); +} + +//------------------------------------------------------------------- +// Copy constructor +//------------------------------------------------------------------- +CbcParam::CbcParam(const CbcParam &rhs) { + type_ = rhs.type_; + lowerDoubleValue_ = rhs.lowerDoubleValue_; + upperDoubleValue_ = rhs.upperDoubleValue_; + lowerIntValue_ = rhs.lowerIntValue_; + upperIntValue_ = rhs.upperIntValue_; + lengthName_ = rhs.lengthName_; + lengthMatch_ = rhs.lengthMatch_; + definedKeyWords_ = rhs.definedKeyWords_; + name_ = rhs.name_; + shortHelp_ = rhs.shortHelp_; + longHelp_ = rhs.longHelp_; + action_ = rhs.action_; + currentKeyWord_ = rhs.currentKeyWord_; + display_ = rhs.display_; + intValue_ = rhs.intValue_; + doubleValue_ = rhs.doubleValue_; + stringValue_ = rhs.stringValue_; + whereUsed_ = rhs.whereUsed_; + fakeKeyWord_ = rhs.fakeKeyWord_; + fakeValue_ = rhs.fakeValue_; +} + +//------------------------------------------------------------------- +// Destructor +//------------------------------------------------------------------- +CbcParam::~CbcParam() {} + +//---------------------------------------------------------------- +// Assignment operator +//------------------------------------------------------------------- +CbcParam &CbcParam::operator=(const CbcParam &rhs) { + if (this != &rhs) { + type_ = rhs.type_; + lowerDoubleValue_ = rhs.lowerDoubleValue_; + upperDoubleValue_ = rhs.upperDoubleValue_; + lowerIntValue_ = rhs.lowerIntValue_; + upperIntValue_ = rhs.upperIntValue_; + lengthName_ = rhs.lengthName_; + lengthMatch_ = rhs.lengthMatch_; + definedKeyWords_ = rhs.definedKeyWords_; + name_ = rhs.name_; + shortHelp_ = rhs.shortHelp_; + longHelp_ = rhs.longHelp_; + action_ = rhs.action_; + currentKeyWord_ = rhs.currentKeyWord_; + display_ = rhs.display_; + intValue_ = rhs.intValue_; + doubleValue_ = rhs.doubleValue_; + stringValue_ = rhs.stringValue_; + whereUsed_ = rhs.whereUsed_; + fakeKeyWord_ = rhs.fakeKeyWord_; + fakeValue_ = rhs.fakeValue_; + } + return *this; +} +void CbcParam::gutsOfConstructor() { + std::string::size_type shriekPos = name_.find('!'); + lengthName_ = static_cast(name_.length()); + if (shriekPos == std::string::npos) { + // does not contain '!' + lengthMatch_ = lengthName_; + } else { + lengthMatch_ = static_cast(shriekPos); + name_ = name_.substr(0, shriekPos) + name_.substr(shriekPos + 1); + lengthName_--; + } +} + +// Insert string (only valid for keywords) +void CbcParam::append(std::string keyWord) { + definedKeyWords_.push_back(keyWord); +} + +double CbcParam::doubleParameter(OsiSolverInterface *model) const { + double value = 0.0; + bool getDblParamRetValue; + switch (type_) { + case CLP_PARAM_DBL_DUALTOLERANCE: + getDblParamRetValue = model->getDblParam(OsiDualTolerance, value); + assert(getDblParamRetValue); + break; + case CLP_PARAM_DBL_PRIMALTOLERANCE: + getDblParamRetValue = model->getDblParam(OsiPrimalTolerance, value); + assert(getDblParamRetValue); + break; + default: + return doubleValue_; + break; + } + return value; +} +double CbcParam::doubleParameter(CbcModel &model) const { + double value; + switch (type_) { + case CBC_PARAM_DBL_INFEASIBILITYWEIGHT: + value = model.getDblParam(CbcModel::CbcInfeasibilityWeight); + break; + case CBC_PARAM_DBL_INTEGERTOLERANCE: + value = model.getDblParam(CbcModel::CbcIntegerTolerance); + break; + case CBC_PARAM_DBL_INCREMENT: + value = model.getDblParam(CbcModel::CbcCutoffIncrement); + break; + case CBC_PARAM_DBL_ALLOWABLEGAP: + value = model.getDblParam(CbcModel::CbcAllowableGap); + break; + case CBC_PARAM_DBL_GAPRATIO: + value = model.getDblParam(CbcModel::CbcAllowableFractionGap); + break; + case CBC_PARAM_DBL_CUTOFF: + value = model.getCutoff(); + break; + case CBC_PARAM_DBL_TIMELIMIT_BAB: + value = model.getDblParam(CbcModel::CbcMaximumSeconds); + break; + case CBC_PARAM_DBL_MAXSECONDSNIFS: + value = model.getDblParam(CbcModel::CbcMaxSecondsNotImproving); + break; + + case CLP_PARAM_DBL_DUALTOLERANCE: + case CLP_PARAM_DBL_PRIMALTOLERANCE: + value = doubleParameter(model.solver()); + break; + default: + value = doubleValue_; + break; + } + return value; +} +int CbcParam::setDoubleParameter(OsiSolverInterface *model, double value, + bool doPrinting) { + int returnCode; + std::string message = + setDoubleParameterWithMessage(model, value, returnCode); + if (doPrinting){ + std::cout << message << std::endl; + } + return returnCode; +} +int CbcParam::setDoubleParameter(CbcModel &model, double value, + bool doPrinting) { + int returnCode = 0; + std::string message = + setDoubleParameterWithMessage(model, value, returnCode); + if (doPrinting){ + std::cout << message << std::endl; + } + return returnCode; +} +// Sets double parameter and returns printable string and error code +std::string CbcParam::setDoubleParameterWithMessage(OsiSolverInterface *model, + double value, + int &returnCode) { + std::ostringstream buffer; + if (value < lowerDoubleValue_ || value > upperDoubleValue_) { + buffer << value << " was provided for " << name_; + buffer << " - valid range is " << lowerDoubleValue_; + buffer << " to " << upperDoubleValue_ << std::endl; + returnCode = 1; + } else { + double oldValue = doubleValue_; + buffer << name_ << " was changed from "; + buffer << oldValue << " to " << value << std::endl; + returnCode = 0; + doubleValue_ = value; + switch (type_) { + case CLP_PARAM_DBL_DUALTOLERANCE: + model->getDblParam(OsiDualTolerance, oldValue); + model->setDblParam(OsiDualTolerance, value); + break; + case CLP_PARAM_DBL_PRIMALTOLERANCE: + model->getDblParam(OsiPrimalTolerance, oldValue); + model->setDblParam(OsiPrimalTolerance, value); + break; + default: + break; + } + } + return buffer.str(); +} +// TODO: This function doesn't set all the possible parameters. Does this +// matter? +// Sets double parameter and returns printable string and error code +std::string CbcParam::setDoubleParameterWithMessage(CbcModel &model, + double value, + int &returnCode) { + std::ostringstream buffer; + if (value < lowerDoubleValue_ || value > upperDoubleValue_) { + buffer << value << " was provided for " << name_; + buffer << " - valid range is " << lowerDoubleValue_; + buffer << " to " << upperDoubleValue_ << std::endl; + returnCode = 1; + } else { + double oldValue = doubleValue_; + buffer << name_ << " was changed from "; + buffer << oldValue << " to " << value << std::endl; + returnCode = 0; + doubleValue_ = value; + switch (type_) { + case CBC_PARAM_DBL_INFEASIBILITYWEIGHT: + oldValue = model.getDblParam(CbcModel::CbcInfeasibilityWeight); + model.setDblParam(CbcModel::CbcInfeasibilityWeight, value); + break; + case CBC_PARAM_DBL_INTEGERTOLERANCE: + oldValue = model.getDblParam(CbcModel::CbcIntegerTolerance); + model.setDblParam(CbcModel::CbcIntegerTolerance, value); + break; + case CBC_PARAM_DBL_INCREMENT: + oldValue = model.getDblParam(CbcModel::CbcCutoffIncrement); + model.setDblParam(CbcModel::CbcCutoffIncrement, value); + case CBC_PARAM_DBL_ALLOWABLEGAP: + oldValue = model.getDblParam(CbcModel::CbcAllowableGap); + model.setDblParam(CbcModel::CbcAllowableGap, value); + break; + case CBC_PARAM_DBL_GAPRATIO: + oldValue = model.getDblParam(CbcModel::CbcAllowableFractionGap); + model.setDblParam(CbcModel::CbcAllowableFractionGap, value); + break; + case CBC_PARAM_DBL_CUTOFF: + oldValue = model.getCutoff(); + model.setCutoff(value); + break; + case CBC_PARAM_DBL_TIMELIMIT_BAB: + oldValue = model.getDblParam(CbcModel::CbcMaximumSeconds); + model.setDblParam(CbcModel::CbcMaximumSeconds, value); + break; + case CBC_PARAM_DBL_MAXSECONDSNIFS: + oldValue = model.getDblParam(CbcModel::CbcMaxSecondsNotImproving); + model.setDblParam(CbcModel::CbcMaxSecondsNotImproving, value); + break; + case CLP_PARAM_DBL_DUALTOLERANCE: + case CLP_PARAM_DBL_PRIMALTOLERANCE: + setDoubleParameter(model.solver(), value); + return 0; // to avoid message + default: + break; + } + } + return buffer.str(); +} +void CbcParam::setDoubleValue(double value) { + if (value < lowerDoubleValue_ || value > upperDoubleValue_) { + std::cout << value << " was provided for " << name_ << " - valid range is " + << lowerDoubleValue_ << " to " << upperDoubleValue_ << std::endl; + } else { + doubleValue_ = value; + } +} +std::string CbcParam::setDoubleValueWithMessage(double value) { + std::ostringstream buffer; + if (value < lowerDoubleValue_ || value > upperDoubleValue_) { + buffer << value << " was provided for " << name_; + buffer << " - valid range is " << lowerDoubleValue_; + buffer << " to " << upperDoubleValue_ << std::endl; + } else { + double oldValue = doubleValue_; + buffer << name_ << " was changed from "; + buffer << oldValue << " to " << value << std::endl; + doubleValue_ = value; + } + return buffer.str(); +} +int CbcParam::checkDoubleParameter(double value) const { + if (value < lowerDoubleValue_ || value > upperDoubleValue_) { + std::cout << value << " was provided for " << name_ << " - valid range is " + << lowerDoubleValue_ << " to " << upperDoubleValue_ << std::endl; + return 1; + } else { + return 0; + } +} +int CbcParam::intParameter(OsiSolverInterface *model) const { + int value = 0; + switch (type_) { + case CBC_PARAM_INT_LPLOGLEVEL: + // value=model->logLevel(); + break; + default: + abort(); + } + return value; +} +int CbcParam::intParameter(CbcModel &model) const { + int value; + switch (type_) { + case CBC_PARAM_INT_SOLVERLOGLEVEL: + value = model.messageHandler()->logLevel(); + break; + case CBC_PARAM_INT_LPLOGLEVEL: + value = model.solver()->messageHandler()->logLevel(); + break; + case CBC_PARAM_INT_MAXNODES: + value = model.getIntParam(CbcModel::CbcMaxNumNode); + break; + case CBC_PARAM_INT_MAXNODESNOTIMPROVINGFS: + value = model.getIntParam(CbcModel::CbcMaxNodesNotImproving); + break; + case CBC_PARAM_INT_MAXSOLS: + value = model.getIntParam(CbcModel::CbcMaxNumSol); + break; + case CBC_PARAM_INT_MAXSAVEDSOLS: + value = model.maximumSavedSolutions(); + break; + case CBC_PARAM_INT_STRONGBRANCHING: + value = model.numberStrong(); + break; + case CBC_PARAM_INT_NUMBERBEFORE: + value = model.numberBeforeTrust(); + break; + case CBC_PARAM_INT_NUMBERANALYZE: + value = model.numberAnalyzeIterations(); + break; + case CBC_PARAM_INT_CUTPASSINTREE: + value = model.getMaximumCutPasses(); + break; + case CBC_PARAM_INT_CUTPASS: + value = model.getMaximumCutPassesAtRoot(); + break; +#ifdef COIN_HAS_CBC +#ifdef CBC_THREAD + case CBC_PARAM_INT_THREADS: + value = model.getNumberThreads(); + break; +#endif + case CBC_PARAM_INT_RANDOMSEED: + value = model.getRandomSeed(); + break; +#endif + default: + value = intValue_; + break; + } + return value; +} +int CbcParam::setIntParameter(OsiSolverInterface *model, int value, + bool doPrinting) { + int returnCode; + std::string message = + setIntParameterWithMessage(model, value, returnCode); + if (doPrinting){ + std::cout << message << std::endl; + } + return returnCode; +} +int CbcParam::setIntParameter(CbcModel &model, int value, + bool doPrinting) { + int returnCode; + std::string message = + setIntParameterWithMessage(model, value, returnCode); + if (doPrinting){ + std::cout << message << std::endl; + } + return returnCode; +} +// Sets int parameter and returns printable string and error code +std::string CbcParam::setIntParameterWithMessage(OsiSolverInterface *model, + int value, int &returnCode) { + std::ostringstream buffer; + if (value < lowerIntValue_ || value > upperIntValue_) { + buffer << value << " was provided for " << name_; + buffer << " - valid range is " << lowerIntValue_ << " to "; + buffer << upperIntValue_ << std::endl; + returnCode = 1; + } else { + int oldValue = intValue_; + buffer << name_ << " was changed from " << oldValue; + buffer << " to " << value << std::endl; + returnCode = 0; + intValue_ = value; + switch (type_) { + case CBC_PARAM_INT_LPLOGLEVEL: + model->messageHandler()->setLogLevel(value); + break; + default: + break; + } + } + return buffer.str(); +} +// Sets int parameter and returns printable string and error code +std::string CbcParam::setIntParameterWithMessage(CbcModel &model, int value, + int &returnCode) { + std::ostringstream buffer; + if (value < lowerIntValue_ || value > upperIntValue_) { + buffer << value << " was provided for " << name_; + buffer << " - valid range is " << lowerIntValue_ << " to "; + buffer << upperIntValue_ << std::endl; + returnCode = 1; + } else { + int oldValue = intValue_; + buffer << name_ << " was changed from " << oldValue; + buffer << " to " << value << std::endl; + returnCode = 0; + intValue_ = value; + switch (type_) { + case CBC_PARAM_INT_SOLVERLOGLEVEL: + oldValue = model.messageHandler()->logLevel(); + model.messageHandler()->setLogLevel(CoinAbs(value)); + break; + case CBC_PARAM_INT_LPLOGLEVEL: + oldValue = model.solver()->messageHandler()->logLevel(); + model.solver()->messageHandler()->setLogLevel(value); + break; + case CBC_PARAM_INT_MAXNODES: + oldValue = model.getIntParam(CbcModel::CbcMaxNumNode); + model.setIntParam(CbcModel::CbcMaxNumNode, value); + break; + case CBC_PARAM_INT_MAXNODESNOTIMPROVINGFS: + oldValue = model.getIntParam(CbcModel::CbcMaxNodesNotImproving); + model.setIntParam(CbcModel::CbcMaxNodesNotImproving, value); + break; + + case CBC_PARAM_INT_MAXSOLS: + oldValue = model.getIntParam(CbcModel::CbcMaxNumSol); + model.setIntParam(CbcModel::CbcMaxNumSol, value); + break; + case CBC_PARAM_INT_MAXSAVEDSOLS: + oldValue = model.maximumSavedSolutions(); + model.setMaximumSavedSolutions(value); + break; + case CBC_PARAM_INT_STRONGBRANCHING: + oldValue = model.numberStrong(); + model.setNumberStrong(value); + break; + case CBC_PARAM_INT_NUMBERBEFORE: + oldValue = model.numberBeforeTrust(); + model.setNumberBeforeTrust(value); + break; + case CBC_PARAM_INT_NUMBERANALYZE: + oldValue = model.numberAnalyzeIterations(); + model.setNumberAnalyzeIterations(value); + break; + case CBC_PARAM_INT_CUTPASSINTREE: + oldValue = model.getMaximumCutPasses(); + model.setMaximumCutPasses(value); + break; + case CBC_PARAM_INT_CUTPASS: + oldValue = model.getMaximumCutPassesAtRoot(); + model.setMaximumCutPassesAtRoot(value); + break; +#ifdef COIN_HAS_CBC +#ifdef CBC_THREAD + case CBC_PARAM_INT_THREADS: + oldValue = model.getNumberThreads(); + model.setNumberThreads(value); + break; +#endif + case CBC_PARAM_INT_RANDOMSEED: + oldValue = model.getRandomSeed(); + model.setRandomSeed(value); + break; +#endif + default: + break; + } + } + return buffer.str(); +} +void CbcParam::setIntValue(int value) { + if (value < lowerIntValue_ || value > upperIntValue_) { + std::cout << value << " was provided for " << name_ << " - valid range is " + << lowerIntValue_ << " to " << upperIntValue_ << std::endl; + } else { + intValue_ = value; + } +} +std::string CbcParam::setIntValueWithMessage(int value) { + std::ostringstream buffer; + if (value < lowerIntValue_ || value > upperIntValue_) { + buffer << value << " was provided for " << name_; + buffer << " - valid range is " << lowerIntValue_ << " to "; + buffer << upperIntValue_ << std::endl; + } else { + int oldValue = intValue_; + buffer << name_ << " was changed from " << oldValue; + buffer << " to " << value << std::endl; + intValue_ = value; + } + return buffer.str(); +} +void CbcParam::setStringValue(std::string value) { stringValue_ = value; } + +// Returns name which could match +std::string CbcParam::matchName() const { + if (lengthMatch_ == lengthName_) + return name_; + else + return name_.substr(0, lengthMatch_) + "(" + name_.substr(lengthMatch_) + + ")"; +} + +// Returns length of name for printing +int CbcParam::lengthMatchName() const { + if (lengthName_ == lengthMatch_) + return lengthName_; + else + return lengthName_ + 2; +} + +int CbcParam::matches(std::string input) const { + // look up strings to do more elegantly + if (input.length() > lengthName_) { + return 0; + } else { + unsigned int i; + for (i = 0; i < input.length(); i++) { + if (tolower(name_[i]) != tolower(input[i])) + break; + } + if (i < input.length()) { + return 0; + } else if (i >= lengthMatch_) { + return 1; + } else { + // matched but too short + return 2; + } + } +} + +// Returns parameter option which matches (-1 if none) +int CbcParam::parameterOption(std::string check) const { + int numberItems = static_cast(definedKeyWords_.size()); + if (!numberItems) { + return -1; + } else { + int whichItem = 0; + unsigned int it; + for (it = 0; it < definedKeyWords_.size(); it++) { + std::string thisOne = definedKeyWords_[it]; + std::string::size_type shriekPos = thisOne.find('!'); + size_t length1 = thisOne.length(); + size_t length2 = length1; + if (shriekPos != std::string::npos) { + // contains '!' + length2 = shriekPos; + thisOne = thisOne.substr(0, shriekPos) + thisOne.substr(shriekPos + 1); + length1 = thisOne.length(); + } + if (check.length() <= length1 && length2 <= check.length()) { + unsigned int i; + for (i = 0; i < check.length(); i++) { + if (tolower(thisOne[i]) != tolower(check[i])) + break; + } + if (i < check.length()) { + whichItem++; + } else if (i >= length2) { + break; + } + } else { + whichItem++; + } + } + if (whichItem < numberItems) { + return whichItem; + } else { + if (fakeKeyWord_ <= 0) + return -1; + // allow plus or minus + int n; + if (check.substr(0, 4) == "plus" || check.substr(0, 4) == "PLUS") { + n = 4; + } else if (check.substr(0, 5) == "minus" || + check.substr(0, 5) == "MINUS") { + n = 5; + } else { + return -1; + } + int value = 0; + std::string field = check.substr(n); + if (field != "EOL") { + const char *start = field.c_str(); + char *endPointer = NULL; + // check valid + value = static_cast(strtol(start, &endPointer, 10)); + if (*endPointer != '\0') { + return -1; + } + if (n == 4) + return value + 1000; + else + return -value - 1000; + } else { + return -1; + } + } + } +} +// Prints parameter options +void CbcParam::printOptions() const { + std::cout << "= 0 && + currentKeyWord_ < static_cast(definedKeyWords_.size())); + std::string current = definedKeyWords_[currentKeyWord_]; + std::string::size_type shriekPos = current.find('!'); + if (shriekPos != std::string::npos) { + // contains '!' + current = current.substr(0, shriekPos) + "(" + + current.substr(shriekPos + 1) + ")"; + } + std::cout << ";\n\tcurrent " << current << ">" << std::endl; +} + +// Sets current parameter option using string +void CbcParam::setCurrentOption(const std::string value) { + int action = parameterOption(value); + if (action >= 0) + currentKeyWord_ = action; +#if FLUSH_PRINT_BUFFER > 2 + if (name_ == "bufferedMode") + coinFlushBufferFlag = action; +#endif +} +// Sets current parameter option +void CbcParam::setCurrentOption(int value, bool printIt) { + if (printIt && value != currentKeyWord_) + std::cout << "Option for " << name_ << " changed from " + << definedKeyWords_[currentKeyWord_] << " to " + << definedKeyWords_[value] << std::endl; + +#if FLUSH_PRINT_BUFFER > 2 + if (name_ == "bufferedMode") + coinFlushBufferFlag = value; +#endif + currentKeyWord_ = value; +} +// Sets current parameter option and returns printable string +std::string CbcParam::setCurrentOptionWithMessage(int value) { + std::ostringstream buffer; + if (value != currentKeyWord_) { + buffer << "Option for " << name_ << " changed from "; + char current[100]; + char newString[100]; + if (currentKeyWord_ >= 0 && (fakeKeyWord_ <= 0 || + currentKeyWord_ < fakeKeyWord_)){ + buffer << definedKeyWords_[currentKeyWord_]; + }else if (currentKeyWord_ < 0){ + buffer << "minus" << -currentKeyWord_ - 1000; + }else{ + buffer << "plus" << currentKeyWord_ - 1000; + } + buffer << " to "; + if (value >= 0 && (fakeKeyWord_ <= 0 || value < fakeKeyWord_)){ + buffer << definedKeyWords_[value]; + }else if (value < 0){ + buffer << "minus" << -value - 1000; + }else{ + buffer << "plus" << value - 1000; + } + +#if FLUSH_PRINT_BUFFER > 2 + if (name_ == "bufferedMode") + coinFlushBufferFlag = value; +#endif + currentKeyWord_ = value; + } + return buffer.str(); +} +// Sets current parameter option using string with message +std::string CbcParam::setCurrentOptionWithMessage(const std::string value) { + std::ostringstream buffer; + int action = parameterOption(value); + char current[100]; + if (action >= 0) { +#if FLUSH_PRINT_BUFFER > 2 + if (name_ == "bufferedMode") + coinFlushBufferFlag = action; +#endif + buffer << "Option for " << name_ << " changed from "; + if (currentKeyWord_ >= 0 && (fakeKeyWord_ <= 0 || + currentKeyWord_ < fakeKeyWord_)){ + buffer << definedKeyWords_[currentKeyWord_]; + }else if (currentKeyWord_ < 0){ + buffer << "minus" << -currentKeyWord_ - 1000; + }else{ + buffer << "plus" << currentKeyWord_ - 1000; + } + buffer << " to " << value; + currentKeyWord_ = action; + } else { + buffer << "Option for " << name_ << " given illegal value " << value; + } + return buffer.str(); +} +/* Returns current parameter option position + but if fake keyword returns fakeValue_ +*/ +int CbcParam::currentOptionAsInteger() const { + int fakeInteger; + return currentOptionAsInteger(fakeInteger); +} +/* Returns current parameter option position + but if fake keyword returns fakeValue_ and sets + fakeInteger to value +*/ +int CbcParam::currentOptionAsInteger(int &fakeInteger) const { + fakeInteger = -COIN_INT_MAX; + if (fakeKeyWord_ < 0) { + return currentKeyWord_; + } else if (currentKeyWord_ >= 0 && currentKeyWord_ < fakeKeyWord_) { + return currentKeyWord_; + } else { + // fake + if (currentKeyWord_ < 0) + fakeInteger = currentKeyWord_ + 1000; + else + fakeInteger = currentKeyWord_ - 1000; + return fakeValue_; + } +} + +// TODO: Fix this +// Print Long help +void CbcParam::printLongHelp() const { + if (type_ >= 1 && type_ < 600) { + CoinPrintString(longHelp_); + if (type_ < CLP_PARAM_INT_LOGLEVEL) { + printf("\n", + lowerDoubleValue_, upperDoubleValue_, doubleValue_); + assert(upperDoubleValue_ > lowerDoubleValue_); + } else if (type_ < CLP_PARAM_STR_DIRECTION) { + printf("\n", lowerIntValue_, + upperIntValue_, intValue_); + assert(upperIntValue_ > lowerIntValue_); + } else if (type_ < CLP_PARAM_ACTION_DIRECTORY) { + printOptions(); + } + } +} + +void CbcParam::printString() const { + if (name_ == "directory") + std::cout << "Current working directory is " << stringValue_ << std::endl; + else if (name_.substr(0, 6) == "printM") + std::cout << "Current value of printMask is " << stringValue_ << std::endl; + else + std::cout << "Current default (if $ as parameter) for " << name_ << " is " + << stringValue_ << std::endl; +} + +// Sets value of fake keyword to current size of keywords +void CbcParam::setFakeKeyWord(int fakeValue) { + fakeKeyWord_ = static_cast(definedKeyWords_.size()); + assert(fakeKeyWord_ > 0); + fakeValue_ = fakeValue; + assert(fakeValue_ >= 0); +} + +//########################################################################### +//########################################################################### + +/* + Subroutine to establish the cbc parameter array. See the description of + class CbcParam for details. +*/ +void establishCbcParams(std::vector ¶meters) { + parameters.clear(); + parameters.push_back(CbcParam("?", "For help", CBC_PARAM_GENERALQUERY, 7, 0)); + parameters.push_back( + CbcParam("???", "For help", CBC_PARAM_FULLGENERALQUERY, 7, 0)); + parameters.push_back( + CbcParam("-", "From stdin", CBC_PARAM_ACTION_STDIN, 3, 0)); + +// some help strings that repeat for many options +#define CUTS_LONGHELP \ + "Value 'on' enables the cut generator and CBC will try it in the branch " \ + "and cut tree (see cutDepth on how to fine tune the behavior). " \ + "Value 'root' lets CBC run the cut generator generate only at the root " \ + "node. " \ + "Value 'ifmove' lets CBC use the cut generator in the tree if it looks as " \ + "if it is doing some good and moves the objective value. " \ + "Value 'forceon' turns on the cut generator and forces CBC to use it at " \ + "every node." +#define HEURISTICS_LONGHELP \ + "Value 'on' means to use the heuristic in each node of the tree, i.e. " \ + "after preprocessing. " \ + "Value 'before' means use the heuristic only if option doHeuristics is " \ + "used. " \ + "Value 'both' means to use the heuristic if option doHeuristics is used " \ + "and during solve." + + { + CbcParam p("allC!ommands", "Whether to print less used commands", "no", + CBC_PARAM_STR_ALLCOMMANDS); + + p.append("more"); + p.append("all"); + p.setLonghelp( + "For the sake of your sanity, only the more useful and simple commands \ +are printed out on ?."); + parameters.push_back(p); + } + { + CbcParam p("allow!ableGap", "Stop when gap between best possible and \ +best less than this", + 0.0, COIN_DBL_MAX, CBC_PARAM_DBL_ALLOWABLEGAP); + p.setDoubleValue(1e-10); + p.setLonghelp( + "If the gap between best known solution and the best possible solution is less than this \ +value, then the search will be terminated. Also see ratioGap."); + parameters.push_back(p); + } + { + CbcParam p("artif!icialCost", + "Costs >= this treated as artificials in feasibility pump", 0.0, + COIN_DBL_MAX, CBC_PARAM_DBL_ARTIFICIALCOST, 1); + p.setDoubleValue(0.0); + p.setLonghelp("A value of 0.0 means off. Otherwise, variables with costs " + ">= this are treated as artificial variables and fixed to " + "lower bound in feasibility pump."); + parameters.push_back(p); + } + { + CbcParam p("branch!AndCut", "Do Branch and Cut", CBC_PARAM_ACTION_BAB); + p.setLonghelp( + "This does branch and cut. There are many parameters which can affect the performance. \ +First just try with default settings and look carefully at the log file. Did cuts help? Did they take too long? \ +Look at output to see which cuts were effective and then do some tuning. You will see that the \ +options for cuts are off, on, root and ifmove, forceon. Off is \ +obvious. " CUTS_LONGHELP + " For probing, forceonbut just does fixing probing in tree - not strengthening etc. \ +If pre-processing reduced the size of the \ +problem or strengthened many coefficients then it is probably wise to leave it on. Switch off heuristics \ +which did not provide solutions. The other major area to look at is the search. Hopefully good solutions \ +were obtained fairly early in the search so the important point is to select the best variable to branch on. \ +See whether strong branching did a good job - or did it just take a lot of iterations. Adjust the strongBranching \ +and trustPseudoCosts parameters. If cuts did a good job, then you may wish to \ +have more rounds of cuts - see passC!uts and passT!ree."); + parameters.push_back(p); + } + { + CbcParam p("combine!Solutions", "Whether to use combine solution heuristic", + "off", CBC_PARAM_STR_COMBINE); + + p.append("on"); + p.append("both"); + p.append("before"); + p.append("onquick"); + p.append("bothquick"); + p.append("beforequick"); + p.setLonghelp("This heuristic does branch and cut on given problem by just \ +using variables which have appeared in one or more solutions. \ +It is obviously only tried after two or more solutions have been found. " HEURISTICS_LONGHELP); + + parameters.push_back(p); + } + { + CbcParam p("combine2!Solutions", + "Whether to use crossover solution heuristic", "off", + CBC_PARAM_STR_CROSSOVER2); + p.append("on"); + p.append("both"); + p.append("before"); + p.setLonghelp("This heuristic does branch and cut on the problem given by \ +fixing variables which have the same value in two or more solutions. \ +It obviously only tries after two or more solutions. " HEURISTICS_LONGHELP); + parameters.push_back(p); + } + { + CbcParam p("constraint!fromCutoff", "Whether to use cutoff as constraint", + "off", CBC_PARAM_STR_CUTOFF_CONSTRAINT); + + p.append("on"); + p.append("variable"); + p.append("forcevariable"); + p.append("conflict"); + p.setLonghelp( + "For some problems, cut generators and general branching work better " + "if the problem would be infeasible if the cost is too high. " + "If this option is enabled, the objective function is added as a " + "constraint which right hand side is set to the current cutoff value " + "(objective value of best known solution)"); + parameters.push_back(p); + } + { + CbcParam p("cost!Strategy", "How to use costs for branching priorities", + "off", CBC_PARAM_STR_BRANCHPRIORITY); + + p.append("pri!orities"); + p.append("column!Order?"); + p.append("01f!irst?"); + p.append("01l!ast?"); + p.append("length!?"); + p.append("singletons"); + p.append("nonzero"); + p.append("general!Force?"); + p.setLonghelp( + "Value 'priorities' assigns highest priority to variables with largest " + "absolute cost. This primitive strategy can be surprisingly effective. " + "Value 'columnorder' assigns the priorities 1, 2, 3, ... with respect " + "to the column ordering. " + "Value '01first' ('01last') assignes two sets of priorities such that " + "binary variables get high (low) priority. " + "Value 'length' assigns high priority to variables that occur in many " + "equations. "); + + parameters.push_back(p); + } + { + CbcParam p("cplex!Use", "Whether to use Cplex!", "off", CBC_PARAM_STR_CPX); + p.append("on"); + p.setLonghelp( + " If the user has Cplex, but wants to use some of Cbc's heuristics \ +then you can! If this is on, then Cbc will get to the root node and then \ +hand over to Cplex. If heuristics find a solution this can be significantly \ +quicker. You will probably want to switch off Cbc's cuts as Cplex thinks \ +they are genuine constraints. It is also probable that you want to switch \ +off preprocessing, although for difficult problems it is worth trying \ +both."); + parameters.push_back(p); + } + { + CbcParam p("csv!Statistics", "Create one line of statistics", + CBC_PARAM_ACTION_CSVSTATISTICS, 2, 1); + p.setLonghelp( + "This appends statistics to given file name. It will use the default\ + directory given by 'directory'. A name of '$' will use the previous value for the name. This\ + is initialized to '', i.e. it must be set. Adds header if file empty or does not exist."); + parameters.push_back(p); + } + { + CbcParam p("cutD!epth", "Depth in tree at which to do cuts", -1, + COIN_INT_MAX, CBC_PARAM_INT_CUTDEPTH); + p.setLonghelp( + "Cut generators may be off, on, on only at the root node, or on if they look useful. \ + Setting this option to a positive value K let CBC call a cutgenerator on a node whenever the depth in the tree is a multiple of K. \ + The default of -1 lets CBC decide."); + p.setIntValue(-1); + parameters.push_back(p); + } + { + CbcParam p("cutL!ength", "Length of a cut", -1, COIN_INT_MAX, + CBC_PARAM_INT_CUTLENGTH); + p.setLonghelp( + "At present this only applies to Gomory cuts. -1 (default) leaves as is. \ +Any value >0 says that all cuts <= this length can be generated both at \ +root node and in tree. 0 says to use some dynamic lengths. If value >=10,000,000 \ +then the length in tree is value%10000000 - so 10000100 means unlimited length \ +at root and 100 in tree."); + p.setIntValue(-1); + parameters.push_back(p); + } + { + CbcParam p("cuto!ff", "Bound on the objective value for all solutions", + -COIN_DBL_MAX, COIN_DBL_MAX, CBC_PARAM_DBL_CUTOFF); + p.setDoubleValue(1.0e50); + p.setLonghelp( + "All solutions must have a better objective value (in a minimization sense) than the value of this option. \ +CBC also updates this value whenever it obtains a solution to the value of \ +the objective function of the solution minus the cutoff increment."); + parameters.push_back(p); + } + { + CbcParam p("cuts!OnOff", "Switches all cut generators on or off", "off", + CBC_PARAM_STR_CUTSSTRATEGY); + p.append("on"); + p.append("root"); + p.append("ifmove"); + p.append("forceOn"); + p.setLonghelp( + "This can be used to switch on or off all cut generators (apart from " + "Reduce and Split). " + "Then one can turn individual ones off or on. " CUTS_LONGHELP); + parameters.push_back(p); + } + { + CbcParam p("debug!In", "read valid solution from file", + CBC_PARAM_ACTION_DEBUG, 7, 1); + + p.setLonghelp( + "This will read a solution file from the given file name. It will use the default\ + directory given by 'directory'. A name of '$' will use the previous value for the name. This\ + is initialized to '', i.e. it must be set.\n\n\ +If set to create it will create a file called debug.file after search.\n\n\ +The idea is that if you suspect a bad cut generator \ +you can do a good run with debug set to 'create' and then switch on the cuts you suspect and \ +re-run with debug set to 'debug.file' The create case has same effect as saveSolution."); + parameters.push_back(p); + } + { + CbcParam p("depth!MiniBab", "Depth at which to try mini branch-and-bound", + -COIN_INT_MAX, COIN_INT_MAX, CBC_PARAM_INT_DEPTHMINIBAB); + + p.setIntValue(-1); + p.setLonghelp( + "Rather a complicated parameter but can be useful. -1 means off for large problems but on as if -12 for problems where rows+columns<500, -2 \ +means use Cplex if it is linked in. Otherwise if negative then go into depth first complete search fast branch and bound when depth>= -value-2 \ +(so -3 will use this at depth>=1). This mode is only switched on after 500 nodes. If you really want to switch it off for small problems then set \ +this to -999. If >=0 the value doesn't matter very much. The code will do approximately 100 nodes of fast branch and bound every now and then at depth>=5. \ +The actual logic is too twisted to describe here."); + parameters.push_back(p); + } + { + CbcParam p("dextra3", "Extra double parameter 3", -COIN_DBL_MAX, + COIN_DBL_MAX, CBC_PARAM_DBL_DEXTRA3, 0); + p.setDoubleValue(0.0); + parameters.push_back(p); + } + { + CbcParam p("dextra4", "Extra double parameter 4", -COIN_DBL_MAX, + COIN_DBL_MAX, CBC_PARAM_DBL_DEXTRA4, 0); + p.setDoubleValue(0.0); + parameters.push_back(p); + } + { + CbcParam p("dextra4", "Extra double parameter 5", -COIN_DBL_MAX, + COIN_DBL_MAX, CBC_PARAM_DBL_DEXTRA5, 0); + p.setDoubleValue(0.0); + parameters.push_back(p); + } + { + CbcParam p("Dins", "Whether to try Distance Induced Neighborhood Search", + "off", CBC_PARAM_STR_DINS); + + p.append("on"); + p.append("both"); + p.append("before"); + p.append("often"); + p.setLonghelp(HEURISTICS_LONGHELP); + parameters.push_back(p); + } + { + CbcParam p("direction", "Minimize or Maximize", "min!imize", + CBC_PARAM_STR_DIRECTION); + p.append("max!imize"); + p.append("zero"); + p.setLonghelp( + "The default is minimize - use 'direction maximize' for maximization.\n\ +You can also use the parameters 'maximize' or 'minimize'."); + parameters.push_back(p); + } + { + CbcParam p("directory", "Set Default directory for import etc.", + CBC_PARAM_ACTION_DIRECTORY); + p.setLonghelp( + "This sets the directory which import, export, saveModel, restoreModel etc will use.\ + It is initialized to './'"); + parameters.push_back(p); + } + { + CbcParam p("dirSample", + "Set directory where the COIN-OR sample problems are.", + CBC_PARAM_ACTION_DIRSAMPLE, 7, 1); + + p.setLonghelp( + "This sets the directory where the COIN-OR sample problems reside. It is\ + used only when -unitTest is passed to cbc. cbc will pick up the test problems\ + from this directory.\ + It is initialized to '../../Data/Sample'"); + parameters.push_back(p); + } + { + CbcParam p("dirNetlib", "Set directory where the netlib problems are.", + CBC_PARAM_ACTION_DIRNETLIB, 7, 1); + + p.setLonghelp( + "This sets the directory where the netlib problems reside. One can get\ + the netlib problems from COIN-OR or from the main netlib site. This\ + parameter is used only when -netlib is passed to cbc. cbc will pick up the\ + netlib problems from this directory. If clp is built without zlib support\ + then the problems must be uncompressed.\ + It is initialized to '../../Data/Netlib'"); + parameters.push_back(p); + } + { + CbcParam p("dirMiplib", "Set directory where the miplib 2003 problems are.", + CBC_PARAM_ACTION_DIRMIPLIB, 7, 1); + + p.setLonghelp( + "This sets the directory where the miplib 2003 problems reside. One can\ + get the miplib problems from COIN-OR or from the main miplib site. This\ + parameter is used only when -miplib is passed to cbc. cbc will pick up the\ + miplib problems from this directory. If cbc is built without zlib support\ + then the problems must be uncompressed.\ + It is initialized to '../../Data/miplib3'"); + parameters.push_back(p); + } + { + CbcParam p("diveO!pt", "Diving options", -1, 200000, CBC_PARAM_INT_DIVEOPT, + 1); + p.setLonghelp("If >2 && <20 then modify diving options - \ + \n\t3 only at root and if no solution, \ + \n\t4 only at root and if this heuristic has not got solution, \ + \n\t5 decay only if no solution, \ + \n\t6 if depth <3 or decay, \ + \n\t7 run up to 2 times if solution found 4 otherwise, \ + \n\t>10 All only at root (DivingC normal as value-10), \ + \n\t>20 All with value-20)."); + p.setIntValue(-1); + parameters.push_back(p); + } + { + CbcParam p("diveS!olves", "Diving solve option", -1, 200000, + CBC_PARAM_INT_DIVEOPTSOLVES, 1); + + p.setLonghelp( + "If >0 then do up to this many solves. However, the last digit is ignored \ +and used for extra options: \ + 1-3 enables fixing of satisfied integer variables (but not at bound), \ + where 1 switches this off for that dive if the dive goes infeasible, \ + and 2 switches it off permanently if the dive goes infeasible."); + p.setIntValue(100); + parameters.push_back(p); + } + { + CbcParam p("DivingS!ome", "Whether to try Diving heuristics", "off", + CBC_PARAM_STR_DIVINGS); + + p.append("on"); + p.append("both"); + p.append("before"); + p.setLonghelp( + "This switches on a random diving heuristic at various times. \ +One may prefer to individually turn diving heuristics on or off. " HEURISTICS_LONGHELP); + // C - Coefficient, F - Fractional, G - Guided, L - LineSearch, P - + // PseudoCost, V - VectorLength. + parameters.push_back(p); + } + { + CbcParam p("DivingC!oefficient", + "Whether to try Coefficient diving heuristic", "off", + CBC_PARAM_STR_DIVINGC); + p.append("on"); + p.append("both"); + p.append("before"); + p.setLonghelp(HEURISTICS_LONGHELP); + parameters.push_back(p); + } + { + CbcParam p("DivingF!ractional", + "Whether to try Fractional diving heuristic", "off", + CBC_PARAM_STR_DIVINGF); + p.append("on"); + p.append("both"); + p.append("before"); + p.setLonghelp(HEURISTICS_LONGHELP); + parameters.push_back(p); + } + { + CbcParam p("DivingG!uided", "Whether to try Guided diving heuristic", "off", + CBC_PARAM_STR_DIVINGG); + p.append("on"); + p.append("both"); + p.append("before"); + p.setLonghelp(HEURISTICS_LONGHELP); + parameters.push_back(p); + } + { + CbcParam p("DivingL!ineSearch", + "Whether to try Linesearch diving heuristic", "off", + CBC_PARAM_STR_DIVINGL); + p.append("on"); + p.append("both"); + p.append("before"); + p.setLonghelp(HEURISTICS_LONGHELP); + parameters.push_back(p); + } + { + CbcParam p("DivingP!seudoCost", + "Whether to try Pseudocost diving heuristic", "off", + CBC_PARAM_STR_DIVINGP); + p.append("on"); + p.append("both"); + p.append("before"); + p.setLonghelp(HEURISTICS_LONGHELP); + parameters.push_back(p); + } + { + CbcParam p("DivingV!ectorLength", + "Whether to try Vectorlength diving heuristic", "off", + CBC_PARAM_STR_DIVINGV); + p.append("on"); + p.append("both"); + p.append("before"); + p.setLonghelp(HEURISTICS_LONGHELP); + parameters.push_back(p); + } + { + CbcParam p("doH!euristic", "Do heuristics before any preprocessing", + CBC_PARAM_ACTION_DOHEURISTIC, 3); + p.setLonghelp( + "Normally heuristics are done in branch and bound. It may be useful to do them outside. \ +Only those heuristics with 'both' or 'before' set will run. \ +Doing this may also set cutoff, which can help with preprocessing."); + parameters.push_back(p); + } + { + CbcParam p("dw!Heuristic", "Whether to try Dantzig Wolfe heuristic", "off", + CBC_PARAM_STR_DW); + p.append("on"); + p.append("both"); + p.append("before"); + p.setLonghelp( + "This heuristic is very very compute intensive. It tries to find a " + "Dantzig Wolfe structure and use that. " HEURISTICS_LONGHELP); + parameters.push_back(p); + } + { + CbcParam p("end", "Stops clp execution", CBC_PARAM_ACTION_EXIT); + p.setLonghelp( + "This stops execution ; end, exit, quit and stop are synonyms"); + parameters.push_back(p); + } + { + CbcParam p("environ!ment", "Read commands from environment", + CBC_PARAM_ACTION_ENVIRONMENT, 7, 0); + p.setLonghelp( + "This starts reading from environment variable CBC_CLP_ENVIRONMENT."); + parameters.push_back(p); + } + { + CbcParam p("error!sAllowed", "Whether to allow import errors", "off", + CBC_PARAM_STR_ERRORSALLOWED, 3); + + p.append("on"); + p.setLonghelp( + "The default is not to use any model which had errors when reading the mps file.\ + Setting this to 'on' will allow all errors from which the code can recover\ + simply by ignoring the error. There are some errors from which the code can not recover \ +e.g. no ENDATA. This has to be set before import i.e. -errorsAllowed on -import xxxxxx.mps."); + parameters.push_back(p); + } + { + CbcParam p("exper!iment", "Whether to use testing features", -1, 200000, + CBC_PARAM_INT_EXPERIMENT, 0); + p.setLonghelp("Defines how adventurous you want to be in using new ideas. \ +0 then no new ideas, 1 fairly sensible, 2 a bit dubious, 3 you are on your own!"); + + p.setIntValue(0); + parameters.push_back(p); + } + { + CbcParam p("expensive!Strong", "Whether to do even more strong branching", + 0, COIN_INT_MAX, CBC_PARAM_INT_STRONG_STRATEGY, 0); + + p.setLonghelp("Strategy for extra strong branching. \ +0 is normal strong branching. \ +1, 2, 4, and 6 does strong branching on all fractional variables if \ +at the root node (1), \ +at depth less than modifier (2), \ +objective equals best possible (4), or \ +at depth less than modifier and objective equals best possible (6). \ +11, 12, 14, and 16 are like 1, 2, 4, and 6, respecitively, but do strong branching on all integer (incl. non-fractional) variables. \ +Values >= 100 are used to specify a depth limit (value/100), otherwise 5 is used. \ +If the values >= 100, then above rules are applied to value%100."); + p.setIntValue(0); + parameters.push_back(p); + } + { + CbcParam p("export", "Export model as mps file", CBC_PARAM_ACTION_EXPORT); + + p.setLonghelp( + "This will write an MPS format file to the given file name. It will use the default\ + directory given by 'directory'. A name of '$' will use the previous value for the name. This\ + is initialized to 'default.mps'. \ +It can be useful to get rid of the original names and go over to using Rnnnnnnn and Cnnnnnnn. This can be done by setting 'keepnames' off before importing mps file."); + parameters.push_back(p); + } + { + CbcParam p("extra1", "Extra integer parameter 1", -COIN_INT_MAX, + COIN_INT_MAX, CBC_PARAM_INT_EXTRA1, 0); + p.setIntValue(-1); + parameters.push_back(p); + } + { + CbcParam p("extra2", "Extra integer parameter 2", -COIN_INT_MAX, + COIN_INT_MAX, CBC_PARAM_INT_EXTRA2, 0); + p.setIntValue(-1); + parameters.push_back(p); + } + { + CbcParam p("extra3", "Extra integer parameter 3", -COIN_INT_MAX, + COIN_INT_MAX, CBC_PARAM_INT_EXTRA3, 0); + p.setIntValue(-1); + parameters.push_back(p); + } + { + CbcParam p("extra4", "Extra integer parameter 4", -1, COIN_INT_MAX, + CBC_PARAM_INT_EXTRA4, 0); + + p.setIntValue(-1); + p.setLonghelp("This switches on yet more special options!! \ +The bottom digit is a strategy when to used shadow price stuff e.g. 3 \ +means use until a solution is found. The next two digits say what sort \ +of dual information to use. After that it goes back to powers of 2 so -\n\ +\n\t1000 - switches on experimental hotstart\n\ +\n\t2,4,6000 - switches on experimental methods of stopping cuts\n\ +\n\t8000 - increase minimum drop gradually\n\ +\n\t16000 - switches on alternate gomory criterion"); + parameters.push_back(p); + } + { + CbcParam p("extraV!ariables", "Allow creation of extra integer variables", + -COIN_INT_MAX, COIN_INT_MAX, CBC_PARAM_INT_EXTRA_VARIABLES, 0); + p.setIntValue(0); + p.setLonghelp( + "Switches on a trivial re-formulation that introduces extra integer " + "variables to group together variables with same cost."); + parameters.push_back(p); + } + { + CbcParam p("feas!ibilityPump", + "Whether to try the Feasibility Pump heuristic", "off", + CBC_PARAM_STR_FPUMP); + + p.append("on"); + p.append("both"); + p.append("before"); + p.setLonghelp("This heuristic is due to Fischetti, Glover, and Lodi \ +and uses a sequence of LPs to try and get an integer feasible solution. \ +Some fine tuning is available by options passFeasibilityPump and pumpTune. " HEURISTICS_LONGHELP); + parameters.push_back(p); + } + { + CbcParam p("fix!OnDj", "Try heuristic based on fixing variables with \ +reduced costs greater than this", + -COIN_DBL_MAX, COIN_DBL_MAX, CBC_PARAM_DBL_DJFIX, 1); + p.setLonghelp( + "If this is set integer variables with reduced costs greater than this will be fixed \ +before branch and bound - use with extreme caution!"); + parameters.push_back(p); + } + { + CbcParam p("flow!CoverCuts", "Whether to use Flow Cover cuts", "off", + CBC_PARAM_STR_FLOWCUTS); + p.append("on"); + p.append("root"); + p.append("ifmove"); + p.append("forceOn"); + p.append("onglobal"); + p.setFakeKeyWord(3); + p.setLonghelp(CUTS_LONGHELP " Reference: " + "https://github.com/coin-or/Cgl/wiki/" + "CglFlowCover"); // Can also enter testing + // values by plusnn (==ifmove) + parameters.push_back(p); + } + { + CbcParam p("force!Solution", + "Whether to use given solution as crash for BAB", -1, 20000000, + CBC_PARAM_INT_USESOLUTION); + p.setIntValue(-1); + p.setLonghelp( + "-1 off. If 1 then tries to branch to solution given by AMPL or priorities file. \ +If 0 then just tries to set as best solution \ +If >1 then also does that many nodes on fixed problem."); + parameters.push_back(p); + } + { + CbcParam p("fraction!forBAB", "Fraction in feasibility pump", 1.0e-5, 1.1, + CBC_PARAM_DBL_SMALLBAB, 1); + p.setDoubleValue(0.5); + p.setLonghelp( + "After a pass in the feasibility pump, variables which have not moved \ +about are fixed and if the preprocessed model is smaller than this fraction of the original problem, \ +a few nodes of branch and bound are done on the reduced problem."); + parameters.push_back(p); + } + { + CbcParam p("GMI!Cuts", "Whether to use alternative Gomory cuts", "off", + CBC_PARAM_STR_GMICUTS); + + p.append("on"); + p.append("root"); + p.append("ifmove"); + p.append("forceOn"); + p.append("endonly"); + p.append("long"); + p.append("longroot"); + p.append("longifmove"); + p.append("forceLongOn"); + p.append("longendonly"); + p.setLonghelp(CUTS_LONGHELP " This version is by Giacomo Nannicini and may " + "be more robust than gomoryCuts."); + parameters.push_back(p); + } + { + CbcParam p("gomory!Cuts", "Whether to use Gomory cuts", "off", + CBC_PARAM_STR_GOMORYCUTS); + + p.append("on"); + p.append("root"); + p.append("ifmove"); + p.append("forceOn"); + p.append("onglobal"); + p.append("forceandglobal"); + p.append("forceLongOn"); + p.append("long"); + p.append("shorter"); + p.setLonghelp( + "The original cuts - beware of imitations! Having gone out of favor, \ +they are now more fashionable as LP solvers are more robust and they interact well \ +with other cuts. They will almost always give cuts (although in this executable \ +they are limited as to number of variables in cut). However the cuts may be dense \ +so it is worth experimenting (Long allows any length). " CUTS_LONGHELP + " Reference: https://github.com/coin-or/Cgl/wiki/CglGomory"); + parameters.push_back(p); + } + { + CbcParam p("greedy!Heuristic", "Whether to use a greedy heuristic", "off", + CBC_PARAM_STR_GREEDY); + + p.append("on"); + p.append("both"); + p.append("before"); + // p.append("root"); + p.setLonghelp("This heuristic tries to obtain a feasible solution by just " + "fixing a percentage of variables and then try a small " + "branch and cut run. " HEURISTICS_LONGHELP); + parameters.push_back(p); + } + { + CbcParam p("gsolu!tion", "Puts glpk solution to file", + CBC_PARAM_ACTION_GMPL_SOLUTION); + + p.setLonghelp( + "Will write a glpk solution file to the given file name. It will use the default \ +directory given by 'directory'. A name of '$' will use the previous value for the \ +name. This is initialized to 'stdout' (this defaults to ordinary solution if stdout). \ +If problem created from gmpl model - will do any reports."); + parameters.push_back(p); + } + { + CbcParam p("heur!isticsOnOff", "Switches most primal heuristics on or off", + "off", CBC_PARAM_STR_HEURISTICSTRATEGY); + p.append("on"); + p.setLonghelp( + "This option can be used to switch on or off all heuristics that search for feasible solutions,\ + except for the local tree search, as it dramatically alters the search.\ + Then individual heuristics can be turned off or on."); + parameters.push_back(p); + } + { + CbcParam p("clique!Cuts", "Whether to use Clique cuts", "off", + CBC_PARAM_STR_CLIQUECUTS); + p.append("on"); + p.append("root"); + p.append("ifmove"); + p.append("forceOn"); + p.append("onglobal"); + p.setLonghelp( + "This switches on clique cuts (either at root or in entire tree). \ +An improved version of the Bron-Kerbosch algorithm is used to separate cliques."); + parameters.push_back(p); + } + { + CbcParam p("cgraph", + "Whether to use the conflict graph-based preprocessing and cut " + "separation routines.", + "on", CBC_PARAM_STR_USECGRAPH); + p.append("off"); + p.append("clq"); + p.setLonghelp( + "This switches the conflict graph-based preprocessing and cut separation routines \ +(CglBKClique, CglOddWheel and CliqueStrengthening) on or off. Values:\ +\n\toff: turns these routines off;\ +\n\ton: turns these routines on;\ +\n\tclq: turns these routines off and enables the cut separator of CglClique."); + parameters.push_back(p); + } + { + CbcParam p("bkpivot!ing", + "Pivoting strategy used in Bron-Kerbosch algorithm", 0, 6, + CBC_PARAM_INT_BKPIVOTINGSTRATEGY); + p.setIntValue(3); + parameters.push_back(p); + } + { + CbcParam p( + "bkmaxcalls", + "Maximum number of recursive calls made by Bron-Kerbosch algorithm", 1, + 2147483647, CBC_PARAM_INT_BKMAXCALLS); + p.setIntValue(1000); + parameters.push_back(p); + } + { + CbcParam p("bkclqext!method", + "Strategy used to extend violated cliques found by BK Clique " + "Cut Separation routine", + 0, 5, CBC_PARAM_INT_BKCLQEXTMETHOD); + p.setLonghelp( + "Sets the method used in the extension module of BK Clique Cut Separation routine: \ +0=no extension; 1=random; 2=degree; 3=modified degree; 4=reduced cost(inversely proportional); 5=reduced cost(inversely proportional) + modified degree"); + p.setIntValue(4); + parameters.push_back(p); + } + { + CbcParam p("oddwheel!Cuts", "Whether to use odd wheel cuts", "off", + CBC_PARAM_STR_ODDWHEELCUTS); + p.append("on"); + p.append("root"); + p.append("ifmove"); + p.append("forceOn"); + p.append("onglobal"); + p.setLonghelp("This switches on odd-wheel inequalities (either at root or " + "in entire tree)."); + parameters.push_back(p); + } + { + CbcParam p( + "oddwext!method", + "Strategy used to search for wheel centers for the cuts found by \ +Odd Wheel Cut Separation routine", + 0, 2, CBC_PARAM_INT_ODDWEXTMETHOD); + p.setLonghelp( + "Sets the method used in the extension module of Odd Wheel Cut Separation routine: \ +0=no extension; 1=one variable; 2=clique"); + p.setIntValue(2); + parameters.push_back(p); + } + { + CbcParam p("clqstr!engthen", + "Whether to perform Clique Strengthening preprocessing routine", + "after", CBC_PARAM_STR_CLQSTRENGTHENING); + p.setLonghelp( + "Sets the method used in the Clique Strengthening Preprocessing routine:\ +\n\toff: do not perform clique strengthening;\ +\n\tbefore: perform clique strengthening before initialSolve;\ +\n\tafter: perform clique strengthening after initialSolve."); + p.append("off"); + p.append("before"); + parameters.push_back(p); + } + { + CbcParam p("help", "Print out version, non-standard options and some help", + CBC_PARAM_ACTION_HELP, 3); + p.setLonghelp( + "This prints out some help to get user started. If you have printed this then \ +you should be past that stage:-)"); + parameters.push_back(p); + } + { + CbcParam p("hOp!tions", "Heuristic options", -COIN_INT_MAX, COIN_INT_MAX, + CBC_PARAM_INT_HEUROPTIONS, 1); + p.setIntValue(0); + p.setLonghelp( + "Value 1 stops heuristics immediately if the allowable gap has been reached. \ +Other values are for the feasibility pump - \ +2 says do exact number of passes given, \ +4 only applies if an initial cutoff has been given and says relax after 50 passes, \ +while 8 will adapt the cutoff rhs after the first solution if it looks as if the code is stalling."); + parameters.push_back(p); + } + { + CbcParam p("hot!StartMaxIts", "Maximum iterations on hot start", 0, + COIN_INT_MAX, CBC_PARAM_INT_MAXHOTITS); + parameters.push_back(p); + } + { + CbcParam p("import", "Import model from mps file", CBC_PARAM_ACTION_IMPORT, + 3); + p.setLonghelp( + "This will read an MPS format file from the given file name. It will use the default\ + directory given by 'directory'. A name of '$' will use the previous value for the name. This\ + is initialized to '', i.e. it must be set. If you have libgz then it can read compressed\ + files 'xxxxxxxx.gz' or 'xxxxxxxx.bz2'. \ +If 'keepnames' is off, then names are dropped -> Rnnnnnnn and Cnnnnnnn."); + parameters.push_back(p); + } + { + CbcParam p("inc!rement", "A valid solution must be at least this \ +much better than last integer solution", + -COIN_DBL_MAX, COIN_DBL_MAX, CBC_PARAM_DBL_INCREMENT); + + p.setLonghelp( + "Whenever a solution is found the bound on the objective value for new solutions is set to the\ + objective function of the found solution (in a minimization sense) plus this. If it is not set then CBC will try and work one out, e.g. if \ +all objective coefficients are multiples of 0.01 and only integer variables have entries in \ +the objective function, then the increment can be set to 0.01. Be careful if setting this to a negative value!"); + + parameters.push_back(p); + } + { + CbcParam p("inf!easibilityWeight", "Each integer infeasibility is expected \ +to cost this much", + 0.0, COIN_DBL_MAX, CBC_PARAM_DBL_INFEASIBILITYWEIGHT, 1); + p.setLonghelp( + "A primitive way of deciding which node to explore next. Satisfying each integer infeasibility is \ +expected to cost this much."); + parameters.push_back(p); + } + { + CbcParam p("integerT!olerance", "For a feasible solution \ +no integer variable may be more than this away from an integer value", + 1.0e-20, 0.5, CBC_PARAM_DBL_INTEGERTOLERANCE); + p.setLonghelp("Beware of setting this smaller than the primal feasibility " + "tolerance."); + parameters.push_back(p); + } + { + CbcParam p("knapsack!Cuts", "Whether to use Knapsack cuts", "off", + CBC_PARAM_STR_KNAPSACKCUTS); + + p.append("on"); + p.append("root"); + p.append("ifmove"); + p.append("forceOn"); + p.append("onglobal"); + p.append("forceandglobal"); + p.setLonghelp( + CUTS_LONGHELP + " Reference: https://github.com/coin-or/Cgl/wiki/CglKnapsackCover"); + parameters.push_back(p); + } + { + CbcParam p("lagomory!Cuts", "Whether to use Lagrangean Gomory cuts", "off", + CBC_PARAM_STR_LAGOMORYCUTS); + p.append("endonlyroot"); + p.append("endcleanroot"); + p.append("root"); + p.append("endonly"); + p.append("endclean"); + p.append("endboth"); + p.append("onlyaswell"); + p.append("cleanaswell"); + p.append("bothaswell"); + p.append("onlyinstead"); + p.append("cleaninstead"); + p.append("bothinstead"); + p.append("onlyaswellroot"); + p.append("cleanaswellroot"); + p.append("bothaswellroot"); + p.setLonghelp( + "This is a gross simplification of 'A Relax-and-Cut Framework for Gomory's Mixed-Integer Cuts' \ +by Matteo Fischetti & Domenico Salvagnin. This simplification \ +just uses original constraints while modifying objective using other cuts. \ +So you don't use messy constraints generated by Gomory etc. \ +A variant is to allow non messy cuts e.g. clique cuts. \ +So 'only' does this while 'clean' also allows integral valued cuts. \ +'End' is recommended and waits until other cuts have finished before it \ +does a few passes. \ +The length options for gomory cuts are used."); + parameters.push_back(p); + } + { + CbcParam p("latwomir!Cuts", "Whether to use Lagrangean TwoMir cuts", "off", + CBC_PARAM_STR_LATWOMIRCUTS); + + p.append("endonlyroot"); + p.append("endcleanroot"); + p.append("endbothroot"); + p.append("endonly"); + p.append("endclean"); + p.append("endboth"); + p.append("onlyaswell"); + p.append("cleanaswell"); + p.append("bothaswell"); + p.append("onlyinstead"); + p.append("cleaninstead"); + p.append("bothinstead"); + p.setLonghelp("This is a Lagrangean relaxation for TwoMir cuts. See \ + lagomoryCuts for description of options."); + parameters.push_back(p); + } + { + CbcParam p("lift!AndProjectCuts", "Whether to use Lift and Project cuts", + "off", CBC_PARAM_STR_LANDPCUTS); + + p.append("on"); + p.append("root"); + p.append("ifmove"); + p.append("forceOn"); + p.append("iflongon"); + p.setLonghelp("These cuts may be expensive to compute. " CUTS_LONGHELP + " Reference: https://github.com/coin-or/Cgl/wiki/CglLandP"); + parameters.push_back(p); + } + { + CbcParam p("local!TreeSearch", + "Whether to use local tree search when a solution is found", + "off", CBC_PARAM_STR_LOCALTREE); + p.append("on"); + p.setLonghelp( + "The heuristic is from Fischetti and Lodi and is not really a heuristic although it can be used as one \ +(with limited functionality). It is not switched on when heuristics are switched on."); + parameters.push_back(p); + } + { + CbcParam p("max!imize", "Set optimization direction to maximize", + CBC_PARAM_ACTION_MAXIMIZE, 7); + p.setLonghelp("The default is minimize - use 'maximize' for maximization.\n\ +You can also use the parameters 'direction maximize'."); + parameters.push_back(p); + } + { + CbcParam p("maxN!odes", "Maximum number of nodes to do", -1, COIN_INT_MAX, + CBC_PARAM_INT_MAXNODES); + p.setLonghelp( + "This is a repeatable way to limit search. Normally using time is easier \ +but then the results may not be repeatable."); + parameters.push_back(p); + } + { + CbcParam p("maxNI!FS", + "Maximum number of nodes to be processed without improving the " + "incumbent solution.", + -1, COIN_INT_MAX, CBC_PARAM_INT_MAXNODESNOTIMPROVINGFS); + p.setLonghelp( + "This criterion specifies that when a feasible solution is available, the search should continue\ +only if better feasible solutions were produced in the last nodes."); + parameters.push_back(p); + } + { + CbcParam p("maxSaved!Solutions", "Maximum number of solutions to save", 0, + COIN_INT_MAX, CBC_PARAM_INT_MAXSAVEDSOLS); + p.setLonghelp("Number of solutions to save."); + parameters.push_back(p); + } + { + CbcParam p("maxSo!lutions", "Maximum number of feasible solutions to get", + 1, COIN_INT_MAX, CBC_PARAM_INT_MAXSOLS); + p.setLonghelp("You may want to stop after (say) two solutions or an hour. \ +This is checked every node in tree, so it is possible to get more solutions from heuristics."); + parameters.push_back(p); + } + { + CbcParam p("min!imize", "Set optimization direction to minimize", + CBC_PARAM_ACTION_MINIMIZE, 7); + p.setLonghelp("The default is minimize - use 'maximize' for maximization.\n\ +This should only be necessary if you have previously set maximization \ +You can also use the parameters 'direction minimize'."); + parameters.push_back(p); + } + { + CbcParam p("mipO!ptions", "Dubious options for mip", 0, COIN_INT_MAX, + CBC_PARAM_INT_MIPOPTIONS, 0); + p.setIntValue(1057); + parameters.push_back(p); + } + { + CbcParam p("more!MipOptions", "More dubious options for mip", -1, + COIN_INT_MAX, CBC_PARAM_INT_MOREMIPOPTIONS, 0); + parameters.push_back(p); + } + { + CbcParam p("more2!MipOptions", "More more dubious options for mip", -1, + COIN_INT_MAX, CBC_PARAM_INT_MOREMOREMIPOPTIONS, 0); + p.setIntValue(0); + parameters.push_back(p); + } + { + CbcParam p("mixed!IntegerRoundingCuts", + "Whether to use Mixed Integer Rounding cuts", "off", + CBC_PARAM_STR_MIXEDCUTS); + + p.append("on"); + p.append("root"); + p.append("ifmove"); + p.append("forceOn"); + p.append("onglobal"); + p.setLonghelp( + CUTS_LONGHELP + " Reference: " + "https://github.com/coin-or/Cgl/wiki/CglMixedIntegerRounding2"); + parameters.push_back(p); + } + { + CbcParam p("miplib", "Do some of miplib test set", CBC_PARAM_ACTION_MIPLIB, + 3, 1); + parameters.push_back(p); + } + { + CbcParam p("mips!tart", "reads an initial feasible solution from file", + CBC_PARAM_ACTION_MIPSTART); + p.setLonghelp("\ +The MIPStart allows one to enter an initial integer feasible solution \ +to CBC. Values of the main decision variables which are active (have \ +non-zero values) in this solution are specified in a text file. The \ +text file format used is the same of the solutions saved by CBC, but \ +not all fields are required to be filled. First line may contain the \ +solution status and will be ignored, remaining lines contain column \ +indexes, names and values as in this example:\n\ +\n\ +Stopped on iterations - objective value 57597.00000000\n\ + 0 x(1,1,2,2) 1 \n\ + 1 x(3,1,3,2) 1 \n\ + 5 v(5,1) 2 \n\ + 33 x(8,1,5,2) 1 \n\ + ...\n\ +\n\ +Column indexes are also ignored since pre-processing can change them. \ +There is no need to include values for continuous or integer auxiliary \ +variables, since they can be computed based on main decision variables. \ +Starting CBC with an integer feasible solution can dramatically improve \ +its performance: several MIP heuristics (e.g. RINS) rely on having at \ +least one feasible solution available and can start immediately if the \ +user provides one. Feasibility Pump (FP) is a heuristic which tries to \ +overcome the problem of taking too long to find feasible solution (or \ +not finding at all), but it not always succeeds. If you provide one \ +starting solution you will probably save some time by disabling FP. \ +\n\n\ +Knowledge specific to your problem can be considered to write an \ +external module to quickly produce an initial feasible solution - some \ +alternatives are the implementation of simple greedy heuristics or the \ +solution (by CBC for example) of a simpler model created just to find \ +a feasible solution. \ +\n\n\ +Silly options added. If filename ends .low then integers not mentioned \ +are set low - also .high, .lowcheap, .highcheap, .lowexpensive, .highexpensive \ +where .lowexpensive sets costed ones to make expensive others low. Also if \ +filename starts empty. then no file is read at all - just actions done. \ +\n\n\ +Question and suggestions regarding MIPStart can be directed to\n\ +haroldo.santos@gmail.com. "); + parameters.push_back(p); + } + { + CbcParam p("moreT!une", "Yet more dubious ideas for feasibility pump", 0, + 100000000, CBC_PARAM_INT_FPUMPTUNE2, 0); + + p.setLonghelp("Yet more ideas for Feasibility Pump \n\ +\t/100000 == 1 use box constraints and original obj in cleanup\n\ +\t/1000 == 1 Pump will run twice if no solution found\n\ +\t/1000 == 2 Pump will only run after root cuts if no solution found\n\ +\t/1000 >10 as above but even if solution found\n\ +\t/100 == 1,3.. exact 1.0 for objective values\n\ +\t/100 == 2,3.. allow more iterations per pass\n\ +\t n fix if value of variable same for last n iterations."); + p.setIntValue(0); + parameters.push_back(p); + } + { + CbcParam p("multiple!RootPasses", + "Do multiple root passes to collect cuts and solutions", 0, + COIN_INT_MAX, CBC_PARAM_INT_MULTIPLEROOTS, 0); + p.setIntValue(0); + p.setLonghelp( + "Solve (in parallel, if enabled) the root phase this number of times, \ + each with its own different seed, and collect all solutions and cuts generated. \ + The actual format is aabbcc where aa is the number of extra passes; \ + if bb is non zero, then it is number of threads to use (otherwise uses threads setting); \ + and cc is the number of times to do root phase. \ +The solvers do not interact with each other. However if extra passes are specified \ +then cuts are collected and used in later passes - so there is interaction there. \ +Some parts of this implementation have their origin in idea of \ +Andrea Lodi, Matteo Fischetti, Michele Monaci, Domenico Salvagnin, and Andrea Tramontani."); + parameters.push_back(p); + } + { + CbcParam p("naive!Heuristics", "Whether to try some stupid heuristic", + "off", CBC_PARAM_STR_NAIVE, 7, 1); + + p.append("on"); + p.append("both"); + p.append("before"); + p.setLonghelp("This is naive heuristics which, e.g., fix all integers with " + "costs to zero!. " HEURISTICS_LONGHELP); + parameters.push_back(p); + } + { + CbcParam p("nextB!estSolution", "Prints next best saved solution to file", + CBC_PARAM_ACTION_NEXTBESTSOLUTION); + + p.setLonghelp( + "To write best solution, just use solution. This prints next best (if exists) \ + and then deletes it. \ + This will write a primitive solution file to the given file name. It will use the default\ + directory given by 'directory'. A name of '$' will use the previous value for the name. This\ + is initialized to 'stdout'. The amount of output can be varied using printi!ngOptions or printMask."); + parameters.push_back(p); + } + { + CbcParam p("node!Strategy", + "What strategy to use to select the next node from the branch " + "and cut tree", + "hybrid", CBC_PARAM_STR_NODESTRATEGY); + p.append("fewest"); + p.append("depth"); + p.append("upfewest"); + p.append("downfewest"); + p.append("updepth"); + p.append("downdepth"); + p.setLonghelp( + "Normally before a feasible solution is found, CBC will choose a node with fewest infeasibilities. \ + Alternatively, one may choose tree-depth as the criterion. This requires the minimal amount of memory, but may take a long time to find the best solution.\ + Additionally, one may specify whether up or down branches must \ +be selected first (the up-down choice will carry on after a first solution has been bound). \ +The choice 'hybrid' does breadth first on small depth nodes and then switches to 'fewest'."); + parameters.push_back(p); + } + { + CbcParam p("numberA!nalyze", "Number of analysis iterations", -COIN_INT_MAX, + COIN_INT_MAX, CBC_PARAM_INT_NUMBERANALYZE, 0); + p.setLonghelp( + "This says how many iterations to spend at root node analyzing problem. \ +This is a first try and will hopefully become more sophisticated."); + parameters.push_back(p); + } +#ifdef CBC_HAS_NAUTY + { + CbcParam p("Orbit!alBranching", "Whether to try orbital branching", "off", + CBC_PARAM_STR_ORBITAL); + p.append("slow!ish"); + p.append("strong"); + p.append("force"); + p.append("simple"); + p.append("on"); + p.append("more!printing"); + p.setLonghelp("This switches on Orbital branching. \ +Value 'on' just adds orbital, 'strong' tries extra fixing in strong branching."); + parameters.push_back(p); + } +#endif + { + CbcParam p("PrepN!ames", + "If column names will be kept in pre-processed model", "off", + CBC_PARAM_STR_PREPROCNAMES); + p.append("on"); + p.setLonghelp( + "Normally the preprocessed model has column names replaced by new names C0000...\ +Setting this option to on keeps original names in variables which still exist in the preprocessed problem"); + parameters.push_back(p); + } + + { + CbcParam p("output!Format", "Which output format to use", 1, 6, + CBC_PARAM_INT_OUTPUTFORMAT); + p.setLonghelp( + "Normally export will be done using normal representation for numbers and two values\ + per line. You may want to do just one per line (for grep or suchlike) and you may wish\ + to save with absolute accuracy using a coded version of the IEEE value. A value of 2 is normal.\ + otherwise odd values gives one value per line, even two. Values 1,2 give normal format, 3,4\ + gives greater precision, while 5,6 give IEEE values. When used for exporting a basis 1 does not save \ +values, 2 saves values, 3 with greater accuracy and 4 in IEEE."); + parameters.push_back(p); + } + { + CbcParam p( + "passC!uts", + "Number of rounds that cut generators are applied in the root node", + -COIN_INT_MAX, COIN_INT_MAX, CBC_PARAM_INT_CUTPASS); + + p.setIntValue(20); + p.setLonghelp( + "The default is to do 100 passes if the problem has less than 500 columns, 100 passes (but \ +stop if the drop in the objective function value is small) if the problem has less than 5000 columns, and 20 passes otherwise. \ +A negative value -n means that n passes are also applied if the objective does not drop."); + parameters.push_back(p); + } + { + CbcParam p("passF!easibilityPump", + "How many passes to do in the Feasibility Pump heuristic", 0, + 10000, CBC_PARAM_INT_FPUMPITS); + p.setIntValue(20); + parameters.push_back(p); + } + { + CbcParam p("passT!reeCuts", + "Number of rounds that cut generators are applied in the tree", + -COIN_INT_MAX, COIN_INT_MAX, CBC_PARAM_INT_CUTPASSINTREE); + p.setIntValue(1); + p.setLonghelp( + "The default is to do one pass. A negative value -n means that n " + "passes are also applied if the objective does not drop."); + parameters.push_back(p); + } + { + CbcParam p("pivotAndC!omplement", + "Whether to try Pivot and Complement heuristic", "off", + CBC_PARAM_STR_PIVOTANDCOMPLEMENT); + + p.append("on"); + p.append("both"); + p.append("before"); + p.setLonghelp(HEURISTICS_LONGHELP); + parameters.push_back(p); + } + { + CbcParam p("pivotAndF!ix", "Whether to try Pivot and Fix heuristic", "off", + CBC_PARAM_STR_PIVOTANDFIX); + p.append("on"); + p.append("both"); + p.append("before"); + p.setLonghelp(HEURISTICS_LONGHELP); + parameters.push_back(p); + } + { + CbcParam p("pO!ptions", "Dubious print options", 0, COIN_INT_MAX, + CBC_PARAM_INT_PRINTOPTIONS, 1); + p.setIntValue(0); + p.setLonghelp("If this is > 0 then presolve will give more information and " + "branch and cut will give statistics"); + parameters.push_back(p); + } + { + CbcParam p("preprocess", "Whether to use integer preprocessing", "off", + CBC_PARAM_STR_PREPROCESS); + + p.append("on"); + p.append("save"); + p.append("equal"); + p.append("sos"); + p.append("trysos"); + p.append("equalall"); + p.append("strategy"); + p.append("aggregate"); + p.append("forcesos"); + p.append("stop!aftersaving"); + p.setLonghelp( + "This tries to reduce size of model in a similar way to presolve and \ +it also tries to strengthen the model - this can be very useful and is worth trying. \ + Value 'save' saves the presolved problem to a file presolved.mps.\ + Value 'equal' will turn inequality-cliques into equalities.\ + Value 'sos' lets CBC search for rows with upper bound 1 and where all nonzero coefficients are 1 and creates special ordered sets if the sets are not overlapping and all integer variables (except for at most one) are in the sets.\ + Value 'trysos' is same as 'sos', but allows any number of integer variables outside of sets.\ + Value 'equalall' lets CBC turn all valid inequalities into equalities by adding integer slack variables."); // Value 'strategy' is as on but uses CbcStrategy. + parameters.push_back(p); + } + { + CbcParam p("printi!ngOptions", "Print options", "normal", + CBC_PARAM_STR_INTPRINT, 3); + p.append("integer"); + p.append("special"); + p.append("rows"); + p.append("all"); + p.append("csv"); + p.append("bound!ranging"); + p.append("rhs!ranging"); + p.append("objective!ranging"); + p.append("stats"); + p.append("boundsint"); + p.append("boundsall"); + p.append("fixint"); + p.append("fixall"); + p.setLonghelp( + "This changes the amount and format of printing a solution:\nnormal - nonzero column variables \n\ +integer - nonzero integer column variables\n\ +special - in format suitable for OsiRowCutDebugger\n\ +rows - nonzero column variables and row activities\n\ +all - all column variables and row activities.\n\ +\nFor non-integer problems 'integer' and 'special' act like 'normal'. \ +Also see printMask for controlling output."); + parameters.push_back(p); + } + { + CbcParam p("printM!ask", "Control printing of solution on a mask", + CBC_PARAM_ACTION_PRINTMASK, 3); + + p.setLonghelp( + "If set then only those names which match mask are printed in a solution. \ +'?' matches any character and '*' matches any set of characters. \ + The default is '' i.e. unset so all variables are printed. \ +This is only active if model has names."); + parameters.push_back(p); + } + + { + CbcParam p("prio!rityIn", "Import priorities etc from file", + CBC_PARAM_ACTION_PRIORITYIN, 3); + p.setLonghelp( + "This will read a file with priorities from the given file name. It will use the default\ + directory given by 'directory'. A name of '$' will use the previous value for the name. This\ + is initialized to '', i.e. it must be set. This can not read from compressed files. \ +File is in csv format with allowed headings - name, number, priority, direction, up, down, solution. Exactly one of\ + name and number must be given."); + parameters.push_back(p); + } + + { + CbcParam p("probing!Cuts", "Whether to use Probing cuts", "off", + CBC_PARAM_STR_PROBINGCUTS); + p.append("on"); + p.append("root"); + p.append("ifmove"); + p.append("forceOn"); + p.append("onglobal"); + p.append("forceonglobal"); + p.append("forceOnBut"); + p.append("forceOnStrong"); + p.append("forceOnButStrong"); + p.append("strongRoot"); + p.setLonghelp( + CUTS_LONGHELP + " Value 'forceOnBut' turns on probing and forces CBC to do probing at every node, but does only probing, not strengthening etc. \ + Value 'strong' forces CBC to strongly do probing at every node, that is, also when CBC would usually turn it off because it hasn't found something. \ + Value 'forceonbutstrong' is like 'forceonstrong', but does only probing (column fixing) and turns off row strengthening, so the matrix will not change inside the branch and bound. \ + Reference: https://github.com/coin-or/Cgl/wiki/CglProbing"); + parameters.push_back(p); + } + { + CbcParam p("proximity!Search", "Whether to do proximity search heuristic", + "off", CBC_PARAM_STR_PROXIMITY); + + p.append("on"); + p.append("both"); + p.append("before"); + p.append("10"); + p.append("100"); + p.append("300"); + // but allow numbers after this (returning 1) + p.setFakeKeyWord(1); + p.setLonghelp( + "This heuristic looks for a solution close to the incumbent solution (Fischetti and Monaci, 2012). \ +The idea is to define a sub-MIP without additional constraints but with a modified objective function intended to attract the search \ +in the proximity of the incumbent. \ +The approach works well for 0-1 MIPs whose solution landscape is not too irregular (meaning the there is reasonable probability of \ +finding an improved solution by flipping a small number of binary variables), in particular when it is applied to the first heuristic solutions \ +found at the root node. " HEURISTICS_LONGHELP); // Can also set different + // maxNode settings by plusnnnn + // (and are 'on'(on==30)). + parameters.push_back(p); + } + { + CbcParam p("pumpC!utoff", "Fake cutoff for use in feasibility pump", + -COIN_DBL_MAX, COIN_DBL_MAX, CBC_PARAM_DBL_FAKECUTOFF); + p.setDoubleValue(0.0); + p.setLonghelp( + "A value of 0.0 means off. Otherwise, add a constraint forcing objective below this value\ + in feasibility pump"); + parameters.push_back(p); + } + { + CbcParam p("pumpI!ncrement", "Fake increment for use in feasibility pump", + -COIN_DBL_MAX, COIN_DBL_MAX, CBC_PARAM_DBL_FAKEINCREMENT, 1); + p.setDoubleValue(0.0); + p.setLonghelp( + "A value of 0.0 means off. Otherwise use as absolute increment to cutoff \ +when solution found in feasibility pump"); + parameters.push_back(p); + } + { + CbcParam p("pumpT!une", "Dubious ideas for feasibility pump", 0, 100000000, + CBC_PARAM_INT_FPUMPTUNE); + p.setIntValue(1003); + p.setLonghelp("This fine tunes Feasibility Pump \n\ +\t>=10000000 use as objective weight switch\n\ +\t>=1000000 use as accumulate switch\n\ +\t>=1000 use index+1 as number of large loops\n\ +\t==100 use objvalue +0.05*fabs(objvalue) as cutoff OR fakeCutoff if set\n\ +\t%100 == 10,20 affects how each solve is done\n\ +\t1 == fix ints at bounds, 2 fix all integral ints, 3 and continuous at bounds. \ +If accumulate is on then after a major pass, variables which have not moved \ +are fixed and a small branch and bound is tried."); + p.setIntValue(0); + parameters.push_back(p); + } + { + CbcParam p("randomC!bcSeed", "Random seed for Cbc", -1, COIN_INT_MAX, + CBC_PARAM_INT_RANDOMSEED); + + p.setLonghelp("Allows initialization of the random seed for pseudo-random " + "numbers used in heuristics such as the Feasibility Pump to " + "decide whether to round up or down. " + "The special value of 0 lets Cbc use the time of the day for " + "the initial seed."); + p.setIntValue(-1); + parameters.push_back(p); + } + { + CbcParam p("randomi!zedRounding", + "Whether to try randomized rounding heuristic", "off", + CBC_PARAM_STR_RANDROUND); + p.append("on"); + p.append("both"); + p.append("before"); + p.setLonghelp(HEURISTICS_LONGHELP); + parameters.push_back(p); + } + { + CbcParam p("ratio!Gap", "Stop when gap between best possible and \ +best known is less than this fraction of larger of two", + 0.0, COIN_DBL_MAX, CBC_PARAM_DBL_GAPRATIO); + p.setDoubleValue(1e-4); + p.setLonghelp( + "If the gap between the best known solution and the best possible solution is less than this fraction \ +of the objective value at the root node then the search will terminate. See 'allowableGap' for a \ +way of using absolute value rather than fraction."); + parameters.push_back(p); + } + { + CbcParam p("reduce!AndSplitCuts", "Whether to use Reduce-and-Split cuts", + "off", CBC_PARAM_STR_REDSPLITCUTS); + + p.append("on"); + p.append("root"); + p.append("ifmove"); + p.append("forceOn"); + p.setLonghelp( + "These cuts may be expensive to generate. " CUTS_LONGHELP + " Reference: https://github.com/coin-or/Cgl/wiki/CglRedSplit"); + parameters.push_back(p); + } + { + CbcParam p("reduce2!AndSplitCuts", + "Whether to use Reduce-and-Split cuts - style 2", "off", + CBC_PARAM_STR_REDSPLIT2CUTS); + p.append("on"); + p.append("root"); + p.append("longOn"); + p.append("longRoot"); + p.setLonghelp( + "This switches on reduce and split cuts (either at root or in entire tree). \ +This version is by Giacomo Nannicini based on Francois Margot's version. \ +Standard setting only uses rows in tableau <= 256, long uses all. \ +These cuts may be expensive to generate. \ +See option cuts for more information on the possible values."); + parameters.push_back(p); + } + { + CbcParam p("residual!CapacityCuts", "Whether to use Residual Capacity cuts", + "off", CBC_PARAM_STR_RESIDCUTS); + p.append("on"); + p.append("root"); + p.append("ifmove"); + p.append("forceOn"); + p.setLonghelp( + CUTS_LONGHELP + " Reference: https://github.com/coin-or/Cgl/wiki/CglResidualCapacity"); + + parameters.push_back(p); + } + { + CbcParam p("restore!Model", "Restore model from binary file", + CBC_PARAM_ACTION_RESTORE, 7, 1); + p.setLonghelp( + "This reads data save by saveModel from the given file. It will use the default\ + directory given by 'directory'. A name of '$' will use the previous value for the name. This\ + is initialized to 'default.prob'."); + + parameters.push_back(p); + } + { + CbcParam p("reverse", "Reverses sign of objective", + CBC_PARAM_ACTION_REVERSE, 7, 0); + p.setLonghelp("Useful for testing if maximization works correctly"); + parameters.push_back(p); + } + { + CbcParam p("Rens", "Whether to try Relaxation Enforced Neighborhood Search", + "off", CBC_PARAM_STR_RENS); + p.append("on"); + p.append("both"); + p.append("before"); + p.append("200"); + p.append("1000"); + p.append("10000"); + p.append("dj"); + p.append("djbefore"); + p.append("usesolution"); + p.setLonghelp(HEURISTICS_LONGHELP " Value 'on' just does 50 nodes. 200, " + "1000, and 10000 does that many nodes."); + parameters.push_back(p); + } + { + CbcParam p("Rins", "Whether to try Relaxed Induced Neighborhood Search", + "off", CBC_PARAM_STR_RINS); + p.append("on"); + p.append("both"); + p.append("before"); + p.append("often"); + p.setLonghelp(HEURISTICS_LONGHELP); + parameters.push_back(p); + } + { + CbcParam p("round!ingHeuristic", + "Whether to use simple (but effective) Rounding heuristic", + "off", CBC_PARAM_STR_ROUNDING); + p.append("on"); + p.append("both"); + p.append("before"); + p.setLonghelp(HEURISTICS_LONGHELP); + parameters.push_back(p); + } + { + CbcParam p("saveM!odel", "Save model to binary file", CBC_PARAM_ACTION_SAVE, + 7, 1); + p.setLonghelp( + "This will save the problem to the given file name for future use\ + by restoreModel. It will use the default\ + directory given by 'directory'. A name of '$' will use the previous value for the name. This\ + is initialized to 'default.prob'."); + parameters.push_back(p); + } + { + CbcParam p("saveS!olution", "saves solution to file", + CBC_PARAM_ACTION_SAVESOL); + + p.setLonghelp( + "This will write a binary solution file to the given file name. It will use the default\ + directory given by 'directory'. A name of '$' will use the previous value for the name. This\ + is initialized to 'solution.file'. To read the file use fread(int) twice to pick up number of rows \ +and columns, then fread(double) to pick up objective value, then pick up row activities, row duals, column \ +activities and reduced costs - see bottom of CbcParam.cpp for code that reads or writes file. \ +If name contains '_fix_read_' then does not write but reads and will fix all variables"); + parameters.push_back(p); + } + { + CbcParam p("sec!onds", "maximum seconds", -1.0, COIN_DBL_MAX, + CBC_PARAM_DBL_TIMELIMIT_BAB); + // Meaning 0 - start at very beginning + // 1 start at beginning of preprocessing + // 2 start at beginning of branch and bound +#ifndef CBC_USE_INITIAL_TIME +#define CBC_USE_INITIAL_TIME 1 +#endif +#if CBC_USE_INITIAL_TIME == 0 + p.setLonghelp("After this many seconds in Branch and Bound coin solver " + "will act as if maximum nodes had been reached (time in " + "initial solve and preprocessing is included)."); +#elif CBC_USE_INITIAL_TIME == 1 + p.setLonghelp("After this many seconds in Branch and Bound coin solver " + "will act as if maximum nodes had been reached (time in " + "initial solve not included)."); +#else + p.setLonghelp("After this many seconds in Branch and Bound coin solver " + "will act as if maximum nodes had been reached (time in " + "initial solve and preprocessing not included)."); +#endif + parameters.push_back(p); + } + { + CbcParam p("secni!fs", + "maximum seconds without improving the incumbent solution", -1.0, + COIN_DBL_MAX, CBC_PARAM_DBL_MAXSECONDSNIFS); + p.setLonghelp( + "With this stopping criterion, after a feasible solution is found, the search should continue only if the incumbent solution was updated recently, \ +the tolerance is specified here. A discussion on why this criterion can be useful is included here: \ +https://yetanothermathprogrammingconsultant.blogspot.com/2019/11/mip-solver-stopping-criteria.html ."); + parameters.push_back(p); + } + { + CbcParam p("sleep", "for debug", CBC_PARAM_ACTION_DUMMY, 7, 0); + + p.setLonghelp("If passed to solver fom ampl, then ampl will wait so that " + "you can copy .nl file for debug."); + parameters.push_back(p); + } + { + CbcParam p("slow!cutpasses", + "Maximum number of rounds for slower cut generators", -1, + COIN_INT_MAX, CBC_PARAM_INT_MAXSLOWCUTS); + p.setLonghelp( + "Some cut generators are fairly slow - this limits the number of times they are tried.\ + The cut generators identified as 'may be slow' at present are Lift and project cuts and both versions of Reduce and Split cuts."); + p.setIntValue(10); + parameters.push_back(p); + } + { + CbcParam p("solu!tion", "Prints solution to file", + CBC_PARAM_ACTION_SOLUTION); + p.setLonghelp( + "This will write a primitive solution file to the given file name. It will use the default\ + directory given by 'directory'. A name of '$' will use the previous value for the name. This\ + is initialized to 'stdout'. The amount of output can be varied using printi!ngOptions or printMask."); + parameters.push_back(p); + } + { + CbcParam p("solv!e", "Solve problem", CBC_PARAM_ACTION_BAB); + p.setLonghelp( + "If there are no integer variables then this just solves LP. If there are integer variables \ +this does branch and cut."); + parameters.push_back(p); + } + { + CbcParam p("sosO!ptions", "Whether to use SOS from AMPL", "off", + CBC_PARAM_STR_SOS); + p.append("on"); + p.setCurrentOption("on"); + p.setLonghelp( + "Normally if AMPL says there are SOS variables they should be used, but sometime sthey should\ + be turned off - this does so."); + parameters.push_back(p); + } + { + CbcParam p("slog!Level", "Level of detail in main solver output", -1, 63, + CBC_PARAM_INT_SOLVERLOGLEVEL); + p.setLonghelp( + "If 0 then there should be no output in normal circumstances. 1 is probably the best\ + value for most uses, while 2 and 3 give more information."); + parameters.push_back(p); + } + { + CbcParam p("lplog!Level", "Level of detail in LP solver output", -1, 63, + CBC_PARAM_INT_LPLOGLEVEL); + p.setLonghelp( + "If 0 then there should be no output in normal circumstances. 1 is probably the best\ + value for most uses, while 2 and 3 give more information. This parameter is only for controlling the output of the LP solver"); + parameters.push_back(p); + } + { + // Due to James Howey + CbcParam p("sosP!rioritize", "How to deal with SOS priorities", "off", + CBC_PARAM_STR_SOSPRIORITIZE); + p.append("high"); + p.append("low"); + p.append("orderhigh"); + p.append("orderlow"); + p.setLonghelp( + "This sets priorities for SOS. Values 'high' and 'low' just set a priority \ + relative to the for integer variables. Value 'orderhigh' gives first highest priority to the first SOS and integer variables \ + a low priority. Value 'orderlow' gives integer variables a high priority then SOS in order."); + parameters.push_back(p); + } + { + CbcParam p("timeM!ode", "Whether to use CPU or elapsed time", "cpu", + CBC_PARAM_STR_TIME_MODE); + p.append("elapsed"); + p.setLonghelp( + "cpu uses CPU time for stopping, while elapsed uses elapsed time. \ +(On Windows, elapsed time is always used)."); + parameters.push_back(p); + } + { + CbcParam p("stat!istics", "Print some statistics", + CBC_PARAM_ACTION_STATISTICS); + p.setLonghelp("This command prints some statistics for the current model.\ + If log level >1 then more is printed.\ + These are for presolved model if presolve on (and unscaled)."); + parameters.push_back(p); + } + { + CbcParam p("strat!egy", "Switches on groups of features", 0, 2, + CBC_PARAM_INT_STRATEGY); + p.setLonghelp("This turns on newer features. \ +Use 0 for easy problems, 1 is default, 2 is aggressive. \ +1 uses Gomory cuts with a tolerance of 0.01 at the root node, \ +does a possible restart after 100 nodes if many variables could be fixed, \ +activates a diving and RINS heuristic, and makes the feasibility pump \ +more aggressive."); // This does not apply to unit tests (where 'experiment' may + // have similar effects + p.setIntValue(1); + parameters.push_back(p); + } +#ifdef CBC_KEEP_DEPRECATED + { + CbcParam p("strengthen", "Create strengthened problem", + CBC_PARAM_ACTION_STRENGTHEN, 3); + p.setLonghelp( + "This creates a new problem by applying the root node cuts. All tight constraints \ +will be in resulting problem"); + parameters.push_back(p); + } +#endif + { + CbcParam p("strong!Branching", + "Number of variables to look at in strong branching", 0, + COIN_INT_MAX, CBC_PARAM_INT_STRONGBRANCHING); + p.setIntValue(20); + p.setLonghelp( + "In order to decide which variable to branch on, the code will choose up to this number \ +of unsatisfied variables to try minimal up and down branches on. Then the most effective one is chosen. \ +If a variable is branched on many times then the previous average up and down costs may be used - \ +see also option trustPseudoCosts."); + parameters.push_back(p); + } + { + CbcParam p("testO!si", "Test OsiObject stuff", -1, COIN_INT_MAX, + CBC_PARAM_INT_TESTOSI, 0); + parameters.push_back(p); + } +#ifdef CBC_THREAD + { + CbcParam p("thread!s", "Number of threads to try and use", -100, 100000, + CBC_PARAM_INT_THREADS, 1); + p.setIntValue(0); + p.setLonghelp( + "To use multiple threads, set threads to number wanted. It may be better \ +to use one or two more than number of cpus available. If 100+n then n threads and \ +search is repeatable (maybe be somewhat slower), \ +if 200+n use threads for root cuts, 400+n threads used in sub-trees."); + parameters.push_back(p); + } +#endif + { + CbcParam p("tighten!Factor", "Tighten bounds using this times largest \ +activity at continuous solution", + 1.0e-3, COIN_DBL_MAX, CBC_PARAM_DBL_TIGHTENFACTOR, 0); + p.setLonghelp("This sleazy trick can help on some problems."); + parameters.push_back(p); + } + { + CbcParam p("trust!PseudoCosts", + "Number of branches before we trust pseudocosts", -3, + COIN_INT_MAX, CBC_PARAM_INT_NUMBERBEFORE); + p.setLonghelp( + "Using strong branching computes pseudo-costs. This parameter determines after how many branches for a variable we just \ +trust the pseudo costs and do not do any more strong branching."); + p.setIntValue(10); + parameters.push_back(p); + } + { + CbcParam p("tune!PreProcess", "Dubious tuning parameters for preprocessing", + 0, COIN_INT_MAX, CBC_PARAM_INT_PROCESSTUNE, 1); + p.setLonghelp( + "Format aabbcccc - \n If aa then this is number of major passes (i.e. with presolve) \n \ +If bb and bb>0 then this is number of minor passes (if unset or 0 then 10) \n \ +cccc is bit set \n 0 - 1 Heavy probing \n 1 - 2 Make variables integer if possible (if obj value)\n \ +2 - 4 As above but even if zero objective value\n \ +7 - 128 Try and create cliques\n 8 - 256 If all +1 try hard for dominated rows\n \ +9 - 512 Even heavier probing \n \ +10 - 1024 Use a larger feasibility tolerance in presolve\n \ +11 - 2048 Try probing before creating cliques\n \ +12 - 4096 Switch off duplicate column checking for integers \n \ +13 - 8192 Allow scaled duplicate column checking \n \n \ + Now aa 99 has special meaning i.e. just one simple presolve."); + parameters.push_back(p); + } + { + CbcParam p("two!MirCuts", + "Whether to use Two phase Mixed Integer Rounding cuts", "off", + CBC_PARAM_STR_TWOMIRCUTS); + p.append("on"); + p.append("root"); + p.append("ifmove"); + p.append("forceOn"); + p.append("onglobal"); + p.append("forceandglobal"); + p.append("forceLongOn"); + p.setLonghelp(CUTS_LONGHELP + " Reference: https://github.com/coin-or/Cgl/wiki/CglTwomir"); + parameters.push_back(p); + } + { + CbcParam p("unitTest", "Do unit test", CBC_PARAM_ACTION_UNITTEST, 3, 1); + p.setLonghelp("This exercises the unit test for clp"); + parameters.push_back(p); + } + { + CbcParam p("userCbc", "Hand coded Cbc stuff", CBC_PARAM_ACTION_USERCBC, 0, + 0); + p.setLonghelp( + "There are times e.g. when using AMPL interface when you may wish to do something unusual. \ +Look for USERCBC in main driver and modify sample code. \ +It is possible you can get same effect by using example driver4.cpp."); + parameters.push_back(p); + } + { + CbcParam p("Vnd!VariableNeighborhoodSearch", + "Whether to try Variable Neighborhood Search", "off", + CBC_PARAM_STR_VND); + p.append("on"); + p.append("both"); + p.append("before"); + p.append("intree"); + p.setLonghelp(HEURISTICS_LONGHELP); + parameters.push_back(p); + } + { + CbcParam p("verbose", "Switches on longer help on single ?", 0, 31, + CBC_PARAM_INT_VERBOSE, 0); + p.setLonghelp("Set to 1 to get short help with ? list, 2 to get long help, " + "3 for both. (add 4 to just get ampl ones)."); + p.setIntValue(0); + parameters.push_back(p); + } + { + CbcParam p("vub!heuristic", "Type of VUB heuristic", -2, 20, + CBC_PARAM_INT_VUBTRY, 0); + p.setLonghelp("This heuristic tries and fix some integer variables."); + p.setIntValue(-1); + parameters.push_back(p); + } + { + CbcParam p("zero!HalfCuts", "Whether to use zero half cuts", "off", + CBC_PARAM_STR_ZEROHALFCUTS); + p.append("on"); + p.append("root"); + p.append("ifmove"); + p.append("forceOn"); + p.append("onglobal"); + p.setLonghelp(CUTS_LONGHELP + " This implementation was written by Alberto Caprara."); + parameters.push_back(p); + } +} + +// Given a parameter type - returns its number in list +int whichCbcParam(const CbcParameterType &name, + const std::vector ¶meters) { + for (int i = 0; i < (int)parameters.size(); i++) { + if (parameters[i].type() == name) + return i; + } + return std::numeric_limits::max(); // should not arrive here +} + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 + */ diff --git a/src/Attic/CbcParam.hpp b/src/Attic/CbcParam.hpp new file mode 100644 index 000000000..8e0cce434 --- /dev/null +++ b/src/Attic/CbcParam.hpp @@ -0,0 +1,466 @@ +// Copyright (C) 2002, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef CbcParam_H +#define CbcParam_H + +#include "CbcModel.hpp" +#include "ClpParam.hpp" +#include "OsiSolverInterface.hpp" +class ClpSimplex; +/*! \brief Parameter codes + + Parameter type ranges are allocated as follows +
    +
  • 1 -- 100 double parameters +
  • 101 -- 200 integer parameters +
  • 201 -- 250 string parameters +
  • 251 -- 300 cuts etc(string but broken out for clarity) +
  • 301 -- 400 `actions' +
+ + `Actions' do not necessarily invoke an immediate action; it's just that they + don't fit neatly into the parameters array. + + This coding scheme is in flux. + CBC_PARAM_STR_NODESTRATEGY, + CBC_PARAM_STR_BRANCHSTRATEGY, + CBC_PARAM_NOTUSED_ADDCUTSSTRATEGY, + CLP_PARAM_ACTION_CLEARCUTS, + CBC_PARAM_NOTUSED_OSLSTUFF, + CBC_PARAM_NOTUSED_CBCSTUFF are not used at present (03.10.24). +*/ + +enum CbcParameterType + +{ // Begin used in Clp + // Begin CbcGen + CBC_PARAM_GENERALQUERY = -100, + CBC_PARAM_FULLGENERALQUERY, + CBC_PARAM_STR_ALLCOMMANDS, + // End CbcGen + // End used in Clp + + // Begin CbcGenCbc + CBC_PARAM_DBL_INFEASIBILITYWEIGHT = 51, + CBC_PARAM_DBL_CUTOFF, + CBC_PARAM_DBL_INTEGERTOLERANCE, + CBC_PARAM_DBL_INCREMENT, + CBC_PARAM_DBL_ALLOWABLEGAP, + CBC_PARAM_DBL_TIMELIMIT_BAB, + CBC_PARAM_DBL_MAXSECONDSNIFS, + CBC_PARAM_DBL_GAPRATIO, + // End CbcGenCbc + + // Begin CbcGen + CBC_PARAM_DBL_DJFIX = 81, + CBC_PARAM_DBL_TIGHTENFACTOR, + CBC_PARAM_DBL_FAKEINCREMENT, + CBC_PARAM_DBL_FAKECUTOFF, + CBC_PARAM_DBL_ARTIFICIALCOST, + CBC_PARAM_DBL_DEXTRA3, + CBC_PARAM_DBL_SMALLBAB, + CBC_PARAM_DBL_DEXTRA4, + CBC_PARAM_DBL_DEXTRA5, + + // Begin Used in Clp + CBC_PARAM_INT_SOLVERLOGLEVEL = 101, + CBC_PARAM_INT_OUTPUTFORMAT, + CBC_PARAM_INT_PRINTOPTIONS, + CBC_PARAM_INT_VERBOSE, + + CBC_PARAM_INT_THREADS = 151, + // End used in Clp + CBC_PARAM_INT_LPLOGLEVEL, + CBC_PARAM_INT_CUTDEPTH, + CBC_PARAM_INT_BKPIVOTINGSTRATEGY, + CBC_PARAM_INT_BKMAXCALLS, + CBC_PARAM_INT_BKCLQEXTMETHOD, + CBC_PARAM_INT_ODDWEXTMETHOD, + CBC_PARAM_INT_FPUMPITS, + CBC_PARAM_INT_FPUMPTUNE, + CBC_PARAM_INT_TESTOSI, + CBC_PARAM_INT_EXTRA1, + CBC_PARAM_INT_EXTRA2, + CBC_PARAM_INT_EXTRA3, + CBC_PARAM_INT_EXTRA4, + CBC_PARAM_INT_DEPTHMINIBAB, + CBC_PARAM_INT_CUTPASSINTREE, + CBC_PARAM_INT_VUBTRY, + CBC_PARAM_INT_EXPERIMENT, + CBC_PARAM_INT_DIVEOPT, + CBC_PARAM_INT_DIVEOPTSOLVES, + CBC_PARAM_INT_STRATEGY, + CBC_PARAM_INT_HEUROPTIONS, + CBC_PARAM_INT_CUTLENGTH, + CBC_PARAM_INT_FPUMPTUNE2, + CBC_PARAM_INT_MAXSAVEDSOLS, + CBC_PARAM_INT_RANDOMSEED, + CBC_PARAM_INT_MULTIPLEROOTS, + CBC_PARAM_INT_STRONG_STRATEGY, + CBC_PARAM_INT_EXTRA_VARIABLES, + CBC_PARAM_INT_MAXSLOWCUTS, + CBC_PARAM_INT_MOREMOREMIPOPTIONS, + CBC_PARAM_INT_PROCESSTUNE, + CBC_PARAM_INT_USESOLUTION, + // End CbcGen + + // Begin CbcGenCbc + CBC_PARAM_INT_STRONGBRANCHING, + CBC_PARAM_INT_MAXNODES, + CBC_PARAM_INT_MAXNODESNOTIMPROVINGFS, + CBC_PARAM_INT_NUMBERBEFORE, + CBC_PARAM_INT_NUMBERANALYZE, + CBC_PARAM_INT_MAXSOLS, + CBC_PARAM_INT_MIPOPTIONS, + CBC_PARAM_INT_MOREMIPOPTIONS, + CBC_PARAM_INT_CUTPASS, + // End CbcGenCbc + + // Begin CbcGenOsi + CBC_PARAM_INT_MAXHOTITS, + // End CbcGenOsi + + // Begin used in Cbc + CBC_PARAM_STR_DIRECTION = 201, + CBC_PARAM_STR_ERRORSALLOWED, + CBC_PARAM_STR_INTPRINT, + // End used in Cbc + + // Begin CbcGen + CBC_PARAM_STR_NODESTRATEGY = 301, + CBC_PARAM_STR_BRANCHSTRATEGY, + CBC_PARAM_STR_CUTSSTRATEGY, + CBC_PARAM_STR_HEURISTICSTRATEGY, + CBC_PARAM_STR_USECGRAPH, + CBC_PARAM_STR_CLIQUECUTS, + CBC_PARAM_STR_ODDWHEELCUTS, + CBC_PARAM_STR_CLQSTRENGTHENING, + CBC_PARAM_STR_GOMORYCUTS, + CBC_PARAM_STR_PROBINGCUTS, + CBC_PARAM_STR_KNAPSACKCUTS, + CBC_PARAM_STR_REDSPLITCUTS, + CBC_PARAM_STR_ROUNDING, + CBC_PARAM_STR_SOLVER, + CBC_PARAM_STR_BRANCHPRIORITY, + CBC_PARAM_STR_FLOWCUTS, + CBC_PARAM_STR_MIXEDCUTS, + CBC_PARAM_STR_TWOMIRCUTS, + CBC_PARAM_STR_PREPROCESS, + CBC_PARAM_STR_FPUMP, + CBC_PARAM_STR_GREEDY, + CBC_PARAM_STR_COMBINE, + CBC_PARAM_STR_PROXIMITY, + CBC_PARAM_STR_LOCALTREE, + CBC_PARAM_STR_SOS, + CBC_PARAM_STR_LANDPCUTS, + CBC_PARAM_STR_RINS, + CBC_PARAM_STR_RESIDCUTS, + CBC_PARAM_STR_RENS, + CBC_PARAM_STR_DIVINGS, + CBC_PARAM_STR_DIVINGC, + CBC_PARAM_STR_DIVINGF, + CBC_PARAM_STR_DIVINGG, + CBC_PARAM_STR_DIVINGL, + CBC_PARAM_STR_DIVINGP, + CBC_PARAM_STR_DIVINGV, + CBC_PARAM_STR_DINS, + CBC_PARAM_STR_PIVOTANDFIX, + CBC_PARAM_STR_RANDROUND, + CBC_PARAM_STR_NAIVE, + CBC_PARAM_STR_ZEROHALFCUTS, + CBC_PARAM_STR_CPX, + CBC_PARAM_STR_CROSSOVER2, + CBC_PARAM_STR_PIVOTANDCOMPLEMENT, + CBC_PARAM_STR_VND, + CBC_PARAM_STR_LAGOMORYCUTS, + CBC_PARAM_STR_LATWOMIRCUTS, + CBC_PARAM_STR_REDSPLIT2CUTS, + CBC_PARAM_STR_GMICUTS, + CBC_PARAM_STR_CUTOFF_CONSTRAINT, + CBC_PARAM_STR_DW, + CBC_PARAM_STR_ORBITAL, + CBC_PARAM_STR_PREPROCNAMES, + CBC_PARAM_STR_SOSPRIORITIZE, + CBC_PARAM_STR_TIME_MODE, + // End CbcGen + + // Begin used in Clp + CBC_PARAM_ACTION_DIRECTORY = 401, + CBC_PARAM_ACTION_DIRSAMPLE, + CBC_PARAM_ACTION_DIRNETLIB, + CBC_PARAM_ACTION_DIRMIPLIB, + CBC_PARAM_ACTION_IMPORT, + CBC_PARAM_ACTION_EXPORT, + CBC_PARAM_ACTION_RESTORE, + CBC_PARAM_ACTION_SAVE, + CBC_PARAM_ACTION_MAXIMIZE, + CBC_PARAM_ACTION_MINIMIZE, + CBC_PARAM_ACTION_EXIT, + CBC_PARAM_ACTION_STDIN, + CBC_PARAM_ACTION_UNITTEST, + CBC_PARAM_ACTION_SOLUTION, + CBC_PARAM_ACTION_SAVESOL, + CBC_PARAM_ACTION_HELP, + CBC_PARAM_ACTION_REVERSE, + CBC_PARAM_ACTION_STATISTICS, + CBC_PARAM_ACTION_PRINTMASK, + CBC_PARAM_ACTION_ENVIRONMENT, + CBC_PARAM_ACTION_GMPL_SOLUTION, + CBC_PARAM_ACTION_DUMMY, + + CBC_PARAM_ACTION_BAB = 501, + // End Used in Clp + CBC_PARAM_ACTION_DEBUG, + CBC_PARAM_ACTION_MIPLIB, + CBC_PARAM_ACTION_STRENGTHEN, + CBC_PARAM_ACTION_PRIORITYIN, + CBC_PARAM_ACTION_MIPSTART, + CBC_PARAM_ACTION_USERCBC, + CBC_PARAM_ACTION_DOHEURISTIC, + CBC_PARAM_ACTION_NEXTBESTSOLUTION, + CBC_PARAM_ACTION_CSVSTATISTICS, + + CBC_PARAM_NOTUSED_OSLSTUFF = 601, + CBC_PARAM_NOTUSED_CBCSTUFF, + + CBC_PARAM_NOTUSED_INVALID = 1000 +}; + +/// Very simple class for setting parameters + +class CBCLIB_EXPORT CbcParam { + +public: + /**@name Constructor and destructor */ + //@{ + /// Constructors + CbcParam(); + CbcParam(std::string name, std::string help, double lower, double upper, + CbcParameterType type, int display = 2); + CbcParam(std::string name, std::string help, int lower, int upper, + CbcParameterType type, int display = 2); + // Other strings will be added by insert + CbcParam(std::string name, std::string help, std::string firstValue, + CbcParameterType type, int whereUsed = 7, int display = 2); + // Action + CbcParam(std::string name, std::string help, CbcParameterType type, + int whereUsed = 7, int display = 2); + /// Copy constructor. + CbcParam(const CbcParam &); + /// Assignment operator. This copies the data + CbcParam &operator=(const CbcParam &rhs); + /// Destructor + ~CbcParam(); + //@} + + /**@name stuff */ + //@{ + /// Insert string (only valid for keywords) + void append(std::string keyWord); + /// Returns name + inline std::string name() const { return name_; }; + /// Returns short help + inline std::string shortHelp() const { return shortHelp_; }; + /// Returns long help + inline std::string longHelp() const { return longHelp_; } + /// Returns set of valid strings + inline const std::vector &definedKeywords() const { + return definedKeyWords_; + } + /// Returns the lower bound for a double-valued parameter + inline double lowerDoubleValue() const { return lowerDoubleValue_; } + /// Returns the upper bound for a double-valued parameter + inline double upperDoubleValue() const { return upperDoubleValue_; } + /// Returns the lower bound for an int-valued parameter + inline int lowerIntValue() const { return lowerIntValue_; } + /// Returns the upper bound for an int-valued parameter + inline int upperIntValue() const { return upperIntValue_; } + /// Gets a double parameter + double doubleParameter(OsiSolverInterface *model) const; + /// Gets a double parameter + double doubleParameter(CbcModel &model) const; + /// Sets a double parameter (nonzero code if error) + int setDoubleParameter(OsiSolverInterface *model, double value, + bool doPrinting = false); + /// Sets a double parameter (nonzero code if error) + int setDoubleParameter(CbcModel &model, double value, + bool doPrinting = false); + /// Sets double parameter and returns printable string and error code + std::string setDoubleParameterWithMessage(OsiSolverInterface *model, + double value, int &returnCode); + /// Sets double parameter and returns printable string and error code + std::string setDoubleParameterWithMessage(CbcModel &model, double value, + int &returnCode); + inline double doubleValue() const { return doubleValue_; } + /// Sets double value + void setDoubleValue(double value); + /// Sets double value with message + std::string setDoubleValueWithMessage(double value); + /// Checks a double parameter (nonzero code if error) + int checkDoubleParameter(double value) const; + /// Gets a int parameter + int intParameter(OsiSolverInterface *model) const; + /// Gets a int parameter + int intParameter(CbcModel &model) const; + /// Sets a int parameter (nonzero code if error) + int setIntParameter(CbcModel &model, int value, + bool doPrinting = false); + /// Sets a int parameter (nonzero code if error) + int setIntParameter(OsiSolverInterface *model, int value, + bool doPrinting = false); + /// Sets int parameter and returns printable string and error code + std::string setIntParameterWithMessage(OsiSolverInterface *model, int value, + int &returnCode); + /// Sets int parameter and returns printable string and error code + std::string setIntParameterWithMessage(CbcModel &model, int value, + int &returnCode); + /// Gets int value + inline int intValue() const { return intValue_; } + /// Sets int value + void setIntValue(int value); + /// Sets int value with message + std::string setIntValueWithMessage(int value); + /// Gets string value + inline std::string stringValue() const { return stringValue_; } + /// Sets string value + void setStringValue(std::string value); + /// Returns name which could match + std::string matchName() const; + /// Returns length of name for ptinting + int lengthMatchName() const; + /// Returns 1 if matches minimum, 2 if matches less, 0 if not matched + int matches(std::string input) const; + /// Returns parameter option which matches (-1 if none) + int parameterOption(std::string check) const; + /// Prints parameter options + void printOptions() const; + /// Returns current parameter option + inline std::string currentOption() const { + return definedKeyWords_[currentKeyWord_]; + } + /// Sets current parameter option + void setCurrentOption(int value, bool printIt = false); + /// Sets current parameter option using string + void setCurrentOption(const std::string value); + /// Sets current parameter option and returns printable string + std::string setCurrentOptionWithMessage(int value); + /// Sets current parameter option using string with message + std::string setCurrentOptionWithMessage(const std::string value); + /// Returns current parameter option position + int currentOptionAsInteger() const; + /** Returns current parameter option position + but if fake keyword returns a fake value and sets + fakeInteger to true value. If not fake then fakeInteger is + -COIN_INT_MAX + */ + int currentOptionAsInteger(int &fakeInteger) const; + /// type + inline CbcParameterType type() const { return type_; } + /// whether to display + inline bool displayThis() const { return display_; } + /// Set Long help + inline void setLonghelp(const std::string help) { longHelp_ = help; } + /// Print Long help + void printLongHelp() const; + /// Print action and string + void printString() const; + /// type for classification + inline int indexNumber() const { return indexNumber_; } + /** 7 if used everywhere, + 1 - used by clp + 2 - used by cbc + 4 - used by ampl + */ + inline int whereUsed() const { return whereUsed_; } + /// Gets value of fake keyword + inline int fakeKeyWord() const { return fakeKeyWord_; } + /// Sets value of fake keyword + inline void setFakeKeyWord(int value, int fakeValue) { + fakeKeyWord_ = value; + fakeValue_ = fakeValue; + } + /// Sets value of fake keyword to current size of keywords + void setFakeKeyWord(int fakeValue); + +private: + /// gutsOfConstructor + void gutsOfConstructor(); + //@} + ////////////////// data ////////////////// +private: + /**@name data + We might as well throw all type data in - could derive? + */ + //@{ + // Type see CbcParameterType + CbcParameterType type_; + /// If double == okay + double lowerDoubleValue_; + double upperDoubleValue_; + /// If int == okay + int lowerIntValue_; + int upperIntValue_; + // Length of name + unsigned int lengthName_; + // Minimum match + unsigned int lengthMatch_; + /// set of valid strings + std::vector definedKeyWords_; + /// Name + std::string name_; + /// Short help + std::string shortHelp_; + /// Long help + std::string longHelp_; + /// Action + CbcParameterType action_; + /// Current keyWord (if a keyword parameter) + int currentKeyWord_; + /// Display on ? + bool display_; + /// Integer parameter - current value + int intValue_; + /// Double parameter - current value + double doubleValue_; + /// String parameter - current value + std::string stringValue_; + /// index number to use for display purposes + int indexNumber_; + /** 7 if used everywhere, + 1 - used by clp + 2 - used by cbc + 4 - used by ampl + */ + int whereUsed_; + /** If >=0 then integers allowed as a fake keyword + So minusnnnn would got to -nnnn in currentKeyword_ + and plusnnnn would go to fakeKeyword_+nnnn + */ + int fakeKeyWord_; + /// Return this as main value if an integer + int fakeValue_; + //@} + //@} +}; + +CBCLIB_EXPORT +void setCbcPrinting(bool yesNo); + +#define CBCMAXPARAMETERS 250 +/* + Subroutine to establish the cbc parameter array. See the description of + class CbcParam for details. +*/ +CBCLIB_EXPORT +void establishCbcParams(std::vector ¶ms); +// Given a parameter type - returns its number in list +CBCLIB_EXPORT +int whichCbcParam(const CbcParameterType &name, + const std::vector ¶meters); + +#endif /* CbcParam_H */ + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 + */ diff --git a/src/Attic/CbcSolver.cpp b/src/Attic/CbcSolver.cpp new file mode 100644 index 000000000..4763408ca --- /dev/null +++ b/src/Attic/CbcSolver.cpp @@ -0,0 +1,13420 @@ +// Copyright (C) 2007, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +/*! \file CbcSolver.cpp + \brief Second level routines for the cbc stand-alone solver. +*/ +#include "CbcConfig.h" +#include "CoinPragma.hpp" + +#include +#include +#include +#include +#include +#include +#include +#ifdef HAVE_SIGNAL_H +#ifdef HAVE_EXECINFO_H +#include +#include +void CbcCrashHandler( int sig ); +#endif +#endif + +#include "CoinPragma.hpp" +#include "CoinHelperFunctions.hpp" + +#include "CoinMpsIO.hpp" +#include "CoinModel.hpp" + +#include "ClpFactorization.hpp" +#include "ClpQuadraticObjective.hpp" +#include "CoinTime.hpp" +#include "ClpSimplex.hpp" +#include "ClpSimplexOther.hpp" +#include "ClpSolve.hpp" +#include "ClpMessage.hpp" +#include "ClpPackedMatrix.hpp" +#include "ClpPlusMinusOneMatrix.hpp" +#include "ClpNetworkMatrix.hpp" +#include "ClpDualRowSteepest.hpp" +#include "ClpDualRowDantzig.hpp" +#include "ClpPEDualRowSteepest.hpp" +#include "ClpPEDualRowDantzig.hpp" +#include "ClpPEPrimalColumnSteepest.hpp" +#include "ClpPEPrimalColumnDantzig.hpp" +#include "ClpLinearObjective.hpp" +#include "ClpPrimalColumnSteepest.hpp" +#include "ClpPrimalColumnDantzig.hpp" + +#include "ClpPresolve.hpp" +#ifndef COIN_HAS_CBC +#define COIN_HAS_CBC +#endif +#ifndef COIN_HAS_CLP +#define COIN_HAS_CLP +#endif +#include "CbcOrClpParam.hpp" +#include "OsiRowCutDebugger.hpp" +#include "OsiChooseVariable.hpp" +#include "OsiAuxInfo.hpp" +#include "CbcMipStartIO.hpp" +#include "CbcMessage.hpp" +// for printing +#ifndef CLP_OUTPUT_FORMAT +#define CLP_OUTPUT_FORMAT % 15.8g +#endif +#define CLP_QUOTE(s) CLP_STRING(s) +#define CLP_STRING(s) #s + +#include "CbcSolverHeuristics.hpp" +#ifdef CBC_HAS_GLPK +#include "glpk.h" +extern COINUTILSLIB_EXPORT glp_tran *cbc_glp_tran; +extern COINUTILSLIB_EXPORT glp_prob *cbc_glp_prob; +#else +#define GLP_UNDEF 1 +#define GLP_FEAS 2 +#define GLP_INFEAS 3 +#define GLP_NOFEAS 4 +#define GLP_OPT 5 +#endif + +#ifndef CBC_QUIET +#define CBC_QUIET 0 +#endif + +//#define USER_HAS_FAKE_CLP +//#define USER_HAS_FAKE_CBC +//#define NEW_DEBUG_AND_FILL // use this to make it easier to trap unset + +#ifdef NEW_DEBUG_AND_FILL +#include +#include +#include +void *operator new(size_t size) +{ + void *p = malloc(size); + char *xx = (char *)p; + memset(xx, 0x20, size); + return p; +} +void operator delete(void *p) throw() +{ + free(p); +} +#endif // end NEW_DEBUG +//#define CLP_MALLOC_STATISTICS + +#ifdef CLP_MALLOC_STATISTICS +#include +#include +#include +#include "stolen_from_ekk_malloc.cpp" +static double malloc_times = 0.0; +static double malloc_total = 0.0; +static int malloc_amount[] = { 0, 32, 128, 256, 1024, 4096, 16384, 65536, 262144, INT_MAX }; +static int malloc_n = 10; +double malloc_counts[10] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; +bool malloc_counts_on = true; +void *operator new(size_t size) throw(std::bad_alloc) +{ + malloc_times++; + malloc_total += size; + int i; + for (i = 0; i < malloc_n; i++) { + if ((int)size <= malloc_amount[i]) { + malloc_counts[i]++; + break; + } + } +#ifdef DEBUG_MALLOC + void *p; + if (malloc_counts_on) + p = stolen_from_ekk_mallocBase(size); + else + p = malloc(size); +#else + void *p = malloc(size); +#endif + //char * xx = (char *) p; + //memset(xx,0,size); + // Initialize random seed + //CoinSeedRandom(987654321); + return p; +} +void operator delete(void *p) throw() +{ +#ifdef DEBUG_MALLOC + if (malloc_counts_on) + stolen_from_ekk_freeBase(p); + else + free(p); +#else + free(p); +#endif +} +static void malloc_stats2() +{ + double average = malloc_total / malloc_times; + printf("count %g bytes %g - average %g\n", malloc_times, malloc_total, average); + for (int i = 0; i < malloc_n; i++) + printf("%g ", malloc_counts[i]); + printf("\n"); + malloc_times = 0.0; + malloc_total = 0.0; + memset(malloc_counts, 0, sizeof(malloc_counts)); + // print results +} +#else //CLP_MALLOC_STATISTICS +//void stolen_from_ekk_memory(void * dummy,int type) +//{ +//} +//bool malloc_counts_on=false; +#endif //CLP_MALLOC_STATISTICS + +//#define DMALLOC +#ifdef DMALLOC +#include "dmalloc.h" +#endif + +#ifdef WSSMP_BARRIER +#define FOREIGN_BARRIER +#endif + +#ifdef UFL_BARRIER +#define FOREIGN_BARRIER +#endif + +#ifdef TAUCS_BARRIER +#define FOREIGN_BARRIER +#endif + +static int initialPumpTune = -1; +#include "CoinWarmStartBasis.hpp" + +#include "OsiSolverInterface.hpp" +#include "OsiCuts.hpp" +#include "OsiRowCut.hpp" +#include "OsiColCut.hpp" + +#ifndef COIN_HAS_LINK +#define COIN_HAS_LINK +#endif +#ifdef COIN_HAS_LINK +#include "CbcLinked.hpp" +#endif + +#include "CglCliqueStrengthening.hpp" +#include "CglBKClique.hpp" +#include "CglOddWheel.hpp" +#include "CglMessage.hpp" + +#include "CglPreProcess.hpp" +#include "CglCutGenerator.hpp" +#include "CglGomory.hpp" +#include "CglProbing.hpp" +#include "CglKnapsackCover.hpp" +#include "CglRedSplit.hpp" +#include "CglRedSplit2.hpp" +#include "CglGMI.hpp" +#include "CglClique.hpp" +#include "CglFlowCover.hpp" +#include "CglMixedIntegerRounding2.hpp" +#include "CglTwomir.hpp" +#include "CglDuplicateRow.hpp" +#include "CglStored.hpp" +#include "CglLandP.hpp" +#include "CglResidualCapacity.hpp" +#include "CglZeroHalf.hpp" +#if DEBUG_PREPROCESS >1 +extern double *debugSolution; +extern int debugNumberColumns; +#endif +#include "CbcModel.hpp" +#include "CbcHeuristic.hpp" +#include "CbcHeuristicLocal.hpp" +#include "CbcHeuristicPivotAndFix.hpp" +//#include "CbcHeuristicPivotAndComplement.hpp" +#include "CbcHeuristicRandRound.hpp" +#include "CbcHeuristicGreedy.hpp" +#include "CbcHeuristicFPump.hpp" +#include "CbcHeuristicRINS.hpp" +#include "CbcHeuristicDiveCoefficient.hpp" +#include "CbcHeuristicDiveFractional.hpp" +#include "CbcHeuristicDiveGuided.hpp" +#include "CbcHeuristicDiveVectorLength.hpp" +#include "CbcHeuristicDivePseudoCost.hpp" +#include "CbcHeuristicDiveLineSearch.hpp" +#include "CbcTreeLocal.hpp" +#include "CbcCompareActual.hpp" +#include "CbcCompareObjective.hpp" +#include "CbcBranchActual.hpp" +#include "CbcBranchLotsize.hpp" +#include "CbcOrClpParam.hpp" +#include "CbcCutGenerator.hpp" +#include "CbcStrategy.hpp" +#include "CbcBranchCut.hpp" + +#include "OsiClpSolverInterface.hpp" + +#include "CbcSolverAnalyze.hpp" +#include "CbcSolverExpandKnapsack.hpp" + +#include "CbcSolver.hpp" + +//#define IN_BRANCH_AND_BOUND (0x01000000|262144) +#define IN_BRANCH_AND_BOUND (0x01000000 | 262144 | 128 | 1024 | 2048) +//#define IN_BRANCH_AND_BOUND (0x01000000|262144|128) + +/* + CbcStopNow class definitions. +*/ + +CbcStopNow::CbcStopNow() +{ +} +CbcStopNow::~CbcStopNow() +{ +} +// Copy constructor +CbcStopNow::CbcStopNow(const CbcStopNow &) +{ +} +// Assignment operator +CbcStopNow & +CbcStopNow::operator=(const CbcStopNow &rhs) +{ + if (this != &rhs) { + } + return *this; +} +// Clone +CbcStopNow * +CbcStopNow::clone() const +{ + return new CbcStopNow(*this); +} + +/* + CbcUser class definitions. +*/ + +// User stuff (base class) +CbcUser::CbcUser() + : coinModel_(NULL) + , userName_("null") +{ +} +CbcUser::~CbcUser() +{ + delete coinModel_; +} +// Copy constructor +CbcUser::CbcUser(const CbcUser &rhs) +{ + if (rhs.coinModel_) + coinModel_ = new CoinModel(*rhs.coinModel_); + else + coinModel_ = NULL; + userName_ = rhs.userName_; +} +// Assignment operator +CbcUser & +CbcUser::operator=(const CbcUser &rhs) +{ + if (this != &rhs) { + if (rhs.coinModel_) + coinModel_ = new CoinModel(*rhs.coinModel_); + else + coinModel_ = NULL; + userName_ = rhs.userName_; + } + return *this; +} + +static void putBackOtherSolutions(CbcModel *presolvedModel, CbcModel *model, + CglPreProcess *preProcess) +{ + int numberSolutions = presolvedModel->numberSavedSolutions(); + int numberColumns = presolvedModel->getNumCols(); + if (numberSolutions > 1) { + model->deleteSolutions(); + double *bestSolution = CoinCopyOfArray(presolvedModel->bestSolution(), numberColumns); + //double cutoff = presolvedModel->getCutoff(); + double objectiveValue = presolvedModel->getObjValue(); + //model->createSpaceForSavedSolutions(numberSolutions-1); + for (int iSolution = numberSolutions - 1; iSolution >= 0; iSolution--) { + presolvedModel->setCutoff(COIN_DBL_MAX); + presolvedModel->solver()->setColSolution(presolvedModel->savedSolution(iSolution)); + //presolvedModel->savedSolutionObjective(iSolution)); + preProcess->postProcess(*presolvedModel->solver(), false); + model->setBestSolution(preProcess->originalModel()->getColSolution(), model->solver()->getNumCols(), + presolvedModel->savedSolutionObjective(iSolution)); + } + presolvedModel->setBestObjectiveValue(objectiveValue); + presolvedModel->solver()->setColSolution(bestSolution); + //presolvedModel->setBestSolution(bestSolution,numberColumns,objectiveValue); + } +} + +// For when number of column is messed up e.g. BiLinear +static int numberPrintingColumns(const OsiSolverInterface *solver) +{ +#ifdef COIN_HAS_LINK + const OsiSolverLink *linkSolver = dynamic_cast< const OsiSolverLink * >(solver); + if (!linkSolver) + return solver->getNumCols(); + return linkSolver->coinModel()->numberColumns(); +#else + return solver->getNumCols(); +#endif +} + +/* + CbcSolver class definitions +*/ + +CbcSolver::CbcSolver() + : babModel_(NULL) + , userFunction_(NULL) + , statusUserFunction_(NULL) + , originalSolver_(NULL) + , originalCoinModel_(NULL) + , cutGenerator_(NULL) + , numberUserFunctions_(0) + , numberCutGenerators_(0) + , startTime_(CoinCpuTime()) + , doMiplib_(false) + , noPrinting_(false) + , readMode_(1) +{ + callBack_ = new CbcStopNow(); + fillParameters(); +} +CbcSolver::CbcSolver(const OsiClpSolverInterface &solver) + : babModel_(NULL) + , userFunction_(NULL) + , statusUserFunction_(NULL) + , originalSolver_(NULL) + , originalCoinModel_(NULL) + , cutGenerator_(NULL) + , numberUserFunctions_(0) + , numberCutGenerators_(0) + , startTime_(CoinCpuTime()) + , doMiplib_(false) + , noPrinting_(false) + , readMode_(1) +{ + callBack_ = new CbcStopNow(); + model_ = CbcModel(solver); + fillParameters(); +} +CbcSolver::CbcSolver(const CbcModel &solver) + : babModel_(NULL) + , userFunction_(NULL) + , statusUserFunction_(NULL) + , originalSolver_(NULL) + , originalCoinModel_(NULL) + , cutGenerator_(NULL) + , numberUserFunctions_(0) + , numberCutGenerators_(0) + , startTime_(CoinCpuTime()) + , doMiplib_(false) + , noPrinting_(false) + , readMode_(1) +{ + callBack_ = new CbcStopNow(); + model_ = solver; + fillParameters(); +} +CbcSolver::~CbcSolver() +{ + int i; + for (i = 0; i < numberUserFunctions_; i++) + delete userFunction_[i]; + delete[] userFunction_; + for (i = 0; i < numberCutGenerators_; i++) + delete cutGenerator_[i]; + delete[] cutGenerator_; + delete[] statusUserFunction_; + delete originalSolver_; + delete originalCoinModel_; + delete babModel_; + delete callBack_; +} +// Copy constructor +CbcSolver::CbcSolver(const CbcSolver &rhs) + : model_(rhs.model_) + , babModel_(NULL) + , userFunction_(NULL) + , statusUserFunction_(NULL) + , cutGenerator_(new CglCutGenerator *[rhs.numberCutGenerators()]) + , numberUserFunctions_(rhs.numberUserFunctions_) + , numberCutGenerators_(rhs.numberCutGenerators()) + , startTime_(CoinCpuTime()) + , doMiplib_(rhs.doMiplib_) + , noPrinting_(rhs.noPrinting_) + , readMode_(rhs.readMode_) +{ + fillParameters(); + if (rhs.babModel_) + babModel_ = new CbcModel(*rhs.babModel_); + userFunction_ = new CbcUser *[numberUserFunctions_]; + int i; + for (i = 0; i < numberUserFunctions_; i++) + userFunction_[i] = rhs.userFunction_[i]->clone(); + this->parameters_ = rhs.parameters_; + for (i = 0; i < numberCutGenerators_; i++) + cutGenerator_[i] = rhs.cutGenerator_[i]->clone(); + callBack_ = rhs.callBack_->clone(); + originalSolver_ = NULL; + if (rhs.originalSolver_) { + OsiSolverInterface *temp = rhs.originalSolver_->clone(); + originalSolver_ = dynamic_cast< OsiClpSolverInterface * >(temp); + assert(originalSolver_); + } + originalCoinModel_ = NULL; + if (rhs.originalCoinModel_) + originalCoinModel_ = new CoinModel(*rhs.originalCoinModel_); +} +// Assignment operator +CbcSolver & +CbcSolver::operator=(const CbcSolver &rhs) +{ + if (this != &rhs) { + int i; + for (i = 0; i < numberUserFunctions_; i++) + delete userFunction_[i]; + delete[] userFunction_; + for (i = 0; i < numberCutGenerators_; i++) + delete cutGenerator_[i]; + delete[] statusUserFunction_; + delete originalSolver_; + delete originalCoinModel_; + statusUserFunction_ = NULL; + delete babModel_; + delete callBack_; + numberUserFunctions_ = rhs.numberUserFunctions_; + startTime_ = rhs.startTime_; + this->parameters_ = rhs.parameters_; + for (i = 0; i < numberCutGenerators_; i++) + cutGenerator_[i] = rhs.cutGenerator_[i]->clone(); + noPrinting_ = rhs.noPrinting_; + readMode_ = rhs.readMode_; + doMiplib_ = rhs.doMiplib_; + model_ = rhs.model_; + if (rhs.babModel_) + babModel_ = new CbcModel(*rhs.babModel_); + else + babModel_ = NULL; + userFunction_ = new CbcUser *[numberUserFunctions_]; + for (i = 0; i < numberUserFunctions_; i++) + userFunction_[i] = rhs.userFunction_[i]->clone(); + callBack_ = rhs.callBack_->clone(); + originalSolver_ = NULL; + if (rhs.originalSolver_) { + OsiSolverInterface *temp = rhs.originalSolver_->clone(); + originalSolver_ = dynamic_cast< OsiClpSolverInterface * >(temp); + assert(originalSolver_); + } + originalCoinModel_ = NULL; + if (rhs.originalCoinModel_) + originalCoinModel_ = new CoinModel(*rhs.originalCoinModel_); + } + return *this; +} +// Get int value +int CbcSolver::intValue(CbcOrClpParameterType type) const +{ + return parameters_[whichParam(type, parameters_)].intValue(); +} +// Set int value +void CbcSolver::setIntValue(CbcOrClpParameterType type, int value) +{ + parameters_[whichParam(type, parameters_)].setIntValue(value); +} +// Get double value +double CbcSolver::doubleValue(CbcOrClpParameterType type) const +{ + return parameters_[whichParam(type, parameters_)].doubleValue(); +} +// Set double value +void CbcSolver::setDoubleValue(CbcOrClpParameterType type, double value) +{ + parameters_[whichParam(type, parameters_)].setDoubleValue(value); +} +// User function (NULL if no match) +CbcUser *CbcSolver::userFunction(const char *name) const +{ + int i; + for (i = 0; i < numberUserFunctions_; i++) { + if (!strcmp(name, userFunction_[i]->name().c_str())) + break; + } + if (i < numberUserFunctions_) + return userFunction_[i]; + else + return NULL; +} +void CbcSolver::fillParameters() +{ + establishParams(parameters_); + const char dirsep = CoinFindDirSeparator(); + std::string directory; + std::string dirSample; + std::string dirNetlib; + std::string dirMiplib; + if (dirsep == '/') { + directory = "./"; + dirSample = "../../Data/Sample/"; + dirNetlib = "../../Data/Netlib/"; + dirMiplib = "../../Data/miplib3/"; + } else { + directory = ".\\"; + dirSample = "..\\..\\..\\..\\Data\\Sample\\"; + dirNetlib = "..\\..\\..\\..\\Data\\Netlib\\"; + dirMiplib = "..\\..\\..\\..\\Data\\miplib3\\"; + } + std::string defaultDirectory = directory; + std::string importFile = ""; + std::string exportFile = "default.mps"; + std::string importBasisFile = ""; + std::string importPriorityFile = ""; + std::string mipStartFile = ""; + std::string debugFile = ""; + std::string printMask = ""; + std::string exportBasisFile = "default.bas"; + std::string saveFile = "default.prob"; + std::string restoreFile = "default.prob"; + std::string solutionFile = "stdout"; + std::string solutionSaveFile = "solution.file"; + int doIdiot = -1; + int outputFormat = 2; + int substitution = 3; + int dualize = 3; + int preSolve = 5; + int doSprint = -1; + int testOsiParameters = -1; + int createSolver = 0; + ClpSimplex *lpSolver; + OsiClpSolverInterface *clpSolver; + if (model_.solver()) { + clpSolver = dynamic_cast< OsiClpSolverInterface * >(model_.solver()); + assert(clpSolver); + lpSolver = clpSolver->getModelPtr(); + assert(lpSolver); + } else { + lpSolver = new ClpSimplex(); + clpSolver = new OsiClpSolverInterface(lpSolver, true); + createSolver = 1; + } + parameters_[whichParam(CLP_PARAM_ACTION_BASISIN, parameters_)].setStringValue(importBasisFile); + parameters_[whichParam(CBC_PARAM_ACTION_PRIORITYIN, parameters_)].setStringValue(importPriorityFile); + parameters_[whichParam(CBC_PARAM_ACTION_MIPSTART, parameters_)].setStringValue(mipStartFile); + parameters_[whichParam(CLP_PARAM_ACTION_BASISOUT, parameters_)].setStringValue(exportBasisFile); + parameters_[whichParam(CLP_PARAM_ACTION_DEBUG, parameters_)].setStringValue(debugFile); + parameters_[whichParam(CLP_PARAM_ACTION_PRINTMASK, parameters_)].setStringValue(printMask); + parameters_[whichParam(CLP_PARAM_ACTION_DIRECTORY, parameters_)].setStringValue(directory); + parameters_[whichParam(CLP_PARAM_ACTION_DIRSAMPLE, parameters_)].setStringValue(dirSample); + parameters_[whichParam(CLP_PARAM_ACTION_DIRNETLIB, parameters_)].setStringValue(dirNetlib); + parameters_[whichParam(CBC_PARAM_ACTION_DIRMIPLIB, parameters_)].setStringValue(dirMiplib); + parameters_[whichParam(CLP_PARAM_DBL_DUALBOUND, parameters_)].setDoubleValue(lpSolver->dualBound()); + parameters_[whichParam(CLP_PARAM_DBL_DUALTOLERANCE, parameters_)].setDoubleValue(lpSolver->dualTolerance()); + parameters_[whichParam(CLP_PARAM_ACTION_EXPORT, parameters_)].setStringValue(exportFile); + parameters_[whichParam(CLP_PARAM_INT_IDIOT, parameters_)].setIntValue(doIdiot); + parameters_[whichParam(CLP_PARAM_ACTION_IMPORT, parameters_)].setStringValue(importFile); + parameters_[whichParam(CLP_PARAM_DBL_PRESOLVETOLERANCE, parameters_)].setDoubleValue(1.0e-8); + int iParam = whichParam(CLP_PARAM_INT_SOLVERLOGLEVEL, parameters_); + int value = 1; + clpSolver->messageHandler()->setLogLevel(1); + lpSolver->setLogLevel(1); + parameters_[iParam].setIntValue(value); + iParam = whichParam(CLP_PARAM_INT_LOGLEVEL, parameters_); + model_.messageHandler()->setLogLevel(value); + parameters_[iParam].setIntValue(value); + parameters_[whichParam(CLP_PARAM_INT_MAXFACTOR, parameters_)].setIntValue(lpSolver->factorizationFrequency()); + parameters_[whichParam(CLP_PARAM_INT_MAXITERATION, parameters_)].setIntValue(lpSolver->maximumIterations()); + parameters_[whichParam(CLP_PARAM_INT_OUTPUTFORMAT, parameters_)].setIntValue(outputFormat); + parameters_[whichParam(CLP_PARAM_INT_PRESOLVEPASS, parameters_)].setIntValue(preSolve); + parameters_[whichParam(CLP_PARAM_INT_PERTVALUE, parameters_)].setIntValue(lpSolver->perturbation()); + parameters_[whichParam(CLP_PARAM_DBL_PRIMALTOLERANCE, parameters_)].setDoubleValue(lpSolver->primalTolerance()); + parameters_[whichParam(CLP_PARAM_DBL_PRIMALWEIGHT, parameters_)].setDoubleValue(lpSolver->infeasibilityCost()); + parameters_[whichParam(CLP_PARAM_ACTION_RESTORE, parameters_)].setStringValue(restoreFile); + parameters_[whichParam(CLP_PARAM_ACTION_SAVE, parameters_)].setStringValue(saveFile); + //parameters_[whichParam(CLP_PARAM_DBL_TIMELIMIT,numberParameters_,parameters_)].setDoubleValue(1.0e8); + parameters_[whichParam(CBC_PARAM_DBL_TIMELIMIT_BAB, parameters_)].setDoubleValue(1.0e8); + parameters_[whichParam(CLP_PARAM_ACTION_SOLUTION, parameters_)].setStringValue(solutionFile); + parameters_[whichParam(CLP_PARAM_ACTION_NEXTBESTSOLUTION, parameters_)].setStringValue(solutionFile); + parameters_[whichParam(CLP_PARAM_ACTION_SAVESOL, parameters_)].setStringValue(solutionSaveFile); + parameters_[whichParam(CLP_PARAM_INT_SPRINT, parameters_)].setIntValue(doSprint); + parameters_[whichParam(CLP_PARAM_INT_SUBSTITUTION, parameters_)].setIntValue(substitution); + parameters_[whichParam(CLP_PARAM_INT_DUALIZE, parameters_)].setIntValue(dualize); + parameters_[whichParam(CBC_PARAM_INT_NUMBERBEFORE, parameters_)].setIntValue(model_.numberBeforeTrust()); + parameters_[whichParam(CBC_PARAM_INT_MAXNODES, parameters_)].setIntValue(model_.getMaximumNodes()); + parameters_[whichParam(CBC_PARAM_INT_STRONGBRANCHING, parameters_)].setIntValue(model_.numberStrong()); + parameters_[whichParam(CBC_PARAM_DBL_INFEASIBILITYWEIGHT, parameters_)].setDoubleValue(model_.getDblParam(CbcModel::CbcInfeasibilityWeight)); + parameters_[whichParam(CBC_PARAM_DBL_INTEGERTOLERANCE, parameters_)].setDoubleValue(model_.getDblParam(CbcModel::CbcIntegerTolerance)); + parameters_[whichParam(CBC_PARAM_DBL_INCREMENT, parameters_)].setDoubleValue(model_.getDblParam(CbcModel::CbcCutoffIncrement)); + parameters_[whichParam(CBC_PARAM_INT_TESTOSI, parameters_)].setIntValue(testOsiParameters); + parameters_[whichParam(CBC_PARAM_INT_FPUMPTUNE, parameters_)].setIntValue(1003); + initialPumpTune = 1003; +#ifdef CBC_THREAD + parameters_[whichParam(CBC_PARAM_INT_THREADS, parameters_)].setIntValue(0); +#endif + // Set up likely cut generators and defaults + parameters_[whichParam(CBC_PARAM_STR_PREPROCESS, parameters_)].setCurrentOption("sos"); + parameters_[whichParam(CBC_PARAM_INT_MIPOPTIONS, parameters_)].setIntValue(1057); + parameters_[whichParam(CBC_PARAM_INT_CUTPASSINTREE, parameters_)].setIntValue(1); + parameters_[whichParam(CBC_PARAM_INT_MOREMIPOPTIONS, parameters_)].setIntValue(-1); + parameters_[whichParam(CBC_PARAM_INT_MAXHOTITS, parameters_)].setIntValue(100); + parameters_[whichParam(CBC_PARAM_STR_CUTSSTRATEGY, parameters_)].setCurrentOption("on"); + parameters_[whichParam(CBC_PARAM_STR_HEURISTICSTRATEGY, parameters_)].setCurrentOption("on"); + parameters_[whichParam(CBC_PARAM_STR_NODESTRATEGY, parameters_)].setCurrentOption("fewest"); + parameters_[whichParam(CBC_PARAM_STR_GOMORYCUTS, parameters_)].setCurrentOption("ifmove"); + parameters_[whichParam(CBC_PARAM_STR_PROBINGCUTS, parameters_)].setCurrentOption("ifmove"); + parameters_[whichParam(CBC_PARAM_STR_KNAPSACKCUTS, parameters_)].setCurrentOption("ifmove"); + parameters_[whichParam(CBC_PARAM_STR_ZEROHALFCUTS, parameters_)].setCurrentOption("ifmove"); + parameters_[whichParam(CBC_PARAM_STR_REDSPLITCUTS, parameters_)].setCurrentOption("off"); + parameters_[whichParam(CBC_PARAM_STR_REDSPLIT2CUTS, parameters_)].setCurrentOption("off"); + parameters_[whichParam(CBC_PARAM_STR_GMICUTS, parameters_)].setCurrentOption("off"); + parameters_[whichParam(CBC_PARAM_STR_MIXEDCUTS, parameters_)].setCurrentOption("ifmove"); + parameters_[whichParam(CBC_PARAM_STR_FLOWCUTS, parameters_)].setCurrentOption("ifmove"); + parameters_[whichParam(CBC_PARAM_STR_TWOMIRCUTS, parameters_)].setCurrentOption("ifmove"); + parameters_[whichParam(CBC_PARAM_STR_LANDPCUTS, parameters_)].setCurrentOption("off"); + parameters_[whichParam(CBC_PARAM_STR_RESIDCUTS, parameters_)].setCurrentOption("off"); + parameters_[whichParam(CBC_PARAM_STR_ROUNDING, parameters_)].setCurrentOption("on"); + parameters_[whichParam(CBC_PARAM_STR_FPUMP, parameters_)].setCurrentOption("on"); + parameters_[whichParam(CBC_PARAM_STR_GREEDY, parameters_)].setCurrentOption("on"); + parameters_[whichParam(CBC_PARAM_STR_COMBINE, parameters_)].setCurrentOption("on"); + parameters_[whichParam(CBC_PARAM_STR_CROSSOVER2, parameters_)].setCurrentOption("off"); + parameters_[whichParam(CBC_PARAM_STR_PIVOTANDCOMPLEMENT, parameters_)].setCurrentOption("off"); + parameters_[whichParam(CBC_PARAM_STR_PIVOTANDFIX, parameters_)].setCurrentOption("off"); + parameters_[whichParam(CBC_PARAM_STR_RANDROUND, parameters_)].setCurrentOption("off"); + parameters_[whichParam(CBC_PARAM_STR_NAIVE, parameters_)].setCurrentOption("off"); + parameters_[whichParam(CBC_PARAM_STR_RINS, parameters_)].setCurrentOption("off"); + parameters_[whichParam(CBC_PARAM_STR_DINS, parameters_)].setCurrentOption("off"); + parameters_[whichParam(CBC_PARAM_STR_RENS, parameters_)].setCurrentOption("off"); + parameters_[whichParam(CBC_PARAM_STR_LOCALTREE, parameters_)].setCurrentOption("off"); + parameters_[whichParam(CBC_PARAM_STR_COSTSTRATEGY, parameters_)].setCurrentOption("off"); + parameters_[whichParam(CBC_PARAM_STR_CLIQUECUTS, parameters_)].setCurrentOption("ifmove"); + parameters_[whichParam(CBC_PARAM_STR_ODDWHEELCUTS, parameters_)].setCurrentOption("ifmove"); + parameters_[whichParam(CBC_PARAM_STR_CLQSTRENGTHENING, parameters_)].setCurrentOption("after"); + parameters_[whichParam(CBC_PARAM_STR_USECGRAPH, parameters_)].setCurrentOption("on"); + parameters_[whichParam(CBC_PARAM_INT_BKPIVOTINGSTRATEGY, parameters_)].setIntValue(3); + parameters_[whichParam(CBC_PARAM_INT_BKMAXCALLS, parameters_)].setIntValue(1000); + parameters_[whichParam(CBC_PARAM_INT_BKCLQEXTMETHOD, parameters_)].setIntValue(4); + parameters_[whichParam(CBC_PARAM_INT_ODDWEXTMETHOD, parameters_)].setIntValue(2); + if (createSolver) + delete clpSolver; +} + +/* + Initialise a subset of the parameters prior to processing any input from + the user. + + Why this choice of subset? +*/ +/*! + \todo Guard/replace clp-specific code +*/ +void CbcSolver::fillValuesInSolver() +{ + OsiSolverInterface *solver = model_.solver(); + OsiClpSolverInterface *clpSolver = dynamic_cast< OsiClpSolverInterface * >(solver); + assert(clpSolver); + ClpSimplex *lpSolver = clpSolver->getModelPtr(); + + /* + Why are we reaching into the underlying solver(s) for these settings? + Shouldn't CbcSolver have its own defaults, which are then imposed on the + underlying solver? + + Coming at if from the other side, if CbcSolver had the capability to use + multiple solvers then it definitely makes sense to acquire the defaults from + the solver (on the assumption that we haven't processed command line + parameters yet, which can then override the defaults). But then it's more of + a challenge to avoid solver-specific coding here. + */ + noPrinting_ = (lpSolver->logLevel() == 0); + CoinMessageHandler *generalMessageHandler = clpSolver->messageHandler(); + generalMessageHandler->setPrefix(true); + + lpSolver->setPerturbation(50); + lpSolver->messageHandler()->setPrefix(false); + + parameters_[whichParam(CLP_PARAM_DBL_DUALBOUND, parameters_)].setDoubleValue(lpSolver->dualBound()); + parameters_[whichParam(CLP_PARAM_DBL_DUALTOLERANCE, parameters_)].setDoubleValue(lpSolver->dualTolerance()); + /* + Why are we doing this? We read the log level from parameters_, set it into + the message handlers for cbc and the underlying solver. Then we read the + log level back from the handlers and use it to set the values in + parameters_! + */ + int iParam = whichParam(CLP_PARAM_INT_SOLVERLOGLEVEL, parameters_); + int value = parameters_[iParam].intValue(); + clpSolver->messageHandler()->setLogLevel(value); + lpSolver->setLogLevel(value); + iParam = whichParam(CLP_PARAM_INT_LOGLEVEL, parameters_); + value = parameters_[iParam].intValue(); + model_.messageHandler()->setLogLevel(value); + parameters_[whichParam(CLP_PARAM_INT_LOGLEVEL, parameters_)].setIntValue(model_.logLevel()); + parameters_[whichParam(CLP_PARAM_INT_SOLVERLOGLEVEL, parameters_)].setIntValue(lpSolver->logLevel()); + parameters_[whichParam(CLP_PARAM_INT_MAXFACTOR, parameters_)].setIntValue(lpSolver->factorizationFrequency()); + parameters_[whichParam(CLP_PARAM_INT_MAXITERATION, parameters_)].setIntValue(lpSolver->maximumIterations()); + parameters_[whichParam(CLP_PARAM_INT_PERTVALUE, parameters_)].setIntValue(lpSolver->perturbation()); + parameters_[whichParam(CLP_PARAM_DBL_PRIMALTOLERANCE, parameters_)].setDoubleValue(lpSolver->primalTolerance()); + parameters_[whichParam(CLP_PARAM_DBL_PRIMALWEIGHT, parameters_)].setDoubleValue(lpSolver->infeasibilityCost()); + parameters_[whichParam(CBC_PARAM_INT_NUMBERBEFORE, parameters_)].setIntValue(model_.numberBeforeTrust()); + parameters_[whichParam(CBC_PARAM_INT_MAXNODES, parameters_)].setIntValue(model_.getMaximumNodes()); + parameters_[whichParam(CBC_PARAM_INT_STRONGBRANCHING, parameters_)].setIntValue(model_.numberStrong()); + parameters_[whichParam(CBC_PARAM_DBL_INFEASIBILITYWEIGHT, parameters_)].setDoubleValue(model_.getDblParam(CbcModel::CbcInfeasibilityWeight)); + parameters_[whichParam(CBC_PARAM_DBL_INTEGERTOLERANCE, parameters_)].setDoubleValue(model_.getDblParam(CbcModel::CbcIntegerTolerance)); + parameters_[whichParam(CBC_PARAM_DBL_INCREMENT, parameters_)].setDoubleValue(model_.getDblParam(CbcModel::CbcCutoffIncrement)); +} +// Add user function +void CbcSolver::addUserFunction(CbcUser *function) +{ + CbcUser **temp = new CbcUser *[numberUserFunctions_ + 1]; + int i; + for (i = 0; i < numberUserFunctions_; i++) + temp[i] = userFunction_[i]; + delete[] userFunction_; + userFunction_ = temp; + userFunction_[numberUserFunctions_++] = function->clone(); + delete[] statusUserFunction_; + statusUserFunction_ = NULL; +} +// Set user call back +void CbcSolver::setUserCallBack(CbcStopNow *function) +{ + delete callBack_; + callBack_ = function->clone(); +} +// Copy of model on initial load (will contain output solutions) +void CbcSolver::setOriginalSolver(OsiClpSolverInterface *originalSolver) +{ + delete originalSolver_; + OsiSolverInterface *temp = originalSolver->clone(); + originalSolver_ = dynamic_cast< OsiClpSolverInterface * >(temp); + assert(originalSolver_); +} +// Copy of model on initial load +void CbcSolver::setOriginalCoinModel(CoinModel *originalCoinModel) +{ + delete originalCoinModel_; + originalCoinModel_ = new CoinModel(*originalCoinModel); +} +// Add cut generator +void CbcSolver::addCutGenerator(CglCutGenerator *generator) +{ + CglCutGenerator **temp = new CglCutGenerator *[numberCutGenerators_ + 1]; + int i; + for (i = 0; i < numberCutGenerators_; i++) + temp[i] = cutGenerator_[i]; + delete[] cutGenerator_; + cutGenerator_ = temp; + cutGenerator_[numberCutGenerators_++] = generator->clone(); +} + +/* + The only other solver that's ever been used is cplex, and the use is + limited -- do the root with clp and all the cbc smarts, then give the + problem over to cplex to finish. Although the defines can be read in some + places to allow other options, nothing's been tested and success is + unlikely. + + CBC_OTHER_SOLVER == 1 is cplex. +*/ + +#if CBC_OTHER_SOLVER == 1 +#ifndef CBC_HAS_OSICPX +#error "Configuration did not detect OsiCpx installation." +#else +#include "OsiCpxSolverInterface.hpp" +#endif +#endif + +static void statistics(ClpSimplex *originalModel, ClpSimplex *model); +static bool maskMatches(const int *starts, char **masks, + std::string &check); +static void generateCode(CbcModel *model, const char *fileName, int type, int preProcess); +#ifdef CBC_HAS_NAUTY +// returns number of constraints added +static int nautiedConstraints(CbcModel &model, int maxPass); +#endif + +// dummy fake main programs for UserClp and UserCbc +void fakeMain(ClpSimplex &model, OsiSolverInterface &osiSolver, CbcModel &babSolver); +void fakeMain2(ClpSimplex &model, OsiClpSolverInterface &osiSolver, int options); + +// Allow for interrupts +// But is this threadsafe? (so switched off by option) + +#include "CoinSignal.hpp" +static CbcModel *currentBranchModel = NULL; + +extern "C" { +static void signal_handler(int whichSignal) +{ + if (currentBranchModel != NULL) { + currentBranchModel->sayEventHappened(); // say why stopped + if (currentBranchModel->heuristicModel()) + currentBranchModel->heuristicModel()->sayEventHappened(); + } + return; +} +} + +/* + Debug checks on special ordered sets. + + This is active only for debugging. The entire body of the routine becomes + a noop when COIN_DEVELOP is not defined. To avoid compiler warnings, the + formal parameters also need to go away. +*/ +#ifdef COIN_DEVELOP +void checkSOS(CbcModel *babModel, const OsiSolverInterface *solver) +#else +void checkSOS(CbcModel * /*babModel*/, const OsiSolverInterface * /*solver*/) +#endif +{ +#ifdef COIN_DEVELOP + if (!babModel->ownObjects()) + return; +#if COIN_DEVELOP > 2 + //const double *objective = solver->getObjCoefficients() ; + const double *columnLower = solver->getColLower(); + const double *columnUpper = solver->getColUpper(); + const double *solution = solver->getColSolution(); + //int numberRows = solver->getNumRows(); + //double direction = solver->getObjSense(); + //int iRow,iColumn; +#endif + + // Row copy + CoinPackedMatrix matrixByRow(*solver->getMatrixByRow()); + //const double * elementByRow = matrixByRow.getElements(); + //const int * column = matrixByRow.getIndices(); + //const CoinBigIndex * rowStart = matrixByRow.getVectorStarts(); + const int *rowLength = matrixByRow.getVectorLengths(); + + // Column copy + CoinPackedMatrix matrixByCol(*solver->getMatrixByCol()); + const double *element = matrixByCol.getElements(); + const int *row = matrixByCol.getIndices(); + const CoinBigIndex *columnStart = matrixByCol.getVectorStarts(); + const int *columnLength = matrixByCol.getVectorLengths(); + + const double *rowLower = solver->getRowLower(); + const double *rowUpper = solver->getRowUpper(); + OsiObject **objects = babModel->objects(); + int numberObjects = babModel->numberObjects(); + int numberColumns = solver->getNumCols(); + for (int iObj = 0; iObj < numberObjects; iObj++) { + CbcSOS *objSOS = dynamic_cast< CbcSOS * >(objects[iObj]); + if (objSOS) { + int n = objSOS->numberMembers(); + const int *which = objSOS->members(); +#if COIN_DEVELOP > 2 + const double *weight = objSOS->weights(); +#endif + int type = objSOS->sosType(); + // convexity row? + int iColumn; + iColumn = which[0]; + int j; + int convex = -1; + for (j = columnStart[iColumn]; j < columnStart[iColumn] + columnLength[iColumn]; j++) { + int iRow = row[j]; + double value = element[j]; + if (rowLower[iRow] == 1.0 && rowUpper[iRow] == 1.0 && value == 1.0) { + // possible + if (rowLength[iRow] == n) { + if (convex == -1) + convex = iRow; + else + convex = -2; + } + } + } + printf("set %d of type %d has %d members - possible convexity row %d\n", + iObj, type, n, convex); + for (int i = 0; i < n; i++) { + iColumn = which[i]; + // Column may have been added + if (iColumn < numberColumns) { + int convex2 = -1; + for (j = columnStart[iColumn]; j < columnStart[iColumn] + columnLength[iColumn]; j++) { + int iRow = row[j]; + if (iRow == convex) { + double value = element[j]; + if (value == 1.0) { + convex2 = iRow; + } + } + } + if (convex2 < 0 && convex >= 0) { + printf("odd convexity row\n"); + convex = -2; + } +#if COIN_DEVELOP > 2 + printf("col %d has weight %g and value %g, bounds %g %g\n", + iColumn, weight[i], solution[iColumn], columnLower[iColumn], + columnUpper[iColumn]); +#endif + } + } + } + } +#endif // COIN_DEVELOP +} + +static int dummyCallBack(CbcModel * /*model*/, int /*whereFrom*/) +{ + return 0; +} + +/* + Global parameters for command processing. + + These will need to be moved into an object of some sort in order to make + this set of calls thread-safe. +*/ + +// Alternative to environment +extern char *alternativeEnvironment; +extern int CbcOrClpEnvironmentIndex; + +int callCbc1(const char *input2, CbcModel &model, + int callBack(CbcModel *currentSolver, int whereFrom), + CbcSolverUsefulData ¶meterData); + +/* + Wrappers for CbcMain0, CbcMain1. The various forms of callCbc will eventually + resolve to a call to CbcMain0 followed by a call to callCbc1. +*/ +/* + Simplest calling form: supply just a string with the command options. The + wrapper creates an OsiClpSolverInterface and calls the next wrapper. +*/ +int callCbc(const std::string input2) +{ + char *input3 = CoinStrdup(input2.c_str()); + OsiClpSolverInterface solver1; + int returnCode = callCbc(input3, solver1); + free(input3); + return returnCode; +} + +int callCbc(const char *input2) +{ + { + OsiClpSolverInterface solver1; + return callCbc(input2, solver1); + } +} + +/* + Second calling form: supply the command line and an OsiClpSolverInterface. + the wrapper will create a CbcModel and call the next wrapper. +*/ + +int callCbc(const std::string input2, OsiClpSolverInterface &solver1) +{ + char *input3 = CoinStrdup(input2.c_str()); + int returnCode = callCbc(input3, solver1); + free(input3); + return returnCode; +} + +int callCbc(const char *input2, OsiClpSolverInterface &solver1) +{ + CbcModel model(solver1); + return callCbc(input2, model); +} + +/* + Third calling form: supply the command line and a CbcModel. This wrapper will + actually call CbcMain0 and then call the next set of wrappers (callCbc1) to + handle the call to CbcMain1. +*/ +int callCbc(const char *input2, CbcModel &babSolver) +{ + CbcSolverUsefulData data; +#ifndef CBC_NO_INTERRUPT + data.useSignalHandler_ = true; +#endif +#ifndef CBC_NO_PRINTING + data.noPrinting_ = false; +#endif + CbcMain0(babSolver, data); + return callCbc1(input2, babSolver, dummyCallBack, data); +} + +int callCbc(const std::string input2, CbcModel &babSolver) +{ + CbcSolverUsefulData cbcData; + cbcData.noPrinting_ = false; + char *input3 = CoinStrdup(input2.c_str()); + CbcMain0(babSolver, cbcData); + int returnCode = callCbc1(input3, babSolver, dummyCallBack, cbcData); + free(input3); + return returnCode; +} + +/* + Various overloads of callCbc1. The first pair accepts just a CbcModel and + supplements it with a dummy callback routine. The second pair allows the + user to supply a callback. See CbcMain1 for further explanation of the + callback. The various overloads of callCbc1 resolve to the final version, + which breaks the string into individual parameter strings (i.e., creates + something that looks like a standard argv vector). +*/ + +// Disabling non thread safe overloads +/* + int callCbc1(const std::string input2, CbcModel & babSolver) + { + char * input3 = CoinStrdup(input2.c_str()); + int returnCode = callCbc1(input3, babSolver); + free(input3); + return returnCode; + } + + int callCbc1(const char * input2, CbcModel & model) + { + return callCbc1(input2, model, dummyCallBack); + } + + int callCbc1(const std::string input2, CbcModel & babSolver, + int callBack(CbcModel * currentSolver, int whereFrom)) + { + char * input3 = CoinStrdup(input2.c_str()); + int returnCode = callCbc1(input3, babSolver, callBack); + free(input3); + return returnCode; + } + */ +int callCbc1(const char *input2, CbcModel &model, + int callBack(CbcModel *currentSolver, int whereFrom), + CbcSolverUsefulData ¶meterData) +{ + char *input = CoinStrdup(input2 ? input2 : ""); + size_t length = strlen(input); + bool blank = input[0] == ' '; + int n = blank ? 0 : 1; + for (size_t i = 0; i < length; i++) { + if (blank) { + // look for next non blank + if (input[i] == ' ') { + continue; + } else { + n++; + blank = false; + } + } else { + // look for next blank + if (input[i] != ' ') { + continue; + } else { + blank = true; + } + } + } + char **argv = new char *[n + 2]; + argv[0] = CoinStrdup("cbc"); + size_t i = 0; + while (input[i] == ' ') + i++; + for (int j = 0; j < n; j++) { + size_t saveI = i; + for (; i < length; i++) { + // look for next blank + if (input[i] != ' ') { + continue; + } else { + break; + } + } + input[i++] = '\0'; + argv[j + 1] = CoinStrdup(input + saveI); + while (input[i] == ' ') + i++; + } + argv[n + 1] = CoinStrdup("-quit"); + free(input); + currentBranchModel = NULL; + setCbcOrClpReadMode(1); + setCbcOrClpReadCommand(stdin); + int returnCode = CbcMain1(n + 2, const_cast< const char ** >(argv), + model, callBack, parameterData); + for (int k = 0; k < n + 2; k++) + free(argv[k]); + delete[] argv; + return returnCode; +} + +int callCbc1(const char *input2, CbcModel &model, + int callBack(CbcModel *currentSolver, int whereFrom)) +{ + CbcSolverUsefulData data; + // allow interrupts and printing +#ifndef CBC_NO_INTERRUPT + data.useSignalHandler_ = true; +#endif +#ifndef CBC_NO_PRINTING + data.noPrinting_ = false; +#endif + return callCbc1(input2, model, callBack, data); +} + +CglPreProcess *cbcPreProcessPointer = NULL; + +int CbcClpUnitTest(const CbcModel &saveModel, + const std::string &dirMiplib, int testSwitch, + const double *stuff, int argc, const char ** argv, + int callBack(CbcModel *currentSolver, int whereFrom), + CbcSolverUsefulData ¶meterData); + +//#define CBC_THREAD_SAFE +#ifdef CBC_THREAD_SAFE +// Copies of some input decoding + +static std::string +CoinReadGetCommand(int &whichArgument, int argc, const char *argv[]) +{ + std::string field; + if (whichArgument < argc) + field = argv[whichArgument++]; + else + field = "quit"; + if (field[0] == '-') + field = field.substr(1); + return field; +} +static std::string +CoinReadGetString(int &whichArgument, int argc, const char *argv[]) +{ + std::string field; + if (whichArgument < argc) + field = argv[whichArgument++]; + else + field = ""; + return field; +} +// valid 0 - okay, 1 bad, 2 not there +static int +CoinReadGetIntField(int &whichArgument, int argc, const char *argv[], int *valid) +{ + std::string field; + if (whichArgument < argc) + field = argv[whichArgument++]; + else + field = "0"; + long int value = 0; + const char *start = field.c_str(); + char *endPointer = NULL; + // check valid + value = strtol(start, &endPointer, 10); + if (*endPointer == '\0') { + *valid = 0; + } else { + *valid = 1; + std::cout << "String of " << field; + } + return static_cast< int >(value); +} +static double +CoinReadGetDoubleField(int &whichArgument, int argc, const char *argv[], int *valid) +{ + std::string field; + if (whichArgument < argc) + field = argv[whichArgument++]; + else + field = "0.0"; + double value = 0.0; + const char *start = field.c_str(); + char *endPointer = NULL; + // check valid + value = strtod(start, &endPointer); + if (*endPointer == '\0') { + *valid = 0; + } else { + *valid = 1; + std::cout << "String of " << field; + } + return value; +} +// Redefine all +#define CoinReadGetCommand(x, y) CoinReadGetCommand(whichArgument, x, y) +#define CoinReadGetString(x, y) CoinReadGetString(whichArgument, x, y) +#define CoinReadGetIntField(x, y, z) CoinReadGetIntField(whichArgument, x, y, z) +#define CoinReadGetDoubleField(x, y, z) CoinReadGetDoubleField(whichArgument, x, y, z) +#endif +// Default Constructor +CbcSolverUsefulData::CbcSolverUsefulData() +{ + totalTime_ = 0.0; + noPrinting_ = true; + printWelcome_ = true; + useSignalHandler_ = false; + establishParams(parameters_); +#if 0 + int more2 = parameters_[whichParam(CBC_PARAM_INT_MOREMOREMIPOPTIONS, parameters_)].intValue(); + printf("more2 %d\n",more2); + for (int i = 0; i < (int)parameters_.size(); i++) { + printf("%d param type %d name %s\n",i,parameters_[i].type(), + parameters_[i].matchName().c_str()); + } + more2 = parameters_[whichParam(CBC_PARAM_INT_MOREMOREMIPOPTIONS, parameters_)].intValue(); + printf("more2 %d\n",more2); +#endif +} + +/* Copy constructor . + */ +CbcSolverUsefulData::CbcSolverUsefulData(const CbcSolverUsefulData &rhs) +{ + totalTime_ = rhs.totalTime_; + noPrinting_ = rhs.noPrinting_; + useSignalHandler_ = rhs.useSignalHandler_; + this->parameters_ = rhs.parameters_; +} + +// Assignment operator +CbcSolverUsefulData &CbcSolverUsefulData::operator=(const CbcSolverUsefulData &rhs) +{ + if (this != &rhs) { + totalTime_ = rhs.totalTime_; + noPrinting_ = rhs.noPrinting_; + useSignalHandler_ = rhs.useSignalHandler_; + this->parameters_ = rhs.parameters_; + } + return *this; +} + +// Destructor +CbcSolverUsefulData::~CbcSolverUsefulData() +{ +} + +static bool ends_with(std::string const &value, std::string const &ending) +{ + if (ending.size() > value.size()) + return false; + return std::equal(ending.rbegin(), ending.rend(), value.rbegin()); +} +static void printGeneralMessage(CbcModel &model, const char *message); +// Version of CbcMain1 without callBack +int CbcMain1(int argc, const char *argv[], + CbcModel &model, + CbcSolverUsefulData ¶meterData) +{ + return CbcMain1(argc,argv,model,dummyCallBack,parameterData); +} +/* + Meaning of whereFrom: + 1 after initial solve by dualsimplex etc + 2 after preprocessing + 3 just before branchAndBound (so user can override) + 4 just after branchAndBound (before postprocessing) + 5 after postprocessing + 6 after a user called heuristic phase +*/ +int CbcMain1(int argc, const char *argv[], + CbcModel &model, + int callBack(CbcModel *currentSolver, int whereFrom), + CbcSolverUsefulData ¶meterData) +{ + std::vector< CbcOrClpParam > parameters_(parameterData.parameters_); + double totalTime = parameterData.totalTime_; + bool noPrinting = parameterData.noPrinting_; + bool useSignalHandler = parameterData.useSignalHandler_; + CbcModel &model_ = model; + CglPreProcess *preProcessPointer = NULL; +#ifdef CBC_THREAD_SAFE + // Initialize argument + int whichArgument = 1; +#endif + // Meaning 0 - start at very beginning + // 1 start at beginning of preprocessing + // 2 start at beginning of branch and bound +#ifndef CBC_USE_INITIAL_TIME +#define CBC_USE_INITIAL_TIME 1 +#endif +#if CBC_USE_INITIAL_TIME == 0 + if (model_.useElapsedTime()) + model_.setDblParam(CbcModel::CbcStartSeconds, CoinGetTimeOfDay()); + else + model_.setDblParam(CbcModel::CbcStartSeconds, CoinCpuTime()); +#endif + CbcModel *babModel_ = NULL; + int returnMode = 1; + setCbcOrClpReadMode(1); + int statusUserFunction_[1]; + int numberUserFunctions_ = 1; // to allow for ampl + // Statistics + double statistics_seconds = 0.0, statistics_obj = 0.0; + double statistics_sys_seconds = 0.0, statistics_elapsed_seconds = 0.0; + CoinWallclockTime(); + double statistics_continuous = 0.0, statistics_tighter = 0.0; + double statistics_cut_time = 0.0; + int statistics_nodes = 0, statistics_iterations = 0; + int statistics_nrows = 0, statistics_ncols = 0; + int statistics_nprocessedrows = 0, statistics_nprocessedcols = 0; + std::string statistics_result; + int *statistics_number_cuts = NULL; + const char **statistics_name_generators = NULL; + int statistics_number_generators = 0; + int currentBestSolution = 0; + memset(statusUserFunction_, 0, numberUserFunctions_ * sizeof(int)); + /* Note + This is meant as a stand-alone executable to do as much of coin as possible. + It should only have one solver known to it. + */ + CoinMessageHandler *generalMessageHandler = model_.messageHandler(); + generalMessageHandler->setPrefix(false); + int numberLotSizing = 0; + typedef struct { + double low; + double high; + int column; + } lotStruct; + lotStruct *lotsize = NULL; + typedef struct {lotStruct * lotsize;int numberLotSizing;} lotStruct2; + lotStruct2 passSCtopreprocess; +#ifndef CBC_OTHER_SOLVER + OsiClpSolverInterface *originalSolver = dynamic_cast< OsiClpSolverInterface * >(model_.solver()); + assert(originalSolver); + // Move handler across if not default + if (!originalSolver->defaultHandler() && originalSolver->getModelPtr()->defaultHandler()) + originalSolver->getModelPtr()->passInMessageHandler(originalSolver->messageHandler()); + CoinMessages generalMessages = originalSolver->getModelPtr()->messages(); + char generalPrint[10000]; + if (originalSolver->getModelPtr()->logLevel() == 0) { + noPrinting = true; + parameterData.printWelcome_ = false; + } +#elif CBC_OTHER_SOLVER == 1 + OsiCpxSolverInterface *originalSolver = dynamic_cast< OsiCpxSolverInterface * >(model_.solver()); + assert(originalSolver); + OsiClpSolverInterface dummySolver; + OsiCpxSolverInterface *clpSolver = originalSolver; + CoinMessages generalMessages = dummySolver.getModelPtr()->messages(); + char generalPrint[10000]; + noPrinting = true; +#endif + bool noPrinting_ = noPrinting; + // Say not in integer + int integerStatus = -1; + // Say no resolve after cuts + model_.setResolveAfterTakeOffCuts(false); + // see if log in list + for (int i = 1; i < argc; i++) { + if (!strncmp(argv[i], "log", 3)) { + const char *equals = strchr(argv[i], '='); + if (equals && atoi(equals + 1) != 0) + noPrinting_ = false; + else + noPrinting_ = true; + break; + } else if (!strncmp(argv[i], "-log", 4) && i < argc - 1) { + if (atoi(argv[i + 1]) != 0) + noPrinting_ = false; + else + noPrinting_ = true; + break; + } + } + double time0; + double time0Elapsed = CoinGetTimeOfDay(); + { + double time1 = CoinCpuTime(), time2; + time0 = time1; + double time1Elapsed = time0Elapsed; + bool goodModel = (originalSolver->getNumCols()) ? true : false; + + // register signal handler + //CoinSighandler_t saveSignal=signal(SIGINT,signal_handler); +#if CBC_QUIET < 2 + if (useSignalHandler) + signal(SIGINT, signal_handler); +#endif + // Set up all non-standard stuff + int cutPass = -1234567; + int cutPassInTree = -1234567; + int tunePreProcess = 0; + int testOsiParameters = -1; + // 0 normal, 1 from ampl or MIQP etc (2 allows cuts) + int complicatedInteger = 0; + OsiSolverInterface *solver = model_.solver(); + if (noPrinting_) + setCbcOrClpPrinting(false); +#ifndef CBC_OTHER_SOLVER + OsiClpSolverInterface *clpSolver = dynamic_cast< OsiClpSolverInterface * >(solver); + ClpSimplex *lpSolver = clpSolver->getModelPtr(); + if (noPrinting_) { + lpSolver->setLogLevel(0); + } +#else + ClpSimplex *lpSolver = NULL; +#endif + // For priorities etc + int *priorities = NULL; + int *branchDirection = NULL; + double *pseudoDown = NULL; + double *pseudoUp = NULL; + double *solutionIn = NULL; + int *prioritiesIn = NULL; + std::vector< std::pair< std::string, double > > mipStart; + std::vector< std::pair< std::string, double > > mipStartBefore; + std::string mipStartFile = ""; + int numberSOS = 0; + int *sosStart = NULL; + int *sosIndices = NULL; + char *sosType = NULL; + double *sosReference = NULL; + int *cut = NULL; + int *sosPriority = NULL; + CglStored storedAmpl; + CoinModel *coinModel = NULL; + CoinModel saveCoinModel; + CoinModel saveTightenedModel; + int *whichColumn = NULL; + int *knapsackStart = NULL; + int *knapsackRow = NULL; + int numberKnapsack = 0; + ampl_info info; + { + memset(&info, 0, sizeof(info)); + if (argc > 2 && !strcmp(argv[2], "-AMPL")) { + statusUserFunction_[0] = 1; + // see if log in list + noPrinting_ = true; + for (int i = 1; i < argc; i++) { + if (!strncmp(argv[i], "log", 3)) { + const char *equals = strchr(argv[i], '='); + if (equals && atoi(equals + 1) > 0) { + noPrinting_ = false; + info.logLevel = atoi(equals + 1); + int log = whichParam(CLP_PARAM_INT_LOGLEVEL, parameters_); + parameters_[log].setIntValue(info.logLevel); + // mark so won't be overWritten + info.numberRows = -1234567; + break; + } + } + } + + union { + void *voidModel; + CoinModel *model; + } coinModelStart; + coinModelStart.model = NULL; + int returnCode = readAmpl(&info, argc, const_cast< char ** >(argv), &coinModelStart.voidModel, "cbc"); + coinModel = coinModelStart.model; + if (returnCode) + return returnCode; + if (info.numberSos) { + numberSOS = info.numberSos; + sosStart = info.sosStart; + sosIndices = info.sosIndices; + sosType = info.sosType; + sosReference = info.sosReference; + sosPriority = info.sosPriority; + } + setCbcOrClpReadMode(2); // so will start with parameters + // see if log in list (including environment) + for (int i = 1; i < info.numberArguments; i++) { + if (!strcmp(info.arguments[i], "log")) { + if (i < info.numberArguments - 1 && atoi(info.arguments[i + 1]) > 0) + noPrinting_ = false; + break; + } + } + if (noPrinting_) { + model_.messageHandler()->setLogLevel(0); + setCbcOrClpPrinting(false); + } + if (!noPrinting_) + printf("%d rows, %d columns and %d elements\n", + info.numberRows, info.numberColumns, info.numberElements); +#ifdef COIN_HAS_LINK + if (!coinModel) { +#endif + solver->loadProblem(info.numberColumns, info.numberRows, + reinterpret_cast< const CoinBigIndex * >(info.starts), + info.rows, info.elements, + info.columnLower, info.columnUpper, info.objective, + info.rowLower, info.rowUpper); + // take off cuts if ampl wants that + if (info.cut && 0) { + printf("AMPL CUTS OFF until global cuts fixed\n"); + info.cut = NULL; + } + if (info.cut) { + int numberRows = info.numberRows; + int *whichRow = new int[numberRows]; + // Row copy + const CoinPackedMatrix *matrixByRow = solver->getMatrixByRow(); + const double *elementByRow = matrixByRow->getElements(); + const int *column = matrixByRow->getIndices(); + const CoinBigIndex *rowStart = matrixByRow->getVectorStarts(); + const int *rowLength = matrixByRow->getVectorLengths(); + + const double *rowLower = solver->getRowLower(); + const double *rowUpper = solver->getRowUpper(); + int nDelete = 0; + for (int iRow = 0; iRow < numberRows; iRow++) { + if (info.cut[iRow]) { + whichRow[nDelete++] = iRow; + int start = rowStart[iRow]; + storedAmpl.addCut(rowLower[iRow], rowUpper[iRow], + rowLength[iRow], column + start, elementByRow + start); + } + } + solver->deleteRows(nDelete, whichRow); + delete[] whichRow; + } +#ifdef COIN_HAS_LINK + } else { +#ifndef CBC_OTHER_SOLVER + // save + saveCoinModel = *coinModel; + // load from coin model + OsiSolverLink solver1; + OsiSolverInterface *solver2 = solver1.clone(); + model_.assignSolver(solver2, false); + OsiSolverLink *si = dynamic_cast< OsiSolverLink * >(model_.solver()); + assert(si != NULL); + si->setDefaultMeshSize(0.001); + // need some relative granularity + si->setDefaultBound(100.0); + double dextra3 = parameters_[whichParam(CBC_PARAM_DBL_DEXTRA3, parameters_)].doubleValue(); + if (dextra3) + si->setDefaultMeshSize(dextra3); + si->setDefaultBound(100000.0); + si->setIntegerPriority(1000); + si->setBiLinearPriority(10000); + CoinModel *model2 = reinterpret_cast< CoinModel * >(coinModel); + int logLevel = parameters_[whichParam(CLP_PARAM_INT_LOGLEVEL, parameters_)].intValue(); + si->load(*model2, true, logLevel); + // redo + solver = model_.solver(); + clpSolver = dynamic_cast< OsiClpSolverInterface * >(solver); + lpSolver = clpSolver->getModelPtr(); + clpSolver->messageHandler()->setLogLevel(0); + testOsiParameters = 0; + parameters_[whichParam(CBC_PARAM_INT_TESTOSI, parameters_)].setIntValue(0); + complicatedInteger = 1; + if (info.cut) { + printf("Sorry - can't do cuts with LOS as ruins delicate row order\n"); + abort(); + int numberRows = info.numberRows; + int *whichRow = new int[numberRows]; + // Row copy + const CoinPackedMatrix *matrixByRow = solver->getMatrixByRow(); + const double *elementByRow = matrixByRow->getElements(); + const int *column = matrixByRow->getIndices(); + const CoinBigIndex *rowStart = matrixByRow->getVectorStarts(); + const int *rowLength = matrixByRow->getVectorLengths(); + + const double *rowLower = solver->getRowLower(); + const double *rowUpper = solver->getRowUpper(); + int nDelete = 0; + for (int iRow = 0; iRow < numberRows; iRow++) { + if (info.cut[iRow]) { + whichRow[nDelete++] = iRow; + int start = rowStart[iRow]; + storedAmpl.addCut(rowLower[iRow], rowUpper[iRow], + rowLength[iRow], column + start, elementByRow + start); + } + } + solver->deleteRows(nDelete, whichRow); + // and special matrix + si->cleanMatrix()->deleteRows(nDelete, whichRow); + delete[] whichRow; + } +#endif + } +#endif + // If we had a solution use it + if (info.primalSolution) { + solver->setColSolution(info.primalSolution); + } + // status + if (info.rowStatus) { + unsigned char *statusArray = lpSolver->statusArray(); + int i; + for (i = 0; i < info.numberColumns; i++) + statusArray[i] = static_cast< unsigned char >(info.columnStatus[i]); + statusArray += info.numberColumns; + for (i = 0; i < info.numberRows; i++) + statusArray[i] = static_cast< unsigned char >(info.rowStatus[i]); + CoinWarmStartBasis *basis = lpSolver->getBasis(); + solver->setWarmStart(basis); + delete basis; + } + freeArrays1(&info); + // modify objective if necessary + solver->setObjSense(info.direction); + solver->setDblParam(OsiObjOffset, -info.offset); + if (info.offset) { + sprintf(generalPrint, "Ampl objective offset is %g", + info.offset); + generalMessageHandler->message(CLP_GENERAL, generalMessages) + << generalPrint + << CoinMessageEol; + } + // Set integer variables (unless nonlinear when set) + if (!info.nonLinear) { + for (int i = info.numberColumns - info.numberIntegers; + i < info.numberColumns; i++) + solver->setInteger(i); + } + goodModel = true; + // change argc etc + argc = info.numberArguments; + argv = const_cast< const char ** >(info.arguments); + } + } + // default action on import + int allowImportErrors = 0; + int keepImportNames = 1; + int doIdiot = -1; + int outputFormat = 2; + int slpValue = -1; + int cppValue = -1; + int printOptions = 0; + int printMode = 0; + int presolveOptions = 0; + int substitution = 3; + int dualize = 3; + int doCrash = 0; + int doVector = 0; + int doSprint = -1; + int doScaling = 4; + // set reasonable defaults + int preSolve = 5; + int preProcess = 4; + bool useStrategy = false; + bool preSolveFile = false; + bool strongChanged = false; + bool pumpChanged = false; + + double djFix = 1.0e100; + double tightenFactor = 0.0; + const char dirsep = CoinFindDirSeparator(); + std::string directory; + std::string dirSample; + std::string dirNetlib; + std::string dirMiplib; + if (dirsep == '/') { + directory = "./"; + dirSample = "../../Data/Sample/"; + dirNetlib = "../../Data/Netlib/"; + dirMiplib = "../../Data/miplib3/"; + } else { + directory = ".\\"; + dirSample = "..\\..\\..\\..\\Data\\Sample\\"; + dirNetlib = "..\\..\\..\\..\\Data\\Netlib\\"; + dirMiplib = "..\\..\\..\\..\\Data\\miplib3\\"; + } + std::string defaultDirectory = directory; + std::string importFile = ""; + std::string exportFile = "default.mps"; + std::string importBasisFile = ""; + std::string importPriorityFile = ""; + std::string debugFile = ""; + std::string printMask = ""; + double *debugValues = NULL; + int numberDebugValues = -1; + int basisHasValues = 0; + std::string exportBasisFile = "default.bas"; + std::string saveFile = "default.prob"; + std::string restoreFile = "default.prob"; + std::string solutionFile = "stdout"; + std::string solutionSaveFile = "solution.file"; + int slog = whichParam(CLP_PARAM_INT_SOLVERLOGLEVEL, parameters_); + int log = whichParam(CLP_PARAM_INT_LOGLEVEL, parameters_); +#ifndef CBC_OTHER_SOLVER + double normalIncrement = model_.getCutoffIncrement(); + ; +#endif + if (testOsiParameters >= 0) { + // trying nonlinear - switch off some stuff + preProcess = 0; + } + // Set up likely cut generators and defaults + int nodeStrategy = 0; + bool dominatedCuts = false; + int doSOS = 1; + int verbose = 0; + CglGomory gomoryGen; + // try larger limit + gomoryGen.setLimitAtRoot(1000); + gomoryGen.setLimit(50); + // set default action (0=off,1=on,2=root) + int gomoryAction = 3; + + CglProbing probingGen; + probingGen.setUsingObjective(1); + probingGen.setMaxPass(1); + probingGen.setMaxPassRoot(1); + // Number of unsatisfied variables to look at + probingGen.setMaxProbe(10); + probingGen.setMaxProbeRoot(50); + // How far to follow the consequences + probingGen.setMaxLook(10); + probingGen.setMaxLookRoot(50); + probingGen.setMaxLookRoot(10); + // Only look at rows with fewer than this number of elements + probingGen.setMaxElements(200); + probingGen.setMaxElementsRoot(300); + probingGen.setRowCuts(3); + // set default action (0=off,1=on,2=root) + int probingAction = 1; + + CglKnapsackCover knapsackGen; + //knapsackGen.switchOnExpensive(); + //knapsackGen.setMaxInKnapsack(100); + // set default action (0=off,1=on,2=root) + int knapsackAction = 3; + + CglRedSplit redsplitGen; + //redsplitGen.setLimit(100); + // set default action (0=off,1=on,2=root) + // Off as seems to give some bad cuts + int redsplitAction = 0; + + CglRedSplit2 redsplit2Gen; + //redsplit2Gen.setLimit(100); + // set default action (0=off,1=on,2=root) + // Off + int redsplit2Action = 0; + + CglGMI GMIGen; + //GMIGen.setLimit(100); + // set default action (0=off,1=on,2=root) + // Off + int GMIAction = 0; + + std::string cgraphAction = "on"; + std::string clqstrAction = "after"; + CglBKClique bkCliqueGen; + int cliqueAction = 3, bkPivotingStrategy = 3, maxCallsBK = 1000, bkClqExtMethod = 4; + bool oldCliqueMode = false; + CglOddWheel oddWheelGen; + int oddWheelAction = 3, oddWExtMethod = 2; + + // maxaggr,multiply,criterion(1-3) + CglMixedIntegerRounding2 mixedGen(1, true, 1); + // set default action (0=off,1=on,2=root) + int mixedAction = 3; + mixedGen.setDoPreproc(1); // safer (and better) + + CglFlowCover flowGen; + // set default action (0=off,1=on,2=root) + int flowAction = 3; + + CglTwomir twomirGen; + twomirGen.setMaxElements(250); + // set default action (0=off,1=on,2=root) + int twomirAction = 3; +#ifndef DEBUG_MALLOC + CglLandP landpGen; + landpGen.parameter().maximumCutLength = 2000; + landpGen.validator().setMinViolation(1.0e-4); +#endif + // set default action (0=off,1=on,2=root) + int landpAction = 0; + CglResidualCapacity residualCapacityGen; + residualCapacityGen.setDoPreproc(1); // always preprocess + // set default action (0=off,1=on,2=root) + int residualCapacityAction = 0; + + CglZeroHalf zerohalfGen; + //zerohalfGen.switchOnExpensive(); + // set default action (0=off,1=on,2=root) + int zerohalfAction = 3; + + // Stored cuts + //bool storedCuts = false; + + int useCosts = 0; + // don't use input solution + int useSolution = -1; + + // total number of commands read + int numberGoodCommands = 0; + // Set false if user does anything advanced + bool defaultSettings = true; + + // Hidden stuff for barrier + int choleskyType = 0; + int gamma = 0; + int scaleBarrier = 0; + int doKKT = 0; + int crossover = 2; // do crossover unless quadratic + bool biLinearProblem = false; + // For names + int lengthName = 0; + std::vector< std::string > rowNames; + std::vector< std::string > columnNames; + // Default strategy stuff + { + // try changing tolerance at root +#define MORE_CUTS +#ifdef MORE_CUTS + gomoryGen.setAwayAtRoot(0.005); + twomirGen.setAwayAtRoot(0.005); + twomirGen.setAway(0.01); + //twomirGen.setMirScale(1,1); + //twomirGen.setTwomirScale(1,1); + //twomirGen.setAMax(2); +#else + gomoryGen.setAwayAtRoot(0.01); + twomirGen.setAwayAtRoot(0.01); + twomirGen.setAway(0.01); +#endif + int iParam; + iParam = whichParam(CBC_PARAM_INT_DIVEOPT, parameters_); + parameters_[iParam].setIntValue(2); + iParam = whichParam(CBC_PARAM_INT_FPUMPITS, parameters_); + parameters_[iParam].setIntValue(30); + iParam = whichParam(CBC_PARAM_INT_FPUMPTUNE, parameters_); + parameters_[iParam].setIntValue(1005043); + initialPumpTune = 1005043; + iParam = whichParam(CLP_PARAM_INT_PROCESSTUNE, parameters_); + parameters_[iParam].setIntValue(6); + tunePreProcess = 6; + iParam = whichParam(CBC_PARAM_STR_DIVINGC, parameters_); + parameters_[iParam].setCurrentOption("on"); + iParam = whichParam(CBC_PARAM_STR_RINS, parameters_); + parameters_[iParam].setCurrentOption("on"); + iParam = whichParam(CBC_PARAM_STR_PROBINGCUTS, parameters_); + parameters_[iParam].setCurrentOption("on"); + probingAction = 3; + //parameters_[iParam].setCurrentOption("forceOnStrong"); + //probingAction = 8; + } + std::string field; +#if CBC_QUIET == 0 + if ((!noPrinting_) && (parameterData.printWelcome_)) { + sprintf(generalPrint, + "Welcome to the CBC MILP Solver \n"); + if (strcmp(CBC_VERSION, "trunk")) { + sprintf(generalPrint + strlen(generalPrint), + "Version: %s \n", CBC_VERSION); + } else { + sprintf(generalPrint + strlen(generalPrint), + "Version: Trunk (unstable) \n"); + } + sprintf(generalPrint + strlen(generalPrint), + "Build Date: %s \n", __DATE__); +#ifdef CBC_SVN_REV + sprintf(generalPrint + strlen(generalPrint), + "Revision Number: %d \n", CBC_SVN_REV); +#endif + generalMessageHandler->message(CLP_GENERAL, generalMessages) + << generalPrint + << CoinMessageEol; + // Print command line + if (argc > 1) { + bool foundStrategy = false; + sprintf(generalPrint, "command line - "); + for (int i = 0; i < argc; i++) { + if (!argv[i]) + break; + if (strstr(argv[i], "strat")) + foundStrategy = true; + sprintf(generalPrint + strlen(generalPrint), "%s ", argv[i]); + } + if (!foundStrategy) + sprintf(generalPrint + strlen(generalPrint), "(default strategy 1)"); + generalMessageHandler->message(CLP_GENERAL, generalMessages) + << generalPrint + << CoinMessageEol; + } + } +#endif + while (1) { + // next command + field = CoinReadGetCommand(argc, argv); + // Reset time + time1 = CoinCpuTime(); + time1Elapsed = CoinGetTimeOfDay(); + // adjust field if has odd trailing characters + char temp[200]; + strcpy(temp, field.c_str()); + int length = static_cast< int >(strlen(temp)); + for (int k = length - 1; k >= 0; k--) { + if (temp[k] < ' ') + length--; + else + break; + } + temp[length] = '\0'; + field = temp; + // exit if null or similar + if (!field.length()) { + if (numberGoodCommands == 1 && goodModel) { + // we just had file name - do branch and bound + field = "branch"; + } else if (!numberGoodCommands) { + // let's give the sucker a hint + std::cout + << "CoinSolver takes input from arguments ( - switches to stdin)" + << std::endl + << "Enter ? for list of commands or help" << std::endl; + field = "-"; + } else { + break; + } + } + + // see if ? at end + size_t numberQuery = 0; + if (field != "?" && field != "???") { + size_t length = field.length(); + size_t i; + for (i = length - 1; i > 0; i--) { + if (field[i] == '?') + numberQuery++; + else + break; + } + field = field.substr(0, length - numberQuery); + } + // find out if valid command + int iParam; + int numberMatches = 0; + int firstMatch = -1; + for (iParam = 0; iParam < (int)parameters_.size(); iParam++) { + int match = parameters_[iParam].matches(field); + if (match == 1) { + numberMatches = 1; + firstMatch = iParam; + break; + } else { + if (match && firstMatch < 0) + firstMatch = iParam; + numberMatches += match >> 1; + } + } + if (iParam < (int)parameters_.size() && !numberQuery) { + // found + CbcOrClpParam found = parameters_[iParam]; + CbcOrClpParameterType type = found.type(); + int valid; + numberGoodCommands++; + if (type == CBC_PARAM_ACTION_BAB && goodModel) { + if (clqstrAction == "before") { //performing clique strengthening before initial solve + CglCliqueStrengthening clqStr(model_.solver(), model_.messageHandler()); + clqStr.strengthenCliques(2); + + if (clqStr.constraintsExtended() + clqStr.constraintsDominated() > 0) { + model_.solver()->initialSolve(); + + if ((!noPrinting_) && (model_.messageHandler()->logLevel())) { + if (model_.solver()->isProvenPrimalInfeasible()) { + sprintf(generalPrint, "Clique Strengthening says infeasible!"); + generalMessageHandler->message(CLP_GENERAL, generalMessages) + << generalPrint + << CoinMessageEol; + } else { + sprintf(generalPrint, "After applying Clique Strengthening continuous objective value is %.2lf", model_.solver()->getObjValue()); + generalMessageHandler->message(CLP_GENERAL, generalMessages) + << generalPrint + << CoinMessageEol; + } + } + } + } +#if CBC_USE_INITIAL_TIME==1 + if (model_.useElapsedTime()) + model_.setDblParam(CbcModel::CbcStartSeconds, CoinGetTimeOfDay()); + else + model_.setDblParam(CbcModel::CbcStartSeconds, CoinCpuTime()); +#endif + biLinearProblem = false; + // check if any integers +#ifndef CBC_OTHER_SOLVER + if (info.numberSos && doSOS && statusUserFunction_[0]) { + // SOS + numberSOS = info.numberSos; + } + lpSolver = clpSolver->getModelPtr(); + if (!lpSolver->integerInformation() && !numberSOS && !clpSolver->numberSOS() && !model_.numberObjects() && !clpSolver->numberObjects()) { + type = CLP_PARAM_ACTION_DUALSIMPLEX; +#ifdef CBC_MAXIMUM_BOUND + } else { + double *lower = lpSolver->columnLower(); + double *upper = lpSolver->columnUpper(); + int numberColumns = lpSolver->numberColumns(); + for (int i = 0; i < numberColumns; i++) { + lower[i] = CoinMax(lower[i], -CBC_MAXIMUM_BOUND); + upper[i] = CoinMin(upper[i], CBC_MAXIMUM_BOUND); + } +#endif + } +#endif + } + if (type == CBC_PARAM_GENERALQUERY) { + bool evenHidden = false; + int printLevel = parameters_[whichParam(CLP_PARAM_STR_ALLCOMMANDS, + parameters_)] + .currentOptionAsInteger(); + int convertP[] = { 2, 1, 0 }; + printLevel = convertP[printLevel]; + if ((verbose & 8) != 0) { + // even hidden + evenHidden = true; + verbose &= ~8; + } + if (verbose < 4 && statusUserFunction_[0]) + verbose += 4; + if (verbose < 4) { + std::cout << "In argument list keywords have leading - " + ", -stdin or just - switches to stdin" + << std::endl; + std::cout << "One command per line (and no -)" << std::endl; + std::cout << "abcd? gives list of possibilities, if only one + explanation" << std::endl; + std::cout << "abcd?? adds explanation, if only one fuller help" << std::endl; + std::cout << "abcd without value (where expected) gives current value" << std::endl; + std::cout << "abcd value sets value" << std::endl; + std::cout << "Commands are:" << std::endl; + } else { + std::cout << "Cbc options are set within AMPL with commands like:" << std::endl + << std::endl; + std::cout << " option cbc_options \"cuts=root log=2 feas=on slog=1\"" << std::endl + << std::endl; + std::cout << "only maximize, dual, primal, help and quit are recognized without =" << std::endl; + } + int maxAcross = 10; + if ((verbose % 4) != 0) + maxAcross = 1; + int limits[] = { 1, 51, 101, 151, 201, 301, 401, 501, 601 }; + std::vector< std::string > types; + types.push_back("Double parameters:"); + types.push_back("Branch and Cut double parameters:"); + types.push_back("Integer parameters:"); + types.push_back("Branch and Cut integer parameters:"); + types.push_back("Keyword parameters:"); + types.push_back("Branch and Cut keyword parameters:"); + types.push_back("Actions or string parameters:"); + types.push_back("Branch and Cut actions:"); + int iType; + for (iType = 0; iType < 8; iType++) { + int across = 0; + int lengthLine = 0; + if ((verbose % 4) != 0) + std::cout << std::endl; + std::cout << types[iType] << std::endl; + if ((verbose & 2) != 0) + std::cout << std::endl; + for (iParam = 0; iParam < (int)parameters_.size(); iParam++) { + int type = parameters_[iParam].type(); + //printf("%d type %d limits %d %d display %d\n",iParam, + // type,limits[iType],limits[iType+1],parameters_[iParam].displayThis()); + if ((parameters_[iParam].displayThis() >= printLevel || evenHidden) && type >= limits[iType] + && type < limits[iType + 1]) { + // but skip if not useful for ampl (and in ampl mode) + if (verbose >= 4 && (parameters_[iParam].whereUsed() & 4) == 0) + continue; + if (!across) { + if ((verbose & 2) != 0) + std::cout << "Command "; + } + int length = parameters_[iParam].lengthMatchName() + 1; + if (lengthLine + length > 80) { + std::cout << std::endl; + across = 0; + lengthLine = 0; + } + std::cout << " " << parameters_[iParam].matchName(); + lengthLine += length; + across++; + if (across == maxAcross) { + across = 0; + if ((verbose % 4) != 0) { + // put out description as well + if ((verbose & 1) != 0) + std::cout << " " << parameters_[iParam].shortHelp(); + std::cout << std::endl; + if ((verbose & 2) != 0) { + std::cout << "---- description" << std::endl; + parameters_[iParam].printLongHelp(); + std::cout << "----" << std::endl + << std::endl; + } + } else { + std::cout << std::endl; + } + } + } + } + if (across) + std::cout << std::endl; + } + } else if (type == CBC_PARAM_FULLGENERALQUERY) { + std::cout << "Full list of commands is:" << std::endl; + int maxAcross = 5; + int limits[] = { 1, 51, 101, 151, 201, 301, 401, 501, 601 }; + std::vector< std::string > types; + types.push_back("Double parameters:"); + types.push_back("Branch and Cut double parameters:"); + types.push_back("Integer parameters:"); + types.push_back("Branch and Cut integer parameters:"); + types.push_back("Keyword parameters:"); + types.push_back("Branch and Cut keyword parameters:"); + types.push_back("Actions or string parameters:"); + types.push_back("Branch and Cut actions:"); + int iType; + for (iType = 0; iType < 8; iType++) { + int across = 0; + std::cout << types[iType] << " "; + for (iParam = 0; iParam < (int)parameters_.size(); iParam++) { + int type = parameters_[iParam].type(); + if (type >= limits[iType] + && type < limits[iType + 1]) { + if (!across) + std::cout << " "; + std::cout << parameters_[iParam].matchName() << " "; + across++; + if (across == maxAcross) { + std::cout << std::endl; + across = 0; + } + } + } + if (across) + std::cout << std::endl; + } + } else if (type < 101) { + // get next field as double + double value = CoinReadGetDoubleField(argc, argv, &valid); + if (!valid) { + if (type < 51) { + int returnCode; + const char *message = parameters_[iParam].setDoubleParameterWithMessage(lpSolver, value, returnCode); + if (!noPrinting_ && strlen(message)) { + generalMessageHandler->message(CLP_GENERAL, generalMessages) + << message + << CoinMessageEol; + } + } else if (type < 81) { + int returnCode; + const char *message = parameters_[iParam].setDoubleParameterWithMessage(model_, value, returnCode); + if (!noPrinting_ && strlen(message)) { + generalMessageHandler->message(CLP_GENERAL, generalMessages) + << message + << CoinMessageEol; + } + } else { + int returnCode; + const char *message = parameters_[iParam].setDoubleParameterWithMessage(lpSolver, value, returnCode); + if (!noPrinting_ && strlen(message)) { + generalMessageHandler->message(CLP_GENERAL, generalMessages) + << message + << CoinMessageEol; + } + switch (type) { + case CBC_PARAM_DBL_DJFIX: + djFix = value; +#ifndef CBC_OTHER_SOLVER + if (goodModel && djFix < 1.0e20) { + // do some fixing + clpSolver = dynamic_cast< OsiClpSolverInterface * >(model_.solver()); + clpSolver->initialSolve(); + lpSolver = clpSolver->getModelPtr(); + int numberColumns = lpSolver->numberColumns(); + int i; + const char *type = lpSolver->integerInformation(); + double *lower = lpSolver->columnLower(); + double *upper = lpSolver->columnUpper(); + double *solution = lpSolver->primalColumnSolution(); + double *dj = lpSolver->dualColumnSolution(); + int numberFixed = 0; + double dextra4 = parameters_[whichParam(CBC_PARAM_DBL_DEXTRA4, parameters_)].doubleValue(); + if (dextra4) + printf("Multiple for continuous dj fixing is %g\n", dextra4); + for (i = 0; i < numberColumns; i++) { + double djValue = dj[i]; + if (!type[i]) + djValue *= dextra4; + if (type[i] || dextra4) { + double value = solution[i]; + if (value < lower[i] + 1.0e-5 && djValue > djFix) { + solution[i] = lower[i]; + upper[i] = lower[i]; + numberFixed++; + } else if (value > upper[i] - 1.0e-5 && djValue < -djFix) { + solution[i] = upper[i]; + lower[i] = upper[i]; + numberFixed++; + } + } + } + sprintf(generalPrint, "%d columns fixed\n", numberFixed); + generalMessageHandler->message(CLP_GENERAL, generalMessages) + << generalPrint + << CoinMessageEol; + } +#endif + break; + case CBC_PARAM_DBL_TIGHTENFACTOR: + tightenFactor = value; + if (!complicatedInteger) + defaultSettings = false; // user knows what she is doing + break; + default: + break; + } + } + } else if (valid == 1) { + std::cout << " is illegal for double parameter " << parameters_[iParam].name() << " value remains " << parameters_[iParam].doubleValue() << std::endl; + } else { + std::cout << parameters_[iParam].name() << " has value " << parameters_[iParam].doubleValue() << std::endl; + } + } else if (type < 201) { + // get next field as int + int value = CoinReadGetIntField(argc, argv, &valid); + if (valid == 1 && parameters_[iParam].stringValue()!="") { + // look further + value = + parameters_[iParam].optionIntField(getCoinErrorField(), &valid); + } + if (!valid) { + if (type < 151) { + if (parameters_[iParam].type() == CLP_PARAM_INT_PRESOLVEPASS) + preSolve = value; + else if (parameters_[iParam].type() == CLP_PARAM_INT_IDIOT) + doIdiot = value; + else if (parameters_[iParam].type() == CLP_PARAM_INT_SPRINT) + doSprint = value; + else if (parameters_[iParam].type() == CLP_PARAM_INT_OUTPUTFORMAT) + outputFormat = value; + else if (parameters_[iParam].type() == CLP_PARAM_INT_SLPVALUE) + slpValue = value; + else if (parameters_[iParam].type() == CLP_PARAM_INT_CPP) + cppValue = value; + else if (parameters_[iParam].type() == CLP_PARAM_INT_PRESOLVEOPTIONS) + presolveOptions = value; + else if (parameters_[iParam].type() == CLP_PARAM_INT_PRINTOPTIONS) + printOptions = value; + else if (parameters_[iParam].type() == CLP_PARAM_INT_SUBSTITUTION) + substitution = value; + else if (parameters_[iParam].type() == CLP_PARAM_INT_DUALIZE) + dualize = value; + else if (parameters_[iParam].type() == CLP_PARAM_INT_PROCESSTUNE) + tunePreProcess = value; + else if (parameters_[iParam].type() == CLP_PARAM_INT_USESOLUTION) + useSolution = value; + else if (parameters_[iParam].type() == CLP_PARAM_INT_VERBOSE) + verbose = value; + int returnCode; + const char *message = parameters_[iParam].setIntParameterWithMessage(lpSolver, value, returnCode); + if (parameters_[iParam].type() == CLP_PARAM_INT_SOLVERLOGLEVEL) + clpSolver->messageHandler()->setLogLevel(value); // as well + + if (!noPrinting_ && strlen(message)) { + generalMessageHandler->message(CLP_GENERAL, generalMessages) + << message + << CoinMessageEol; + } + } else { + if (parameters_[iParam].type() == CBC_PARAM_INT_CUTPASS) + cutPass = value; + else if (parameters_[iParam].type() == CBC_PARAM_INT_CUTPASSINTREE) + cutPassInTree = value; + else if (parameters_[iParam].type() == CBC_PARAM_INT_STRONGBRANCHING || parameters_[iParam].type() == CBC_PARAM_INT_NUMBERBEFORE) + strongChanged = true; + else if (parameters_[iParam].type() == CBC_PARAM_INT_FPUMPTUNE || parameters_[iParam].type() == CBC_PARAM_INT_FPUMPTUNE2 || parameters_[iParam].type() == CBC_PARAM_INT_FPUMPITS) + pumpChanged = true; + else if (parameters_[iParam].type() == CBC_PARAM_INT_BKPIVOTINGSTRATEGY) + bkPivotingStrategy = value; + else if (parameters_[iParam].type() == CBC_PARAM_INT_BKMAXCALLS) + maxCallsBK = value; + else if (parameters_[iParam].type() == CBC_PARAM_INT_BKCLQEXTMETHOD) + bkClqExtMethod = value; + else if (parameters_[iParam].type() == CBC_PARAM_INT_ODDWEXTMETHOD) + oddWExtMethod = value; + else if (parameters_[iParam].type() == CBC_PARAM_INT_EXPERIMENT + && value<10000) { + int addFlags = 0; + // switch on some later features if >999 + if (value > 999) { + int switchValue = value / 1000; + const char *message = NULL; + value -= 1000 * switchValue; + parameters_[whichParam(CBC_PARAM_INT_EXPERIMENT, parameters_)].setIntValue(0 /*value*/); + switch (switchValue) { + default: + case 4: + // hotstart 500, -200 cut passes + message = parameters_[whichParam(CBC_PARAM_INT_MAXHOTITS, parameters_)].setIntValueWithMessage(500); + if (!noPrinting_ && message) + generalMessageHandler->message(CLP_GENERAL, generalMessages) + << message << CoinMessageEol; + message = parameters_[whichParam(CBC_PARAM_INT_CUTPASS, parameters_)].setIntValueWithMessage(-200); + if (!noPrinting_ && message) + generalMessageHandler->message(CLP_GENERAL, generalMessages) + << message << CoinMessageEol; + case 3: + // multiple 4 + message = parameters_[whichParam(CBC_PARAM_INT_MULTIPLEROOTS, parameters_)].setIntValueWithMessage(4); + if (!noPrinting_ && message) + generalMessageHandler->message(CLP_GENERAL, generalMessages) + << message << CoinMessageEol; + case 2: + // rens plus all diving at root + message = parameters_[whichParam(CBC_PARAM_INT_DIVEOPT, parameters_)].setIntValueWithMessage(16); + if (!noPrinting_ && message) + generalMessageHandler->message(CLP_GENERAL, generalMessages) + << message << CoinMessageEol; + model_.setNumberAnalyzeIterations(-value); + // -tune 7 zero,lagomory,gmi at root - probing on + case 1: + tunePreProcess = 7; + message = parameters_[whichParam(CLP_PARAM_INT_PROCESSTUNE, parameters_)].setIntValueWithMessage(7); + if (!noPrinting_ && message) + generalMessageHandler->message(CLP_GENERAL, generalMessages) + << message << CoinMessageEol; + //message = parameters_[whichParam(CBC_PARAM_INT_MIPOPTIONS, parameters_)].setIntValueWithMessage(1025); + //if (!noPrinting_&&message) + // generalMessageHandler->message(CLP_GENERAL, generalMessages) + // << message << CoinMessageEol; + message = parameters_[whichParam(CBC_PARAM_STR_PROBINGCUTS, parameters_)].setCurrentOptionWithMessage("on"); + probingAction = 1; + if (!noPrinting_ && message) + generalMessageHandler->message(CLP_GENERAL, generalMessages) + << message << CoinMessageEol; + message = parameters_[whichParam(CBC_PARAM_STR_ZEROHALFCUTS, parameters_)].setCurrentOptionWithMessage("root"); + if (!noPrinting_ && message) + generalMessageHandler->message(CLP_GENERAL, generalMessages) + << message << CoinMessageEol; + message = parameters_[whichParam(CBC_PARAM_STR_LAGOMORYCUTS, parameters_)].setCurrentOptionWithMessage("root"); + if (!noPrinting_ && message) + generalMessageHandler->message(CLP_GENERAL, generalMessages) + << message << CoinMessageEol; + GMIAction = 2; + message = parameters_[whichParam(CBC_PARAM_STR_GMICUTS, parameters_)].setCurrentOptionWithMessage("root"); + if (!noPrinting_ && message) + generalMessageHandler->message(CLP_GENERAL, generalMessages) + << message << CoinMessageEol; + } + value = 0; + } + if (value >= 10) { + addFlags = 1048576 * (value / 10); + value = value % 10; + parameters_[whichParam(CBC_PARAM_INT_EXPERIMENT, parameters_)].setIntValue(value); + } +#ifndef CBC_EXPERIMENT7 + if (value == 1) { + // just experimental preprocessing and more restarts + tunePreProcess |= 8192; + model_.setSpecialOptions(model_.specialOptions()|(512|32768)); + } +#else + if (value == 1 || value == 2) { + // just experimental preprocessing and more restarts + tunePreProcess |= 8199; + model_.setSpecialOptions(model_.specialOptions()|(512|32768)); + if (value == 2) { + value = 1; + int more2 = parameters_[whichParam(CBC_PARAM_INT_MOREMOREMIPOPTIONS, parameters_)].intValue(); + parameters_[whichParam(CBC_PARAM_INT_MOREMOREMIPOPTIONS, parameters_)].setIntValue(more2|1048576); + } + } +#endif + if (value > 1) { + int values[] = { 24003, 280003, 792003, 24003, 24003 }; + if (value >= 2 && value <= 3) { + // swap default diving + int iParam = whichParam(CBC_PARAM_STR_DIVINGC, parameters_); + parameters_[iParam].setCurrentOption("off"); + iParam = whichParam(CBC_PARAM_STR_DIVINGP, parameters_); + parameters_[iParam].setCurrentOption("on"); + } + int extra4 = values[value - 1] + addFlags; + parameters_[whichParam(CBC_PARAM_INT_EXTRA4, parameters_)].setIntValue(extra4); + if (!noPrinting_) { + generalMessageHandler->message(CLP_GENERAL, generalMessages) + << "switching on global root cuts for gomory and knapsack" + << CoinMessageEol; + generalMessageHandler->message(CLP_GENERAL, generalMessages) + << "using OSL factorization" + << CoinMessageEol; + generalMessageHandler->message(CLP_GENERAL, generalMessages) + << "extra options - -rens on -extra4 " + << extra4 << " -passc 1000!" + << CoinMessageEol; + } + parameters_[whichParam(CBC_PARAM_STR_PROBINGCUTS, parameters_)].setCurrentOption("forceOnStrong"); + probingAction = 8; + parameters_[whichParam(CBC_PARAM_STR_GOMORYCUTS, parameters_)].setCurrentOption("onGlobal"); + gomoryAction = 5; + parameters_[whichParam(CBC_PARAM_STR_KNAPSACKCUTS, parameters_)].setCurrentOption("onGlobal"); + knapsackAction = 5; + parameters_[whichParam(CLP_PARAM_STR_FACTORIZATION, parameters_)].setCurrentOption("osl"); + lpSolver->factorization()->forceOtherFactorization(3); + parameters_[whichParam(CBC_PARAM_INT_MAXHOTITS, parameters_)].setIntValue(100); + parameters_[whichParam(CBC_PARAM_INT_CUTPASS, parameters_)].setIntValue(1000); + cutPass = 1000; + parameters_[whichParam(CBC_PARAM_STR_RENS, parameters_)].setCurrentOption("on"); + } + } else if (parameters_[iParam].type() == CBC_PARAM_INT_STRATEGY) { + if (value == 0) { + gomoryGen.setAwayAtRoot(0.05); + int iParam; + iParam = whichParam(CBC_PARAM_INT_DIVEOPT, parameters_); + parameters_[iParam].setIntValue(-1); + iParam = whichParam(CBC_PARAM_INT_FPUMPITS, parameters_); + parameters_[iParam].setIntValue(20); + iParam = whichParam(CBC_PARAM_INT_FPUMPTUNE, parameters_); + parameters_[iParam].setIntValue(1003); + initialPumpTune = 1003; + iParam = whichParam(CLP_PARAM_INT_PROCESSTUNE, parameters_); + parameters_[iParam].setIntValue(0); + tunePreProcess = 0; + iParam = whichParam(CBC_PARAM_STR_DIVINGC, parameters_); + parameters_[iParam].setCurrentOption("off"); + iParam = whichParam(CBC_PARAM_STR_RINS, parameters_); + parameters_[iParam].setCurrentOption("off"); + iParam = whichParam(CBC_PARAM_STR_PROBINGCUTS, parameters_); + // but not if cuts off + int jParam = whichParam(CBC_PARAM_STR_CUTSSTRATEGY, parameters_); + + jParam = parameters_[jParam].currentOptionAsInteger(); + if (jParam) { + parameters_[iParam].setCurrentOption("on"); + probingAction = 1; + } else { + parameters_[iParam].setCurrentOption("off"); + probingAction = 0; + } + } + } + int returnCode; + const char *message = parameters_[iParam].setIntParameterWithMessage(model_, value, returnCode); + if (!noPrinting_ && strlen(message)) { + generalMessageHandler->message(CLP_GENERAL, generalMessages) + << message + << CoinMessageEol; + } + } + } else if (valid == 1) { + std::cout << "String of " << getCoinErrorField(); + std::cout << " is illegal for integer parameter " << parameters_[iParam].name() << " value remains " << parameters_[iParam].intValue() << std::endl; + } else { + std::cout << parameters_[iParam].name() << " has value " << parameters_[iParam].intValue() << std::endl; + } + } else if (type < 401) { + // one of several strings + std::string value = CoinReadGetString(argc, argv); + int action = parameters_[iParam].parameterOption(value); + if (action < 0) { + if (value != "EOL") { + // no match + parameters_[iParam].printOptions(); + } else { + // print current value + std::cout << parameters_[iParam].name() << " has value " << parameters_[iParam].currentOption() << std::endl; + } + } else { + const char *message = parameters_[iParam].setCurrentOptionWithMessage(action); + if (!noPrinting_ && strlen(message)) { + generalMessageHandler->message(CLP_GENERAL, generalMessages) + << message + << CoinMessageEol; + } + // for now hard wired + switch (type) { + case CLP_PARAM_STR_DIRECTION: + if (action == 0) + lpSolver->setOptimizationDirection(1); + else if (action == 1) + lpSolver->setOptimizationDirection(-1); + else + lpSolver->setOptimizationDirection(0); + break; + case CLP_PARAM_STR_DUALPIVOT: + if (action == 0) { + ClpDualRowSteepest steep(3); + lpSolver->setDualRowPivotAlgorithm(steep); + } else if (action == 1) { + ClpDualRowDantzig dantzig; + //ClpDualRowSteepest dantzig(5); + lpSolver->setDualRowPivotAlgorithm(dantzig); + } else if (action == 2) { + // partial steep + ClpDualRowSteepest steep(2); + lpSolver->setDualRowPivotAlgorithm(steep); + } else if (action == 3) { + ClpDualRowSteepest steep; + lpSolver->setDualRowPivotAlgorithm(steep); + } else if (action == 4) { + // Positive edge steepest + ClpPEDualRowSteepest p(fabs(parameters_[whichParam(CLP_PARAM_DBL_PSI, parameters_)].doubleValue())); + lpSolver->setDualRowPivotAlgorithm(p); + } else if (action == 5) { + // Positive edge Dantzig + ClpPEDualRowDantzig p(fabs(parameters_[whichParam(CLP_PARAM_DBL_PSI, parameters_)].doubleValue())); + lpSolver->setDualRowPivotAlgorithm(p); + } + break; + case CLP_PARAM_STR_PRIMALPIVOT: + if (action == 0) { + ClpPrimalColumnSteepest steep(3); + lpSolver->setPrimalColumnPivotAlgorithm(steep); + } else if (action == 1) { + ClpPrimalColumnSteepest steep(0); + lpSolver->setPrimalColumnPivotAlgorithm(steep); + } else if (action == 2) { + ClpPrimalColumnDantzig dantzig; + lpSolver->setPrimalColumnPivotAlgorithm(dantzig); + } else if (action == 3) { + ClpPrimalColumnSteepest steep(4); + lpSolver->setPrimalColumnPivotAlgorithm(steep); + } else if (action == 4) { + ClpPrimalColumnSteepest steep(1); + lpSolver->setPrimalColumnPivotAlgorithm(steep); + } else if (action == 5) { + ClpPrimalColumnSteepest steep(2); + lpSolver->setPrimalColumnPivotAlgorithm(steep); + } else if (action == 6) { + ClpPrimalColumnSteepest steep(10); + lpSolver->setPrimalColumnPivotAlgorithm(steep); + } else if (action == 7) { + // Positive edge steepest + ClpPEPrimalColumnSteepest p(fabs(parameters_[whichParam(CLP_PARAM_DBL_PSI, parameters_)].doubleValue())); + lpSolver->setPrimalColumnPivotAlgorithm(p); + } else if (action == 8) { + // Positive edge Dantzig + ClpPEPrimalColumnDantzig p(fabs(parameters_[whichParam(CLP_PARAM_DBL_PSI, parameters_)].doubleValue())); + lpSolver->setPrimalColumnPivotAlgorithm(p); + } + break; + case CLP_PARAM_STR_SCALING: + lpSolver->scaling(action); + solver->setHintParam(OsiDoScale, action != 0, OsiHintTry); + doScaling = action; + break; + case CLP_PARAM_STR_AUTOSCALE: + lpSolver->setAutomaticScaling(action != 0); + break; + case CLP_PARAM_STR_SPARSEFACTOR: + lpSolver->setSparseFactorization((1 - action) != 0); + break; + case CLP_PARAM_STR_BIASLU: + lpSolver->factorization()->setBiasLU(action); + break; + case CLP_PARAM_STR_PERTURBATION: + if (action == 0) + lpSolver->setPerturbation(50); + else + lpSolver->setPerturbation(100); + break; + case CLP_PARAM_STR_ERRORSALLOWED: + allowImportErrors = action; + break; + case CLP_PARAM_STR_INTPRINT: + printMode = action; + break; + //case CLP_PARAM_NOTUSED_ALGORITHM: + //algorithm = action; + //defaultSettings=false; // user knows what she is doing + //abort(); + //break; + case CLP_PARAM_STR_KEEPNAMES: + keepImportNames = 1 - action; + break; + case CLP_PARAM_STR_PRESOLVE: + if (action == 0) + preSolve = 5; + else if (action == 1) + preSolve = 0; + else if (action == 2) + preSolve = 10; + else + preSolveFile = true; + break; + case CLP_PARAM_STR_PFI: + lpSolver->factorization()->setForrestTomlin(action == 0); + break; + case CLP_PARAM_STR_FACTORIZATION: + lpSolver->factorization()->forceOtherFactorization(action); + break; + case CLP_PARAM_STR_CRASH: + doCrash = action; + break; + case CLP_PARAM_STR_VECTOR: + doVector = action; + break; + case CLP_PARAM_STR_MESSAGES: + lpSolver->messageHandler()->setPrefix(action != 0); + break; + case CLP_PARAM_STR_CHOLESKY: + choleskyType = action; + break; + case CLP_PARAM_STR_GAMMA: + gamma = action; + break; + case CLP_PARAM_STR_BARRIERSCALE: + scaleBarrier = action; + break; + case CLP_PARAM_STR_KKT: + doKKT = action; + break; + case CLP_PARAM_STR_CROSSOVER: + crossover = action; + break; + case CLP_PARAM_STR_TIME_MODE: + model_.setUseElapsedTime(action != 0); + break; + case CBC_PARAM_STR_SOS: + doSOS = action; + break; + case CBC_PARAM_STR_CLQSTRENGTHENING: + clqstrAction = value; + break; + case CBC_PARAM_STR_USECGRAPH: + cgraphAction = value; + break; + case CBC_PARAM_STR_CLIQUECUTS: + defaultSettings = false; // user knows what she is doing + cliqueAction = action; + break; + case CBC_PARAM_STR_ODDWHEELCUTS: + defaultSettings = false; // user knows what she is doing + oddWheelAction = action; + break; + case CBC_PARAM_STR_GOMORYCUTS: + defaultSettings = false; // user knows what she is doing + gomoryAction = action; + break; + case CBC_PARAM_STR_PROBINGCUTS: + defaultSettings = false; // user knows what she is doing + probingAction = action; + break; + case CBC_PARAM_STR_KNAPSACKCUTS: + defaultSettings = false; // user knows what she is doing + knapsackAction = action; + break; + case CBC_PARAM_STR_REDSPLITCUTS: + defaultSettings = false; // user knows what she is doing + redsplitAction = action; + break; + case CBC_PARAM_STR_REDSPLIT2CUTS: + defaultSettings = false; // user knows what she is doing + redsplit2Action = action; + break; + case CBC_PARAM_STR_GMICUTS: + defaultSettings = false; // user knows what she is doing + GMIAction = action; + break; + case CBC_PARAM_STR_FLOWCUTS: + defaultSettings = false; // user knows what she is doing + flowAction = action; + break; + case CBC_PARAM_STR_MIXEDCUTS: + defaultSettings = false; // user knows what she is doing + mixedAction = action; + break; + case CBC_PARAM_STR_TWOMIRCUTS: + defaultSettings = false; // user knows what she is doing + twomirAction = action; + break; + case CBC_PARAM_STR_LANDPCUTS: + defaultSettings = false; // user knows what she is doing + landpAction = action; + break; + case CBC_PARAM_STR_RESIDCUTS: + defaultSettings = false; // user knows what she is doing + residualCapacityAction = action; + break; + case CBC_PARAM_STR_ZEROHALFCUTS: + defaultSettings = false; // user knows what she is doing + zerohalfAction = action; + break; + case CBC_PARAM_STR_ROUNDING: + defaultSettings = false; // user knows what she is doing + break; + case CBC_PARAM_STR_FPUMP: + defaultSettings = false; // user knows what she is doing + break; + case CBC_PARAM_STR_RINS: + break; + case CBC_PARAM_STR_DINS: + break; + case CBC_PARAM_STR_RENS: + break; + case CBC_PARAM_STR_CUTSSTRATEGY: + gomoryAction = action; + probingAction = action; + knapsackAction = action; + cliqueAction = action; + flowAction = action; + mixedAction = action; + twomirAction = action; + zerohalfAction = action; + oddWheelAction = action; + parameters_[whichParam(CBC_PARAM_STR_GOMORYCUTS, parameters_)].setCurrentOption(action); + parameters_[whichParam(CBC_PARAM_STR_PROBINGCUTS, parameters_)].setCurrentOption(action); + parameters_[whichParam(CBC_PARAM_STR_KNAPSACKCUTS, parameters_)].setCurrentOption(action); + parameters_[whichParam(CBC_PARAM_STR_CLIQUECUTS, parameters_)].setCurrentOption(action); + parameters_[whichParam(CBC_PARAM_STR_FLOWCUTS, parameters_)].setCurrentOption(action); + parameters_[whichParam(CBC_PARAM_STR_MIXEDCUTS, parameters_)].setCurrentOption(action); + parameters_[whichParam(CBC_PARAM_STR_TWOMIRCUTS, parameters_)].setCurrentOption(action); + parameters_[whichParam(CBC_PARAM_STR_ZEROHALFCUTS, parameters_)].setCurrentOption(action); + parameters_[whichParam(CBC_PARAM_STR_ODDWHEELCUTS, parameters_)].setCurrentOption(action); + if (!action) { + // switch off clique strengthening + clqstrAction = "off"; + } + break; + case CBC_PARAM_STR_HEURISTICSTRATEGY: + parameters_[whichParam(CBC_PARAM_STR_ROUNDING, parameters_)].setCurrentOption(action); + parameters_[whichParam(CBC_PARAM_STR_GREEDY, parameters_)].setCurrentOption(action); + parameters_[whichParam(CBC_PARAM_STR_COMBINE, parameters_)].setCurrentOption(action); + //parameters_[whichParam(CBC_PARAM_STR_LOCALTREE,numberParameters_,parameters_)].setCurrentOption(action); + parameters_[whichParam(CBC_PARAM_STR_FPUMP, parameters_)].setCurrentOption(action); + parameters_[whichParam(CBC_PARAM_STR_DIVINGC, parameters_)].setCurrentOption(action); + parameters_[whichParam(CBC_PARAM_STR_RINS, parameters_)].setCurrentOption(action); + break; + case CBC_PARAM_STR_GREEDY: + case CBC_PARAM_STR_DIVINGS: + case CBC_PARAM_STR_DIVINGC: + case CBC_PARAM_STR_DIVINGF: + case CBC_PARAM_STR_DIVINGG: + case CBC_PARAM_STR_DIVINGL: + case CBC_PARAM_STR_DIVINGP: + case CBC_PARAM_STR_DIVINGV: + case CBC_PARAM_STR_COMBINE: + case CBC_PARAM_STR_PIVOTANDCOMPLEMENT: + case CBC_PARAM_STR_PIVOTANDFIX: + case CBC_PARAM_STR_RANDROUND: + case CBC_PARAM_STR_LOCALTREE: + case CBC_PARAM_STR_NAIVE: + case CBC_PARAM_STR_CPX: + defaultSettings = false; // user knows what she is doing + break; + case CBC_PARAM_STR_COSTSTRATEGY: + useCosts = action; + break; + case CBC_PARAM_STR_NODESTRATEGY: + nodeStrategy = action; + break; + case CBC_PARAM_STR_PREPROCESS: + preProcess = action; + break; + default: + //abort(); + break; + } + } + } else { + // action + if (type == CLP_PARAM_ACTION_EXIT) { + if (statusUserFunction_[0]) { + if (info.numberIntegers || info.numberBinary) { + // integer + } else { + // linear + } + writeAmpl(&info); + freeArrays2(&info); + freeArgs(&info); + } + break; // stop all + } + switch (type) { + case CLP_PARAM_ACTION_DUALSIMPLEX: + case CLP_PARAM_ACTION_PRIMALSIMPLEX: + case CLP_PARAM_ACTION_SOLVECONTINUOUS: + case CLP_PARAM_ACTION_BARRIER: + if (goodModel) { + // Say not in integer + integerStatus = -1; + double objScale = parameters_[whichParam(CLP_PARAM_DBL_OBJSCALE2, parameters_)].doubleValue(); + // deal with positive edge + double psi = parameters_[whichParam(CLP_PARAM_DBL_PSI, parameters_)].doubleValue(); + if (psi > 0.0) { + ClpDualRowPivot *dualp = lpSolver->dualRowPivot(); + ClpDualRowSteepest *d1 = dynamic_cast< ClpDualRowSteepest * >(dualp); + ClpDualRowDantzig *d2 = dynamic_cast< ClpDualRowDantzig * >(dualp); + if (d1) { + ClpPEDualRowSteepest p(psi, d1->mode()); + lpSolver->setDualRowPivotAlgorithm(p); + } else if (d2) { + ClpPEDualRowDantzig p(psi); + lpSolver->setDualRowPivotAlgorithm(p); + } + ClpPrimalColumnPivot *primalp = lpSolver->primalColumnPivot(); + ClpPrimalColumnSteepest *p1 = dynamic_cast< ClpPrimalColumnSteepest * >(primalp); + ClpPrimalColumnDantzig *p2 = dynamic_cast< ClpPrimalColumnDantzig * >(primalp); + if (p1) { + ClpPEPrimalColumnSteepest p(psi, p1->mode()); + lpSolver->setPrimalColumnPivotAlgorithm(p); + } else if (p2) { + ClpPEPrimalColumnDantzig p(psi); + lpSolver->setPrimalColumnPivotAlgorithm(p); + } + } + if (objScale != 1.0) { + int iColumn; + int numberColumns = lpSolver->numberColumns(); + double *dualColumnSolution = lpSolver->dualColumnSolution(); + ClpObjective *obj = lpSolver->objectiveAsObject(); + assert(dynamic_cast< ClpLinearObjective * >(obj)); + double offset; + double *objective = obj->gradient(NULL, NULL, offset, true); + for (iColumn = 0; iColumn < numberColumns; iColumn++) { + dualColumnSolution[iColumn] *= objScale; + objective[iColumn] *= objScale; + ; + } + int iRow; + int numberRows = lpSolver->numberRows(); + double *dualRowSolution = lpSolver->dualRowSolution(); + for (iRow = 0; iRow < numberRows; iRow++) + dualRowSolution[iRow] *= objScale; + lpSolver->setObjectiveOffset(objScale * lpSolver->objectiveOffset()); + } + ClpSolve::SolveType method; + ClpSolve::PresolveType presolveType; + ClpSimplex *model2 = lpSolver; + if (dualize) { + bool tryIt = true; + double fractionColumn = 1.0; + double fractionRow = 1.0; + if (dualize == 3) { + dualize = 1; + int numberColumns = lpSolver->numberColumns(); + int numberRows = lpSolver->numberRows(); + if (numberRows < 50000 || 5 * numberColumns > numberRows) { + tryIt = false; + } else { + fractionColumn = 0.1; + fractionRow = 0.1; + } + } + if (tryIt) { + model2 = static_cast< ClpSimplexOther * >(model2)->dualOfModel(fractionRow, fractionColumn); + if (model2) { + sprintf(generalPrint, "Dual of model has %d rows and %d columns", + model2->numberRows(), model2->numberColumns()); + generalMessageHandler->message(CLP_GENERAL, generalMessages) + << generalPrint + << CoinMessageEol; + model2->setOptimizationDirection(1.0); + } else { + model2 = lpSolver; + dualize = 0; + } + } else { + dualize = 0; + } + } + if (noPrinting_) + lpSolver->setLogLevel(0); + ClpSolve solveOptions; + solveOptions.setPresolveActions(presolveOptions); + solveOptions.setSubstitution(substitution); + if (preSolve != 5 && preSolve) { + presolveType = ClpSolve::presolveNumber; + if (preSolve < 0) { + preSolve = -preSolve; + if (preSolve <= 100) { + presolveType = ClpSolve::presolveNumber; + sprintf(generalPrint, "Doing %d presolve passes - picking up non-costed slacks", + preSolve); + generalMessageHandler->message(CLP_GENERAL, generalMessages) + << generalPrint + << CoinMessageEol; + solveOptions.setDoSingletonColumn(true); + } else { + preSolve -= 100; + presolveType = ClpSolve::presolveNumberCost; + sprintf(generalPrint, "Doing %d presolve passes - picking up costed slacks", + preSolve); + generalMessageHandler->message(CLP_GENERAL, generalMessages) + << generalPrint + << CoinMessageEol; + } + } + } else if (preSolve) { + presolveType = ClpSolve::presolveOn; + } else { + presolveType = ClpSolve::presolveOff; + } + solveOptions.setPresolveType(presolveType, preSolve); + if (type == CLP_PARAM_ACTION_DUALSIMPLEX || type == CLP_PARAM_ACTION_SOLVECONTINUOUS) { + method = ClpSolve::useDual; + } else if (type == CLP_PARAM_ACTION_PRIMALSIMPLEX) { + method = ClpSolve::usePrimalorSprint; + } else { + method = ClpSolve::useBarrier; + if (crossover == 1) { + method = ClpSolve::useBarrierNoCross; + } else if (crossover == 2) { + ClpObjective *obj = lpSolver->objectiveAsObject(); + if (obj->type() > 1) { + method = ClpSolve::useBarrierNoCross; + presolveType = ClpSolve::presolveOff; + solveOptions.setPresolveType(presolveType, preSolve); + } + } + } + solveOptions.setSolveType(method); + if (preSolveFile) + presolveOptions |= 0x40000000; + solveOptions.setSpecialOption(4, presolveOptions); + solveOptions.setSpecialOption(5, printOptions); + if (doVector) { + ClpMatrixBase *matrix = lpSolver->clpMatrix(); + if (dynamic_cast< ClpPackedMatrix * >(matrix)) { + ClpPackedMatrix *clpMatrix = dynamic_cast< ClpPackedMatrix * >(matrix); + clpMatrix->makeSpecialColumnCopy(); + } + } + if (method == ClpSolve::useDual) { + // dual + if (doCrash) + solveOptions.setSpecialOption(0, 1, doCrash); // crash + else if (doIdiot) + solveOptions.setSpecialOption(0, 2, doIdiot); // possible idiot + } else if (method == ClpSolve::usePrimalorSprint) { + // primal + // if slp turn everything off + if (slpValue > 0) { + doCrash = false; + doSprint = 0; + doIdiot = -1; + solveOptions.setSpecialOption(1, 10, slpValue); // slp + method = ClpSolve::usePrimal; + } + if (doCrash) { + solveOptions.setSpecialOption(1, 1, doCrash); // crash + } else if (doSprint > 0) { + // sprint overrides idiot + solveOptions.setSpecialOption(1, 3, doSprint); // sprint + } else if (doIdiot > 0) { + solveOptions.setSpecialOption(1, 2, doIdiot); // idiot + } else if (slpValue <= 0) { + if (doIdiot == 0) { + if (doSprint == 0) + solveOptions.setSpecialOption(1, 4); // all slack + else + solveOptions.setSpecialOption(1, 9); // all slack or sprint + } else { + if (doSprint == 0) + solveOptions.setSpecialOption(1, 8); // all slack or idiot + else + solveOptions.setSpecialOption(1, 7); // initiative + } + } + if (basisHasValues == -1) + solveOptions.setSpecialOption(1, 11); // switch off values + } else if (method == ClpSolve::useBarrier || method == ClpSolve::useBarrierNoCross) { + int barrierOptions = choleskyType; + if (scaleBarrier) + barrierOptions |= 8; + if (doKKT) + barrierOptions |= 16; + if (gamma) + barrierOptions |= 32 * gamma; + if (crossover == 3) + barrierOptions |= 256; // try presolve in crossover + solveOptions.setSpecialOption(4, barrierOptions); + } + model2->setMaximumSeconds(model_.getMaximumSeconds()); +#ifdef COIN_HAS_LINK + OsiSolverInterface *coinSolver = model_.solver(); + OsiSolverLink *linkSolver = dynamic_cast< OsiSolverLink * >(coinSolver); + if (!linkSolver) { + model2->initialSolve(solveOptions); + } else { + // special solver + int testOsiOptions = parameters_[whichParam(CBC_PARAM_INT_TESTOSI, parameters_)].intValue(); + double *solution = NULL; + if (testOsiOptions < 10) { + solution = linkSolver->nonlinearSLP(slpValue > 0 ? slpValue : 20, 1.0e-5); + } else if (testOsiOptions >= 10) { + CoinModel coinModel = *linkSolver->coinModel(); + ClpSimplex *tempModel = approximateSolution(coinModel, slpValue > 0 ? slpValue : 50, 1.0e-5, 0); + assert(tempModel); + solution = CoinCopyOfArray(tempModel->primalColumnSolution(), coinModel.numberColumns()); + model2->setObjectiveValue(tempModel->objectiveValue()); + model2->setProblemStatus(tempModel->problemStatus()); + model2->setSecondaryStatus(tempModel->secondaryStatus()); + delete tempModel; + } + if (solution) { + memcpy(model2->primalColumnSolution(), solution, + CoinMin(model2->numberColumns(), linkSolver->coinModel()->numberColumns()) * sizeof(double)); + delete[] solution; + } else { + printf("No nonlinear solution\n"); + } + } +#else + model2->initialSolve(solveOptions); +#endif + { + // map states + /* clp status + -1 - unknown e.g. before solve or if postSolve says not optimal + 0 - optimal + 1 - primal infeasible + 2 - dual infeasible + 3 - stopped on iterations or time + 4 - stopped due to errors + 5 - stopped by event handler (virtual int ClpEventHandler::event()) */ + /* cbc status + -1 before branchAndBound + 0 finished - check isProvenOptimal or isProvenInfeasible to see if solution found + (or check value of best solution) + 1 stopped - on maxnodes, maxsols, maxtime + 2 difficulties so run was abandoned + (5 event user programmed event occurred) */ + /* clp secondary status of problem - may get extended + 0 - none + 1 - primal infeasible because dual limit reached OR probably primal + infeasible but can't prove it (main status 4) + 2 - scaled problem optimal - unscaled problem has primal infeasibilities + 3 - scaled problem optimal - unscaled problem has dual infeasibilities + 4 - scaled problem optimal - unscaled problem has primal and dual infeasibilities + 5 - giving up in primal with flagged variables + 6 - failed due to empty problem check + 7 - postSolve says not optimal + 8 - failed due to bad element check + 9 - status was 3 and stopped on time + 100 up - translation of enum from ClpEventHandler + */ + /* cbc secondary status of problem + -1 unset (status_ will also be -1) + 0 search completed with solution + 1 linear relaxation not feasible (or worse than cutoff) + 2 stopped on gap + 3 stopped on nodes + 4 stopped on time + 5 stopped on user event + 6 stopped on solutions + 7 linear relaxation unbounded + 8 stopped on iterations limit + */ + int iStatus = model2->status(); + int iStatus2 = model2->secondaryStatus(); + if (iStatus == 0) { + iStatus2 = 0; + if (found.type() == CBC_PARAM_ACTION_BAB) { + // set best solution in model as no integers + model_.setBestSolution(model2->primalColumnSolution(), + model2->numberColumns(), + model2->getObjValue() * model2->getObjSense()); + } + } else if (iStatus == 1) { + iStatus = 0; + iStatus2 = 1; // say infeasible + } else if (iStatus == 2) { + iStatus = 0; + iStatus2 = 7; // say unbounded + } else if (iStatus == 3) { + iStatus = 1; + if (iStatus2 == 9) // what does 9 mean ????????????? + iStatus2 = 4; + else + iStatus2 = 3; // Use nodes - as closer than solutions + } else if (iStatus == 4) { + iStatus = 2; // difficulties + iStatus2 = 0; + } + model_.setProblemStatus(iStatus); + model_.setSecondaryStatus(iStatus2); + if ((iStatus == 2 || iStatus2 > 0) && !noPrinting_) { + std::string statusName[] = { "", "Stopped on ", "Run abandoned", "", "", "User ctrl-c" }; + std::string minor[] = { "Optimal solution found", "Linear relaxation infeasible", "Optimal solution found (within gap tolerance)", "node limit", "time limit", "user ctrl-c", "solution limit", "Linear relaxation unbounded", "iterations limit", "Problem proven infeasible" }; + sprintf(generalPrint, "\nResult - %s%s\n\n", + statusName[iStatus].c_str(), + minor[iStatus2].c_str()); + sprintf(generalPrint + strlen(generalPrint), + "Enumerated nodes: 0\n"); + sprintf(generalPrint + strlen(generalPrint), + "Total iterations: 0\n"); +#if CBC_QUIET == 0 + sprintf(generalPrint + strlen(generalPrint), + "Time (CPU seconds): %.2f\n", + CoinCpuTime() - time0); + sprintf(generalPrint + strlen(generalPrint), + "Time (Wallclock Seconds): %.2f\n", + CoinGetTimeOfDay() - time0Elapsed); +#endif + generalMessageHandler->message(CLP_GENERAL, generalMessages) + << generalPrint + << CoinMessageEol; + } + //assert (lpSolver==clpSolver->getModelPtr()); + assert(clpSolver == model_.solver()); + clpSolver->setWarmStart(NULL); + // and in babModel if exists + if (babModel_) { + babModel_->setProblemStatus(iStatus); + babModel_->setSecondaryStatus(iStatus2); + } + int returnCode = callBack(&model, 1); + if (returnCode) { + // exit if user wants + delete babModel_; + babModel_ = NULL; + return returnCode; + } + } + basisHasValues = 1; + if (dualize) { + int returnCode = static_cast< ClpSimplexOther * >(lpSolver)->restoreFromDual(model2); + if (model2->status() == 3) + returnCode = 0; + delete model2; + if (returnCode && dualize != 2) + lpSolver->primal(1); + model2 = lpSolver; + } + if (statusUserFunction_[0]) { + double value = model2->getObjValue(); + char buf[300]; + int pos = 0; + int iStat = model2->status(); + if (iStat == 0) { + pos += sprintf(buf + pos, "optimal,"); + } else if (iStat == 1) { + // infeasible + pos += sprintf(buf + pos, "infeasible,"); + } else if (iStat == 2) { + // unbounded + pos += sprintf(buf + pos, "unbounded,"); + } else if (iStat == 3) { + pos += sprintf(buf + pos, "stopped on iterations or time,"); + } else if (iStat == 4) { + iStat = 7; + pos += sprintf(buf + pos, "stopped on difficulties,"); + } else if (iStat == 5) { + iStat = 3; + pos += sprintf(buf + pos, "stopped on ctrl-c,"); + } else if (iStat == 6) { + // bab infeasible + pos += sprintf(buf + pos, "integer infeasible,"); + iStat = 1; + } else { + pos += sprintf(buf + pos, "status unknown,"); + iStat = 6; + } + info.problemStatus = iStat; + info.objValue = value; + pos += sprintf(buf + pos, " objective %.*g", ampl_obj_prec(), + value); + sprintf(buf + pos, "\n%d iterations", + model2->getIterationCount()); + free(info.primalSolution); + int numberColumns = model2->numberColumns(); + info.primalSolution = reinterpret_cast< double * >(malloc(numberColumns * sizeof(double))); + CoinCopyN(model2->primalColumnSolution(), numberColumns, info.primalSolution); + int numberRows = model2->numberRows(); + free(info.dualSolution); + info.dualSolution = reinterpret_cast< double * >(malloc(numberRows * sizeof(double))); + CoinCopyN(model2->dualRowSolution(), numberRows, info.dualSolution); + CoinWarmStartBasis *basis = model2->getBasis(); + free(info.rowStatus); + info.rowStatus = reinterpret_cast< int * >(malloc(numberRows * sizeof(int))); + free(info.columnStatus); + info.columnStatus = reinterpret_cast< int * >(malloc(numberColumns * sizeof(int))); + // Put basis in + int i; + // free,basic,ub,lb are 0,1,2,3 + for (i = 0; i < numberRows; i++) { + CoinWarmStartBasis::Status status = basis->getArtifStatus(i); + info.rowStatus[i] = status; + } + for (i = 0; i < numberColumns; i++) { + CoinWarmStartBasis::Status status = basis->getStructStatus(i); + info.columnStatus[i] = status; + } + // put buffer into info + strcpy(info.buffer, buf); + delete basis; + } + } else { + sprintf(generalPrint, "** Current model not valid"); + printGeneralMessage(model_, generalPrint); + } + break; + case CLP_PARAM_ACTION_STATISTICS: + if (goodModel) { + // If presolve on look at presolved + bool deleteModel2 = false; + ClpSimplex *model2 = lpSolver; + if (preSolve) { + ClpPresolve pinfo; + int presolveOptions2 = presolveOptions & ~0x40000000; + if ((presolveOptions2 & 0xffff) != 0) + pinfo.setPresolveActions(presolveOptions2); + pinfo.setSubstitution(substitution); + if ((printOptions & 1) != 0) + pinfo.statistics(); + double presolveTolerance = parameters_[whichParam(CLP_PARAM_DBL_PRESOLVETOLERANCE, parameters_)].doubleValue(); + model2 = pinfo.presolvedModel(*lpSolver, presolveTolerance, + true, preSolve); + if (model2) { + printf("Statistics for presolved model\n"); + deleteModel2 = true; + } else { + printf("Presolved model looks infeasible - will use unpresolved\n"); + model2 = lpSolver; + } + } else { + printf("Statistics for unpresolved model\n"); + model2 = lpSolver; + } + statistics(lpSolver, model2); + if (deleteModel2) + delete model2; + } else { + sprintf(generalPrint, "** Current model not valid"); + printGeneralMessage(model_, generalPrint); + } + break; + case CLP_PARAM_ACTION_TIGHTEN: + if (goodModel) { + int numberInfeasibilities = lpSolver->tightenPrimalBounds(); + if (numberInfeasibilities) { + sprintf(generalPrint, "** Analysis indicates model infeasible"); + printGeneralMessage(model_, generalPrint); + } + } else { + sprintf(generalPrint, "** Current model not valid"); + printGeneralMessage(model_, generalPrint); + } + break; + case CLP_PARAM_ACTION_PLUSMINUS: + if (goodModel) { + ClpMatrixBase *saveMatrix = lpSolver->clpMatrix(); + ClpPackedMatrix *clpMatrix = dynamic_cast< ClpPackedMatrix * >(saveMatrix); + if (clpMatrix) { + ClpPlusMinusOneMatrix *newMatrix = new ClpPlusMinusOneMatrix(*(clpMatrix->matrix())); + if (newMatrix->getIndices()) { + lpSolver->replaceMatrix(newMatrix); + delete saveMatrix; + sprintf(generalPrint, "Matrix converted to +- one matrix"); + printGeneralMessage(model_, generalPrint); + } else { + sprintf(generalPrint, "Matrix can not be converted to +- 1 matrix"); + printGeneralMessage(model_, generalPrint); + } + } else { + sprintf(generalPrint, "Matrix not a ClpPackedMatrix"); + printGeneralMessage(model_, generalPrint); + } + } else { + sprintf(generalPrint, "** Current model not valid"); + printGeneralMessage(model_, generalPrint); + } + break; + case CLP_PARAM_ACTION_OUTDUPROWS: + dominatedCuts = true; +#ifdef JJF_ZERO + if (goodModel) { + int numberRows = clpSolver->getNumRows(); + //int nOut = outDupRow(clpSolver); + CglDuplicateRow dupcuts(clpSolver); + storedCuts = dupcuts.outDuplicates(clpSolver) != 0; + int nOut = numberRows - clpSolver->getNumRows(); + if (nOut && !noPrinting_) + sprintf(generalPrint, "%d rows eliminated", nOut); + generalMessageHandler->message(CLP_GENERAL, generalMessages) + << generalPrint + << CoinMessageEol; + } else { + sprintf(generalPrint, "** Current model not valid"); + printGeneralMessage(model_, generalPrint); + } +#endif + break; + case CLP_PARAM_ACTION_NETWORK: + if (goodModel) { + ClpMatrixBase *saveMatrix = lpSolver->clpMatrix(); + ClpPackedMatrix *clpMatrix = dynamic_cast< ClpPackedMatrix * >(saveMatrix); + if (clpMatrix) { + ClpNetworkMatrix *newMatrix = new ClpNetworkMatrix(*(clpMatrix->matrix())); + if (newMatrix->getIndices()) { + lpSolver->replaceMatrix(newMatrix); + delete saveMatrix; + sprintf(generalPrint, "Matrix converted to network matrix"); + printGeneralMessage(model_, generalPrint); + } else { + sprintf(generalPrint, "Matrix can not be converted to network matrix"); + printGeneralMessage(model_, generalPrint); + } + } else { + sprintf(generalPrint, "Matrix not a ClpPackedMatrix"); + printGeneralMessage(model_, generalPrint); + } + } else { + sprintf(generalPrint, "** Current model not valid"); + printGeneralMessage(model_, generalPrint); + } + break; + case CBC_PARAM_ACTION_DOHEURISTIC: + if (goodModel) { +#if CBC_USE_INITIAL_TIME==1 + if (model_.useElapsedTime()) + model_.setDblParam(CbcModel::CbcStartSeconds, CoinGetTimeOfDay()); + else + model_.setDblParam(CbcModel::CbcStartSeconds, CoinCpuTime()); +#endif + int vubAction = parameters_[whichParam(CBC_PARAM_INT_VUBTRY, parameters_)].intValue(); + if (vubAction != -1) { + // look at vubs + // extra1 is number of ints to leave free + // Just ones which affect >= extra3 + int extra3 = parameters_[whichParam(CBC_PARAM_INT_EXTRA3, parameters_)].intValue(); + /* 2 is cost above which to fix if feasible + 3 is fraction of integer variables fixed if relaxing (0.97) + 4 is fraction of all variables fixed if relaxing (0.0) + */ + double dextra[6]; + int extra[5]; + extra[1] = parameters_[whichParam(CBC_PARAM_INT_EXTRA1, parameters_)].intValue(); + int exp1 = parameters_[whichParam(CBC_PARAM_INT_EXPERIMENT, parameters_)].intValue(); + if (exp1 == 4 && extra[1] == -1) + extra[1] = 999998; + dextra[1] = parameters_[whichParam(CBC_PARAM_DBL_FAKEINCREMENT, parameters_)].doubleValue(); + dextra[2] = parameters_[whichParam(CBC_PARAM_DBL_FAKECUTOFF, parameters_)].doubleValue(); + dextra[3] = parameters_[whichParam(CBC_PARAM_DBL_DEXTRA3, parameters_)].doubleValue(); + dextra[4] = parameters_[whichParam(CBC_PARAM_DBL_DEXTRA4, parameters_)].doubleValue(); + dextra[5] = parameters_[whichParam(CBC_PARAM_DBL_DEXTRA5, parameters_)].doubleValue(); + if (!dextra[3]) + dextra[3] = 0.97; + //OsiClpSolverInterface * newSolver = + fixVubs(model_, extra3, vubAction, generalMessageHandler, + debugValues, dextra, extra); + //assert (!newSolver); + } + // Actually do heuristics + // may need to flip objective + bool needFlip = model_.solver()->getObjSense() < 0.0; + if (needFlip) + model_.flipModel(); + //if we do then - fix priorities in clonebutmodel_.convertToDynamic(); + bool objectsExist = model_.objects() != NULL; + if (!objectsExist) { + model_.findIntegers(false); + model_.convertToDynamic(); + } + // set priorities etc + if (priorities) { + OsiObject **objects = model_.objects(); + int numberObjects = model_.numberObjects(); + for (int iObj = 0; iObj < numberObjects; iObj++) { + CbcSimpleInteger *obj = dynamic_cast< CbcSimpleInteger * >(objects[iObj]); + if (!obj) + continue; + int iColumn = obj->columnNumber(); + if (branchDirection) { + obj->setPreferredWay(branchDirection[iColumn]); + } + if (priorities) { + int iPriority = priorities[iColumn]; + if (iPriority > 0) + obj->setPriority(iPriority); + } + if (pseudoUp && pseudoUp[iColumn]) { + CbcSimpleIntegerPseudoCost *obj1a = dynamic_cast< CbcSimpleIntegerPseudoCost * >(objects[iObj]); + assert(obj1a); + if (pseudoDown[iColumn] > 0.0) + obj1a->setDownPseudoCost(pseudoDown[iColumn]); + if (pseudoUp[iColumn] > 0.0) + obj1a->setUpPseudoCost(pseudoUp[iColumn]); + } + } + } + doHeuristics(&model_, 2, parameters_, + noPrinting_, initialPumpTune); + if (!objectsExist) { + model_.deleteObjects(false); + } + if (needFlip) + model_.flipModel(); + if (model_.bestSolution()) { + model_.setProblemStatus(1); + model_.setSecondaryStatus(6); + if (statusUserFunction_[0]) { + double value = model_.getObjValue(); + char buf[300]; + int pos = 0; + pos += sprintf(buf + pos, "feasible,"); + info.problemStatus = 0; + info.objValue = value; + pos += sprintf(buf + pos, " objective %.*g", ampl_obj_prec(), + value); + sprintf(buf + pos, "\n0 iterations"); + free(info.primalSolution); + int numberColumns = lpSolver->numberColumns(); + info.primalSolution = reinterpret_cast< double * >(malloc(numberColumns * sizeof(double))); + CoinCopyN(model_.bestSolution(), numberColumns, info.primalSolution); + int numberRows = lpSolver->numberRows(); + free(info.dualSolution); + info.dualSolution = reinterpret_cast< double * >(malloc(numberRows * sizeof(double))); + CoinZeroN(info.dualSolution, numberRows); + CoinWarmStartBasis *basis = lpSolver->getBasis(); + free(info.rowStatus); + info.rowStatus = reinterpret_cast< int * >(malloc(numberRows * sizeof(int))); + free(info.columnStatus); + info.columnStatus = reinterpret_cast< int * >(malloc(numberColumns * sizeof(int))); + // Put basis in + int i; + // free,basic,ub,lb are 0,1,2,3 + for (i = 0; i < numberRows; i++) { + CoinWarmStartBasis::Status status = basis->getArtifStatus(i); + info.rowStatus[i] = status; + } + for (i = 0; i < numberColumns; i++) { + CoinWarmStartBasis::Status status = basis->getStructStatus(i); + info.columnStatus[i] = status; + } + // put buffer into info + strcpy(info.buffer, buf); + delete basis; + } + } + int returnCode = callBack(&model, 6); + if (returnCode) { + // exit if user wants + delete babModel_; + babModel_ = NULL; + return returnCode; + } + } + break; + case CBC_PARAM_ACTION_MIPLIB: + // User can set options - main difference is lack of model and CglPreProcess + goodModel = true; + parameters_[whichParam(CBC_PARAM_INT_MULTIPLEROOTS, parameters_)].setIntValue(0); + /* + Run branch-and-cut. First set a few options -- node comparison, scaling. + Print elapsed time at the end. + */ + case CBC_PARAM_ACTION_BAB: // branchAndBound + // obsolete case STRENGTHEN: + if (goodModel) { + bool miplib = type == CBC_PARAM_ACTION_MIPLIB; + int logLevel = parameters_[slog].intValue(); + int truncateColumns = COIN_INT_MAX; + int truncateRows = -1; + bool redoSOS = false; + double *truncatedRhsLower = NULL; + double *truncatedRhsUpper = NULL; + int *newPriorities = NULL; + // Reduce printout + if (logLevel <= 1) { + model_.solver()->setHintParam(OsiDoReducePrint, true, OsiHintTry); + } else { + model_.solver()->setHintParam(OsiDoReducePrint, false, OsiHintTry); + } + { + OsiSolverInterface *solver = model_.solver(); +#ifndef CBC_OTHER_SOLVER + OsiClpSolverInterface *si = dynamic_cast< OsiClpSolverInterface * >(solver); + assert(si != NULL); + si->getModelPtr()->scaling(doScaling); + ClpSimplex *lpSolver = si->getModelPtr(); + // deal with positive edge + double psi = parameters_[whichParam(CLP_PARAM_DBL_PSI, parameters_)].doubleValue(); + if (psi > 0.0) { + ClpDualRowPivot *dualp = lpSolver->dualRowPivot(); + ClpDualRowSteepest *d1 = dynamic_cast< ClpDualRowSteepest * >(dualp); + ClpDualRowDantzig *d2 = dynamic_cast< ClpDualRowDantzig * >(dualp); + if (d1) { + ClpPEDualRowSteepest p(psi, d1->mode()); + lpSolver->setDualRowPivotAlgorithm(p); + } else if (d2) { + ClpPEDualRowDantzig p(psi); + lpSolver->setDualRowPivotAlgorithm(p); + } + ClpPrimalColumnPivot *primalp = lpSolver->primalColumnPivot(); + ClpPrimalColumnSteepest *p1 = dynamic_cast< ClpPrimalColumnSteepest * >(primalp); + ClpPrimalColumnDantzig *p2 = dynamic_cast< ClpPrimalColumnDantzig * >(primalp); + if (p1) { + ClpPEPrimalColumnSteepest p(psi, p1->mode()); + lpSolver->setPrimalColumnPivotAlgorithm(p); + } else if (p2) { + ClpPEPrimalColumnDantzig p(psi); + lpSolver->setPrimalColumnPivotAlgorithm(p); + } + } + if (doVector) { + ClpMatrixBase *matrix = lpSolver->clpMatrix(); + if (dynamic_cast< ClpPackedMatrix * >(matrix)) { + ClpPackedMatrix *clpMatrix = dynamic_cast< ClpPackedMatrix * >(matrix); + clpMatrix->makeSpecialColumnCopy(); + } + } +#elif CBC_OTHER_SOLVER == 1 + OsiCpxSolverInterface *si = dynamic_cast< OsiCpxSolverInterface * >(solver); + assert(si != NULL); +#endif + statistics_nrows = si->getNumRows(); + statistics_ncols = si->getNumCols(); + statistics_nprocessedrows = si->getNumRows(); + statistics_nprocessedcols = si->getNumCols(); + // See if quadratic +#ifndef CBC_OTHER_SOLVER +#ifdef COIN_HAS_LINK + if (!complicatedInteger) { + ClpQuadraticObjective *obj = (dynamic_cast< ClpQuadraticObjective * >(lpSolver->objectiveAsObject())); + if (obj) { + preProcess = 0; + int testOsiOptions = parameters_[whichParam(CBC_PARAM_INT_TESTOSI, parameters_)].intValue(); + parameters_[whichParam(CBC_PARAM_INT_TESTOSI, parameters_)].setIntValue(CoinMax(0, testOsiOptions)); + // create coin model + coinModel = lpSolver->createCoinModel(); + assert(coinModel); + // load from coin model + OsiSolverLink solver1; + OsiSolverInterface *solver2 = solver1.clone(); + model_.assignSolver(solver2, false); + OsiSolverLink *si = dynamic_cast< OsiSolverLink * >(model_.solver()); + assert(si != NULL); + si->setDefaultMeshSize(0.001); + // need some relative granularity + si->setDefaultBound(100.0); + double dextra3 = parameters_[whichParam(CBC_PARAM_DBL_DEXTRA3, parameters_)].doubleValue(); + if (dextra3) + si->setDefaultMeshSize(dextra3); + si->setDefaultBound(1000.0); + si->setIntegerPriority(1000); + si->setBiLinearPriority(10000); + biLinearProblem = true; + si->setSpecialOptions2(2 + 4 + 8); + CoinModel *model2 = coinModel; + si->load(*model2, true, parameters_[log].intValue()); + // redo + solver = model_.solver(); + clpSolver = dynamic_cast< OsiClpSolverInterface * >(solver); + lpSolver = clpSolver->getModelPtr(); + clpSolver->messageHandler()->setLogLevel(0); + testOsiParameters = 0; + complicatedInteger = 2; // allow cuts + OsiSolverInterface *coinSolver = model_.solver(); + OsiSolverLink *linkSolver = dynamic_cast< OsiSolverLink * >(coinSolver); + if (linkSolver->quadraticModel()) { + ClpSimplex *qp = linkSolver->quadraticModel(); + //linkSolver->nonlinearSLP(CoinMax(slpValue,10),1.0e-5); + qp->nonlinearSLP(CoinMax(slpValue, 40), 1.0e-5); + qp->primal(1); + OsiSolverLinearizedQuadratic solver2(qp); + const double *solution = NULL; + // Reduce printout + solver2.setHintParam(OsiDoReducePrint, true, OsiHintTry); + CbcModel model2(solver2); + // Now do requested saves and modifications + CbcModel *cbcModel = &model2; + OsiSolverInterface *osiModel = model2.solver(); + OsiClpSolverInterface *osiclpModel = dynamic_cast< OsiClpSolverInterface * >(osiModel); + ClpSimplex *clpModel = osiclpModel->getModelPtr(); + + // Set changed values + int numCutGens = 0; + + CglProbing probing; + probing.setMaxProbe(10); + probing.setMaxLook(10); + probing.setMaxElements(200); + probing.setMaxProbeRoot(50); + probing.setMaxLookRoot(10); + probing.setRowCuts(3); + probing.setUsingObjective(true); + cbcModel->addCutGenerator(&probing, -1, "Probing", true, false, false, -100, -1, -1); + cbcModel->cutGenerator(numCutGens++)->setTiming(true); + + CglGomory gomory; + gomory.setLimitAtRoot(512); + cbcModel->addCutGenerator(&gomory, -98, "Gomory", true, false, false, -100, -1, -1); + cbcModel->cutGenerator(numCutGens++)->setTiming(true); + + CglKnapsackCover knapsackCover; + cbcModel->addCutGenerator(&knapsackCover, -98, "KnapsackCover", true, false, false, -100, -1, -1); + cbcModel->cutGenerator(numCutGens++)->setTiming(true); + + CglRedSplit redSplit; + cbcModel->addCutGenerator(&redSplit, -99, "RedSplit", true, false, false, -100, -1, -1); + cbcModel->cutGenerator(numCutGens++)->setTiming(true); + + CglBKClique bkClique; + bkClique.setMaxCallsBK(1000); + bkClique.setExtendingMethod(4); + bkClique.setPivotingStrategy(3); + cbcModel->addCutGenerator(&bkClique, -98, "Clique", true, false, false, -100, -1, -1); + cbcModel->cutGenerator(numCutGens++)->setTiming(true); + + CglOddWheel oddWheel; + oddWheel.setExtendingMethod(2); + cbcModel->addCutGenerator(&oddWheel, -98, "OddWheel", true, false, false, -100, -1, -1); + cbcModel->cutGenerator(numCutGens++)->setTiming(true); + + CglMixedIntegerRounding2 mixedIntegerRounding2; + cbcModel->addCutGenerator(&mixedIntegerRounding2, -98, "MixedIntegerRounding2", true, false, false, -100, -1, -1); + cbcModel->cutGenerator(numCutGens++)->setTiming(true); + + CglFlowCover flowCover; + cbcModel->addCutGenerator(&flowCover, -98, "FlowCover", true, false, false, -100, -1, -1); + cbcModel->cutGenerator(numCutGens++)->setTiming(true); + + CglTwomir twomir; + twomir.setMaxElements(250); + cbcModel->addCutGenerator(&twomir, -99, "Twomir", true, false, false, -100, -1, -1); + cbcModel->cutGenerator(numCutGens++)->setTiming(true); + int heuristicOption = parameters_[whichParam(CBC_PARAM_STR_HEURISTICSTRATEGY, parameters_)].currentOptionAsInteger(); + if (heuristicOption) { + CbcHeuristicFPump heuristicFPump(*cbcModel); + heuristicFPump.setWhen(13); + heuristicFPump.setMaximumPasses(20); + heuristicFPump.setMaximumRetries(7); + heuristicFPump.setHeuristicName("feasibility pump"); + heuristicFPump.setInitialWeight(1); + heuristicFPump.setFractionSmall(0.6); + cbcModel->addHeuristic(&heuristicFPump); + + CbcRounding rounding(*cbcModel); + rounding.setHeuristicName("rounding"); + cbcModel->addHeuristic(&rounding); + + CbcHeuristicLocal heuristicLocal(*cbcModel); + heuristicLocal.setHeuristicName("combine solutions"); + heuristicLocal.setSearchType(1); + heuristicLocal.setFractionSmall(0.6); + cbcModel->addHeuristic(&heuristicLocal); + + CbcHeuristicGreedyCover heuristicGreedyCover(*cbcModel); + heuristicGreedyCover.setHeuristicName("greedy cover"); + cbcModel->addHeuristic(&heuristicGreedyCover); + + CbcHeuristicGreedyEquality heuristicGreedyEquality(*cbcModel); + heuristicGreedyEquality.setHeuristicName("greedy equality"); + cbcModel->addHeuristic(&heuristicGreedyEquality); +#ifdef CBC_EXPERIMENT7 +#ifndef CBC_OTHER_SOLVER + CbcHeuristicRandRound heuristicRandRound(*cbcModel); + heuristicRandRound.setHeuristicName("random rounding"); + cbcModel->addHeuristic(&heuristicRandRound); + #endif +#endif + } + CbcCompareDefault compare; + cbcModel->setNodeComparison(compare); + cbcModel->setNumberBeforeTrust(10); + cbcModel->setSpecialOptions(2); + cbcModel->messageHandler()->setLogLevel(1); + cbcModel->setMaximumCutPassesAtRoot(-100); + cbcModel->setMaximumCutPasses(1); + cbcModel->setMinimumDrop(0.05); + // For branchAndBound this may help + clpModel->defaultFactorizationFrequency(); + clpModel->setDualBound(1.0001e+08); + clpModel->setPerturbation(50); + osiclpModel->setSpecialOptions(193); + osiclpModel->messageHandler()->setLogLevel(0); + osiclpModel->setIntParam(OsiMaxNumIterationHotStart, 100); + osiclpModel->setHintParam(OsiDoReducePrint, true, OsiHintTry); + // You can save some time by switching off message building + // clpModel->messagesPointer()->setDetailMessages(100,10000,(int *) NULL); + + // Solve + + cbcModel->initialSolve(); + if (clpModel->tightenPrimalBounds() != 0) { + sprintf(generalPrint, "Problem is infeasible - tightenPrimalBounds!"); + printGeneralMessage(model_, generalPrint); + break; + } + clpModel->dual(); // clean up + cbcModel->initialSolve(); +#ifdef CBC_THREAD + int numberThreads = parameters_[whichParam(CBC_PARAM_INT_THREADS, parameters_)].intValue(); + cbcModel->setNumberThreads(numberThreads % 100); + cbcModel->setThreadMode(CoinMin(numberThreads / 100, 7)); +#endif + //setCutAndHeuristicOptions(*cbcModel); + cbcModel->branchAndBound(); + OsiSolverLinearizedQuadratic *solver3 = dynamic_cast< OsiSolverLinearizedQuadratic * >(model2.solver()); + assert(solver3); + solution = solver3->bestSolution(); + double bestObjectiveValue = solver3->bestObjectiveValue(); + linkSolver->setBestObjectiveValue(bestObjectiveValue); + if (solution) { + // make sure array large enough + int arraySize = solver3->getNumCols(); + int wanted = linkSolver->getNumCols(); + double * solution2 = new double[wanted]; + memset(solution2,0,wanted*sizeof(double)); + memcpy(solution2,solution,arraySize*sizeof(double)); + linkSolver->setBestSolution(solution2, solver3->getNumCols()); + model_.setBestSolution(solution2,model_.getNumCols(), + bestObjectiveValue); + model_.setCutoff(bestObjectiveValue+1.0e-4); + delete [] solution2; + } + CbcHeuristicDynamic3 dynamic(model_); + dynamic.setHeuristicName("dynamic pass thru"); + if (heuristicOption) + model_.addHeuristic(&dynamic); + // if convex + if ((linkSolver->specialOptions2() & 4) != 0 && solution) { + int numberColumns = coinModel->numberColumns(); + assert(linkSolver->objectiveVariable() == numberColumns); + // add OA cut + double offset; + double *gradient = new double[numberColumns + 1]; + memcpy(gradient, qp->objectiveAsObject()->gradient(qp, solution, offset, true, 2), + numberColumns * sizeof(double)); + double rhs = 0.0; + int *column = new int[numberColumns + 1]; + int n = 0; + for (int i = 0; i < numberColumns; i++) { + double value = gradient[i]; + if (fabs(value) > 1.0e-12) { + gradient[n] = value; + rhs += value * solution[i]; + column[n++] = i; + } + } + gradient[n] = -1.0; + column[n++] = numberColumns; + storedAmpl.addCut(-COIN_DBL_MAX, offset + 1.0e-7, n, column, gradient); + linkSolver->addRow(n, column, gradient, + -COIN_DBL_MAX, offset + 1.0e-7); + delete[] gradient; + delete[] column; + } + // could do three way branching round a) continuous b) best solution + //printf("obj %g\n", bestObjectiveValue); + linkSolver->initialSolve(); + } + } + } +#endif +#endif + if (logLevel <= 1) + si->setHintParam(OsiDoReducePrint, true, OsiHintTry); +#ifndef CBC_OTHER_SOLVER + si->setSpecialOptions(0x40000000); +#endif + } + if (!miplib) { + if (!preSolve) { + model_.solver()->setHintParam(OsiDoPresolveInInitial, false, OsiHintTry); + model_.solver()->setHintParam(OsiDoPresolveInResolve, false, OsiHintTry); + } + double time1a = CoinCpuTime(); + OsiSolverInterface *solver = model_.solver(); +#ifndef CBC_OTHER_SOLVER + OsiClpSolverInterface *si = dynamic_cast< OsiClpSolverInterface * >(solver); + if (si) + si->setSpecialOptions(si->specialOptions() | 1024); +#endif + model_.initialSolve(); +#ifndef CBC_OTHER_SOLVER + ClpSimplex *clpSolver = si->getModelPtr(); + int iStatus = clpSolver->status(); + int iStatus2 = clpSolver->secondaryStatus(); + if (iStatus == 0) { + iStatus2 = 0; + } else if (iStatus == 1) { + iStatus = 0; + iStatus2 = 1; // say infeasible + } else if (iStatus == 2) { + iStatus = 0; + iStatus2 = 7; // say unbounded + } else if (iStatus == 3) { + iStatus = 1; + if (iStatus2 == 9) + iStatus2 = 4; + else + iStatus2 = 3; // Use nodes - as closer than solutions + } else if (iStatus == 4) { + iStatus = 2; // difficulties + iStatus2 = 0; + } + model_.setProblemStatus(iStatus); + model_.setSecondaryStatus(iStatus2); + si->setWarmStart(NULL); + int returnCode = 0; + if (callBack != NULL) + callBack(&model_, 1); + if (returnCode) { + // exit if user wants + delete babModel_; + babModel_ = NULL; + return returnCode; + } + if (clpSolver->status() > 0) { + // and in babModel if exists + if (babModel_) { + babModel_->setProblemStatus(iStatus); + babModel_->setSecondaryStatus(iStatus2); + } + if (!noPrinting_) { + iStatus = clpSolver->status(); + const char *msg[] = { "infeasible", "unbounded", "stopped", + "difficulties", "other" }; + sprintf(generalPrint, "Problem is %s - %.2f seconds", + msg[iStatus - 1], CoinCpuTime() - time1a); + generalMessageHandler->message(CLP_GENERAL, generalMessages) + << generalPrint + << CoinMessageEol; + } + break; + } + clpSolver->setSpecialOptions(clpSolver->specialOptions() | IN_BRANCH_AND_BOUND); // say is Cbc (and in branch and bound) +#elif CBC_OTHER_SOLVER == 1 +#endif + if (!noPrinting_) { + sprintf(generalPrint, "Continuous objective value is %g - %.2f seconds", + solver->getObjValue(), CoinCpuTime() - time1a); + generalMessageHandler->message(CLP_GENERAL, generalMessages) + << generalPrint + << CoinMessageEol; + } + if (model_.getMaximumNodes() == -987654321) { + // See if No objective! + int numberColumns = clpSolver->getNumCols(); + const double *obj = clpSolver->getObjCoefficients(); + const double *lower = clpSolver->getColLower(); + const double *upper = clpSolver->getColUpper(); + int nObj = 0; + for (int i = 0; i < numberColumns; i++) { + if (upper[i] > lower[i] && obj[i]) + nObj++; + } + if (!nObj) { + printf("************No objective!!\n"); + model_.setMaximumSolutions(1); + // Column copy + CoinPackedMatrix matrixByCol(*model_.solver()->getMatrixByCol()); + //const double * element = matrixByCol.getElements(); + //const int * row = matrixByCol.getIndices(); + //const CoinBigIndex * columnStart = matrixByCol.getVectorStarts(); + const int *columnLength = matrixByCol.getVectorLengths(); + for (int i = 0; i < numberColumns; i++) { + double value = (CoinDrand48() + 0.5) * 10000; + value = 10; + value *= columnLength[i]; + int iValue = static_cast< int >(value) / 10; + //iValue=1; + clpSolver->setObjCoeff(i, iValue); + } + } + } +#ifndef CBC_OTHER_SOLVER + if (!complicatedInteger && preProcess == 0 && clpSolver->tightenPrimalBounds(0.0, 0, true) != 0) { + sprintf(generalPrint, "Problem is infeasible - tightenPrimalBounds!"); + printGeneralMessage(model_, generalPrint); + model_.setProblemStatus(0); + model_.setSecondaryStatus(1); + // say infeasible for solution + integerStatus = 6; + // and in babModel if exists + if (babModel_) { + babModel_->setProblemStatus(0); + babModel_->setSecondaryStatus(1); + } + break; + } + if (clpSolver->dualBound() == 1.0e10) { + ClpSimplex temp = *clpSolver; + temp.setLogLevel(0); + temp.dual(0, 7); + // user did not set - so modify + // get largest scaled away from bound + double largest = 1.0e-12; + double largestScaled = 1.0e-12; + int numberRows = temp.numberRows(); + const double *rowPrimal = temp.primalRowSolution(); + const double *rowLower = temp.rowLower(); + const double *rowUpper = temp.rowUpper(); + const double *rowScale = temp.rowScale(); + int iRow; + for (iRow = 0; iRow < numberRows; iRow++) { + double value = rowPrimal[iRow]; + double above = value - rowLower[iRow]; + double below = rowUpper[iRow] - value; + if (above < 1.0e12) { + largest = CoinMax(largest, above); + } + if (below < 1.0e12) { + largest = CoinMax(largest, below); + } + if (rowScale) { + double multiplier = rowScale[iRow]; + above *= multiplier; + below *= multiplier; + } + if (above < 1.0e12) { + largestScaled = CoinMax(largestScaled, above); + } + if (below < 1.0e12) { + largestScaled = CoinMax(largestScaled, below); + } + } + + int numberColumns = temp.numberColumns(); + const double *columnPrimal = temp.primalColumnSolution(); + const double *columnLower = temp.columnLower(); + const double *columnUpper = temp.columnUpper(); + const double *columnScale = temp.columnScale(); + int iColumn; + for (iColumn = 0; iColumn < numberColumns; iColumn++) { + double value = columnPrimal[iColumn]; + double above = value - columnLower[iColumn]; + double below = columnUpper[iColumn] - value; + if (above < 1.0e12) { + largest = CoinMax(largest, above); + } + if (below < 1.0e12) { + largest = CoinMax(largest, below); + } + if (columnScale) { + double multiplier = 1.0 / columnScale[iColumn]; + above *= multiplier; + below *= multiplier; + } + if (above < 1.0e12) { + largestScaled = CoinMax(largestScaled, above); + } + if (below < 1.0e12) { + largestScaled = CoinMax(largestScaled, below); + } + } +#ifdef COIN_DEVELOP + if (!noPrinting_) + std::cout << "Largest (scaled) away from bound " << largestScaled + << " unscaled " << largest << std::endl; +#endif + clpSolver->setDualBound(CoinMax(1.0001e8, CoinMin(100.0 * largest, 1.00001e10))); + } + si->resolve(); // clean up +#endif + } + // If user made settings then use them + if (!defaultSettings) { + OsiSolverInterface *solver = model_.solver(); + if (!doScaling) + solver->setHintParam(OsiDoScale, false, OsiHintTry); +#ifndef CBC_OTHER_SOLVER + OsiClpSolverInterface *si = dynamic_cast< OsiClpSolverInterface * >(solver); + assert(si != NULL); + // get clp itself + ClpSimplex *modelC = si->getModelPtr(); + //if (modelC->tightenPrimalBounds()!=0) { + //std::cout<<"Problem is infeasible!"<tightenPrimalBounds(tightenFactor) != 0) { + sprintf(generalPrint, "Problem is infeasible!"); + printGeneralMessage(model_, generalPrint); + model_.setProblemStatus(0); + model_.setSecondaryStatus(1); + // and in babModel if exists + if (babModel_) { + babModel_->setProblemStatus(0); + babModel_->setSecondaryStatus(1); + } + break; + } + } +#endif + } + + // See if we want preprocessing + OsiSolverInterface *saveSolver = NULL; + CglPreProcess process; + // Say integers in sync + bool integersOK = true; + delete babModel_; + babModel_ = new CbcModel(model_); +#ifndef CBC_OTHER_SOLVER + int numberChanged = 0; + OsiSolverInterface *solver3 = clpSolver->clone(); + babModel_->assignSolver(solver3); + OsiClpSolverInterface *clpSolver2 = dynamic_cast< OsiClpSolverInterface * >(babModel_->solver()); + if (clpSolver2->messageHandler()->logLevel()) + clpSolver2->messageHandler()->setLogLevel(1); + if (logLevel > -1) + clpSolver2->messageHandler()->setLogLevel(logLevel); + lpSolver = clpSolver2->getModelPtr(); + if (lpSolver->factorizationFrequency() == 200 && !miplib) { + // User did not touch preset + int numberRows = lpSolver->numberRows(); + const int cutoff1 = 10000; + const int cutoff2 = 100000; + const int base = 75; + const int freq0 = 50; + const int freq1 = 200; + const int freq2 = 400; + const int maximum = 1000; + int frequency; + if (numberRows < cutoff1) + frequency = base + numberRows / freq0; + else if (numberRows < cutoff2) + frequency = base + cutoff1 / freq0 + (numberRows - cutoff1) / freq1; + else + frequency = base + cutoff1 / freq0 + (cutoff2 - cutoff1) / freq1 + (numberRows - cutoff2) / freq2; + lpSolver->setFactorizationFrequency(CoinMin(maximum, frequency)); + } +#elif CBC_OTHER_SOLVER == 1 + OsiSolverInterface *solver3 = model_.solver()->clone(); + babModel_->assignSolver(solver3); +#endif + time2 = CoinCpuTime(); + totalTime += time2 - time1; + //time1 = time2; + double timeLeft = babModel_->getMaximumSeconds(); + int numberOriginalColumns = babModel_->solver()->getNumCols(); + if (preProcess == 7) { + // use strategy instead + preProcess = 0; + useStrategy = true; +#ifdef COIN_HAS_LINK + // empty out any cuts + if (storedAmpl.sizeRowCuts()) { + printf("Emptying ampl stored cuts as internal preprocessing\n"); + CglStored temp; + storedAmpl = temp; + } +#endif + } + if (preProcess && type == CBC_PARAM_ACTION_BAB) { + // see whether to switch off preprocessing + // only allow SOS and integer + OsiObject **objects = babModel_->objects(); + int numberObjects = babModel_->numberObjects(); + for (int iObj = 0; iObj < numberObjects; iObj++) { + CbcSOS *objSOS = dynamic_cast< CbcSOS * >(objects[iObj]); + CbcSimpleInteger *objSimpleInteger = dynamic_cast< CbcSimpleInteger * >(objects[iObj]); + if (!objSimpleInteger && !objSOS) { + // find all integers anyway + babModel_->findIntegers(true); + preProcess = 0; + break; + } + } + } + if (type == CBC_PARAM_ACTION_BAB) { + if (preProcess == 0 && numberLotSizing) { + if (!babModel_->numberObjects()) { + /* model may not have created objects + If none then create + */ + babModel_->findIntegers(true); + } + // Lotsizing + //int numberColumns = babModel_->solver()->getNumCols(); + CbcObject **objects = new CbcObject *[numberLotSizing]; + double points[] = { 0.0, 0.0, 0.0, 0.0 }; + for (int i = 0; i < numberLotSizing; i++) { + int iColumn = lotsize[i].column; + points[2] = lotsize[i].low; + points[3] = lotsize[i].high; + objects[i] = new CbcLotsize(&model_, iColumn, 2, + points, true); + } + babModel_->addObjects(numberLotSizing, objects); + for (int i = 0; i < numberLotSizing; i++) + delete objects[i]; + delete[] objects; + } + double limit; + clpSolver->getDblParam(OsiDualObjectiveLimit, limit); + if (clpSolver->getObjValue() * clpSolver->getObjSense() >= limit * clpSolver->getObjSense()) + preProcess = 0; + } + if (mipStartBefore.size()) { + CbcModel tempModel = *babModel_; + assert(babModel_->getNumCols() == model_.getNumCols()); + std::vector< std::string > colNames; + for (int i = 0; (i < model_.solver()->getNumCols()); ++i) + colNames.push_back(model_.solver()->getColName(i)); + std::vector< double > x(model_.getNumCols(), 0.0); + double obj; + int status = CbcMipStartIO::computeCompleteSolution(&tempModel, tempModel.solver(), colNames, mipStartBefore, &x[0], obj, 0, tempModel.messageHandler(), tempModel.messagesPointer()); + // set cutoff ( a trifle high) + if (!status) { + double newCutoff = CoinMin(babModel_->getCutoff(), obj + 1.0e-4); + babModel_->setBestSolution(&x[0], static_cast< int >(x.size()), obj, false); + babModel_->setCutoff(newCutoff); + babModel_->setSolutionCount(1); + model_.setBestSolution(&x[0], static_cast< int >(x.size()), obj, false); + model_.setCutoff(newCutoff); + model_.setSolutionCount(1); + } + } + bool hasTimePreproc = !babModel_->maximumSecondsReached(); + if (!hasTimePreproc) + preProcess = 0; + // See if we need to skip preprocessing + if (preProcess) { + int numberGenerators = model_.numberCutGenerators(); + int iGenerator; + for (iGenerator = 0; iGenerator < numberGenerators; iGenerator++) { + CglCutGenerator *generator = + babModel_->cutGenerator(iGenerator)->generator(); + + if (generator->needsOriginalModel()) + break; + } + if (iGenerator < numberGenerators) { + preProcess = 0; + printGeneralMessage(model_, + "PreProcessing switched off due to lazy constraints"); + } + } + if (preProcess && type == CBC_PARAM_ACTION_BAB) { + saveSolver = babModel_->solver()->clone(); + /* Do not try and produce equality cliques and + do up to 10 passes */ + OsiSolverInterface *solver2; + { + // Tell solver we are in Branch and Cut + saveSolver->setHintParam(OsiDoInBranchAndCut, true, OsiHintDo); + // Default set of cut generators + CglProbing generator1; + generator1.setUsingObjective(1); + generator1.setMaxPass(1); + generator1.setMaxPassRoot(1); + generator1.setMaxProbeRoot(CoinMin(3000, saveSolver->getNumCols())); + generator1.setMaxElements(100); + generator1.setMaxElementsRoot(200); + generator1.setMaxLookRoot(50); + if (saveSolver->getNumCols() > 3000) + generator1.setMaxProbeRoot(123); + generator1.setRowCuts(3); + // switch off duplicate columns if we have a solution + if (model_.bestSolution() /*||debugValues*/) + tunePreProcess |= 4096; + // take off top + int tune2 = tunePreProcess % 10000; + if ((tune2 & (1|512)) != 0) { + // heavy probing + generator1.setMaxPassRoot(2); +#ifndef CBC_EXPERIMENT7 + generator1.setMaxElements(1000); +#else + if ((tune2 & 512) != 0) + generator1.setMaxElementsRoot(saveSolver->getNumCols()); + else + generator1.setMaxElements(1000); +#endif + generator1.setMaxProbeRoot(saveSolver->getNumCols()); + if ((tune2 & 512) != 0) + generator1.setMaxLookRoot(CoinMin(saveSolver->getNumCols(),1000)); + else + generator1.setMaxLookRoot(CoinMin(saveSolver->getNumCols(),400)); + } + if ((babModel_->specialOptions() & 65536) != 0) + process.setOptions(1); + // Add in generators + if ((model_.moreSpecialOptions() & 65536) == 0) + process.addCutGenerator(&generator1); + int translate[] = { 9999, 0, 0, -3, 2, 3, -2, 9999, 4, 5, 0 , -2}; + process.passInMessageHandler(babModel_->messageHandler()); + //process.messageHandler()->setLogLevel(babModel_->logLevel()); + if (info.numberSos && doSOS && statusUserFunction_[0]) { + // SOS + numberSOS = info.numberSos; + sosStart = info.sosStart; + sosIndices = info.sosIndices; + } + if (numberSOS && doSOS) { + // SOS + int numberColumns = saveSolver->getNumCols(); + char *prohibited = new char[numberColumns]; + memset(prohibited, 0, numberColumns); + // worth looking to see if any members can be made integer + + int numberRows = saveSolver->getNumRows(); + const CoinPackedMatrix *matrixByCol = saveSolver->getMatrixByCol(); + const double *element = matrixByCol->getElements(); + const int *row = matrixByCol->getIndices(); + const CoinBigIndex *columnStart = matrixByCol->getVectorStarts(); + const int *columnLength = matrixByCol->getVectorLengths(); + const double *columnLower = saveSolver->getColLower(); + const double *columnUpper = saveSolver->getColUpper(); + const double *rowLower = saveSolver->getRowLower(); + const double *rowUpper = saveSolver->getRowUpper(); + double *sameElement = new double[numberRows]; + int *rowCount = new int[2 * numberRows]; + int *rowUsed = rowCount + numberRows; + memset(sameElement, 0, numberRows * sizeof(double)); + memset(rowCount, 0, numberRows * sizeof(int)); + int numberInteresting1 = 0; + int numberInteresting2 = 0; + int numberChanged = 0; + for (int iSet = 0; iSet < numberSOS; iSet++) { + if (sosType[iSet] != 1) { + for (int i = sosStart[iSet]; + i < sosStart[iSet + 1]; i++) { + numberInteresting2++; + int iColumn = sosIndices[i]; + prohibited[iColumn] = 1; + } + } else { + int nUsed = 0; + for (int i = sosStart[iSet]; + i < sosStart[iSet + 1]; i++) { + int iColumn = sosIndices[i]; + for (CoinBigIndex j = columnStart[iColumn]; + j < columnStart[iColumn] + columnLength[iColumn]; j++) { + int iRow = row[j]; + double el = element[j]; + if (rowCount[iRow]) { + if (el != sameElement[iRow]) + sameElement[iRow] = 0.0; + } else { + sameElement[iRow] = el; + rowUsed[nUsed++] = iRow; + } + rowCount[iRow]++; + } + } + int nInSet = sosStart[iSet + 1] - sosStart[iSet]; + double nonzeroValue = COIN_DBL_MAX; + for (int iUsed = 0; iUsed < nUsed; iUsed++) { + int iRow = rowUsed[iUsed]; + if (rowCount[iRow] == nInSet && sameElement[iRow] && rowLower[iRow] == rowUpper[iRow]) { + // all entries must be 0.0 or xx + nonzeroValue = rowLower[iRow] / sameElement[iRow]; + } + rowCount[iRow] = 0; + sameElement[iRow] = 0.0; + } + if (nonzeroValue != COIN_DBL_MAX) { + // could do scaling otherwise + if (fabs(nonzeroValue - 1.0) < 1.0e-8) { + for (int i = sosStart[iSet]; + i < sosStart[iSet + 1]; i++) { + int iColumn = sosIndices[i]; + if (columnUpper[iColumn] < 0.0 || columnLower[iColumn] > 1.0) { + printf("sos says infeasible\n"); + } + if (!saveSolver->isInteger(iColumn)) { + numberChanged++; + saveSolver->setInteger(iColumn); + } + if (columnUpper[iColumn] < 1.0) + saveSolver->setColUpper(iColumn, 0.0); + else + saveSolver->setColUpper(iColumn, 1.0); + if (columnLower[iColumn] > 0.0) + saveSolver->setColLower(iColumn, 1.0); + else + saveSolver->setColLower(iColumn, 0.0); +#ifndef DO_LESS_PROHIBITED + prohibited[iColumn] = 1; +#endif + } + } else { + for (int i = sosStart[iSet]; + i < sosStart[iSet + 1]; i++) { + int iColumn = sosIndices[i]; +#ifndef DO_LESS_PROHIBITED + prohibited[iColumn] = 1; +#endif + } + } + } else { + for (int i = sosStart[iSet]; + i < sosStart[iSet + 1]; i++) { + int iColumn = sosIndices[i]; + if (!saveSolver->isInteger(iColumn)) + numberInteresting1++; +#ifdef DO_LESS_PROHIBITED + if (!saveSolver->isInteger(iColumn)) +#endif + prohibited[iColumn] = 1; + } + } + } + } + if (numberChanged || numberInteresting1 || numberInteresting2) { + sprintf(generalPrint, "%d variables in SOS1 sets made integer, %d non integer in SOS1, %d in SOS2\n", + numberChanged, numberInteresting1, numberInteresting2); + generalMessageHandler->message(CLP_GENERAL, generalMessages) + << generalPrint + << CoinMessageEol; + } + delete[] sameElement; + delete[] rowCount; + process.passInProhibited(prohibited, numberColumns); + delete[] prohibited; + } + if (0) { + + // Special integers + int numberColumns = saveSolver->getNumCols(); + char *prohibited = new char[numberColumns]; + memset(prohibited, 0, numberColumns); + const CoinPackedMatrix *matrix = saveSolver->getMatrixByCol(); + const int *columnLength = matrix->getVectorLengths(); + int numberProhibited = 0; + for (int iColumn = numberColumns - 1; iColumn >= 0; iColumn--) { + if (!saveSolver->isInteger(iColumn) || columnLength[iColumn] > 1) + break; + numberProhibited++; + prohibited[iColumn] = 1; + } + if (numberProhibited) { + process.passInProhibited(prohibited, numberColumns); + printf("**** Treating last %d integers as special - give high priority?\n", numberProhibited); + } + delete[] prohibited; + } + if (!model_.numberObjects() && true) { + /* model may not have created objects + If none then create + */ + model_.findIntegers(true); + } + // Lotsizing + if (numberLotSizing) { + int numberColumns = saveSolver->getNumCols(); + int numberRows = saveSolver->getNumRows(); +#if 0 + // Create model which uses 0-1 variables + { + double * els = new double[8*numberLotSizing]; + int * cols = new int[4*numberLotSizing]; + CoinBigIndex * starts = new CoinBigIndex [2*numberLotSizing+1]; + // add 0-1 variables + double * tup = els+4*numberLotSizing; + double * tlo = tup+2*numberLotSizing; + for (int i=0;i(saveSolver); + assert(si != NULL); + // get clp itself + ClpSimplex *model = si->getModelPtr(); + model->tightenPrimalBounds(0.0,0); + model->addColumns(numberLotSizing,tlo,tup,els,NULL,NULL,NULL); + for (int i=0;isetInteger(i+numberColumns); + starts[0]=0; + CoinBigIndex n=0; + const double * columnUpper = model->columnUpper(); + for (int i=0;iaddRows(n,tlo,tup,starts,cols,els); + model->writeMps("equivalentInteger.mps"); + exit(1); + } +#endif + char *prohibited = new char[numberColumns+numberRows]; + char *prohibitedRow = prohibited+numberColumns; + memset(prohibited, 0, numberColumns+numberRows); + const CoinPackedMatrix *matrix = saveSolver->getMatrixByCol(); + //const double *element = matrix->getElements(); + const int *row = matrix->getIndices(); + const CoinBigIndex *columnStart = matrix->getVectorStarts(); + const int *columnLength = matrix->getVectorLengths(); + for (int i = 0; i < numberLotSizing; i++) { + int iColumn = lotsize[i].column; + prohibited[iColumn] = 2; +#if 0 + // also leave all rows + for (CoinBigIndex j = columnStart[iColumn]; + j < columnStart[iColumn] + columnLength[iColumn]; j++) { + int iRow = row[j]; + prohibitedRow[iRow] = -2; + } +#endif + } + process.passInProhibited(prohibited, numberColumns); + process.passInRowTypes(prohibitedRow, numberRows); + passSCtopreprocess.lotsize=lotsize; + passSCtopreprocess.numberLotSizing=numberLotSizing; + process.setApplicationData(&passSCtopreprocess); + process.setOptions(128|256|process.options()); + delete[] prohibited; + } + if (model_.numberObjects()) { + OsiObject **oldObjects = babModel_->objects(); + int numberOldObjects = babModel_->numberObjects(); + if (!numberOldObjects) { + oldObjects = model_.objects(); + numberOldObjects = model_.numberObjects(); + } + // SOS + int numberColumns = saveSolver->getNumCols(); + char *prohibited = new char[numberColumns]; + memset(prohibited, 0, numberColumns); + int numberProhibited = 0; + for (int iObj = 0; iObj < numberOldObjects; iObj++) { + CbcSOS *obj = dynamic_cast< CbcSOS * >(oldObjects[iObj]); + if (obj) { + int n = obj->numberMembers(); + const int *which = obj->members(); + for (int i = 0; i < n; i++) { + int iColumn = which[i]; +#ifdef DO_LESS_PROHIBITED + if (!saveSolver->isInteger(iColumn)) +#endif + prohibited[iColumn] = 1; + numberProhibited++; + } + } + CbcLotsize *obj2 = dynamic_cast< CbcLotsize * >(oldObjects[iObj]); + if (obj2) { + int iColumn = obj2->columnNumber(); + prohibited[iColumn] = 1; + numberProhibited++; + } + } + if (numberProhibited) + process.passInProhibited(prohibited, numberColumns); + delete[] prohibited; + } + int numberPasses = 10; +#ifndef CBC_OTHER_SOLVER + if (doSprint > 0) { + // Sprint for primal solves + ClpSolve::SolveType method = ClpSolve::usePrimalorSprint; + ClpSolve::PresolveType presolveType = ClpSolve::presolveOff; + int numberPasses = 5; + int options[] = { 0, 3, 0, 0, 0, 0 }; + int extraInfo[] = { -1, 20, -1, -1, -1, -1 }; + extraInfo[1] = doSprint; + int independentOptions[] = { 0, 0, 3 }; + ClpSolve clpSolve(method, presolveType, numberPasses, + options, extraInfo, independentOptions); + // say use in OsiClp + clpSolve.setSpecialOption(6, 1); + OsiClpSolverInterface *osiclp = dynamic_cast< OsiClpSolverInterface * >(saveSolver); + osiclp->setSolveOptions(clpSolve); + osiclp->setHintParam(OsiDoDualInResolve, false); + // switch off row copy + osiclp->getModelPtr()->setSpecialOptions(osiclp->getModelPtr()->specialOptions() | 256); + osiclp->getModelPtr()->setInfeasibilityCost(1.0e11); + } +#endif +#ifndef CBC_OTHER_SOLVER + { + OsiClpSolverInterface *osiclp = dynamic_cast< OsiClpSolverInterface * >(saveSolver); + osiclp->setSpecialOptions(osiclp->specialOptions() | 1024); + osiclp->getModelPtr()->setClpScaledMatrix(NULL); // safer + int savePerturbation = osiclp->getModelPtr()->perturbation(); + //#define CBC_TEMP1 +#ifdef CBC_TEMP1 + if (savePerturbation == 50) + osiclp->getModelPtr()->setPerturbation(52); // try less +#endif + if ((model_.moreSpecialOptions() & 65536) != 0) + process.setOptions(2 + 4 + 8); // no cuts + cbcPreProcessPointer = &process; + preProcessPointer = &process; // threadsafe + int saveOptions = osiclp->getModelPtr()->moreSpecialOptions(); + if ((model_.specialOptions() & 16777216) != 0 && model_.getCutoff() > 1.0e30) { + osiclp->getModelPtr()->setMoreSpecialOptions(saveOptions | 262144); + } +#if DEBUG_PREPROCESS > 1 + if (debugValues) { + process.setApplicationData(const_cast< double * >(debugValues)); + } +#endif + if (debugFile=="unitTest") { + babModel_->solver()->activateRowCutDebugger(argv[1]); + OsiRowCutDebugger * debugger = + babModel_->solver()->getRowCutDebuggerAlways(); + numberDebugValues = babModel_->getNumCols(); + debugValues = + CoinCopyOfArray(debugger->optimalSolution(), + numberDebugValues); + } + redoSOS = true; + bool keepPPN = parameters_[whichParam(CBC_PARAM_STR_PREPROCNAMES, parameters_)].currentOptionAsInteger(); +#ifdef SAVE_NAUTY + keepPPN = 1; +#endif + process.setKeepColumnNames(keepPPN); + process.setTimeLimit(babModel_->getMaximumSeconds() - babModel_->getCurrentSeconds(), babModel_->useElapsedTime()); + if (model.getKeepNamesPreproc()) + process.setKeepColumnNames(true); + if (keepPPN) + babModel_->setKeepNamesPreproc(1); + setPreProcessingMode(saveSolver,1); + solver2 = process.preProcessNonDefault(*saveSolver, translate[preProcess], numberPasses, + tunePreProcess); + setPreProcessingMode(saveSolver,0); + if (solver2) { + setPreProcessingMode(solver2,0); + model_.setOriginalColumns(process.originalColumns(), solver2->getNumCols()); + + osiclp->getModelPtr()->setPerturbation(savePerturbation); + osiclp->getModelPtr()->setMoreSpecialOptions(saveOptions); + /* clean solvers - should be done in preProcess but + that doesn't know about Clp */ + OsiClpSolverInterface * solver; + solver = dynamic_cast(solver2); + solver->getModelPtr()->cleanScalingEtc(); + solver = dynamic_cast(process.originalModel()); + solver->getModelPtr()->cleanScalingEtc(); + solver = dynamic_cast(process.startModel()); + if (solver) + solver->getModelPtr()->cleanScalingEtc(); + int numberSolvers = process.numberSolvers(); + if (numberSolvers==99) + numberSolvers = 1; // really just 1 + // some of these may be same + for (int i=0;i(process.modelAtPass(i)); + if (solver) + solver->getModelPtr()->cleanScalingEtc(); + solver = dynamic_cast(process.modifiedModel(i)); + if (solver) + solver->getModelPtr()->cleanScalingEtc(); + } + } + } +#elif CBC_OTHER_SOLVER == 1 + cbcPreProcessPointer = &process; + preProcessPointer = &process; // threadsafe + redoSOS = true; + if (model.getKeepNamesPreproc()) + process.setKeepColumnNames(true); + solver2 = process.preProcessNonDefault(*saveSolver, translate[preProcess], numberPasses, + tunePreProcess); +#endif + integersOK = false; // We need to redo if CbcObjects exist + // Tell solver we are not in Branch and Cut + saveSolver->setHintParam(OsiDoInBranchAndCut, false, OsiHintDo); + if (solver2) + solver2->setHintParam(OsiDoInBranchAndCut, false, OsiHintDo); + } + if (!solver2 && statusUserFunction_[0]) { + // infeasible + info.problemStatus = 1; + info.objValue = 1.0e100; + sprintf(info.buffer, "infeasible/unbounded by pre-processing"); + info.primalSolution = NULL; + info.dualSolution = NULL; + break; + } + if (!noPrinting_) { + if (!solver2) { + sprintf(generalPrint, "Pre-processing says infeasible or unbounded"); + generalMessageHandler->message(CLP_GENERAL, generalMessages) + << generalPrint + << CoinMessageEol; + } else { + //printf("processed model has %d rows, %d columns and %d elements\n", + // solver2->getNumRows(),solver2->getNumCols(),solver2->getNumElements()); + } + } + if (!solver2) { + // say infeasible for solution + integerStatus = 6; + delete saveSolver; + saveSolver = NULL; + model_.setProblemStatus(0); + model_.setSecondaryStatus(1); + babModel_->setProblemStatus(0); + babModel_->setSecondaryStatus(1); + } else { + statistics_nprocessedrows = solver2->getNumRows(); + statistics_nprocessedcols = solver2->getNumCols(); + model_.setProblemStatus(-1); + babModel_->setProblemStatus(-1); + } + int returnCode = 0; + if (callBack != NULL) + returnCode = callBack(babModel_, 2); + if (returnCode) { + // exit if user wants + delete babModel_; + babModel_ = NULL; + return returnCode; + } + if (!solver2) + break; + if (model_.bestSolution()) { + // need to redo - in case no better found in BAB + // just get integer part right + const int *originalColumns = process.originalColumns(); + int numberColumns = CoinMin(solver2->getNumCols(), babModel_->getNumCols()); + double *bestSolution = babModel_->bestSolution(); + const double *oldBestSolution = model_.bestSolution(); + for (int i = 0; i < numberColumns; i++) { + int jColumn = originalColumns[i]; + bestSolution[i] = oldBestSolution[jColumn]; + } + } + //solver2->resolve(); + if (preProcess == 2 || preProcess >= 10) { + // names are wrong - redo + const int *originalColumns = process.originalColumns(); + int numberColumns = solver2->getNumCols(); + OsiSolverInterface *originalSolver = model.solver(); + int numberOriginalColumns = originalSolver->getNumCols(); + for (int i = 0; i < numberColumns; i++) { + int iColumn = originalColumns[i]; + if (iColumnsetColName(i, originalSolver->getColName(iColumn)); + } + OsiClpSolverInterface *clpSolver2 = dynamic_cast< OsiClpSolverInterface * >(solver2); + ClpSimplex *lpSolver = clpSolver2->getModelPtr(); + char name[100]; + if (preProcess == 2) { + strcpy(name, "presolved.mps"); + } else { + //strcpy(name,lpSolver->problemName().c_str()); + int iParam; + for (iParam = 0; iParam < (int)parameters_.size(); iParam++) { + int match = parameters_[iParam].matches("import"); + if (match == 1) + break; + } + strcpy(name, parameters_[iParam].stringValue().c_str()); + char *dot = strstr(name, ".mps"); + if (!dot) + dot = strstr(name, ".lp"); + if (preProcess>=10&&!dot) { + // get some sort of name + dot = name+strlen(name); + } + if (dot) { + *dot = '\0'; + int n = static_cast< int >(dot - name); + int i; + for (i = n - 1; i >= 0; i--) { + if (name[i] == '/') + break; + } + if (i >= 0) + memmove(name, name + i + 1, n); + strcat(name, "_preprocessed.mps"); + } else { + strcpy(name, "preprocessed.mps"); + } + } + lpSolver->writeMps(name, 0, 1, lpSolver->optimizationDirection()); + printf("Preprocessed model (minimization) on %s - size %d %d \n", + name,lpSolver->getNumRows(),lpSolver->getNumCols()); + if (preProcess >= 10) { + printf("user wanted to stop\n"); + return 0; //exit(0); + } + } + { + // look at new integers + int numberOriginalColumns = process.originalModel()->getNumCols(); + const int *originalColumns = process.originalColumns(); + OsiClpSolverInterface *osiclp2 = dynamic_cast< OsiClpSolverInterface * >(solver2); + int numberColumns = osiclp2->getNumCols(); + OsiClpSolverInterface *osiclp = dynamic_cast< OsiClpSolverInterface * >(saveSolver); + for (int i = 0; i < numberColumns; i++) { + int iColumn = originalColumns[i]; + if (iColumn < numberOriginalColumns) { + if (osiclp2->isInteger(i) && !osiclp->isInteger(iColumn)) + osiclp2->setOptionalInteger(i); // say optional + } + } + // do lotsizing + if (numberLotSizing) { + const double *columnLower = solver2->getColLower(); + const double *columnUpper = solver2->getColUpper(); + CbcObject **objects = new CbcObject *[numberLotSizing]; + double points[] = { 0.0, 0.0, 0.0, 0.0 }; + int *back = new int[numberOriginalColumns]; + for (int i = 0; i < numberOriginalColumns; i++) + back[i] = -1; + for (int i = 0; i < numberColumns; i++) { + int iColumn = originalColumns[i]; + back[iColumn] = i; + } + int n = numberLotSizing; + numberLotSizing = 0; + for (int i = 0; i < n; i++) { + int iColumn = lotsize[i].column; + iColumn = back[iColumn]; + if (iColumn>=0) { + if (columnLower[iColumn]lotsize[i].low) { + points[2] = lotsize[i].low; + points[3] = columnUpper[iColumn]; + objects[numberLotSizing++] = + new CbcLotsize(babModel_, iColumn, 2, + points, true); + } + } + } + delete [] back; + babModel_->addObjects(numberLotSizing, objects); + for (int i = 0; i < numberLotSizing; i++) + delete objects[i]; + delete[] objects; + if (numberLotSizing < n) { + sprintf(generalPrint, "Pre-processing reduced number of SC variables from %d to %d",n,numberLotSizing); + generalMessageHandler->message(CLP_GENERAL, generalMessages) + << generalPrint + << CoinMessageEol; + } + } + // redo existing SOS + if (osiclp->numberSOS()) { + redoSOS = false; + int *back = new int[numberOriginalColumns]; + for (int i = 0; i < numberOriginalColumns; i++) + back[i] = -1; + for (int i = 0; i < numberColumns; i++) { + int iColumn = originalColumns[i]; + back[iColumn] = i; + } + int numberSOSOld = osiclp->numberSOS(); + int numberSOS = osiclp2->numberSOS(); + assert(numberSOS == numberSOSOld); + CoinSet *setInfo = const_cast< CoinSet * >(osiclp2->setInfo()); + for (int i = 0; i < numberSOS; i++) { + //int type = setInfo[i].setType(); + int n = setInfo[i].numberEntries(); + int *which = setInfo[i].modifiableWhich(); +#ifndef DO_LESS_PROHIBITED + for (int j = 0; j < n; j++) { + int iColumn = which[j]; + iColumn = back[iColumn]; + assert(iColumn >= 0); + which[j] = iColumn; + } +#else + double *weights = setInfo[i].modifiableWeights(); + int n2 = 0; + for (int j = 0; j < n; j++) { + int iColumn = which[j]; + iColumn = back[iColumn]; + if (iColumn >= 0) { + which[n2] = iColumn; + weights[n2++] = weights[j]; + } + } + setInfo[i].setNumberEntries(n2); +#endif + } + delete[] back; + } + } + // we have to keep solver2 so pass clone + solver2 = solver2->clone(); + // see if extra variables wanted + int threshold = parameters_[whichParam(CBC_PARAM_INT_EXTRA_VARIABLES, parameters_)].intValue(); + int more2 = parameters_[whichParam(CBC_PARAM_INT_MOREMOREMIPOPTIONS, parameters_)].intValue(); + if (threshold || (more2 & (512 | 1024)) != 0) { + int numberColumns = solver2->getNumCols(); + truncateRows = solver2->getNumRows(); + bool modifiedModel = false; + int highPriority = 0; + /* + normal - no priorities + >10000 equal high priority + >20000 higher priority for higher cost + */ + if (threshold > 10000) { + highPriority = threshold / 10000; + threshold -= 10000 * highPriority; + } + // If 1000 set then don't put obj on ne variables + bool moveObjective = true; + if (threshold > 1000) { + moveObjective = false; + threshold -= 1000; + } + const double *columnLower = solver2->getColLower(); + const double *columnUpper = solver2->getColUpper(); + const double *objective = solver2->getObjCoefficients(); + int numberIntegers = 0; + int numberBinary = 0; + int numberTotalIntegers = 0; + double *obj = new double[numberColumns]; + int *which = new int[numberColumns]; + for (int iColumn = 0; iColumn < numberColumns; iColumn++) { + if (solver2->isInteger(iColumn)) { + numberTotalIntegers++; + if (columnUpper[iColumn] > columnLower[iColumn]) { + numberIntegers++; + if (columnLower[iColumn] == 0.0 && columnUpper[iColumn] == 1) + numberBinary++; + } + } + } + int numberSort = 0; + int numberZero = 0; + int numberZeroContinuous = 0; + int numberDifferentObj = 0; + int numberContinuous = 0; + for (int iColumn = 0; iColumn < numberColumns; iColumn++) { + if (columnUpper[iColumn] > columnLower[iColumn]) { + if (solver2->isInteger(iColumn)) { + if (!objective[iColumn]) { + numberZero++; + } else { + obj[numberSort] = fabs(objective[iColumn]); + which[numberSort++] = iColumn; + } + } else if (objective[iColumn]) { + numberContinuous++; + } else { + numberZeroContinuous++; + } + } + } + CoinSort_2(obj, obj + numberSort, which); + double last = obj[0]; + for (int jColumn = 1; jColumn < numberSort; jColumn++) { + if (fabs(obj[jColumn] - last) > 1.0e-12) { + numberDifferentObj++; + last = obj[jColumn]; + } + } + numberDifferentObj++; + sprintf(generalPrint, "Problem has %d integers (%d of which binary) and %d continuous", + numberIntegers, numberBinary, numberColumns - numberIntegers); + generalMessageHandler->message(CLP_GENERAL, generalMessages) + << generalPrint + << CoinMessageEol; + if (numberColumns > numberIntegers) { + sprintf(generalPrint, "%d continuous have nonzero objective, %d have zero objective", + numberContinuous, numberZeroContinuous); + generalMessageHandler->message(CLP_GENERAL, generalMessages) + << generalPrint + << CoinMessageEol; + } + sprintf(generalPrint, "%d integer have nonzero objective, %d have zero objective, %d different nonzero (taking abs)", + numberSort, numberZero, numberDifferentObj); + generalMessageHandler->message(CLP_GENERAL, generalMessages) + << generalPrint + << CoinMessageEol; + if (numberDifferentObj <= threshold + (numberZero) ? 1 : 0 && numberDifferentObj) { + int *backward = NULL; + if (highPriority) { + newPriorities = new int[numberTotalIntegers + numberDifferentObj + numberColumns]; + backward = newPriorities + numberTotalIntegers + numberDifferentObj; + numberTotalIntegers = 0; + for (int iColumn = 0; iColumn < numberColumns; iColumn++) { + if (solver2->isInteger(iColumn)) { + backward[iColumn] = numberTotalIntegers; + newPriorities[numberTotalIntegers++] = 10000; + } + } + } + int iLast = 0; + double last = obj[0]; + for (int jColumn = 1; jColumn < numberSort; jColumn++) { + if (fabs(obj[jColumn] - last) > 1.0e-12) { + sprintf(generalPrint, "%d variables have objective of %g", + jColumn - iLast, last); + generalMessageHandler->message(CLP_GENERAL, generalMessages) + << generalPrint + << CoinMessageEol; + iLast = jColumn; + last = obj[jColumn]; + } + } + sprintf(generalPrint, "%d variables have objective of %g", + numberSort - iLast, last); + generalMessageHandler->message(CLP_GENERAL, generalMessages) + << generalPrint + << CoinMessageEol; + int spaceNeeded = numberSort + numberDifferentObj; + CoinBigIndex *columnAddDummy = new CoinBigIndex[numberDifferentObj + 1]; + int *columnAdd = new int[spaceNeeded]; + double *elementAdd = new double[spaceNeeded]; + CoinBigIndex *rowAdd = new CoinBigIndex[numberDifferentObj + 1]; + double *objectiveNew = new double[3 * numberDifferentObj]; + double *lowerNew = objectiveNew + numberDifferentObj; + double *upperNew = lowerNew + numberDifferentObj; + memset(columnAddDummy, 0, + (numberDifferentObj + 1) * sizeof(CoinBigIndex)); + iLast = 0; + last = obj[0]; + numberDifferentObj = 0; + int priorityLevel = 9999; + int numberElements = 0; + rowAdd[0] = 0; + for (int jColumn = 1; jColumn < numberSort + 1; jColumn++) { + if (jColumn == numberSort || fabs(obj[jColumn] - last) > 1.0e-12) { + // not if just one + if (jColumn - iLast > 1) { + // do priority + if (highPriority == 1) { + newPriorities[numberTotalIntegers + numberDifferentObj] + = 500; + } else if (highPriority == 2) { + newPriorities[numberTotalIntegers + numberDifferentObj] + = priorityLevel; + priorityLevel--; + } + int iColumn = which[iLast]; + objectiveNew[numberDifferentObj] = objective[iColumn]; + double lower = 0.0; + double upper = 0.0; + for (int kColumn = iLast; kColumn < jColumn; kColumn++) { + iColumn = which[kColumn]; + if (moveObjective) + solver2->setObjCoeff(iColumn, 0.0); + double lowerValue = columnLower[iColumn]; + double upperValue = columnUpper[iColumn]; + double elementValue = -1.0; + if (objectiveNew[numberDifferentObj] * objective[iColumn] < 0.0) { + lowerValue = -columnUpper[iColumn]; + upperValue = -columnLower[iColumn]; + elementValue = 1.0; + } + if (!moveObjective) + objectiveNew[numberDifferentObj] = 0.0; + columnAdd[numberElements] = iColumn; + elementAdd[numberElements++] = elementValue; + if (lower != -COIN_DBL_MAX) { + if (lowerValue != -COIN_DBL_MAX) + lower += lowerValue; + else + lower = -COIN_DBL_MAX; + } + if (upper != COIN_DBL_MAX) { + if (upperValue != COIN_DBL_MAX) + upper += upperValue; + else + upper = COIN_DBL_MAX; + } + } + columnAdd[numberElements] = numberColumns + numberDifferentObj; + elementAdd[numberElements++] = 1.0; + lowerNew[numberDifferentObj] = lower; + upperNew[numberDifferentObj] = upper; + numberDifferentObj++; + rowAdd[numberDifferentObj] = numberElements; + } else if (highPriority) { + // just one + // do priority + int iColumn = which[iLast]; + int iInt = backward[iColumn]; + if (highPriority == 1) { + newPriorities[iInt] = 500; + } else { + newPriorities[iInt] = priorityLevel; + priorityLevel--; + } + } + if (jColumn < numberSort) { + iLast = jColumn; + last = obj[jColumn]; + } + } + } + if (numberDifferentObj) { + // add columns + solver2->addCols(numberDifferentObj, + columnAddDummy, NULL, NULL, + lowerNew, upperNew, objectiveNew); + // add constraints and make integer if all integer in group +#ifdef CBC_HAS_CLP + OsiClpSolverInterface *clpSolver2 + = dynamic_cast< OsiClpSolverInterface * >(solver2); +#endif + for (int iObj = 0; iObj < numberDifferentObj; iObj++) { + lowerNew[iObj] = 0.0; + upperNew[iObj] = 0.0; + solver2->setInteger(numberColumns + iObj); +#ifdef CBC_HAS_CLP + if (clpSolver2) + clpSolver2->setOptionalInteger(numberColumns + iObj); +#endif + } + solver2->addRows(numberDifferentObj, + rowAdd, columnAdd, elementAdd, + lowerNew, upperNew); + sprintf(generalPrint, "Replacing model - %d new variables", numberDifferentObj); + modifiedModel = true; + } + delete[] columnAdd; + delete[] columnAddDummy; + delete[] elementAdd; + delete[] rowAdd; + delete[] objectiveNew; + } + delete[] which; + delete[] obj; + if ((more2 & (512 | 1024)) != 0) { + // try for row slacks etc + // later do row branching + int iRow, iColumn; + int numberColumns = solver2->getNumCols(); + int numberRows = solver2->getNumRows(); + int fudgeObjective = more2 & 512; + int addSlacks = more2 & 1024; + if (fudgeObjective) { + bool moveObj = false; + fudgeObjective = 0; + const double *objective = solver2->getObjCoefficients(); + const double *columnLower = solver2->getColLower(); + const double *columnUpper = solver2->getColUpper(); + double *newValues = new double[numberColumns + 1]; + int *newColumn = new int[numberColumns + 1]; + bool allInteger = true; + int n = 0; + double newLower = 0.0; + double newUpper = 0.0; + for (iColumn = 0; iColumn < numberColumns; iColumn++) { + if (objective[iColumn]) { + if (!solver2->isInteger(iColumn)) { + allInteger = false; + break; + } else { + double value = objective[iColumn]; + double nearest = floor(value + 0.5); + if (fabs(value - nearest) > 1.0e-8) { + allInteger = false; + break; + } else { + newValues[n] = nearest; + newColumn[n++] = iColumn; + if (nearest > 0.0) { + newLower += CoinMax(columnLower[iColumn], -1.0e20) * nearest; + newUpper += CoinMin(columnUpper[iColumn], 1.0e20) * nearest; + } else { + newUpper += CoinMax(columnLower[iColumn], -1.0e20) * nearest; + newLower += CoinMin(columnUpper[iColumn], 1.0e20) * nearest; + } + } + } + } + } + if (allInteger && n) { + fudgeObjective = n; + solver2->addCol(0, NULL, NULL, newLower, newUpper, 0.0, "obj_col"); + solver2->setInteger(numberColumns); + newValues[n] = -1.0; + newColumn[n++] = numberColumns; + solver2->addRow(n, newColumn, newValues, 0.0, 0.0); + if (moveObj) { + memset(newValues, 0, numberColumns * sizeof(double)); + newValues[numberColumns] = 1.0; + solver2->setObjective(newValues); + } + numberRows++; + numberColumns++; + } + delete[] newValues; + delete[] newColumn; + } + if (addSlacks) { + bool moveObj = false; + addSlacks = 0; + // get row copy + const CoinPackedMatrix *matrix = solver2->getMatrixByRow(); + const double *element = matrix->getElements(); + const int *column = matrix->getIndices(); + const CoinBigIndex *rowStart = matrix->getVectorStarts(); + const int *rowLength = matrix->getVectorLengths(); + const double *rowLower = solver2->getRowLower(); + const double *rowUpper = solver2->getRowUpper(); + const double *columnLower = solver2->getColLower(); + const double *columnUpper = solver2->getColUpper(); + + // maximum space for additional columns + CoinBigIndex *newColumnStart = new CoinBigIndex[numberRows + 1]; + newColumnStart[0] = 0; + int *newRow = new int[numberRows]; + double *newElement = new double[numberRows]; + double *newObjective = new double[numberRows]; + double *newColumnLower = new double[numberRows]; + double *newColumnUpper = new double[numberRows]; + double *oldObjective = CoinCopyOfArray(solver2->getObjCoefficients(), + numberColumns); + for (iRow = 0; iRow < numberRows; iRow++) { + if (rowLower[iRow] != rowUpper[iRow]) { + bool allInteger = true; + double newLower = 0.0; + double newUpper = 0.0; + double constantObjective = 0.0; + for (CoinBigIndex j = rowStart[iRow]; j < rowStart[iRow] + rowLength[iRow]; j++) { + int iColumn = column[j]; + if (!solver2->isInteger(iColumn)) { + allInteger = false; + break; + } else { + double value = element[j]; + double nearest = floor(value + 0.5); + if (fabs(value - nearest) > 1.0e-8) { + allInteger = false; + break; + } else { + if (!oldObjective[iColumn]) + constantObjective = COIN_DBL_MAX; + if (!constantObjective) { + constantObjective = oldObjective[iColumn] / nearest; + } else if (constantObjective != COIN_DBL_MAX) { + double newConstant = oldObjective[iColumn] / nearest; + if (constantObjective > 0.0) { + if (newConstant <= 0.0) + constantObjective = COIN_DBL_MAX; + else + constantObjective = CoinMin(constantObjective, newConstant); + } else { + if (newConstant >= 0.0) + constantObjective = COIN_DBL_MAX; + else + constantObjective = CoinMax(constantObjective, newConstant); + } + } + if (nearest > 0.0) { + newLower += CoinMax(columnLower[iColumn], -1.0e20) * nearest; + newUpper += CoinMin(columnUpper[iColumn], 1.0e20) * nearest; + } else { + newUpper += CoinMax(columnLower[iColumn], -1.0e20) * nearest; + newLower += CoinMin(columnUpper[iColumn], 1.0e20) * nearest; + } + } + } + } + if (allInteger) { + newColumnStart[addSlacks + 1] = addSlacks + 1; + newRow[addSlacks] = iRow; + newElement[addSlacks] = -1.0; + newObjective[addSlacks] = 0.0; + if (moveObj && constantObjective != COIN_DBL_MAX) { + // move some of objective here if looks constant + newObjective[addSlacks] = constantObjective; + for (CoinBigIndex j = rowStart[iRow]; j < rowStart[iRow] + rowLength[iRow]; j++) { + int iColumn = column[j]; + double value = element[j]; + double nearest = floor(value + 0.5); + oldObjective[iColumn] -= nearest * constantObjective; + } + } + newColumnLower[addSlacks] = CoinMax(newLower, ceil(rowLower[iRow])); + ; + newColumnUpper[addSlacks] = CoinMin(newUpper, floor(rowUpper[iRow])); + addSlacks++; + } + } + } + if (addSlacks) { + solver2->setObjective(oldObjective); + solver2->addCols(addSlacks, newColumnStart, newRow, newElement, + newColumnLower, newColumnUpper, newObjective); + truncatedRhsLower = CoinCopyOfArray(solver2->getRowLower(), numberRows); + truncatedRhsUpper = CoinCopyOfArray(solver2->getRowUpper(), numberRows); + for (int j = 0; j < addSlacks; j++) { + int iRow = newRow[j]; + solver2->setRowLower(iRow, 0.0); + solver2->setRowUpper(iRow, 0.0); + int iColumn = j + numberColumns; + solver2->setInteger(iColumn); + std::string name = solver2->getRowName(iRow); + name += "_int"; + solver2->setColName(iColumn, name); + } + } + } + if (fudgeObjective || addSlacks) { + modifiedModel = true; + if (fudgeObjective && addSlacks) { + sprintf(generalPrint, "Objective integer added with %d elements and %d Integer slacks added", + fudgeObjective, addSlacks); + } else if (fudgeObjective) { + // just objective + sprintf(generalPrint, "Objective integer added with %d elements", + fudgeObjective); + more2 &= ~1024; + } else { + // just slacks + sprintf(generalPrint, "%d Integer slacks added", addSlacks); + more2 &= ~512; + } + } else { + more2 &= ~(512 | 1024); + } + parameters_[whichParam(CBC_PARAM_INT_MOREMOREMIPOPTIONS, parameters_)].setIntValue(more2); + } + if (modifiedModel) { + generalMessageHandler->message(CLP_GENERAL, generalMessages) + << generalPrint + << CoinMessageEol; + truncateColumns = numberColumns; + } + } + babModel_->assignSolver(solver2); + babModel_->setOriginalColumns(process.originalColumns(), + truncateColumns); + babModel_->initialSolve(); +#if CBC_USE_INITIAL_TIME == 2 + // time starts from here? + time1Elapsed = CoinGetTimeOfDay(); + time1 = CoinCpuTime(); + if (babModel_->useElapsedTime()) + babModel_->setDblParam(CbcModel::CbcStartSeconds, CoinGetTimeOfDay()); + else + babModel_->setDblParam(CbcModel::CbcStartSeconds, CoinCpuTime()); + //babModel_->setMaximumSeconds(timeLeft - (CoinCpuTime() - time2)); +#endif + } + + if (cgraphAction == "off") { + // switch off new clique, odd wheel and clique strengthening + cliqueAction = 0; + oddWheelAction = 0; + clqstrAction = "off"; + } else if (cgraphAction == "clq") { + // old style + oddWheelAction = 0; + clqstrAction = "off"; + oldCliqueMode = true; + } + if (clqstrAction == "after") { + CglCliqueStrengthening clqStr(babModel_->solver(), babModel_->messageHandler()); + clqStr.strengthenCliques(4); + + if (clqStr.constraintsExtended() + clqStr.constraintsDominated() > 0) { + OsiSolverInterface * solver = babModel_->solver(); + bool takeHint; + OsiHintStrength strength; + solver->getHintParam(OsiDoDualInResolve, + takeHint, strength); + solver->setHintParam(OsiDoDualInResolve, false,OsiHintTry); + solver->resolve(); + solver->setHintParam(OsiDoDualInResolve, takeHint,strength); + + if (!noPrinting_ && (babModel_->messageHandler()->logLevel())) { + if (solver->isProvenPrimalInfeasible()) { + sprintf(generalPrint, "Clique Strengthening says infeasible!"); + generalMessageHandler->message(CLP_GENERAL, generalMessages) + << generalPrint + << CoinMessageEol; + } else { + sprintf(generalPrint, "After applying Clique Strengthening continuous objective value is %.2lf", solver->getObjValue()); + generalMessageHandler->message(CLP_GENERAL, generalMessages) + << generalPrint + << CoinMessageEol; + } + } // results of clique Strengthening stengthening + } // checking impact of clique Strengthening stengthening + } // clique Strengthening + + // now tighten bounds + if (!miplib) { +#ifndef CBC_OTHER_SOLVER + OsiClpSolverInterface *si = dynamic_cast< OsiClpSolverInterface * >(babModel_->solver()); + assert(si != NULL); + // get clp itself + ClpSimplex *modelC = si->getModelPtr(); + //if (noPrinting_) + //modelC->setLogLevel(0); + if (!complicatedInteger && modelC->tightenPrimalBounds() != 0) { + sprintf(generalPrint, "Problem is infeasible!"); + printGeneralMessage(model_, generalPrint); + model_.setProblemStatus(0); + model_.setSecondaryStatus(1); + // say infeasible for solution + integerStatus = 6; + delete saveSolver; + saveSolver = NULL; + // and in babModel_ if exists + if (babModel_) { + babModel_->setProblemStatus(0); + babModel_->setSecondaryStatus(1); + } + break; + } + si->resolve(); +#elif CBC_OTHER_SOLVER == 1 +#endif + } + if (debugValues) { + // for debug + std::string problemName; + babModel_->solver()->getStrParam(OsiProbName, problemName); + babModel_->solver()->activateRowCutDebugger(problemName.c_str()); + twomirGen.probname_ = CoinStrdup(problemName.c_str()); + // checking seems odd + //redsplitGen.set_given_optsol(babModel_->solver()->getRowCutDebuggerAlways()->optimalSolution(), + // babModel_->getNumCols()); + } + int testOsiOptions = parameters_[whichParam(CBC_PARAM_INT_TESTOSI, parameters_)].intValue(); +#ifndef JJF_ONE + // If linked then see if expansion wanted + { + OsiSolverLink *solver3 = dynamic_cast< OsiSolverLink * >(babModel_->solver()); + int options = parameters_[whichParam(CBC_PARAM_INT_MIPOPTIONS, parameters_)].intValue() / 10000; + if (solver3 || (options & 16) != 0) { + if (options) { + /* + 1 - force mini branch and bound + 2 - set priorities high on continuous + 4 - try adding OA cuts + 8 - try doing quadratic linearization + 16 - try expanding knapsacks + */ + if ((options & 16)) { + int numberColumns = saveCoinModel.numberColumns(); + int numberRows = saveCoinModel.numberRows(); + whichColumn = new int[numberColumns]; + knapsackStart = new int[numberRows + 1]; + knapsackRow = new int[numberRows]; + numberKnapsack = 10000; + int extra1 = parameters_[whichParam(CBC_PARAM_INT_EXTRA1, parameters_)].intValue(); + int extra2 = parameters_[whichParam(CBC_PARAM_INT_EXTRA2, parameters_)].intValue(); + int logLevel = parameters_[log].intValue(); + OsiSolverInterface *solver = expandKnapsack(saveCoinModel, whichColumn, knapsackStart, + knapsackRow, numberKnapsack, + storedAmpl, logLevel, extra1, extra2, + saveTightenedModel); + if (solver) { +#ifndef CBC_OTHER_SOLVER + clpSolver = dynamic_cast< OsiClpSolverInterface * >(solver); + assert(clpSolver); + lpSolver = clpSolver->getModelPtr(); +#endif + babModel_->assignSolver(solver); + testOsiOptions = 0; + // allow gomory + complicatedInteger = 0; + // Priorities already done + free(info.priorities); + info.priorities = NULL; + } else { + numberKnapsack = 0; + delete[] whichColumn; + delete[] knapsackStart; + delete[] knapsackRow; + whichColumn = NULL; + knapsackStart = NULL; + knapsackRow = NULL; + } + } + } + } + } +#endif + if (useCosts && testOsiOptions < 0) { + int numberColumns = babModel_->getNumCols(); + int *sort = new int[numberColumns]; + double *dsort = new double[numberColumns]; + int *priority = new int[numberColumns]; + const double *objective = babModel_->getObjCoefficients(); + const double *lower = babModel_->getColLower(); + const double *upper = babModel_->getColUpper(); + const CoinPackedMatrix *matrix = babModel_->solver()->getMatrixByCol(); + const int *columnLength = matrix->getVectorLengths(); + int iColumn; + int n = 0; + for (iColumn = 0; iColumn < numberColumns; iColumn++) { + if (babModel_->isInteger(iColumn)) { + sort[n] = n; + if (useCosts == 1) { + dsort[n++] = -fabs(objective[iColumn]); + } else if (useCosts == 2) { + dsort[n++] = iColumn; + } else if (useCosts == 3) { + dsort[n++] = (upper[iColumn]-lower[iColumn])==1.0 ?1:2; + } else if (useCosts == 4) { + dsort[n++] = (upper[iColumn]-lower[iColumn])!=1.0 ?1:2; + } else if (useCosts == 5) { + dsort[n++] = -columnLength[iColumn]; + } else if (useCosts == 6) { + dsort[n++] = (columnLength[iColumn] == 1) ? -1.0 : 0.0; + } else if (useCosts == 7) { + dsort[n++] = (objective[iColumn]) ? -1.0 : 0.0; + } + } + } + CoinSort_2(dsort, dsort + n, sort); + int level = 999; + double last = -1.0e100; + for (int i = 0; i < n; i++) { + int iPut = sort[i]; + if (dsort[i] != last) { + level++; + last = dsort[i]; + } + priority[iPut] = level; + } + if (newPriorities) { + // get rid of + delete[] newPriorities; + newPriorities = NULL; + } + babModel_->passInPriorities(priority, false); + integersOK = true; + delete[] priority; + delete[] sort; + delete[] dsort; + } + // Set up heuristics + doHeuristics(babModel_, ((!miplib) ? 1 : 10), parameters_, + noPrinting_, initialPumpTune); + if (!miplib) { + if (parameters_[whichParam(CBC_PARAM_STR_LOCALTREE, parameters_)].currentOptionAsInteger()) { + CbcTreeLocal localTree(babModel_, NULL, 10, 0, 0, 10000, 2000); + babModel_->passInTreeHandler(localTree); + } + } + if (type == CBC_PARAM_ACTION_MIPLIB) { + if (babModel_->numberStrong() == 5 && babModel_->numberBeforeTrust() == 5) + babModel_->setNumberBeforeTrust(10); + } + int experimentFlag = parameters_[whichParam(CBC_PARAM_INT_EXPERIMENT, parameters_)].intValue(); + int strategyFlag = parameters_[whichParam(CBC_PARAM_INT_STRATEGY, parameters_)].intValue(); + int bothFlags = CoinMax(CoinMin(experimentFlag, 1), strategyFlag); + // add cut generators if wanted + int switches[30] = {}; + int accuracyFlag[30] = {}; + char doAtEnd[30] = {}; + int lagrangeanFlag = (parameters_[whichParam(CBC_PARAM_INT_MOREMOREMIPOPTIONS,parameters_)].intValue()&(7*33554432))>>9; +#define ALL_LAGRANGEAN 1 + int numberGenerators = 0; + int translate[] = { -100, -1, -99, -98, 1, -1098, -999, 1, 1, 1, -1 }; + int maximumSlowPasses = parameters_[whichParam(CBC_PARAM_INT_MAX_SLOW_CUTS, + parameters_)] + .intValue(); + if (probingAction) { + int numberColumns = babModel_->solver()->getNumCols(); + if (probingAction > 7) { + probingGen.setMaxElements(numberColumns); + probingGen.setMaxElementsRoot(numberColumns); + } + probingGen.setMaxProbeRoot(CoinMin(2000, numberColumns)); + probingGen.setMaxProbeRoot(123); + probingGen.setMaxProbe(123); + probingGen.setMaxLookRoot(20); + if (probingAction == 7 || probingAction == 9) + probingGen.setRowCuts(-3); // strengthening etc just at root + if (probingAction == 8 || probingAction == 9) { + // Number of unsatisfied variables to look at + probingGen.setMaxProbeRoot(numberColumns); + probingGen.setMaxProbe(numberColumns); + // How far to follow the consequences + probingGen.setMaxLook(50); + probingGen.setMaxLookRoot(50); + } + if (probingAction == 10) { + probingGen.setMaxPassRoot(2); + probingGen.setMaxProbeRoot(numberColumns); + probingGen.setMaxLookRoot(numberColumns); + } + // If 5 then force on + int iAction = translate[probingAction]; + if (probingAction == 5) + iAction = 1; + babModel_->addCutGenerator(&probingGen, iAction, "Probing"); + accuracyFlag[numberGenerators] = 5; + switches[numberGenerators++] = 0; + } + if (gomoryAction && (complicatedInteger != 1 || (gomoryAction == 1 || gomoryAction >= 4))) { + // try larger limit + int numberColumns = babModel_->getNumCols(); + if (gomoryAction == 7) { + gomoryAction = 4; + gomoryGen.setLimitAtRoot(numberColumns); + gomoryGen.setLimit(numberColumns); + } else if (gomoryAction == 8) { + gomoryAction = 3; + gomoryGen.setLimitAtRoot(numberColumns); + gomoryGen.setLimit(200); + } else if (gomoryAction == 9) { + gomoryAction = 3; + gomoryGen.setLimitAtRoot(500); + gomoryGen.setLimit(200); + } else if (numberColumns > 5000) { + //#define MORE_CUTS2 +#ifdef MORE_CUTS2 + // try larger limit + gomoryGen.setLimitAtRoot(numberColumns); + gomoryGen.setLimit(200); +#else + gomoryGen.setLimitAtRoot(2000); + //gomoryGen.setLimit(200); +#endif + } else { +#ifdef MORE_CUTS2 + // try larger limit + gomoryGen.setLimitAtRoot(numberColumns); + gomoryGen.setLimit(200); +#endif + } + int cutLength = parameters_[whichParam(CBC_PARAM_INT_CUTLENGTH, parameters_)].intValue(); + if (cutLength != -1) { + gomoryGen.setLimitAtRoot(cutLength); + if (cutLength < 10000000) { + gomoryGen.setLimit(cutLength); + } else { + gomoryGen.setLimit(cutLength % 10000000); + } + } + int laGomory = parameters_[whichParam(CBC_PARAM_STR_LAGOMORYCUTS, parameters_)].currentOptionAsInteger(); + int gType = translate[gomoryAction]; + if (!laGomory) { + // Normal + babModel_->addCutGenerator(&gomoryGen, translate[gomoryAction], "Gomory"); + accuracyFlag[numberGenerators] = 3; + switches[numberGenerators++] = lagrangeanFlag; + } else { + laGomory--; + int type = (laGomory % 3) + 1; + int when = laGomory / 3; + char atEnd = (when < 2) ? 1 : 0; + int gomoryTypeMajor = 10; + if (when != 3) { + // normal as well + babModel_->addCutGenerator(&gomoryGen, gType, "Gomory"); + accuracyFlag[numberGenerators] = 3; + switches[numberGenerators++] = 0; + if (when == 2) { + gomoryTypeMajor = 20; + } else if (when == 4) { + gomoryTypeMajor = 20; + when = 0; + } + } else { + when--; // so on + gomoryTypeMajor = 20; + } + if (!when) + gType = -99; // root + gomoryGen.passInOriginalSolver(babModel_->solver()); + if ((type & 1) != 0) { + // clean + gomoryGen.setGomoryType(gomoryTypeMajor + 1); + babModel_->addCutGenerator(&gomoryGen, gType, "GomoryL1"); + accuracyFlag[numberGenerators] = 3; + doAtEnd[numberGenerators] = atEnd; + if (atEnd) { + babModel_->cutGenerator(numberGenerators)->setMaximumTries(99999999); + babModel_->cutGenerator(numberGenerators)->setHowOften(1); + } + switches[numberGenerators++] = 0; + } + if ((type & 2) != 0) { + // simple + gomoryGen.setGomoryType(gomoryTypeMajor + 2); + babModel_->addCutGenerator(&gomoryGen, gType, "GomoryL2"); + accuracyFlag[numberGenerators] = 3; + doAtEnd[numberGenerators] = atEnd; + if (atEnd) { + babModel_->cutGenerator(numberGenerators)->setMaximumTries(99999999); + babModel_->cutGenerator(numberGenerators)->setHowOften(1); + } + switches[numberGenerators++] = 0; + } + } + } +#ifdef CLIQUE_ANALYSIS + if (miplib && !storedAmpl.sizeRowCuts()) { + printf("looking at probing\n"); + babModel_->addCutGenerator(&storedAmpl, 1, "Stored"); + accuracyFlag[numberGenerators] = 0; + switches[numberGenerators++] = 0; + } +#endif + if (knapsackAction) { + babModel_->addCutGenerator(&knapsackGen, translate[knapsackAction], "Knapsack"); + accuracyFlag[numberGenerators] = 1; + switches[numberGenerators++] = -2; + } + if (redsplitAction && !complicatedInteger) { + babModel_->addCutGenerator(&redsplitGen, translate[redsplitAction], "Reduce-and-split"); + accuracyFlag[numberGenerators] = 5; + // slow ? - just do a few times + if (redsplitAction != 1) { + babModel_->cutGenerator(numberGenerators)->setMaximumTries(maximumSlowPasses); + babModel_->cutGenerator(numberGenerators)->setHowOften(10); + } + switches[numberGenerators++] = 1 | (ALL_LAGRANGEAN*lagrangeanFlag); + } + if (redsplit2Action && !complicatedInteger) { + int maxLength = 256; + if (redsplit2Action > 2) { + redsplit2Action -= 2; + maxLength = COIN_INT_MAX; + } + CglRedSplit2Param ¶meters = redsplit2Gen.getParam(); + parameters.setMaxNonzeroesTab(maxLength); + babModel_->addCutGenerator(&redsplit2Gen, translate[redsplit2Action], "Reduce-and-split(2)"); + accuracyFlag[numberGenerators] = 5; + // slow ? - just do a few times + if (redsplit2Action != 1) { + babModel_->cutGenerator(numberGenerators)->setHowOften(maximumSlowPasses); + babModel_->cutGenerator(numberGenerators)->setMaximumTries(maximumSlowPasses); + babModel_->cutGenerator(numberGenerators)->setHowOften(5); + } + + switches[numberGenerators++] = 1 | (ALL_LAGRANGEAN*lagrangeanFlag); + } + if (GMIAction && !complicatedInteger) { + if (GMIAction > 5) { + // long + GMIAction -= 5; + CglGMIParam ¶meters = GMIGen.getParam(); + parameters.setMaxSupportRel(1.0); + } + babModel_->addCutGenerator(&GMIGen, translate[GMIAction], "Gomory(2)"); + if (GMIAction == 5) { + // just at end and root + GMIAction = 2; + doAtEnd[numberGenerators] = 1; + babModel_->cutGenerator(numberGenerators)->setMaximumTries(99999999); + babModel_->cutGenerator(numberGenerators)->setHowOften(1); + } + accuracyFlag[numberGenerators] = 5; + switches[numberGenerators++] = 0 | (ALL_LAGRANGEAN*lagrangeanFlag); + } + if (!oldCliqueMode) { + bkCliqueGen.setMaxCallsBK(maxCallsBK); + bkCliqueGen.setExtendingMethod(bkClqExtMethod); + bkCliqueGen.setPivotingStrategy(bkPivotingStrategy); + babModel_->addCutGenerator(&bkCliqueGen, translate[cliqueAction], "Clique"); + accuracyFlag[numberGenerators] = 0; + switches[numberGenerators++] = 0; + } else if (cgraphAction == "clq") { + // old style + CglClique clique; + clique.setStarCliqueReport(false); + clique.setRowCliqueReport(false); + clique.setMinViolation(0.05); + // ifmove + babModel_->addCutGenerator(&clique, translate[cliqueAction], + "Clique"); + accuracyFlag[numberGenerators] = 0; + switches[numberGenerators++] = 0; + } + if (oddWheelAction) { + oddWheelGen.setExtendingMethod(oddWExtMethod); + babModel_->addCutGenerator(&oddWheelGen, translate[oddWheelAction], "OddWheel"); + accuracyFlag[numberGenerators] = 0; + switches[numberGenerators++] = 0; + } + if (mixedAction) { + babModel_->addCutGenerator(&mixedGen, translate[mixedAction], "MixedIntegerRounding2"); + accuracyFlag[numberGenerators] = 2; + switches[numberGenerators++] = 0 | (ALL_LAGRANGEAN*lagrangeanFlag); + } + if (flowAction) { + babModel_->addCutGenerator(&flowGen, translate[flowAction], "FlowCover"); + accuracyFlag[numberGenerators] = 2; + switches[numberGenerators++] = 0 | (ALL_LAGRANGEAN*lagrangeanFlag); + } + if (twomirAction && (complicatedInteger != 1 || (twomirAction == 1 || twomirAction >= 4))) { + // try larger limit + int numberColumns = babModel_->getNumCols(); + if (twomirAction == 7) { + twomirAction = 4; + twomirGen.setMaxElements(numberColumns); + } else if (numberColumns > 5000 && twomirAction == 4) { + twomirGen.setMaxElements(2000); + } + int laTwomir = parameters_[whichParam(CBC_PARAM_STR_LATWOMIRCUTS, parameters_)].currentOptionAsInteger(); + int twomirType = translate[twomirAction]; + if (!laTwomir) { + // Normal + babModel_->addCutGenerator(&twomirGen, translate[twomirAction], "TwoMirCuts"); + accuracyFlag[numberGenerators] = 4; + switches[numberGenerators++] = 1 | (ALL_LAGRANGEAN*lagrangeanFlag); + } else { + laTwomir--; + int type = (laTwomir % 3) + 1; + int when = laTwomir / 3; + char atEnd = (when < 2) ? 1 : 0; + int twomirTypeMajor = 10; + if (when < 3) { + // normal as well + babModel_->addCutGenerator(&twomirGen, translate[twomirAction], "TwoMirCuts"); + accuracyFlag[numberGenerators] = 4; + switches[numberGenerators++] = 1; + if (when == 2) + twomirTypeMajor = 10; + } else { + when--; // so on + twomirTypeMajor = 20; + } + if (!when) + twomirType = -99; // root + twomirGen.passInOriginalSolver(babModel_->solver()); + if ((type & 1) != 0) { + // clean + twomirGen.setTwomirType(twomirTypeMajor + 1); + babModel_->addCutGenerator(&twomirGen, twomirType, "TwoMirCutsL1"); + accuracyFlag[numberGenerators] = 4; + doAtEnd[numberGenerators] = atEnd; + switches[numberGenerators++] = atEnd ? 0 : 1; + } + if ((type & 2) != 0) { + // simple + twomirGen.setTwomirType(twomirTypeMajor + 2); + babModel_->addCutGenerator(&twomirGen, twomirType, "TwoMirCutsL2"); + accuracyFlag[numberGenerators] = 4; + doAtEnd[numberGenerators] = atEnd; + switches[numberGenerators++] = atEnd ? 0 : 1; + } + } + } +#ifndef DEBUG_MALLOC + if (landpAction) { + if (landpAction==5) { + // allow longer + landpGen.parameter().maximumCutLength = 2000000; + landpAction = 3; + } + babModel_->addCutGenerator(&landpGen, translate[landpAction], "LiftAndProject"); + accuracyFlag[numberGenerators] = 5; + // slow ? - just do a few times + if (landpAction != 1) { + babModel_->cutGenerator(numberGenerators)->setMaximumTries(maximumSlowPasses); + babModel_->cutGenerator(numberGenerators)->setHowOften(10); + } + switches[numberGenerators++] = 1 | (ALL_LAGRANGEAN*lagrangeanFlag); + } +#endif + if (residualCapacityAction) { + babModel_->addCutGenerator(&residualCapacityGen, translate[residualCapacityAction], "ResidualCapacity"); + accuracyFlag[numberGenerators] = 5; + switches[numberGenerators++] = 1 | (ALL_LAGRANGEAN*lagrangeanFlag); + } + if (zerohalfAction) { + if (zerohalfAction > 4) { + //zerohalfAction -=4; + zerohalfGen.setFlags(1); + } + babModel_->addCutGenerator(&zerohalfGen, translate[zerohalfAction], "ZeroHalf"); + accuracyFlag[numberGenerators] = 5; + babModel_->cutGenerator(numberGenerators)->setNeedsRefresh(true); + switches[numberGenerators++] = 2; + } + if (dominatedCuts) + babModel_->setSpecialOptions(babModel_->specialOptions() | 64); + // Say we want timings + numberGenerators = babModel_->numberCutGenerators(); + int iGenerator; + int cutDepth = parameters_[whichParam(CBC_PARAM_INT_CUTDEPTH, parameters_)].intValue(); + for (iGenerator = 0; iGenerator < numberGenerators; iGenerator++) { + CbcCutGenerator *generator = babModel_->cutGenerator(iGenerator); + int howOften = generator->howOften(); + int iSwitch = switches[iGenerator]; + int iSwitch2, iSwitch3; + if (iSwitch>=0) { + iSwitch2 = iSwitch&127; + iSwitch3 = (iSwitch & ~16383)>>3; + // say if wants modified solver + generator->setSwitches(generator->switches()|iSwitch3); + } else { + iSwitch2 = iSwitch; + } + if (howOften == -98 || howOften == -99 || generator->maximumTries() > 0) + generator->setSwitchOffIfLessThan(iSwitch2); + // Use if any at root as more likely later and fairly cheap + //if (switches[iGenerator]==-2) + //generator->setWhetherToUse(true); + generator->setInaccuracy(accuracyFlag[iGenerator]); + if (doAtEnd[iGenerator]) { + generator->setWhetherCallAtEnd(true); + //generator->setMustCallAgain(true); + } + generator->setTiming(true); + if (cutDepth >= 0) + generator->setWhatDepth(cutDepth); + } + // Could tune more + if (!miplib) { + double minimumDrop = fabs(babModel_->solver()->getObjValue()) * 1.0e-5 + 1.0e-5; + babModel_->setMinimumDrop(CoinMin(5.0e-2, minimumDrop)); + if (cutPass == -1234567) { + if (babModel_->getNumCols() < 500) + babModel_->setMaximumCutPassesAtRoot(-100); // always do 100 if possible + else if (babModel_->getNumCols() < 5000) + babModel_->setMaximumCutPassesAtRoot(100); // use minimum drop + else + babModel_->setMaximumCutPassesAtRoot(50); + } else { + babModel_->setMaximumCutPassesAtRoot(cutPass); + } + if (cutPassInTree == -1234567) + babModel_->setMaximumCutPasses(4); + else + babModel_->setMaximumCutPasses(cutPassInTree); + } else if (cutPass != -1234567) { + babModel_->setMaximumCutPassesAtRoot(cutPass); + } + // Do more strong branching if small + //if (babModel_->getNumCols()<5000) + //babModel_->setNumberStrong(20); + // Switch off strong branching if wanted + //if (babModel_->getNumCols()>10*babModel_->getNumRows()) + //babModel_->setNumberStrong(0); + if (!noPrinting_) { + int iLevel = parameters_[log].intValue(); + if (iLevel < 0) { + if (iLevel > -10) { + babModel_->setPrintingMode(1); + } else { + babModel_->setPrintingMode(2); + iLevel += 10; + parameters_[log].setIntValue(iLevel); + } + iLevel = -iLevel; + } + babModel_->messageHandler()->setLogLevel(iLevel); + //if (babModel_->getNumCols() > 2000 || babModel_->getNumRows() > 1500 || babModel_->messageHandler()->logLevel() > 1) + // babModel_->setPrintFrequency(100); + babModel_->setPrintFrequency(1); + } + + babModel_->solver()->setIntParam(OsiMaxNumIterationHotStart, + parameters_[whichParam(CBC_PARAM_INT_MAXHOTITS, parameters_)].intValue()); +#ifndef CBC_OTHER_SOLVER + OsiClpSolverInterface *osiclp = dynamic_cast< OsiClpSolverInterface * >(babModel_->solver()); + // go faster stripes + if ((osiclp->getNumRows() < 300 && osiclp->getNumCols() < 500)) { + osiclp->setupForRepeatedUse(2, parameters_[slog].intValue()); + if (bothFlags >= 1) { + ClpSimplex *lp = osiclp->getModelPtr(); + int specialOptions = lp->specialOptions(); + lp->setSpecialOptions(specialOptions | (2048 + 4096)); + } + } else { + osiclp->setupForRepeatedUse(0, parameters_[slog].intValue()); + } + if (bothFlags >= 2) { + ClpSimplex *lp = osiclp->getModelPtr(); + int specialOptions = lp->specialOptions(); + lp->setSpecialOptions(specialOptions | (2048 + 4096)); + } + double increment = babModel_->getCutoffIncrement(); + ; + int *changed = NULL; + if (!miplib && increment == normalIncrement) + changed = analyze(osiclp, numberChanged, increment, false, generalMessageHandler, noPrinting); +#elif CBC_OTHER_SOLVER == 1 + double increment = babModel_->getCutoffIncrement(); + ; +#endif + if (debugValues) { + int numberColumns = babModel_->solver()->getNumCols(); + if (numberDebugValues == numberColumns) { + // for debug + babModel_->solver()->activateRowCutDebugger(debugValues); + } else { + int numberOriginalColumns = process.originalModel()->getNumCols(); +#if DEBUG_PREPROCESS < 2 + if (numberDebugValues <= numberOriginalColumns) { + const int *originalColumns = process.originalColumns(); + double *newValues = new double[numberColumns]; + // in case preprocess added columns! + // need to find values + OsiSolverInterface *siCopy = babModel_->solver()->clone(); + for (int i = 0; i < numberColumns; i++) { + int jColumn = originalColumns[i]; + if (jColumn < numberDebugValues && siCopy->isInteger(i)) { + // integer variable + double soln = floor(debugValues[jColumn] + 0.5); + // Set bounds to fix variable to its solution + siCopy->setColUpper(i, soln); + siCopy->setColLower(i, soln); + } + } + // All integers have been fixed at optimal value. + // Now solve to get continuous values + siCopy->setHintParam(OsiDoScale, false); + siCopy->initialSolve(); + if (siCopy->isProvenOptimal()) { + memcpy(newValues, siCopy->getColSolution(), + numberColumns * sizeof(double)); + } else { + printf("BAD debug file\n"); + siCopy->writeMps("Bad"); + exit(22); + } + delete siCopy; + // for debug + babModel_->solver()->activateRowCutDebugger(newValues); + delete[] newValues; + } else { + printf("debug file has incorrect number of columns\n"); + } +#else + // for debug + babModel_->solver()->activateRowCutDebugger(debugSolution); +#endif + } + } + babModel_->setCutoffIncrement(CoinMax(babModel_->getCutoffIncrement(), increment)); + // Turn this off if you get problems + // Used to be automatically set + int mipOptions = parameters_[whichParam(CBC_PARAM_INT_MIPOPTIONS, parameters_)].intValue() % 10000; + if (mipOptions != (1057) && mipOptions != 1025) { + sprintf(generalPrint, "mip options %d", mipOptions); + generalMessageHandler->message(CLP_GENERAL, generalMessages) + << generalPrint + << CoinMessageEol; + } +#ifndef CBC_OTHER_SOLVER + osiclp->setSpecialOptions(mipOptions); +#elif CBC_OTHER_SOLVER == 1 +#endif + // probably faster to use a basis to get integer solutions + babModel_->setSpecialOptions(babModel_->specialOptions() | 2); + currentBranchModel = babModel_; + //OsiSolverInterface * strengthenedModel=NULL; + if (type == CBC_PARAM_ACTION_BAB || type == CBC_PARAM_ACTION_MIPLIB) { + if (strategyFlag == 1) { + // try reduced model + babModel_->setSpecialOptions(babModel_->specialOptions() | 512); + } + if (experimentFlag >= 5 || strategyFlag == 2) { + // try reduced model at root + babModel_->setSpecialOptions(babModel_->specialOptions() | 32768); + if (experimentFlag >= 10000) { + // try reduced model at root with cuts + babModel_->setSpecialOptions(babModel_->specialOptions() | 512); + } + } + { + int depthMiniBab = parameters_[whichParam(CBC_PARAM_INT_DEPTHMINIBAB, parameters_)].intValue(); + if (depthMiniBab != -1) + babModel_->setFastNodeDepth(depthMiniBab); + } + int extra4 = parameters_[whichParam(CBC_PARAM_INT_EXTRA4, parameters_)].intValue(); + if (extra4 >= 0) { + int strategy = extra4 % 10; + extra4 /= 10; + int method = extra4 % 100; + extra4 /= 100; + extra4 = strategy + method * 8 + extra4 * 1024; + babModel_->setMoreSpecialOptions(extra4); + } + int moreMipOptions = parameters_[whichParam(CBC_PARAM_INT_MOREMIPOPTIONS, parameters_)].intValue(); + if (moreMipOptions >= 0) { + sprintf(generalPrint, "more mip options %d", moreMipOptions); + generalMessageHandler->message(CLP_GENERAL, generalMessages) + << generalPrint + << CoinMessageEol; +#if 1 + // some options may have been set already + // e.g. use elapsed time + babModel_->setMoreSpecialOptions(moreMipOptions | babModel_->moreSpecialOptions()); +#else + OsiClpSolverInterface *osiclp = dynamic_cast< OsiClpSolverInterface * >(babModel_->solver()); + if (moreMipOptions == 10000) { + // test memory saving + moreMipOptions -= 10000; + ClpSimplex *lpSolver = osiclp->getModelPtr(); + lpSolver->setPersistenceFlag(1); + // switch off row copy if few rows + if (lpSolver->numberRows() < 150) + lpSolver->setSpecialOptions(lpSolver->specialOptions() | 256); + } + if (moreMipOptions < 10000 && moreMipOptions) { + if (((moreMipOptions + 1) % 1000000) != 0) + babModel_->setSearchStrategy(moreMipOptions % 1000000); + } else if (moreMipOptions < 100000) { + // try reduced model + babModel_->setSpecialOptions(babModel_->specialOptions() | 512); + } + // go faster stripes + if (moreMipOptions >= 999999) { + if (osiclp) { + int save = osiclp->specialOptions(); + osiclp->setupForRepeatedUse(2, 0); + osiclp->setSpecialOptions(save | osiclp->specialOptions()); + } + } +#endif + } + } + { + int extra1 = parameters_[whichParam(CBC_PARAM_INT_EXTRA1, parameters_)].intValue(); + if (extra1 != -1) { + if (extra1 < 0) { + if (extra1 == -7777) + extra1 = -1; + else if (extra1 == -8888) + extra1 = 1; + babModel_->setWhenCuts(-extra1); + } else if (extra1 < 19000) { + babModel_->setSearchStrategy(extra1); + printf("XXXXX searchStrategy %d\n", extra1); + } else { + int n = extra1 - 20000; + if (!n) + n--; + babModel_->setNumberAnalyzeIterations(n); + printf("XXXXX analyze %d\n", extra1); + } + } else if (bothFlags >= 1) { + babModel_->setWhenCuts(999998); + } + } + if (type == CBC_PARAM_ACTION_BAB) { + if (statusUserFunction_[0]) { + priorities = info.priorities; + branchDirection = info.branchDirection; + pseudoDown = info.pseudoDown; + pseudoUp = info.pseudoUp; + solutionIn = info.primalSolution; + prioritiesIn = info.priorities; + if (info.numberSos && doSOS) { + // SOS + numberSOS = info.numberSos; + sosStart = info.sosStart; + sosIndices = info.sosIndices; + sosType = info.sosType; + sosReference = info.sosReference; + sosPriority = info.sosPriority; + } + } + const int *originalColumns = preProcess ? process.originalColumns() : NULL; + if (model.getMIPStart().size()) + mipStart = model.getMIPStart(); + std::string testEmpty = mipStartFile.substr(0, 6); + if ((mipStart.size() || testEmpty == "empty.") && !mipStartBefore.size() + && babModel_->getNumCols()) { + std::vector< std::string > colNames; + if (preProcess) { + /* translating mipstart solution */ + std::map< std::string, double > mipStartV; + for (size_t i = 0; (i < mipStart.size()); ++i) + mipStartV[mipStart[i].first] = mipStart[i].second; + + std::vector< std::pair< std::string, double > > mipStart2; + for (int i = 0; (i < babModel_->solver()->getNumCols()); ++i) { + int iColumn = babModel_->originalColumns()[i]; + if (iColumn >= 0 && iColumn < model.getNumCols()) { + std::string cname = model_.solver()->getColName(iColumn); + colNames.push_back(cname); + babModel_->solver()->setColName(i, cname); + std::map< std::string, double >::const_iterator msIt = mipStartV.find(cname); + if (msIt != mipStartV.end()) + mipStart2.push_back(std::pair< std::string, double >(cname, msIt->second)); + } else { + // created variable + char newName[15]; + sprintf(newName, "C%7.7d", i); + colNames.push_back(newName); + } + } + mipStart = mipStart2; + } else { + for (int i = 0; (i < babModel_->solver()->getNumCols()); ++i) + colNames.push_back(model_.solver()->getColName(i)); + } + //printf("--- %s %d\n", babModel_->solver()->getColName(0).c_str(), babModel_->solver()->getColNames().size() ); + //printf("-- SIZES of models %d %d %d\n", model_.getNumCols(), babModel_->solver()->getNumCols(), babModel_->solver()->getColNames().size() ); + std::vector< double > x(babModel_->getNumCols(), 0.0); + double obj; + babModel_->findIntegers(true); + int extraActions = 0; + int lengthFileName = mipStartFile.size(); + const char *checkEnd[6] = { + ".low", ".high", ".lowcheap", ".highcheap", ".lowexpensive", ".highexpensive" + }; + for (extraActions = 0; extraActions < 6; extraActions++) { + if (ends_with(mipStartFile, std::string(checkEnd[extraActions]))) + break; + } + if (extraActions == 6) + extraActions = 0; + else + extraActions++; + int status = CbcMipStartIO::computeCompleteSolution(babModel_, babModel_->solver(), colNames, mipStart, &x[0], obj, extraActions, babModel_->messageHandler(), babModel_->messagesPointer()); + if (!status) { + // need to check more babModel_->setBestSolution( &x[0], static_cast(x.size()), obj, false ); + OsiBabSolver dummy; + babModel_->passInSolverCharacteristics(&dummy); + babModel_->createContinuousSolver(); + /* This is a mess - mipStart does not really know about + SOS (but I am not going to try and fix that at present). + But at least we should make sure solution is valid */ + int numberObjects = babModel_->numberObjects(); + OsiObject **oldObjects = babModel_->objects(); + int numberSOS = 0; + if (preProcess && redoSOS) { + for (int iObj = 0; iObj < numberObjects; iObj++) { + int iColumn = oldObjects[iObj]->columnNumber(); + if (iColumn < 0 || iColumn >= numberOriginalColumns) { + CbcSOS *objSOS = dynamic_cast< CbcSOS * >(oldObjects[iObj]); + if (objSOS) { + numberSOS++; + } else { + printf("not sure mipstart can deal with this\n"); + abort(); + } + } + } + } + if (!numberSOS) { + // normal + babModel_->setBestSolution(CBC_ROUNDING, + obj, &x[0], 1); + } else { + // save and restore! + OsiObject **sosObjects = new OsiObject *[numberSOS]; + int *newColumn = new int[numberOriginalColumns]; + int i; + for (i = 0; i < numberOriginalColumns; i++) + newColumn[i] = -1; + for (i = 0; i < babModel_->getNumCols(); i++) + newColumn[originalColumns[i]] = i; + int nSOS = 0; + for (int iObj = 0; iObj < numberObjects; iObj++) { + int iColumn = oldObjects[iObj]->columnNumber(); + if (iColumn < 0 || iColumn >= numberOriginalColumns) { + CbcSOS *objSOS = dynamic_cast< CbcSOS * >(oldObjects[iObj]); + if (objSOS) { + sosObjects[nSOS++] = objSOS->clone(); + int n = objSOS->numberMembers(); + int *which = objSOS->mutableMembers(); + int nn = 0; + for (i = 0; i < n; i++) { + int iColumn = which[i]; + int jColumn = newColumn[iColumn]; + if (jColumn >= 0) { + which[nn++] = jColumn; + } + } + objSOS->setNumberMembers(nn); + } + } + } + delete [] newColumn; + babModel_->setBestSolution(CBC_ROUNDING, + obj, &x[0], 1); + // restore! + nSOS = 0; + for (int iObj = 0; iObj < numberObjects; iObj++) { + int iColumn = oldObjects[iObj]->columnNumber(); + if (iColumn < 0 || iColumn >= numberOriginalColumns) { + CbcSOS *objSOS = dynamic_cast< CbcSOS * >(oldObjects[iObj]); + if (objSOS) { + delete oldObjects[iObj]; + oldObjects[iObj] = sosObjects[nSOS++]; + } + } + } + delete [] sosObjects; + } + /* But this is outside branchAndBound so needs to know + about direction */ + if (babModel_->getObjSense()==-1.0) { + double increment = obj-babModel_->getCutoff(); + babModel_->setCutoff(-obj-increment); + babModel_->setMinimizationObjValue(-obj); + } + babModel_->clearContinuousSolver(); + babModel_->passInSolverCharacteristics(NULL); + if (useSolution == 0) + babModel_->setHotstartSolution(&x[0]); + } + } + + if (solutionIn && useSolution >= 0) { + if (!prioritiesIn) { + int n; + if (preProcess) { + int numberColumns = babModel_->getNumCols(); + // extend arrays in case SOS + n = originalColumns[numberColumns - 1] + 1; + } else { + n = babModel_->getNumCols(); + } + prioritiesIn = reinterpret_cast< int * >(malloc(n * sizeof(int))); + for (int i = 0; i < n; i++) + prioritiesIn[i] = 100; + } + if (preProcess) { + int numberColumns = babModel_->getNumCols(); + // extend arrays in case SOS + int n = originalColumns[numberColumns - 1] + 1; + int nSmaller = CoinMin(n, numberOriginalColumns); + double *solutionIn2 = new double[n]; + int *prioritiesIn2 = new int[n]; + int i; + for (i = 0; i < nSmaller; i++) { + solutionIn2[i] = solutionIn[i]; + prioritiesIn2[i] = prioritiesIn[i]; + } + for (; i < n; i++) { + solutionIn2[i] = 0.0; + prioritiesIn2[i] = 1000000; + } +#ifndef NDEBUG + int iLast = -1; +#endif + for (i = 0; i < numberColumns; i++) { + int iColumn = originalColumns[i]; +#ifndef NDEBUG + assert(iColumn > iLast); + iLast = iColumn; +#endif + solutionIn2[i] = solutionIn2[iColumn]; + if (prioritiesIn) + prioritiesIn2[i] = prioritiesIn2[iColumn]; + } + if (useSolution) + babModel_->setHotstartSolution(solutionIn2, prioritiesIn2); + else + babModel_->setBestSolution(solutionIn2, numberColumns, + COIN_DBL_MAX, true); + delete[] solutionIn2; + delete[] prioritiesIn2; + } else { + if (useSolution) + babModel_->setHotstartSolution(solutionIn, prioritiesIn); + else + babModel_->setBestSolution(solutionIn, babModel_->getNumCols(), + COIN_DBL_MAX, true); + } + } + OsiSolverInterface *testOsiSolver = (testOsiOptions >= 0) ? babModel_->solver() : NULL; + if (!testOsiSolver) { + // ************************************************************* + // CbcObjects + if (preProcess && (process.numberSOS() || babModel_->numberObjects())) { + int numberSOS = process.numberSOS(); + int numberIntegers = babModel_->numberIntegers(); + /* model may not have created objects + If none then create + */ + if (!integersOK) { + int type = (pseudoUp) ? 1 : 0; + babModel_->findIntegers(true, type); + numberIntegers = babModel_->numberIntegers(); + } + OsiObject **oldObjects = babModel_->objects(); + // Do sets and priorities + OsiObject **objects = new OsiObject *[numberSOS]; + // set old objects to have low priority + int numberOldObjects = babModel_->numberObjects(); + int numberColumns = babModel_->getNumCols(); + // backward pointer to new variables + // extend arrays in case SOS + assert(originalColumns); + int n = CoinMin(truncateColumns, numberColumns); + // allow for empty problem + n = (n) ? originalColumns[n - 1] + 1 : 0; + n = CoinMax(n, CoinMax(numberColumns, numberOriginalColumns)); + int *newColumn = new int[n]; + int i; + for (i = 0; i < numberOriginalColumns; i++) + newColumn[i] = -1; + for (i = 0; i < CoinMin(truncateColumns, numberColumns); i++) + newColumn[originalColumns[i]] = i; + int nMissing = 0; + for (int iObj = 0; iObj < numberOldObjects; iObj++) { + if (process.numberSOS()) + oldObjects[iObj]->setPriority(numberColumns + 1); + int iColumn = oldObjects[iObj]->columnNumber(); + if (iColumn < 0 || iColumn >= numberOriginalColumns) { + if (redoSOS) { // now done earlier?? + CbcSOS *obj = dynamic_cast< CbcSOS * >(oldObjects[iObj]); + if (obj) { + int n = obj->numberMembers(); + int *which = obj->mutableMembers(); + double *weights = obj->mutableWeights(); + int nn = 0; + for (i = 0; i < n; i++) { + int iColumn = which[i]; + int jColumn = newColumn[iColumn]; + if (jColumn >= 0) { + which[nn] = jColumn; + weights[nn++] = weights[i]; + } else { + nMissing++; + } + } + obj->setNumberMembers(nn); + } + } + continue; + } + if (originalColumns) + iColumn = originalColumns[iColumn]; + if (branchDirection) { + CbcSimpleInteger *obj = dynamic_cast< CbcSimpleInteger * >(oldObjects[iObj]); + if (obj) { + obj->setPreferredWay(branchDirection[iColumn]); + } else { + CbcObject *obj = dynamic_cast< CbcObject * >(oldObjects[iObj]); + assert(obj); + obj->setPreferredWay(branchDirection[iColumn]); + } + } + if (pseudoUp) { + CbcSimpleIntegerPseudoCost *obj1a = dynamic_cast< CbcSimpleIntegerPseudoCost * >(oldObjects[iObj]); + assert(obj1a); + if (pseudoDown[iColumn] > 0.0) + obj1a->setDownPseudoCost(pseudoDown[iColumn]); + if (pseudoUp[iColumn] > 0.0) + obj1a->setUpPseudoCost(pseudoUp[iColumn]); + } + } + if (nMissing) { +#ifndef DO_LESS_PROHIBITED + sprintf(generalPrint, "%d SOS variables vanished due to pre processing? - check validity?", nMissing); +#else + sprintf(generalPrint, "%d SOS variables eliminated by pre processing", nMissing); +#endif + generalMessageHandler->message(CLP_GENERAL, generalMessages) + << generalPrint + << CoinMessageEol; + } + delete[] newColumn; + const int *starts = process.startSOS(); + const int *which = process.whichSOS(); + const int *type = process.typeSOS(); + const double *weight = process.weightSOS(); + int iSOS; + for (iSOS = 0; iSOS < numberSOS; iSOS++) { + int iStart = starts[iSOS]; + int n = starts[iSOS + 1] - iStart; + //#define MAKE_SOS_CLIQUES +#ifndef MAKE_SOS_CLIQUES + objects[iSOS] = new CbcSOS(babModel_, n, which + iStart, weight + iStart, + iSOS, type[iSOS]); +#else + objects[iSOS] = new CbcClique(babModel_, 1, n, which + iStart, + NULL, -iSOS - 1); +#endif + // branch on long sets first + objects[iSOS]->setPriority(numberColumns - n); + } + if (numberSOS) + babModel_->addObjects(numberSOS, objects); + for (iSOS = 0; iSOS < numberSOS; iSOS++) + delete objects[iSOS]; + delete[] objects; + } else if (priorities || branchDirection || pseudoDown || pseudoUp || numberSOS) { + // do anyway for priorities etc + int numberIntegers = babModel_->numberIntegers(); + /* model may not have created objects + If none then create + */ + if (!numberIntegers || !babModel_->numberObjects()) { + int type = (pseudoUp) ? 1 : 0; + babModel_->findIntegers(true, type); + } + if (numberSOS) { + // Do sets and priorities + OsiObject **objects = new OsiObject *[numberSOS]; + int iSOS; + if (originalColumns) { + // redo sequence numbers + int numberColumns = babModel_->getNumCols(); + int nOld = originalColumns[numberColumns - 1] + 1; + int *back = new int[nOld]; + int i; + for (i = 0; i < nOld; i++) + back[i] = -1; + for (i = 0; i < numberColumns; i++) + back[originalColumns[i]] = i; + // Really need better checks + int nMissing = 0; +#ifndef DO_LESS_PROHIBITED + int n = sosStart[numberSOS]; + for (i = 0; i < n; i++) { + int iColumn = sosIndices[i]; + int jColumn = back[iColumn]; + if (jColumn >= 0) + sosIndices[i] = jColumn; + else + nMissing++; + } +#else + int startSet = 0; + int iPut = 0; + for (int j = 0; j < numberSOS; j++) { + for (i = startSet; i < sosStart[j + 1]; i++) { + int iColumn = sosIndices[i]; + int jColumn = back[iColumn]; + if (jColumn >= 0) { + sosReference[iPut] = sosReference[i]; + sosIndices[iPut++] = jColumn; + } else { + nMissing++; + } + } + startSet = sosStart[j + 1]; + sosStart[j + 1] = iPut; + } +#endif + delete[] back; + if (nMissing) { +#ifndef DO_LESS_PROHIBITED + sprintf(generalPrint, "%d SOS variables vanished due to pre processing? - check validity?", nMissing); +#else + sprintf(generalPrint, "%d SOS variables eliminated by pre processing", nMissing); +#endif + generalMessageHandler->message(CLP_GENERAL, generalMessages) + << generalPrint + << CoinMessageEol; + } + } + int sosPriorityOption = parameters_[whichParam(CBC_PARAM_STR_SOSPRIORITIZE, parameters_)].currentOptionAsInteger(); + if (sosPriorityOption) { + const char *msg[4] = { + "high with equal priority", + "low with equal priority", + "high but with decreasing priority", + "low and decreasing priority" + }; + sprintf(generalPrint, "Setting %d SOS priorities %s", numberSOS, msg[sosPriorityOption - 1]); + generalMessageHandler->message(CLP_GENERAL, generalMessages) + << generalPrint + << CoinMessageEol; + } + for (iSOS = 0; iSOS < numberSOS; iSOS++) { + int iStart = sosStart[iSOS]; + int n = sosStart[iSOS + 1] - iStart; + CbcSOS *sosObject = new CbcSOS(babModel_, n, sosIndices + iStart, sosReference + iStart, + iSOS, sosType[iSOS]); + if (sosPriority) { + sosObject->setPriority(sosPriority[iSOS]); + } else if (sosPriorityOption) { + int priority = 10; + switch (sosPriorityOption) { + case 2: + priority = 100000; + break; + case 3: + // really should check <990 sets + priority = 10 + iSOS; + break; + case 4: + priority = 100000 + iSOS; + break; + } + sosObject->setPriority(priority); + } else if (!prioritiesIn) { + sosObject->setPriority(10); // rather than 1000 + } + objects[iSOS] = sosObject; + } + // delete any existing SOS objects + int numberObjects = babModel_->numberObjects(); + OsiObject **oldObjects = babModel_->objects(); + int nNew = 0; + for (int i = 0; i < numberObjects; i++) { + OsiObject *objThis = oldObjects[i]; + CbcSOS *obj1 = dynamic_cast< CbcSOS * >(objThis); + OsiSOS *obj2 = dynamic_cast< OsiSOS * >(objThis); + if (!obj1 && !obj2) { + oldObjects[nNew++] = objThis; + } else { + delete objThis; + } + } + babModel_->setNumberObjects(nNew); + babModel_->addObjects(numberSOS, objects); + for (iSOS = 0; iSOS < numberSOS; iSOS++) + delete objects[iSOS]; + delete[] objects; + } + } + OsiObject **objects = babModel_->objects(); + int numberObjects = babModel_->numberObjects(); + for (int iObj = 0; iObj < numberObjects; iObj++) { + // skip sos + CbcSOS *objSOS = dynamic_cast< CbcSOS * >(objects[iObj]); + if (objSOS) + continue; +#ifdef MAKE_SOS_CLIQUES + // skip cliques + CbcClique *objClique = dynamic_cast< CbcClique * >(objects[iObj]); + if (objClique) + continue; +#endif + int iColumn = objects[iObj]->columnNumber(); + assert(iColumn >= 0); + if (originalColumns) + iColumn = originalColumns[iColumn]; + if (branchDirection) { + CbcSimpleInteger *obj = dynamic_cast< CbcSimpleInteger * >(objects[iObj]); + if (obj) { + obj->setPreferredWay(branchDirection[iColumn]); + } else { + CbcObject *obj = dynamic_cast< CbcObject * >(objects[iObj]); + assert(obj); + obj->setPreferredWay(branchDirection[iColumn]); + } + } + if (priorities) { + int iPriority = priorities[iColumn]; + if (iPriority > 0) + objects[iObj]->setPriority(iPriority); + } + if (pseudoUp && pseudoUp[iColumn]) { + CbcSimpleIntegerPseudoCost *obj1a = dynamic_cast< CbcSimpleIntegerPseudoCost * >(objects[iObj]); + assert(obj1a); + if (pseudoDown[iColumn] > 0.0) + obj1a->setDownPseudoCost(pseudoDown[iColumn]); + if (pseudoUp[iColumn] > 0.0) + obj1a->setUpPseudoCost(pseudoUp[iColumn]); + } + } + // ************************************************************* + } else { + // ************************************************************* + // OsiObjects + // Find if none + int numberIntegers = testOsiSolver->getNumIntegers(); + /* model may not have created objects + If none then create + */ + if (!numberIntegers || !testOsiSolver->numberObjects()) { + //int type = (pseudoUp) ? 1 : 0; + testOsiSolver->findIntegers(false); + numberIntegers = testOsiSolver->getNumIntegers(); + } + if (preProcess && process.numberSOS()) { + int numberSOS = process.numberSOS(); + OsiObject **oldObjects = testOsiSolver->objects(); + // Do sets and priorities + OsiObject **objects = new OsiObject *[numberSOS]; + // set old objects to have low priority + int numberOldObjects = testOsiSolver->numberObjects(); + int numberColumns = testOsiSolver->getNumCols(); + for (int iObj = 0; iObj < numberOldObjects; iObj++) { + oldObjects[iObj]->setPriority(numberColumns + 1); + int iColumn = oldObjects[iObj]->columnNumber(); + assert(iColumn >= 0); + if (iColumn >= numberOriginalColumns) + continue; + if (originalColumns) + iColumn = originalColumns[iColumn]; + if (branchDirection) { + OsiSimpleInteger *obj = dynamic_cast< OsiSimpleInteger * >(oldObjects[iObj]); + if (obj) { + obj->setPreferredWay(branchDirection[iColumn]); + } else { + OsiObject2 *obj = dynamic_cast< OsiObject2 * >(oldObjects[iObj]); + if (obj) + obj->setPreferredWay(branchDirection[iColumn]); + } + } + if (pseudoUp) { + abort(); + } + } + const int *starts = process.startSOS(); + const int *which = process.whichSOS(); + const int *type = process.typeSOS(); + const double *weight = process.weightSOS(); + int iSOS; + for (iSOS = 0; iSOS < numberSOS; iSOS++) { + int iStart = starts[iSOS]; + int n = starts[iSOS + 1] - iStart; + objects[iSOS] = new OsiSOS(testOsiSolver, n, which + iStart, weight + iStart, + type[iSOS]); + // branch on long sets first + objects[iSOS]->setPriority(numberColumns - n); + } + testOsiSolver->addObjects(numberSOS, objects); + for (iSOS = 0; iSOS < numberSOS; iSOS++) + delete objects[iSOS]; + delete[] objects; + } else if (priorities || branchDirection || pseudoDown || pseudoUp || numberSOS) { + if (numberSOS) { + // Do sets and priorities + OsiObject **objects = new OsiObject *[numberSOS]; + int iSOS; + if (originalColumns) { + // redo sequence numbers + int numberColumns = testOsiSolver->getNumCols(); + int nOld = originalColumns[numberColumns - 1] + 1; + int *back = new int[nOld]; + int i; + for (i = 0; i < nOld; i++) + back[i] = -1; + for (i = 0; i < numberColumns; i++) + back[originalColumns[i]] = i; + // Really need better checks + int nMissing = 0; + int n = sosStart[numberSOS]; + for (i = 0; i < n; i++) { + int iColumn = sosIndices[i]; + int jColumn = back[iColumn]; + if (jColumn >= 0) + sosIndices[i] = jColumn; + else + nMissing++; + } + delete[] back; + if (nMissing) { + sprintf(generalPrint, "%d SOS variables vanished due to pre processing? - check validity?", nMissing); + generalMessageHandler->message(CLP_GENERAL, generalMessages) + << generalPrint + << CoinMessageEol; + } + } + for (iSOS = 0; iSOS < numberSOS; iSOS++) { + int iStart = sosStart[iSOS]; + int n = sosStart[iSOS + 1] - iStart; + objects[iSOS] = new OsiSOS(testOsiSolver, n, sosIndices + iStart, sosReference + iStart, + sosType[iSOS]); + if (sosPriority) + objects[iSOS]->setPriority(sosPriority[iSOS]); + else if (!prioritiesIn) + objects[iSOS]->setPriority(10); // rather than 1000 + } + // delete any existing SOS objects + int numberObjects = testOsiSolver->numberObjects(); + OsiObject **oldObjects = testOsiSolver->objects(); + int nNew = 0; + for (int i = 0; i < numberObjects; i++) { + OsiObject *objThis = oldObjects[i]; + OsiSOS *obj1 = dynamic_cast< OsiSOS * >(objThis); + OsiSOS *obj2 = dynamic_cast< OsiSOS * >(objThis); + if (!obj1 && !obj2) { + oldObjects[nNew++] = objThis; + } else { + delete objThis; + } + } + testOsiSolver->setNumberObjects(nNew); + testOsiSolver->addObjects(numberSOS, objects); + for (iSOS = 0; iSOS < numberSOS; iSOS++) + delete objects[iSOS]; + delete[] objects; + } + } + OsiObject **objects = testOsiSolver->objects(); + int numberObjects = testOsiSolver->numberObjects(); + int logLevel = parameters_[log].intValue(); + for (int iObj = 0; iObj < numberObjects; iObj++) { + // skip sos + OsiSOS *objSOS = dynamic_cast< OsiSOS * >(objects[iObj]); + if (objSOS) { + if (logLevel > 2) + printf("Set %d is SOS - priority %d\n", iObj, objSOS->priority()); + continue; + } + int iColumn = objects[iObj]->columnNumber(); + if (iColumn >= 0) { + if (originalColumns) + iColumn = originalColumns[iColumn]; + if (branchDirection) { + OsiSimpleInteger *obj = dynamic_cast< OsiSimpleInteger * >(objects[iObj]); + if (obj) { + obj->setPreferredWay(branchDirection[iColumn]); + } else { + OsiObject2 *obj = dynamic_cast< OsiObject2 * >(objects[iObj]); + if (obj) + obj->setPreferredWay(branchDirection[iColumn]); + } + } + if (priorities) { + int iPriority = priorities[iColumn]; + if (iPriority > 0) + objects[iObj]->setPriority(iPriority); + } + if (logLevel > 2) + printf("Obj %d is int? - priority %d\n", iObj, objects[iObj]->priority()); + if (pseudoUp && pseudoUp[iColumn]) { + abort(); + } + } + } + // ************************************************************* + } + int statistics = (printOptions > 0) ? printOptions : 0; + if (!statusUserFunction_[0]) { + free(priorities); + priorities = NULL; + free(branchDirection); + branchDirection = NULL; + free(pseudoDown); + pseudoDown = NULL; + free(pseudoUp); + pseudoUp = NULL; + free(solutionIn); + solutionIn = NULL; + free(prioritiesIn); + prioritiesIn = NULL; + free(sosStart); + sosStart = NULL; + free(sosIndices); + sosIndices = NULL; + free(sosType); + sosType = NULL; + free(sosReference); + sosReference = NULL; + free(cut); + cut = NULL; + free(sosPriority); + sosPriority = NULL; + } + if (nodeStrategy) { + // change default + if (nodeStrategy > 2) { + // up or down + int way = (((nodeStrategy - 1) % 2) == 1) ? -1 : +1; + babModel_->setPreferredWay(way); +#ifdef JJF_ZERO + OsiObject **objects = babModel_->objects(); + int numberObjects = babModel_->numberObjects(); + for (int iObj = 0; iObj < numberObjects; iObj++) { + CbcObject *obj = dynamic_cast< CbcObject * >(objects[iObj]); + assert(obj); + obj->setPreferredWay(way); + } +#endif + } + if (nodeStrategy == 2 || nodeStrategy > 4) { + // depth + CbcCompareDefault compare; + compare.setWeight(-3.0); + babModel_->setNodeComparison(compare); + } else if (nodeStrategy == 0) { + // hybrid was default i.e. mixture of low depth and infeasibility + } else if (nodeStrategy == 1) { + // real fewest + CbcCompareDefault compare; + compare.setWeight(-2.0); + babModel_->setNodeComparison(compare); + } + } + if (cppValue >= 0) { + int prepro = useStrategy ? -1 : preProcess; + // generate code + FILE *fp = fopen("user_driver.cpp", "w"); + if (fp) { + // generate enough to do BAB + babModel_->generateCpp(fp, 1); + OsiClpSolverInterface *osiclp = dynamic_cast< OsiClpSolverInterface * >(babModel_->solver()); + // Make general so do factorization + int factor = osiclp->getModelPtr()->factorizationFrequency(); + osiclp->getModelPtr()->setFactorizationFrequency(200); + osiclp->generateCpp(fp); + osiclp->getModelPtr()->setFactorizationFrequency(factor); + //solveOptions.generateCpp(fp); + fclose(fp); + // now call generate code + generateCode(babModel_, "user_driver.cpp", cppValue, prepro); + } else { + std::cout << "Unable to open file user_driver.cpp" << std::endl; + } + } + if (!babModel_->numberStrong() && babModel_->numberBeforeTrust() > 0) + babModel_->setNumberBeforeTrust(0); + if (useStrategy) { + CbcStrategyDefault strategy(1, babModel_->numberStrong(), babModel_->numberBeforeTrust()); + strategy.setupPreProcessing(1); + babModel_->setStrategy(strategy); + } + if (testOsiOptions >= 0) { + sprintf(generalPrint, "Testing OsiObject options %d", testOsiOptions); + generalMessageHandler->message(CLP_GENERAL, generalMessages) + << generalPrint + << CoinMessageEol; + if (!numberSOS) { + babModel_->solver()->findIntegersAndSOS(false); +#ifdef COIN_HAS_LINK + // If linked then pass in model + OsiSolverLink *solver3 = dynamic_cast< OsiSolverLink * >(babModel_->solver()); + if (solver3) { + CbcHeuristicDynamic3 serendipity(*babModel_); + serendipity.setHeuristicName("linked"); + int heuristicOption = parameters_[whichParam(CBC_PARAM_STR_HEURISTICSTRATEGY, parameters_)].currentOptionAsInteger(); + if (heuristicOption) + babModel_->addHeuristic(&serendipity); + double dextra3 = parameters_[whichParam(CBC_PARAM_DBL_DEXTRA3, parameters_)].doubleValue(); + if (dextra3) + solver3->setMeshSizes(dextra3); + int options = parameters_[whichParam(CBC_PARAM_INT_MIPOPTIONS, parameters_)].intValue() / 10000; + CglStored stored; + if (options) { + printf("nlp options %d\n", options); + /* + 1 - force mini branch and bound + 2 - set priorities high on continuous + 4 - try adding OA cuts + 8 - try doing quadratic linearization + 16 - try expanding knapsacks + 32 - OA cuts strictly concave + 64 - no branching at all on bilinear x-x! + */ + if ((options & 2)) { + solver3->setBiLinearPriorities(10, tightenFactor > 0.0 ? tightenFactor : 1.0); + } else if (tightenFactor > 0.0) { + // set grid size for all continuous bi-linear + solver3->setMeshSizes(tightenFactor); + } + if ((options & 4)) { + solver3->setSpecialOptions2(solver3->specialOptions2() | (8 + 4)); + // say convex + solver3->sayConvex((options & 32) == 0); + } + int extra1 = parameters_[whichParam(CBC_PARAM_INT_EXTRA1, parameters_)].intValue(); + if ((options & 1) != 0 && extra1 > 0) + solver3->setFixedPriority(extra1); + double cutoff = COIN_DBL_MAX; + if ((options & 8)) + cutoff = solver3->linearizedBAB(&stored); + if (cutoff < babModel_->getCutoff()) { + babModel_->setCutoff(cutoff); + // and solution + //babModel_->setBestObjectiveValue(solver3->bestObjectiveValue()); + babModel_->setBestSolution(solver3->bestSolution(), solver3->getNumCols(), + solver3->bestObjectiveValue()); + } + if ((options & 64)) + solver3->setBranchingStrategyOnVariables(16, -1, 4); + } + solver3->setCbcModel(babModel_); + if (stored.sizeRowCuts()) + babModel_->addCutGenerator(&stored, 1, "Stored"); + CglTemporary temp; + babModel_->addCutGenerator(&temp, 1, "OnceOnly"); + //choose.setNumberBeforeTrusted(2000); + //choose.setNumberStrong(20); + } + // For temporary testing of heuristics + //int testOsiOptions = parameters_[whichParam(CBC_PARAM_INT_TESTOSI,numberParameters_,parameters_)].intValue(); + if (testOsiOptions >= 10) { + if (testOsiOptions >= 20) + testOsiOptions -= 10; + printf("*** Temp heuristic with mode %d\n", testOsiOptions - 10); + OsiSolverLink *solver3 = dynamic_cast< OsiSolverLink * >(babModel_->solver()); + assert(solver3); + int extra1 = parameters_[whichParam(CBC_PARAM_INT_EXTRA1, parameters_)].intValue(); + solver3->setBiLinearPriority(extra1); + printf("bilinear priority now %d\n", extra1); + int extra2 = parameters_[whichParam(CBC_PARAM_INT_EXTRA2, parameters_)].intValue(); + double saveDefault = solver3->defaultBound(); + solver3->setDefaultBound(static_cast< double >(extra2)); + double *solution = solver3->heuristicSolution(slpValue > 0 ? slpValue : 40, 1.0e-5, testOsiOptions - 10); + solver3->setDefaultBound(saveDefault); + if (!solution) + printf("Heuristic failed\n"); + } +#endif + } else { + // move across + babModel_->deleteObjects(false); + //babModel_->addObjects(babModel_->solver()->numberObjects(),babModel_->solver()->objects()); + } + CbcBranchDefaultDecision decision; + if (babModel_->numberStrong()) { + OsiChooseStrong choose(babModel_->solver()); + choose.setNumberBeforeTrusted(babModel_->numberBeforeTrust()); + choose.setNumberStrong(babModel_->numberStrong()); + choose.setShadowPriceMode(testOsiOptions); + decision.setChooseMethod(choose); + } else { + OsiChooseVariable choose(babModel_->solver()); + decision.setChooseMethod(choose); + } + babModel_->setBranchingMethod(decision); + if (useCosts && testOsiOptions >= 0) { + if (newPriorities) { + // get rid of + delete[] newPriorities; + newPriorities = NULL; + } + int numberColumns = babModel_->getNumCols(); + int *sort = new int[numberColumns]; + double *dsort = new double[numberColumns]; + int *priority = new int[numberColumns]; + const double *objective = babModel_->getObjCoefficients(); + const double *lower = babModel_->getColLower(); + const double *upper = babModel_->getColUpper(); + const CoinPackedMatrix *matrix = babModel_->solver()->getMatrixByCol(); + const int *columnLength = matrix->getVectorLengths(); + int iColumn; + for (iColumn = 0; iColumn < numberColumns; iColumn++) { + sort[iColumn] = iColumn; + if (useCosts == 1) + dsort[iColumn] = -fabs(objective[iColumn]); + else if (useCosts == 2) + dsort[iColumn] = iColumn; + else if (useCosts == 3) + dsort[iColumn] = upper[iColumn] - lower[iColumn]; + else if (useCosts == 4) + dsort[iColumn] = -(upper[iColumn] - lower[iColumn]); + else if (useCosts == 5) + dsort[iColumn] = -columnLength[iColumn]; + } + CoinSort_2(dsort, dsort + numberColumns, sort); + int level = 0; + double last = -1.0e100; + for (int i = 0; i < numberColumns; i++) { + int iPut = sort[i]; + if (dsort[i] != last) { + level++; + last = dsort[i]; + } + priority[iPut] = level; + } + OsiObject **objects = babModel_->objects(); + int numberObjects = babModel_->numberObjects(); + for (int iObj = 0; iObj < numberObjects; iObj++) { + OsiObject *obj = objects[iObj]; + int iColumn = obj->columnNumber(); + if (iColumn >= 0) + obj->setPriority(priority[iColumn]); + } + delete[] priority; + delete[] sort; + delete[] dsort; + } + } + checkSOS(babModel_, babModel_->solver()); + if (doSprint > 0) { + // Sprint for primal solves + ClpSolve::SolveType method = ClpSolve::usePrimalorSprint; + ClpSolve::PresolveType presolveType = ClpSolve::presolveOff; + int numberPasses = 5; + int options[] = { 0, 3, 0, 0, 0, 0 }; + int extraInfo[] = { -1, 20, -1, -1, -1, -1 }; + extraInfo[1] = doSprint; + int independentOptions[] = { 0, 0, 3 }; + ClpSolve clpSolve(method, presolveType, numberPasses, + options, extraInfo, independentOptions); + // say use in OsiClp + clpSolve.setSpecialOption(6, 1); + OsiClpSolverInterface *osiclp = dynamic_cast< OsiClpSolverInterface * >(babModel_->solver()); + osiclp->setSolveOptions(clpSolve); + osiclp->setHintParam(OsiDoDualInResolve, false); + // switch off row copy + osiclp->getModelPtr()->setSpecialOptions(osiclp->getModelPtr()->specialOptions() | 256); + osiclp->getModelPtr()->setInfeasibilityCost(1.0e11); + } +#ifdef COIN_HAS_LINK + if (storedAmpl.sizeRowCuts()) { + if (preProcess) { + const int *originalColumns = process.originalColumns(); + int numberColumns = babModel_->getNumCols(); + int *newColumn = new int[numberOriginalColumns]; + int i; + for (i = 0; i < numberOriginalColumns; i++) + newColumn[i] = -1; + for (i = 0; i < numberColumns; i++) { + int iColumn = originalColumns[i]; + newColumn[iColumn] = i; + } + int *buildColumn = new int[numberColumns]; + // Build up valid cuts + int nBad = 0; + int nCuts = storedAmpl.sizeRowCuts(); + CglStored newCuts; + for (i = 0; i < nCuts; i++) { + const OsiRowCut *cut = storedAmpl.rowCutPointer(i); + double lb = cut->lb(); + double ub = cut->ub(); + int n = cut->row().getNumElements(); + const int *column = cut->row().getIndices(); + const double *element = cut->row().getElements(); + bool bad = false; + for (int i = 0; i < n; i++) { + int iColumn = column[i]; + iColumn = newColumn[iColumn]; + if (iColumn >= 0) { + buildColumn[i] = iColumn; + } else { + bad = true; + break; + } + } + if (!bad) { + newCuts.addCut(lb, ub, n, buildColumn, element); + } else { + nBad++; + } + } + storedAmpl = newCuts; + if (nBad) + printf("%d cuts dropped\n", nBad); + delete[] newColumn; + delete[] buildColumn; + } + } +#endif +#ifdef CLP_MALLOC_STATISTICS + malloc_stats(); + malloc_stats2(); +#endif +#ifndef CBC_OTHER_SOLVER + if (outputFormat == 5) { + osiclp = dynamic_cast< OsiClpSolverInterface * >(babModel_->solver()); + lpSolver = osiclp->getModelPtr(); + lpSolver->setPersistenceFlag(1); + } +#endif + // add in lotsizing + if (statusUserFunction_[0] && info.special) { + int numberColumns = babModel_->getNumCols(); + int i; + int n = 0; + if (preProcess) { + const int *originalColumns = process.originalColumns(); + for (i = 0; i < numberColumns; i++) { + int iColumn = originalColumns[i]; + assert(iColumn >= i); + int iType = info.special[iColumn]; + if (iType) { + assert(iType == 1); + n++; + } + info.special[i] = iType; + } + } + if (n) { + int numberIntegers = 0; + int numberOldObjects = 0; + OsiObject **oldObjects = NULL; + const double *lower = babModel_->solver()->getColLower(); + const double *upper = babModel_->solver()->getColUpper(); + if (testOsiOptions < 0) { + // ************************************************************* + // CbcObjects + numberIntegers = babModel_->numberIntegers(); + /* model may not have created objects + If none then create + */ + if (!numberIntegers || !babModel_->numberObjects()) { + int type = (pseudoUp) ? 1 : 0; + babModel_->findIntegers(true, type); + numberIntegers = babModel_->numberIntegers(); + } + oldObjects = babModel_->objects(); + numberOldObjects = babModel_->numberObjects(); + } else { + numberIntegers = testOsiSolver->getNumIntegers(); + if (!numberIntegers || !testOsiSolver->numberObjects()) { + /* model may not have created objects + If none then create + */ + testOsiSolver->findIntegers(false); + numberIntegers = testOsiSolver->getNumIntegers(); + } + oldObjects = testOsiSolver->objects(); + numberOldObjects = testOsiSolver->numberObjects(); + } + OsiObject **objects = new OsiObject *[n]; + n = 0; + // set new objects to have one lower priority + double ranges[] = { -COIN_DBL_MAX, -1.0, 1.0, COIN_DBL_MAX }; + for (int iObj = 0; iObj < numberOldObjects; iObj++) { + int iColumn = oldObjects[iObj]->columnNumber(); + if (iColumn >= 0 && info.special[iColumn]) { + if (lower[iColumn] <= -1.0 && upper[iColumn] >= 0.0) { + ranges[0] = lower[iColumn]; + ranges[3] = upper[iColumn]; + int priority = oldObjects[iObj]->priority(); + if (testOsiOptions < 0) { + objects[n] = new CbcLotsize(babModel_, iColumn, 2, ranges, true); + } else { + objects[n] = new OsiLotsize(testOsiSolver, iColumn, 2, ranges, true); + } + objects[n++]->setPriority(priority - 1); + } + } + } + if (testOsiOptions < 0) { + babModel_->addObjects(n, objects); + } else { + testOsiSolver->addObjects(n, objects); + } + for (i = 0; i < n; i++) + delete objects[i]; + delete[] objects; + } + } + if (storedAmpl.sizeRowCuts()) { + //babModel_->addCutGenerator(&storedAmpl,1,"AmplStored"); + int numberRowCuts = storedAmpl.sizeRowCuts(); + for (int i = 0; i < numberRowCuts; i++) { + const OsiRowCut *rowCutPointer = storedAmpl.rowCutPointer(i); + babModel_->makeGlobalCut(rowCutPointer); + } + } + // If defaults then increase trust for small models + if (!strongChanged && false) { + int numberColumns = babModel_->getNumCols(); + if (numberColumns <= 50) + babModel_->setNumberBeforeTrust(1000); + else if (numberColumns <= 100) + babModel_->setNumberBeforeTrust(100); + else if (numberColumns <= 300) + babModel_->setNumberBeforeTrust(50); + } +#ifdef CBC_THREAD + int numberThreads = parameters_[whichParam(CBC_PARAM_INT_THREADS, parameters_)].intValue(); + babModel_->setNumberThreads(numberThreads % 100); + babModel_->setThreadMode(numberThreads / 100); +#endif + int returnCode = 0; + if (callBack != NULL) + returnCode = callBack(babModel_, 3); + if (returnCode) { + // exit if user wants + delete babModel_; + babModel_ = NULL; + return returnCode; + } +#ifndef CBC_OTHER_SOLVER + osiclp = dynamic_cast< OsiClpSolverInterface * >(babModel_->solver()); + lpSolver = osiclp->getModelPtr(); + int hotits = parameters_[whichParam(CBC_PARAM_INT_MAXHOTITS, parameters_)].intValue(); + if (hotits > 100) { + osiclp->setSpecialOptions(osiclp->specialOptions() & ~32); + osiclp->setIntParam(OsiMaxNumIterationHotStart, hotits); + } else { + osiclp->setIntParam(OsiMaxNumIterationHotStart, hotits); + } +#elif CBC_OTHER_SOLVER == 1 +#endif + if ((experimentFlag >= 1 || strategyFlag >= 1) && + abs(babModel_->fastNodeDepth()) == 1) { + int iType = babModel_->fastNodeDepth(); + int iDepth = iType <0 ? -12 : 8; + int iSize = iType <0 ? 10000 : 500; + if (babModel_->solver()->getNumCols() + + babModel_->solver()->getNumRows() < iSize) { + babModel_->setFastNodeDepth(iDepth); + } else { + babModel_->setFastNodeDepth(-1); // not sure about when +1 + } + } else if (babModel_->fastNodeDepth() == -999) { + babModel_->setFastNodeDepth(-1); + } + int heurOptions = parameters_[whichParam(CBC_PARAM_INT_HOPTIONS, parameters_)].intValue(); + if (heurOptions > 100) + babModel_->setSpecialOptions(babModel_->specialOptions() | 8192); + +#ifndef CBC_OTHER_SOLVER +#ifdef CLP_MULTIPLE_FACTORIZATIONS + int denseCode = parameters_[whichParam(CBC_PARAM_INT_DENSE, parameters_)].intValue(); + int smallCode = parameters_[whichParam(CBC_PARAM_INT_SMALLFACT, parameters_)].intValue(); + if (bothFlags >= 1) { + if (denseCode < 0) + denseCode = 40; + if (smallCode < 0 && !lpSolver->factorization()->isDenseOrSmall()) + smallCode = 40; + } + if (denseCode > 0) { + lpSolver->factorization()->setGoDenseThreshold(denseCode); + assert(osiclp == babModel_->solver()); + osiclp->setSpecialOptions(osiclp->specialOptions() | 1024); + } + if (smallCode > 0 && smallCode > denseCode) + lpSolver->factorization()->setGoSmallThreshold(smallCode); + //if (denseCode>=lpSolver->numberRows()) { + //lpSolver->factorization()->goDense(); + //} + if (lpSolver->factorization()->goOslThreshold() > 1000) { + // use osl in gomory (may not if CglGomory decides not to) + int numberGenerators = babModel_->numberCutGenerators(); + int nGomory = 0; + for (int iGenerator = 0; iGenerator < numberGenerators; + iGenerator++) { + CbcCutGenerator *generator = babModel_->cutGenerator(iGenerator); + CglGomory *gomory = dynamic_cast< CglGomory * >(generator->generator()); + if (gomory) { + if (nGomory < 2) { + gomory->useAlternativeFactorization(); + } else if (gomory->originalSolver()) { + OsiClpSolverInterface *clpSolver = dynamic_cast< OsiClpSolverInterface * >(gomory->originalSolver()); + if (clpSolver) { + ClpSimplex *simplex = clpSolver->getModelPtr(); + simplex->factorization()->setGoOslThreshold(0); + } + } + nGomory++; + } + } + } +#endif +#endif +#ifdef CLIQUE_ANALYSIS + if (!storedAmpl.sizeRowCuts()) { + printf("looking at probing\n"); + babModel_->addCutGenerator(&storedAmpl, 1, "Stored"); + } +#endif +#ifdef SOS_AS_CUTS +#ifdef CBC_HAS_CLP + /* SOS as cuts + Could be a bit more sophisticated e.g. only non duplicates + Could do something for SOS 2? + */ + { + OsiClpSolverInterface *clpSolver = dynamic_cast< OsiClpSolverInterface * >(babModel_->solver()); + if (clpSolver && clpSolver->numberSOS()) { + // SOS + int numberSOS = clpSolver->numberSOS(); + const CoinSet *setInfo = clpSolver->setInfo(); + CglStored sosCuts; + const double *lower = clpSolver->getColLower(); + const double *upper = clpSolver->getColUpper(); + // Start Cliques + // sizes + int nEls = 0; + for (int i = 0; i < numberSOS; i++) + nEls += setInfo[i].numberEntries(); + double *els = new double[nEls + 2 * numberSOS]; + for (int i = 0; i < nEls; i++) + els[i] = 1.0; + double *lo = els + nEls; + double *up = lo + numberSOS; + // need to get rid of sos + ClpSimplex *fakeSimplex = new ClpSimplex(*clpSolver->getModelPtr()); +#if 0 + int numberRows=fakeSimplex->numberRows(); + int * starts = + new int[CoinMax(numberSOS+1,numberRows)]; + int * columns = new int[nEls]; + for (int i=0;ideleteRows(numberRows,starts); +#else + int *starts = new int[numberSOS + 1]; + int *columns = new int[nEls]; +#endif + int nAdded = 0; + starts[0] = 0; + nEls = 0; + + // just SOS 1 with 0-1 + for (int i = 0; i < numberSOS; i++) { + int type = setInfo[i].setType(); + if (type == 2) + continue; + int n = setInfo[i].numberEntries(); + const int *which = setInfo[i].which(); + for (int j = 0; j < n; j++) { + int iColumn = which[j]; + if (lower[iColumn] || upper[iColumn] != 1.0) { + n = -1; + break; // no good + } + } + if (n > 0) { + memcpy(columns + nEls, which, n * sizeof(int)); + lo[nAdded] = -COIN_DBL_MAX; + up[nAdded] = 1.0; + nAdded++; + nEls += n; + starts[nAdded] = nEls; + } + } + if (nAdded) + fakeSimplex->addRows(nAdded, + lo, up, + starts, columns, els); + if (nAdded) { + OsiClpSolverInterface fakeSolver(fakeSimplex); + CglFakeClique fakeGen(&fakeSolver, false); + fakeGen.setStarCliqueReport(false); + fakeGen.setRowCliqueReport(false); + fakeGen.setMinViolation(0.05); + babModel_->addCutGenerator(&fakeGen, 1, "SosCuts"); + //fakeSimplex->writeMps("bad.mps",0,1); + sosCuts.setProbingInfo(new CglTreeProbingInfo(&fakeSolver)); + } + delete fakeSimplex; + // End Cliques + // Start Stored + nAdded = 0; + for (int i = 0; i < numberSOS; i++) { + int type = setInfo[i].setType(); + int n = setInfo[i].numberEntries(); + const int *which = setInfo[i].which(); + double rhs = 0.0; + double previous = 0.0; + for (int j = 0; j < n; j++) { + int iColumn = which[j]; + if (lower[iColumn]) { + n = -1; + break; // no good + } + rhs = CoinMax(upper[iColumn] + previous, rhs); + if (type == 2) + previous = upper[iColumn]; + } + if (n > 0) { + sosCuts.addCut(0.0, rhs, + n, which, els); + nAdded++; + } + } + if (nAdded) + babModel_->addCutGenerator(&sosCuts, 1, "SosCuts2"); + // End Stored + delete[] els; + delete[] columns; + delete[] starts; + } + } +#endif +#endif + if (useSolution > 1) { + // use hotstart to try and find solution + CbcHeuristicPartial partial(*babModel_, 10000, useSolution); + partial.setHeuristicName("Partial solution given"); + babModel_->addHeuristic(&partial); + } + if (logLevel <= 1 && babModel_->solver()->messageHandler() != babModel_->messageHandler()) + babModel_->solver()->setHintParam(OsiDoReducePrint, true, OsiHintTry); +#ifdef CBC_TEMP1 + if (osiclp->getModelPtr()->perturbation() == 50) + osiclp->getModelPtr()->setPerturbation(52); // try less +#endif +#ifdef JJF_ZERO + if (osiclp->getNumCols() == 29404) { + void restoreSolution(ClpSimplex * lpSolver, + std::string fileName, int mode); + restoreSolution(osiclp->getModelPtr(), "debug.file", 0); + int numberColumns = osiclp->getNumCols(); + const double *solution = osiclp->getColSolution(); + const int *originalColumns = process.originalColumns(); + for (int i = 0; i < numberColumns; i++) { + int iColumn = originalColumns[i]; + if (saveSolver->isInteger(iColumn)) { + double value = solution[i]; + double value2 = floor(value + 0.5); + assert(fabs(value - value2) < 1.0e-3); + saveSolver->setColLower(iColumn, value2); + saveSolver->setColUpper(iColumn, value2); + } + } + saveSolver->writeMps("fixed"); + babModel_->setBestSolution(osiclp->getColSolution(), + osiclp->getNumCols(), + 1.5325e10); + } else { + babModel_->branchAndBound(statistics); + } +#else +#ifdef ORBITAL + CbcOrbital orbit(babModel_); + orbit.morph(); + exit(1); +#endif + int hOp1 = parameters_[whichParam(CBC_PARAM_INT_HOPTIONS, parameters_)].intValue() / 100000; + if (hOp1 % 10) { + CbcCompareDefault compare; + compare.setBreadthDepth(hOp1 % 10); + babModel_->setNodeComparison(compare); + } else if (hOp1 == 10) { + CbcCompareObjective compare; + babModel_->setNodeComparison(compare); + } +#if CBC_OTHER_SOLVER == 1 + if (dynamic_cast< OsiCpxSolverInterface * >(babModel_->solver())) + babModel_->solver()->messageHandler()->setLogLevel(0); +#endif + if (parameters_[whichParam(CBC_PARAM_STR_CPX, parameters_)].currentOptionAsInteger()) { + babModel_->setSpecialOptions(babModel_->specialOptions() | 16384); + //if (babModel_->fastNodeDepth()==-1) + babModel_->setFastNodeDepth(-2); // Use Cplex at root + } + int hOp2 = parameters_[whichParam(CBC_PARAM_INT_HOPTIONS, parameters_)].intValue() / 10000; + if (hOp2 % 10) { + babModel_->setSpecialOptions(babModel_->specialOptions() | 16384); + if (babModel_->fastNodeDepth() == -1) + babModel_->setFastNodeDepth(-2); // Use Cplex at root + } + if (experimentFlag >= 5 && experimentFlag < 10000) { + CbcModel donor(*babModel_); + int options = babModel_->specialOptions(); + donor.setSpecialOptions(options | 262144); + ClpSimplex *lpSolver2; + OsiClpSolverInterface *clpSolver2; + clpSolver2 = dynamic_cast< OsiClpSolverInterface * >(donor.solver()); + assert(clpSolver2); + lpSolver2 = clpSolver2->getModelPtr(); + assert(lpSolver2); + if (lpSolver->factorization()->isDenseOrSmall()) { + lpSolver2->factorization()->forceOtherFactorization(0); + lpSolver2->factorization()->setGoOslThreshold(0); + lpSolver2->factorization()->setGoDenseThreshold(0); + lpSolver2->factorization()->setGoSmallThreshold(0); + lpSolver2->allSlackBasis(); + lpSolver2->initialSolve(); + int numberGenerators = donor.numberCutGenerators(); + for (int iGenerator = 0; iGenerator < numberGenerators; + iGenerator++) { + CbcCutGenerator *generator = donor.cutGenerator(iGenerator); + CglGomory *gomory = dynamic_cast< CglGomory * >(generator->generator()); + if (gomory) + gomory->useAlternativeFactorization(false); + } + } else { + printf("code this\n"); + abort(); + } + babModel_->setSpecialOptions(options | 524288); + CglStored *stored = new CglStored(donor.getNumCols()); + donor.setStoredRowCuts(stored); + donor.branchAndBound(0); + babModel_->setStoredRowCuts(donor.storedRowCuts()); + donor.setStoredRowCuts(NULL); + } + // We may have priorities from extra variables + int more2 = parameters_[whichParam(CBC_PARAM_INT_MOREMOREMIPOPTIONS, parameters_)].intValue(); + if (newPriorities) { + if (truncateColumns < babModel_->getNumCols()) { + // set new ones as high prority + babModel_->passInPriorities(newPriorities, false); + } + delete[] newPriorities; + } else if ((more2 & (512 | 1024)) != 0) { + babModel_->findIntegers(true); + int numberIntegers = babModel_->numberIntegers(); + int *newPriorities = new int[numberIntegers]; + int n = numberIntegers - (babModel_->getNumCols() - truncateColumns); + for (int i = 0; i < n; i++) + newPriorities[i] = babModel_->priority(i); +#if 1 + int ixxxxxx = parameters_[whichParam(CBC_PARAM_INT_MAXNODES, parameters_)].intValue(); + int obj_priority = 1000; + int slack_priority = 1000; + if (ixxxxxx >= 1000000 && ixxxxxx < 1010000) { + ixxxxxx -= 1000000; + if (ixxxxxx == 0) { + obj_priority = 1000; + slack_priority = 1000; + } else if (ixxxxxx == 1) { + obj_priority = 10000; + slack_priority = 10000; + } else if (ixxxxxx == 2) { + obj_priority = 100; + slack_priority = 100; + } else if (ixxxxxx == 3) { + obj_priority = 100; + slack_priority = 10000; + } else if (ixxxxxx == 4) { + obj_priority = 10000; + slack_priority = 100; + } else if (ixxxxxx == 5) { + obj_priority = 100; + slack_priority = 200; + } else if (ixxxxxx == 6) { + obj_priority = 200; + slack_priority = 100; + } else { + abort(); + } + } + if ((more2 & 512) != 0) { + newPriorities[n++] = obj_priority; + } + if ((more2 & 1024) != 0) { + for (int i = n; i < numberIntegers; i++) + newPriorities[i] = slack_priority; + } +#else +#define PRIORITY_TRY 0 +#if PRIORITY_TRY == 0 +#define OBJ_PRIORITY 1000 +#define SLACK_PRIORITY 1000 +#elif PRIORITY_TRY == 1 +#define OBJ_PRIORITY 10000 +#define SLACK_PRIORITY 10000 +#elif PRIORITY_TRY == 2 +#define OBJ_PRIORITY 100 +#define SLACK_PRIORITY 100 +#elif PRIORITY_TRY == 3 +#define OBJ_PRIORITY 100 +#define SLACK_PRIORITY 10000 +#elif PRIORITY_TRY == 4 +#define OBJ_PRIORITY 10000 +#define SLACK_PRIORITY 100 +#elif PRIORITY_TRY == 5 +#define OBJ_PRIORITY 100 +#define SLACK_PRIORITY 200 +#elif PRIORITY_TRY == 6 +#define OBJ_PRIORITY 200 +#define SLACK_PRIORITY 100 +#endif + if ((more2 & 512) != 0) { + newPriorities[n++] = OBJ_PRIORITY; + } + if ((more2 & 1024) != 0) { + for (int i = n; i < numberIntegers; i++) + newPriorities[i] = SLACK_PRIORITY; + } +#endif + babModel_->passInPriorities(newPriorities, false); + delete[] newPriorities; + } +#ifdef JJF_ZERO + int extra5 = parameters_[whichParam(EXTRA5, parameters_)].intValue(); + if (extra5 > 0) { + int numberGenerators = babModel_->numberCutGenerators(); + for (int iGenerator = 0; iGenerator < numberGenerators; + iGenerator++) { + CbcCutGenerator *generator = babModel_->cutGenerator(iGenerator); + CglGomory *gomory = dynamic_cast< CglGomory * >(generator->generator()); + if (gomory) { + CglGomory gomory2(*gomory); + gomory2.useAlternativeFactorization(!gomory->alternativeFactorization()); + babModel_->addCutGenerator(&gomory2, -99, "Gomory2"); + } + } + } +#endif + int specialOptions = parameters_[whichParam(CBC_PARAM_INT_STRONG_STRATEGY, parameters_)].intValue(); + if (specialOptions >= 0) + babModel_->setStrongStrategy(specialOptions); + int jParam = whichParam(CBC_PARAM_STR_CUTOFF_CONSTRAINT, + parameters_); + if (parameters_[jParam].currentOptionAsInteger()) { + babModel_->setCutoffAsConstraint(true); + int moreOptions = babModel_->moreSpecialOptions(); + if (parameters_[jParam].currentOptionAsInteger() == 4) + babModel_->setMoreSpecialOptions(moreOptions | 4194304); + } + int multipleRoot = parameters_[whichParam(CBC_PARAM_INT_MULTIPLEROOTS, parameters_)].intValue(); + if (multipleRoot < 10000) { + babModel_->setMultipleRootTries(multipleRoot); + } else { + // will be doing repeated solves and saves + int numberGoes = multipleRoot / 10000; + multipleRoot -= 10000 * numberGoes; + int moreOptions = babModel_->moreSpecialOptions(); + if (numberGoes < 100) { + remove("global.cuts"); + remove("global.fix"); + moreOptions |= (67108864 | 134217728); + } else { + moreOptions |= 67108864 * (numberGoes / 100); + numberGoes = numberGoes % 100; + } + babModel_->setMultipleRootTries(multipleRoot); + babModel_->setMoreSpecialOptions(moreOptions); + int numberColumns = babModel_->getNumCols(); + double *bestValues = new double[numberGoes]; + double **bestSolutions = new double *[numberGoes]; + int *which = new int[numberGoes]; + int numberSolutions = 0; + sprintf(generalPrint, "Starting %d passes each with %d solvers", + numberGoes, multipleRoot % 10); + generalMessageHandler->message(CLP_GENERAL, generalMessages) + << generalPrint + << CoinMessageEol; + for (int iGo = 0; iGo < numberGoes; iGo++) { + sprintf(generalPrint, "Starting pass %d", iGo + 1); + generalMessageHandler->message(CLP_GENERAL, generalMessages) + << generalPrint + << CoinMessageEol; + CbcModel tempModel = *babModel_; + tempModel.setMaximumNodes(0); + // switch off cuts if none generated + int numberGenerators = tempModel.numberCutGenerators(); + for (int iGenerator = 0; iGenerator < numberGenerators; iGenerator++) { + CbcCutGenerator *generator = tempModel.cutGenerator(iGenerator); + generator->setSwitchOffIfLessThan(1); + } + // random + tempModel.setRandomSeed(tempModel.getRandomSeed() + 100000000 * (iGo + 1 + 5 * numberGoes)); + for (int i = 0; i < tempModel.numberHeuristics(); i++) + tempModel.heuristic(i)->setSeed(tempModel.heuristic(i)->getSeed() + 100000000 * iGo); +#ifndef CBC_OTHER_SOLVER + OsiClpSolverInterface *solver = dynamic_cast< OsiClpSolverInterface * >(tempModel.solver()); + ClpSimplex *simplex = solver->getModelPtr(); + int solverSeed = simplex->randomNumberGenerator()->getSeed(); + simplex->setRandomSeed(solverSeed + 100000000 * (iGo + 1)); +#endif + tempModel.branchAndBound(); + if (tempModel.bestSolution()) { + bestSolutions[numberSolutions] = CoinCopyOfArray(tempModel.bestSolution(), + numberColumns); + bestValues[numberSolutions] = -tempModel.getMinimizationObjValue(); + which[numberSolutions] = numberSolutions; + numberSolutions++; + } + } + // allow solutions + double sense = babModel_->solver()->getObjSense(); + ; + CoinSort_2(bestValues, bestValues + numberSolutions, which); + babModel_->setMoreSpecialOptions(moreOptions & (~16777216)); + for (int i = 0; i < numberSolutions; i++) { + int k = which[i]; + if (bestValues[i] < babModel_->getCutoff()) { + babModel_->setBestSolution(bestSolutions[k], numberColumns, + -bestValues[i] * sense, true); + babModel_->incrementUsed(bestSolutions[k]); + } + delete[] bestSolutions[k]; + } + babModel_->setMoreSpecialOptions(moreOptions); + if (numberSolutions) + sprintf(generalPrint, "Ending major passes - best solution %g", -bestValues[numberSolutions - 1]); + else + sprintf(generalPrint, "Ending major passes - no solution found"); + generalMessageHandler->message(CLP_GENERAL, generalMessages) + << generalPrint + << CoinMessageEol; + delete[] which; + delete[] bestValues; + delete[] bestSolutions; + } + if (biLinearProblem) + babModel_->setSpecialOptions(babModel_->specialOptions() & (~(512 | 32768))); + babModel_->setMoreSpecialOptions2(parameters_[whichParam(CBC_PARAM_INT_MOREMOREMIPOPTIONS, parameters_)].intValue()); +#ifdef CBC_HAS_NAUTY + int nautyAdded = 0; + { + int jParam = whichParam(CBC_PARAM_STR_ORBITAL, + parameters_); + if (parameters_[jParam].currentOptionAsInteger()) { + int k = parameters_[jParam].currentOptionAsInteger(); + if (k < 4) { + babModel_->setMoreSpecialOptions2(babModel_->moreSpecialOptions2() | (k * 128)); + } else if (k == 4) { +#define MAX_NAUTY_PASS 2000 + nautyAdded = nautiedConstraints(*babModel_, + MAX_NAUTY_PASS); + } else { + assert (k==5 || k ==6); + if (k ==5) + babModel_->setMoreSpecialOptions2(babModel_->moreSpecialOptions2() | 128 | 256 | 131072); + else + babModel_->setMoreSpecialOptions2(babModel_->moreSpecialOptions2() | 128 | 256 | 131072 | 262144); + } + } + } +#endif + // Set up pointer to preProcess + if (preProcessPointer) { + babModel_->setPreProcess(preProcessPointer); + } +#ifndef CBC_OTHER_SOLVER + { + OsiClpSolverInterface *solver = dynamic_cast< OsiClpSolverInterface * >(babModel_->solver()); + ClpSimplex *simplex = solver->getModelPtr(); + // if wanted go back to old printing method + double value = simplex->getMinIntervalProgressUpdate(); + if (value<=0.0) { + babModel_->setSecsPrintFrequency(-1.0); + if (value<-1.0) { + babModel_->setPrintFrequency(static_cast(-value)); + } else { + if (babModel_->getNumCols() > 2000) + babModel_->setPrintFrequency(100); + else + babModel_->setPrintFrequency(1000); + } + } else { + babModel_->setSecsPrintFrequency(value); + } + } +#endif + babModel_->branchAndBound(statistics); +#ifdef CBC_HAS_NAUTY + if (nautyAdded) { + int *which = new int[nautyAdded]; + int numberOldRows = babModel_->solver()->getNumRows() - nautyAdded; + for (int i = 0; i < nautyAdded; i++) + which[i] = i + numberOldRows; + babModel_->solver()->deleteRows(nautyAdded, which); + delete[] which; + babModel_->solver()->resolve(); + } +#endif + if (truncateColumns < babModel_->solver()->getNumCols()) { + OsiSolverInterface *solverX = babModel_->solver(); + int numberColumns = solverX->getNumCols(); + int numberRows = solverX->getNumRows(); + int numberDelete = numberColumns - truncateColumns; + int *delStuff = new int[numberDelete]; + for (int i = 0; i < numberDelete; i++) + delStuff[i] = i + truncateColumns; + solverX->deleteCols(numberDelete, delStuff); + numberDelete = numberRows - truncateRows; + for (int i = 0; i < numberDelete; i++) + delStuff[i] = i + truncateRows; + solverX->deleteRows(numberDelete, delStuff); + delete[] delStuff; + if (truncatedRhsLower) { + numberRows = solverX->getNumRows(); + for (int i = 0; i < numberRows; i++) { + solverX->setRowLower(i, truncatedRhsLower[i]); + solverX->setRowUpper(i, truncatedRhsUpper[i]); + } + delete[] truncatedRhsLower; + delete[] truncatedRhsUpper; + } + } + //#define CLP_FACTORIZATION_INSTRUMENT +#ifdef CLP_FACTORIZATION_INSTRUMENT + extern double factorization_instrument(int type); + double facTime = factorization_instrument(0); + printf("Factorization %g seconds\n", + facTime); +#endif +#endif +#ifdef COIN_DEVELOP +#ifndef JJF_ONE + { + int numberColumns = babModel_->getNumCols(); + const double *solution = babModel_->bestSolution(); + if (solution && numberColumns < 1000) { + for (int i = 0; i < numberColumns; i++) { + if (solution[i]) + printf("SOL %d %.18g\n", i, solution[i]); + } + } + } +#endif + void printHistory(const char *file /*,CbcModel * model*/); + printHistory("branch.log" /*,babModel_*/); +#endif + returnCode = 0; + if (callBack != NULL) + returnCode = callBack(babModel_, 4); + if (returnCode) { + // exit if user wants + model_.moveInfo(*babModel_); + delete babModel_; + babModel_ = NULL; + return returnCode; + } +#ifdef CLP_MALLOC_STATISTICS + malloc_stats(); + malloc_stats2(); +#endif + checkSOS(babModel_, babModel_->solver()); + } else if (type == CBC_PARAM_ACTION_MIPLIB) { + int typeOfCuts = babModel_->numberCutGenerators() ? 1 : -1; + CbcStrategyDefault strategy(typeOfCuts, + babModel_->numberStrong(), + babModel_->numberBeforeTrust()); + // Set up pre-processing + int translate2[] = { 9999, 1, 1, 3, 2, 4, 5, 6, 6 }; + if (preProcess) + strategy.setupPreProcessing(translate2[preProcess]); + babModel_->setStrategy(strategy); +#ifdef CBC_THREAD + int numberThreads = parameters_[whichParam(CBC_PARAM_INT_THREADS, parameters_)].intValue(); + babModel_->setNumberThreads(numberThreads % 100); + babModel_->setThreadMode(numberThreads / 100); +#endif +#ifndef CBC_OTHER_SOLVER + if (outputFormat == 5) { + osiclp = dynamic_cast< OsiClpSolverInterface * >(babModel_->solver()); + lpSolver = osiclp->getModelPtr(); + lpSolver->setPersistenceFlag(1); + } +#endif + if (testOsiOptions >= 0) { + printf("Testing OsiObject options %d\n", testOsiOptions); + CbcBranchDefaultDecision decision; + OsiChooseStrong choose(babModel_->solver()); + choose.setNumberBeforeTrusted(babModel_->numberBeforeTrust()); + choose.setNumberStrong(babModel_->numberStrong()); + choose.setShadowPriceMode(testOsiOptions); + //babModel_->deleteObjects(false); + decision.setChooseMethod(choose); + babModel_->setBranchingMethod(decision); + } + model_ = *babModel_; +#ifndef CBC_OTHER_SOLVER + { + osiclp = dynamic_cast< OsiClpSolverInterface * >(model_.solver()); + lpSolver = osiclp->getModelPtr(); + lpSolver->setSpecialOptions(lpSolver->specialOptions() | IN_BRANCH_AND_BOUND); // say is Cbc (and in branch and bound) + if (lpSolver->factorization()->goOslThreshold() > 1000) { + // use osl in gomory (may not if CglGomory decides not to) + int numberGenerators = model_.numberCutGenerators(); + for (int iGenerator = 0; iGenerator < numberGenerators; + iGenerator++) { + CbcCutGenerator *generator = model_.cutGenerator(iGenerator); + CglGomory *gomory = dynamic_cast< CglGomory * >(generator->generator()); + if (gomory) + gomory->useAlternativeFactorization(); + } + } + } +#endif + /* LL: this was done in CoinSolve.cpp: main(argc, argv). + I have moved it here so that the miplib directory location + could be passed to CbcClpUnitTest. */ + /* JJF: No need to have 777 flag at all - user + says -miplib + */ + int extra2 = parameters_[whichParam(CBC_PARAM_INT_EXTRA2, parameters_)].intValue(); + double stuff[11]; + stuff[0] = parameters_[whichParam(CBC_PARAM_DBL_FAKEINCREMENT, parameters_)].doubleValue(); + stuff[1] = parameters_[whichParam(CBC_PARAM_DBL_FAKECUTOFF, parameters_)].doubleValue(); + stuff[2] = parameters_[whichParam(CBC_PARAM_DBL_DEXTRA3, parameters_)].doubleValue(); + stuff[3] = parameters_[whichParam(CBC_PARAM_DBL_DEXTRA4, parameters_)].doubleValue(); + stuff[4] = parameters_[whichParam(CBC_PARAM_INT_DENSE, parameters_)].intValue(); + stuff[5] = parameters_[whichParam(CBC_PARAM_INT_EXTRA1, parameters_)].intValue(); + stuff[6] = parameters_[whichParam(CBC_PARAM_INT_EXTRA3, parameters_)].intValue(); + stuff[7] = parameters_[whichParam(CBC_PARAM_INT_DEPTHMINIBAB, parameters_)].intValue(); + stuff[8] = bothFlags; + stuff[9] = doVector; + stuff[10] = parameters_[whichParam(CBC_PARAM_INT_SMALLFACT, parameters_)].intValue(); + if (dominatedCuts) + model_.setSpecialOptions(model_.specialOptions() | 64); + if (parameters_[whichParam(CBC_PARAM_STR_CPX, parameters_)].currentOptionAsInteger()) { + model_.setSpecialOptions(model_.specialOptions() | 16384); + //if (model_.fastNodeDepth()==-1) + model_.setFastNodeDepth(-2); // Use Cplex at root + } + int hOp2 = parameters_[whichParam(CBC_PARAM_INT_HOPTIONS, parameters_)].intValue() / 10000; + if (hOp2 % 10) { + model_.setSpecialOptions(model_.specialOptions() | 16384); + if (model_.fastNodeDepth() == -1) + model_.setFastNodeDepth(-2); // Use Cplex at root + } + int multipleRoot = parameters_[whichParam(CBC_PARAM_INT_MULTIPLEROOTS, parameters_)].intValue(); + model_.setMultipleRootTries(multipleRoot); + int specialOptions = parameters_[whichParam(CBC_PARAM_INT_STRONG_STRATEGY, parameters_)].intValue(); + if (specialOptions >= 0) + model_.setStrongStrategy(specialOptions); + if (!pumpChanged) { + // Make more lightweight + for (int iHeur = 0; iHeur < model_.numberHeuristics(); iHeur++) { + CbcHeuristic *heuristic = model_.heuristic(iHeur); + CbcHeuristicFPump *pump = dynamic_cast< CbcHeuristicFPump * >(heuristic); + if (pump) { + CbcHeuristicFPump heuristic4(model_); + heuristic4.setFractionSmall(0.5); + heuristic4.setMaximumPasses(5); + heuristic4.setFeasibilityPumpOptions(30); + heuristic4.setWhen(13); + heuristic4.setHeuristicName("feasibility pump"); + //CbcHeuristicFPump & pump2 = pump; + *pump = heuristic4; + } + } + } +#ifndef CBC_OTHER_SOLVER + { + OsiClpSolverInterface *solver = dynamic_cast< OsiClpSolverInterface * >(model_.solver()); + ClpSimplex *simplex = solver->getModelPtr(); + // if wanted go back to old printing method + double value = simplex->getMinIntervalProgressUpdate(); + if (value<=0.0) { + model_.setSecsPrintFrequency(-1.0); + if (value<0.0) { + model_.setPrintFrequency(static_cast(-value)); + } + } else { + model_.setSecsPrintFrequency(value); + } + } +#endif + int returnCode = CbcClpUnitTest(model_, dirMiplib, extra2, stuff,argc,argv,callBack,parameterData); + babModel_ = NULL; + return returnCode; + } else { + abort(); // can't get here + //strengthenedModel = babModel_->strengthenedModel(); + } + currentBranchModel = NULL; +#ifndef CBC_OTHER_SOLVER + osiclp = dynamic_cast< OsiClpSolverInterface * >(babModel_->solver()); + if (debugFile == "createAfterPre" && babModel_->bestSolution()) { + lpSolver = osiclp->getModelPtr(); + //move best solution (should be there -- but ..) + int n = lpSolver->getNumCols(); + memcpy(lpSolver->primalColumnSolution(), babModel_->bestSolution(), n * sizeof(double)); + saveSolution(osiclp->getModelPtr(), "debug.file"); + } +#endif + statistics_cut_time = 0.0; + if (!noPrinting_) { + // Print more statistics + sprintf(generalPrint, "Cuts at root node changed objective from %g to %g", + babModel_->getContinuousObjective(), babModel_->rootObjectiveAfterCuts()); + generalMessageHandler->message(CLP_GENERAL, generalMessages) + << generalPrint + << CoinMessageEol; + + numberGenerators = babModel_->numberCutGenerators(); + // can get here twice! + if (statistics_number_cuts != NULL) + delete[] statistics_number_cuts; + statistics_number_cuts = new int[numberGenerators]; + + if (statistics_name_generators != NULL) + delete[] statistics_name_generators; + statistics_name_generators = new const char *[numberGenerators]; + + statistics_number_generators = numberGenerators; + + char timing[30]; + for (iGenerator = 0; iGenerator < numberGenerators; iGenerator++) { + CbcCutGenerator *generator = babModel_->cutGenerator(iGenerator); + statistics_name_generators[iGenerator] = generator->cutGeneratorName(); + statistics_number_cuts[iGenerator] = generator->numberCutsInTotal(); + sprintf(generalPrint, "%s was tried %d times and created %d cuts of which %d were active after adding rounds of cuts", + generator->cutGeneratorName(), + generator->numberTimesEntered(), + generator->numberCutsInTotal() + generator->numberColumnCuts(), + generator->numberCutsActive()); + if (generator->timing()) { + sprintf(timing, " (%.3f seconds)", generator->timeInCutGenerator()); + strcat(generalPrint, timing); + statistics_cut_time += generator->timeInCutGenerator(); + } + CglStored *stored = dynamic_cast< CglStored * >(generator->generator()); + if (stored && !generator->numberCutsInTotal()) + continue; +#ifndef CLP_INVESTIGATE + CglImplication *implication = dynamic_cast< CglImplication * >(generator->generator()); + if (implication && !generator->numberCutsInTotal()) + continue; +#endif + generalMessageHandler->message(CLP_GENERAL, generalMessages) + << generalPrint + << CoinMessageEol; + } +#ifdef COIN_DEVELOP + printf("%d solutions found by heuristics\n", + babModel_->getNumberHeuristicSolutions()); + // Not really generator but I am feeling lazy + for (iGenerator = 0; iGenerator < babModel_->numberHeuristics(); iGenerator++) { + CbcHeuristic *heuristic = babModel_->heuristic(iGenerator); + if (heuristic->numRuns()) { + // Need to bring others inline + sprintf(generalPrint, "%s was tried %d times out of %d and created %d solutions\n", + heuristic->heuristicName(), + heuristic->numRuns(), + heuristic->numCouldRun(), + heuristic->numberSolutionsFound()); + generalMessageHandler->message(CLP_GENERAL, generalMessages) + << generalPrint + << CoinMessageEol; + } + } +#endif + } + // adjust time to allow for children on some systems + time2 = CoinCpuTime() + CoinCpuTimeJustChildren(); + totalTime += time2 - time1; + // For best solution + double *bestSolution = NULL; + // Say in integer + if (babModel_->status()) { + // treat as stopped + integerStatus = 3; + } else { + if (babModel_->isProvenOptimal()) { + integerStatus = 0; + } else if (!babModel_->bestSolution()) { + // infeasible + integerStatus = 6; + delete saveSolver; + saveSolver = NULL; + } + } + if (babModel_->getMinimizationObjValue() < 1.0e50 && type == CBC_PARAM_ACTION_BAB) { + // post process + int n; + if (preProcess) { + n = saveSolver->getNumCols(); + bestSolution = new double[n]; +#ifndef CBC_OTHER_SOLVER + OsiClpSolverInterface *clpSolver = dynamic_cast< OsiClpSolverInterface * >(babModel_->solver()); +#else + OsiCpxSolverInterface *clpSolver = dynamic_cast< OsiCpxSolverInterface * >(babModel_->solver()); +#endif + // Save bounds on processed model + const int *originalColumns = process.originalColumns(); + int numberColumns2 = clpSolver->getNumCols(); + double *lower2 = new double[n]; + double *upper2 = new double[n]; + for (int i = 0; i < n; i++) { + lower2[i] = COIN_DBL_MAX; + upper2[i] = -COIN_DBL_MAX; + } + const double *columnLower = clpSolver->getColLower(); + const double *columnUpper = clpSolver->getColUpper(); + for (int i = 0; i < numberColumns2; i++) { + int jColumn = originalColumns[i]; + if (jColumn < n) { + lower2[jColumn] = columnLower[i]; + upper2[jColumn] = columnUpper[i]; + } + } +#ifndef CBC_OTHER_SOLVER + ClpSimplex *lpSolver = clpSolver->getModelPtr(); + lpSolver->setSpecialOptions(lpSolver->specialOptions() | IN_BRANCH_AND_BOUND); // say is Cbc (and in branch and bound) +#endif + // put back any saved solutions + putBackOtherSolutions(babModel_, &model_, &process); + setPreProcessingMode(babModel_->solver(),2); + process.postProcess(*babModel_->solver()); + setPreProcessingMode(saveSolver,0); +#ifdef COIN_DEVELOP + if (model_.bestSolution() && fabs(model_.getMinimizationObjValue() - babModel_->getMinimizationObjValue()) < 1.0e-8) { + const double *b1 = model_.bestSolution(); + const double *b2 = saveSolver->getColSolution(); + const double *columnLower = saveSolver->getColLower(); + const double *columnUpper = saveSolver->getColUpper(); + for (int i = 0; i < n; i++) { + if (fabs(b1[i] - b2[i]) > 1.0e-7) { + printf("%d %g %g %g %g\n", i, b1[i], b2[i], + columnLower[i], columnUpper[i]); + } + } + } +#endif + bool tightenB = false; + { + int n = babModel_->numberObjects(); + for (int i = 0; i < n; i++) { + const OsiObject *obj = babModel_->object(i); + if (!dynamic_cast< const CbcSimpleInteger * >(obj)) { + tightenB = true; + break; + } + } + } + // Solution now back in saveSolver + // Double check bounds + columnLower = saveSolver->getColLower(); + columnUpper = saveSolver->getColUpper(); + if ((process.options()&128)!=0) + tightenB = false; + int numberChanged = 0; + if ((process.options()&256)==0) { + for (int i = 0; i < n; i++) { + if (!saveSolver->isInteger(i) && !tightenB) + continue; + if (lower2[i] != COIN_DBL_MAX) { + if (lower2[i] != columnLower[i] || upper2[i] != columnUpper[i]) { + if (lower2[i] < columnLower[i] || upper2[i] > columnUpper[i]) { +#ifdef COIN_DEVELOP + printf("odd bounds tighter"); + printf("%d bab bounds %g %g now %g %g\n", + i, lower2[i], upper2[i], columnLower[i], + columnUpper[i]); +#endif + } else { +#ifdef COIN_DEVELOP + printf("%d bab bounds %g %g now %g %g\n", + i, lower2[i], upper2[i], columnLower[i], + columnUpper[i]); +#endif + numberChanged++; + saveSolver->setColLower(i, lower2[i]); + saveSolver->setColUpper(i, upper2[i]); + } + } + } + } +#ifdef JJF_ZERO + // See if sos so we can fix + OsiClpSolverInterface *osiclp = dynamic_cast< OsiClpSolverInterface * >(saveSolver); + if (osiclp && osiclp->numberSOS()) { + // SOS + numberSOS = osiclp->numberSOS(); + const CoinSet *setInfo = osiclp->setInfo(); + int i; + for (i = 0; i < numberSOS; i++) { + int type = setInfo[i].setType(); + int n = setInfo[i].numberEntries(); + const int *which = setInfo[i].which(); + int first = -1; + int last = -1; + for (int j = 0; j < n; j++) { + int iColumn = which[j]; + if (fabs(solution[iColumn]) > 1.0e-7) { + last = j; + if (first < 0) + first = j; + } + } + assert(last - first < type); + for (int j = 0; j < n; j++) { + if (j < first || j > last) { + int iColumn = which[j]; + saveSolver->setColLower(iColumn, 0.0); + saveSolver->setColUpper(iColumn, 0.0); + } + } + } + } +#endif + } + delete[] lower2; + delete[] upper2; + if (numberChanged) { + sprintf(generalPrint, "%d bounds tightened after postprocessing\n", + numberChanged); + generalMessageHandler->message(CLP_GENERAL, generalMessages) + << generalPrint + << CoinMessageEol; + } + //saveSolver->resolve(); + if (true /*!saveSolver->isProvenOptimal()*/) { + // try all slack + CoinWarmStartBasis *basis = dynamic_cast< CoinWarmStartBasis * >(babModel_->solver()->getEmptyWarmStart()); + saveSolver->setWarmStart(basis); + delete basis; + saveSolver->initialSolve(); +#ifdef COIN_DEVELOP + saveSolver->writeMps("inf2"); +#endif + OsiClpSolverInterface *osiclp = dynamic_cast< OsiClpSolverInterface * >(saveSolver); + if (osiclp) + osiclp->getModelPtr()->checkUnscaledSolution(); + } + + //assert(saveSolver->isProvenOptimal()); +#ifndef CBC_OTHER_SOLVER + // and original solver + originalSolver->setDblParam(OsiDualObjectiveLimit, COIN_DBL_MAX); + assert(n >= originalSolver->getNumCols()); + n = originalSolver->getNumCols(); + originalSolver->setColLower(saveSolver->getColLower()); + originalSolver->setColUpper(saveSolver->getColUpper()); + // basis + CoinWarmStartBasis *basis = dynamic_cast< CoinWarmStartBasis * >(babModel_->solver()->getWarmStart()); + originalSolver->setBasis(*basis); + delete basis; + originalSolver->resolve(); + if (!originalSolver->isProvenOptimal()) { + // try all slack + CoinWarmStartBasis *basis = dynamic_cast< CoinWarmStartBasis * >(babModel_->solver()->getEmptyWarmStart()); + originalSolver->setBasis(*basis); + delete basis; + originalSolver->initialSolve(); + OsiClpSolverInterface *osiclp = dynamic_cast< OsiClpSolverInterface * >(originalSolver); + if (osiclp) + osiclp->getModelPtr()->checkUnscaledSolution(); + } + //assert(originalSolver->isProvenOptimal()); +#endif + babModel_->assignSolver(saveSolver); + memcpy(bestSolution, babModel_->solver()->getColSolution(), n * sizeof(double)); + } else { + n = babModel_->solver()->getNumCols(); + bestSolution = new double[n]; + memcpy(bestSolution, babModel_->solver()->getColSolution(), n * sizeof(double)); + } + if (returnMode == 1 && model_.numberSavedSolutions() < 2) { + model_.deleteSolutions(); + model_.setBestSolution(bestSolution, n, babModel_->getMinimizationObjValue()); + } + babModel_->deleteSolutions(); + babModel_->setBestSolution(bestSolution, n, babModel_->getMinimizationObjValue()); +#ifndef CBC_OTHER_SOLVER + // and put back in very original solver + { + ClpSimplex *original = originalSolver->getModelPtr(); + double *lower = original->columnLower(); + double *upper = original->columnUpper(); + double *solution = original->primalColumnSolution(); + int n = original->numberColumns(); + //assert (!n||n==babModel_->solver()->getNumCols()); + for (int i = 0; i < n; i++) { + solution[i] = bestSolution[i]; + if (originalSolver->isInteger(i)) { + lower[i] = solution[i]; + upper[i] = solution[i]; + } + } + // basis + CoinWarmStartBasis *basis = dynamic_cast< CoinWarmStartBasis * >(babModel_->solver()->getWarmStart()); + originalSolver->setBasis(*basis); + delete basis; + originalSolver->setDblParam(OsiDualObjectiveLimit, COIN_DBL_MAX); +#ifdef COIN_HAS_LINK + if (originalSolver->getMatrixByCol()) + originalSolver->setHintParam(OsiDoPresolveInResolve, true, OsiHintTry); +#else + originalSolver->setHintParam(OsiDoPresolveInResolve, true, OsiHintTry); +#endif + originalSolver->resolve(); + if (!originalSolver->isProvenOptimal()) { + // try all slack + CoinWarmStartBasis *basis = dynamic_cast< CoinWarmStartBasis * >(babModel_->solver()->getEmptyWarmStart()); + originalSolver->setBasis(*basis); + delete basis; + originalSolver->initialSolve(); + OsiClpSolverInterface *osiclp = dynamic_cast< OsiClpSolverInterface * >(originalSolver); + if (osiclp) + osiclp->getModelPtr()->checkUnscaledSolution(); +#ifdef CLP_INVESTIGATE + if (!originalSolver->isProvenOptimal()) { + if (saveSolver) { + printf("saveSolver and originalSolver matrices saved\n"); + saveSolver->writeMps("infA"); + } else { + printf("originalSolver matrix saved\n"); + originalSolver->writeMps("infB"); + } + } +#endif + } + //assert(originalSolver->isProvenOptimal()); + } +#endif + checkSOS(babModel_, babModel_->solver()); + } else if (model_.bestSolution() && type == CBC_PARAM_ACTION_BAB && model_.getMinimizationObjValue() < 1.0e50 && preProcess) { + sprintf(generalPrint, "Restoring heuristic best solution of %g", model_.getMinimizationObjValue()); + generalMessageHandler->message(CLP_GENERAL, generalMessages) + << generalPrint + << CoinMessageEol; + int n = saveSolver->getNumCols(); + bestSolution = new double[n]; + // Put solution now back in saveSolver + saveSolver->setColSolution(model_.bestSolution()); + babModel_->assignSolver(saveSolver); + saveSolver = NULL; + babModel_->setMinimizationObjValue(model_.getMinimizationObjValue()); + memcpy(bestSolution, babModel_->solver()->getColSolution(), n * sizeof(double)); +#ifndef CBC_OTHER_SOLVER + // and put back in very original solver + { + ClpSimplex *original = originalSolver->getModelPtr(); + double *lower = original->columnLower(); + double *upper = original->columnUpper(); + double *solution = original->primalColumnSolution(); + int n = original->numberColumns(); + //assert (!n||n==babModel_->solver()->getNumCols()); + for (int i = 0; i < n; i++) { + solution[i] = bestSolution[i]; + if (originalSolver->isInteger(i)) { + lower[i] = solution[i]; + upper[i] = solution[i]; + } + } + // basis + CoinWarmStartBasis *basis = dynamic_cast< CoinWarmStartBasis * >(babModel_->solver()->getWarmStart()); + originalSolver->setBasis(*basis); + delete basis; + } +#endif + } +#ifndef CBC_OTHER_SOLVER + //if (type==CBC_PARAM_ACTION_STRENGTHEN&&strengthenedModel) + //clpSolver = dynamic_cast< OsiClpSolverInterface*> (strengthenedModel); + else if (statusUserFunction_[0]) + clpSolver = dynamic_cast< OsiClpSolverInterface * >(babModel_->solver()); + lpSolver = clpSolver->getModelPtr(); + if (numberChanged) { + for (int i = 0; i < numberChanged; i++) { + int iColumn = changed[i]; + clpSolver->setContinuous(iColumn); + } + delete[] changed; + } +#endif + if (type == CBC_PARAM_ACTION_BAB) { +#ifndef CBC_OTHER_SOLVER + //move best solution (should be there -- but ..) + int n = lpSolver->getNumCols(); + if (bestSolution) { + memcpy(lpSolver->primalColumnSolution(), bestSolution, n * sizeof(double)); + // now see what that does to row solution + int numberRows = lpSolver->numberRows(); + double *rowSolution = lpSolver->primalRowSolution(); + memset(rowSolution, 0, numberRows * sizeof(double)); + lpSolver->clpMatrix()->times(1.0, bestSolution, rowSolution); + lpSolver->setObjectiveValue(babModel_->getObjValue()); + } + if (debugFile == "create" && bestSolution) { + saveSolution(lpSolver, "debug.file"); + } +#else + if (bestSolution) { + model_.solver()->setColSolution(bestSolution); + } +#endif + delete saveSolver; + delete[] bestSolution; + std::string statusName[] = { "", "Stopped on ", "Run abandoned", "", "", "User ctrl-c" }; + std::string minor[] = { "Optimal solution found", "Linear relaxation infeasible", "Optimal solution found (within gap tolerance)", "node limit", "time limit", "user ctrl-c", "solution limit", "Linear relaxation unbounded", "Problem proven infeasible" }; + int iStat = babModel_->status(); + int iStat2 = babModel_->secondaryStatus(); + if (!iStat && !iStat2 && !bestSolution) + iStat2 = 8; + if (!iStat && iStat2 == 1 && bestSolution) + iStat2 = 0; // solution and search completed + statistics_seconds = time2 - time1; + statistics_sys_seconds = CoinSysTime(); + statistics_elapsed_seconds = CoinWallclockTime(); + statistics_obj = babModel_->getObjValue(); + statistics_continuous = babModel_->getContinuousObjective(); + statistics_tighter = babModel_->rootObjectiveAfterCuts(); + statistics_nodes = babModel_->getNodeCount(); + statistics_iterations = babModel_->getIterationCount(); + ; + statistics_result = statusName[iStat]; + ; + if (!noPrinting_) { + sprintf(generalPrint, "\nResult - %s%s\n", + statusName[iStat].c_str(), + minor[iStat2].c_str()); + generalMessageHandler->message(CLP_GENERAL, generalMessages) + << generalPrint + << CoinMessageEol; + if (babModel_->bestSolution()) { + sprintf(generalPrint, + "Objective value: %.8f\n", + babModel_->getObjValue()); + } else { + sprintf(generalPrint, + "No feasible solution found\n"); + } + if (iStat2 >= 2 && iStat2 <= 6) { + bool minimizing = babModel_->solver()->getObjSense() > 0.0; + sprintf(generalPrint + strlen(generalPrint), + "%s bound: %.3f\n", + minimizing ? "Lower" : "Upper", + babModel_->getBestPossibleObjValue()); + if (babModel_->bestSolution()) { + sprintf(generalPrint + strlen(generalPrint), + "Gap: %.2f\n", + (babModel_->getObjValue() - babModel_->getBestPossibleObjValue()) / fabs(babModel_->getBestPossibleObjValue())); + } + } + sprintf(generalPrint + strlen(generalPrint), + "Enumerated nodes: %d\n", + babModel_->getNodeCount()); + sprintf(generalPrint + strlen(generalPrint), + "Total iterations: %d\n", + babModel_->getIterationCount()); +#if CBC_QUIET == 0 + sprintf(generalPrint + strlen(generalPrint), + "Time (CPU seconds): %.2f\n", + CoinCpuTime() - time1); + sprintf(generalPrint + strlen(generalPrint), + "Time (Wallclock seconds): %.2f\n", + CoinGetTimeOfDay() - time1Elapsed); +#endif + generalMessageHandler->message(CLP_GENERAL, generalMessages) + << generalPrint + << CoinMessageEol; + } + int returnCode = 0; + if (callBack != NULL) + returnCode = callBack(babModel_, 5); + if (returnCode) { + // exit if user wants + model_.moveInfo(*babModel_); + delete babModel_; + babModel_ = NULL; + return returnCode; + } + if (statusUserFunction_[0]) { + clpSolver = dynamic_cast< OsiClpSolverInterface * >(babModel_->solver()); + lpSolver = clpSolver->getModelPtr(); + double value = babModel_->getObjValue() * lpSolver->getObjSense(); + char buf[300]; + int pos = 0; + if (iStat == 0) { + if (babModel_->getObjValue() < 1.0e40) { + pos += sprintf(buf + pos, "optimal,"); + } else { + // infeasible + iStat = 1; + pos += sprintf(buf + pos, "infeasible,"); + } + } else if (iStat == 1) { + if (iStat2 != 6) + iStat = 3; + else + iStat = 4; + pos += sprintf(buf + pos, "stopped on %s,", minor[iStat2].c_str()); + } else if (iStat == 2) { + iStat = 7; + pos += sprintf(buf + pos, "stopped on difficulties,"); + } else if (iStat == 5) { + iStat = 3; + pos += sprintf(buf + pos, "stopped on ctrl-c,"); + } else { + pos += sprintf(buf + pos, "status unknown,"); + iStat = 6; + } + info.problemStatus = iStat; + info.objValue = value; + if (babModel_->getObjValue() < 1.0e40) { + int precision = ampl_obj_prec(); + if (precision > 0) + pos += sprintf(buf + pos, " objective %.*g", precision, + value); + else + pos += sprintf(buf + pos, " objective %g", value); + } + sprintf(buf + pos, "\n%d nodes, %d iterations, %g seconds", + babModel_->getNodeCount(), + babModel_->getIterationCount(), + totalTime); + if (bestSolution) { + free(info.primalSolution); + if (!numberKnapsack) { + info.primalSolution = (double *)malloc(n * sizeof(double)); + CoinCopyN(lpSolver->primalColumnSolution(), n, info.primalSolution); + int numberRows = lpSolver->numberRows(); + free(info.dualSolution); + info.dualSolution = (double *)malloc(numberRows * sizeof(double)); + CoinCopyN(lpSolver->dualRowSolution(), numberRows, info.dualSolution); + } else { + // expanded knapsack + info.dualSolution = NULL; + int numberColumns = saveCoinModel.numberColumns(); + info.primalSolution = (double *)malloc(numberColumns * sizeof(double)); + // Fills in original solution (coinModel length) + afterKnapsack(saveTightenedModel, whichColumn, knapsackStart, + knapsackRow, numberKnapsack, + lpSolver->primalColumnSolution(), info.primalSolution, 1); + } + } else { + info.primalSolution = NULL; + info.dualSolution = NULL; + } + // put buffer into info + strcpy(info.buffer, buf); + } + } else { + sprintf(generalPrint, "Model strengthened - now has %d rows", + clpSolver->getNumRows()); + printGeneralMessage(model_, generalPrint); + } + time1 = time2; + if (statusUserFunction_[0]) { + // keep if going to be destroyed + OsiSolverInterface *solver = babModel_->solver(); + OsiClpSolverInterface *clpSolver = dynamic_cast< OsiClpSolverInterface * >(solver); + ClpSimplex *lpSolver2 = clpSolver->getModelPtr(); + if (lpSolver == lpSolver2) + babModel_->setModelOwnsSolver(false); + } + //delete babModel_; + //babModel_=NULL; + } else { + sprintf(generalPrint, "** Current model not valid"); + printGeneralMessage(model_, generalPrint); + } + break; + case CLP_PARAM_ACTION_IMPORT: { + if (!statusUserFunction_[0]) { + free(priorities); + priorities = NULL; + free(branchDirection); + branchDirection = NULL; + free(pseudoDown); + pseudoDown = NULL; + free(pseudoUp); + pseudoUp = NULL; + free(solutionIn); + solutionIn = NULL; + free(prioritiesIn); + prioritiesIn = NULL; + free(sosStart); + sosStart = NULL; + free(sosIndices); + sosIndices = NULL; + free(sosType); + sosType = NULL; + free(sosReference); + sosReference = NULL; + free(cut); + cut = NULL; + free(sosPriority); + sosPriority = NULL; + } + //delete babModel_; + //babModel_=NULL; + // get next field + field = CoinReadGetString(argc, argv); + if (field == "$") { + field = parameters_[iParam].stringValue(); + } else if (field == "EOL") { + parameters_[iParam].printString(); + break; + } else { + parameters_[iParam].setStringValue(field); + } + std::string fileName; + bool canOpen = false; + // See if gmpl file + int gmpl = 0; + std::string gmplData; + if (field == "-" || field == "stdin") { + // stdin + canOpen = true; + fileName = "-"; + } else if (field == "-lp" || field == "stdin_lp") { + // stdin + canOpen = true; + fileName = "-"; + gmpl = -1; //.lp format + } else { + // See if .lp + { + const char *c_name = field.c_str(); + size_t length = strlen(c_name); + if ((length > 3 && !strncmp(c_name + length - 3, ".lp", 3)) || (length > 6 && !strncmp(c_name + length - 6, ".lp.gz", 6)) || (length > 7 && !strncmp(c_name + length - 7, ".lp.bz2", 7))) + gmpl = -1; // .lp + } + bool absolutePath; + if (dirsep == '/') { + // non Windows (or cygwin) + absolutePath = (field[0] == '/'); + } else { + //Windows (non cycgwin) + absolutePath = (field[0] == '\\'); + // but allow for : + if (strchr(field.c_str(), ':')) + absolutePath = true; + } + if (absolutePath) { + fileName = field; + size_t length = field.size(); + size_t percent = field.find('%'); + if (percent < length && percent > 0) { + gmpl = 1; + fileName = field.substr(0, percent); + gmplData = field.substr(percent + 1); + if (percent < length - 1) + gmpl = 2; // two files + printf("GMPL model file %s and data file %s\n", + fileName.c_str(), gmplData.c_str()); + } + } else if (field[0] == '~') { + char *environVar = getenv("HOME"); + if (environVar) { + std::string home(environVar); + field = field.erase(0, 1); + fileName = home + field; + } else { + fileName = field; + } + } else { + fileName = directory + field; + // See if gmpl (model & data) - or even lp file + size_t length = field.size(); + size_t percent = field.find('%'); + if (percent < length && percent > 0) { + gmpl = 1; + fileName = directory + field.substr(0, percent); + gmplData = directory + field.substr(percent + 1); + if (percent < length - 1) + gmpl = 2; // two files + printf("GMPL model file %s and data file %s\n", + fileName.c_str(), gmplData.c_str()); + } + } + std::string name = fileName; + if (fileCoinReadable(name)) { + // can open - lets go for it + canOpen = true; + if (gmpl == 2) { + FILE *fp; + fp = fopen(gmplData.c_str(), "r"); + if (fp) { + fclose(fp); + } else { + canOpen = false; + sprintf(generalPrint, "Unable to open file %s", gmplData.c_str()); + printGeneralMessage(model_, generalPrint); + } + } + } else { + sprintf(generalPrint, "Unable to open file %s", fileName.c_str()); + printGeneralMessage(model_, generalPrint); + } + } + if (canOpen) { + int status; + numberLotSizing = 0; + delete[] lotsize; +#ifndef CBC_OTHER_SOLVER + ClpSimplex *lpSolver = clpSolver->getModelPtr(); + if (!gmpl) { + status = clpSolver->readMps(fileName.c_str(), + keepImportNames != 0, + allowImportErrors != 0); + } else if (gmpl > 0) { +#ifdef COINUTILS_HAS_GLPK + status = lpSolver->readGMPL(fileName.c_str(), + (gmpl == 2) ? gmplData.c_str() : NULL, + keepImportNames != 0); +#else + std::cout << "Cbc was not built with GMPL support. Exiting.\n" + << std::endl; + abort(); +#endif + } else { +#ifdef KILL_ZERO_READLP + status = clpSolver->readLp(fileName.c_str(), lpSolver->getSmallElementValue()); +#else + status = clpSolver->readLp(fileName.c_str(), 1.0e-12); +#endif + } +#else + status = clpSolver->readMps(fileName.c_str(), ""); +#endif + if (!status || (status > 0 && allowImportErrors)) { +#ifndef CBC_OTHER_SOLVER + if (keepImportNames) { + lengthName = lpSolver->lengthNames(); + rowNames = *(lpSolver->rowNames()); + columnNames = *(lpSolver->columnNames()); + } else { + lengthName = 0; + } + // really just for testing + double objScale = parameters_[whichParam(CLP_PARAM_DBL_OBJSCALE2, parameters_)].doubleValue(); + if (objScale != 1.0) { + int iColumn; + int numberColumns = lpSolver->numberColumns(); + double *dualColumnSolution = lpSolver->dualColumnSolution(); + ClpObjective *obj = lpSolver->objectiveAsObject(); + assert(dynamic_cast< ClpLinearObjective * >(obj)); + double offset; + double *objective = obj->gradient(NULL, NULL, offset, true); + for (iColumn = 0; iColumn < numberColumns; iColumn++) { + dualColumnSolution[iColumn] *= objScale; + objective[iColumn] *= objScale; + } + int iRow; + int numberRows = lpSolver->numberRows(); + double *dualRowSolution = lpSolver->dualRowSolution(); + for (iRow = 0; iRow < numberRows; iRow++) + dualRowSolution[iRow] *= objScale; + lpSolver->setObjectiveOffset(objScale * lpSolver->objectiveOffset()); + } + goodModel = true; + // sets to all slack (not necessary?) + lpSolver->createStatus(); + // See if sos + if (clpSolver->numberSOS()) { + // SOS + numberSOS = clpSolver->numberSOS(); + const CoinSet *setInfo = clpSolver->setInfo(); + sosStart = reinterpret_cast< int * >(malloc((numberSOS + 1) * sizeof(int))); + sosType = reinterpret_cast< char * >(malloc(numberSOS * sizeof(char))); + const double *lower = clpSolver->getColLower(); + const double *upper = clpSolver->getColUpper(); + int i; + int nTotal = 0; + sosStart[0] = 0; + for (i = 0; i < numberSOS; i++) { + int type = setInfo[i].setType(); + int n = setInfo[i].numberEntries(); + sosType[i] = static_cast< char >(type); + nTotal += n; + sosStart[i + 1] = nTotal; + } + sosIndices = reinterpret_cast< int * >(malloc(nTotal * sizeof(int))); + sosReference = reinterpret_cast< double * >(malloc(nTotal * sizeof(double))); + for (i = 0; i < numberSOS; i++) { + int n = setInfo[i].numberEntries(); + const int *which = setInfo[i].which(); + const double *weights = setInfo[i].weights(); + int base = sosStart[i]; + for (int j = 0; j < n; j++) { + int k = which[j]; + // don't allow free + if (upper[k] > 1.0e15) + clpSolver->setColUpper(k, 1.0e15); + if (lower[k] < -1.0e15) + clpSolver->setColLower(k, -1.0e15); + sosIndices[j + base] = k; + sosReference[j + base] = weights ? weights[j] : static_cast< double >(j); + } + } + } + // make sure integer + // also deal with semi-continuous + int numberColumns = lpSolver->numberColumns(); + int i; + for (i = 0; i < numberColumns; i++) { + if (clpSolver->integerType(i) > 2) + break; + if (lpSolver->isInteger(i)) + clpSolver->setInteger(i); + } + if (i < numberColumns) { + // semi-continuous + clpSolver->setSpecialOptions(clpSolver->specialOptions() | 8388608); + int iStart = i; + for (i = iStart; i < numberColumns; i++) { + if (clpSolver->integerType(i) > 2) + numberLotSizing++; + } + lotsize = new lotStruct[numberLotSizing]; + numberLotSizing = 0; + const double *lower = clpSolver->getColLower(); + const double *upper = clpSolver->getColUpper(); + for (i = iStart; i < numberColumns; i++) { + if (clpSolver->integerType(i) > 2) { + int iType = clpSolver->integerType(i) - 3; + if (!iType) + clpSolver->setContinuous(i); + else + clpSolver->setInteger(i); + lotsize[numberLotSizing].column = i; + lotsize[numberLotSizing].high = upper[i]; + if (lower[i]) { + lotsize[numberLotSizing++].low = lower[i]; + clpSolver->setColLower(i, 0.0); + } else { + lotsize[numberLotSizing++].low = 1.0; + } + } + } + } +#else + lengthName = 0; + goodModel = true; +#endif + time2 = CoinCpuTime(); + totalTime += time2 - time1; + time1 = time2; + // Go to canned file if just input file + if (getCbcOrClpReadMode() == 2 && argc == 2) { + // only if ends .mps + char *find = const_cast< char * >(strstr(fileName.c_str(), ".mps")); + if (find && find[4] == '\0') { + find[1] = 'p'; + find[2] = 'a'; + find[3] = 'r'; + FILE *fp = fopen(fileName.c_str(), "r"); + if (fp) { + setCbcOrClpReadCommand(fp); // Read from that file + setCbcOrClpReadMode(-1); + } + } + } + } else { + // errors + sprintf(generalPrint, "There were %d errors on input", status); + printGeneralMessage(model_, generalPrint); + } + } + } break; + case CLP_PARAM_ACTION_MODELIN: +#ifndef CBC_OTHER_SOLVER +#ifdef COIN_HAS_LINK + { + // get next field + field = CoinReadGetString(argc, argv); + if (field == "$") { + field = parameters_[iParam].stringValue(); + } else if (field == "EOL") { + parameters_[iParam].printString(); + break; + } else { + parameters_[iParam].setStringValue(field); + } + std::string fileName; + bool canOpen = false; + if (field == "-") { + // stdin + canOpen = true; + fileName = "-"; + } else { + bool absolutePath; + if (dirsep == '/') { + // non Windows (or cygwin) + absolutePath = (field[0] == '/'); + } else { + //Windows (non cycgwin) + absolutePath = (field[0] == '\\'); + // but allow for : + if (strchr(field.c_str(), ':')) + absolutePath = true; + } + if (absolutePath) { + fileName = field; + } else if (field[0] == '~') { + char *environVar = getenv("HOME"); + if (environVar) { + std::string home(environVar); + field = field.erase(0, 1); + fileName = home + field; + } else { + fileName = field; + } + } else { + fileName = directory + field; + } + FILE *fp = fopen(fileName.c_str(), "r"); + if (fp) { + // can open - lets go for it + fclose(fp); + canOpen = true; + } else { + sprintf(generalPrint, "Unable to open file %s", fileName.c_str()); + printGeneralMessage(model_, generalPrint); + } + } + if (canOpen) { + CoinModel coinModel(fileName.c_str(), 2); + // load from coin model + OsiSolverLink solver1; + OsiSolverInterface *solver2 = solver1.clone(); + model_.assignSolver(solver2, false); + OsiSolverLink *si = dynamic_cast< OsiSolverLink * >(model_.solver()); + assert(si != NULL); + si->setDefaultMeshSize(0.001); + // need some relative granularity + si->setDefaultBound(100.0); + double dextra3 = parameters_[whichParam(CBC_PARAM_DBL_DEXTRA3, parameters_)].doubleValue(); + if (dextra3) + si->setDefaultMeshSize(dextra3); + si->setDefaultBound(100.0); + si->setIntegerPriority(1000); + si->setBiLinearPriority(10000); + CoinModel *model2 = &coinModel; + si->load(*model2); + // redo + solver = model_.solver(); + clpSolver = dynamic_cast< OsiClpSolverInterface * >(solver); + lpSolver = clpSolver->getModelPtr(); + clpSolver->messageHandler()->setLogLevel(0); + testOsiParameters = 0; + complicatedInteger = 2; + } + } +#endif +#endif + break; + case CLP_PARAM_ACTION_EXPORT: + if (goodModel) { + // get next field + field = CoinReadGetString(argc, argv); + if (field == "$") { + field = parameters_[iParam].stringValue(); + } else if (field == "EOL") { + parameters_[iParam].printString(); + break; + } else { + parameters_[iParam].setStringValue(field); + } + std::string fileName; + bool canOpen = false; + if (field[0] == '/' || field[0] == '\\') { + fileName = field; + } else if (field[0] == '~') { + char *environVar = getenv("HOME"); + if (environVar) { + std::string home(environVar); + field = field.erase(0, 1); + fileName = home + field; + } else { + fileName = field; + } + } else { + fileName = directory + field; + } + FILE *fp = fopen(fileName.c_str(), "w"); + if (fp) { + // can open - lets go for it + fclose(fp); + canOpen = true; + } else { + sprintf(generalPrint, "Unable to open file %s", fileName.c_str()); + printGeneralMessage(model_, generalPrint); + } + if (canOpen) { + // If presolve on then save presolved + bool deleteModel2 = false; + ClpSimplex *model2 = lpSolver; + if (dualize && dualize < 3) { + model2 = static_cast< ClpSimplexOther * >(model2)->dualOfModel(); + sprintf(generalPrint, "Dual of model has %d rows and %d columns", + model2->numberRows(), model2->numberColumns()); + generalMessageHandler->message(CLP_GENERAL, generalMessages) + << generalPrint + << CoinMessageEol; + model2->setOptimizationDirection(1.0); + } +#ifndef CBC_OTHER_SOLVER + if (info.numberSos && doSOS && statusUserFunction_[0]) { + // SOS + numberSOS = info.numberSos; + sosStart = info.sosStart; + sosIndices = info.sosIndices; + sosReference = info.sosReference; + clpSolver->setSOSData(numberSOS, info.sosType, sosStart, sosIndices, sosReference); + } + numberSOS = clpSolver->numberSOS(); + if (numberSOS || lotsize) + preSolve = false; +#endif + if (preSolve) { + ClpPresolve pinfo; + int presolveOptions2 = presolveOptions & ~0x40000000; + if ((presolveOptions2 & 0xffff) != 0) + pinfo.setPresolveActions(presolveOptions2); + if ((printOptions & 1) != 0) + pinfo.statistics(); + double presolveTolerance = parameters_[whichParam(CLP_PARAM_DBL_PRESOLVETOLERANCE, parameters_)].doubleValue(); + model2 = pinfo.presolvedModel(*lpSolver, presolveTolerance, + true, preSolve); + if (model2) { + printf("Saving presolved model on %s\n", + fileName.c_str()); + deleteModel2 = true; + } else { + printf("Presolved model looks infeasible - saving original on %s\n", + fileName.c_str()); + deleteModel2 = false; + model2 = lpSolver; + } + // see if extension lp + bool writeLp = false; + { + int lengthName = strlen(fileName.c_str()); + if (lengthName > 3 && !strcmp(fileName.c_str() + lengthName - 3, ".lp")) + writeLp = true; + } + if (!writeLp) { + model2->writeMps(fileName.c_str(), (outputFormat - 1) / 2, 1 + ((outputFormat - 1) & 1)); + } else { + FILE *fp = fopen(fileName.c_str(), "w"); + assert(fp); + OsiClpSolverInterface solver(model2); + solver.writeLp(fp, 1.0e-12); + fclose(fp); + } + if (deleteModel2) + delete model2; + } else { + printf("Saving model on %s\n", + fileName.c_str()); +#ifdef COIN_HAS_LINK + OsiSolverLink *linkSolver = dynamic_cast< OsiSolverLink * >(clpSolver); + if (!linkSolver || !linkSolver->quadraticModel()) { +#endif + // Convert names + int iRow; + int numberRows = model2->numberRows(); + int iColumn; + int numberColumns = model2->numberColumns(); + + char **rowNames = NULL; + char **columnNames = NULL; + if (model2->lengthNames()) { + rowNames = new char *[numberRows]; + for (iRow = 0; iRow < numberRows; iRow++) { + rowNames[iRow] = CoinStrdup(model2->rowName(iRow).c_str()); + } + + columnNames = new char *[numberColumns]; + for (iColumn = 0; iColumn < numberColumns; iColumn++) { + columnNames[iColumn] = CoinStrdup(model2->columnName(iColumn).c_str()); + } + } + // see if extension lp + bool writeLp = false; + { + int lengthName = strlen(fileName.c_str()); + if (lengthName > 3 && !strcmp(fileName.c_str() + lengthName - 3, ".lp")) + writeLp = true; + } + if (lotsize) { + for (int i = 0; i < numberLotSizing; i++) { + int iColumn = lotsize[i].column; + double low = lotsize[i].low; + if (low != 1.0) + clpSolver->setColLower(iColumn, low); + int type; + if (clpSolver->isInteger(iColumn)) + type = 4; + else + type = 3; + clpSolver->setColumnType(iColumn, type); + } + } + if (!writeLp) { + remove(fileName.c_str()); + //model_.addSOSEtcToSolver(); + clpSolver->writeMpsNative(fileName.c_str(), const_cast< const char ** >(rowNames), const_cast< const char ** >(columnNames), + (outputFormat - 1) / 2, 1 + ((outputFormat - 1) & 1)); + } else { + FILE *fp = fopen(fileName.c_str(), "w"); + assert(fp); + clpSolver->writeLp(fp, 1.0e-12); + } + if (rowNames) { + for (iRow = 0; iRow < numberRows; iRow++) { + free(rowNames[iRow]); + } + delete[] rowNames; + for (iColumn = 0; iColumn < numberColumns; iColumn++) { + free(columnNames[iColumn]); + } + delete[] columnNames; + } + if (lotsize) { + for (int i = 0; i < numberLotSizing; i++) { + int iColumn = lotsize[i].column; + int itype = clpSolver->integerType(iColumn); + clpSolver->setColLower(iColumn, 0.0); + if (itype == 3) + clpSolver->setContinuous(iColumn); + else + clpSolver->setInteger(iColumn); + } + } +#ifdef COIN_HAS_LINK + } else { + linkSolver->quadraticModel()->writeMps(fileName.c_str(), (outputFormat - 1) / 2, 1 + ((outputFormat - 1) & 1)); + } +#endif + } + time2 = CoinCpuTime(); + totalTime += time2 - time1; + time1 = time2; + } + } else { + sprintf(generalPrint, "** Current model not valid"); + printGeneralMessage(model_, generalPrint); + } + break; + case CLP_PARAM_ACTION_BASISIN: + if (goodModel) { + // get next field + field = CoinReadGetString(argc, argv); + if (field == "$") { + field = parameters_[iParam].stringValue(); + } else if (field == "EOL") { + parameters_[iParam].printString(); + break; + } else { + parameters_[iParam].setStringValue(field); + } + std::string fileName; + bool canOpen = false; + if (field == "-") { + // stdin + canOpen = true; + fileName = "-"; + } else { + if (field[0] == '/' || field[0] == '\\') { + fileName = field; + } else if (field[0] == '~') { + char *environVar = getenv("HOME"); + if (environVar) { + std::string home(environVar); + field = field.erase(0, 1); + fileName = home + field; + } else { + fileName = field; + } + } else { + fileName = directory + field; + } + FILE *fp = fopen(fileName.c_str(), "r"); + if (fp) { + // can open - lets go for it + fclose(fp); + canOpen = true; + } else { + sprintf(generalPrint, "Unable to open file %s", fileName.c_str()); + printGeneralMessage(model_, generalPrint); + } + } + if (canOpen) { +#ifndef CBC_OTHER_SOLVER + int values = lpSolver->readBasis(fileName.c_str()); + if (values == 0) + basisHasValues = -1; + else + basisHasValues = 1; + assert(lpSolver == clpSolver->getModelPtr()); + clpSolver->setWarmStart(NULL); +#endif + } + } else { + sprintf(generalPrint, "** Current model not valid"); + printGeneralMessage(model_, generalPrint); + } + break; + case CBC_PARAM_ACTION_PRIORITYIN: + if (goodModel) { + // get next field + field = CoinReadGetString(argc, argv); + if (field == "$") { + field = parameters_[iParam].stringValue(); + } else if (field == "EOL") { + parameters_[iParam].printString(); + break; + } else { + parameters_[iParam].setStringValue(field); + } + std::string fileName; + if (field[0] == '/' || field[0] == '\\') { + fileName = field; + } else if (field[0] == '~') { + char *environVar = getenv("HOME"); + if (environVar) { + std::string home(environVar); + field = field.erase(0, 1); + fileName = home + field; + } else { + fileName = field; + } + } else { + fileName = directory + field; + } + FILE *fp = fopen(fileName.c_str(), "r"); + if (fp) { + // can open - lets go for it + std::string headings[] = { "name", "number", "direction", "priority", "up", "down", + "solution", "priin" }; + int got[] = { -1, -1, -1, -1, -1, -1, -1, -1 }; + int order[8]; + bool useMasks = false; + if (strstr(fileName.c_str(), "mask_")) { + // look more closely + const char *name = fileName.c_str(); + int length = strlen(name); + for (int i = length - 1; i >= 0; i--) { + if (name[i] == dirsep) { + name += i + 1; + break; + } + } + useMasks = !strncmp(name, "mask_", 5); + } + assert(sizeof(got) == sizeof(order)); + int nAcross = 0; + char line[1000]; + int numberColumns = lpSolver->numberColumns(); + if (!fgets(line, 1000, fp)) { + std::cout << "Odd file " << fileName << std::endl; + } else { + char *pos = line; + char *put = line; + while (*pos >= ' ' && *pos != '\n') { + if (*pos != ' ' && *pos != '\t') { + *put = static_cast< char >(tolower(*pos)); + put++; + } + pos++; + } + *put = '\0'; + pos = line; + int i; + bool good = true; + while (pos) { + char *comma = strchr(pos, ','); + if (comma) + *comma = '\0'; + for (i = 0; i < static_cast< int >(sizeof(got) / sizeof(int)); i++) { + if (headings[i] == pos) { + if (got[i] < 0) { + order[nAcross] = i; + got[i] = nAcross++; + } else { + // duplicate + good = false; + } + break; + } + } + if (i == static_cast< int >(sizeof(got) / sizeof(int))) + good = false; + if (comma) { + *comma = ','; + pos = comma + 1; + } else { + break; + } + } + if (got[0] < 0 && got[1] < 0) + good = false; + if (got[0] >= 0 && got[1] >= 0) + good = false; + if (got[0] >= 0 && !lpSolver->lengthNames()) + good = false; + int numberFields = 99; + if (good && (strstr(fileName.c_str(), ".mst") || strstr(fileName.c_str(), ".MST") || strstr(fileName.c_str(), ".csv"))) { + numberFields = 0; + for (i = 2; i < static_cast< int >(sizeof(got) / sizeof(int)); i++) { + if (got[i] >= 0) + numberFields++; + } + if (!numberFields) { + // Like Cplex format + order[nAcross] = 6; + got[6] = nAcross++; + } + } + if (good) { + char **columnNames = new char *[numberColumns]; + //pseudoDown = NULL; + //pseudoUp = NULL; + //branchDirection = NULL; + //if (got[5]!=-1) + pseudoDown = reinterpret_cast< double * >(malloc(numberColumns * sizeof(double))); + //if (got[4]!=-1) + pseudoUp = reinterpret_cast< double * >(malloc(numberColumns * sizeof(double))); + //if (got[2]!=-1) + branchDirection = reinterpret_cast< int * >(malloc(numberColumns * sizeof(int))); + priorities = reinterpret_cast< int * >(malloc(numberColumns * sizeof(int))); + free(solutionIn); + solutionIn = NULL; + free(prioritiesIn); + prioritiesIn = NULL; + int iColumn; + if (got[6] >= 0) { + solutionIn = reinterpret_cast< double * >(malloc(numberColumns * sizeof(double))); + for (iColumn = 0; iColumn < numberColumns; iColumn++) + solutionIn[iColumn] = -COIN_DBL_MAX; + } + if (got[7] >= 0 || !numberFields) { + prioritiesIn = reinterpret_cast< int * >(malloc(numberColumns * sizeof(int))); + for (iColumn = 0; iColumn < numberColumns; iColumn++) + prioritiesIn[iColumn] = 10000; + } + for (iColumn = 0; iColumn < numberColumns; iColumn++) { + columnNames[iColumn] = CoinStrdup(lpSolver->columnName(iColumn).c_str()); + //if (got[5]!=-1) + pseudoDown[iColumn] = 0.0; + //if (got[4]!=-1) + pseudoUp[iColumn] = 0.0; + //if (got[2]!=-1) + branchDirection[iColumn] = 0; + priorities[iColumn] = useMasks ? -123456789 : 0; + } + int nBadPseudo = 0; + int nBadDir = 0; + int nBadPri = 0; + int nBadName = 0; + int nBadLine = 0; + int nLine = 0; + iColumn = -1; + int lowestPriority = -COIN_INT_MAX; + bool needCard = true; + while (!needCard || fgets(line, 1000, fp)) { + if (!strncmp(line, "ENDATA", 6) || !strncmp(line, "endata", 6)) + break; + nLine++; + if (!useMasks) + iColumn = -1; + else + needCard = false; + double up = 0.0; + double down = 0.0; + int pri = 0; + int dir = 0; + double solValue = COIN_DBL_MAX; + int priValue = 1000000; + char *pos = line; + char *put = line; + if (!numberFields) { + // put in , + for (i = 4; i < 100; i++) { + if (line[i] == ' ' || line[i] == '\t') { + line[i] = ','; + break; + } + } + } + while (*pos >= ' ' && *pos != '\n') { + if (*pos != ' ' && *pos != '\t') { + *put = *pos; + put++; + } + pos++; + } + *put = '\0'; + pos = line; + for (int i = 0; i < nAcross; i++) { + char *comma = strchr(pos, ','); + if (comma) { + *comma = '\0'; + } else if (i < nAcross - 1) { + nBadLine++; + break; + } + switch (order[i]) { + // name + case 0: + iColumn++; + for (; iColumn < numberColumns; iColumn++) { + if (priorities[iColumn] != -123456789) { + if (!strcmp(columnNames[iColumn], pos)) + break; + } else { + // mask (at present ? and trailing *) + const char *name = columnNames[iColumn]; + int length = strlen(name); + int lengthMask = strlen(pos); + bool asterisk = pos[lengthMask - 1] == '*'; + if (asterisk) + length = lengthMask - 1; + int i; + for (i = 0; i < length; i++) { + if (name[i] != pos[i]) { + if (pos[i] != '?') + break; + } + } + if (i == length) + break; + } + } + if (iColumn == numberColumns) { + iColumn = -1; + needCard = true; + } + break; + // number + case 1: + iColumn = atoi(pos); + if (iColumn < 0 || iColumn >= numberColumns) + iColumn = -1; + break; + // direction + case 2: + if (*pos == 'D') + dir = -1; + else if (*pos == 'U') + dir = 1; + else if (*pos == 'N') + dir = 0; + else if (*pos == '1' && *(pos + 1) == '\0') + dir = 1; + else if (*pos == '0' && *(pos + 1) == '\0') + dir = 0; + else if (*pos == '1' && *(pos + 1) == '1' && *(pos + 2) == '\0') + dir = -1; + else + dir = -2; // bad + break; + // priority + case 3: + pri = atoi(pos); + lowestPriority = CoinMax(lowestPriority, pri); + break; + // up + case 4: + up = atof(pos); + break; + // down + case 5: + down = atof(pos); + break; + // sol value + case 6: + solValue = atof(pos); + break; + // priority in value + case 7: + priValue = atoi(pos); + break; + } + if (comma) { + *comma = ','; + pos = comma + 1; + } + } + if (iColumn >= 0) { + if (down < 0.0) { + nBadPseudo++; + down = 0.0; + } + if (up < 0.0) { + nBadPseudo++; + up = 0.0; + } + if (!up) + up = down; + if (!down) + down = up; + if (dir < -1 || dir > 1) { + nBadDir++; + dir = 0; + } + if (pri < 0) { + nBadPri++; + pri = 0; + } + //if (got[5]!=-1) + pseudoDown[iColumn] = down; + //if (got[4]!=-1) + pseudoUp[iColumn] = up; + //if (got[2]!=-1) + branchDirection[iColumn] = dir; + priorities[iColumn] = pri; + if (solValue != COIN_DBL_MAX) { + assert(solutionIn); + solutionIn[iColumn] = solValue; + } + if (priValue != 1000000) { + assert(prioritiesIn); + prioritiesIn[iColumn] = priValue; + } + } else if (!useMasks) { + nBadName++; + } + } + for (iColumn = 0; iColumn < numberColumns; iColumn++) { + if (priorities[iColumn] == -123456789) + priorities[iColumn] = lowestPriority + 1; + } + if (!noPrinting_) { + printf("%d fields and %d records", nAcross, nLine); + if (nBadPseudo) + printf(" %d bad pseudo costs", nBadPseudo); + if (nBadDir) + printf(" %d bad directions", nBadDir); + if (nBadPri) + printf(" %d bad priorities", nBadPri); + if (nBadName) + printf(" ** %d records did not match on name/sequence", nBadName); + printf("\n"); + } + for (iColumn = 0; iColumn < numberColumns; iColumn++) { + free(columnNames[iColumn]); + } + delete[] columnNames; + } else { + std::cout << "Duplicate or unknown keyword - or name/number fields wrong" << line << std::endl; + } + } + fclose(fp); + } else { + sprintf(generalPrint, "Unable to open file %s", fileName.c_str()); + printGeneralMessage(model_, generalPrint); + } + } else { + sprintf(generalPrint, "** Current model not valid"); + printGeneralMessage(model_, generalPrint); + } + break; + case CBC_PARAM_ACTION_MIPSTART: + if (goodModel) { + // get next field + field = CoinReadGetString(argc, argv); + mipStartFile = field; + if (field == "$") { + field = parameters_[iParam].stringValue(); + } else if (field == "EOL") { + parameters_[iParam].printString(); + break; + } else { + parameters_[iParam].setStringValue(field); + } + std::string fileName; + if (field[0] == '/' || field[0] == '\\') { + fileName = field; + } else if (field[0] == '~') { + char *environVar = getenv("HOME"); + if (environVar) { + std::string home(environVar); + field = field.erase(0, 1); + fileName = home + field; + } else { + fileName = field; + } + } else { + fileName = directory + field; + } + sprintf(generalPrint, "opening mipstart file %s.", fileName.c_str()); + generalMessageHandler->message(CLP_GENERAL, generalMessages) << generalPrint << CoinMessageEol; + double msObj; + + CbcMipStartIO::read(model_.solver(), fileName.c_str(), mipStart, msObj, model_.messageHandler(), model_.messagesPointer()); + // copy to before preprocess if has .before. + if (strstr(fileName.c_str(), ".before.")) { + mipStartBefore = mipStart; + sprintf(generalPrint, "file %s will be used before preprocessing.", fileName.c_str()); + generalMessageHandler->message(CLP_GENERAL, generalMessages) + << generalPrint + << CoinMessageEol; + } + } else { + sprintf(generalPrint, "** Current model not valid"); + printGeneralMessage(model_, generalPrint); + } + break; + case CLP_PARAM_ACTION_DEBUG: + if (goodModel) { + delete[] debugValues; + debugValues = NULL; + // get next field + field = CoinReadGetString(argc, argv); + if (field == "$") { + field = parameters_[iParam].stringValue(); + } else if (field == "EOL") { + parameters_[iParam].printString(); + break; + } else { + parameters_[iParam].setStringValue(field); + debugFile = field; + if (debugFile == "create" || debugFile == "createAfterPre") { + printf("Will create a debug file so this run should be a good one\n"); + break; + } else if (debugFile == "unitTest") { + printf("debug will be done using file name of model\n"); + break; + } + } + std::string fileName; + if (field[0] == '/' || field[0] == '\\') { + fileName = field; + } else if (field[0] == '~') { + char *environVar = getenv("HOME"); + if (environVar) { + std::string home(environVar); + field = field.erase(0, 1); + fileName = home + field; + } else { + fileName = field; + } + } else { + fileName = directory + field; + } + FILE *fp = fopen(fileName.c_str(), "rb"); + if (fp) { + // can open - lets go for it + int numRows; + double obj; + size_t nRead; + nRead = fread(&numRows, sizeof(int), 1, fp); + if (nRead != 1) + throw("Error in fread"); + nRead = fread(&numberDebugValues, sizeof(int), 1, fp); + if (nRead != 1) + throw("Error in fread"); + nRead = fread(&obj, sizeof(double), 1, fp); + if (nRead != 1) + throw("Error in fread"); + debugValues = new double[numberDebugValues + numRows]; + nRead = fread(debugValues, sizeof(double), numRows, fp); + if (nRead != static_cast< size_t >(numRows)) + throw("Error in fread"); + nRead = fread(debugValues, sizeof(double), numRows, fp); + if (nRead != static_cast< size_t >(numRows)) + throw("Error in fread"); + nRead = fread(debugValues, sizeof(double), numberDebugValues, fp); + if (nRead != static_cast< size_t >(numberDebugValues)) + throw("Error in fread"); + printf("%d doubles read into debugValues\n", numberDebugValues); +#if DEBUG_PREPROCESS > 1 + debugSolution = debugValues; + debugNumberColumns = numberDebugValues; +#endif + if (numberDebugValues < 200) { + for (int i = 0; i < numberDebugValues; i++) { + if (clpSolver->isInteger(i) && debugValues[i]) + printf("%d %g\n", i, debugValues[i]); + } + } + fclose(fp); + } else { + sprintf(generalPrint, "Unable to open file %s", fileName.c_str()); + printGeneralMessage(model_, generalPrint); + } + } else { + sprintf(generalPrint, "** Current model not valid"); + printGeneralMessage(model_, generalPrint); + } + break; + case CLP_PARAM_ACTION_PRINTMASK: + // get next field + { + std::string name = CoinReadGetString(argc, argv); + if (name != "EOL") { + parameters_[iParam].setStringValue(name); + printMask = name; + } else { + parameters_[iParam].printString(); + } + } + break; + case CLP_PARAM_ACTION_BASISOUT: + if (goodModel) { + // get next field + field = CoinReadGetString(argc, argv); + if (field == "$") { + field = parameters_[iParam].stringValue(); + } else if (field == "EOL") { + parameters_[iParam].printString(); + break; + } else { + parameters_[iParam].setStringValue(field); + } + std::string fileName; + bool canOpen = false; + if (field[0] == '/' || field[0] == '\\') { + fileName = field; + } else if (field[0] == '~') { + char *environVar = getenv("HOME"); + if (environVar) { + std::string home(environVar); + field = field.erase(0, 1); + fileName = home + field; + } else { + fileName = field; + } + } else { + fileName = directory + field; + } + FILE *fp = fopen(fileName.c_str(), "w"); + if (fp) { + // can open - lets go for it + fclose(fp); + canOpen = true; + } else { + sprintf(generalPrint, "Unable to open file %s", fileName.c_str()); + printGeneralMessage(model_, generalPrint); + } + if (canOpen) { + ClpSimplex *model2 = lpSolver; + model2->writeBasis(fileName.c_str(), outputFormat > 1, outputFormat - 2); + time2 = CoinCpuTime(); + totalTime += time2 - time1; + time1 = time2; + } + } else { + sprintf(generalPrint, "** Current model not valid"); + printGeneralMessage(model_, generalPrint); + } + break; + case CLP_PARAM_ACTION_SAVE: { + // get next field + field = CoinReadGetString(argc, argv); + if (field == "$") { + field = parameters_[iParam].stringValue(); + } else if (field == "EOL") { + parameters_[iParam].printString(); + break; + } else { + parameters_[iParam].setStringValue(field); + } + std::string fileName; + bool canOpen = false; + if (field[0] == '/' || field[0] == '\\') { + fileName = field; + } else if (field[0] == '~') { + char *environVar = getenv("HOME"); + if (environVar) { + std::string home(environVar); + field = field.erase(0, 1); + fileName = home + field; + } else { + fileName = field; + } + } else { + fileName = directory + field; + } + FILE *fp = fopen(fileName.c_str(), "wb"); + if (fp) { + // can open - lets go for it + fclose(fp); + canOpen = true; + } else { + sprintf(generalPrint, "Unable to open file %s", fileName.c_str()); + printGeneralMessage(model_, generalPrint); + } + if (canOpen) { + int status; + // If presolve on then save presolved + bool deleteModel2 = false; + ClpSimplex *model2 = lpSolver; + if (preSolve) { + ClpPresolve pinfo; + double presolveTolerance = parameters_[whichParam(CLP_PARAM_DBL_PRESOLVETOLERANCE, parameters_)].doubleValue(); + model2 = pinfo.presolvedModel(*lpSolver, presolveTolerance, + false, preSolve); + if (model2) { + printf("Saving presolved model on %s\n", + fileName.c_str()); + deleteModel2 = true; + } else { + printf("Presolved model looks infeasible - saving original on %s\n", + fileName.c_str()); + deleteModel2 = false; + model2 = lpSolver; + } + } else { + printf("Saving model on %s\n", + fileName.c_str()); + } + status = model2->saveModel(fileName.c_str()); + if (deleteModel2) + delete model2; + if (!status) { + goodModel = true; + time2 = CoinCpuTime(); + totalTime += time2 - time1; + time1 = time2; + } else { + // errors + sprintf(generalPrint, "There were errors on output"); + printGeneralMessage(model_, generalPrint); + } + } + } break; + case CLP_PARAM_ACTION_RESTORE: { + // get next field + field = CoinReadGetString(argc, argv); + if (field == "$") { + field = parameters_[iParam].stringValue(); + } else if (field == "EOL") { + parameters_[iParam].printString(); + break; + } else { + parameters_[iParam].setStringValue(field); + } + std::string fileName; + bool canOpen = false; + if (field[0] == '/' || field[0] == '\\') { + fileName = field; + } else if (field[0] == '~') { + char *environVar = getenv("HOME"); + if (environVar) { + std::string home(environVar); + field = field.erase(0, 1); + fileName = home + field; + } else { + fileName = field; + } + } else { + fileName = directory + field; + } + FILE *fp = fopen(fileName.c_str(), "rb"); + if (fp) { + // can open - lets go for it + fclose(fp); + canOpen = true; + } else { + sprintf(generalPrint, "Unable to open file %s", fileName.c_str()); + printGeneralMessage(model_, generalPrint); + } + if (canOpen) { + int status = lpSolver->restoreModel(fileName.c_str()); + if (!status) { + goodModel = true; + time2 = CoinCpuTime(); + totalTime += time2 - time1; + time1 = time2; + } else { + // errors + sprintf(generalPrint, "There were errors on input"); + printGeneralMessage(model_, generalPrint); + } + } + } break; + case CLP_PARAM_ACTION_MAXIMIZE: + lpSolver->setOptimizationDirection(-1); + break; + case CLP_PARAM_ACTION_MINIMIZE: + lpSolver->setOptimizationDirection(1); + break; + case CLP_PARAM_ACTION_ALLSLACK: + lpSolver->allSlackBasis(true); + break; + case CLP_PARAM_ACTION_REVERSE: + if (goodModel) { + int iColumn; + int numberColumns = lpSolver->numberColumns(); + double *dualColumnSolution = lpSolver->dualColumnSolution(); + ClpObjective *obj = lpSolver->objectiveAsObject(); + assert(dynamic_cast< ClpLinearObjective * >(obj)); + double offset; + double *objective = obj->gradient(NULL, NULL, offset, true); + for (iColumn = 0; iColumn < numberColumns; iColumn++) { + dualColumnSolution[iColumn] = dualColumnSolution[iColumn]; + objective[iColumn] = -objective[iColumn]; + } + int iRow; + int numberRows = lpSolver->numberRows(); + double *dualRowSolution = lpSolver->dualRowSolution(); + for (iRow = 0; iRow < numberRows; iRow++) + dualRowSolution[iRow] = dualRowSolution[iRow]; + } + break; + case CLP_PARAM_ACTION_DIRECTORY: { + std::string name = CoinReadGetString(argc, argv); + if (name != "EOL") { + size_t length = name.length(); + if (length > 0 && name[length - 1] == dirsep) { + directory = name; + } else { + directory = name + dirsep; + } + parameters_[iParam].setStringValue(directory); + } else { + parameters_[iParam].printString(); + } + } break; + case CLP_PARAM_ACTION_DIRSAMPLE: { + std::string name = CoinReadGetString(argc, argv); + if (name != "EOL") { + size_t length = name.length(); + if (length > 0 && name[length - 1] == dirsep) { + dirSample = name; + } else { + dirSample = name + dirsep; + } + parameters_[iParam].setStringValue(dirSample); + } else { + parameters_[iParam].printString(); + } + } break; + case CLP_PARAM_ACTION_DIRNETLIB: { + std::string name = CoinReadGetString(argc, argv); + if (name != "EOL") { + size_t length = name.length(); + if (length > 0 && name[length - 1] == dirsep) { + dirNetlib = name; + } else { + dirNetlib = name + dirsep; + } + parameters_[iParam].setStringValue(dirNetlib); + } else { + parameters_[iParam].printString(); + } + } break; + case CBC_PARAM_ACTION_DIRMIPLIB: { + std::string name = CoinReadGetString(argc, argv); + if (name != "EOL") { + size_t length = name.length(); + if (length > 0 && name[length - 1] == dirsep) { + dirMiplib = name; + } else { + dirMiplib = name + dirsep; + } + parameters_[iParam].setStringValue(dirMiplib); + } else { + parameters_[iParam].printString(); + } + } break; + case CLP_PARAM_ACTION_STDIN: + setCbcOrClpReadMode(-1); + break; + case CLP_PARAM_ACTION_NETLIB_DUAL: + case CLP_PARAM_ACTION_NETLIB_EITHER: + case CLP_PARAM_ACTION_NETLIB_BARRIER: + case CLP_PARAM_ACTION_NETLIB_PRIMAL: + case CLP_PARAM_ACTION_NETLIB_TUNE: { + printf("unit test is now only from clp - does same thing\n"); + //return(22); + } break; + case CLP_PARAM_ACTION_UNITTEST: { + int returnCode; + if (!strcmp(argv[1],"-dirMiplib") || !strcmp(argv[1],"-dirmiplib")) + returnCode = CbcClpUnitTest(model_, dirMiplib, -3, NULL, + argc,argv,callBack,parameterData); + else + returnCode = CbcClpUnitTest(model_, dirSample, -2, NULL, + argc,argv,callBack,parameterData); + babModel_ = NULL; + return returnCode; + } + case CLP_PARAM_ACTION_FAKEBOUND: + if (goodModel) { + // get bound + double value = CoinReadGetDoubleField(argc, argv, &valid); + if (!valid) { + sprintf(generalPrint, "Setting %s to DEBUG %g", parameters_[iParam].name().c_str(), value); + printGeneralMessage(model_, generalPrint); + int iRow; + int numberRows = lpSolver->numberRows(); + double *rowLower = lpSolver->rowLower(); + double *rowUpper = lpSolver->rowUpper(); + for (iRow = 0; iRow < numberRows; iRow++) { + // leave free ones for now + if (rowLower[iRow] > -1.0e20 || rowUpper[iRow] < 1.0e20) { + rowLower[iRow] = CoinMax(rowLower[iRow], -value); + rowUpper[iRow] = CoinMin(rowUpper[iRow], value); + } + } + int iColumn; + int numberColumns = lpSolver->numberColumns(); + double *columnLower = lpSolver->columnLower(); + double *columnUpper = lpSolver->columnUpper(); + for (iColumn = 0; iColumn < numberColumns; iColumn++) { + // leave free ones for now + if (columnLower[iColumn] > -1.0e20 || columnUpper[iColumn] < 1.0e20) { + columnLower[iColumn] = CoinMax(columnLower[iColumn], -value); + columnUpper[iColumn] = CoinMin(columnUpper[iColumn], value); + } + } + } else if (valid == 1) { + abort(); + } else { + std::cout << "enter value for " << parameters_[iParam].name() << std::endl; + } + } + break; + case CLP_PARAM_ACTION_REALLY_SCALE: + if (goodModel) { + ClpSimplex newModel(*lpSolver, + lpSolver->scalingFlag()); + printf("model really really scaled\n"); + *lpSolver = newModel; + } + break; + case CLP_PARAM_ACTION_USERCLP: +#ifdef USER_HAS_FAKE_CLP + // Replace the sample code by whatever you want + if (goodModel) { + // Way of using an existing piece of code + OsiClpSolverInterface *clpSolver = dynamic_cast< OsiClpSolverInterface * >(model_.solver()); + ClpSimplex *lpSolver = clpSolver->getModelPtr(); + // set time from integer model + double timeToGo = model_.getMaximumSeconds(); + lpSolver->setMaximumSeconds(timeToGo); + int extra1 = parameters_[whichParam(CBC_PARAM_INT_EXTRA1, parameters_)].intValue(); + fakeMain2(*lpSolver, *clpSolver, extra1); + lpSolver = clpSolver->getModelPtr(); + // My actual usage has objective only in clpSolver + //double objectiveValue=clpSolver->getObjValue(); + //int iStat = lpSolver->status(); + //int iStat2 = lpSolver->secondaryStatus(); + } +#endif + break; + case CBC_PARAM_ACTION_USERCBC: +#ifdef USER_HAS_FAKE_CBC + // Replace the sample code by whatever you want + if (goodModel) { + // Way of using an existing piece of code + OsiClpSolverInterface *clpSolver = dynamic_cast< OsiClpSolverInterface * >(model_.solver()); + ClpSimplex *lpSolver = clpSolver->getModelPtr(); + // set time from integer model + double timeToGo = model_.getMaximumSeconds(); + lpSolver->setMaximumSeconds(timeToGo); + fakeMain(*lpSolver, *clpSolver, model); + // My actual usage has objective only in clpSolver + double objectiveValue = clpSolver->getObjValue(); + int iStat = lpSolver->status(); + int iStat2 = lpSolver->secondaryStatus(); + // make sure solution back in correct place + clpSolver = dynamic_cast< OsiClpSolverInterface * >(model_.solver()); + lpSolver = clpSolver->getModelPtr(); + if (statusUserFunction_[0]) { + int n = clpSolver->getNumCols(); + double value = objectiveValue * lpSolver->getObjSense(); + char buf[300]; + int pos = 0; + std::string minor[] = { "", "", "gap", "nodes", "time", "", "solutions", "user ctrl-c" }; + if (iStat == 0) { + if (objectiveValue < 1.0e40) { + pos += sprintf(buf + pos, "optimal,"); + } else { + // infeasible + iStat = 1; + pos += sprintf(buf + pos, "infeasible,"); + } + } else if (iStat == 1) { + if (iStat2 != 6) + iStat = 3; + else + iStat = 4; + pos += sprintf(buf + pos, "stopped on %s,", minor[iStat2].c_str()); + } else if (iStat == 2) { + iStat = 7; + pos += sprintf(buf + pos, "stopped on difficulties,"); + } else if (iStat == 5) { + iStat = 3; + pos += sprintf(buf + pos, "stopped on ctrl-c,"); + } else if (iStat == 6) { + // bab infeasible + pos += sprintf(buf + pos, "integer infeasible,"); + iStat = 1; + } else { + pos += sprintf(buf + pos, "status unknown,"); + iStat = 6; + } + info.problemStatus = iStat; + info.objValue = value; + if (objectiveValue < 1.0e40) + pos += sprintf(buf + pos, " objective %.*g", ampl_obj_prec(), + value); + sprintf(buf + pos, "\n%d nodes, %d iterations", + model_.getNodeCount(), + model_.getIterationCount()); + if (objectiveValue < 1.0e50) { + free(info.primalSolution); + info.primalSolution = (double *)malloc(n * sizeof(double)); + CoinCopyN(lpSolver->primalColumnSolution(), n, info.primalSolution); + int numberRows = lpSolver->numberRows(); + free(info.dualSolution); + info.dualSolution = (double *)malloc(numberRows * sizeof(double)); + CoinCopyN(lpSolver->dualRowSolution(), numberRows, info.dualSolution); + } else { + info.primalSolution = NULL; + info.dualSolution = NULL; + } + // put buffer into info + strcpy(info.buffer, buf); + } + } +#endif + break; + case CLP_PARAM_ACTION_HELP: + std::cout << "Cbc version " << CBC_VERSION + << ", build " << __DATE__ << std::endl; + std::cout << "Non default values:-" << std::endl; + std::cout << "Perturbation " << lpSolver->perturbation() << " (default 100)" + << std::endl; + CoinReadPrintit( + "Presolve being done with 5 passes\n\ +Dual steepest edge steep/partial on matrix shape and factorization density\n\ +Clpnnnn taken out of messages\n\ +If Factorization frequency default then done on size of matrix\n\n\ +(-)unitTest, (-)netlib or (-)netlibp will do standard tests\n\n\ +You can switch to interactive mode at any time so\n\ +clp watson.mps -scaling off -primalsimplex\nis the same as\n\ +clp watson.mps -\nscaling off\nprimalsimplex"); + break; + case CLP_PARAM_ACTION_CSVSTATISTICS: { + // get next field + field = CoinReadGetString(argc, argv); + if (field == "$") { + field = parameters_[iParam].stringValue(); + } else if (field == "EOL") { + parameters_[iParam].printString(); + break; + } else { + parameters_[iParam].setStringValue(field); + } + std::string fileName; + if (field[0] == '/' || field[0] == '\\') { + fileName = field; + } else if (field[0] == '~') { + char *environVar = getenv("HOME"); + if (environVar) { + std::string home(environVar); + field = field.erase(0, 1); + fileName = home + field; + } else { + fileName = field; + } + } else { + fileName = directory + field; + } + int state = 0; + char buffer[1000]; + FILE *fp = fopen(fileName.c_str(), "r"); + if (fp) { + // file already there + state = 1; + char *getBuffer = fgets(buffer, 1000, fp); + if (getBuffer) { + // assume header there + state = 2; + } + fclose(fp); + } + fp = fopen(fileName.c_str(), "a"); + if (fp) { + // can open - lets go for it + // first header if needed + if (state != 2) { + fprintf(fp, "Name,result,time,sys,elapsed,objective,continuous,tightened,cut_time,nodes,iterations,rows,columns,processed_rows,processed_columns"); + for (int i = 0; i < statistics_number_generators; i++) + fprintf(fp, ",%s", statistics_name_generators[i]); + fprintf(fp, ",runtime_options"); + fprintf(fp, "\n"); + } + strcpy(buffer, argv[1]); + char *slash = buffer; + for (int i = 0; i < static_cast< int >(strlen(buffer)); i++) { + if (buffer[i] == '/' || buffer[i] == '\\') + slash = buffer + i + 1; + } + fprintf(fp, "%s,%s,%.2f,%.2f,%.2f,%.16g,%g,%g,%.2f,%d,%d,%d,%d,%d,%d", + slash, statistics_result.c_str(), statistics_seconds, + statistics_sys_seconds, statistics_elapsed_seconds, + statistics_obj, + statistics_continuous, statistics_tighter, statistics_cut_time, statistics_nodes, + statistics_iterations, statistics_nrows, statistics_ncols, + statistics_nprocessedrows, statistics_nprocessedcols); + for (int i = 0; i < statistics_number_generators; i++) + fprintf(fp, ",%d", statistics_number_cuts != NULL ? statistics_number_cuts[i] : 0); + fprintf(fp, ","); + for (int i = 1; i < argc; i++) { + if (strstr(argv[i], ".gz") || strstr(argv[i], ".mps")) + continue; + if (!argv[i] || !strncmp(argv[i], "-csv", 4)) + break; + fprintf(fp, "%s ", argv[i]); + } + fprintf(fp, "\n"); + fclose(fp); + } else { + sprintf(generalPrint, "Unable to open file %s", fileName.c_str()); + printGeneralMessage(model_, generalPrint); + } + } break; + case CLP_PARAM_ACTION_SOLUTION: + case CLP_PARAM_ACTION_NEXTBESTSOLUTION: + case CLP_PARAM_ACTION_GMPL_SOLUTION: + if (goodModel) { + ClpSimplex *saveLpSolver = NULL; + // get next field + field = CoinReadGetString(argc, argv); + bool append = false; + if (field == "append$") { + field = "$"; + append = true; + } + if (field == "$") { + field = parameters_[iParam].stringValue(); + } else if (field == "EOL") { + parameters_[iParam].printString(); + break; + } else { + parameters_[iParam].setStringValue(field); + } + std::string fileName; + FILE *fp = NULL; + if (field == "-" || field == "EOL" || field == "stdout") { + // stdout + fp = stdout; + } else if (field == "stderr") { + // stderr + fp = stderr; + } else { + bool absolutePath; + if (dirsep == '/') { + // non Windows (or cygwin) + absolutePath = (field[0] == '/'); + } else { + //Windows (non cycgwin) + absolutePath = (field[0] == '\\'); + // but allow for : + if (strchr(field.c_str(), ':')) + absolutePath = true; + } + if (absolutePath) { + fileName = field; + } else if (field[0] == '~') { + char *environVar = getenv("HOME"); + if (environVar) { + std::string home(environVar); + field = field.erase(0, 1); + fileName = home + field; + } else { + fileName = field; + } + } else { + fileName = directory + field; + } + if (!append) + fp = fopen(fileName.c_str(), "w"); + else + fp = fopen(fileName.c_str(), "a"); + } + if (fp) { +#ifndef CBC_OTHER_SOLVER + // See if Glpk + if (type == CLP_PARAM_ACTION_GMPL_SOLUTION) { + int numberRows = lpSolver->getNumRows(); + int numberColumns = lpSolver->getNumCols(); + int numberGlpkRows = numberRows + 1; +#ifdef CBC_HAS_GLPK + if (cbc_glp_prob) { + // from gmpl + numberGlpkRows = glp_get_num_rows(cbc_glp_prob); + if (numberGlpkRows != numberRows) + printf("Mismatch - cbc %d rows, glpk %d\n", + numberRows, numberGlpkRows); + } +#endif + fprintf(fp, "%d %d\n", numberGlpkRows, + numberColumns); + int iStat = lpSolver->status(); + int iStat2 = GLP_UNDEF; + bool integerProblem = false; + if (integerStatus >= 0) { + iStat = integerStatus; + integerProblem = true; + } + if (iStat == 0) { + // optimal + if (integerProblem) + iStat2 = GLP_OPT; + else + iStat2 = GLP_FEAS; + } else if (iStat == 1) { + // infeasible + iStat2 = GLP_NOFEAS; + } else if (iStat == 2) { + // unbounded + // leave as 1 + } else if (iStat >= 3 && iStat <= 5) { + if (babModel_ && !babModel_->bestSolution()) + iStat2 = GLP_NOFEAS; + else + iStat2 = GLP_FEAS; + } else if (iStat == 6) { + // bab infeasible + iStat2 = GLP_NOFEAS; + } + lpSolver->computeObjectiveValue(false); + double objValue = clpSolver->getObjValue(); + if (integerProblem) + fprintf(fp, "%d %g\n", iStat2, objValue); + else + fprintf(fp, "%d 2 %g\n", iStat2, objValue); + if (numberGlpkRows > numberRows) { + // objective as row + if (integerProblem) { + fprintf(fp, "%g\n", objValue); + } else { + fprintf(fp, "4 %g 1.0\n", objValue); + } + } + int lookup[6] = { 4, 1, 3, 2, 4, 5 }; + const double *primalRowSolution = lpSolver->primalRowSolution(); + const double *dualRowSolution = lpSolver->dualRowSolution(); + for (int i = 0; i < numberRows; i++) { + if (integerProblem) { + fprintf(fp, "%g\n", primalRowSolution[i]); + } else { + fprintf(fp, "%d %g %g\n", lookup[lpSolver->getRowStatus(i)], + primalRowSolution[i], dualRowSolution[i]); + } + } + const double *primalColumnSolution = lpSolver->primalColumnSolution(); + const double *dualColumnSolution = lpSolver->dualColumnSolution(); + for (int i = 0; i < numberColumns; i++) { + if (integerProblem) { + fprintf(fp, "%g\n", primalColumnSolution[i]); + } else { + fprintf(fp, "%d %g %g\n", lookup[lpSolver->getColumnStatus(i)], + primalColumnSolution[i], dualColumnSolution[i]); + } + } + fclose(fp); +#ifdef CBC_HAS_GLPK + if (cbc_glp_prob) { + if (integerProblem) { + glp_read_mip(cbc_glp_prob, fileName.c_str()); + glp_mpl_postsolve(cbc_glp_tran, + cbc_glp_prob, + GLP_MIP); + } else { + glp_read_sol(cbc_glp_prob, fileName.c_str()); + glp_mpl_postsolve(cbc_glp_tran, + cbc_glp_prob, + GLP_SOL); + } + // free up as much as possible + glp_free(cbc_glp_prob); + glp_mpl_free_wksp(cbc_glp_tran); + cbc_glp_prob = NULL; + cbc_glp_tran = NULL; + //gmp_free_mem(); + /* check that no memory blocks are still allocated */ + glp_free_env(); + } +#endif + break; + } + if (printMode < 5) { + if (type == CLP_PARAM_ACTION_NEXTBESTSOLUTION) { + // save + const double *nextBestSolution = model_.savedSolution(currentBestSolution++); + if (!nextBestSolution) { + sprintf(generalPrint, "All alternative solutions printed"); + generalMessageHandler->message(CLP_GENERAL, generalMessages) + << generalPrint + << CoinMessageEol; + break; + } else { + sprintf(generalPrint, "Alternative solution - %d remaining", model_.numberSavedSolutions() - 2); + generalMessageHandler->message(CLP_GENERAL, generalMessages) + << generalPrint + << CoinMessageEol; + } + saveLpSolver = lpSolver; + assert(clpSolver->getModelPtr() == saveLpSolver); + lpSolver = new ClpSimplex(*saveLpSolver); +#ifndef NDEBUG + ClpSimplex *oldSimplex = clpSolver->swapModelPtr(lpSolver); + assert(oldSimplex == saveLpSolver); +#else + clpSolver->swapModelPtr(lpSolver); +#endif + double *solution = lpSolver->primalColumnSolution(); + double *lower = lpSolver->columnLower(); + double *upper = lpSolver->columnUpper(); + int numberColumns = lpSolver->numberColumns(); + memcpy(solution, nextBestSolution, numberColumns * sizeof(double)); + model_.deleteSavedSolution(1); + for (int i = 0; i < numberColumns; i++) { + if (clpSolver->isInteger(i)) { + double value = floor(solution[i] + 0.5); + lower[i] = value; + upper[i] = value; + } + } + lpSolver->allSlackBasis(); + lpSolver->initialSolve(); + } + // Write solution header (suggested by Luigi Poderico) + // Refresh solver + lpSolver = clpSolver->getModelPtr(); + ClpQuadraticObjective * quadObj = + dynamic_cast(lpSolver->objectiveAsObject()); + double objValue; + if (!quadObj) { + lpSolver->computeObjectiveValue(false); + objValue = lpSolver->getObjValue(); + } else { + double *solution = lpSolver->primalColumnSolution(); + objValue = quadObj->objectiveValue(lpSolver,solution); + // offset + objValue -= lpSolver->objectiveOffset(); + } + int iStat = lpSolver->status(); + int iStat2 = -1; + if (integerStatus >= 0) { + iStat = integerStatus; + iStat2 = babModel_ ? babModel_->secondaryStatus() + : model_.secondaryStatus(); + } + if (iStat == 0) { + fprintf(fp, "Optimal"); + if (iStat2 == 2) { + fprintf(fp, " (within gap tolerance)"); + } + } else if (iStat == 1) { + // infeasible + fprintf(fp, "Infeasible"); + } else if (iStat == 2) { + // unbounded + fprintf(fp, "Unbounded"); + } else if (iStat >= 3 && iStat <= 5) { + if (iStat == 3) { + if (iStat2 == 4) { + fprintf(fp, "Stopped on time"); + } else { + fprintf(fp, "Stopped on iterations"); + } + } else if (iStat == 4) { + fprintf(fp, "Stopped on difficulties"); + } else { + fprintf(fp, "Stopped on ctrl-c"); + } + if (babModel_ && !babModel_->bestSolution()) + fprintf(fp, " (no integer solution - continuous used)"); + } else if (iStat == 6) { + // bab infeasible + fprintf(fp, "Integer infeasible"); + } else { + fprintf(fp, "Status unknown"); + } + fprintf(fp, " - objective value %.8f\n", objValue); + } +#endif + // make fancy later on + int iRow; + int numberRows = clpSolver->getNumRows(); + const double *dualRowSolution = clpSolver->getRowPrice(); + const double *primalRowSolution = clpSolver->getRowActivity(); + const double *rowLower = clpSolver->getRowLower(); + const double *rowUpper = clpSolver->getRowUpper(); + double primalTolerance; + clpSolver->getDblParam(OsiPrimalTolerance, primalTolerance); + size_t lengthPrint = static_cast< size_t >(CoinMax(lengthName, 8)); + bool doMask = (printMask != "" && lengthName); + int *maskStarts = NULL; + int maxMasks = 0; + char **masks = NULL; + if (doMask) { + int nAst = 0; + const char *pMask2 = printMask.c_str(); + char pMask[100]; + size_t iChar; + size_t lengthMask = strlen(pMask2); + assert(lengthMask < 100); + if (*pMask2 == '"') { + if (pMask2[lengthMask - 1] != '"') { + printf("mismatched \" in mask %s\n", pMask2); + break; + } else { + strcpy(pMask, pMask2 + 1); + *strchr(pMask, '"') = '\0'; + } + } else if (*pMask2 == '\'') { + if (pMask2[lengthMask - 1] != '\'') { + printf("mismatched ' in mask %s\n", pMask2); + break; + } else { + strcpy(pMask, pMask2 + 1); + *strchr(pMask, '\'') = '\0'; + } + } else { + strcpy(pMask, pMask2); + } + if (lengthMask > static_cast< size_t >(lengthName)) { + printf("mask %s too long - skipping\n", pMask); + break; + } + maxMasks = 1; + for (iChar = 0; iChar < lengthMask; iChar++) { + if (pMask[iChar] == '*') { + nAst++; + maxMasks *= (lengthName + 1); + } + } + int nEntries = 1; + maskStarts = new int[lengthName + 2]; + masks = new char *[maxMasks]; + char **newMasks = new char *[maxMasks]; + int i; + for (i = 0; i < maxMasks; i++) { + masks[i] = new char[lengthName + 1]; + newMasks[i] = new char[lengthName + 1]; + } + strcpy(masks[0], pMask); + for (int iAst = 0; iAst < nAst; iAst++) { + int nOldEntries = nEntries; + nEntries = 0; + for (int iEntry = 0; iEntry < nOldEntries; iEntry++) { + char *oldMask = masks[iEntry]; + char *ast = strchr(oldMask, '*'); + assert(ast); + size_t length = strlen(oldMask) - 1; + size_t nBefore = ast - oldMask; + size_t nAfter = length - nBefore; + // and add null + nAfter++; + for (int i = 0; i <= lengthName - static_cast< int >(length); i++) { + char *maskOut = newMasks[nEntries]; + memcpy(maskOut, oldMask, nBefore); + for (int k = 0; k < i; k++) + maskOut[k + nBefore] = '?'; + memcpy(maskOut + nBefore + i, ast + 1, nAfter); + nEntries++; + assert(nEntries <= maxMasks); + } + } + char **temp = masks; + masks = newMasks; + newMasks = temp; + } + // Now extend and sort + int *sort = new int[nEntries]; + for (i = 0; i < nEntries; i++) { + char *maskThis = masks[i]; + size_t length = strlen(maskThis); + while (length > 0 && maskThis[length - 1] == ' ') + length--; + maskThis[length] = '\0'; + sort[i] = static_cast< int >(length); + } + CoinSort_2(sort, sort + nEntries, masks); + int lastLength = -1; + for (i = 0; i < nEntries; i++) { + int length = sort[i]; + while (length > lastLength) + maskStarts[++lastLength] = i; + } + maskStarts[++lastLength] = nEntries; + delete[] sort; + for (i = 0; i < maxMasks; i++) + delete[] newMasks[i]; + delete[] newMasks; + } + if (printMode > 5 && printMode < 12) { + ClpSimplex *solver = clpSolver->getModelPtr(); + int numberColumns = numberPrintingColumns(clpSolver); + //int numberColumns = solver->numberColumns(); + // column length unless rhs ranging + int number = numberColumns; + if (lpSolver->status()) { + fprintf(fp, "**** Results not valid when LP not optimal\n"); + number = 0; + } + switch (printMode) { + // bound ranging + case 6: + fprintf(fp, "Bound ranging"); + break; + // rhs ranging + case 7: + fprintf(fp, "Rhs ranging"); + if (!lpSolver->status()) + number = numberRows; + break; + // objective ranging + case 8: + fprintf(fp, "Objective ranging"); + break; + } + if (lengthName) + fprintf(fp, ",name"); + fprintf(fp, ",increase,variable,decrease,variable\n"); + int *which = new int[number]; + if (printMode != 7) { + if (!doMask) { + for (int i = 0; i < number; i++) + which[i] = i; + } else { + int n = 0; + for (int i = 0; i < number; i++) { + if (maskMatches(maskStarts, masks, columnNames[i])) + which[n++] = i; + } + if (n) { + number = n; + } else { + printf("No names match - doing all\n"); + for (int i = 0; i < number; i++) + which[i] = i; + } + } + } else { + if (!doMask) { + for (int i = 0; i < number; i++) + which[i] = i + numberColumns; + } else { + int n = 0; + for (int i = 0; i < number; i++) { + if (maskMatches(maskStarts, masks, rowNames[i])) + which[n++] = i + numberColumns; + } + if (n) { + number = n; + } else { + printf("No names match - doing all\n"); + for (int i = 0; i < number; i++) + which[i] = i + numberColumns; + } + } + } + double *valueIncrease = new double[number]; + int *sequenceIncrease = new int[number]; + double *valueDecrease = new double[number]; + int *sequenceDecrease = new int[number]; + switch (printMode) { + // bound or rhs ranging + case 6: + case 7: + solver->primalRanging(numberRows, + which, valueIncrease, sequenceIncrease, + valueDecrease, sequenceDecrease); + break; + // objective ranging + case 8: + solver->dualRanging(number, + which, valueIncrease, sequenceIncrease, + valueDecrease, sequenceDecrease); + break; + } + for (int i = 0; i < number; i++) { + int iWhich = which[i]; + fprintf(fp, "%d,", (iWhich < numberColumns) ? iWhich : iWhich - numberColumns); + if (lengthName) { + const char *name = (printMode == 7) ? rowNames[iWhich - numberColumns].c_str() : columnNames[iWhich].c_str(); + fprintf(fp, "%s,", name); + } + if (valueIncrease[i] < 1.0e30) { + fprintf(fp, "%.10g,", valueIncrease[i]); + int outSequence = sequenceIncrease[i]; + if (outSequence < numberColumns) { + if (lengthName) + fprintf(fp, "%s,", columnNames[outSequence].c_str()); + else + fprintf(fp, "C%7.7d,", outSequence); + } else { + outSequence -= numberColumns; + if (lengthName) + fprintf(fp, "%s,", rowNames[outSequence].c_str()); + else + fprintf(fp, "R%7.7d,", outSequence); + } + } else { + fprintf(fp, "1.0e100,,"); + } + if (valueDecrease[i] < 1.0e30) { + fprintf(fp, "%.10g,", valueDecrease[i]); + int outSequence = sequenceDecrease[i]; + if (outSequence < numberColumns) { + if (lengthName) + fprintf(fp, "%s", columnNames[outSequence].c_str()); + else + fprintf(fp, "C%7.7d", outSequence); + } else { + outSequence -= numberColumns; + if (lengthName) + fprintf(fp, "%s", rowNames[outSequence].c_str()); + else + fprintf(fp, "R%7.7d", outSequence); + } + } else { + fprintf(fp, "1.0e100,"); + } + fprintf(fp, "\n"); + } + if (fp != stdout) + fclose(fp); + delete[] which; + delete[] valueIncrease; + delete[] sequenceIncrease; + delete[] valueDecrease; + delete[] sequenceDecrease; + if (masks) { + delete[] maskStarts; + for (int i = 0; i < maxMasks; i++) + delete[] masks[i]; + delete[] masks; + } + break; + } + char printFormat[50]; + sprintf(printFormat, " %s %s\n", + CLP_QUOTE(CLP_OUTPUT_FORMAT), + CLP_QUOTE(CLP_OUTPUT_FORMAT)); + if (printMode > 2 && printMode < 5) { + for (iRow = 0; iRow < numberRows; iRow++) { + int type = printMode - 3; + if (primalRowSolution[iRow] > rowUpper[iRow] + primalTolerance || primalRowSolution[iRow] < rowLower[iRow] - primalTolerance) { + fprintf(fp, "** "); + type = 2; + } else if (fabs(primalRowSolution[iRow]) > 1.0e-8) { + type = 1; + } else if (numberRows < 50) { + type = 3; + } + if (doMask && !maskMatches(maskStarts, masks, rowNames[iRow])) + type = 0; + if (type) { + fprintf(fp, "%7d ", iRow); + if (lengthName) { + const char *name = rowNames[iRow].c_str(); + size_t n = strlen(name); + size_t i; + for (i = 0; i < n; i++) + fprintf(fp, "%c", name[i]); + for (; i < lengthPrint; i++) + fprintf(fp, " "); + } + fprintf(fp, printFormat, primalRowSolution[iRow], + dualRowSolution[iRow]); + } + } + } + int iColumn; + int numberColumns = numberPrintingColumns(clpSolver); + const double *dualColumnSolution = clpSolver->getReducedCost(); + const double *primalColumnSolution = clpSolver->getColSolution(); + const double *columnLower = clpSolver->getColLower(); + const double *columnUpper = clpSolver->getColUpper(); + if (printMode != 2 && printMode < 12) { + if (printMode == 5) { + if (lengthName) + fprintf(fp, "name"); + else + fprintf(fp, "number"); + fprintf(fp, ",solution\n"); + } + for (iColumn = 0; iColumn < numberColumns; iColumn++) { + int type = (printMode > 3) ? 1 : 0; + if (primalColumnSolution[iColumn] > columnUpper[iColumn] + primalTolerance || primalColumnSolution[iColumn] < columnLower[iColumn] - primalTolerance) { + fprintf(fp, "** "); + type = 2; + } else if (fabs(primalColumnSolution[iColumn]) > 1.0e-8) { + type = 1; + } else if (numberColumns < 50) { + type = 3; + } + // see if integer + if ((!clpSolver->isInteger(iColumn) || fabs(primalColumnSolution[iColumn]) < 1.0e-8) + && printMode == 1) + type = 0; + if (doMask && !maskMatches(maskStarts, masks, columnNames[iColumn])) + type = 0; + if (type) { + if (printMode != 5) { + fprintf(fp, "%7d ", iColumn); + if (lengthName) { + const char *name = columnNames[iColumn].c_str(); + size_t n = strlen(name); + size_t i; + for (i = 0; i < n; i++) + fprintf(fp, "%c", name[i]); + for (; i < lengthPrint; i++) + fprintf(fp, " "); + } + fprintf(fp, printFormat, + primalColumnSolution[iColumn], + dualColumnSolution[iColumn]); + } else { + char temp[100]; + if (lengthName) { + const char *name = columnNames[iColumn].c_str(); + for (int i = 0; i < lengthName; i++) + temp[i] = name[i]; + temp[lengthName] = '\0'; + } else { + sprintf(temp, "%7d", iColumn); + } + sprintf(temp + strlen(temp), ", %15.8g", + primalColumnSolution[iColumn]); + size_t n = strlen(temp); + size_t k = 0; + for (size_t i = 0; i < n + 1; i++) { + if (temp[i] != ' ') + temp[k++] = temp[i]; + } + fprintf(fp, "%s\n", temp); + } + } + } + if (type == CLP_PARAM_ACTION_NEXTBESTSOLUTION) { + if (saveLpSolver) { + clpSolver->swapModelPtr(saveLpSolver); + delete lpSolver; + lpSolver = saveLpSolver; + saveLpSolver = NULL; + } + } + } else if (printMode == 2) { + // special format suitable for OsiRowCutDebugger + int n = 0; + bool comma = false; + bool newLine = false; + fprintf(fp, "\tint intIndicesV[]={\n"); + for (iColumn = 0; iColumn < numberColumns; iColumn++) { + if (primalColumnSolution[iColumn] > 0.5 && model_.solver()->isInteger(iColumn)) { + if (comma) + fprintf(fp, ","); + if (newLine) + fprintf(fp, "\n"); + fprintf(fp, "%d ", iColumn); + comma = true; + newLine = false; + n++; + if (n == 10) { + n = 0; + newLine = true; + } + } + } + fprintf(fp, "};\n"); + n = 0; + comma = false; + newLine = false; + fprintf(fp, "\tdouble intSolnV[]={\n"); + for (iColumn = 0; iColumn < numberColumns; iColumn++) { + if (primalColumnSolution[iColumn] > 0.5 && model_.solver()->isInteger(iColumn)) { + if (comma) + fprintf(fp, ","); + if (newLine) + fprintf(fp, "\n"); + int value = static_cast< int >(primalColumnSolution[iColumn] + 0.5); + fprintf(fp, "%d. ", value); + comma = true; + newLine = false; + n++; + if (n == 10) { + n = 0; + newLine = true; + } + } + } + fprintf(fp, "};\n"); + } else { + // Make up a fake bounds section + char outputValue[24]; + for (iColumn = 0; iColumn < numberColumns; iColumn++) { + if (printMode == 13 || model_.solver()->isInteger(iColumn)) { + fprintf(fp, " FX BOUND001 "); + const char *name = columnNames[iColumn].c_str(); + size_t n = strlen(name); + size_t i; + for (i = 0; i < n; i++) + fprintf(fp, "%c", name[i]); + for (; i < lengthPrint; i++) + fprintf(fp, " "); + CoinConvertDouble(5, 2, primalColumnSolution[iColumn], + outputValue); + fprintf(fp, " %s\n", outputValue); + } else { + fprintf(fp, " LO BOUND001 "); + const char *name = columnNames[iColumn].c_str(); + size_t n = strlen(name); + size_t i; + for (i = 0; i < n; i++) + fprintf(fp, "%c", name[i]); + for (; i < lengthPrint; i++) + fprintf(fp, " "); + CoinConvertDouble(5, 2, CoinMax(-1.0e30, columnLower[iColumn]), + outputValue); + fprintf(fp, " %s\n", outputValue); + fprintf(fp, " UP BOUND001 "); + for (i = 0; i < n; i++) + fprintf(fp, "%c", name[i]); + for (; i < lengthPrint; i++) + fprintf(fp, " "); + CoinConvertDouble(5, 2, CoinMin(1.0e30, columnUpper[iColumn]), + outputValue); + fprintf(fp, " %s\n", outputValue); + } + } + for (iColumn = 0; iColumn < numberColumns; iColumn++) { + if (primalColumnSolution[iColumn] > columnUpper[iColumn] + primalTolerance || primalColumnSolution[iColumn] < columnLower[iColumn] - primalTolerance) { + fprintf(fp, " FX BOUND002 "); + const char *name = columnNames[iColumn].c_str(); + size_t n = strlen(name); + size_t i; + for (i = 0; i < n; i++) + fprintf(fp, "%c", name[i]); + for (; i < lengthPrint; i++) + fprintf(fp, " "); + CoinConvertDouble(5, 2, primalColumnSolution[iColumn], + outputValue); + fprintf(fp, " %s\n", outputValue); + } + } + } + if (fp != stdout) + fclose(fp); + if (masks) { + delete[] maskStarts; + for (int i = 0; i < maxMasks; i++) + delete[] masks[i]; + delete[] masks; + } + } else { + sprintf(generalPrint, "Unable to open file %s", fileName.c_str()); + printGeneralMessage(model_, generalPrint); + } + } else { + sprintf(generalPrint, "** Current model not valid"); + printGeneralMessage(model_, generalPrint); + } + break; + case CLP_PARAM_ACTION_SAVESOL: + if (goodModel) { + // get next field + field = CoinReadGetString(argc, argv); + if (field == "$") { + field = parameters_[iParam].stringValue(); + } else if (field == "EOL") { + parameters_[iParam].printString(); + break; + } else { + parameters_[iParam].setStringValue(field); + } + std::string fileName; + if (field[0] == '/' || field[0] == '\\') { + fileName = field; + } else if (field[0] == '~') { + char *environVar = getenv("HOME"); + if (environVar) { + std::string home(environVar); + field = field.erase(0, 1); + fileName = home + field; + } else { + fileName = field; + } + } else { + fileName = directory + field; + } + saveSolution(lpSolver, fileName); + } else { + sprintf(generalPrint, "** Current model not valid"); + printGeneralMessage(model_, generalPrint); + } + break; + case CLP_PARAM_ACTION_DUMMY: + break; + case CLP_PARAM_ACTION_ENVIRONMENT: + CbcOrClpEnvironmentIndex = 0; + break; + case CLP_PARAM_ACTION_PARAMETRICS: + if (goodModel) { + // get next field + field = CoinReadGetString(argc, argv); + if (field == "$") { + field = parameters_[iParam].stringValue(); + } else if (field == "EOL") { + parameters_[iParam].printString(); + break; + } else { + parameters_[iParam].setStringValue(field); + } + std::string fileName; + //bool canOpen = false; + if (field[0] == '/' || field[0] == '\\') { + fileName = field; + } else if (field[0] == '~') { + char *environVar = getenv("HOME"); + if (environVar) { + std::string home(environVar); + field = field.erase(0, 1); + fileName = home + field; + } else { + fileName = field; + } + } else { + fileName = directory + field; + } + static_cast< ClpSimplexOther * >(lpSolver)->parametrics(fileName.c_str()); + time2 = CoinCpuTime(); + totalTime += time2 - time1; + time1 = time2; + } else { + sprintf(generalPrint, "** Current model not valid"); + printGeneralMessage(model_, generalPrint); + } + break; + case CLP_PARAM_ACTION_GUESS: + if (goodModel && model_.solver()) { + delete[] alternativeEnvironment; + OsiClpSolverInterface *clpSolver = dynamic_cast< OsiClpSolverInterface * >(model_.solver()); + assert(clpSolver); + lpSolver = clpSolver->getModelPtr(); + assert(lpSolver); + ClpSimplexOther *model2 = static_cast< ClpSimplexOther * >(lpSolver); + alternativeEnvironment = + const_cast(model2->guess(1).c_str()); + if (alternativeEnvironment) + CbcOrClpEnvironmentIndex = 0; + else + std::cout << "** Guess unable to generate commands" << std::endl; + } else { + std::cout << "** Guess needs a valid model" << std::endl; + } + break; + default: + abort(); + } + } + } else if (!numberMatches) { + std::cout << "No match for " << field << " - ? for list of commands" + << std::endl; + } else if (numberMatches == 1) { + if (!numberQuery) { + std::cout << "Short match for " << field << " - completion: "; + std::cout << parameters_[firstMatch].matchName() << std::endl; + } else if (numberQuery) { + std::cout << parameters_[firstMatch].matchName() << " : "; + std::cout << parameters_[firstMatch].shortHelp() << std::endl; + if (numberQuery >= 2) + parameters_[firstMatch].printLongHelp(); + } + } else { + if (!numberQuery) + std::cout << "Multiple matches for " << field << " - possible completions:" + << std::endl; + else + std::cout << "Completions of " << field << ":" << std::endl; + for (iParam = 0; iParam < (int)parameters_.size(); iParam++) { + int match = parameters_[iParam].matches(field); + if (match && parameters_[iParam].displayThis()) { + std::cout << parameters_[iParam].matchName(); + if (numberQuery >= 2) + std::cout << " : " << parameters_[iParam].shortHelp(); + std::cout << std::endl; + } + } + } + } + delete coinModel; + } +#if CBC_QUIET == 0 + sprintf(generalPrint, + "Total time (CPU seconds): %.2f (Wallclock seconds): %.2f\n", + CoinCpuTime() - time0, + CoinGetTimeOfDay() - time0Elapsed); + generalMessageHandler->message(CLP_GENERAL, generalMessages) + << generalPrint + << CoinMessageEol; +#endif +#ifdef CBC_HAS_GLPK + if (cbc_glp_prob) { + // free up as much as possible + glp_free(cbc_glp_prob); + glp_mpl_free_wksp(cbc_glp_tran); + glp_free_env(); + cbc_glp_prob = NULL; + cbc_glp_tran = NULL; + } +#endif + delete[] lotsize; + if (statistics_number_cuts != NULL) + delete[] statistics_number_cuts; + + if (statistics_name_generators != NULL) + delete[] statistics_name_generators; + // By now all memory should be freed +#ifdef DMALLOC + //dmalloc_log_unfreed(); + //dmalloc_shutdown(); +#endif + if (babModel_) { + model_.moveInfo(*babModel_); +#ifndef CBC_OTHER_SOLVER + OsiClpSolverInterface *clpSolver0 = dynamic_cast< OsiClpSolverInterface * >(babModel_->solver()); + ClpSimplex *lpSolver0 = clpSolver0->getModelPtr(); + OsiClpSolverInterface *clpSolver = dynamic_cast< OsiClpSolverInterface * >(model_.solver()); + ClpSimplex *lpSolver = clpSolver->getModelPtr(); + if (lpSolver0 != lpSolver && lpSolver != originalSolver->getModelPtr()) + lpSolver->moveInfo(*lpSolver0); + //babModel_->setModelOwnsSolver(false); +#endif + } + + delete babModel_; + + babModel_ = NULL; + model_.solver()->setWarmStart(NULL); + //sprintf(generalPrint, "Total time %.2f", CoinCpuTime() - time0); + //generalMessageHandler->message(CLP_GENERAL, generalMessages) + //<< generalPrint + //<< CoinMessageEol; + return 0; +} + +int CbcMain(int argc, const char *argv[], + CbcModel &model) +{ + CbcSolverUsefulData cbcData; + cbcData.noPrinting_ = false; + CbcMain0(model, cbcData); + return CbcMain1(argc, argv, model, dummyCallBack, cbcData); +} + +void CbcMain0(CbcModel &model, + CbcSolverUsefulData ¶meterData) +{ +#ifdef HAVE_SIGNAL_H +#ifdef HAVE_EXECINFO_H + signal(SIGSEGV, CbcCrashHandler); + signal(SIGABRT, CbcCrashHandler); + signal(SIGFPE, CbcCrashHandler); + +#endif +#endif + + std::vector< CbcOrClpParam > ¶meters = parameterData.parameters_; + +#ifndef CBC_OTHER_SOLVER + OsiClpSolverInterface *originalSolver = dynamic_cast< OsiClpSolverInterface * >(model.solver()); +#elif CBC_OTHER_SOLVER == 1 + OsiCpxSolverInterface *originalSolver = dynamic_cast< OsiCpxSolverInterface * >(model.solver()); + // Dummy solvers + OsiClpSolverInterface dummySolver; + ClpSimplex *lpSolver = dummySolver.getModelPtr(); + OsiCpxSolverInterface *clpSolver = originalSolver; +#endif + assert(originalSolver); + CoinMessageHandler *generalMessageHandler = originalSolver->messageHandler(); + generalMessageHandler->setPrefix(true); +#ifndef CBC_OTHER_SOLVER + OsiSolverInterface *solver = model.solver(); + OsiClpSolverInterface *clpSolver = dynamic_cast< OsiClpSolverInterface * >(solver); + ClpSimplex *lpSolver = clpSolver->getModelPtr(); + lpSolver->setPerturbation(50); + lpSolver->messageHandler()->setPrefix(false); +#endif + //establishParams(numberParameters, parameters) ; + const char dirsep = CoinFindDirSeparator(); + std::string directory; + std::string dirSample; + std::string dirNetlib; + std::string dirMiplib; + if (dirsep == '/') { + directory = "./"; + dirSample = "../../Data/Sample/"; + dirNetlib = "../../Data/Netlib/"; + dirMiplib = "../../Data/miplib3/"; + } else { + directory = ".\\"; + dirSample = "..\\..\\..\\..\\Data\\Sample\\"; + dirNetlib = "..\\..\\..\\..\\Data\\Netlib\\"; + dirMiplib = "..\\..\\..\\..\\Data\\miplib3\\"; + } + std::string defaultDirectory = directory; + std::string importFile = ""; + std::string exportFile = "default.mps"; + std::string importBasisFile = ""; + std::string importPriorityFile = ""; + std::string debugFile = ""; + std::string printMask = ""; + std::string exportBasisFile = "default.bas"; + std::string saveFile = "default.prob"; + std::string restoreFile = "default.prob"; + std::string solutionFile = "stdout"; + std::string solutionSaveFile = "solution.file"; + int doIdiot = -1; + int outputFormat = 2; + int substitution = 3; + int dualize = 3; + int preSolve = 5; + int doSprint = -1; + int testOsiParameters = -1; + parameters[whichParam(CLP_PARAM_ACTION_BASISIN, parameters)].setStringValue(importBasisFile); + parameters[whichParam(CBC_PARAM_ACTION_PRIORITYIN, parameters)].setStringValue(importPriorityFile); + parameters[whichParam(CLP_PARAM_ACTION_BASISOUT, parameters)].setStringValue(exportBasisFile); + parameters[whichParam(CLP_PARAM_ACTION_DEBUG, parameters)].setStringValue(debugFile); + parameters[whichParam(CLP_PARAM_ACTION_PRINTMASK, parameters)].setStringValue(printMask); + parameters[whichParam(CLP_PARAM_ACTION_DIRECTORY, parameters)].setStringValue(directory); + parameters[whichParam(CLP_PARAM_ACTION_DIRSAMPLE, parameters)].setStringValue(dirSample); + parameters[whichParam(CLP_PARAM_ACTION_DIRNETLIB, parameters)].setStringValue(dirNetlib); + parameters[whichParam(CBC_PARAM_ACTION_DIRMIPLIB, parameters)].setStringValue(dirMiplib); + parameters[whichParam(CLP_PARAM_DBL_DUALBOUND, parameters)].setDoubleValue(lpSolver->dualBound()); + parameters[whichParam(CLP_PARAM_DBL_DUALTOLERANCE, parameters)].setDoubleValue(lpSolver->dualTolerance()); + parameters[whichParam(CLP_PARAM_ACTION_EXPORT, parameters)].setStringValue(exportFile); + parameters[whichParam(CLP_PARAM_INT_IDIOT, parameters)].setIntValue(doIdiot); + parameters[whichParam(CLP_PARAM_ACTION_IMPORT, parameters)].setStringValue(importFile); + parameters[whichParam(CLP_PARAM_DBL_PRESOLVETOLERANCE, parameters)].setDoubleValue(1.0e-8); + int slog = whichParam(CLP_PARAM_INT_SOLVERLOGLEVEL, parameters); + int log = whichParam(CLP_PARAM_INT_LOGLEVEL, parameters); + parameters[slog].setIntValue(1); + clpSolver->messageHandler()->setLogLevel(1); + model.messageHandler()->setLogLevel(1); + lpSolver->setLogLevel(1); + parameters[log].setIntValue(1); + parameters[whichParam(CLP_PARAM_INT_MAXFACTOR, parameters)].setIntValue(lpSolver->factorizationFrequency()); + parameters[whichParam(CLP_PARAM_INT_MAXITERATION, parameters)].setIntValue(lpSolver->maximumIterations()); + parameters[whichParam(CLP_PARAM_INT_OUTPUTFORMAT, parameters)].setIntValue(outputFormat); + parameters[whichParam(CLP_PARAM_INT_PRESOLVEPASS, parameters)].setIntValue(preSolve); + parameters[whichParam(CLP_PARAM_INT_PERTVALUE, parameters)].setIntValue(lpSolver->perturbation()); + parameters[whichParam(CLP_PARAM_DBL_PRIMALTOLERANCE, parameters)].setDoubleValue(lpSolver->primalTolerance()); + parameters[whichParam(CLP_PARAM_DBL_PRIMALWEIGHT, parameters)].setDoubleValue(lpSolver->infeasibilityCost()); + parameters[whichParam(CLP_PARAM_ACTION_RESTORE, parameters)].setStringValue(restoreFile); + parameters[whichParam(CLP_PARAM_ACTION_SAVE, parameters)].setStringValue(saveFile); + //parameters[whichParam(CLP_PARAM_DBL_TIMELIMIT,numberParameters,parameters)].setDoubleValue(1.0e8); + parameters[whichParam(CBC_PARAM_DBL_TIMELIMIT_BAB, parameters)].setDoubleValue(1.0e8); + parameters[whichParam(CLP_PARAM_ACTION_SOLUTION, parameters)].setStringValue(solutionFile); + parameters[whichParam(CLP_PARAM_ACTION_NEXTBESTSOLUTION, parameters)].setStringValue(solutionFile); + parameters[whichParam(CLP_PARAM_ACTION_SAVESOL, parameters)].setStringValue(solutionSaveFile); + parameters[whichParam(CLP_PARAM_INT_SPRINT, parameters)].setIntValue(doSprint); + parameters[whichParam(CLP_PARAM_INT_SUBSTITUTION, parameters)].setIntValue(substitution); + parameters[whichParam(CLP_PARAM_INT_DUALIZE, parameters)].setIntValue(dualize); + model.setNumberBeforeTrust(10); + parameters[whichParam(CBC_PARAM_INT_NUMBERBEFORE, parameters)].setIntValue(5); + parameters[whichParam(CBC_PARAM_INT_MAXNODES, parameters)].setIntValue(model.getMaximumNodes()); + model.setNumberStrong(5); + parameters[whichParam(CBC_PARAM_INT_STRONGBRANCHING, parameters)].setIntValue(model.numberStrong()); + parameters[whichParam(CBC_PARAM_DBL_INFEASIBILITYWEIGHT, parameters)].setDoubleValue(model.getDblParam(CbcModel::CbcInfeasibilityWeight)); + parameters[whichParam(CBC_PARAM_DBL_INTEGERTOLERANCE, parameters)].setDoubleValue(model.getDblParam(CbcModel::CbcIntegerTolerance)); + parameters[whichParam(CBC_PARAM_DBL_INCREMENT, parameters)].setDoubleValue(model.getDblParam(CbcModel::CbcCutoffIncrement)); + parameters[whichParam(CBC_PARAM_INT_TESTOSI, parameters)].setIntValue(testOsiParameters); + parameters[whichParam(CBC_PARAM_INT_FPUMPTUNE, parameters)].setIntValue(1003); + initialPumpTune = 1003; +#ifdef CBC_THREAD + parameters[whichParam(CBC_PARAM_INT_THREADS, parameters)].setIntValue(0); +#endif + // Set up likely cut generators and defaults + parameters[whichParam(CBC_PARAM_STR_CLIQUECUTS, parameters)].setCurrentOption("ifmove"); + parameters[whichParam(CBC_PARAM_STR_ODDWHEELCUTS, parameters)].setCurrentOption("ifmove"); + parameters[whichParam(CBC_PARAM_STR_CLQSTRENGTHENING, parameters)].setCurrentOption("after"); + parameters[whichParam(CBC_PARAM_STR_USECGRAPH, parameters)].setCurrentOption("on"); + parameters[whichParam(CBC_PARAM_INT_BKPIVOTINGSTRATEGY, parameters)].setIntValue(3); + parameters[whichParam(CBC_PARAM_INT_BKMAXCALLS, parameters)].setIntValue(1000); + parameters[whichParam(CBC_PARAM_INT_BKCLQEXTMETHOD, parameters)].setIntValue(4); + parameters[whichParam(CBC_PARAM_INT_ODDWEXTMETHOD, parameters)].setIntValue(2); + parameters[whichParam(CBC_PARAM_STR_PREPROCESS, parameters)].setCurrentOption("sos"); + parameters[whichParam(CBC_PARAM_INT_MIPOPTIONS, parameters)].setIntValue(1057); + parameters[whichParam(CBC_PARAM_INT_CUTPASSINTREE, parameters)].setIntValue(1); + parameters[whichParam(CBC_PARAM_INT_MOREMIPOPTIONS, parameters)].setIntValue(-1); + parameters[whichParam(CBC_PARAM_INT_MAXHOTITS, parameters)].setIntValue(100); + parameters[whichParam(CBC_PARAM_STR_CUTSSTRATEGY, parameters)].setCurrentOption("on"); + parameters[whichParam(CBC_PARAM_STR_HEURISTICSTRATEGY, parameters)].setCurrentOption("on"); + parameters[whichParam(CBC_PARAM_STR_NODESTRATEGY, parameters)].setCurrentOption("fewest"); + parameters[whichParam(CBC_PARAM_STR_GOMORYCUTS, parameters)].setCurrentOption("ifmove"); + parameters[whichParam(CBC_PARAM_STR_PROBINGCUTS, parameters)].setCurrentOption("ifmove"); + parameters[whichParam(CBC_PARAM_STR_KNAPSACKCUTS, parameters)].setCurrentOption("ifmove"); + parameters[whichParam(CBC_PARAM_STR_ZEROHALFCUTS, parameters)].setCurrentOption("ifmove"); + parameters[whichParam(CBC_PARAM_STR_REDSPLITCUTS, parameters)].setCurrentOption("off"); + parameters[whichParam(CBC_PARAM_STR_REDSPLIT2CUTS, parameters)].setCurrentOption("off"); + parameters[whichParam(CBC_PARAM_STR_GMICUTS, parameters)].setCurrentOption("off"); + parameters[whichParam(CBC_PARAM_STR_MIXEDCUTS, parameters)].setCurrentOption("ifmove"); + parameters[whichParam(CBC_PARAM_STR_FLOWCUTS, parameters)].setCurrentOption("ifmove"); + parameters[whichParam(CBC_PARAM_STR_TWOMIRCUTS, parameters)].setCurrentOption("root"); + parameters[whichParam(CBC_PARAM_STR_LANDPCUTS, parameters)].setCurrentOption("off"); + parameters[whichParam(CBC_PARAM_STR_RESIDCUTS, parameters)].setCurrentOption("off"); + parameters[whichParam(CBC_PARAM_STR_ROUNDING, parameters)].setCurrentOption("on"); + parameters[whichParam(CBC_PARAM_STR_FPUMP, parameters)].setCurrentOption("on"); + parameters[whichParam(CBC_PARAM_STR_GREEDY, parameters)].setCurrentOption("on"); + parameters[whichParam(CBC_PARAM_STR_COMBINE, parameters)].setCurrentOption("off"); + parameters[whichParam(CBC_PARAM_STR_CROSSOVER2, parameters)].setCurrentOption("off"); + parameters[whichParam(CBC_PARAM_STR_PIVOTANDCOMPLEMENT, parameters)].setCurrentOption("off"); + parameters[whichParam(CBC_PARAM_STR_PIVOTANDFIX, parameters)].setCurrentOption("off"); + parameters[whichParam(CBC_PARAM_STR_RANDROUND, parameters)].setCurrentOption("off"); + parameters[whichParam(CBC_PARAM_STR_NAIVE, parameters)].setCurrentOption("off"); + parameters[whichParam(CBC_PARAM_STR_RINS, parameters)].setCurrentOption("off"); + parameters[whichParam(CBC_PARAM_STR_DINS, parameters)].setCurrentOption("off"); + parameters[whichParam(CBC_PARAM_STR_RENS, parameters)].setCurrentOption("off"); + parameters[whichParam(CBC_PARAM_STR_LOCALTREE, parameters)].setCurrentOption("off"); + parameters[whichParam(CBC_PARAM_STR_COSTSTRATEGY, parameters)].setCurrentOption("off"); +#ifdef CBC_HAS_NAUTY + parameters[whichParam(CBC_PARAM_STR_ORBITAL, parameters)].setCurrentOption("on"); +#endif +} + +/* + Routines to print statistics. +*/ +static void breakdown(const char *name, int numberLook, const double *region) +{ + double range[] = { + -COIN_DBL_MAX, + -1.0e15, -1.0e11, -1.0e8, -1.0e5, -1.0e4, -1.0e3, -1.0e2, -1.0e1, + -1.0, + -1.0e-1, -1.0e-2, -1.0e-3, -1.0e-4, -1.0e-5, -1.0e-8, -1.0e-11, -1.0e-15, + 0.0, + 1.0e-15, 1.0e-11, 1.0e-8, 1.0e-5, 1.0e-4, 1.0e-3, 1.0e-2, 1.0e-1, + 1.0, + 1.0e1, 1.0e2, 1.0e3, 1.0e4, 1.0e5, 1.0e8, 1.0e11, 1.0e15, + COIN_DBL_MAX + }; + int nRanges = static_cast< int >(sizeof(range) / sizeof(double)); + int *number = new int[nRanges]; + memset(number, 0, nRanges * sizeof(int)); + int *numberExact = new int[nRanges]; + memset(numberExact, 0, nRanges * sizeof(int)); + int i; + for (i = 0; i < numberLook; i++) { + double value = region[i]; + for (int j = 0; j < nRanges; j++) { + if (value == range[j]) { + numberExact[j]++; + break; + } else if (value < range[j]) { + number[j]++; + break; + } + } + } + printf("\n%s has %d entries\n", name, numberLook); + for (i = 0; i < nRanges; i++) { + if (number[i]) + printf("%d between %g and %g", number[i], range[i - 1], range[i]); + if (numberExact[i]) { + if (number[i]) + printf(", "); + printf("%d exactly at %g", numberExact[i], range[i]); + } + if (number[i] + numberExact[i]) + printf("\n"); + } + delete[] number; + delete[] numberExact; +} +static void sortOnOther(int *column, + const CoinBigIndex *rowStart, + int *order, + int *other, + int nRow, + int nInRow, + int where) +{ + if (nRow < 2 || where >= nInRow) + return; + // do initial sort + int kRow; + int iRow; + for (kRow = 0; kRow < nRow; kRow++) { + iRow = order[kRow]; + other[kRow] = column[rowStart[iRow] + where]; + } + CoinSort_2(other, other + nRow, order); + int first = 0; + iRow = order[0]; + int firstC = column[rowStart[iRow] + where]; + kRow = 1; + while (kRow < nRow) { + int lastC = 9999999; + ; + for (; kRow < nRow + 1; kRow++) { + if (kRow < nRow) { + iRow = order[kRow]; + lastC = column[rowStart[iRow] + where]; + } else { + lastC = 9999999; + } + if (lastC > firstC) + break; + } + // sort + sortOnOther(column, rowStart, order + first, other, kRow - first, + nInRow, where + 1); + firstC = lastC; + first = kRow; + } +} +static void statistics(ClpSimplex *originalModel, ClpSimplex *model) +{ + int numberColumns = originalModel->numberColumns(); + const char *integerInformation = originalModel->integerInformation(); + const double *columnLower = originalModel->columnLower(); + const double *columnUpper = originalModel->columnUpper(); + int numberIntegers = 0; + int numberBinary = 0; + int iRow, iColumn; + if (integerInformation) { + for (iColumn = 0; iColumn < numberColumns; iColumn++) { + if (integerInformation[iColumn]) { + if (columnUpper[iColumn] > columnLower[iColumn]) { + numberIntegers++; + if (columnLower[iColumn] == 0.0 && columnUpper[iColumn] == 1) + numberBinary++; + } + } + } + printf("Original problem has %d integers (%d of which binary)\n", + numberIntegers, numberBinary); + } + numberColumns = model->numberColumns(); + int numberRows = model->numberRows(); + columnLower = model->columnLower(); + columnUpper = model->columnUpper(); + const double *rowLower = model->rowLower(); + const double *rowUpper = model->rowUpper(); + const double *objective = model->objective(); + if (model->integerInformation()) { + const char *integerInformation = model->integerInformation(); + int numberIntegers = 0; + int numberBinary = 0; + double *obj = new double[numberColumns]; + int *which = new int[numberColumns]; + for (int iColumn = 0; iColumn < numberColumns; iColumn++) { + if (columnUpper[iColumn] > columnLower[iColumn]) { + if (integerInformation[iColumn]) { + numberIntegers++; + if (columnLower[iColumn] == 0.0 && columnUpper[iColumn] == 1) + numberBinary++; + } + } + } + if (numberColumns != originalModel->numberColumns()) + printf("Presolved problem has %d integers (%d of which binary)\n", + numberIntegers, numberBinary); + for (int ifInt = 0; ifInt < 2; ifInt++) { + for (int ifAbs = 0; ifAbs < 2; ifAbs++) { + int numberSort = 0; + int numberZero = 0; + int numberDifferentObj = 0; + for (int iColumn = 0; iColumn < numberColumns; iColumn++) { + if (columnUpper[iColumn] > columnLower[iColumn]) { + if (!ifInt || integerInformation[iColumn]) { + obj[numberSort] = (ifAbs) ? fabs(objective[iColumn]) : objective[iColumn]; + which[numberSort++] = iColumn; + if (!objective[iColumn]) + numberZero++; + } + } + } + CoinSort_2(obj, obj + numberSort, which); + double last = obj[0]; + for (int jColumn = 1; jColumn < numberSort; jColumn++) { + if (fabs(obj[jColumn] - last) > 1.0e-12) { + numberDifferentObj++; + last = obj[jColumn]; + } + } + numberDifferentObj++; + printf("==== "); + if (ifInt) + printf("for integers "); + if (!ifAbs) + printf("%d zero objective ", numberZero); + else + printf("absolute objective values "); + printf("%d different\n", numberDifferentObj); + bool saveModel = false; + int target = model->logLevel(); + if (target > 10000) { + if (ifInt && !ifAbs) + saveModel = true; + target -= 10000; + } + + if (target <= 100) + target = 12; + else + target -= 100; + if (numberDifferentObj < target) { + int iLast = 0; + double last = obj[0]; + for (int jColumn = 1; jColumn < numberSort; jColumn++) { + if (fabs(obj[jColumn] - last) > 1.0e-12) { + printf("%d variables have objective of %g\n", + jColumn - iLast, last); + iLast = jColumn; + last = obj[jColumn]; + } + } + printf("%d variables have objective of %g\n", + numberSort - iLast, last); + if (saveModel) { + int spaceNeeded = numberSort + numberDifferentObj; + CoinBigIndex *columnAddDummy = new CoinBigIndex[numberDifferentObj + 1]; + int *columnAdd = new int[spaceNeeded]; + double *elementAdd = new double[spaceNeeded]; + CoinBigIndex *rowAdd = new CoinBigIndex[2 * numberDifferentObj + 1]; + int *newIsInteger = reinterpret_cast< int * >(rowAdd + numberDifferentObj + 1); + double *objectiveNew = new double[3 * numberDifferentObj]; + double *lowerNew = objectiveNew + numberDifferentObj; + double *upperNew = lowerNew + numberDifferentObj; + memset(columnAddDummy, 0, + (numberDifferentObj + 1) * sizeof(CoinBigIndex)); + ClpSimplex tempModel = *model; + int iLast = 0; + double last = obj[0]; + numberDifferentObj = 0; + int numberElements = 0; + rowAdd[0] = 0; + double *objective = tempModel.objective(); + for (int jColumn = 1; jColumn < numberSort + 1; jColumn++) { + if (jColumn == numberSort || fabs(obj[jColumn] - last) > 1.0e-12) { + // not if just one + if (jColumn - iLast > 1) { + bool allInteger = integerInformation != NULL; + int iColumn = which[iLast]; + objectiveNew[numberDifferentObj] = objective[iColumn]; + double lower = 0.0; + double upper = 0.0; + for (int kColumn = iLast; kColumn < jColumn; kColumn++) { + iColumn = which[kColumn]; + objective[iColumn] = 0.0; + double lowerValue = columnLower[iColumn]; + double upperValue = columnUpper[iColumn]; + double elementValue = -1.0; + if (objectiveNew[numberDifferentObj] * objective[iColumn] < 0.0) { + lowerValue = -columnUpper[iColumn]; + upperValue = -columnLower[iColumn]; + elementValue = 1.0; + } + columnAdd[numberElements] = iColumn; + elementAdd[numberElements++] = elementValue; + if (integerInformation && !integerInformation[iColumn]) + allInteger = false; + if (lower != -COIN_DBL_MAX) { + if (lowerValue != -COIN_DBL_MAX) + lower += lowerValue; + else + lower = -COIN_DBL_MAX; + } + if (upper != COIN_DBL_MAX) { + if (upperValue != COIN_DBL_MAX) + upper += upperValue; + else + upper = COIN_DBL_MAX; + } + } + columnAdd[numberElements] = numberColumns + numberDifferentObj; + elementAdd[numberElements++] = 1.0; + newIsInteger[numberDifferentObj] = (allInteger) ? 1 : 0; + lowerNew[numberDifferentObj] = lower; + upperNew[numberDifferentObj] = upper; + numberDifferentObj++; + rowAdd[numberDifferentObj] = numberElements; + } + iLast = jColumn; + last = obj[jColumn]; + } + } + // add columns + tempModel.addColumns(numberDifferentObj, lowerNew, upperNew, + objectiveNew, + columnAddDummy, NULL, NULL); + // add constraints and make integer if all integer in group + for (int iObj = 0; iObj < numberDifferentObj; iObj++) { + lowerNew[iObj] = 0.0; + upperNew[iObj] = 0.0; + if (newIsInteger[iObj]) + tempModel.setInteger(numberColumns + iObj); + } + tempModel.addRows(numberDifferentObj, lowerNew, upperNew, + rowAdd, columnAdd, elementAdd); + delete[] columnAdd; + delete[] columnAddDummy; + delete[] elementAdd; + delete[] rowAdd; + delete[] objectiveNew; + // save + std::string tempName = model->problemName(); + if (ifInt) + tempName += "_int"; + if (ifAbs) + tempName += "_abs"; + tempName += ".mps"; + tempModel.writeMps(tempName.c_str()); + } + } + } + } + delete[] which; + delete[] obj; + printf("===== end objective counts\n"); + } + CoinPackedMatrix *matrix = model->matrix(); + CoinBigIndex numberElements = matrix->getNumElements(); + const int *columnLength = matrix->getVectorLengths(); + //const CoinBigIndex * columnStart = matrix->getVectorStarts(); + const double *elementByColumn = matrix->getElements(); + int *number = new int[numberRows + 1]; + memset(number, 0, (numberRows + 1) * sizeof(int)); + int numberObjSingletons = 0; + /* cType + 0 0/inf, 1 0/up, 2 lo/inf, 3 lo/up, 4 free, 5 fix, 6 -inf/0, 7 -inf/up, + 8 0/1 + */ + int cType[9]; + std::string cName[] = { "0.0->inf,", "0.0->up,", "lo->inf,", "lo->up,", "free,", "fixed,", "-inf->0.0,", + "-inf->up,", "0.0->1.0" }; + int nObjective = 0; + memset(cType, 0, sizeof(cType)); + for (iColumn = 0; iColumn < numberColumns; iColumn++) { + int length = columnLength[iColumn]; + if (length == 1 && objective[iColumn]) + numberObjSingletons++; + number[length]++; + if (objective[iColumn]) + nObjective++; + if (columnLower[iColumn] > -1.0e20) { + if (columnLower[iColumn] == 0.0) { + if (columnUpper[iColumn] > 1.0e20) + cType[0]++; + else if (columnUpper[iColumn] == 1.0) + cType[8]++; + else if (columnUpper[iColumn] == 0.0) + cType[5]++; + else + cType[1]++; + } else { + if (columnUpper[iColumn] > 1.0e20) + cType[2]++; + else if (columnUpper[iColumn] == columnLower[iColumn]) + cType[5]++; + else + cType[3]++; + } + } else { + if (columnUpper[iColumn] > 1.0e20) + cType[4]++; + else if (columnUpper[iColumn] == 0.0) + cType[6]++; + else + cType[7]++; + } + } + /* rType + 0 E 0, 1 E 1, 2 E -1, 3 E other, 4 G 0, 5 G 1, 6 G other, + 7 L 0, 8 L 1, 9 L other, 10 Range 0/1, 11 Range other, 12 free + */ + int rType[13]; + std::string rName[] = { "E 0.0,", "E 1.0,", "E -1.0,", "E other,", "G 0.0,", "G 1.0,", "G other,", + "L 0.0,", "L 1.0,", "L other,", "Range 0.0->1.0,", "Range other,", "Free" }; + memset(rType, 0, sizeof(rType)); + for (iRow = 0; iRow < numberRows; iRow++) { + if (rowLower[iRow] > -1.0e20) { + if (rowLower[iRow] == 0.0) { + if (rowUpper[iRow] > 1.0e20) + rType[4]++; + else if (rowUpper[iRow] == 1.0) + rType[10]++; + else if (rowUpper[iRow] == 0.0) + rType[0]++; + else + rType[11]++; + } else if (rowLower[iRow] == 1.0) { + if (rowUpper[iRow] > 1.0e20) + rType[5]++; + else if (rowUpper[iRow] == rowLower[iRow]) + rType[1]++; + else + rType[11]++; + } else if (rowLower[iRow] == -1.0) { + if (rowUpper[iRow] > 1.0e20) + rType[6]++; + else if (rowUpper[iRow] == rowLower[iRow]) + rType[2]++; + else + rType[11]++; + } else { + if (rowUpper[iRow] > 1.0e20) + rType[6]++; + else if (rowUpper[iRow] == rowLower[iRow]) + rType[3]++; + else + rType[11]++; + } + } else { + if (rowUpper[iRow] > 1.0e20) + rType[12]++; + else if (rowUpper[iRow] == 0.0) + rType[7]++; + else if (rowUpper[iRow] == 1.0) + rType[8]++; + else + rType[9]++; + } + } + // Basic statistics + printf("\n\nProblem has %d rows, %d columns (%d with objective) and %d elements\n", + numberRows, numberColumns, nObjective, numberElements); + if (number[0] + number[1]) { + printf("There are "); + if (numberObjSingletons) + printf("%d singletons with objective ", numberObjSingletons); + int numberNoObj = number[1] - numberObjSingletons; + if (numberNoObj) + printf("%d singletons with no objective ", numberNoObj); + if (number[0]) + printf("** %d columns have no entries", number[0]); + printf("\n"); + } + printf("Column breakdown:\n"); + int k; + for (k = 0; k < static_cast< int >(sizeof(cType) / sizeof(int)); k++) { + printf("%d of type %s ", cType[k], cName[k].c_str()); + if (((k + 1) % 3) == 0) + printf("\n"); + } + if ((k % 3) != 0) + printf("\n"); + printf("Row breakdown:\n"); + for (k = 0; k < static_cast< int >(sizeof(rType) / sizeof(int)); k++) { + printf("%d of type %s ", rType[k], rName[k].c_str()); + if (((k + 1) % 3) == 0) + printf("\n"); + } + if ((k % 3) != 0) + printf("\n"); + //#define SYM +#ifndef SYM + if (model->logLevel() < 2) + return; +#endif + int kMax = model->logLevel() > 3 ? 1000000 : 10; + k = 0; + for (iRow = 1; iRow <= numberRows; iRow++) { + if (number[iRow]) { + k++; + printf("%d columns have %d entries\n", number[iRow], iRow); + if (k == kMax) + break; + } + } + if (k < numberRows) { + int kk = k; + k = 0; + for (iRow = numberRows; iRow >= 1; iRow--) { + if (number[iRow]) { + k++; + if (k == kMax) + break; + } + } + if (k > kk) { + printf("\n .........\n\n"); + iRow = k; + k = 0; + for (; iRow < numberRows; iRow++) { + if (number[iRow]) { + k++; + printf("%d columns have %d entries\n", number[iRow], iRow); + if (k == kMax) + break; + } + } + } + } + delete[] number; + printf("\n\n"); + if (model->logLevel() == 63 +#ifdef SYM + || true +#endif + ) { + // get column copy + CoinPackedMatrix columnCopy = *matrix; + const int *columnLength = columnCopy.getVectorLengths(); + number = new int[numberRows + 1]; + memset(number, 0, (numberRows + 1) * sizeof(int)); + for (iColumn = 0; iColumn < numberColumns; iColumn++) { + int length = columnLength[iColumn]; + number[length]++; + } + k = 0; + for (iRow = 1; iRow <= numberRows; iRow++) { + if (number[iRow]) { + k++; + } + } + int *row = columnCopy.getMutableIndices(); + const CoinBigIndex *columnStart = columnCopy.getVectorStarts(); + double *element = columnCopy.getMutableElements(); + int *order = new int[numberColumns]; + int *other = new int[numberColumns]; + for (iColumn = 0; iColumn < numberColumns; iColumn++) { + int length = columnLength[iColumn]; + order[iColumn] = iColumn; + other[iColumn] = length; + CoinBigIndex start = columnStart[iColumn]; + CoinSort_2(row + start, row + start + length, element + start); + } + CoinSort_2(other, other + numberColumns, order); + int jColumn = number[0] + number[1]; + for (iRow = 2; iRow <= numberRows; iRow++) { + if (number[iRow]) { + printf("XX %d columns have %d entries\n", number[iRow], iRow); + int kColumn = jColumn + number[iRow]; + sortOnOther(row, columnStart, + order + jColumn, other, number[iRow], iRow, 0); + // Now print etc + if (iRow < 500000) { + for (int lColumn = jColumn; lColumn < kColumn; lColumn++) { + iColumn = order[lColumn]; + CoinBigIndex start = columnStart[iColumn]; + if (model->logLevel() == 63) { + printf("column %d %g <= ", iColumn, columnLower[iColumn]); + for (CoinBigIndex i = start; i < start + iRow; i++) + printf("( %d, %g) ", row[i], element[i]); + printf("<= %g\n", columnUpper[iColumn]); + } + } + } + jColumn = kColumn; + } + } + delete[] order; + delete[] other; + delete[] number; + } + // get row copy + CoinPackedMatrix rowCopy = *matrix; + rowCopy.reverseOrdering(); + const int *rowLength = rowCopy.getVectorLengths(); + number = new int[numberColumns + 1]; + memset(number, 0, (numberColumns + 1) * sizeof(int)); + if (model->logLevel() > 3) { + // get column copy + CoinPackedMatrix columnCopy = *matrix; + const int *columnLength = columnCopy.getVectorLengths(); + const int *row = columnCopy.getIndices(); + const CoinBigIndex *columnStart = columnCopy.getVectorStarts(); + const double *element = columnCopy.getElements(); + const double *elementByRow = rowCopy.getElements(); + const CoinBigIndex *rowStart = rowCopy.getVectorStarts(); + const int *column = rowCopy.getIndices(); + int nPossibleZeroCost = 0; + int nPossibleNonzeroCost = 0; + for (int iColumn = 0; iColumn < numberColumns; iColumn++) { + int length = columnLength[iColumn]; + if (columnLower[iColumn] < -1.0e30 && columnUpper[iColumn] > 1.0e30) { + if (length == 1) { + printf("Singleton free %d - cost %g\n", iColumn, objective[iColumn]); + } else if (length == 2) { + int iRow0 = row[columnStart[iColumn]]; + int iRow1 = row[columnStart[iColumn] + 1]; + double element0 = element[columnStart[iColumn]]; + double element1 = element[columnStart[iColumn] + 1]; + int n0 = rowLength[iRow0]; + int n1 = rowLength[iRow1]; + printf("Doubleton free %d - cost %g - %g in %srow with %d entries and %g in %srow with %d entries\n", + iColumn, objective[iColumn], element0, (rowLower[iRow0] == rowUpper[iRow0]) ? "==" : "", n0, + element1, (rowLower[iRow1] == rowUpper[iRow1]) ? "==" : "", n1); + } + } + if (length == 1) { + int iRow = row[columnStart[iColumn]]; + double value = COIN_DBL_MAX; + for (CoinBigIndex i = rowStart[iRow]; i < rowStart[iRow] + rowLength[iRow]; i++) { + int jColumn = column[i]; + if (jColumn != iColumn) { + if (value != elementByRow[i]) { + if (value == COIN_DBL_MAX) { + value = elementByRow[i]; + } else { + value = -COIN_DBL_MAX; + break; + } + } + } + } + if (!objective[iColumn]) { + if (model->logLevel() > 4) + printf("Singleton %d with no objective in row with %d elements - rhs %g,%g\n", iColumn, rowLength[iRow], rowLower[iRow], rowUpper[iRow]); + nPossibleZeroCost++; + } else if (value != -COIN_DBL_MAX) { + if (model->logLevel() > 4) + printf("Singleton %d (%s) with objective in row %d (%s) with %d equal elements - rhs %g,%g\n", iColumn, model->getColumnName(iColumn).c_str(), + iRow, model->getRowName(iRow).c_str(), + rowLength[iRow], rowLower[iRow], rowUpper[iRow]); + nPossibleNonzeroCost++; + } + } + } + if (nPossibleZeroCost || nPossibleNonzeroCost) + printf("%d singletons with zero cost, %d with valid cost\n", + nPossibleZeroCost, nPossibleNonzeroCost); + // look for DW + int *blockStart = new int[2 * (numberRows + numberColumns) + 1 + numberRows]; + int *columnBlock = blockStart + numberRows; + int *nextColumn = columnBlock + numberColumns; + int *blockCount = nextColumn + numberColumns; + int *blockEls = blockCount + numberRows + 1; + int direction[2] = { -1, 1 }; + int bestBreak = -1; + double bestValue = 0.0; + int iPass = 0; + int halfway = (numberRows + 1) / 2; + int firstMaster = -1; + int lastMaster = -2; + while (iPass < 2) { + int increment = direction[iPass]; + int start = increment > 0 ? 0 : numberRows - 1; + int stop = increment > 0 ? numberRows : -1; + int numberBlocks = 0; + int thisBestBreak = -1; + double thisBestValue = COIN_DBL_MAX; + int numberRowsDone = 0; + int numberMarkedColumns = 0; + int maximumBlockSize = 0; + for (int i = 0; i < numberRows + 2 * numberColumns; i++) + blockStart[i] = -1; + for (int i = 0; i < numberRows + 1; i++) + blockCount[i] = 0; + for (int iRow = start; iRow != stop; iRow += increment) { + int iBlock = -1; + for (CoinBigIndex j = rowStart[iRow]; j < rowStart[iRow] + rowLength[iRow]; j++) { + int iColumn = column[j]; + int whichColumnBlock = columnBlock[iColumn]; + if (whichColumnBlock >= 0) { + // column marked + if (iBlock < 0) { + // put row in that block + iBlock = whichColumnBlock; + } else if (iBlock != whichColumnBlock) { + // merge + blockCount[iBlock] += blockCount[whichColumnBlock]; + blockCount[whichColumnBlock] = 0; + int jColumn = blockStart[whichColumnBlock]; + while (jColumn >= 0) { + columnBlock[jColumn] = iBlock; + iColumn = jColumn; + jColumn = nextColumn[jColumn]; + } + nextColumn[iColumn] = blockStart[iBlock]; + blockStart[iBlock] = blockStart[whichColumnBlock]; + blockStart[whichColumnBlock] = -1; + } + } + } + int n = numberMarkedColumns; + if (iBlock < 0) { + //new block + if (rowLength[iRow]) { + numberBlocks++; + iBlock = numberBlocks; + int jColumn = column[rowStart[iRow]]; + columnBlock[jColumn] = iBlock; + blockStart[iBlock] = jColumn; + numberMarkedColumns++; + for (CoinBigIndex j = rowStart[iRow] + 1; j < rowStart[iRow] + rowLength[iRow]; j++) { + int iColumn = column[j]; + columnBlock[iColumn] = iBlock; + numberMarkedColumns++; + nextColumn[jColumn] = iColumn; + jColumn = iColumn; + } + blockCount[iBlock] = numberMarkedColumns - n; + } else { + // empty + iBlock = numberRows; + } + } else { + // put in existing block + int jColumn = blockStart[iBlock]; + for (CoinBigIndex j = rowStart[iRow]; j < rowStart[iRow] + rowLength[iRow]; j++) { + int iColumn = column[j]; + assert(columnBlock[iColumn] < 0 || columnBlock[iColumn] == iBlock); + if (columnBlock[iColumn] < 0) { + columnBlock[iColumn] = iBlock; + numberMarkedColumns++; + nextColumn[iColumn] = jColumn; + jColumn = iColumn; + } + } + blockStart[iBlock] = jColumn; + blockCount[iBlock] += numberMarkedColumns - n; + } + maximumBlockSize = CoinMax(maximumBlockSize, blockCount[iBlock]); + numberRowsDone++; + if (thisBestValue * numberRowsDone > maximumBlockSize && numberRowsDone > halfway) { + thisBestBreak = iRow; + thisBestValue = static_cast< double >(maximumBlockSize) / static_cast< double >(numberRowsDone); + } + } + if (thisBestBreak == stop) + thisBestValue = COIN_DBL_MAX; + iPass++; + if (iPass == 1) { + bestBreak = thisBestBreak; + bestValue = thisBestValue; + } else { + if (bestValue < thisBestValue) { + firstMaster = 0; + lastMaster = bestBreak; + } else { + firstMaster = thisBestBreak; // ? +1 + lastMaster = numberRows; + } + } + } + if (firstMaster < lastMaster) { + printf("%d master rows %d <= < %d\n", lastMaster - firstMaster, + firstMaster, lastMaster); + for (int i = 0; i < numberRows + 2 * numberColumns; i++) + blockStart[i] = -1; + for (int i = firstMaster; i < lastMaster; i++) + blockStart[i] = -2; + int firstRow = 0; + int numberBlocks = -1; + while (true) { + for (; firstRow < numberRows; firstRow++) { + if (blockStart[firstRow] == -1) + break; + } + if (firstRow == numberRows) + break; + int nRows = 0; + numberBlocks++; + int numberStack = 1; + blockCount[0] = firstRow; + while (numberStack) { + int iRow = blockCount[--numberStack]; + for (CoinBigIndex j = rowStart[iRow]; j < rowStart[iRow] + rowLength[iRow]; j++) { + int iColumn = column[j]; + int iBlock = columnBlock[iColumn]; + if (iBlock < 0) { + columnBlock[iColumn] = numberBlocks; + for (CoinBigIndex k = columnStart[iColumn]; + k < columnStart[iColumn] + columnLength[iColumn]; k++) { + int jRow = row[k]; + int rowBlock = blockStart[jRow]; + if (rowBlock == -1) { + nRows++; + blockStart[jRow] = numberBlocks; + blockCount[numberStack++] = jRow; + } + } + } + } + } + if (!nRows) { + // empty!! + numberBlocks--; + } + firstRow++; + } + // adjust + numberBlocks++; + for (int i = 0; i < numberBlocks; i++) { + blockCount[i] = 0; + nextColumn[i] = 0; + } + int numberEmpty = 0; + int numberMaster = 0; + memset(blockEls, 0, numberBlocks * sizeof(int)); + for (int iRow = 0; iRow < numberRows; iRow++) { + int iBlock = blockStart[iRow]; + if (iBlock >= 0) { + blockCount[iBlock]++; + blockEls[iBlock] += rowLength[iRow]; + } else { + if (iBlock == -2) + numberMaster++; + else + numberEmpty++; + } + } + int numberEmptyColumns = 0; + int numberMasterColumns = 0; + for (int iColumn = 0; iColumn < numberColumns; iColumn++) { + int iBlock = columnBlock[iColumn]; + if (iBlock >= 0) { + nextColumn[iBlock]++; + } else { + if (columnLength[iColumn]) + numberMasterColumns++; + else + numberEmptyColumns++; + } + } + int largestRows = 0; + int largestColumns = 0; + for (int i = 0; i < numberBlocks; i++) { + if (blockCount[i] + nextColumn[i] > largestRows + largestColumns) { + largestRows = blockCount[i]; + largestColumns = nextColumn[i]; + } + } + bool useful = true; + if (numberMaster > halfway || largestRows * 3 > numberRows) + useful = false; + printf("%s %d blocks (largest %d,%d), %d master rows (%d empty) out of %d, %d master columns (%d empty) out of %d\n", + useful ? "**Useful" : "NoGood", + numberBlocks, largestRows, largestColumns, numberMaster, numberEmpty, numberRows, + numberMasterColumns, numberEmptyColumns, numberColumns); + FILE *fp = NULL; + bool justIntegers = true; + bool oneFile = true; + int logLevel = model->logLevel(); + if (logLevel > 19) { + logLevel -= 2; + oneFile = true; + fp = fopen("fake.bnd", "w"); + } + if (logLevel == 19) + justIntegers = false; + for (int i = 0; i < numberBlocks; i++) + printf("Block %d has %d rows and %d columns (%d elements)\n", + i, blockCount[i], nextColumn[i], blockEls[i]); + if (logLevel >= 17 && logLevel <= 21) { + int *whichRows = new int[numberRows + numberColumns]; + int *whichColumns = whichRows + numberRows; + char name[20]; + for (int iBlock = 0; iBlock < numberBlocks; iBlock++) { + sprintf(name, "block%d.mps", iBlock); + int nRows = 0; + for (int iRow = 0; iRow < numberRows; iRow++) { + if (blockStart[iRow] == iBlock) + whichRows[nRows++] = iRow; + } + int nColumns = 0; + for (int iColumn = 0; iColumn < numberColumns; iColumn++) { + if (columnBlock[iColumn] == iBlock) + whichColumns[nColumns++] = iColumn; + } + ClpSimplex subset(model, nRows, whichRows, nColumns, whichColumns); + for (int jRow = 0; jRow < nRows; jRow++) { + int iRow = whichRows[jRow]; + std::string name = model->getRowName(iRow); + subset.setRowName(jRow, name); + } + int nInteger = 0; + for (int jColumn = 0; jColumn < nColumns; jColumn++) { + int iColumn = whichColumns[jColumn]; + if (model->isInteger(iColumn)) { + subset.setInteger(jColumn); + nInteger++; + } + std::string name = model->getColumnName(iColumn); + subset.setColumnName(jColumn, name); + } + if (logLevel == 17) { + subset.writeMps(name, 0, 1); + } else if (nInteger) { + OsiClpSolverInterface subset2(&subset); + CbcModel smallModel(subset2); + smallModel.branchAndBound(); + const double *solution = smallModel.bestSolution(); + if (solution) { + if (!oneFile) { + sprintf(name, "block%d.bnd", iBlock); + fp = fopen(name, "w"); + assert(fp); + } + fprintf(fp, "BBB objective %g for block %d\n", + smallModel.getObjValue(), iBlock); + for (int jColumn = 0; jColumn < nColumns; jColumn++) { + if (subset.isInteger(jColumn) || !justIntegers) + fprintf(fp, " FX BOUND1 %.8s %g\n", + subset.getColumnName(jColumn).c_str(), + solution[jColumn]); + } + if (!oneFile) + fclose(fp); + } else { + printf("***** Problem is infeasible\n"); + abort(); + } + } + } + if (oneFile) + fclose(fp); + delete[] whichRows; + } + } + delete[] blockStart; + } + for (iRow = 0; iRow < numberRows; iRow++) { + int length = rowLength[iRow]; + number[length]++; + } + if (number[0]) + printf("** %d rows have no entries\n", number[0]); + k = 0; + for (iColumn = 1; iColumn <= numberColumns; iColumn++) { + if (number[iColumn]) { + k++; + printf("%d rows have %d entries\n", number[iColumn], iColumn); + if (k == kMax) + break; + } + } + if (k < numberColumns) { + int kk = k; + k = 0; + for (iColumn = numberColumns; iColumn >= 1; iColumn--) { + if (number[iColumn]) { + k++; + if (k == kMax) + break; + } + } + if (k > kk) { + printf("\n .........\n\n"); + iColumn = k; + k = 0; + for (; iColumn < numberColumns; iColumn++) { + if (number[iColumn]) { + k++; + printf("%d rows have %d entries\n", number[iColumn], iColumn); + if (k == kMax) + break; + } + } + } + } + if (model->logLevel() == 63 +#ifdef SYM + || true +#endif + ) { + int *column = rowCopy.getMutableIndices(); + const CoinBigIndex *rowStart = rowCopy.getVectorStarts(); + double *element = rowCopy.getMutableElements(); + int *order = new int[numberRows]; + int *other = new int[numberRows]; + for (iRow = 0; iRow < numberRows; iRow++) { + int length = rowLength[iRow]; + order[iRow] = iRow; + other[iRow] = length; + CoinBigIndex start = rowStart[iRow]; + CoinSort_2(column + start, column + start + length, element + start); + } + CoinSort_2(other, other + numberRows, order); + int jRow = number[0] + number[1]; + double *weight = new double[numberRows]; + double *randomColumn = new double[numberColumns + 1]; + double *randomRow = new double[numberRows + 1]; + int *sortRow = new int[numberRows]; + int *possibleRow = new int[numberRows]; + int *backRow = new int[numberRows]; + int *stackRow = new int[numberRows]; + int *sortColumn = new int[numberColumns]; + int *possibleColumn = new int[numberColumns]; + int *backColumn = new int[numberColumns]; + int *backColumn2 = new int[numberColumns]; + int *mapRow = new int[numberRows]; + int *mapColumn = new int[numberColumns]; + int *stackColumn = new int[numberColumns]; + double randomLower = CoinDrand48(); + double randomUpper = CoinDrand48(); + double randomInteger = CoinDrand48(); + CoinBigIndex *startAdd = new CoinBigIndex[numberRows + 1]; + int *columnAdd = new int[2 * numberElements]; + double *elementAdd = new double[2 * numberElements]; + int nAddRows = 0; + startAdd[0] = 0; + for (iColumn = 0; iColumn < numberColumns; iColumn++) { + randomColumn[iColumn] = CoinDrand48(); + backColumn2[iColumn] = -1; + } + for (iColumn = 2; iColumn <= numberColumns; iColumn++) { + if (number[iColumn]) { + printf("XX %d rows have %d entries\n", number[iColumn], iColumn); + int kRow = jRow + number[iColumn]; + sortOnOther(column, rowStart, + order + jRow, other, number[iColumn], iColumn, 0); + // Now print etc + if (iColumn < 500000) { + int nLook = 0; + for (int lRow = jRow; lRow < kRow; lRow++) { + iRow = order[lRow]; + CoinBigIndex start = rowStart[iRow]; + if (model->logLevel() == 63) { + printf("row %d %g <= ", iRow, rowLower[iRow]); + for (CoinBigIndex i = start; i < start + iColumn; i++) + printf("( %d, %g) ", column[i], element[i]); + printf("<= %g\n", rowUpper[iRow]); + } + int first = column[start]; + double sum = 0.0; + for (CoinBigIndex i = start; i < start + iColumn; i++) { + int jColumn = column[i]; + double value = element[i]; + jColumn -= first; + assert(jColumn >= 0); + sum += value * randomColumn[jColumn]; + } + if (rowLower[iRow] > -1.0e30 && rowLower[iRow]) + sum += rowLower[iRow] * randomLower; + else if (!rowLower[iRow]) + sum += 1.234567e-7 * randomLower; + if (rowUpper[iRow] < 1.0e30 && rowUpper[iRow]) + sum += rowUpper[iRow] * randomUpper; + else if (!rowUpper[iRow]) + sum += 1.234567e-7 * randomUpper; + sortRow[nLook] = iRow; + randomRow[nLook++] = sum; + // best way is to number unique elements and bounds and use + if (fabs(sum) > 1.0e4) + sum *= 1.0e-6; + weight[iRow] = sum; + } + assert(nLook <= numberRows); + CoinSort_2(randomRow, randomRow + nLook, sortRow); + randomRow[nLook] = COIN_DBL_MAX; + double last = -COIN_DBL_MAX; + int iLast = -1; + for (int iLook = 0; iLook < nLook + 1; iLook++) { + if (randomRow[iLook] > last) { + if (iLast >= 0) { + int n = iLook - iLast; + if (n > 1) { + //printf("%d rows possible?\n",n); + } + } + iLast = iLook; + last = randomRow[iLook]; + } + } + } + jRow = kRow; + } + } + CoinPackedMatrix columnCopy = *matrix; + const int *columnLength = columnCopy.getVectorLengths(); + const int *row = columnCopy.getIndices(); + const CoinBigIndex *columnStart = columnCopy.getVectorStarts(); + const double *elementByColumn = columnCopy.getElements(); + for (iColumn = 0; iColumn < numberColumns; iColumn++) { + int length = columnLength[iColumn]; + CoinBigIndex start = columnStart[iColumn]; + double sum = objective[iColumn]; + if (columnLower[iColumn] > -1.0e30 && columnLower[iColumn]) + sum += columnLower[iColumn] * randomLower; + else if (!columnLower[iColumn]) + sum += 1.234567e-7 * randomLower; + if (columnUpper[iColumn] < 1.0e30 && columnUpper[iColumn]) + sum += columnUpper[iColumn] * randomUpper; + else if (!columnUpper[iColumn]) + sum += 1.234567e-7 * randomUpper; + if (model->isInteger(iColumn)) + sum += 9.87654321e-6 * randomInteger; + for (CoinBigIndex i = start; i < start + length; i++) { + int iRow = row[i]; + sum += elementByColumn[i] * weight[iRow]; + } + sortColumn[iColumn] = iColumn; + randomColumn[iColumn] = sum; + } + { + CoinSort_2(randomColumn, randomColumn + numberColumns, sortColumn); + for (iColumn = 0; iColumn < numberColumns; iColumn++) { + int i = sortColumn[iColumn]; + backColumn[i] = iColumn; + } + randomColumn[numberColumns] = COIN_DBL_MAX; + double last = -COIN_DBL_MAX; + int iLast = -1; + for (int iLook = 0; iLook < numberColumns + 1; iLook++) { + if (randomColumn[iLook] > last) { + if (iLast >= 0) { + int n = iLook - iLast; + if (n > 1) { + //printf("%d columns possible?\n",n); + } + for (int i = iLast; i < iLook; i++) { + possibleColumn[sortColumn[i]] = n; + } + } + iLast = iLook; + last = randomColumn[iLook]; + } + } + for (iRow = 0; iRow < numberRows; iRow++) { + CoinBigIndex start = rowStart[iRow]; + double sum = 0.0; + int length = rowLength[iRow]; + for (CoinBigIndex i = start; i < start + length; i++) { + int jColumn = column[i]; + double value = element[i]; + jColumn = backColumn[jColumn]; + sum += value * randomColumn[jColumn]; + //if (iColumn==23089||iRow==23729) + //printf("row %d cola %d colb %d value %g rand %g sum %g\n", + // iRow,jColumn,column[i],value,randomColumn[jColumn],sum); + } + sortRow[iRow] = iRow; + randomRow[iRow] = weight[iRow]; + randomRow[iRow] = sum; + } + CoinSort_2(randomRow, randomRow + numberRows, sortRow); + for (iRow = 0; iRow < numberRows; iRow++) { + int i = sortRow[iRow]; + backRow[i] = iRow; + } + randomRow[numberRows] = COIN_DBL_MAX; + last = -COIN_DBL_MAX; + iLast = -1; + // Do backward indices from order + for (iRow = 0; iRow < numberRows; iRow++) { + other[order[iRow]] = iRow; + } + for (int iLook = 0; iLook < numberRows + 1; iLook++) { + if (randomRow[iLook] > last) { + if (iLast >= 0) { + int n = iLook - iLast; + if (n > 1) { + //printf("%d rows possible?\n",n); + // Within group sort as for original "order" + for (int i = iLast; i < iLook; i++) { + int jRow = sortRow[i]; + order[i] = other[jRow]; + } + CoinSort_2(order + iLast, order + iLook, sortRow + iLast); + } + for (int i = iLast; i < iLook; i++) { + possibleRow[sortRow[i]] = n; + } + } + iLast = iLook; + last = randomRow[iLook]; + } + } + // Temp out + for (int iLook = 0; iLook < numberRows - 1000000; iLook++) { + iRow = sortRow[iLook]; + CoinBigIndex start = rowStart[iRow]; + int length = rowLength[iRow]; + int numberPossible = possibleRow[iRow]; + for (CoinBigIndex i = start; i < start + length; i++) { + int jColumn = column[i]; + if (possibleColumn[jColumn] != numberPossible) + numberPossible = -1; + } + int n = numberPossible; + if (numberPossible > 1) { + //printf("pppppossible %d\n",numberPossible); + for (int jLook = iLook + 1; jLook < iLook + numberPossible; jLook++) { + int jRow = sortRow[jLook]; + CoinBigIndex start2 = rowStart[jRow]; + assert(numberPossible == possibleRow[jRow]); + assert(length == rowLength[jRow]); + for (CoinBigIndex i = start2; i < start2 + length; i++) { + int jColumn = column[i]; + if (possibleColumn[jColumn] != numberPossible) + numberPossible = -1; + } + } + if (numberPossible < 2) { + // switch off + for (int jLook = iLook; jLook < iLook + n; jLook++) + possibleRow[sortRow[jLook]] = -1; + } + // skip rest + iLook += n - 1; + } else { + possibleRow[iRow] = -1; + } + } + for (int iLook = 0; iLook < numberRows; iLook++) { + iRow = sortRow[iLook]; + int numberPossible = possibleRow[iRow]; + // Only if any integers + int numberIntegers = 0; + CoinBigIndex start = rowStart[iRow]; + int length = rowLength[iRow]; + for (CoinBigIndex i = start; i < start + length; i++) { + int jColumn = column[i]; + if (model->isInteger(jColumn)) + numberIntegers++; + } + if (numberPossible > 1 && !numberIntegers) { + //printf("possible %d - but no integers\n",numberPossible); + } + if (numberPossible > 1 && (numberIntegers || false)) { + // + printf("possible %d - %d integers\n", numberPossible, numberIntegers); + int lastLook = iLook; + int nMapRow = -1; + for (int jLook = iLook + 1; jLook < iLook + numberPossible; jLook++) { + // stop if too many failures + if (jLook > iLook + 10 && nMapRow < 0) + break; + // Create identity mapping + int i; + for (i = 0; i < numberRows; i++) + mapRow[i] = i; + for (i = 0; i < numberColumns; i++) + mapColumn[i] = i; + int offset = jLook - iLook; + int nStackC = 0; + // build up row and column mapping + int nStackR = 1; + stackRow[0] = iLook; + bool good = true; + while (nStackR) { + nStackR--; + int look1 = stackRow[nStackR]; + int look2 = look1 + offset; + assert(randomRow[look1] == randomRow[look2]); + int row1 = sortRow[look1]; + int row2 = sortRow[look2]; + assert(mapRow[row1] == row1); + assert(mapRow[row2] == row2); + mapRow[row1] = row2; + mapRow[row2] = row1; + CoinBigIndex start1 = rowStart[row1]; + CoinBigIndex offset2 = rowStart[row2] - start1; + int length = rowLength[row1]; + assert(length == rowLength[row2]); + for (CoinBigIndex i = start1; i < start1 + length; i++) { + int jColumn1 = column[i]; + int jColumn2 = column[i + offset2]; + if (randomColumn[backColumn[jColumn1]] != randomColumn[backColumn[jColumn2]]) { + good = false; + break; + } + if (mapColumn[jColumn1] == jColumn1) { + // not touched + assert(mapColumn[jColumn2] == jColumn2); + if (jColumn1 != jColumn2) { + // Put on stack + mapColumn[jColumn1] = jColumn2; + mapColumn[jColumn2] = jColumn1; + stackColumn[nStackC++] = jColumn1; + } + } else { + if (mapColumn[jColumn1] != jColumn2 || mapColumn[jColumn2] != jColumn1) { + // bad + good = false; + printf("bad col\n"); + break; + } + } + } + if (!good) + break; + while (nStackC) { + nStackC--; + int iColumn = stackColumn[nStackC]; + int iColumn2 = mapColumn[iColumn]; + assert(iColumn != iColumn2); + int length = columnLength[iColumn]; + assert(length == columnLength[iColumn2]); + CoinBigIndex start = columnStart[iColumn]; + CoinBigIndex offset2 = columnStart[iColumn2] - start; + for (CoinBigIndex i = start; i < start + length; i++) { + int iRow = row[i]; + int iRow2 = row[i + offset2]; + if (mapRow[iRow] == iRow) { + // First (but be careful) + if (iRow != iRow2) { + //mapRow[iRow]=iRow2; + //mapRow[iRow2]=iRow; + int iBack = backRow[iRow]; + int iBack2 = backRow[iRow2]; + if (randomRow[iBack] == randomRow[iBack2] && iBack2 - iBack == offset) { + stackRow[nStackR++] = iBack; + } else { + //printf("randomRow diff - weights %g %g\n", + // weight[iRow],weight[iRow2]); + // bad + good = false; + break; + } + } + } else { + if (mapRow[iRow] != iRow2 || mapRow[iRow2] != iRow) { + // bad + good = false; + printf("bad row\n"); + break; + } + } + } + if (!good) + break; + } + } + // then check OK + if (good) { + for (iRow = 0; iRow < numberRows; iRow++) { + CoinBigIndex start = rowStart[iRow]; + int length = rowLength[iRow]; + if (mapRow[iRow] == iRow) { + for (CoinBigIndex i = start; i < start + length; i++) { + int jColumn = column[i]; + backColumn2[jColumn] = static_cast< int >(i - start); + } + for (CoinBigIndex i = start; i < start + length; i++) { + int jColumn = column[i]; + if (mapColumn[jColumn] != jColumn) { + int jColumn2 = mapColumn[jColumn]; + CoinBigIndex i2 = backColumn2[jColumn2]; + if (i2 < 0) { + good = false; + } else if (element[i] != element[i2 + start]) { + good = false; + } + } + } + for (CoinBigIndex i = start; i < start + length; i++) { + int jColumn = column[i]; + backColumn2[jColumn] = -1; + } + } else { + int row2 = mapRow[iRow]; + assert(iRow = mapRow[row2]); + if (rowLower[iRow] != rowLower[row2] || rowLower[row2] != rowLower[iRow]) + good = false; + CoinBigIndex offset2 = rowStart[row2] - start; + for (CoinBigIndex i = start; i < start + length; i++) { + int jColumn = column[i]; + double value = element[i]; + int jColumn2 = column[i + offset2]; + double value2 = element[i + offset2]; + if (value != value2 || mapColumn[jColumn] != jColumn2 || mapColumn[jColumn2] != jColumn) + good = false; + } + } + } + if (good) { + // check rim + for (iColumn = 0; iColumn < numberColumns; iColumn++) { + if (mapColumn[iColumn] != iColumn) { + int iColumn2 = mapColumn[iColumn]; + if (objective[iColumn] != objective[iColumn2]) + good = false; + if (columnLower[iColumn] != columnLower[iColumn2]) + good = false; + if (columnUpper[iColumn] != columnUpper[iColumn2]) + good = false; + if (model->isInteger(iColumn) != model->isInteger(iColumn2)) + good = false; + } + } + } + if (good) { + // temp + if (nMapRow < 0) { + //const double * solution = model->primalColumnSolution(); + // find mapped + int nMapColumn = 0; + for (int i = 0; i < numberColumns; i++) { + if (mapColumn[i] > i) + nMapColumn++; + } + nMapRow = 0; + int kRow = -1; + for (int i = 0; i < numberRows; i++) { + if (mapRow[i] > i) { + nMapRow++; + kRow = i; + } + } + printf("%d columns, %d rows\n", nMapColumn, nMapRow); + if (nMapRow == 1) { + CoinBigIndex start = rowStart[kRow]; + int length = rowLength[kRow]; + printf("%g <= ", rowLower[kRow]); + for (CoinBigIndex i = start; i < start + length; i++) { + int jColumn = column[i]; + if (mapColumn[jColumn] != jColumn) + printf("* "); + printf("%d,%g ", jColumn, element[i]); + } + printf("<= %g\n", rowUpper[kRow]); + } + } + // temp + int row1 = sortRow[lastLook]; + int row2 = sortRow[jLook]; + lastLook = jLook; + CoinBigIndex start1 = rowStart[row1]; + CoinBigIndex offset2 = rowStart[row2] - start1; + int length = rowLength[row1]; + assert(length == rowLength[row2]); + CoinBigIndex put = startAdd[nAddRows]; + double multiplier = length < 11 ? 2.0 : 1.125; + double value = 1.0; + for (CoinBigIndex i = start1; i < start1 + length; i++) { + int jColumn1 = column[i]; + int jColumn2 = column[i + offset2]; + columnAdd[put] = jColumn1; + elementAdd[put++] = value; + columnAdd[put] = jColumn2; + elementAdd[put++] = -value; + value *= multiplier; + } + nAddRows++; + startAdd[nAddRows] = put; + } else { + printf("ouch - did not check out as good\n"); + } + } + } + // skip rest + iLook += numberPossible - 1; + } + } + } + if (nAddRows) { + double *lower = new double[nAddRows]; + double *upper = new double[nAddRows]; + int i; + //const double * solution = model->primalColumnSolution(); + for (i = 0; i < nAddRows; i++) { + lower[i] = 0.0; + upper[i] = COIN_DBL_MAX; + } + printf("Adding %d rows with %d elements\n", nAddRows, + startAdd[nAddRows]); + //ClpSimplex newModel(*model); + //newModel.addRows(nAddRows,lower,upper,startAdd,columnAdd,elementAdd); + //newModel.writeMps("modified.mps"); + delete[] lower; + delete[] upper; + } + delete[] startAdd; + delete[] columnAdd; + delete[] elementAdd; + delete[] order; + delete[] other; + delete[] randomColumn; + delete[] weight; + delete[] randomRow; + delete[] sortRow; + delete[] backRow; + delete[] possibleRow; + delete[] sortColumn; + delete[] backColumn; + delete[] backColumn2; + delete[] possibleColumn; + delete[] mapRow; + delete[] mapColumn; + delete[] stackRow; + delete[] stackColumn; + } + delete[] number; + // Now do breakdown of ranges + breakdown("Elements", static_cast< int >(numberElements), elementByColumn); + breakdown("RowLower", numberRows, rowLower); + breakdown("RowUpper", numberRows, rowUpper); + breakdown("ColumnLower", numberColumns, columnLower); + breakdown("ColumnUpper", numberColumns, columnUpper); + breakdown("Objective", numberColumns, objective); +} + +static bool maskMatches(const int *starts, char **masks, + std::string &check) +{ + // back to char as I am old fashioned + const char *checkC = check.c_str(); + size_t length = strlen(checkC); + while (length > 0 && checkC[length - 1] == ' ') + length--; + for (int i = starts[length]; i < starts[length + 1]; i++) { + char *thisMask = masks[i]; + size_t k; + for (k = 0; k < length; k++) { + if (thisMask[k] != '?' && thisMask[k] != checkC[k]) + break; + } + if (k == length) + return true; + } + return false; +} + +static void clean(char *temp) +{ + char *put = temp; + while (*put >= ' ') + put++; + *put = '\0'; +} + +static void generateCode(CbcModel * /*model*/, const char *fileName, int type, int preProcess) +{ + // options on code generation + bool sizecode = (type & 4) != 0; + type &= 3; + FILE *fp = fopen(fileName, "r"); + assert(fp); + int numberLines = 0; +#define MAXLINES 5000 +#define MAXONELINE 200 + char line[MAXLINES][MAXONELINE]; + strcpy(line[numberLines++], "0#if defined(_MSC_VER)"); + strcpy(line[numberLines++], "0// Turn off compiler warning about long names"); + strcpy(line[numberLines++], "0# pragma warning(disable:4786)"); + strcpy(line[numberLines++], "0#endif\n"); + strcpy(line[numberLines++], "0#include "); + strcpy(line[numberLines++], "0#include "); + strcpy(line[numberLines++], "0#include \"OsiClpSolverInterface.hpp\""); + strcpy(line[numberLines++], "0#include \"CbcModel.hpp\""); + strcpy(line[numberLines++], "0#include \"CbcCutGenerator.hpp\""); + strcpy(line[numberLines++], "0#include \"CbcStrategy.hpp\""); + strcpy(line[numberLines++], "0#include \"CglPreProcess.hpp\""); + strcpy(line[numberLines++], "0#include \"CoinTime.hpp\""); + if (preProcess > 0) + strcpy(line[numberLines++], "0#include \"CglProbing.hpp\""); // possibly redundant + // To allow generated 5's to be just before branchAndBound - do rest here + strcpy(line[numberLines++], "5 cbcModel->initialSolve();"); + strcpy(line[numberLines++], "5 if (clpModel->tightenPrimalBounds()!=0) {"); + strcpy(line[numberLines++], "5 std::cout<<\"Problem is infeasible - tightenPrimalBounds!\"<dual(); // clean up"); + if (sizecode) { + // override some settings + strcpy(line[numberLines++], "5 // compute some things using problem size"); + strcpy(line[numberLines++], "5 cbcModel->setMinimumDrop(CoinMin(5.0e-2,"); + strcpy(line[numberLines++], "5 fabs(cbcModel->getMinimizationObjValue())*1.0e-3+1.0e-4));"); + strcpy(line[numberLines++], "5 if (cbcModel->getNumCols()<500)"); + strcpy(line[numberLines++], "5 cbcModel->setMaximumCutPassesAtRoot(-100); // always do 100 if possible"); + strcpy(line[numberLines++], "5 else if (cbcModel->getNumCols()<5000)"); + strcpy(line[numberLines++], "5 cbcModel->setMaximumCutPassesAtRoot(100); // use minimum drop"); + strcpy(line[numberLines++], "5 else"); + strcpy(line[numberLines++], "5 cbcModel->setMaximumCutPassesAtRoot(20);"); + strcpy(line[numberLines++], "5 cbcModel->setMaximumCutPasses(1);"); + } + if (preProcess <= 0) { + // no preprocessing or strategy + if (preProcess) { + strcpy(line[numberLines++], "5 // Preprocessing using CbcStrategy"); + strcpy(line[numberLines++], "5 CbcStrategyDefault strategy(1,5,5);"); + strcpy(line[numberLines++], "5 strategy.setupPreProcessing(1);"); + strcpy(line[numberLines++], "5 cbcModel->setStrategy(strategy);"); + } + } else { + int translate[] = { 9999, 0, 0, -1, 2, 3, -2 }; + strcpy(line[numberLines++], "5 // Hand coded preprocessing"); + strcpy(line[numberLines++], "5 CglPreProcess process;"); + strcpy(line[numberLines++], "5 OsiSolverInterface * saveSolver=cbcModel->solver()->clone();"); + strcpy(line[numberLines++], "5 // Tell solver we are in Branch and Cut"); + strcpy(line[numberLines++], "5 saveSolver->setHintParam(OsiDoInBranchAndCut,true,OsiHintDo) ;"); + strcpy(line[numberLines++], "5 // Default set of cut generators"); + strcpy(line[numberLines++], "5 CglProbing generator1;"); + strcpy(line[numberLines++], "5 generator1.setUsingObjective(1);"); + strcpy(line[numberLines++], "5 generator1.setMaxPass(3);"); + strcpy(line[numberLines++], "5 generator1.setMaxProbeRoot(saveSolver->getNumCols());"); + strcpy(line[numberLines++], "5 generator1.setMaxElements(100);"); + strcpy(line[numberLines++], "5 generator1.setMaxLookRoot(50);"); + strcpy(line[numberLines++], "5 generator1.setRowCuts(3);"); + strcpy(line[numberLines++], "5 // Add in generators"); + strcpy(line[numberLines++], "5 process.addCutGenerator(&generator1);"); + strcpy(line[numberLines++], "5 process.messageHandler()->setLogLevel(cbcModel->logLevel());"); + strcpy(line[numberLines++], "5 OsiSolverInterface * solver2 = "); + sprintf(line[numberLines++], "5 process.preProcessNonDefault(*saveSolver,%d,10);", translate[preProcess]); + strcpy(line[numberLines++], "5 // Tell solver we are not in Branch and Cut"); + strcpy(line[numberLines++], "5 saveSolver->setHintParam(OsiDoInBranchAndCut,false,OsiHintDo) ;"); + strcpy(line[numberLines++], "5 if (solver2)"); + strcpy(line[numberLines++], "5 solver2->setHintParam(OsiDoInBranchAndCut,false,OsiHintDo) ;"); + strcpy(line[numberLines++], "5 if (!solver2) {"); + strcpy(line[numberLines++], "5 std::cout<<\"Pre-processing says infeasible!\"<getNumRows()"); + strcpy(line[numberLines++], "5 <<\" rows, \"<getNumCols()"); + strcpy(line[numberLines++], "5 <<\" columns and \"<getNumElements()"); + strcpy(line[numberLines++], "5 <<\" elements\"<getNumElements()<clone();"); + strcpy(line[numberLines++], "5 cbcModel->assignSolver(solver2);"); + strcpy(line[numberLines++], "5 cbcModel->initialSolve();"); + } + while (fgets(line[numberLines], MAXONELINE, fp)) { + assert(numberLines < MAXLINES); + clean(line[numberLines]); + numberLines++; + } + fclose(fp); + strcpy(line[numberLines++], "0\nint main (int argc, const char *argv[])\n{"); + strcpy(line[numberLines++], "0 OsiClpSolverInterface solver1;"); + strcpy(line[numberLines++], "0 int status=1;"); + strcpy(line[numberLines++], "0 if (argc<2)"); + strcpy(line[numberLines++], "0 std::cout<<\"Please give file name\"< (osiModel);"); + strcpy(line[numberLines++], "0 ClpSimplex * clpModel = osiclpModel->getModelPtr();"); + // add in comments about messages + strcpy(line[numberLines++], "3 // You can save some time by switching off message building"); + strcpy(line[numberLines++], "3 // clpModel->messagesPointer()->setDetailMessages(100,10000,(int *) NULL);"); + // add in actual solve + strcpy(line[numberLines++], "5 cbcModel->branchAndBound();"); + strcpy(line[numberLines++], "8 std::cout<getNodeCount()<<\" nodes with objective \""); + strcpy(line[numberLines++], "8 <getObjValue()"); + strcpy(line[numberLines++], "8 <<(!cbcModel->status() ? \" Finished\" : \" Not finished\")"); + strcpy(line[numberLines++], "8 <getMinimizationObjValue()<1.0e50) {"); + if (preProcess > 0) { + strcpy(line[numberLines++], "5 // post process"); + strcpy(line[numberLines++], "5 process.postProcess(*cbcModel->solver());"); + strcpy(line[numberLines++], "5 // Solution now back in saveSolver"); + strcpy(line[numberLines++], "5 cbcModel->assignSolver(saveSolver);"); + strcpy(line[numberLines++], "5 memcpy(cbcModel->bestSolution(),cbcModel->solver()->getColSolution(),"); + strcpy(line[numberLines++], "5 numberColumns*sizeof(double));"); + } + strcpy(line[numberLines++], "5 // put back in original solver"); + strcpy(line[numberLines++], "5 solver1.setColSolution(cbcModel->bestSolution());"); + strcpy(line[numberLines++], "5 const double * solution = solver1.getColSolution();"); + strcpy(line[numberLines++], "8 \n // Now you would use solution etc etc\n"); + strcpy(line[numberLines++], "5"); + strcpy(line[numberLines++], "5 // Get names from solver1 (as OsiSolverInterface may lose)"); + strcpy(line[numberLines++], "5 std::vector columnNames = *solver1.getModelPtr()->columnNames();"); + strcpy(line[numberLines++], "5 "); + strcpy(line[numberLines++], "5 int iColumn;"); + strcpy(line[numberLines++], "5 std::cout<1.0e-7&&solver1.isInteger(iColumn)) "); + strcpy(line[numberLines++], "5 std::cout< 0) + wanted[1] = wanted[6] = 1; + if (type > 1) + wanted[2] = wanted[4] = wanted[7] = 1; + std::string header[9] = { "", "Save values", "Redundant save of default values", "Set changed values", + "Redundant set default values", "Solve", "Restore values", "Redundant restore values", "Finish up" }; + for (int iType = 0; iType < 9; iType++) { + if (!wanted[iType]) + continue; + int n = 0; + int iLine; + for (iLine = 0; iLine < numberLines; iLine++) { + if (line[iLine][0] == '0' + iType) { + if (!n && header[iType] != "") + fprintf(fp, "\n // %s\n\n", header[iType].c_str()); + n++; + // skip save and clp as cloned + if (!strstr(line[iLine], "save") || (!strstr(line[iLine], "clpMo") && !strstr(line[iLine], "_Osi"))) + fprintf(fp, "%s\n", line[iLine] + 1); + } + } + } + fclose(fp); + printf("C++ file written to %s\n", fileName); +} +// Print a general message +static void printGeneralMessage(CbcModel &model, const char *message) +{ +#ifndef DISALLOW_PRINTING + model.messageHandler()->message(CBC_FPUMP1, model.messages()) + << message + << CoinMessageEol; +#endif +} +#ifdef CBC_HAS_NAUTY +#include "CbcSymmetry.hpp" +// returns number of constraints added +static int nautiedConstraints(CbcModel &model, int maxPass) +{ + bool changed = true; + int numberAdded = 0; + int numberPasses = 0; + int changeType = 0; //(more2&(128|256))>>7; + OsiSolverInterface *solverOriginal = model.solver(); +#define REALLY_CHANGE +#ifdef REALLY_CHANGE + OsiSolverInterface *solver = solverOriginal; +#else + int numberOriginalRows = solverOriginal->getNumRows(); + OsiSolverInterface *solver = solverOriginal->clone(); +#endif + while (changed) { + changed = false; + CbcSymmetry symmetryInfo; + //symmetryInfo.setModel(&model); + // for now strong is just on counts - use user option + //int maxN=5000000; + //OsiSolverInterface * solver = model.solver(); + symmetryInfo.setupSymmetry(&model); + int numberGenerators = symmetryInfo.statsOrbits(&model, 0); + if (numberGenerators) { + //symmetryInfo.Print_Orbits(); + int numberUsefulOrbits = symmetryInfo.numberUsefulOrbits(); + if (numberUsefulOrbits) { + symmetryInfo.Compute_Symmetry(); + symmetryInfo.fillOrbits(/*true*/); + const int *orbits = symmetryInfo.whichOrbit(); + int numberUsefulOrbits = symmetryInfo.numberUsefulOrbits(); + int *counts = new int[numberUsefulOrbits]; + memset(counts, 0, numberUsefulOrbits * sizeof(int)); + int numberColumns = solver->getNumCols(); + int numberUseful = 0; + if (changeType == 1) { + // just 0-1 + for (int i = 0; i < numberColumns; i++) { + int iOrbit = orbits[i]; + if (iOrbit >= 0) { + if (solver->isBinary(i)) { + counts[iOrbit]++; + numberUseful++; + } + } + } + } else if (changeType == 2) { + // just integer + for (int i = 0; i < numberColumns; i++) { + int iOrbit = orbits[i]; + if (iOrbit >= 0) { + if (solver->isInteger(i)) { + counts[iOrbit]++; + numberUseful++; + } + } + } + } else { + // all + for (int i = 0; i < numberColumns; i++) { + int iOrbit = orbits[i]; + if (iOrbit >= 0) { + counts[iOrbit]++; + numberUseful++; + } + } + } + int iOrbit = -1; +#define LONGEST 0 +#if LONGEST + // choose longest + int maxOrbit = 0; + for (int i = 0; i < numberUsefulOrbits; i++) { + if (counts[i] > maxOrbit) { + maxOrbit = counts[i]; + iOrbit = i; + } + } +#else + // choose closest to 2 + int minOrbit = numberColumns + 1; + for (int i = 0; i < numberUsefulOrbits; i++) { + if (counts[i] > 1 && counts[i] < minOrbit) { + minOrbit = counts[i]; + iOrbit = i; + } + } +#endif + delete[] counts; + if (!numberUseful) + break; + // take largest + const double *solution = solver->getColSolution(); + double *size = new double[numberColumns]; + int *which = new int[numberColumns]; + int nIn = 0; + for (int i = 0; i < numberColumns; i++) { + if (orbits[i] == iOrbit) { + size[nIn] = -solution[i]; + which[nIn++] = i; + } + } + if (nIn > 1) { + //printf("Using orbit length %d\n",nIn); + CoinSort_2(size, size + nIn, which); + size[0] = 1.0; + size[1] = -1.0; +#if LONGEST == 0 + solver->addRow(2, which, size, 0.0, COIN_DBL_MAX); + numberAdded++; +#elif LONGEST == 1 + for (int i = 0; i < nIn - 1; i++) { + solver->addRow(2, which + i, size, 0.0, COIN_DBL_MAX); + numberAdded++; + } +#else + for (int i = 0; i < nIn - 1; i++) { + solver->addRow(2, which, size, 0.0, COIN_DBL_MAX); + which[1] = which[2 + i]; + numberAdded++; + } +#endif + numberPasses++; + if (numberPasses < maxPass) + changed = true; + } + delete[] size; + delete[] which; + } + } + } + if (numberAdded) { + char general[100]; + if (numberPasses < maxPass) + sprintf(general, "%d constraints added in %d passes", numberAdded, + numberPasses); + else + sprintf(general, "%d constraints added in %d passes (maximum) - must be better way", numberAdded, + numberPasses); + model.messageHandler()->message(CBC_GENERAL, + model.messages()) + << general << CoinMessageEol; +#ifdef SAVE_NAUTY + OsiClpSolverInterface *clpSolver = dynamic_cast< OsiClpSolverInterface * >(solver); + ClpSimplex *lpSolver = clpSolver->getModelPtr(); + char name[100]; + strcpy(name, lpSolver->problemName().c_str()); + strcat(name, "_nauty"); + printf("saving model on %s\n", name); + solver->writeMps(name); +#endif + } +#ifndef REALLY_CHANGE + CbcRowCuts *globalCuts = model.globalCuts(); + int numberRows = solver->getNumRows(); + if (numberRows > numberOriginalRows) { + const CoinPackedMatrix *rowCopy = solver->getMatrixByRow(); + const int *column = rowCopy->getIndices(); + const int *rowLength = rowCopy->getVectorLengths(); + const CoinBigIndex *rowStart = rowCopy->getVectorStarts(); + const double *elements = rowCopy->getElements(); + const double *rowLower = solver->getRowLower(); + const double *rowUpper = solver->getRowUpper(); + for (int iRow = numberOriginalRows; iRow < numberRows; iRow++) { + OsiRowCut rc; + rc.setLb(rowLower[iRow]); + rc.setUb(rowUpper[iRow]); + CoinBigIndex start = rowStart[iRow]; + rc.setRow(rowLength[iRow], column + start, elements + start, false); + globalCuts->addCutIfNotDuplicate(rc); + } + } + delete solver; +#endif + return numberAdded; +} +#endif + +static char cbcCrashAnnounced = 0; + +#ifdef HAVE_EXECINFO_H +#ifdef HAVE_SIGNAL_H +void CbcCrashHandler( int sig ) { + char signame[256] = ""; + switch (sig) { + case SIGILL: + strcpy(signame, "SIGILL"); + break; + case SIGSEGV: + strcpy(signame, "SIGSEGV"); + break; + case SIGABRT: + strcpy(signame, "SIGABRT"); + break; + } + + fflush(stderr); + fflush(stdout); + fprintf(stderr, "\n\nERROR while running Cbc. Signal %s caught. Getting stack trace.\n", signame); fflush(stderr); + { + char *st = getenv("RUNNING_TEST"); + if (st) { + fprintf(stderr, "Error happened while running the \"%s\" test\n", st); + fflush(stderr); + } + } + +#define MAX_FRAMES 50 + void *array[MAX_FRAMES]; + size_t size; + char **strings; + size_t i; + + size = backtrace (array, MAX_FRAMES); + strings = backtrace_symbols (array, size); + + for (i = 0; i < size; i++) { + fprintf (stderr, "%s\n", strings[i]); + fflush(stderr); + } + fprintf(stderr, "\n\n"); fflush(stderr); + + free (strings); + + if (!cbcCrashAnnounced) { + cbcCrashAnnounced = 1; + abort(); + } +#undef MAX_FRAMES +} +#endif +#endif + + +/* + Version 1.00.00 November 16 2005. + This is to stop me (JJF) messing about too much. + Tuning changes should be noted here. + The testing next version may be activated by CBC_NEXT_VERSION + This applies to OsiClp, Clp etc + Version 1.00.01 November 24 2005 + Added several classes for advanced users. This can't affect code (if you don't use it) + Made some tiny changes (for N way branching) which should not change anything. + CbcNWay object class - for N way branching this also allows use of CbcConsequence class. + CbcBranchAllDifferent object class - for branching on general integer variables + to stop them having same value so branches are x >= y+1 and x <= y-1. + Added two new Cgl classes - CglAllDifferent which does column fixing (too slowly) + and CglStored which just has a list of cuts which can be activated. + Modified preprocess option to SOS + Version 1.00.02 December 9 2005 + Added use of CbcStrategy to do clean preprocessing + Added use of referenceSolver for cleaner repetition of Cbc + Version 1.01.00 February 2 2006 + Added first try at Ampl interface + Version 1.04 June 2007 + Goes parallel + Version 2.00 September 2007 + Improvements to feaspump + Source code changes so up to 2.0 +*/ +#if 0 +static char printArray[250]; +// Sets double parameter and returns printable string and error code +const char * +CbcOrClpParam::setDoubleParameterWithMessage(CbcModel &model, double value, int &returnCode) +{ + if (value < lowerDoubleValue_ || value > upperDoubleValue_) { + sprintf(printArray, "%g was provided for %s - valid range is %g to %g", + value, name_.c_str(), lowerDoubleValue_, upperDoubleValue_); + returnCode = 1; + } else { + double oldValue = doubleValue_; + doubleValue_ = value; + switch (type_) { + case CBC_PARAM_DBL_INFEASIBILITYWEIGHT: + oldValue = model.getDblParam(CbcModel::CbcInfeasibilityWeight); + model.setDblParam(CbcModel::CbcInfeasibilityWeight, value); + break; + case CBC_PARAM_DBL_INTEGERTOLERANCE: + oldValue = model.getDblParam(CbcModel::CbcIntegerTolerance); + model.setDblParam(CbcModel::CbcIntegerTolerance, value); + break; + case CBC_PARAM_DBL_INCREMENT: + oldValue = model.getDblParam(CbcModel::CbcCutoffIncrement); + model.setDblParam(CbcModel::CbcCutoffIncrement, value); + case CBC_PARAM_DBL_ALLOWABLEGAP: + oldValue = model.getDblParam(CbcModel::CbcAllowableGap); + model.setDblParam(CbcModel::CbcAllowableGap, value); + break; + case CBC_PARAM_DBL_GAPRATIO: + oldValue = model.getDblParam(CbcModel::CbcAllowableFractionGap); + model.setDblParam(CbcModel::CbcAllowableFractionGap, value); + break; + case CBC_PARAM_DBL_CUTOFF: + oldValue = model.getCutoff(); + model.setCutoff(value); + break; + case CBC_PARAM_DBL_TIMELIMIT_BAB: + oldValue = model.getDblParam(CbcModel::CbcMaximumSeconds); + model.setDblParam(CbcModel::CbcMaximumSeconds, value); + break; + case CBC_PARAM_DBL_MAXSECONDSNIFS: + oldValue = model.getDblParam(CbcModel::CbcMaxSecondsNotImproving); + model.setDblParam(CbcModel::CbcMaxSecondsNotImproving, value); + break; + case CLP_PARAM_DBL_DUALTOLERANCE: + case CLP_PARAM_DBL_PRIMALTOLERANCE: + setDoubleParameter(model.solver(), value); + return 0; // to avoid message + default: + break; + } + sprintf(printArray, "%s was changed from %g to %g", + name_.c_str(), oldValue, value); + returnCode = 0; + } + return printArray; +} +// Sets int parameter and returns printable string and error code +const char * +CbcOrClpParam::setIntParameterWithMessage(CbcModel &model, int value, int &returnCode) +{ + if (value < lowerIntValue_ || value > upperIntValue_) { + sprintf(printArray, "%d was provided for %s - valid range is %d to %d", + value, name_.c_str(), lowerIntValue_, upperIntValue_); + returnCode = 1; + } else { + printArray[0] = '\0'; + if (value == intValue_) + return printArray; + int oldValue = intValue_; + intValue_ = value; + switch (type_) { + case CLP_PARAM_INT_LOGLEVEL: + oldValue = model.messageHandler()->logLevel(); + model.messageHandler()->setLogLevel(CoinAbs(value)); + break; + case CLP_PARAM_INT_SOLVERLOGLEVEL: + oldValue = model.solver()->messageHandler()->logLevel(); + model.solver()->messageHandler()->setLogLevel(value); + break; + case CBC_PARAM_INT_MAXNODES: + oldValue = model.getIntParam(CbcModel::CbcMaxNumNode); + model.setIntParam(CbcModel::CbcMaxNumNode, value); + break; + case CBC_PARAM_INT_MAXNODESNOTIMPROVINGFS: + oldValue = model.getIntParam(CbcModel::CbcMaxNodesNotImproving); + model.setIntParam(CbcModel::CbcMaxNodesNotImproving, value); + break; + + case CBC_PARAM_INT_MAXSOLS: + oldValue = model.getIntParam(CbcModel::CbcMaxNumSol); + model.setIntParam(CbcModel::CbcMaxNumSol, value); + break; + case CBC_PARAM_INT_MAXSAVEDSOLS: + oldValue = model.maximumSavedSolutions(); + model.setMaximumSavedSolutions(value); + break; + case CBC_PARAM_INT_STRONGBRANCHING: + oldValue = model.numberStrong(); + model.setNumberStrong(value); + break; + case CBC_PARAM_INT_NUMBERBEFORE: + oldValue = model.numberBeforeTrust(); + model.setNumberBeforeTrust(value); + break; + case CBC_PARAM_INT_NUMBERANALYZE: + oldValue = model.numberAnalyzeIterations(); + model.setNumberAnalyzeIterations(value); + break; + case CBC_PARAM_INT_CUTPASSINTREE: + oldValue = model.getMaximumCutPasses(); + model.setMaximumCutPasses(value); + break; + case CBC_PARAM_INT_CUTPASS: + oldValue = model.getMaximumCutPassesAtRoot(); + model.setMaximumCutPassesAtRoot(value); + break; +#ifdef COIN_HAS_CBC +#ifdef CBC_THREAD + case CBC_PARAM_INT_THREADS: + oldValue = model.getNumberThreads(); + model.setNumberThreads(value); + break; +#endif + case CBC_PARAM_INT_RANDOMSEED: + oldValue = model.getRandomSeed(); + model.setRandomSeed(value); + break; +#endif + default: + break; + } + sprintf(printArray, "%s was changed from %d to %d", + name_.c_str(), oldValue, value); + returnCode = 0; + } + return printArray; +} +int CbcOrClpParam::setDoubleParameter(OsiSolverInterface *model, double value) +{ + int returnCode; + setDoubleParameterWithMessage(model, value, returnCode); + //if (doPrinting && strlen(printArray)) + //std::cout << printArray << std::endl; + return returnCode; +} +// Sets double parameter and returns printable string and error code +const char * +CbcOrClpParam::setDoubleParameterWithMessage(OsiSolverInterface *model, double value, int &returnCode) +{ + if (value < lowerDoubleValue_ || value > upperDoubleValue_) { + sprintf(printArray, "%g was provided for %s - valid range is %g to %g", + value, name_.c_str(), lowerDoubleValue_, upperDoubleValue_); + std::cout << value << " was provided for " << name_ << " - valid range is " << lowerDoubleValue_ << " to " << upperDoubleValue_ << std::endl; + returnCode = 1; + } else { + double oldValue = doubleValue_; + doubleValue_ = value; + switch (type_) { + case CLP_PARAM_DBL_DUALTOLERANCE: + model->getDblParam(OsiDualTolerance, oldValue); + model->setDblParam(OsiDualTolerance, value); + break; + case CLP_PARAM_DBL_PRIMALTOLERANCE: + model->getDblParam(OsiPrimalTolerance, oldValue); + model->setDblParam(OsiPrimalTolerance, value); + break; + default: + break; + } + sprintf(printArray, "%s was changed from %g to %g", + name_.c_str(), oldValue, value); + returnCode = 0; + } + return printArray; +} +#endif diff --git a/src/Attic/CbcSolver.hpp b/src/Attic/CbcSolver.hpp new file mode 100644 index 000000000..54ef4f8d5 --- /dev/null +++ b/src/Attic/CbcSolver.hpp @@ -0,0 +1,489 @@ +// Copyright (C) 2007, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +/*! \file CbcSolver.hpp + \brief Defines CbcSolver, the proposed top-level class for the new-style + cbc solver. + + This class is currently an orphan. With the removal of all code flagged + with the NEW_STYLE_SOLVER, this class is never instantiated (and cannot + be instantiated). It is available to be coopted as a top-level object + wrapping the current CbcMain0 and CbcMain1, should that appear to be a + desireable path forward. -- lh, 091211 -- +*/ + +#ifndef CbcSolver_H +#define CbcSolver_H + +#include +#include +#include "CoinMessageHandler.hpp" +#include "OsiClpSolverInterface.hpp" + +#if CBC_OTHER_SOLVER == 1 +#include "OsiCpxSolverInterface.hpp" +#endif + +#include "CbcModel.hpp" +#include "CbcOrClpParam.hpp" +#include "CoinUtilsConfig.h" + +class CbcUser; +class CbcStopNow; +class CglCutGenerator; + +//############################################################################# + +/*! \brief This allows the use of the standalone solver in a flexible manner. + + It has an original OsiClpSolverInterface and CbcModel which it can use + repeatedly, e.g., to get a heuristic solution and then start again. + + So I [jjf] will need a primitive scripting language which can then call + solve and manipulate solution value and solution arrays. + + Also provides for user callback functions. Currently two ideas in + gestation, CbcUser and CbcStopNow. The latter seems limited to deciding + whether or not to stop. The former seems completely general, with a notion + of importing and exporting, and a `solve', which should be interpreted as + `do whatever this user function does'. + + Parameter initialisation is at last centralised in fillParameters(). +*/ + +class CBCSOLVERLIB_EXPORT CbcSolver { + +public: + ///@name Solve method + //@{ + /** This takes a list of commands, does "stuff" and returns + returnMode - + 0 model and solver untouched - babModel updated + 1 model updated - just with solution basis etc + 2 model updated i.e. as babModel (babModel NULL) (only use without preprocessing) + */ + int solve(int argc, const char *argv[], int returnMode); + /** This takes a list of commands, does "stuff" and returns + returnMode - + 0 model and solver untouched - babModel updated + 1 model updated - just with solution basis etc + 2 model updated i.e. as babModel (babModel NULL) (only use without preprocessing) + */ + int solve(const char *input, int returnMode); + //@} + ///@name Constructors and destructors etc + //@{ + /// Default Constructor + CbcSolver(); + + /// Constructor from solver + CbcSolver(const OsiClpSolverInterface &); + + /// Constructor from model + CbcSolver(const CbcModel &); + + /** Copy constructor . + */ + CbcSolver(const CbcSolver &rhs); + + /// Assignment operator + CbcSolver &operator=(const CbcSolver &rhs); + + /// Destructor + ~CbcSolver(); + /// Fill with standard parameters + void fillParameters(); + /*! \brief Set default values in solvers from parameters + + Misleading. The current code actually reads default values from + the underlying solvers and installs them as default values for a subset of + parameters in #parameters_. + */ + void fillValuesInSolver(); + /// Add user function + void addUserFunction(CbcUser *function); + /// Set user call back + void setUserCallBack(CbcStopNow *function); + /// Add cut generator + void addCutGenerator(CglCutGenerator *generator); + //@} + ///@name miscellaneous methods to line up with old + //@{ + // analyze model + int *analyze(OsiClpSolverInterface *solverMod, int &numberChanged, double &increment, + bool changeInt, CoinMessageHandler *generalMessageHandler); + /** 1 - add heuristics to model + 2 - do heuristics (and set cutoff and best solution) + 3 - for miplib test so skip some + (out model later) + */ + //int doHeuristics(CbcModel * model, int type); + /** Updates model_ from babModel_ according to returnMode + returnMode - + 0 model and solver untouched - babModel updated + 1 model updated - just with solution basis etc + 2 model updated i.e. as babModel (babModel NULL) (only use without preprocessing) + */ + void updateModel(ClpSimplex *model2, int returnMode); + //@} + ///@name useful stuff + //@{ + /// Get int value + int intValue(CbcOrClpParameterType type) const; + /// Set int value + void setIntValue(CbcOrClpParameterType type, int value); + /// Get double value + double doubleValue(CbcOrClpParameterType type) const; + /// Set double value + void setDoubleValue(CbcOrClpParameterType type, double value); + /// User function (NULL if no match) + CbcUser *userFunction(const char *name) const; + /// Return original Cbc model + inline CbcModel *model() + { + return &model_; + } + /// Return updated Cbc model + inline CbcModel *babModel() + { + return babModel_; + } + /// Number of userFunctions + inline int numberUserFunctions() const + { + return numberUserFunctions_; + } + /// User function array + inline CbcUser **userFunctionArray() const + { + return userFunction_; + } + /// Copy of model on initial load (will contain output solutions) + inline OsiClpSolverInterface *originalSolver() const + { + return originalSolver_; + } + /// Copy of model on initial load + inline CoinModel *originalCoinModel() const + { + return originalCoinModel_; + } + /// Copy of model on initial load (will contain output solutions) + void setOriginalSolver(OsiClpSolverInterface *originalSolver); + /// Copy of model on initial load + void setOriginalCoinModel(CoinModel *originalCoinModel); + /// Number of cutgenerators + inline int numberCutGenerators() const + { + return numberCutGenerators_; + } + /// Cut generator array + inline CglCutGenerator **cutGeneratorArray() const + { + return cutGenerator_; + } + /// Start time + inline double startTime() const + { + return startTime_; + } + /// Whether to print to std::cout + inline void setPrinting(bool onOff) + { + noPrinting_ = !onOff; + } + /// Where to start reading commands + inline void setReadMode(int value) + { + readMode_ = value; + } + //@} +private: + ///@name Private member data + //@{ + + /// Reference model + CbcModel model_; + + /// Updated model + CbcModel *babModel_; + + /// User functions + CbcUser **userFunction_; + /** Status of user functions + 0 - not used + 1 - needs cbc_load + 2 - available - data in coinModel + 3 - data loaded - can do cbc_save + */ + int *statusUserFunction_; + /// Copy of model on initial load (will contain output solutions) + OsiClpSolverInterface *originalSolver_; + /// Copy of model on initial load + CoinModel *originalCoinModel_; + /// Cut generators + CglCutGenerator **cutGenerator_; + /// Number of user functions + int numberUserFunctions_; + /// Number of cut generators + int numberCutGenerators_; + /// Stop now stuff + CbcStopNow *callBack_; + /// Cpu time at instantiation + double startTime_; + /// Parameters and values + std::vector< CbcOrClpParam > parameters_; + /// Whether to do miplib test + bool doMiplib_; + /// Whether to print to std::cout + bool noPrinting_; + /// Where to start reading commands + int readMode_; + //@} +}; +//############################################################################# + +/// Structure to hold useful arrays +typedef struct { + // Priorities + int *priorities_; + // SOS priorities + int *sosPriority_; + // Direction to branch first + int *branchDirection_; + // Input solution + double *primalSolution_; + // Down pseudo costs + double *pseudoDown_; + // Up pseudo costs + double *pseudoUp_; +} CbcSolverUsefulData2; + +//############################################################################# + +/** + The CbcSolver class was taken out at a 9/12/09 meeting + This is a feeble replacement. + At present everything is public +*/ +class CBCSOLVERLIB_EXPORT CbcSolverUsefulData { + +public: + ///@name Constructors and destructors etc + //@{ + /// Default Constructor + CbcSolverUsefulData(); + + /** Copy constructor . + */ + CbcSolverUsefulData(const CbcSolverUsefulData &rhs); + + /// Assignment operator + CbcSolverUsefulData &operator=(const CbcSolverUsefulData &rhs); + + /// Destructor + ~CbcSolverUsefulData(); + //@} + + ///@name Member data + //@{ + // For time + double totalTime_; + // Parameters + std::vector parameters_; + // Printing + bool noPrinting_; + // Whether to use signal handler + bool useSignalHandler_; + // Default pump tuning + int initialPumpTune_; + // even with verbose >=1 this may not be the first call to + // the solver + bool printWelcome_; + + //@} +}; +/// And this uses it +// When we want to load up CbcModel with options first +CBCSOLVERLIB_EXPORT +void CbcMain0(CbcModel &babSolver, CbcSolverUsefulData &solverData); +CBCSOLVERLIB_EXPORT +int CbcMain1(int argc, const char *argv[], CbcModel &babSolver, int(CbcModel *currentSolver, int whereFrom), CbcSolverUsefulData &solverData); +CBCSOLVERLIB_EXPORT +int CbcMain1(int argc, const char *argv[], CbcModel &babSolver, + CbcSolverUsefulData &solverData); + +CBCSOLVERLIB_EXPORT +int CbcMain(int argc, const char *argv[], CbcModel &babSolver); +// four ways of calling +CBCSOLVERLIB_EXPORT +int callCbc(const char *input2, OsiClpSolverInterface &solver1); +CBCSOLVERLIB_EXPORT +int callCbc(const char *input2); +CBCSOLVERLIB_EXPORT +int callCbc(const std::string input2, OsiClpSolverInterface &solver1); +CBCSOLVERLIB_EXPORT +int callCbc(const std::string input2); +// two ways of calling +CBCSOLVERLIB_EXPORT +int callCbc(const char *input2, CbcModel &babSolver); +CBCSOLVERLIB_EXPORT +int callCbc(const std::string input2, CbcModel &babSolver); +// And when CbcMain0 already called to initialize (with call back) (see CbcMain1 for whereFrom) +CBCSOLVERLIB_EXPORT +int callCbc1(const char *input2, CbcModel &babSolver, int(CbcModel *currentSolver, int whereFrom)); + +//############################################################################# + +/*! \brief A class to allow the use of unknown user functionality + + For example, access to a modelling language (CbcAmpl). +*/ +class CBCSOLVERLIB_EXPORT CbcUser { + +public: + ///@name import/export methods + //@{ + /*! \brief Import - gets full command arguments + + \return + - -1 - no action + - 0 - data read in without error + - 1 - errors + */ + virtual int importData(CbcSolver * /*model*/, int & /*argc*/, char ** /*argv[]*/) + { + return -1; + } + + /*! \brief Export + + Values for mode: + - 1 OsiClpSolver + - 2 CbcModel + - add 10 if infeasible from odd situation + */ + virtual void exportSolution(CbcSolver * /*model*/, + int /*mode*/, const char * /*message*/ = NULL) {} + + /// Export Data (i.e. at very end) + virtual void exportData(CbcSolver * /*model*/) {} + + /// Get useful stuff + virtual void fillInformation(CbcSolver * /*model*/, + CbcSolverUsefulData & /*info*/) {} + //@} + + ///@name usage methods + //@{ + /// CoinModel if valid + inline CoinModel *coinModel() const + { + return coinModel_; + } + /// Other info - needs expanding + virtual void *stuff() + { + return NULL; + } + /// Name + inline std::string name() const + { + return userName_; + } + /// Solve (whatever that means) + virtual void solve(CbcSolver *model, const char *options) = 0; + /// Returns true if function knows about option + virtual bool canDo(const char *options) = 0; + //@} + + ///@name Constructors and destructors etc + //@{ + /// Default Constructor + CbcUser(); + + /// Copy constructor + CbcUser(const CbcUser &rhs); + + /// Assignment operator + CbcUser &operator=(const CbcUser &rhs); + + /// Clone + virtual CbcUser *clone() const = 0; + + /// Destructor + virtual ~CbcUser(); + //@} + +protected: + ///@name Private member data + //@{ + + /// CoinModel + CoinModel *coinModel_; + + /// Name of user function + std::string userName_; + + //@} +}; +//############################################################################# + +/*! \brief Support the use of a call back class to decide whether to stop + + Definitely under construction. +*/ + +class CBCSOLVERLIB_EXPORT CbcStopNow { + +public: + ///@name Decision methods + //@{ + /*! \brief Import + + Values for whereFrom: + - 1 after initial solve by dualsimplex etc + - 2 after preprocessing + - 3 just before branchAndBound (so user can override) + - 4 just after branchAndBound (before postprocessing) + - 5 after postprocessing + - 6 after a user called heuristic phase + + \return 0 if good + nonzero return code to stop + */ + virtual int callBack(CbcModel * /*currentSolver*/, int /*whereFrom*/) + { + return 0; + } + //@} + + ///@name Constructors and destructors etc + //@{ + /// Default Constructor + CbcStopNow(); + + /** Copy constructor . + */ + CbcStopNow(const CbcStopNow &rhs); + + /// Assignment operator + CbcStopNow &operator=(const CbcStopNow &rhs); + + /// Clone + virtual CbcStopNow *clone() const; + + /// Destructor + virtual ~CbcStopNow(); + //@} + +private: + ///@name Private member data + //@{ + //@} +}; +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/src/Attic/CbcSolverHeuristics.cpp b/src/Attic/CbcSolverHeuristics.cpp new file mode 100644 index 000000000..e1132c149 --- /dev/null +++ b/src/Attic/CbcSolverHeuristics.cpp @@ -0,0 +1,1721 @@ +// Copyright (C) 2007, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +/*! \file CbcSolverHeuristics.cpp + \brief Second level routines for the cbc stand-alone solver. +*/ + +#include "CbcConfig.h" +#include "CoinPragma.hpp" + +#include "CoinTime.hpp" + +#include "OsiClpSolverInterface.hpp" + +#include "ClpPresolve.hpp" + +#include "CbcOrClpParam.hpp" + +#include "CbcModel.hpp" + +#include "CbcHeuristicLocal.hpp" +#include "CbcHeuristicPivotAndFix.hpp" +//#include "CbcHeuristicPivotAndComplement.hpp" +#include "CbcHeuristicRandRound.hpp" +#include "CbcHeuristicGreedy.hpp" +#include "CbcHeuristicFPump.hpp" +#include "CbcHeuristicRINS.hpp" +#include "CbcHeuristicDW.hpp" +#include "CbcHeuristicVND.hpp" + +#include "CbcHeuristicDiveCoefficient.hpp" +#include "CbcHeuristicDiveFractional.hpp" +#include "CbcHeuristicDiveGuided.hpp" +#include "CbcHeuristicDiveVectorLength.hpp" +#include "CbcHeuristicDivePseudoCost.hpp" +#include "CbcHeuristicDiveLineSearch.hpp" + +#include "CbcStrategy.hpp" +#include "OsiAuxInfo.hpp" + +#include "ClpSimplexOther.hpp" + +// Crunch down model +void crunchIt(ClpSimplex *model) +{ +#ifdef JJF_ZERO + model->dual(); +#else + int numberColumns = model->numberColumns(); + int numberRows = model->numberRows(); + // Use dual region + double *rhs = model->dualRowSolution(); + int *whichRow = new int[3 * numberRows]; + int *whichColumn = new int[2 * numberColumns]; + int nBound; + ClpSimplex *small = static_cast< ClpSimplexOther * >(model)->crunch(rhs, whichRow, whichColumn, + nBound, false, false); + if (small) { + small->dual(); + if (small->problemStatus() == 0) { + model->setProblemStatus(0); + static_cast< ClpSimplexOther * >(model)->afterCrunch(*small, whichRow, whichColumn, nBound); + } else if (small->problemStatus() != 3) { + model->setProblemStatus(1); + } else { + if (small->problemStatus() == 3) { + // may be problems + small->computeObjectiveValue(); + model->setObjectiveValue(small->objectiveValue()); + model->setProblemStatus(3); + } else { + model->setProblemStatus(3); + } + } + delete small; + } else { + model->setProblemStatus(1); + } + delete[] whichRow; + delete[] whichColumn; +#endif +} +/* + On input + doAction - 0 just fix in original and return NULL + 1 return fixed non-presolved solver + 2 as one but use presolve Inside this + 3 use presolve and fix ones with large cost + ? do heuristics and set best solution + ? do BAB and just set best solution + 10+ then use lastSolution and relax a few + -2 cleanup afterwards if using 2 + On output - number fixed +*/ +OsiClpSolverInterface * +fixVubs(CbcModel &model, int skipZero2, + int &doAction, + CoinMessageHandler * /*generalMessageHandler*/, + const double *lastSolution, double dextra[6], + int extra[5]) +{ + if (doAction == 11 && !lastSolution) + lastSolution = model.bestSolution(); + assert(((doAction >= 0 && doAction <= 3) && !lastSolution) || (doAction == 11 && lastSolution)); + double fractionIntFixed = dextra[3]; + double fractionFixed = dextra[4]; + double fixAbove = dextra[2]; + double fixAboveValue = (dextra[5] > 0.0) ? dextra[5] : 1.0; +#ifdef COIN_DETAIL + double time1 = CoinCpuTime(); +#endif + int leaveIntFree = extra[1]; + OsiSolverInterface *originalSolver = model.solver(); + OsiClpSolverInterface *originalClpSolver = dynamic_cast< OsiClpSolverInterface * >(originalSolver); + ClpSimplex *originalLpSolver = originalClpSolver->getModelPtr(); + int *originalColumns = NULL; + OsiClpSolverInterface *clpSolver; + ClpSimplex *lpSolver; + ClpPresolve pinfo; + assert(originalSolver->getObjSense() > 0); + if (doAction == 2 || doAction == 3) { + double *saveLB = NULL; + double *saveUB = NULL; + int numberColumns = originalLpSolver->numberColumns(); + if (fixAbove > 0.0) { +#ifdef COIN_DETAIL + double time1 = CoinCpuTime(); +#endif + originalClpSolver->initialSolve(); + COIN_DETAIL_PRINT(printf("first solve took %g seconds\n", CoinCpuTime() - time1)); + double *columnLower = originalLpSolver->columnLower(); + double *columnUpper = originalLpSolver->columnUpper(); + const double *solution = originalLpSolver->primalColumnSolution(); + saveLB = CoinCopyOfArray(columnLower, numberColumns); + saveUB = CoinCopyOfArray(columnUpper, numberColumns); + const double *objective = originalLpSolver->getObjCoefficients(); + int iColumn; + int nFix = 0; + int nArt = 0; + for (iColumn = 0; iColumn < numberColumns; iColumn++) { + if (objective[iColumn] > fixAbove) { + if (solution[iColumn] < columnLower[iColumn] + 1.0e-8) { + columnUpper[iColumn] = columnLower[iColumn]; + nFix++; + } else { + nArt++; + } + } else if (objective[iColumn] < -fixAbove) { + if (solution[iColumn] > columnUpper[iColumn] - 1.0e-8) { + columnLower[iColumn] = columnUpper[iColumn]; + nFix++; + } else { + nArt++; + } + } + } + COIN_DETAIL_PRINT(printf("%d artificials fixed, %d left as in solution\n", nFix, nArt)); + lpSolver = pinfo.presolvedModel(*originalLpSolver, 1.0e-8, true, 10); + if (!lpSolver || doAction == 2) { + // take off fixing in original + memcpy(columnLower, saveLB, numberColumns * sizeof(double)); + memcpy(columnUpper, saveUB, numberColumns * sizeof(double)); + } + delete[] saveLB; + delete[] saveUB; + if (!lpSolver) { + // try again + pinfo.destroyPresolve(); + lpSolver = pinfo.presolvedModel(*originalLpSolver, 1.0e-8, true, 10); + assert(lpSolver); + } + } else { + lpSolver = pinfo.presolvedModel(*originalLpSolver, 1.0e-8, true, 10); + assert(lpSolver); + } + clpSolver = new OsiClpSolverInterface(lpSolver, true); + assert(lpSolver == clpSolver->getModelPtr()); + numberColumns = lpSolver->numberColumns(); + originalColumns = CoinCopyOfArray(pinfo.originalColumns(), numberColumns); + doAction = 1; + } else { + OsiSolverInterface *solver = originalSolver->clone(); + clpSolver = dynamic_cast< OsiClpSolverInterface * >(solver); + lpSolver = clpSolver->getModelPtr(); + } + // Tighten bounds + lpSolver->tightenPrimalBounds(0.0, 11, true); + int numberColumns = clpSolver->getNumCols(); + double *saveColumnLower = CoinCopyOfArray(lpSolver->columnLower(), numberColumns); + double *saveColumnUpper = CoinCopyOfArray(lpSolver->columnUpper(), numberColumns); + //char generalPrint[200]; + const double *objective = lpSolver->getObjCoefficients(); + double *columnLower = lpSolver->columnLower(); + double *columnUpper = lpSolver->columnUpper(); + int numberRows = clpSolver->getNumRows(); + int iRow, iColumn; + + // Row copy + CoinPackedMatrix matrixByRow(*clpSolver->getMatrixByRow()); + const double *elementByRow = matrixByRow.getElements(); + const int *column = matrixByRow.getIndices(); + const CoinBigIndex *rowStart = matrixByRow.getVectorStarts(); + const int *rowLength = matrixByRow.getVectorLengths(); + + // Column copy + CoinPackedMatrix matrixByCol(*clpSolver->getMatrixByCol()); + //const double * element = matrixByCol.getElements(); + const int *row = matrixByCol.getIndices(); + const CoinBigIndex *columnStart = matrixByCol.getVectorStarts(); + const int *columnLength = matrixByCol.getVectorLengths(); + + const double *rowLower = clpSolver->getRowLower(); + const double *rowUpper = clpSolver->getRowUpper(); + + // Get maximum size of VUB tree + // otherColumn is one fixed to 0 if this one zero + CoinBigIndex nEl = matrixByCol.getNumElements(); + CoinBigIndex *fixColumn = new CoinBigIndex[numberColumns + 1]; + int *otherColumn = new int[nEl]; + int *fix = new int[numberColumns]; + char *mark = new char[numberColumns]; + memset(mark, 0, numberColumns); + int numberInteger = 0; + int numberOther = 0; + fixColumn[0] = 0; + double large = lpSolver->largeValue(); // treat bounds > this as infinite +#ifndef NDEBUG + double large2 = 1.0e10 * large; +#endif + double tolerance = lpSolver->primalTolerance(); + int *check = new int[numberRows]; + for (iRow = 0; iRow < numberRows; iRow++) { + check[iRow] = -2; // don't check + if (rowLower[iRow] < -1.0e6 && rowUpper[iRow] > 1.0e6) + continue; // unlikely + // possible row + int numberPositive = 0; + int iPositive = -1; + int numberNegative = 0; + int iNegative = -1; + CoinBigIndex rStart = rowStart[iRow]; + CoinBigIndex rEnd = rowStart[iRow] + rowLength[iRow]; + CoinBigIndex j; + int kColumn; + for (j = rStart; j < rEnd; ++j) { + double value = elementByRow[j]; + kColumn = column[j]; + if (columnUpper[kColumn] > columnLower[kColumn]) { + if (value > 0.0) { + numberPositive++; + iPositive = kColumn; + } else { + numberNegative++; + iNegative = kColumn; + } + } + } + if (numberPositive == 1 && numberNegative == 1) + check[iRow] = -1; // try both + if (numberPositive == 1 && rowLower[iRow] > -1.0e20) + check[iRow] = iPositive; + else if (numberNegative == 1 && rowUpper[iRow] < 1.0e20) + check[iRow] = iNegative; + } + for (iColumn = 0; iColumn < numberColumns; iColumn++) { + fix[iColumn] = -1; + if (columnUpper[iColumn] > columnLower[iColumn] + 1.0e-8) { + if (clpSolver->isInteger(iColumn)) + numberInteger++; + if (columnLower[iColumn] == 0.0) { + bool infeasible = false; + fix[iColumn] = 0; + // fake upper bound + double saveUpper = columnUpper[iColumn]; + columnUpper[iColumn] = 0.0; + for (CoinBigIndex i = columnStart[iColumn]; + i < columnStart[iColumn] + columnLength[iColumn]; i++) { + iRow = row[i]; + if (check[iRow] != -1 && check[iRow] != iColumn) + continue; // unlikely + // possible row + int infiniteUpper = 0; + int infiniteLower = 0; + double maximumUp = 0.0; + double maximumDown = 0.0; + double newBound; + CoinBigIndex rStart = rowStart[iRow]; + CoinBigIndex rEnd = rowStart[iRow] + rowLength[iRow]; + CoinBigIndex j; + int kColumn; + // Compute possible lower and upper ranges + for (j = rStart; j < rEnd; ++j) { + double value = elementByRow[j]; + kColumn = column[j]; + if (value > 0.0) { + if (columnUpper[kColumn] >= large) { + ++infiniteUpper; + } else { + maximumUp += columnUpper[kColumn] * value; + } + if (columnLower[kColumn] <= -large) { + ++infiniteLower; + } else { + maximumDown += columnLower[kColumn] * value; + } + } else if (value < 0.0) { + if (columnUpper[kColumn] >= large) { + ++infiniteLower; + } else { + maximumDown += columnUpper[kColumn] * value; + } + if (columnLower[kColumn] <= -large) { + ++infiniteUpper; + } else { + maximumUp += columnLower[kColumn] * value; + } + } + } + // Build in a margin of error + maximumUp += 1.0e-8 * fabs(maximumUp); + maximumDown -= 1.0e-8 * fabs(maximumDown); + double maxUp = maximumUp + infiniteUpper * 1.0e31; + double maxDown = maximumDown - infiniteLower * 1.0e31; + if (maxUp <= rowUpper[iRow] + tolerance && maxDown >= rowLower[iRow] - tolerance) { + //printf("Redundant row in vubs %d\n",iRow); + } else { + if (maxUp < rowLower[iRow] - 100.0 * tolerance || maxDown > rowUpper[iRow] + 100.0 * tolerance) { + infeasible = true; + break; + } + double lower = rowLower[iRow]; + double upper = rowUpper[iRow]; + for (j = rStart; j < rEnd; ++j) { + double value = elementByRow[j]; + kColumn = column[j]; + double nowLower = columnLower[kColumn]; + double nowUpper = columnUpper[kColumn]; + if (value > 0.0) { + // positive value + if (lower > -large) { + if (!infiniteUpper) { + assert(nowUpper < large2); + newBound = nowUpper + (lower - maximumUp) / value; + // relax if original was large + if (fabs(maximumUp) > 1.0e8) + newBound -= 1.0e-12 * fabs(maximumUp); + } else if (infiniteUpper == 1 && nowUpper > large) { + newBound = (lower - maximumUp) / value; + // relax if original was large + if (fabs(maximumUp) > 1.0e8) + newBound -= 1.0e-12 * fabs(maximumUp); + } else { + newBound = -COIN_DBL_MAX; + } + if (newBound > nowLower + 1.0e-12 && newBound > -large) { + // Tighten the lower bound + // check infeasible (relaxed) + if (nowUpper < newBound) { + if (nowUpper - newBound < -100.0 * tolerance) { + infeasible = true; + break; + } + } + } + } + if (upper < large) { + if (!infiniteLower) { + assert(nowLower > -large2); + newBound = nowLower + (upper - maximumDown) / value; + // relax if original was large + if (fabs(maximumDown) > 1.0e8) + newBound += 1.0e-12 * fabs(maximumDown); + } else if (infiniteLower == 1 && nowLower < -large) { + newBound = (upper - maximumDown) / value; + // relax if original was large + if (fabs(maximumDown) > 1.0e8) + newBound += 1.0e-12 * fabs(maximumDown); + } else { + newBound = COIN_DBL_MAX; + } + if (newBound < nowUpper - 1.0e-12 && newBound < large) { + // Tighten the upper bound + // check infeasible (relaxed) + if (nowLower > newBound) { + if (newBound - nowLower < -100.0 * tolerance) { + infeasible = true; + break; + } else { + newBound = nowLower; + } + } + if (!newBound || (clpSolver->isInteger(kColumn) && newBound < 0.999)) { + // fix to zero + if (!mark[kColumn]) { + otherColumn[numberOther++] = kColumn; + mark[kColumn] = 1; + if (check[iRow] == -1) + check[iRow] = iColumn; + else + assert(check[iRow] == iColumn); + } + } + } + } + } else { + // negative value + if (lower > -large) { + if (!infiniteUpper) { + assert(nowLower < large2); + newBound = nowLower + (lower - maximumUp) / value; + // relax if original was large + if (fabs(maximumUp) > 1.0e8) + newBound += 1.0e-12 * fabs(maximumUp); + } else if (infiniteUpper == 1 && nowLower < -large) { + newBound = (lower - maximumUp) / value; + // relax if original was large + if (fabs(maximumUp) > 1.0e8) + newBound += 1.0e-12 * fabs(maximumUp); + } else { + newBound = COIN_DBL_MAX; + } + if (newBound < nowUpper - 1.0e-12 && newBound < large) { + // Tighten the upper bound + // check infeasible (relaxed) + if (nowLower > newBound) { + if (newBound - nowLower < -100.0 * tolerance) { + infeasible = true; + break; + } else { + newBound = nowLower; + } + } + if (!newBound || (clpSolver->isInteger(kColumn) && newBound < 0.999)) { + // fix to zero + if (!mark[kColumn]) { + otherColumn[numberOther++] = kColumn; + mark[kColumn] = 1; + if (check[iRow] == -1) + check[iRow] = iColumn; + else + assert(check[iRow] == iColumn); + } + } + } + } + if (upper < large) { + if (!infiniteLower) { + assert(nowUpper < large2); + newBound = nowUpper + (upper - maximumDown) / value; + // relax if original was large + if (fabs(maximumDown) > 1.0e8) + newBound -= 1.0e-12 * fabs(maximumDown); + } else if (infiniteLower == 1 && nowUpper > large) { + newBound = (upper - maximumDown) / value; + // relax if original was large + if (fabs(maximumDown) > 1.0e8) + newBound -= 1.0e-12 * fabs(maximumDown); + } else { + newBound = -COIN_DBL_MAX; + } + if (newBound > nowLower + 1.0e-12 && newBound > -large) { + // Tighten the lower bound + // check infeasible (relaxed) + if (nowUpper < newBound) { + if (nowUpper - newBound < -100.0 * tolerance) { + infeasible = true; + break; + } + } + } + } + } + } + } + } + for (CoinBigIndex i = fixColumn[iColumn]; i < numberOther; i++) + mark[otherColumn[i]] = 0; + // reset bound unless infeasible + if (!infeasible || !clpSolver->isInteger(iColumn)) + columnUpper[iColumn] = saveUpper; + else if (clpSolver->isInteger(iColumn)) + columnLower[iColumn] = 1.0; + } + } + fixColumn[iColumn + 1] = numberOther; + } + delete[] check; + delete[] mark; + // Now do reverse way + int *counts = new int[numberColumns]; + CoinZeroN(counts, numberColumns); + for (iColumn = 0; iColumn < numberColumns; iColumn++) { + for (CoinBigIndex i = fixColumn[iColumn]; i < fixColumn[iColumn + 1]; i++) + counts[otherColumn[i]]++; + } + numberOther = 0; + CoinBigIndex *fixColumn2 = new CoinBigIndex[numberColumns + 1]; + int *otherColumn2 = new int[fixColumn[numberColumns]]; + fixColumn2[0] = 0; + for (iColumn = 0; iColumn < numberColumns; iColumn++) { + numberOther += counts[iColumn]; + counts[iColumn] = 0; + fixColumn2[iColumn + 1] = numberOther; + } + // Create other way + for (iColumn = 0; iColumn < numberColumns; iColumn++) { + for (CoinBigIndex i = fixColumn[iColumn]; i < fixColumn[iColumn + 1]; i++) { + int jColumn = otherColumn[i]; + CoinBigIndex put = fixColumn2[jColumn] + counts[jColumn]; + counts[jColumn]++; + otherColumn2[put] = iColumn; + } + } + // get top layer i.e. those which are not fixed by any other + int kLayer = 0; + while (true) { + int numberLayered = 0; + for (iColumn = 0; iColumn < numberColumns; iColumn++) { + if (fix[iColumn] == kLayer) { + for (CoinBigIndex i = fixColumn2[iColumn]; i < fixColumn2[iColumn + 1]; i++) { + int jColumn = otherColumn2[i]; + if (fix[jColumn] == kLayer) { + fix[iColumn] = kLayer + 100; + } + } + } + if (fix[iColumn] == kLayer) { + numberLayered++; + } + } + if (numberLayered) { + kLayer += 100; + } else { + break; + } + } + for (int iPass = 0; iPass < 2; iPass++) { + for (int jLayer = 0; jLayer < kLayer; jLayer++) { + int check[] = { -1, 0, 1, 2, 3, 4, 5, 10, 50, 100, 500, 1000, 5000, 10000, COIN_INT_MAX }; + int nCheck = static_cast< int >(sizeof(check) / sizeof(int)); + int countsI[20]; + int countsC[20]; + assert(nCheck <= 20); + memset(countsI, 0, nCheck * sizeof(int)); + memset(countsC, 0, nCheck * sizeof(int)); + check[nCheck - 1] = numberColumns; + int numberLayered = 0; + int numberInteger = 0; + for (iColumn = 0; iColumn < numberColumns; iColumn++) { + if (fix[iColumn] == jLayer) { + numberLayered++; + int nFix = static_cast< int >(fixColumn[iColumn + 1] - fixColumn[iColumn]); + if (iPass) { + // just integers + nFix = 0; + for (CoinBigIndex i = fixColumn[iColumn]; i < fixColumn[iColumn + 1]; i++) { + int jColumn = otherColumn[i]; + if (clpSolver->isInteger(jColumn)) + nFix++; + } + } + int iFix; + for (iFix = 0; iFix < nCheck; iFix++) { + if (nFix <= check[iFix]) + break; + } + assert(iFix < nCheck); + if (clpSolver->isInteger(iColumn)) { + numberInteger++; + countsI[iFix]++; + } else { + countsC[iFix]++; + } + } + } +#ifdef COIN_DETAIL + if (numberLayered) { + printf("%d (%d integer) at priority %d\n", numberLayered, numberInteger, 1 + (jLayer / 100)); + char buffer[50]; + for (int i = 1; i < nCheck; i++) { + if (countsI[i] || countsC[i]) { + if (i == 1) + sprintf(buffer, " == zero "); + else if (i < nCheck - 1) + sprintf(buffer, "> %6d and <= %6d ", check[i - 1], check[i]); + else + sprintf(buffer, "> %6d ", check[i - 1]); + printf("%s %8d integers and %8d continuous\n", buffer, countsI[i], countsC[i]); + } + } + } +#endif + } + } + delete[] counts; + // Now do fixing + { + // switch off presolve and up weight + ClpSolve solveOptions; + //solveOptions.setPresolveType(ClpSolve::presolveOff,0); + solveOptions.setSolveType(ClpSolve::usePrimalorSprint); + //solveOptions.setSpecialOption(1,3,30); // sprint + int numberColumns = lpSolver->numberColumns(); + int iColumn; + bool allSlack = true; + for (iColumn = 0; iColumn < numberColumns; iColumn++) { + if (lpSolver->getColumnStatus(iColumn) == ClpSimplex::basic) { + allSlack = false; + break; + } + } + if (allSlack) + solveOptions.setSpecialOption(1, 2, 50); // idiot + lpSolver->setInfeasibilityCost(1.0e11); + lpSolver->defaultFactorizationFrequency(); + if (doAction != 11) + lpSolver->initialSolve(solveOptions); + double *columnLower = lpSolver->columnLower(); + double *columnUpper = lpSolver->columnUpper(); + double *fullSolution = lpSolver->primalColumnSolution(); + const double *dj = lpSolver->dualColumnSolution(); + int iPass = 0; +#define MAXPROB 2 + ClpSimplex models[MAXPROB]; + int kPass = -1; + int kLayer = 0; + int skipZero = 0; + if (skipZero2 == -1) + skipZero2 = 40; //-1; + /* 0 fixed to 0 by choice + 1 lb of 1 by choice + 2 fixed to 0 by another + 3 as 2 but this go + -1 free + */ + char *state = new char[numberColumns]; + for (iColumn = 0; iColumn < numberColumns; iColumn++) + state[iColumn] = -1; + while (true) { + double largest = -0.1; + double smallest = 1.1; + int iLargest = -1; + int iSmallest = -1; + int atZero = 0; + int atOne = 0; + int toZero = 0; + int toOne = 0; + int numberFree = 0; + int numberGreater = 0; + columnLower = lpSolver->columnLower(); + columnUpper = lpSolver->columnUpper(); + fullSolution = lpSolver->primalColumnSolution(); + if (doAction == 11) { + { + double *columnLower = lpSolver->columnLower(); + double *columnUpper = lpSolver->columnUpper(); + // lpSolver->dual(); + memcpy(columnLower, saveColumnLower, numberColumns * sizeof(double)); + memcpy(columnUpper, saveColumnUpper, numberColumns * sizeof(double)); + // lpSolver->dual(); + int iColumn; + for (iColumn = 0; iColumn < numberColumns; iColumn++) { + if (columnUpper[iColumn] > columnLower[iColumn] + 1.0e-8) { + if (clpSolver->isInteger(iColumn)) { + double value = lastSolution[iColumn]; + int iValue = static_cast< int >(value + 0.5); + assert(fabs(value - static_cast< double >(iValue)) < 1.0e-3); + assert(iValue >= columnLower[iColumn] && iValue <= columnUpper[iColumn]); + columnLower[iColumn] = iValue; + columnUpper[iColumn] = iValue; + } + } + } + lpSolver->initialSolve(solveOptions); + memcpy(columnLower, saveColumnLower, numberColumns * sizeof(double)); + memcpy(columnUpper, saveColumnUpper, numberColumns * sizeof(double)); + } + for (iColumn = 0; iColumn < numberColumns; iColumn++) { + if (columnUpper[iColumn] > columnLower[iColumn] + 1.0e-8) { + if (clpSolver->isInteger(iColumn)) { + double value = lastSolution[iColumn]; + int iValue = static_cast< int >(value + 0.5); + assert(fabs(value - static_cast< double >(iValue)) < 1.0e-3); + assert(iValue >= columnLower[iColumn] && iValue <= columnUpper[iColumn]); + if (!fix[iColumn]) { + if (iValue == 0) { + state[iColumn] = 0; + assert(!columnLower[iColumn]); + columnUpper[iColumn] = 0.0; + } else if (iValue == 1) { + state[iColumn] = 1; + columnLower[iColumn] = 1.0; + } else { + // leave fixed + columnLower[iColumn] = iValue; + columnUpper[iColumn] = iValue; + } + } else if (iValue == 0) { + state[iColumn] = 10; + columnUpper[iColumn] = 0.0; + } else { + // leave fixed + columnLower[iColumn] = iValue; + columnUpper[iColumn] = iValue; + } + } + } + } + int jLayer = 0; + int nFixed = -1; + int nTotalFixed = 0; + while (nFixed) { + nFixed = 0; + for (iColumn = 0; iColumn < numberColumns; iColumn++) { + if (columnUpper[iColumn] == 0.0 && fix[iColumn] == jLayer) { + for (CoinBigIndex i = fixColumn[iColumn]; i < fixColumn[iColumn + 1]; i++) { + int jColumn = otherColumn[i]; + if (columnUpper[jColumn]) { + bool canFix = true; + for (CoinBigIndex k = fixColumn2[jColumn]; k < fixColumn2[jColumn + 1]; k++) { + int kColumn = otherColumn2[k]; + if (state[kColumn] == 1) { + canFix = false; + break; + } + } + if (canFix) { + columnUpper[jColumn] = 0.0; + nFixed++; + } + } + } + } + } + nTotalFixed += nFixed; + jLayer += 100; + } + COIN_DETAIL_PRINT(printf("This fixes %d variables in lower priorities\n", nTotalFixed)); + break; + } + for (iColumn = 0; iColumn < numberColumns; iColumn++) { + if (!clpSolver->isInteger(iColumn) || fix[iColumn] > kLayer) + continue; + // skip if fixes nothing + if (fixColumn[iColumn + 1] - fixColumn[iColumn] <= skipZero2) + continue; + double value = fullSolution[iColumn]; + if (value > 1.00001) { + numberGreater++; + continue; + } + double lower = columnLower[iColumn]; + double upper = columnUpper[iColumn]; + if (lower == upper) { + if (lower) + atOne++; + else + atZero++; + continue; + } + if (value < 1.0e-7) { + toZero++; + columnUpper[iColumn] = 0.0; + state[iColumn] = 10; + continue; + } + if (value > 1.0 - 1.0e-7) { + toOne++; + columnLower[iColumn] = 1.0; + state[iColumn] = 1; + continue; + } + numberFree++; + // skip if fixes nothing + if (fixColumn[iColumn + 1] - fixColumn[iColumn] <= skipZero) + continue; + if (value < smallest) { + smallest = value; + iSmallest = iColumn; + } + if (value > largest) { + largest = value; + iLargest = iColumn; + } + } + if (toZero || toOne) + COIN_DETAIL_PRINT(printf("%d at 0 fixed and %d at one fixed\n", toZero, toOne)); + COIN_DETAIL_PRINT(printf("%d variables free, %d fixed to 0, %d to 1 - smallest %g, largest %g\n", + numberFree, atZero, atOne, smallest, largest)); + if (numberGreater && !iPass) + COIN_DETAIL_PRINT(printf("%d variables have value > 1.0\n", numberGreater)); + //skipZero2=0; // leave 0 fixing + int jLayer = 0; + int nFixed = -1; + int nTotalFixed = 0; + while (nFixed) { + nFixed = 0; + for (iColumn = 0; iColumn < numberColumns; iColumn++) { + if (columnUpper[iColumn] == 0.0 && fix[iColumn] == jLayer) { + for (CoinBigIndex i = fixColumn[iColumn]; i < fixColumn[iColumn + 1]; i++) { + int jColumn = otherColumn[i]; + if (columnUpper[jColumn]) { + bool canFix = true; + for (CoinBigIndex k = fixColumn2[jColumn]; k < fixColumn2[jColumn + 1]; k++) { + int kColumn = otherColumn2[k]; + if (state[kColumn] == 1) { + canFix = false; + break; + } + } + if (canFix) { + columnUpper[jColumn] = 0.0; + nFixed++; + } + } + } + } + } + nTotalFixed += nFixed; + jLayer += 100; + } + COIN_DETAIL_PRINT(printf("This fixes %d variables in lower priorities\n", nTotalFixed)); + if (iLargest < 0 || numberFree <= leaveIntFree) + break; + double movement; + int way; + if (smallest <= 1.0 - largest && smallest < 0.2 && largest < fixAboveValue) { + columnUpper[iSmallest] = 0.0; + state[iSmallest] = 0; + movement = smallest; + way = -1; + } else { + columnLower[iLargest] = 1.0; + state[iLargest] = 1; + movement = 1.0 - largest; + way = 1; + } + double saveObj = lpSolver->objectiveValue(); + iPass++; + kPass = iPass % MAXPROB; + models[kPass] = *lpSolver; + if (way == -1) { + // fix others + for (CoinBigIndex i = fixColumn[iSmallest]; i < fixColumn[iSmallest + 1]; i++) { + int jColumn = otherColumn[i]; + if (state[jColumn] == -1) { + columnUpper[jColumn] = 0.0; + state[jColumn] = 3; + } + } + } + double maxCostUp = COIN_DBL_MAX; + objective = lpSolver->getObjCoefficients(); + if (way == -1) + maxCostUp = (1.0 - movement) * objective[iSmallest]; + lpSolver->setDualObjectiveLimit(saveObj + maxCostUp); + crunchIt(lpSolver); + double moveObj = lpSolver->objectiveValue() - saveObj; + COIN_DETAIL_PRINT(printf("movement %s was %g costing %g\n", + (way == -1) ? "down" : "up", movement, moveObj)); + if (way == -1 && (moveObj >= maxCostUp || lpSolver->status())) { + // go up + columnLower = models[kPass].columnLower(); + columnUpper = models[kPass].columnUpper(); + columnLower[iSmallest] = 1.0; + columnUpper[iSmallest] = saveColumnUpper[iSmallest]; + *lpSolver = models[kPass]; + columnLower = lpSolver->columnLower(); + columnUpper = lpSolver->columnUpper(); + fullSolution = lpSolver->primalColumnSolution(); + dj = lpSolver->dualColumnSolution(); + columnLower[iSmallest] = 1.0; + columnUpper[iSmallest] = saveColumnUpper[iSmallest]; + state[iSmallest] = 1; + // unfix others + for (CoinBigIndex i = fixColumn[iSmallest]; i < fixColumn[iSmallest + 1]; i++) { + int jColumn = otherColumn[i]; + if (state[jColumn] == 3) { + columnUpper[jColumn] = saveColumnUpper[jColumn]; + state[jColumn] = -1; + } + } + crunchIt(lpSolver); + } + models[kPass] = *lpSolver; + } + lpSolver->dual(); + COIN_DETAIL_PRINT(printf("Fixing took %g seconds\n", CoinCpuTime() - time1)); + columnLower = lpSolver->columnLower(); + columnUpper = lpSolver->columnUpper(); + fullSolution = lpSolver->primalColumnSolution(); + dj = lpSolver->dualColumnSolution(); + int *sort = new int[numberColumns]; + double *dsort = new double[numberColumns]; + int chunk = 20; + int iRelax = 0; + //double fractionFixed=6.0/8.0; + // relax while lots fixed + while (true) { + if (skipZero2 > 10 && doAction < 10) + break; + iRelax++; + int n = 0; + double sum0 = 0.0; + double sum00 = 0.0; + double sum1 = 0.0; + for (iColumn = 0; iColumn < numberColumns; iColumn++) { + if (!clpSolver->isInteger(iColumn) || fix[iColumn] > kLayer) + continue; + // skip if fixes nothing + if (fixColumn[iColumn + 1] - fixColumn[iColumn] == 0 && doAction < 10) + continue; + double djValue = dj[iColumn]; + if (state[iColumn] == 1) { + assert(columnLower[iColumn]); + assert(fullSolution[iColumn] > 0.1); + if (djValue > 0.0) { + //printf("YY dj of %d at %g is %g\n",iColumn,value,djValue); + sum1 += djValue; + sort[n] = iColumn; + dsort[n++] = -djValue; + } else { + //printf("dj of %d at %g is %g\n",iColumn,value,djValue); + } + } else if (state[iColumn] == 0 || state[iColumn] == 10) { + assert(fullSolution[iColumn] < 0.1); + assert(!columnUpper[iColumn]); + double otherValue = 0.0; + int nn = 0; + for (CoinBigIndex i = fixColumn[iColumn]; i < fixColumn[iColumn + 1]; i++) { + int jColumn = otherColumn[i]; + if (columnUpper[jColumn] == 0.0) { + if (dj[jColumn] < -1.0e-5) { + nn++; + otherValue += dj[jColumn]; // really need to look at rest + } + } + } + if (djValue < -1.0e-2 || otherValue < -1.0e-2) { + //printf("XX dj of %d at %g is %g - %d out of %d contribute %g\n",iColumn,value,djValue, + // nn,fixColumn[iColumn+1]-fixColumn[iColumn],otherValue); + if (djValue < 1.0e-8) { + sum0 -= djValue; + sum00 -= otherValue; + sort[n] = iColumn; + if (djValue < -1.0e-2) + dsort[n++] = djValue + otherValue; + else + dsort[n++] = djValue + 0.001 * otherValue; + } + } else { + //printf("dj of %d at %g is %g - no contribution from %d\n",iColumn,value,djValue, + // fixColumn[iColumn+1]-fixColumn[iColumn]); + } + } + } + CoinSort_2(dsort, dsort + n, sort); + double *originalColumnLower = saveColumnLower; + double *originalColumnUpper = saveColumnUpper; + double *lo = CoinCopyOfArray(columnLower, numberColumns); + double *up = CoinCopyOfArray(columnUpper, numberColumns); + for (int k = 0; k < CoinMin(chunk, n); k++) { + iColumn = sort[k]; + state[iColumn] = -2; + } + memcpy(columnLower, originalColumnLower, numberColumns * sizeof(double)); + memcpy(columnUpper, originalColumnUpper, numberColumns * sizeof(double)); + int nFixed = 0; + int nFixed0 = 0; + int nFixed1 = 0; + for (iColumn = 0; iColumn < numberColumns; iColumn++) { + if (state[iColumn] == 0 || state[iColumn] == 10) { + columnUpper[iColumn] = 0.0; + assert(lo[iColumn] == 0.0); + nFixed++; + nFixed0++; + for (CoinBigIndex i = fixColumn[iColumn]; i < fixColumn[iColumn + 1]; i++) { + int jColumn = otherColumn[i]; + if (columnUpper[jColumn]) { + bool canFix = true; + for (CoinBigIndex k = fixColumn2[jColumn]; k < fixColumn2[jColumn + 1]; k++) { + int kColumn = otherColumn2[k]; + if (state[kColumn] == 1 || state[kColumn] == -2) { + canFix = false; + break; + } + } + if (canFix) { + columnUpper[jColumn] = 0.0; + assert(lo[jColumn] == 0.0); + nFixed++; + } + } + } + } else if (state[iColumn] == 1) { + columnLower[iColumn] = 1.0; + nFixed1++; + } + } + COIN_DETAIL_PRINT(printf("%d fixed %d orig 0 %d 1\n", nFixed, nFixed0, nFixed1)); + int jLayer = 0; + nFixed = -1; + int nTotalFixed = 0; + while (nFixed) { + nFixed = 0; + for (iColumn = 0; iColumn < numberColumns; iColumn++) { + if (columnUpper[iColumn] == 0.0 && fix[iColumn] == jLayer) { + for (CoinBigIndex i = fixColumn[iColumn]; i < fixColumn[iColumn + 1]; i++) { + int jColumn = otherColumn[i]; + if (columnUpper[jColumn]) { + bool canFix = true; + for (CoinBigIndex k = fixColumn2[jColumn]; k < fixColumn2[jColumn + 1]; k++) { + int kColumn = otherColumn2[k]; + if (state[kColumn] == 1 || state[kColumn] == -2) { + canFix = false; + break; + } + } + if (canFix) { + columnUpper[jColumn] = 0.0; + assert(lo[jColumn] == 0.0); + nFixed++; + } + } + } + } + } + nTotalFixed += nFixed; + jLayer += 100; + } + nFixed = 0; + int nFixedI = 0; + for (iColumn = 0; iColumn < numberColumns; iColumn++) { + if (columnLower[iColumn] == columnUpper[iColumn]) { + if (clpSolver->isInteger(iColumn)) + nFixedI++; + nFixed++; + } + } + COIN_DETAIL_PRINT(printf("This fixes %d variables in lower priorities - total %d (%d integer) - all target %d, int target %d\n", + nTotalFixed, nFixed, nFixedI, static_cast< int >(fractionFixed * numberColumns), static_cast< int >(fractionIntFixed * numberInteger))); + int nBad = 0; + int nRelax = 0; + for (iColumn = 0; iColumn < numberColumns; iColumn++) { + if (lo[iColumn] < columnLower[iColumn] || up[iColumn] > columnUpper[iColumn]) { + COIN_DETAIL_PRINT(printf("bad %d old %g %g, new %g %g\n", iColumn, lo[iColumn], up[iColumn], + columnLower[iColumn], columnUpper[iColumn])); + nBad++; + } + if (lo[iColumn] > columnLower[iColumn] || up[iColumn] < columnUpper[iColumn]) { + nRelax++; + } + } + COIN_DETAIL_PRINT(printf("%d relaxed\n", nRelax)); + if (iRelax > 20 && nRelax == chunk) + nRelax = 0; + if (iRelax > 50) + nRelax = 0; + assert(!nBad); + delete[] lo; + delete[] up; + lpSolver->primal(1); + if (nFixed < fractionFixed * numberColumns || nFixedI < fractionIntFixed * numberInteger || !nRelax) + break; + } + delete[] state; + delete[] sort; + delete[] dsort; + } + delete[] fix; + delete[] fixColumn; + delete[] otherColumn; + delete[] otherColumn2; + delete[] fixColumn2; + // See if was presolved + if (originalColumns) { + columnLower = lpSolver->columnLower(); + columnUpper = lpSolver->columnUpper(); + for (iColumn = 0; iColumn < numberColumns; iColumn++) { + saveColumnLower[iColumn] = columnLower[iColumn]; + saveColumnUpper[iColumn] = columnUpper[iColumn]; + } + pinfo.postsolve(true); + columnLower = originalLpSolver->columnLower(); + columnUpper = originalLpSolver->columnUpper(); + double *newColumnLower = lpSolver->columnLower(); + double *newColumnUpper = lpSolver->columnUpper(); + for (iColumn = 0; iColumn < numberColumns; iColumn++) { + int jColumn = originalColumns[iColumn]; + columnLower[jColumn] = CoinMax(columnLower[jColumn], newColumnLower[iColumn]); + columnUpper[jColumn] = CoinMin(columnUpper[jColumn], newColumnUpper[iColumn]); + } + numberColumns = originalLpSolver->numberColumns(); + delete[] originalColumns; + } + delete[] saveColumnLower; + delete[] saveColumnUpper; + if (!originalColumns) { + // Basis + memcpy(originalLpSolver->statusArray(), lpSolver->statusArray(), numberRows + numberColumns); + memcpy(originalLpSolver->primalColumnSolution(), lpSolver->primalColumnSolution(), numberColumns * sizeof(double)); + memcpy(originalLpSolver->primalRowSolution(), lpSolver->primalRowSolution(), numberRows * sizeof(double)); + // Fix in solver + columnLower = lpSolver->columnLower(); + columnUpper = lpSolver->columnUpper(); + } + double *originalColumnLower = originalLpSolver->columnLower(); + double *originalColumnUpper = originalLpSolver->columnUpper(); + // number fixed + doAction = 0; + for (iColumn = 0; iColumn < numberColumns; iColumn++) { + originalColumnLower[iColumn] = columnLower[iColumn]; + originalColumnUpper[iColumn] = columnUpper[iColumn]; + if (columnLower[iColumn] == columnUpper[iColumn]) + doAction++; + } + COIN_DETAIL_PRINT(printf("%d fixed by vub preprocessing\n", doAction)); + if (originalColumns) { + originalLpSolver->initialSolve(); + } + delete clpSolver; + return NULL; +} + +int doHeuristics(CbcModel *model, int type, std::vector< CbcOrClpParam > parameters_, + int noPrinting_, int initialPumpTune) +{ +#ifdef JJF_ZERO //NEW_STYLE_SOLVER==0 + CbcOrClpParam *parameters_ = parameters; + int numberParameters_ = numberParameters; + bool noPrinting_ = noPrinting_; +#endif + char generalPrint[10000]; + CoinMessages generalMessages = model->messages(); + CoinMessageHandler *generalMessageHandler = model->messageHandler(); + //generalMessageHandler->setPrefix(false); + bool anyToDo = false; + int logLevel = parameters_[whichParam(CLP_PARAM_INT_LOGLEVEL, parameters_)].intValue(); + int useFpump = parameters_[whichParam(CBC_PARAM_STR_FPUMP, parameters_)].currentOptionAsInteger(); + int useRounding = parameters_[whichParam(CBC_PARAM_STR_ROUNDING, parameters_)].currentOptionAsInteger(); + int useGreedy = parameters_[whichParam(CBC_PARAM_STR_GREEDY, parameters_)].currentOptionAsInteger(); + int useCombine = parameters_[whichParam(CBC_PARAM_STR_COMBINE, parameters_)].currentOptionAsInteger(); + int useProximity = parameters_[whichParam(CBC_PARAM_STR_PROXIMITY, parameters_)].currentOptionAsInteger(); + int useCrossover = parameters_[whichParam(CBC_PARAM_STR_CROSSOVER2, parameters_)].currentOptionAsInteger(); + //int usePivotC = parameters_[whichParam(CBC_PARAM_STR_PIVOTANDCOMPLEMENT, parameters_)].currentOptionAsInteger(); + int usePivotF = parameters_[whichParam(CBC_PARAM_STR_PIVOTANDFIX, parameters_)].currentOptionAsInteger(); + int useRand = parameters_[whichParam(CBC_PARAM_STR_RANDROUND, parameters_)].currentOptionAsInteger(); + int useRINS = parameters_[whichParam(CBC_PARAM_STR_RINS, parameters_)].currentOptionAsInteger(); + int useRENS = parameters_[whichParam(CBC_PARAM_STR_RENS, parameters_)].currentOptionAsInteger(); + int useVND = parameters_[whichParam(CBC_PARAM_STR_VND, parameters_)].currentOptionAsInteger(); + int useDINS = parameters_[whichParam(CBC_PARAM_STR_DINS, parameters_)].currentOptionAsInteger(); + int useDIVING2 = parameters_[whichParam(CBC_PARAM_STR_DIVINGS, parameters_)].currentOptionAsInteger(); + int useNaive = parameters_[whichParam(CBC_PARAM_STR_NAIVE, parameters_)].currentOptionAsInteger(); + int useDW = parameters_[whichParam(CBC_PARAM_STR_DW, parameters_)].currentOptionAsInteger(); + int kType = (type < 10) ? type : 1; + assert(kType == 1 || kType == 2); + // FPump done first as it only works if no solution + if (useFpump >= kType && useFpump <= kType + 1) { + anyToDo = true; + CbcHeuristicFPump heuristic4(*model); + double dextra3 = parameters_[whichParam(CBC_PARAM_DBL_SMALLBAB, parameters_)].doubleValue(); + heuristic4.setFractionSmall(dextra3); + double dextra1 = parameters_[whichParam(CBC_PARAM_DBL_ARTIFICIALCOST, parameters_)].doubleValue(); + if (dextra1) + heuristic4.setArtificialCost(dextra1); + heuristic4.setMaximumPasses(parameters_[whichParam(CBC_PARAM_INT_FPUMPITS, parameters_)].intValue()); + if (parameters_[whichParam(CBC_PARAM_INT_FPUMPITS, parameters_)].intValue() == 21) + heuristic4.setIterationRatio(1.0); + int pumpTune = parameters_[whichParam(CBC_PARAM_INT_FPUMPTUNE, parameters_)].intValue(); + int pumpTune2 = parameters_[whichParam(CBC_PARAM_INT_FPUMPTUNE2, parameters_)].intValue(); + if (pumpTune > 0) { + bool printStuff = (pumpTune != initialPumpTune || logLevel > 1 || pumpTune2 > 0) + && !noPrinting_; + if (printStuff) { + generalMessageHandler->message(CBC_GENERAL, generalMessages) + << "Options for feasibility pump - " + << CoinMessageEol; + } + /* + >=10000000 for using obj + >=1000000 use as accumulate switch + >=1000 use index+1 as number of large loops + >=100 use dextra1 as cutoff + %100 == 10,20 etc for experimentation + 1 == fix ints at bounds, 2 fix all integral ints, 3 and continuous at bounds + 4 and static continuous, 5 as 3 but no internal integers + 6 as 3 but all slack basis! + */ + double value = model->solver()->getObjSense() * model->solver()->getObjValue(); + int w = pumpTune / 10; + int i = w % 10; + w /= 10; + int c = w % 10; + w /= 10; + int r = w; + int accumulate = r / 1000; + r -= 1000 * accumulate; + if (accumulate >= 100) { + int which = accumulate / 100; + accumulate -= 100 * which; + which--; + // weights and factors + double weight[] = { 0.01, 0.01, 0.1, 0.1, 0.5, 0.5, 1.0, 1.0, 5.0, 5.0 }; + double factor[] = { 0.1, 0.5, 0.1, 0.5, 0.1, 0.5, 0.1, 0.5, 0.1, 0.5 }; + heuristic4.setInitialWeight(weight[which]); + heuristic4.setWeightFactor(factor[which]); + if (printStuff) { + sprintf(generalPrint, "Initial weight for objective %g, decay factor %g", + weight[which], factor[which]); + generalMessageHandler->message(CBC_GENERAL, generalMessages) + << generalPrint + << CoinMessageEol; + } + } + // fake cutoff + if (c) { + double cutoff; + model->solver()->getDblParam(OsiDualObjectiveLimit, cutoff); + cutoff = CoinMin(cutoff, value + 0.05 * fabs(value) * c); + double fakeCutoff = parameters_[whichParam(CBC_PARAM_DBL_FAKECUTOFF, parameters_)].doubleValue(); + if (fakeCutoff) + cutoff = fakeCutoff; + heuristic4.setFakeCutoff(cutoff); + if (printStuff) { + sprintf(generalPrint, "Fake cutoff of %g", cutoff); + generalMessageHandler->message(CBC_GENERAL, generalMessages) + << generalPrint + << CoinMessageEol; + } + } + int offRandomEtc = 0; + if (pumpTune2) { + if ((pumpTune2 / 1000) != 0) { + offRandomEtc = 1000000 * (pumpTune2 / 1000); + if (printStuff) { + generalMessageHandler->message(CBC_GENERAL, generalMessages) + << "Feasibility pump may run twice" + << CoinMessageEol; + } + pumpTune2 = pumpTune2 % 1000; + } + if ((pumpTune2 / 100) != 0) { + offRandomEtc += 100 * (pumpTune2 / 100); + if (printStuff) { + generalMessageHandler->message(CBC_GENERAL, generalMessages) + << "Not using randomized objective" + << CoinMessageEol; + } + } + int maxAllowed = pumpTune2 % 100; + if (maxAllowed) { + offRandomEtc += 1000 * maxAllowed; + if (printStuff) { + sprintf(generalPrint, "Fixing if same for %d passes", + maxAllowed); + generalMessageHandler->message(CBC_GENERAL, generalMessages) + << generalPrint + << CoinMessageEol; + } + } + } + if (accumulate) { + heuristic4.setAccumulate(accumulate); + if (printStuff) { + if (accumulate) { + sprintf(generalPrint, "Accumulate of %d", accumulate); + generalMessageHandler->message(CBC_GENERAL, generalMessages) + << generalPrint + << CoinMessageEol; + } + } + } + if (r) { + // also set increment + //double increment = (0.01*i+0.005)*(fabs(value)+1.0e-12); + double increment = 0.0; + double fakeIncrement = parameters_[whichParam(CBC_PARAM_DBL_FAKEINCREMENT, parameters_)].doubleValue(); + if (fakeIncrement) + increment = fakeIncrement; + if (increment >= 0.0) + heuristic4.setAbsoluteIncrement(increment); + else + heuristic4.setRelativeIncrement(-increment); + heuristic4.setMaximumRetries(r + 1); + if (printStuff) { + if (increment) { + if (increment > 0.0) + sprintf(generalPrint, "Absolute increment of %g", increment); + else + sprintf(generalPrint, "Relative increment of %g", -increment); + generalMessageHandler->message(CBC_GENERAL, generalMessages) + << generalPrint + << CoinMessageEol; + } + sprintf(generalPrint, "%d retries", r + 1); + generalMessageHandler->message(CBC_GENERAL, generalMessages) + << generalPrint + << CoinMessageEol; + } + } + if (i + offRandomEtc) { + heuristic4.setFeasibilityPumpOptions(i * 10 + offRandomEtc); + if (printStuff) { + sprintf(generalPrint, "Feasibility pump options of %d", + i * 10 + offRandomEtc); + generalMessageHandler->message(CBC_GENERAL, generalMessages) + << generalPrint + << CoinMessageEol; + } + } + pumpTune = pumpTune % 100; + if (pumpTune == 6) + pumpTune = 13; + heuristic4.setWhen((pumpTune % 10) + 10); + if (printStuff) { + sprintf(generalPrint, "Tuning (fixing) %d", pumpTune % 10); + generalMessageHandler->message(CBC_GENERAL, generalMessages) + << generalPrint + << CoinMessageEol; + } + } + heuristic4.setHeuristicName("feasibility pump"); + //#define ROLF +#ifdef ROLF + CbcHeuristicFPump pump(*model); + pump.setMaximumTime(60); + pump.setMaximumPasses(100); + pump.setMaximumRetries(1); + pump.setFixOnReducedCosts(0); + pump.setHeuristicName("Feasibility pump"); + pump.setFractionSmall(1.0); + pump.setWhen(13); + model->addHeuristic(&pump); +#else + model->addHeuristic(&heuristic4); +#endif + } + if (useRounding >= type && useRounding >= kType && useRounding <= kType + 1) { + CbcRounding heuristic1(*model); + heuristic1.setHeuristicName("rounding"); + model->addHeuristic(&heuristic1); + anyToDo = true; + } + if (useGreedy >= type && useGreedy >= kType && useGreedy <= kType + 1) { + CbcHeuristicGreedyCover heuristic3(*model); + heuristic3.setHeuristicName("greedy cover"); + CbcHeuristicGreedyEquality heuristic3a(*model); + heuristic3a.setHeuristicName("greedy equality"); + model->addHeuristic(&heuristic3); + model->addHeuristic(&heuristic3a); + anyToDo = true; + } + if ((useRENS == 7 && kType == 1) || (useRENS == 8 && kType == 2)) { + useRENS = 1 + 2 * (useRENS - 7); + CbcHeuristicRENS heuristic6a(*model); + heuristic6a.setHeuristicName("RENSdj"); + heuristic6a.setFractionSmall(0.6 /*3.4*/); + heuristic6a.setFeasibilityPumpOptions(3); + heuristic6a.setNumberNodes(10); + heuristic6a.setWhereFrom(4 * 256 + 4 * 1); + heuristic6a.setWhen(2); + heuristic6a.setRensType(1 + 16); + model->addHeuristic(&heuristic6a); + heuristic6a.setHeuristicName("RENSub"); + heuristic6a.setFractionSmall(0.4); + heuristic6a.setFeasibilityPumpOptions(1008003); + heuristic6a.setNumberNodes(50); + heuristic6a.setWhereFrom(4 * 256 + 4 * 1); + heuristic6a.setWhen(2); + heuristic6a.setRensType(2 + 16); + model->addHeuristic(&heuristic6a); + } + if ((useRENS >= kType && useRENS <= kType + 1) || useRENS > 2) { + CbcHeuristicRENS heuristic6(*model); + heuristic6.setHeuristicName("RENS"); + heuristic6.setFractionSmall(0.4); + heuristic6.setFeasibilityPumpOptions(1008003); + int nodes[] = { -2, 50, 50, 50, 200, 1000, 10000, -1, -1, 200 }; + heuristic6.setNumberNodes(nodes[useRENS]); + heuristic6.setRensType(useRENS != 9 ? 0 : 32); + model->addHeuristic(&heuristic6); + anyToDo = true; + } + if (useVND >= kType && useVND <= kType + 1) { + CbcHeuristicVND heuristic6b(*model); + heuristic6b.setHeuristicName("VND"); + heuristic6b.setFractionSmall(0.4); + heuristic6b.setFeasibilityPumpOptions(1008003); + int nodes[] = { -2, 50, 50, 50, 200, 1000, 10000 }; + heuristic6b.setNumberNodes(nodes[useVND]); + model->addHeuristic(&heuristic6b); + anyToDo = true; + } + if (useNaive >= kType && useNaive <= kType + 1) { + CbcHeuristicNaive heuristic5b(*model); + heuristic5b.setHeuristicName("Naive"); + heuristic5b.setFractionSmall(0.4); + heuristic5b.setNumberNodes(50); + model->addHeuristic(&heuristic5b); + anyToDo = true; + } + int useDIVING = 0; + { + int useD; + useD = parameters_[whichParam(CBC_PARAM_STR_DIVINGV, parameters_)].currentOptionAsInteger(); + useDIVING |= 1 * ((useD >= kType) ? 1 : 0); + useD = parameters_[whichParam(CBC_PARAM_STR_DIVINGG, parameters_)].currentOptionAsInteger(); + useDIVING |= 2 * ((useD >= kType) ? 1 : 0); + useD = parameters_[whichParam(CBC_PARAM_STR_DIVINGF, parameters_)].currentOptionAsInteger(); + useDIVING |= 4 * ((useD >= kType) ? 1 : 0); + useD = parameters_[whichParam(CBC_PARAM_STR_DIVINGC, parameters_)].currentOptionAsInteger(); + useDIVING |= 8 * ((useD >= kType) ? 1 : 0); + useD = parameters_[whichParam(CBC_PARAM_STR_DIVINGL, parameters_)].currentOptionAsInteger(); + useDIVING |= 16 * ((useD >= kType) ? 1 : 0); + useD = parameters_[whichParam(CBC_PARAM_STR_DIVINGP, parameters_)].currentOptionAsInteger(); + useDIVING |= 32 * ((useD >= kType) ? 1 : 0); + } + if (useDIVING2 >= kType && useDIVING2 <= kType + 1) { + int diveOptions = parameters_[whichParam(CBC_PARAM_INT_DIVEOPT, parameters_)].intValue(); + if (diveOptions < 0 || diveOptions > 10) + diveOptions = 2; + CbcHeuristicJustOne heuristicJustOne(*model); + heuristicJustOne.setHeuristicName("DiveAny"); + heuristicJustOne.setWhen(diveOptions); + // add in others + CbcHeuristicDiveCoefficient heuristicDC(*model); + heuristicDC.setHeuristicName("DiveCoefficient"); + heuristicJustOne.addHeuristic(&heuristicDC, 1.0); + CbcHeuristicDiveFractional heuristicDF(*model); + heuristicDF.setHeuristicName("DiveFractional"); + heuristicJustOne.addHeuristic(&heuristicDF, 1.0); + CbcHeuristicDiveGuided heuristicDG(*model); + heuristicDG.setHeuristicName("DiveGuided"); + heuristicJustOne.addHeuristic(&heuristicDG, 1.0); + CbcHeuristicDiveLineSearch heuristicDL(*model); + heuristicDL.setHeuristicName("DiveLineSearch"); + heuristicJustOne.addHeuristic(&heuristicDL, 1.0); + CbcHeuristicDivePseudoCost heuristicDP(*model); + heuristicDP.setHeuristicName("DivePseudoCost"); + heuristicJustOne.addHeuristic(&heuristicDP, 1.0); + CbcHeuristicDiveVectorLength heuristicDV(*model); + heuristicDV.setHeuristicName("DiveVectorLength"); + heuristicJustOne.addHeuristic(&heuristicDV, 1.0); + // Now normalize probabilities + heuristicJustOne.normalizeProbabilities(); + model->addHeuristic(&heuristicJustOne); + } + + if (useDIVING > 0) { + int majorIterations = parameters_[whichParam(CBC_PARAM_INT_DIVEOPTSOLVES, parameters_)].intValue(); + int diveOptions2 = parameters_[whichParam(CBC_PARAM_INT_DIVEOPT, parameters_)].intValue(); + int diveOptions; + if (diveOptions2 > 99) { + // switch on various active set stuff + diveOptions = diveOptions2 % 100; + diveOptions2 /= 100; + } else { + diveOptions = diveOptions2; + diveOptions2 = 0; + } + if (diveOptions < 0 || diveOptions > 29) + diveOptions = 2; + int diveOptionsNotC = diveOptions; + if (diveOptions > 10) { + if (diveOptions > 20) { + diveOptions -= 20; + diveOptionsNotC -= 20; + } else { + diveOptions -= 10; + diveOptionsNotC = 4; + } + useDIVING = 63; + } + if ((useDIVING & 1) != 0) { + CbcHeuristicDiveVectorLength heuristicDV(*model); + heuristicDV.setHeuristicName("DiveVectorLength"); + heuristicDV.setWhen(diveOptionsNotC); + heuristicDV.setMaxIterations(majorIterations); + if (diveOptions2) { + heuristicDV.setPercentageToFix(0.0); + heuristicDV.setMaxSimplexIterations(COIN_INT_MAX); + heuristicDV.setMaxSimplexIterationsAtRoot(COIN_INT_MAX - (diveOptions2 - 1)); + } + model->addHeuristic(&heuristicDV); + } + if ((useDIVING & 2) != 0) { + CbcHeuristicDiveGuided heuristicDG(*model); + heuristicDG.setHeuristicName("DiveGuided"); + heuristicDG.setWhen(diveOptionsNotC); + heuristicDG.setMaxIterations(majorIterations); + if (diveOptions2) { + heuristicDG.setPercentageToFix(0.0); + heuristicDG.setMaxSimplexIterations(COIN_INT_MAX); + heuristicDG.setMaxSimplexIterationsAtRoot(COIN_INT_MAX - (diveOptions2 - 1)); + } + model->addHeuristic(&heuristicDG); + } + if ((useDIVING & 4) != 0) { + CbcHeuristicDiveFractional heuristicDF(*model); + heuristicDF.setHeuristicName("DiveFractional"); + heuristicDF.setWhen(diveOptionsNotC); + heuristicDF.setMaxIterations(majorIterations); + if (diveOptions2) { + heuristicDF.setPercentageToFix(0.0); + heuristicDF.setMaxSimplexIterations(COIN_INT_MAX); + heuristicDF.setMaxSimplexIterationsAtRoot(COIN_INT_MAX - (diveOptions2 - 1)); + } + model->addHeuristic(&heuristicDF); + } + if ((useDIVING & 8) != 0) { + CbcHeuristicDiveCoefficient heuristicDC(*model); + heuristicDC.setHeuristicName("DiveCoefficient"); + heuristicDC.setWhen(diveOptions); + heuristicDC.setMaxIterations(majorIterations); + if (diveOptions2) { + heuristicDC.setPercentageToFix(0.0); + heuristicDC.setMaxSimplexIterations(COIN_INT_MAX); + heuristicDC.setMaxSimplexIterationsAtRoot(COIN_INT_MAX - (diveOptions2 - 1)); + } + model->addHeuristic(&heuristicDC); + } + if ((useDIVING & 16) != 0) { + CbcHeuristicDiveLineSearch heuristicDL(*model); + heuristicDL.setHeuristicName("DiveLineSearch"); + heuristicDL.setWhen(diveOptionsNotC); + heuristicDL.setMaxIterations(majorIterations); + if (diveOptions2) { + heuristicDL.setPercentageToFix(0.0); + heuristicDL.setMaxSimplexIterations(COIN_INT_MAX); + heuristicDL.setMaxSimplexIterationsAtRoot(COIN_INT_MAX - (diveOptions2 - 1)); + } + model->addHeuristic(&heuristicDL); + } + if ((useDIVING & 32) != 0) { + CbcHeuristicDivePseudoCost heuristicDP(*model); + heuristicDP.setHeuristicName("DivePseudoCost"); + heuristicDP.setWhen(diveOptionsNotC /*+ diveOptions2*/); + heuristicDP.setMaxIterations(majorIterations); + if (diveOptions2) { + heuristicDP.setPercentageToFix(0.0); + heuristicDP.setMaxSimplexIterations(COIN_INT_MAX); + heuristicDP.setMaxSimplexIterationsAtRoot(COIN_INT_MAX - (diveOptions2 - 1)); + } + model->addHeuristic(&heuristicDP); + } + anyToDo = true; + } +#ifdef JJF_ZERO + if (usePivotC >= type && usePivotC <= kType + 1) { + CbcHeuristicPivotAndComplement heuristic(*model); + heuristic.setHeuristicName("pivot and complement"); + heuristic.setFractionSmall(10.0); // normally 0.5 + model->addHeuristic(&heuristic); + anyToDo = true; + } +#endif + if (usePivotF >= type && usePivotF <= kType + 1) { + CbcHeuristicPivotAndFix heuristic(*model); + heuristic.setHeuristicName("pivot and fix"); + heuristic.setFractionSmall(10.0); // normally 0.5 + model->addHeuristic(&heuristic); + anyToDo = true; + } + if (useRand >= type && useRand <= kType + 1) { + CbcHeuristicRandRound heuristic(*model); + heuristic.setHeuristicName("randomized rounding"); + heuristic.setFractionSmall(10.0); // normally 0.5 + model->addHeuristic(&heuristic); + anyToDo = true; + } + if (useDINS >= kType && useDINS <= kType + 1) { + CbcHeuristicDINS heuristic5a(*model); + heuristic5a.setHeuristicName("DINS"); + heuristic5a.setFractionSmall(0.6); + if (useDINS < 4) + heuristic5a.setDecayFactor(5.0); + else + heuristic5a.setDecayFactor(1.5); + heuristic5a.setNumberNodes(1000); + model->addHeuristic(&heuristic5a); + anyToDo = true; + } + if (useRINS >= kType && useRINS <= kType + 1) { + CbcHeuristicRINS heuristic5(*model); + heuristic5.setHeuristicName("RINS"); + if (useRINS < 4) { + heuristic5.setFractionSmall(0.5); + heuristic5.setDecayFactor(5.0); + } else { + heuristic5.setFractionSmall(0.6); + heuristic5.setDecayFactor(1.5); + } + model->addHeuristic(&heuristic5); + anyToDo = true; + } + if (useDW >= kType && useDW <= kType + 1) { + CbcHeuristicDW heuristic13(*model); + heuristic13.setHeuristicName("Dantzig-Wolfe"); + heuristic13.setNumberPasses(100); + heuristic13.setNumberBadPasses(10); + int numberIntegers = 0; + const OsiSolverInterface *solver = model->solver(); + int numberColumns = solver->getNumCols(); + for (int i = 0; i < numberColumns; i++) { + if (solver->isInteger(i)) + numberIntegers++; + } + heuristic13.setNumberNeeded(CoinMin(200, numberIntegers / 10)); + model->addHeuristic(&heuristic13); + anyToDo = true; + } + if (useCombine >= kType && (useCombine - 1) % 3 <= kType) { + CbcHeuristicLocal heuristic2(*model); + heuristic2.setHeuristicName("combine solutions"); + heuristic2.setFractionSmall(0.5); + int searchType = 1; + if (useCombine > 3) + searchType += 10; // experiment + heuristic2.setSearchType(searchType); + model->addHeuristic(&heuristic2); + anyToDo = true; + } + if ((useProximity >= kType && useProximity <= kType + 1) || (kType == 1 && useProximity > 3)) { + CbcHeuristicProximity heuristic2a(*model); + heuristic2a.setHeuristicName("Proximity Search"); + heuristic2a.setFractionSmall(9999999.0); + heuristic2a.setNumberNodes(30); + heuristic2a.setFeasibilityPumpOptions(-2); + if (useProximity >= 4) { + const int nodes[] = { 10, 100, 300 }; + heuristic2a.setNumberNodes(nodes[useProximity - 4]); + // more print out and stronger feasibility pump + if (useProximity == 6) + heuristic2a.setFeasibilityPumpOptions(-3); + } else { + int proximityNumber; + parameters_[whichParam(CBC_PARAM_STR_PROXIMITY, parameters_)].currentOptionAsInteger(proximityNumber); + if (proximityNumber > 0) { + heuristic2a.setNumberNodes(proximityNumber); + // more print out and stronger feasibility pump + if (proximityNumber >= 300) + heuristic2a.setFeasibilityPumpOptions(-3); + } + } + model->addHeuristic(&heuristic2a); + anyToDo = true; + } + if (useCrossover >= kType && useCrossover <= kType + 1) { + CbcHeuristicCrossover heuristic2a(*model); + heuristic2a.setHeuristicName("crossover"); + heuristic2a.setFractionSmall(0.3); + // just fix at lower + heuristic2a.setWhen(11); + model->addHeuristic(&heuristic2a); + model->setMaximumSavedSolutions(5); + anyToDo = true; + } + int heurSwitches = parameters_[whichParam(CBC_PARAM_INT_HOPTIONS, parameters_)].intValue() % 100; + if (heurSwitches) { + for (int iHeur = 0; iHeur < model->numberHeuristics(); iHeur++) { + CbcHeuristic *heuristic = model->heuristic(iHeur); + heuristic->setSwitches(heurSwitches); + } + } + if (type == 2 && anyToDo) { + // Do heuristics +#ifndef JJF_ONE + // clean copy + CbcModel model2(*model); + // But get rid of heuristics in model + model->doHeuristicsAtRoot(2); + if (logLevel <= 1) + model2.solver()->setHintParam(OsiDoReducePrint, true, OsiHintTry); + OsiBabSolver defaultC; + //solver_->setAuxiliaryInfo(&defaultC); + model2.passInSolverCharacteristics(&defaultC); + // Save bounds + int numberColumns = model2.solver()->getNumCols(); + model2.createContinuousSolver(); + bool cleanModel = !model2.numberIntegers() && !model2.numberObjects(); + model2.findIntegers(false); + int heurOptions = (parameters_[whichParam(CBC_PARAM_INT_HOPTIONS, parameters_)].intValue() / 100) % 100; + if (heurOptions == 0 || heurOptions == 2) { + model2.doHeuristicsAtRoot(1); + } else if (heurOptions == 1 || heurOptions == 3) { + model2.setMaximumNodes(-1); + CbcStrategyDefault strategy(0, 5, 5); + strategy.setupPreProcessing(1, 0); + model2.setStrategy(strategy); + model2.branchAndBound(); + } + if (cleanModel) + model2.zapIntegerInformation(false); + if (model2.bestSolution()) { + double value = model2.getMinimizationObjValue(); + model->setCutoff(value); + model->setBestSolution(model2.bestSolution(), numberColumns, value); + model->setSolutionCount(1); + model->setNumberHeuristicSolutions(1); + } +#else + if (logLevel <= 1) + model->solver()->setHintParam(OsiDoReducePrint, true, OsiHintTry); + OsiBabSolver defaultC; + //solver_->setAuxiliaryInfo(&defaultC); + model->passInSolverCharacteristics(&defaultC); + // Save bounds + int numberColumns = model->solver()->getNumCols(); + model->createContinuousSolver(); + bool cleanModel = !model->numberIntegers() && !model->numberObjects(); + model->findIntegers(false); + model->doHeuristicsAtRoot(1); + if (cleanModel) + model->zapIntegerInformation(false); +#endif + return 0; + } else { + return 0; + } +} diff --git a/src/Attic/CbcSolverHeuristics.hpp b/src/Attic/CbcSolverHeuristics.hpp new file mode 100644 index 000000000..50532de47 --- /dev/null +++ b/src/Attic/CbcSolverHeuristics.hpp @@ -0,0 +1,41 @@ +// Copyright (C) 2007, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +/*! \file CbcSolverHeuristics.hpp + \brief Routines for doing heuristics. +*/ + +#ifndef CbcSolverHeuristics_H +#define CbcSolverHeuristics_H + +void crunchIt(ClpSimplex *model); + +/* + On input + doAction - 0 just fix in original and return NULL + 1 return fixed non-presolved solver + 2 as one but use presolve Inside this + 3 use presolve and fix ones with large cost + ? do heuristics and set best solution + ? do BAB and just set best solution + 10+ then use lastSolution and relax a few + -2 cleanup afterwards if using 2 + On output - number fixed +*/ +OsiClpSolverInterface * +fixVubs(CbcModel &model, int skipZero2, + int &doAction, + CoinMessageHandler * /*generalMessageHandler*/, + const double *lastSolution, double dextra[6], + int extra[5]); + +/** 1 - add heuristics to model + 2 - do heuristics (and set cutoff and best solution) + 3 - for miplib test so skip some + (out model later) + */ +int doHeuristics(CbcModel *model, int type, std::vector< CbcOrClpParam > parameters_, + int noPrinting_, int initialPumpTune); + +#endif //CbcSolverHeuristics_H diff --git a/src/Attic/Cbc_C_Interface.cpp b/src/Attic/Cbc_C_Interface.cpp new file mode 100644 index 000000000..75bf6a739 --- /dev/null +++ b/src/Attic/Cbc_C_Interface.cpp @@ -0,0 +1,4874 @@ +// Copyright (C) 2004, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "Cbc_C_Interface.h" + +#ifdef CBC_THREAD +#include +#endif + +#include "CoinPragma.hpp" +//#include "CoinHelperFunctions.hpp" +//#include "CoinPackedMatrix.hpp" +#include "CoinTime.hpp" + +#include "CbcModel.hpp" +#include "CbcSolver.hpp" +#include "CbcBranchActual.hpp" + +#include "CoinMessageHandler.hpp" +#include "OsiClpSolverInterface.hpp" +#include "OsiFeatures.hpp" +#include "ClpSimplexOther.hpp" +#include "CglCutGenerator.hpp" +#include "CglProbing.hpp" +#include "CglStored.hpp" +#include "CglCliqueStrengthening.hpp" +#include "CglGomory.hpp" +#include "CglGMI.hpp" +#include "CglFlowCover.hpp" +#include "CglZeroHalf.hpp" +#include "CglClique.hpp" +#include "CglBKClique.hpp" +#include "CglOddWheel.hpp" +#include "CglKnapsackCover.hpp" +#include "CglRedSplit.hpp" +#include "CglRedSplit2.hpp" +#include "CglResidualCapacity.hpp" +#include "CglMixedIntegerRounding2.hpp" +#include "CglTwomir.hpp" +#include "CglZeroHalf.hpp" +#include "CglLandP.hpp" +#include "CbcCutGenerator.hpp" +#include "ClpDualRowSteepest.hpp" +#include "ClpDualRowDantzig.hpp" +#include "ClpPEDualRowSteepest.hpp" +#include "ClpPEDualRowDantzig.hpp" +#include "CbcMipStartIO.hpp" +#include "ClpMessage.hpp" +#include "CoinStaticConflictGraph.hpp" +#include +#include "CoinFileIO.hpp" + +using namespace std; + +static char **to_char_vec( const vector< string > &names ); +static void *xmalloc( const size_t size ); +static void *xrealloc( void *ptr, const size_t newSize ); +static void Cbc_updateSlack( Cbc_Model *model, const double *ractivity ); + +#define VALIDATE_ROW_INDEX(iRow, model) \ + if (iRow<0 || iRow >= Cbc_getNumRows(model)) { \ + fprintf( stderr, "Invalid row index (%d), valid range is [0,%d). At %s:%d\n", \ + iRow, model->solver_->getNumRows()+model->nRows, __FILE__, __LINE__ ); \ + fflush(stderr); \ + abort(); \ + } + +#define VALIDATE_COL_INDEX(iColumn , model) \ + if ( iColumn<0 || iColumn >= Cbc_getNumCols(model) ) { \ + fprintf( stderr, "Invalid column index (%d), valid range is [0,%d). At %s:%d\n", \ + iColumn, model->solver_->getNumCols()+model->nCols, __FILE__, __LINE__ ); \ + fflush(stderr); \ + abort(); \ + } + +// returns a pointer to the first position of a std::vector +#define VEC_PTR(vec) (&((*vec)[0])) + +/* to check if solution (and of which type) + * is available */ +enum OptimizationTask { + ModelNotOptimized = 0, + ContinuousOptimization = 1, + IntegerOptimization = 2 +}; + + +// To allow call backs +class Cbc_MessageHandler + : public CoinMessageHandler { + +public: + /**@name Overrides */ + //@{ + virtual int print(); + //@} + /**@name set and get */ + //@{ + /// Model + const Cbc_Model *model() const; + void setModel(Cbc_Model *model); + /// Call back + void setCallBack(cbc_callback callback); + //@} + + /**@name Constructors, destructor */ + //@{ + /** Default constructor. */ + Cbc_MessageHandler(); + /// Constructor with pointer to model + Cbc_MessageHandler(Cbc_Model *model, + FILE *userPointer = NULL); + /** Destructor */ + virtual ~Cbc_MessageHandler(); + //@} + + /**@name Copy method */ + //@{ + /** The copy constructor. */ + Cbc_MessageHandler(const Cbc_MessageHandler &); + /** The copy constructor from an CoinSimplexMessageHandler. */ + Cbc_MessageHandler(const CoinMessageHandler &); + + Cbc_MessageHandler &operator=(const Cbc_MessageHandler &); + /// Clone + virtual CoinMessageHandler *clone() const; + //@} + +protected: + /**@name Data members + The data members are protected to allow access for derived classes. */ + //@{ + /// Pointer back to model + Cbc_Model *model_; + /// call back + cbc_callback callback_; + //@} +}; + +// command line arguments related to the lp relaxation solution +//static char cmdLPoptions[][80] = +// {"pertv", "idiot", "log", "seconds", "primalt", "dualt", "zerot", +// "pretol", "psi", "maxit", "crash", "scal" }; +//static int nCmcLpOptions = 12; + +static char cbc_annouced = 0; + + + +struct Cbc_Model { + /** + * Problem is stored here: before optimizing + * this should be cloned because CBC modifies + * directly this object dution the solution process + **/ + OsiClpSolverInterface *solver_; + + vector< string > vcbcOptions; // to keep the order of the options + map< string, string > cbcOptions; // to quickly check current value of option + + char relax_; + + // buffer for columns + int colSpace; + int nCols; + int cNameSpace; + int *cNameStart; + char *cInt; + char *cNames; + double *cLB; + double *cUB; + double *cObj; + int nInt; + + int cElementsSpace; + CoinBigIndex *cStart; + int *cIdx; + double *cCoef; + + vector< double > *iniSol; + double iniObj; + + // buffer for rows + int rowSpace; + int nRows; + int rNameSpace; + int *rNameStart; + char *rNames; + double *rLB; + double *rUB; + int rElementsSpace; + CoinBigIndex *rStart; + int *rIdx; + double *rCoef; + + // for fast search of columns + void *colNameIndex; + void *rowNameIndex; + + cbc_incumbent_callback inc_callback; + cbc_progress_callback progr_callback; + cbc_callback userCallBack; + + cbc_cut_callback cut_callback; + string cutCBName; + void *cutCBData; + int cutCBhowOften; + char cutCBAtSol; + + enum OptimizationTask lastOptimization; + + /** + * Incumbent callback callback data + **/ + void *icAppData; + + /** + * Progress callback callback data + **/ + void *pgrAppData; + +#ifdef CBC_THREAD + pthread_mutex_t cbcMutexCG; + pthread_mutex_t cbcMutexEvent; +#endif + + double obj_value; + + /* storage of Special Ordered Sets */ + int nSos; + int sosCap; + int sosSize; + int sosElCap; + int sosElSize; + int *sosRowStart; + int *sosType; + int *sosEl; + double *sosElWeight; + + /* MIPStart */ + int nColsMS; + char **colNamesMS; + double *colValuesMS; + int charSpaceMS; + + /* space to query conflict graph */ + size_t cg_space; + size_t *cg_neighs; + bool *cg_iv; + + // parameters + enum LPMethod lp_method; + enum DualPivot dualp; + + // lazy constraints + CglStored *lazyConstrs; + + int int_param[N_INT_PARAMS]; + double dbl_param[N_DBL_PARAMS]; + + /* used for MIP and continuous, just pointers */ + const double *x; + const double *rActv; + const double *rSlk; + + // integer optimization results + int mipStatus; + int mipSecStatus; + char mipIsAbandoned; + char mipIsProvenOptimal; + char mipIsProvenInfeasible; + char mipIsContinuousUnbounded; + char mipIsNodeLimitReached; + char mipIsSecondsLimitReached; + char mipIsSolutionLimitReached; + char mipIsInitialSolveAbandoned; + char mipIsInitialSolveProvenOptimal; + char mipIsInitialSolveProvenPrimalInfeasible; + double mipBestPossibleObjValue; + int mipNumSavedSolutions; + int mipNodeCount; + std::vector< std::vector< double > > *mipSavedSolution; + std::vector< double > *mipSavedSolutionObj; + std::vector< double > *mipBestSolution; + std::vector< double > *mipRowActivity; + + // to store computed slacks for MIPs and LPs + std::vector< double > *slack; + + int mipIterationCount; +}; + +/* Buffers sizes */ +#define INI_COL_SPACE 8192 +#define INI_ROW_SPACE 8192 + +// bobe including extras.h to get strdup() +#if defined(__MWERKS__) +// #include // bobe 06-02-14 +#endif + +#define CbcGetProperty(T, prop) \ + T CBC_LINKAGE \ + Cbc_##prop(Cbc_Model *m) \ + { \ + return m->model_->prop(); \ + } + +#define CbcSetSolverProperty(T, prop) \ + void CBC_LINKAGE \ + Cbc_##prop(Cbc_Model *m, int index, T val) \ + { \ + m->model_->solver()->prop(index, val); \ + } + +const int VERBOSE = 0; + +typedef std::map< std::string, int > NameIndex; + +// cut generator to accept callbacks in CBC +// +class CglCallback : public CglCutGenerator +{ + public: + CglCallback(); + + cbc_cut_callback cut_callback_; + void *appdata; +#ifdef CBC_THREAD + pthread_mutex_t *cbcMutex; +#endif + + //CbcModel *model; + + /// Copy constructor + CglCallback(const CglCallback& rhs); + + /// Clone + virtual CglCutGenerator * clone() const; + + virtual void generateCuts( const OsiSolverInterface & si, OsiCuts & cs, + const CglTreeInfo info = CglTreeInfo() ); + + virtual ~CglCallback(); + private: +}; + +CglCallback::CglCallback() + : cut_callback_(NULL), + appdata(NULL) +#ifdef CBC_THREAD + ,cbcMutex(NULL) +#endif + +{ +} + +CglCallback::CglCallback(const CglCallback& rhs) +{ + this->cut_callback_ = rhs.cut_callback_; + this->appdata = rhs.appdata; +#ifdef CBC_THREAD + this->cbcMutex = rhs.cbcMutex; +#endif +} + +CglCutGenerator* CglCallback::clone() const +{ + CglCallback *cglcb = new CglCallback(); + cglcb->cut_callback_ = this->cut_callback_; + cglcb->appdata = this->appdata; +#ifdef CBC_THREAD + cglcb->cbcMutex = this->cbcMutex; +#endif + + return static_cast(cglcb); +} + +void CglCallback::generateCuts( const OsiSolverInterface &si, OsiCuts &cs, const CglTreeInfo info ) +{ +#ifdef CBC_THREAD + assert(this->cbcMutex); + pthread_mutex_lock((this->cbcMutex)); +#endif + + this->cut_callback_( (OsiSolverInterface *) &si, &cs, this->appdata, info.level, info.pass ); + +#ifdef CBC_THREAD + pthread_mutex_unlock((this->cbcMutex)); +#endif +} + +CglCallback::~CglCallback() +{ + +} + +class Cbc_EventHandler : public CbcEventHandler { +public: + virtual CbcAction event(CbcEvent whichEvent); + Cbc_EventHandler(); + Cbc_EventHandler(CbcModel *model); + virtual ~Cbc_EventHandler(); + Cbc_EventHandler(const Cbc_EventHandler &rhs); + Cbc_EventHandler &operator=(const Cbc_EventHandler &rhs); + virtual CbcEventHandler *clone() const; + + double bestCost; + double bestBound; + cbc_incumbent_callback inc_callback; + cbc_progress_callback progr_callback; + void *appData; + void *pgAppData; +#ifdef CBC_THREAD + pthread_mutex_t *cbcMutex; +#endif +}; + +Cbc_EventHandler::Cbc_EventHandler() + : CbcEventHandler() + , bestCost(COIN_DBL_MAX) + , bestBound(COIN_DBL_MIN) + , inc_callback(NULL) + , progr_callback(NULL) + , appData(NULL) + , pgAppData(NULL) +#ifdef CBC_THREAD + , cbcMutex(NULL) +#endif +{ +} + +Cbc_EventHandler::Cbc_EventHandler(const Cbc_EventHandler &rhs) + : CbcEventHandler(rhs) + , bestCost(rhs.bestCost) + , bestBound(rhs.bestBound) + , inc_callback(rhs.inc_callback) + , progr_callback(rhs.progr_callback) + , appData(rhs.appData) + , pgAppData(rhs.pgAppData) +#ifdef CBC_THREAD + , cbcMutex(rhs.cbcMutex) +#endif + +{ +} + +Cbc_EventHandler::Cbc_EventHandler(CbcModel *model) + : CbcEventHandler(model) + , bestCost(COIN_DBL_MAX) + , bestBound(COIN_DBL_MIN) + , inc_callback(NULL) + , progr_callback(NULL) + , appData(NULL) + , pgAppData(NULL) +#ifdef CBC_THREAD + , cbcMutex(NULL) +#endif + +{ +} + +Cbc_EventHandler::~Cbc_EventHandler() +{ +} + +Cbc_EventHandler &Cbc_EventHandler::operator=(const Cbc_EventHandler &rhs) +{ + if (this != &rhs) { + CbcEventHandler::operator=(rhs); + this->bestCost = rhs.bestCost; + this->bestBound = rhs.bestBound; + this->inc_callback = rhs.inc_callback; + this->progr_callback = rhs.progr_callback; + this->appData = rhs.appData; + this->pgAppData = rhs.pgAppData; +#ifdef CBC_THREAD + this->cbcMutex = rhs.cbcMutex; +#endif + } + return *this; +} + +CbcEventHandler *Cbc_EventHandler::clone() const +{ + return new Cbc_EventHandler(*this); +} + +CbcEventHandler::CbcAction Cbc_EventHandler::event(CbcEvent whichEvent) +{ + // if in sub tree carry on + if ((model_->specialOptions() & 2048) == 0) { + if ((whichEvent == solution || whichEvent == heuristicSolution)) { + + OsiSolverInterface *origSolver = model_->solver(); + const OsiSolverInterface *pps = model_->postProcessedSolver(1); + + const OsiSolverInterface *solver = pps ? pps : origSolver; + +#ifdef CBC_THREAD + assert(this->cbcMutex); + pthread_mutex_lock((this->cbcMutex)); +#endif + if (bestCost >= solver->getObjValue() + 1e-10) { + bestCost = solver->getObjValue(); + + if (this->inc_callback != NULL) { + int charSize = 0; + const double *x = solver->getColSolution(); + std::vector< std::pair > sol; + for (int i = 0; (i < solver->getNumCols()); ++i) { + if (fabs(x[i]) <= 1e-7) + continue; + sol.push_back( std::pair( solver->getColName(i), x[i] )); + charSize += (int)solver->getColName(i).size()+1; + } // checking non zero cols + size_t nNZ = sol.size(); + char **cnames = new char*[nNZ]; + double *xv = new double[nNZ]; + cnames[0] = new char[charSize]; + for ( int i=1 ; (i<(int)sol.size()) ; ++i ) + cnames[i] = cnames[i-1] + sol[i-1].first.size()+1; + for ( int i=0 ; (i<(int)sol.size()) ; ++i ) + strcpy( cnames[i], sol[i].first.c_str() ); + for (int i = 0; (i < (int)nNZ); ++i) + xv[i] = sol[i].second; + + this->inc_callback(model_, bestCost, nNZ, cnames, xv, this->appData); + + delete[] xv; + delete[] cnames[0]; + delete[] cnames; + } // incumbent callback + if (this->progr_callback) { + const CbcModel *model = this->getModel(); + double secs = model->getCurrentSeconds(); + double lb = model->getBestPossibleObjValue(); + this->progr_callback((void *) model, 0, model->getNodeCount(), "sol", secs, lb, bestCost, 0, NULL, this->pgAppData); + } // incumbent callback + } // improved cost +#ifdef CBC_THREAD + assert(this->cbcMutex); + pthread_mutex_unlock((this->cbcMutex)); +#endif + } // solution found + + if (this->progr_callback) + { +#ifdef CBC_THREAD + assert(this->cbcMutex); + pthread_mutex_lock((this->cbcMutex)); +#endif + if (this->getModel()->getBestPossibleObjValue() >= this->bestBound+1e-5) + { + this->bestBound = this->getModel()->getBestPossibleObjValue(); + const CbcModel *model = this->getModel(); + double secs = model->getCurrentSeconds(); + this->progr_callback((void *) model, 0, model->getNodeCount(), "bnd", secs, bestBound, bestCost, 0, NULL, this->pgAppData); + } // improved lower bound +#ifdef CBC_THREAD + assert(this->cbcMutex); + pthread_mutex_unlock((this->cbcMutex)); +#endif + } // has progress callback + } // not in subtree + + return noAction; +} + + +//------------------------------------------------------------------- +// Default Constructor +//------------------------------------------------------------------- +Cbc_MessageHandler::Cbc_MessageHandler() + : CoinMessageHandler() + , model_(NULL) + , callback_(NULL) +{ +} + +//------------------------------------------------------------------- +// Copy constructor +//------------------------------------------------------------------- +Cbc_MessageHandler::Cbc_MessageHandler(const Cbc_MessageHandler &rhs) + : CoinMessageHandler(rhs) + , model_(rhs.model_) + , callback_(rhs.callback_) +{ +} + +Cbc_MessageHandler::Cbc_MessageHandler(const CoinMessageHandler &rhs) + : CoinMessageHandler(rhs) + , model_(NULL) + , callback_(NULL) +{ +} + +// Constructor with pointer to model +Cbc_MessageHandler::Cbc_MessageHandler(Cbc_Model *model, + FILE * /*userPointer*/) + : CoinMessageHandler() + , model_(model) + , callback_(NULL) +{ +} + +//------------------------------------------------------------------- +// Destructor +//------------------------------------------------------------------- +Cbc_MessageHandler::~Cbc_MessageHandler() +{ +} + +//---------------------------------------------------------------- +// Assignment operator +//------------------------------------------------------------------- +Cbc_MessageHandler & +Cbc_MessageHandler::operator=(const Cbc_MessageHandler &rhs) +{ + if (this != &rhs) { + CoinMessageHandler::operator=(rhs); + model_ = rhs.model_; + callback_ = rhs.callback_; + } + return *this; +} +//------------------------------------------------------------------- +// Clone +//------------------------------------------------------------------- +CoinMessageHandler *Cbc_MessageHandler::clone() const +{ + return new Cbc_MessageHandler(*this); +} +int Cbc_MessageHandler::print() +{ + if (callback_) { + int messageNumber = currentMessage().externalNumber(); + if (currentSource() != "Cbc") + messageNumber += 1000000; + int i; + int nDouble = numberDoubleFields(); + assert(nDouble <= 200); + double vDouble[200]; + for (i = 0; i < nDouble; i++) + vDouble[i] = doubleValue(i); + int nInt = numberIntFields(); + assert(nInt <= 200); + int vInt[200]; + for (i = 0; i < nInt; i++) + vInt[i] = intValue(i); + int nString = numberStringFields(); + assert(nString <= 200); + char *vString[200]; + for (i = 0; i < nString; i++) { + std::string value = stringValue(i); + vString[i] = CoinStrdup(value.c_str()); + } + callback_(model_, messageNumber, + nDouble, vDouble, + nInt, vInt, + nString, vString); + for (i = 0; i < nString; i++) + free(vString[i]); + } + return CoinMessageHandler::print(); + return 0; +} +const Cbc_Model * +Cbc_MessageHandler::model() const +{ + return model_; +} +void Cbc_MessageHandler::setModel(Cbc_Model *model) +{ + model_ = model; +} +// Call back +void Cbc_MessageHandler::setCallBack(cbc_callback callback) +{ + callback_ = callback; +} + +#include +#include +#include + +#if defined(__MWERKS__) +#pragma export on +#endif + +/** + * + * C Interface Routines + * + */ + +/* Version */ +const char *CBC_LINKAGE Cbc_getVersion() +{ + return CBC_VERSION; +} + +static void Cbc_flushCols(Cbc_Model *model) { + if (model->nCols == 0) + return; + + OsiClpSolverInterface *solver = model->solver_; + + int colsBefore = solver->getNumCols(); + solver->addCols( model->nCols, model->cStart, model->cIdx, model->cCoef, model->cLB, model->cUB, model->cObj ); + + if (model->nInt) { + for ( int i=0 ; inCols; ++i ) + if (model->cInt[i]) + solver->setInteger( colsBefore+i ); + } + + for ( int i=0 ; inCols; ++i ) + solver->setColName( colsBefore+i, std::string(model->cNames+model->cNameStart[i]) ); + + model->nCols = 0; + model->cStart[0] = 0; + model->nInt = 0; + model->cNameStart[0] = 0; +} + +static void Cbc_flushRows(Cbc_Model *model) { + if (model->nRows == 0) + return; + + OsiClpSolverInterface *solver = model->solver_; + + int rowsBefore = solver->getNumRows(); + solver->addRows(model->nRows, model->rStart, model->rIdx, model->rCoef, model->rLB, model->rUB); + + for ( int i=0 ; inRows; ++i ) + { + const int rIdx = rowsBefore+i; + const std::string rName = std::string(model->rNames+model->rNameStart[i]); + solver->setRowName(rIdx, rName); + } + + model->nRows = 0; + model->rStart[0] = 0; + model->rNameStart[0] = 0; +} + +// flushes buffers of new variables +static void Cbc_flush( Cbc_Model *model) +{ +#ifdef DEBUG + if (model->rStart && model->cStart) { + assert( model->rStart[model->nRows] == 0 || model->cStart[model->nCols] == 0 ); + } +#endif + + if ( model->rStart && model->rStart[model->nRows] == 0 ) { + // rows have no reference to columns, so rows can be added first + Cbc_flushRows(model); + Cbc_flushCols(model); + } + else + { + // cols have no reference to columns, so rows can be added first + Cbc_flushCols(model); + Cbc_flushRows(model); + } +} + +static void Cbc_checkSpaceColBuffer( Cbc_Model *model, int additionlNameSpace, int additionalNzSpace ) +{ + // initialize buffer + if ( model->colSpace == 0 ) + { + // initial buffer allocation + model->colSpace = INI_COL_SPACE; + int c = model->colSpace; + model->nCols = 0; + model->cNameSpace = max(INI_COL_SPACE*7, additionlNameSpace*10); + + model->cNameStart = (int *) xmalloc( sizeof(int)*c ); + model->cNameStart[0] = 0; + + model->cInt = (char *) xmalloc( sizeof(char)*c ); + model->cNames = (char *) xmalloc( sizeof(char)*model->cNameSpace ); + model->cLB = (double *) xmalloc( sizeof(double)*c ); + model->cUB = (double *)xmalloc( sizeof(double)*c ); + model->cObj = (double *)xmalloc( sizeof(double)*c ); + model->cStart = (CoinBigIndex *) xmalloc( sizeof(CoinBigIndex)*c ); + model->cStart[0] = 0; + + model->cElementsSpace = max(INI_COL_SPACE*5, additionalNzSpace*10); + model->cIdx = (int *) xmalloc( sizeof(int)*model->cElementsSpace ); + model->cCoef = (double *) xmalloc( sizeof(double)*model->cElementsSpace ); + } + else + { + // already allocated, checking for resizes + + // check buffer space + if (model->nCols+2 >= model->colSpace) + { + model->colSpace *= 2; + int c = model->colSpace; + + model->cNameStart = (int *) xrealloc( model->cNameStart, sizeof(int)*c ); + model->cInt = (char *) xrealloc( model->cInt, sizeof(char)*c ); + model->cLB = (double *) xrealloc( model->cLB, sizeof(double)*c ); + model->cUB = (double *) xrealloc( model->cUB, sizeof(double)*c ); + model->cObj = (double *) xrealloc( model->cObj, sizeof(double)*c ); + model->cStart = (CoinBigIndex *) xrealloc( model->cStart, sizeof(CoinBigIndex)*c ); + } + // check string buffer space + int slen = additionlNameSpace + 1; + int reqsize = slen + model->cNameStart[model->nCols]+1; + if (reqsize>model->cNameSpace) + { + model->cNameSpace = max(model->cNameSpace*2, additionlNameSpace); + model->cNames = (char *) xrealloc( model->cNames, sizeof(char)*model->cNameSpace ); + } + + if (model->cStart[model->nCols]+additionalNzSpace+1 >= model->cElementsSpace) { + model->cElementsSpace = std::max(model->cStart[model->nCols]+additionalNzSpace+1, model->cElementsSpace*2); + model->cIdx = (int *) xrealloc( model->cIdx, sizeof(int)*model->cElementsSpace ); + model->cCoef = (double *) xrealloc( model->cCoef, sizeof(double)*model->cElementsSpace ); + } // space on column non-zeros + + } // additional allocations + +} + +static void Cbc_addColBuffer( Cbc_Model *model, + const char *name, + int rNz, int *rIdx, double *rCoef, + double lb, double ub, double obj, + char isInteger ) +{ +#define MAX_COL_NAME_SIZE 1024 + Cbc_checkSpaceColBuffer( model, MAX_COL_NAME_SIZE, rNz ); + int p = model->nCols; + model->cInt[p] = isInteger; + model->cLB[p] = lb; + model->cUB[p] = ub; + model->cObj[p] = obj; + model->nInt += (int)isInteger; + + int ps = model->cNameStart[p]; + strncpy( model->cNames+ps, name, MAX_COL_NAME_SIZE ); + int len = min( (int)strlen(name), MAX_COL_NAME_SIZE ); + + int stNz = model->cStart[p]; + + if (rNz) { +#ifdef DEBUG + for ( int i=0 ; (icIdx+stNz, rIdx, sizeof(int)*rNz ); + memcpy( model->cCoef+stNz, rCoef, sizeof(double)*rNz ); + } + + model->nCols++; + model->cNameStart[model->nCols] = ps + len + 1; + model->cStart[model->nCols] = stNz + rNz; +#undef MAX_COL_NAME_SIZE +} + +static void Cbc_deleteColBuffer( Cbc_Model *model ) +{ + if (model->colSpace == 0) + return; + + free(model->cNameStart); + free(model->cInt); + free(model->cNames); + free(model->cLB); + free(model->cUB); + free(model->cObj); + free(model->cStart); + free(model->cIdx); + free(model->cCoef); + + model->cNameStart = NULL; + model->cInt = NULL; + model->cNames = NULL; + model->cLB = NULL; + model->cUB = NULL; + model->cObj = NULL; + model->cStart = NULL; + model->cIdx = NULL; + model->cCoef = NULL; + + model->colSpace = model->cNameSpace = model->cElementsSpace = model->nCols = model->nInt = 0; +} + +static void Cbc_checkSpaceRowBuffer(Cbc_Model *model, int nzRow, int rowNameLen) +{ + if (model->rowSpace == 0) + { + // allocating buffer + model->rowSpace = INI_ROW_SPACE; + model->rStart = (CoinBigIndex *)xmalloc(sizeof(CoinBigIndex)*model->rowSpace); + model->rStart[0] = 0; + model->rLB = (double *)xmalloc(sizeof(double)*model->rowSpace); + model->rUB = (double *)xmalloc(sizeof(double)*model->rowSpace); + model->rNameStart = (int *)xmalloc(sizeof(int)*model->rowSpace); + model->rNameStart[0] = 0; + + model->rElementsSpace = std::max(INI_ROW_SPACE*15, nzRow*10); + model->rIdx = (int *)xmalloc(sizeof(int)*model->rElementsSpace); + model->rCoef = (double *)xmalloc(sizeof(double)*model->rElementsSpace); + + model->rNameSpace = max(INI_ROW_SPACE*10, rowNameLen*10); + model->rNames = (char *)xmalloc(sizeof(char)*model->rNameSpace); + } + else + { + // checking if some resize is needed + if (model->nRows+2 >= model->rowSpace) + { + model->rowSpace = std::max(2*model->rowSpace, model->nRows+2); + model->rStart = (CoinBigIndex *)xrealloc(model->rStart, sizeof(CoinBigIndex)*model->rowSpace); + model->rLB = (double *)xrealloc(model->rLB, sizeof(double)*model->rowSpace); + model->rUB = (double *)xrealloc(model->rUB, sizeof(double)*model->rowSpace); + model->rNameStart = (int *)xrealloc(model->rNameStart, sizeof(int)*model->rowSpace); + } // rowSpace + + if (model->rStart[model->nRows]+nzRow+1 >= model->rElementsSpace) + { + model->rElementsSpace = std::max(2*model->rElementsSpace, model->rStart[model->nRows]+nzRow+1); + model->rIdx = (int *)xrealloc(model->rIdx, sizeof(int)*model->rElementsSpace); + model->rCoef = (double *)xrealloc(model->rCoef, sizeof(double)*model->rElementsSpace); + } // elements space + + if (model->rNameStart[model->nRows]+rowNameLen+2 >= model->rNameSpace) + { + model->rNameSpace = std::max(model->rNameSpace*2, model->rNameSpace+rowNameLen+2); + model->rNames = (char *)xrealloc(model->rNames, sizeof(char)*model->rNameSpace); + } // row names resize + } // checks for resize +} // Cbc_checkSpaceRowBuffer + +static void Cbc_addRowBuffer( + Cbc_Model *model, + int nz, + const int *rIdx, + const double *rCoef, + double rLB, + double rUB, + const char *rName) +{ +#ifdef DEBUG + { + std::vector< char > iv = std::vector( Cbc_getNumCols(model), 0 ); + for ( int i=0 ; i= 1) { + fprintf(stderr, "Error in Cbc_addRow: adding row with repeated column (%d) indexes \n", rIdx[i] ); + exit(1); + } + iv[rIdx[i]]++; + } + } +#endif + int nameLen = (int)strlen(rName); + Cbc_checkSpaceRowBuffer(model, nz, nameLen); + const int st = model->rStart[model->nRows]; + + model->rLB[model->nRows] = rLB; + model->rUB[model->nRows] = rUB; + memcpy(model->rIdx + st, rIdx, sizeof(int)*nz); + memcpy(model->rCoef + st, rCoef, sizeof(double)*nz); + + char *spcName = model->rNames + model->rNameStart[model->nRows]; + strcpy(spcName, rName); + + model->nRows++; + model->rStart[model->nRows] = st + nz; + model->rNameStart[model->nRows] = model->rNameStart[model->nRows-1] + nameLen + 1; +} + +static void Cbc_deleteRowBuffer(Cbc_Model *model) +{ + if (model->rowSpace == 0) + return; + + free(model->rStart); + free(model->rLB); + free(model->rUB); + free(model->rNameStart); + free(model->rIdx); + free(model->rCoef); + free(model->rNames); + + model->rStart = NULL; + model->rLB = NULL; + model->rUB = NULL; + model->rNameStart = NULL; + model->rIdx = NULL; + model->rCoef = NULL; + model->rNames = NULL; + + model->rowSpace = 0; + model->nRows = 0; + model->rNameSpace = 0; + model->rElementsSpace = 0; +} + +static void Cbc_iniBuffer(Cbc_Model *model) +{ + // initialize columns buffer + model->colSpace = 0; + model->nCols = 0; + model->cNameSpace = 0; + model->cNameStart = NULL; + model->cInt = NULL; + model->cNames= NULL; + model->cLB = NULL; + model->cUB = NULL; + model->cObj = NULL; + model->cStart = NULL; + model->cIdx = NULL; + model->cCoef = NULL; + model->nInt = 0; + model->cElementsSpace = 0; + + // initialize rows buffer + model->rowSpace = 0; + model->nRows = 0; + model->rNameSpace = 0; + model->rNameStart = 0; + model->rNames = NULL; + model->rLB = NULL; + model->rUB = NULL; + model->rElementsSpace = 0; + model->rStart = NULL; + model->rIdx = NULL; + model->rCoef = NULL; + + // SOS buffer + model->nSos = 0; + model->sosCap = 0; + model->sosSize = 0; + model->sosElCap = 0; + model->sosElSize = 0; + model->sosRowStart = NULL; + model->sosEl = NULL; + model->sosElWeight = NULL; + model->sosType = NULL; + + model->nColsMS = 0; + model->colNamesMS = NULL; + model->colValuesMS = NULL; +} + +static void Cbc_iniParams( Cbc_Model *model ); +static void Cbc_cleanOptResults(Cbc_Model *model); + +/* Default Cbc_Model constructor */ +Cbc_Model *CBC_LINKAGE +Cbc_newModel() +{ + Cbc_Model *model = new Cbc_Model(); + + Cbc_iniParams(model); + + model->solver_ = new OsiClpSolverInterface(); + model->solver_->setIntParam(OsiNameDiscipline, 1); + + model->relax_ = 0; + model->obj_value = COIN_DBL_MAX; + + model->inc_callback = NULL; + model->progr_callback = NULL; + model->userCallBack = NULL; + + model->cut_callback = NULL; + model->cutCBData = NULL; + model->cutCBhowOften = -1; + model->cutCBAtSol = 0; + + model->lastOptimization = ModelNotOptimized; + + model->icAppData = NULL; + model->pgrAppData = NULL; + + model->colNameIndex = NULL; + model->rowNameIndex = NULL; + + model->iniSol = NULL; + model->iniObj = DBL_MAX; + + Cbc_cleanOptResults(model); + Cbc_iniBuffer(model); + + // MIP Solution storage structures + model->mipSavedSolution = NULL; + model->mipSavedSolutionObj = NULL; + model->mipBestSolution = NULL; + model->mipRowActivity = NULL; + + model->slack = NULL; + +#ifdef CBC_THREAD + pthread_mutex_init(&(model->cbcMutexCG), NULL); + pthread_mutex_init(&(model->cbcMutexEvent), NULL); +#endif + + model->lazyConstrs = NULL; + + return model; +} + +/* Cbc_Model Destructor */ +void CBC_LINKAGE +Cbc_deleteModel(Cbc_Model *model) +{ + Cbc_deleteColBuffer(model); + Cbc_deleteRowBuffer(model); + + if (model->sosRowStart) { + free(model->sosRowStart); + free(model->sosEl); + free(model->sosElWeight); + free(model->sosType); + } + + if (model->cg_space) { + free( model->cg_iv ); + free( model->cg_neighs ); + } + + if (model->slack) { + delete model->slack; + } + +#ifdef CBC_THREAD + pthread_mutex_destroy(&(model->cbcMutexCG)); + pthread_mutex_destroy(&(model->cbcMutexEvent)); +#endif + + if (model->colNameIndex) + { + NameIndex *m = (NameIndex *)model->colNameIndex; + delete m; + m = (NameIndex *)model->rowNameIndex; + assert( m != NULL ); + delete m; + } + + if (model->solver_) + delete model->solver_; + + if (model->iniSol) + delete model->iniSol; + + if (model->nColsMS) { + if (model->colNamesMS) { + free(model->colNamesMS[0]); + free(model->colNamesMS); + model->colNamesMS = NULL; + } + free(model->colValuesMS); + model->colValuesMS = NULL; + } + + if (model->lazyConstrs) + delete model->lazyConstrs; + + if (model->mipSavedSolution) { + delete model->mipSavedSolution; + delete model->mipSavedSolutionObj; + delete model->mipBestSolution; + delete model->mipRowActivity; + } + + delete model; +} + +/* Loads a problem (the constraints on the + rows are given by lower and upper bounds). If a pointer is NULL then the + following values are the default: +
    +
  • colub: all columns have upper bound infinity +
  • collb: all columns have lower bound 0 +
  • rowub: all rows have upper bound infinity +
  • rowlb: all rows have lower bound -infinity +
  • obj: all variables have 0 objective coefficient +
+ + Just like the other loadProblem() method except that the matrix is + given in a standard column major ordered format (without gaps). +*/ +void CBC_LINKAGE +Cbc_loadProblem(Cbc_Model *model, 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) +{ + OsiClpSolverInterface *solver = model->solver_; + + solver->loadProblem(numcols, numrows, start, index, value, + collb, colub, obj, rowlb, rowub); +} // Cbc_loadProblem() + +/* should be called after reading a new problem */ +static void fillAllNameIndexes(Cbc_Model *model) +{ + if (!model->colNameIndex) + return; + + OsiClpSolverInterface *solver = model->solver_; + NameIndex &colNameIndex = *((NameIndex *)model->colNameIndex); + colNameIndex.clear(); + NameIndex &rowNameIndex = *((NameIndex *)model->rowNameIndex); + rowNameIndex.clear(); + + for ( int i=0 ; (igetNumCols()) ; ++i ) + colNameIndex[solver->getColName(i)] = i; + + for ( int i=0 ; (igetNumRows()) ; ++i ) + rowNameIndex[solver->getRowName(i)] = i; +} + +/** Reads an MPS file + * + * @param model problem object + * @param fileName file name + * @return returns the number of errors (see OsiMpsReader class)m + **/ +int CBC_LINKAGE +Cbc_readMps(Cbc_Model *model, const char *filename) +{ + OsiClpSolverInterface *solver = model->solver_; + int status = solver->readMps(filename, true, false); + if ((status>0)&&(model->int_param[INT_PARAM_LOG_LEVEL] > 0)) { + fflush(stdout); fflush(stderr); + fprintf(stderr, "%d errors occurred while reading MPS.\n", status); + fflush(stderr); + } + + Cbc_deleteColBuffer(model); + Cbc_deleteRowBuffer(model); + Cbc_iniBuffer(model); + + fillAllNameIndexes(model); + + return status; +} + +/** Writes an MPS file + * + * @param model problem object + * @param fileName file name + **/ +void CBC_LINKAGE +Cbc_writeMps(Cbc_Model *model, const char *filename) +{ + Cbc_flush(model); + + model->solver_->writeMps(filename, "mps", Cbc_getObjSense(model)); +} + +int CBC_LINKAGE Cbc_readBasis(Cbc_Model *model, const char *filename) { + OsiClpSolverInterface *solver = model->solver_; + ClpSimplex *clps = solver->getModelPtr(); + int status = clps->readBasis(filename); + if (status == 1) { + CoinWarmStartBasis *basis = clps->getBasis(); + solver->setWarmStart(basis); + delete basis; + } + return status; +} + +int CBC_LINKAGE Cbc_writeBasis(Cbc_Model *model, const char *filename, char writeValues, int formatType) { + OsiClpSolverInterface *solver = model->solver_; + ClpSimplex *clps = solver->getModelPtr(); + return clps->writeBasis(filename, writeValues, formatType); +} + +/** Writes an LP file + * + * @param model problem object + * @param fileName file name */ +void CBC_LINKAGE +Cbc_writeLp(Cbc_Model *model, const char *filename) +{ + Cbc_flush(model); + + char outFile[512]; + strncpy(outFile, filename, 511); + + char *s = NULL; + if ((s = strstr(outFile, ".lp"))) { + if (s != outFile) // not at the start + *s = '\0'; + } + + model->solver_->writeLp(outFile); +} + +/** Reads an LP file + * + * @param model problem object + * @param fileName file name */ +int CBC_LINKAGE +Cbc_readLp(Cbc_Model *model, const char *filename) +{ + int result = 1; + OsiClpSolverInterface *solver = model->solver_; + result = solver->readLp(filename); + assert(result == 0); + + Cbc_deleteColBuffer(model); + Cbc_deleteRowBuffer(model); + Cbc_iniBuffer(model); + + fillAllNameIndexes(model); + + return result; +} + +/** @brief If Cbc was built with gzip compressed files support + * + * @return 1 if yes, 0 otherwise + **/ +char CBC_LINKAGE +Cbc_supportsGzip() { + return (char)CoinFileInput::haveGzipSupport(); +} + +/** @brief If Cbc was built with bzip2 compressed files support + * + * @return 1 if yes, 0 otherwise + **/ +char CBC_LINKAGE +Cbc_supportsBzip2() { + return (char)CoinFileInput::haveBzip2Support(); +} + +/* Sets an initial feasible solution + * + * @param model problem object + **/ +void CBC_LINKAGE +Cbc_setInitialSolution(Cbc_Model *model, const double *sol) +{ + Cbc_flush(model); + int n = Cbc_getNumCols(model); + // We need to manually compute the objective here for some reason + const double *objvec = Cbc_getObjCoefficients(model); + double objval = 0; + for (int i = 0; i < n; i++) { + objval += objvec[i] * sol[i]; + } + + if (model->iniSol) { + model->iniSol->resize( Cbc_getNumCols(model) ); + double *iniSol = &((*model->iniSol)[0]); + memcpy( iniSol, sol, sizeof(double)*Cbc_getNumCols(model) ); + } else { + model->iniSol = new vector(sol, sol+n); + } + + model->iniObj = objval; +} + + +void CBC_LINKAGE +Cbc_setIntParam(Cbc_Model *model, enum IntParam which, const int val) { + assert(which < N_INT_PARAMS); + model->int_param[which] = val; +} + +void CBC_LINKAGE +Cbc_setDblParam(Cbc_Model *model, enum DblParam which, const double val) { + assert(which < N_DBL_PARAMS); + model->dbl_param[which] = val; +} + +double CBC_LINKAGE +Cbc_getDblParam(Cbc_Model *model, enum DblParam which) { + assert(which < N_DBL_PARAMS); + return model->dbl_param[which]; +} + +int CBC_LINKAGE +Cbc_getIntParam(Cbc_Model *model, enum IntParam which) { + assert(which < N_INT_PARAMS); + return model->int_param[which]; +} + +void CBC_LINKAGE +Cbc_setParameter(Cbc_Model *model, const char *name, const char *value) +{ + if (model->cbcOptions.find(string(name))==model->cbcOptions.end()) + model->vcbcOptions.push_back(string(name)); + model->cbcOptions[name] = string(value); +} + +/* Fills in array with problem name */ +void CBC_LINKAGE +Cbc_problemName(Cbc_Model *model, int maxNumberCharacters, char *array) +{ + std::string name; + model->solver_->getStrParam(OsiProbName, name); + strncpy(array, name.c_str(), maxNumberCharacters); +} +/* Sets problem name. Must have \0 at end. */ +int CBC_LINKAGE +Cbc_setProblemName(Cbc_Model *model, const char *array) +{ + bool result = false; + result = model->solver_->setStrParam(OsiProbName, array); + + return (result) ? 1 : 0; +} + +int CBC_LINKAGE Cbc_status(Cbc_Model *model) { + switch (model->lastOptimization) { + case ModelNotOptimized: + fprintf( stderr, "Status not available, model was not optimized yet.\n"); + abort(); + break; + case ContinuousOptimization: + fprintf( stderr, "Cbc_status only available for MIP models.\n"); + abort(); + break; + case IntegerOptimization: + return model->mipStatus; + } + + return INT_MAX; +} + + +int CBC_LINKAGE Cbc_secondaryStatus(Cbc_Model *model) { + switch (model->lastOptimization) { + case ModelNotOptimized: + fprintf( stderr, "Status not available, model was not optimized yet.\n"); + abort(); + break; + case ContinuousOptimization: + fprintf( stderr, "Cbc_status only available for MIP models.\n"); + abort(); + break; + case IntegerOptimization: + return model->mipSecStatus; + } + + return INT_MAX; +} + +void CBC_LINKAGE Cbc_computeFeatures(Cbc_Model *model, double *features) { + OsiFeatures::compute(features, model->solver_); +} + +CBCSOLVERLIB_EXPORT int CBC_LINKAGE +Cbc_nFeatures() { + return OsiFeatures::n; +} + +const char * CBC_LINKAGE Cbc_featureName(int i) { + return OsiFeatures::name(i); +} + +/* Number of elements in matrix */ +int CBC_LINKAGE +Cbc_getNumElements(Cbc_Model *model) +{ + int tmpNZCols = 0, tmpNZRows = 0; + if (model->cStart) + tmpNZCols = model->cStart[model->nCols]; + + if (model->rStart) + tmpNZRows = model->rStart[model->nRows]; + + return model->solver_->getNumElements() + + tmpNZCols + tmpNZRows; +} + +const void * CBC_LINKAGE Cbc_conflictGraph( Cbc_Model *model ) { + return model->solver_->getCGraph(); +} + +/** @brief Updates (or creates, if first time) the conflict graph + * + * @param model problem object + **/ +void CBC_LINKAGE Cbc_updateConflictGraph( Cbc_Model *model ) { + Cbc_flush(model); + model->solver_->checkCGraph(); +} + +int CBC_LINKAGE +Cbc_getNumIntegers(Cbc_Model *model) +{ + return model->solver_->getNumIntegers() + model->nInt; +} + +// Column starts in matrix +const CoinBigIndex *CBC_LINKAGE +Cbc_getVectorStarts(Cbc_Model *model) +{ + Cbc_flush(model); + + const CoinPackedMatrix *matrix = NULL; + matrix = model->solver_->getMatrixByCol(); + return (matrix == NULL) ? NULL : matrix->getVectorStarts(); +} + +// Row indices in matrix +const int *CBC_LINKAGE +Cbc_getIndices(Cbc_Model *model) +{ + Cbc_flush(model); + + const int *result = NULL; + const CoinPackedMatrix *matrix = NULL; + matrix = model->solver_->getMatrixByCol(); + result = (matrix == NULL) ? NULL : matrix->getIndices(); + + return result; +} + +// Element values in matrix +const double *CBC_LINKAGE +Cbc_getElements(Cbc_Model *model) +{ + Cbc_flush(model); + + const double *result = NULL; + const CoinPackedMatrix *matrix = NULL; + matrix = model->solver_->getMatrixByCol(); + result = (matrix == NULL) ? NULL : matrix->getElements(); + + return result; +} +// ====================================================================== + +/* Pass in Callback function */ +void CBC_LINKAGE +Cbc_registerCallBack(Cbc_Model *model, + cbc_callback userCallBack) +{ + model->userCallBack = userCallBack; +} +/* Unset Callback function */ +void CBC_LINKAGE +Cbc_clearCallBack(Cbc_Model *model) +{ + model->userCallBack = NULL; +} + +/* length of names (0 means no names0 */ +size_t CBC_LINKAGE +Cbc_maxNameLength(Cbc_Model *model) +{ + size_t result = 0; + OsiSolverInterface::OsiNameVec const &rownames = model->solver_->getRowNames(); + for (size_t i = 0; i < rownames.size(); i++) { + if (rownames[i].length() > result) + result = rownames[i].length(); + } + OsiSolverInterface::OsiNameVec const &colnames = model->solver_->getColNames(); + for (size_t i = 0; i < colnames.size(); i++) { + if (colnames[i].length() > result) + result = colnames[i].length(); + } + + // go trough buffered names also + for ( size_t i=0 ; (i<(size_t)model->nCols) ; ++i ) + result = max( result, strlen(model->cNames+model->cNameStart[i]) ); + + for ( size_t i=0 ; (i<(size_t)model->nRows) ; ++i ) + result = max( result, strlen(model->rNames+model->rNameStart[i]) ); + + return result; +} + +void CBC_LINKAGE +Cbc_getRowName(Cbc_Model *model, int iRow, char *name, size_t maxLength) +{ + VALIDATE_ROW_INDEX( iRow, model ); + + if (iRow < model->solver_->getNumRows()) { + std::string rowname = model->solver_->getRowName(iRow); + strncpy(name, rowname.c_str(), maxLength); + name[maxLength - 1] = '\0'; + } else { + int idxRowBuffer = iRow - model->solver_->getNumRows(); + strncpy( name, model->rNames+model->rNameStart[idxRowBuffer], maxLength ); + } +} + +void CBC_LINKAGE +Cbc_getColName(Cbc_Model *model, int iColumn, char *name, size_t maxLength) +{ + VALIDATE_COL_INDEX( iColumn, model ); + + if (iColumn < model->solver_->getNumCols()) { + std::string colname = model->solver_->getColName(iColumn); + strncpy(name, colname.c_str(), maxLength); + name[maxLength - 1] = '\0'; + } else { + int idxColBuffer = iColumn - model->solver_->getNumCols(); + strncpy( name, model->cNames+model->cNameStart[idxColBuffer], maxLength ); + } + +} + +void CBC_LINKAGE +Cbc_setColName(Cbc_Model *model, int iColumn, const char *name) +{ + VALIDATE_COL_INDEX( iColumn, model ); + + Cbc_flush(model); + OsiClpSolverInterface *solver = model->solver_; + std::string previousName = solver->getColName(iColumn); + solver->setColName(iColumn, name); + + if (!model->colNameIndex) + return; + NameIndex &colNameIndex = *((NameIndex *)model->colNameIndex); + NameIndex::iterator it = colNameIndex.find(previousName); + if (it!=colNameIndex.end()) + colNameIndex.erase(it); + colNameIndex[name] = iColumn; +} + +void CBC_LINKAGE +Cbc_setRowName(Cbc_Model *model, int iRow, const char *name) +{ + VALIDATE_ROW_INDEX( iRow, model ); + + Cbc_flush(model); + OsiClpSolverInterface *solver = model->solver_; + std::string previousName = solver->getRowName(iRow); + solver->setRowName(iRow, name); + + if (!model->rowNameIndex) + return; + NameIndex &rowNameIndex = *((NameIndex *)model->rowNameIndex); + NameIndex::iterator it = rowNameIndex.find(std::string(previousName)); + if (it!=rowNameIndex.end()) + rowNameIndex.erase(it); + rowNameIndex[name] = iRow; +} + +void CBC_LINKAGE +Cbc_setSolveRelax(Cbc_Model *model, char solveOnlyRelax) +{ + model->relax_ = solveOnlyRelax; +} + +static int cbc_callb(CbcModel *cbcModel, int whereFrom) { + Cbc_EventHandler *cbc_eh = dynamic_cast(cbcModel->getEventHandler()); + if (cbc_eh == NULL) + return 0; + + if (cbc_eh->progr_callback != NULL) + { + switch (whereFrom) + { + case 1: + cbc_eh->progr_callback(cbcModel, 0, 0, "root lp relax", cbcModel->getCurrentSeconds(), + cbcModel->getBestPossibleObjValue(), DBL_MAX, 0, NULL, cbc_eh->pgAppData); + break; + case 2: + cbc_eh->progr_callback(cbcModel, 0, 0, "pre-proc", cbcModel->getCurrentSeconds(), + cbcModel->getBestPossibleObjValue(), cbcModel->getObjValue(), 0, NULL, cbc_eh->pgAppData); + break; + } // where from + } // has progress callback + + return 0; +} + +// adds all sos objects to the current cbcModel_ object +static void Cbc_addAllSOS( Cbc_Model *model, CbcModel &cbcModel ); + +// adds mipstart if available +static void Cbc_addMS( Cbc_Model *model, CbcModel &cbcModel ); + +int CBC_LINKAGE +Cbc_solveLinearProgram(Cbc_Model *model) +{ + Cbc_flush( model ); + OsiClpSolverInterface *solver = model->solver_; + ClpSimplex *clps = solver->getModelPtr(); + assert(clps); + + // stopping criteria + double prevMaxSecs = clps->maximumSeconds(); + clps->setMaximumSeconds(model->dbl_param[DBL_PARAM_TIME_LIMIT]); + + CoinMessages generalMessages = clps->messages(); + clps->setRandomSeed( model->int_param[INT_PARAM_RANDOM_SEED] ); + + solver->setDblParam( OsiPrimalTolerance, model->dbl_param[DBL_PARAM_PRIMAL_TOL]); + solver->setDblParam( OsiDualTolerance, model->dbl_param[DBL_PARAM_DUAL_TOL]); + + clps->setPerturbation(model->int_param[INT_PARAM_PERT_VALUE]); + solver->messageHandler()->setLogLevel( model->int_param[INT_PARAM_LOG_LEVEL] ); + + if (! cbc_annouced) { + char generalPrint[512]; + sprintf(generalPrint, + "Welcome to the CBC MILP Solver \n"); + if (strcmp(CBC_VERSION, "trunk")) { + sprintf(generalPrint + strlen(generalPrint), + "Version: %s \n", CBC_VERSION); + } else { + sprintf(generalPrint + strlen(generalPrint), + "Version: Trunk\n"); + } + sprintf(generalPrint + strlen(generalPrint), + "Build Date: %s \n", __DATE__); +#ifdef CBC_SVN_REV + sprintf(generalPrint + strlen(generalPrint), + "Revision Number: %d \n", CBC_SVN_REV); +#endif + solver->messageHandler()->setPrefix(false); + solver->messageHandler()->message(CLP_GENERAL, generalMessages) + << generalPrint + << CoinMessageEol; + solver->messageHandler()->setPrefix(true); + cbc_annouced = 1; + } + + model->lastOptimization = ContinuousOptimization; + + if (solver->basisIsAvailable()) { + solver->resolve(); + if (solver->isProvenOptimal()) { + clps->setMaximumSeconds(prevMaxSecs); + return 0; + } + if (solver->isProvenDualInfeasible()) { + clps->setMaximumSeconds(prevMaxSecs); + return 3; + } + if (solver->isProvenPrimalInfeasible()) { + clps->setMaximumSeconds(prevMaxSecs); + return 2; + } + if (solver->isIterationLimitReached() || solver->isPrimalObjectiveLimitReached() || solver->isDualObjectiveLimitReached()) { + clps->setMaximumSeconds(prevMaxSecs); + return 1; + } + if (solver->isAbandoned()) { + clps->setMaximumSeconds(prevMaxSecs); + fprintf(stderr, "Error while resolving the linear program.\n"); + fflush(stdout); fflush(stderr); + abort(); + } + } // resolve + + /* checking if options should be automatically tuned */ + if (model->lp_method == LPM_Auto) { + ClpSimplexOther *clpo = static_cast(clps); + assert(clpo); + char *opts = const_cast(clpo->guess(0).c_str()); + + if (opts) { + if (strstr(opts, "-primals") != NULL) { + model->lp_method = LPM_Primal; + //printf("Using primal;\n"); + } + else if (strstr(opts, "-duals") != NULL) { + model->lp_method = LPM_Dual; + //printf("Using dual;\n"); + } + else if (strstr(opts, "-barrier") != NULL) { + //printf("Using barrier;\n"); + model->lp_method = LPM_Barrier; + } + + char *s = NULL; + char str[256] = ""; + if ((s=strstr(opts, "-idiot"))) { + s = strstr(s+1, " "); + if (s) { + strcpy(str, s+1); + if ((s = strstr(str+1, " "))) + *s = '\0'; + int idiot = atoi(str); + //printf("Setting idiot to %d\n", idiot); + model->int_param[INT_PARAM_IDIOT] = idiot; + } + } // idiot + if ((s=strstr(opts, "-pertv"))) { + s = strstr(s+1, " "); + if (s) { + strcpy(str, s+1); + if ((s = strstr(str+1, " "))) + *s = '\0'; + int pertv = atoi(str); + //printf("Setting pertv to %d\n", pertv); + model->int_param[INT_PARAM_PERT_VALUE] = pertv; + } + } // perturbation value + if ((s=strstr(opts, "-psi"))) { + s = strstr(s+1, " "); + if (s) { + strcpy(str, s+1); + if ((s = strstr(str+1, " "))) + *s = '\0'; + double psi = atof(str); + //printf("Setting psi to %g\n", psi); + model->int_param[DBL_PARAM_PSI] = psi; + } + } // perturbation value + if ((s=strstr(opts, "-dualpivot"))) { + strcpy(str, s+1); + if ((s = strstr(str+1, " "))) + *s = '\0'; + if (strstr(str, "pesteep")) { + model->dualp = DP_PESteepest; + //printf("Setting dual pivot to pesteep.\n"); + } + } // dual pivot + delete[] opts; + } + } // auto + + /* for integer or linear optimization starting with LP relaxation */ + ClpSolve clpOptions; + char methodName[256] = ""; + switch (model->lp_method) { + case LPM_Auto: + fprintf(stderr, "Method should be already configured.\n"); + exit(1); + break; + case LPM_Primal: + if (model->int_param[INT_PARAM_IDIOT] > 0) + clpOptions.setSpecialOption(1, 2, model->int_param[INT_PARAM_IDIOT]); + clpOptions.setSolveType( ClpSolve::usePrimal ); + sprintf(methodName, "Primal Simplex"); + break; + case LPM_Dual: + clpOptions.setSolveType( ClpSolve::useDual ); + sprintf(methodName, "Dual Simplex"); + break; + case LPM_Barrier: + clpOptions.setSolveType( ClpSolve::useBarrier ); + clpOptions.setSpecialOption(4, 4); + sprintf(methodName, "Barrier"); + break; + case LPM_BarrierNoCross: + clpOptions.setSolveType( ClpSolve::useBarrierNoCross ); + sprintf(methodName, "Barrier No Crossover"); + break; + } + solver->setSolveOptions(clpOptions); + + switch (model->dualp) { + case DP_Auto: + { + ClpDualRowSteepest asteep(3); + clps->setDualRowPivotAlgorithm(asteep); + break; + } + case DP_Dantzig: + { + ClpDualRowDantzig dantzig; + clps->setDualRowPivotAlgorithm(dantzig); + break; + } + case DP_Partial: + { + ClpDualRowSteepest bsteep(2); + clps->setDualRowPivotAlgorithm(bsteep); + break; + } + case DP_Steepest: + { + ClpDualRowSteepest csteep; + clps->setDualRowPivotAlgorithm(csteep); + break; + } + case DP_PESteepest: + { + ClpPEDualRowSteepest p(model->dbl_param[DBL_PARAM_PSI]); + clps->setDualRowPivotAlgorithm(p); + break; + } + } + + if (model->int_param[INT_PARAM_LOG_LEVEL] > 0) + { + char phaseName[128] = ""; + if (solver->getNumIntegers() && (!model->relax_)) + sprintf(phaseName, "Linear programming relaxation problem"); + else + sprintf(phaseName, "Linear programming problem"); + + char msg[512] = ""; + sprintf(msg, "Starting solution of the %s using %s\n", phaseName, methodName ); + printf("%s\n", msg); fflush(stdout); + } + + model->lastOptimization = ContinuousOptimization; + solver->initialSolve(); + + if (solver->isProvenOptimal()) { + model->obj_value = solver->getObjValue(); + model->x = solver->getColSolution(); + model->rActv = solver->getRowActivity(); + Cbc_updateSlack(model, solver->getRowActivity()); + model->rSlk = &((*(model->slack))[0]); + clps->setMaximumSeconds(prevMaxSecs); + return 0; + } + if (solver->isIterationLimitReached()) { + model->obj_value = solver->getObjValue(); + clps->setMaximumSeconds(prevMaxSecs); + return 1; + } + if (solver->isProvenDualInfeasible()) { + clps->setMaximumSeconds(prevMaxSecs); + return 3; + } + if (solver->isProvenPrimalInfeasible()) { + clps->setMaximumSeconds(prevMaxSecs); + return 2; + } + + clps->setMaximumSeconds(prevMaxSecs); + return -1; +} + +void Cbc_updateSlack( Cbc_Model *model, const double *ractivity ) { + if (model->slack == NULL) { + model->slack = new vector(); + } + model->slack->resize(Cbc_getNumRows(model)); + + double *slack_ = VEC_PTR(model->slack); + + int nRows = model->solver_->getNumRows(); + const char *sense = model->solver_->getRowSense(); + const double *rrhs = model->solver_->getRightHandSide(); + for ( int i=0 ; (isolver_->getRowUpper()[i] - activity, + activity - model->solver_->getRowLower()[i] ); + break; + } + } +} + + +void CBC_LINKAGE Cbc_strengthenPacking(Cbc_Model *model) { + Cbc_flush(model); + OsiClpSolverInterface *solver = model->solver_; + CglCliqueStrengthening clqStr(solver); + if (clqStr.messageHandler()) + clqStr.messageHandler()->setLogLevel(model->int_param[INT_PARAM_LOG_LEVEL]); + clqStr.strengthenCliques(); +} + +void CBC_LINKAGE +Cbc_strengthenPackingRows(Cbc_Model *model, size_t n, const size_t rows[]) +{ + Cbc_flush(model); + OsiClpSolverInterface *solver = model->solver_; + CglCliqueStrengthening clqStr(solver); + if (clqStr.messageHandler()) + clqStr.messageHandler()->setLogLevel(model->int_param[INT_PARAM_LOG_LEVEL]); + clqStr.strengthenCliques(n, rows); +} + +static void Cbc_cleanOptResults(Cbc_Model *model) { + model->obj_value = COIN_DBL_MAX; + model->mipStatus = -1; + model->mipSecStatus = -1; + model->mipIsAbandoned = 0; + model->mipIsProvenOptimal = 0; + model->mipIsProvenInfeasible = 0; + model->mipIsContinuousUnbounded = 0; + model->mipIsNodeLimitReached = 0; + model->mipIsSecondsLimitReached = 0; + model->mipIsSolutionLimitReached = 0; + model->mipIsInitialSolveAbandoned = 0; + model->mipIsInitialSolveProvenOptimal = 0; + model->mipIsInitialSolveProvenPrimalInfeasible = 0; + model->mipBestPossibleObjValue = COIN_DBL_MIN; + model->mipNumSavedSolutions = 0; + model->mipNodeCount = 0; + model->mipIterationCount = 0; + model->x = NULL; + model->rActv = NULL; + model->rSlk = NULL; +} + +static void Cbc_getMIPOptimizationResults( Cbc_Model *model, CbcModel &cbcModel ) { + model->mipStatus = cbcModel.status(); + model->mipSecStatus = cbcModel.secondaryStatus(); + model->mipIsAbandoned = cbcModel.isAbandoned(); + model->mipIsProvenOptimal = cbcModel.isProvenOptimal(); + model->mipIsProvenInfeasible = cbcModel.isProvenInfeasible(); + model->mipIsContinuousUnbounded = cbcModel.isContinuousUnbounded(); + model->mipIsNodeLimitReached = cbcModel.isNodeLimitReached(); + model->mipIsSecondsLimitReached = cbcModel.isSecondsLimitReached(); + model->mipIsSolutionLimitReached = cbcModel.isSolutionLimitReached(); + model->mipIsInitialSolveAbandoned = cbcModel.isInitialSolveAbandoned(); + model->mipIsInitialSolveProvenOptimal = cbcModel.isInitialSolveProvenOptimal(); + model->mipIsInitialSolveProvenPrimalInfeasible = cbcModel.isInitialSolveProvenPrimalInfeasible(); + model->mipIterationCount = cbcModel.getIterationCount(); + model->mipNodeCount = cbcModel.getNodeCount(); + model->mipNumSavedSolutions = cbcModel.numberSavedSolutions(); + model->mipBestPossibleObjValue = cbcModel.getBestPossibleObjValue(); + + int numSols = model->mipNumSavedSolutions; + + if ( numSols == 0 ) + return; + + /* allocating space for MIP solution(s) related structures */ + if (model->mipBestSolution == NULL) { + model->mipSavedSolution = new std::vector< vector< double > >(); + model->mipSavedSolutionObj = new std::vector< double >(); + model->mipBestSolution = new std::vector< double >(); + model->mipRowActivity = new std::vector< double >(); + } + int numCols = Cbc_getNumCols(model); + int numRows = Cbc_getNumRows(model); + model->mipSavedSolution->resize( numSols ); + for ( int i=0 ; imipSavedSolution))[i].resize( numCols ); + + model->mipSavedSolutionObj->resize( numSols ); + model->mipBestSolution->resize( numCols ); + model->mipRowActivity->resize( numRows ); + + OsiClpSolverInterface *solver = model->solver_; + if (model->int_param[INT_PARAM_ROUND_INT_VARS]) { + cbcModel.roundIntVars(); + } + + memcpy( VEC_PTR(model->mipBestSolution), cbcModel.bestSolution(), sizeof(double)*numCols ); + model->x = VEC_PTR(model->mipBestSolution); + model->obj_value = cbcModel.getObjValue(); + + /* solution pool */ + for ( int i=0 ; imipSavedSolutionObj))[i] = cbcModel.savedSolutionObjective(i); + const double *xi = cbcModel.savedSolution(i); + double *xd = &((*(model->mipSavedSolution))[i][0]); + memcpy(xd, xi, sizeof(double)*numCols ); + if (model->int_param[INT_PARAM_ROUND_INT_VARS]) { + for ( int j=0 ; (jmipRowActivity))[0]), cbcModel.getRowActivity(), sizeof(double)*numRows ); + + if (cbcModel.getObjSense()==-1) { + model->obj_value = 0.0; + + for (int j=0 ; jgetNumCols() ; ++j ) + model->obj_value += cbcModel.bestSolution()[j] * solver->getObjCoefficients()[j]; + } // circunvent CBC bug + + /* setting this solution as a MIPStart for possible next optimization */ + if (model->nColsMS) { + if (model->colNamesMS) { + free(model->colNamesMS[0]); + free(model->colNamesMS); + model->colNamesMS = NULL; + } + free(model->colValuesMS); + model->colValuesMS = NULL; + } + + vector< string > cnames; + vector< double > cvalues; + model->charSpaceMS = 0; + for ( int j=0 ; (j= 1e-8 ) { + cnames.push_back( model->solver_->getColName(j) ); + cvalues.push_back( cbcModel.bestSolution()[j] ); + model->charSpaceMS += model->solver_->getColName(j).length() + 1; + } + } + model->charSpaceMS *= sizeof(char); + + model->colNamesMS = (char**)xmalloc(sizeof(char*)*cnames.size()); + model->colNamesMS[0] = (char*)xmalloc(sizeof(char)*model->charSpaceMS); + model->nColsMS = cnames.size(); + for ( int i=1 ; (inColsMS) ; ++i ) + model->colNamesMS[i] = model->colNamesMS[i-1] + cnames[i-1].length() + 1; + + for ( int i=0 ; (inColsMS) ; ++i ) { + strcpy(model->colNamesMS[i], cnames[i].c_str()); + } + model->colValuesMS = (double*)xmalloc(sizeof(double)*model->nColsMS); + memcpy(model->colValuesMS, &cvalues[0], sizeof(double)*model->nColsMS); +} + +int CBC_LINKAGE +Cbc_solve(Cbc_Model *model) +{ + Cbc_cleanOptResults(model); + + int res = Cbc_solveLinearProgram(model); + + if (res == 1) + return 1; + if (res==2 || res==3) + return 0; + + OsiClpSolverInterface *solver = model->solver_; + + if (solver->isProvenPrimalInfeasible() || solver->isProvenDualInfeasible() || + solver->isAbandoned() || solver->isIterationLimitReached() || model->relax_ == 1 + || ((solver->getNumIntegers()+model->nSos)==0)) { + if (solver->isProvenOptimal() || solver->isIterationLimitReached()) { + model->obj_value = solver->getObjValue(); + Cbc_updateSlack(model, solver->getRowActivity() ); + model->x = solver->getColSolution(); + model->rSlk = &((*(model->slack))[0]); + model->rActv = solver->getRowActivity(); + } + + return 0; + } + + /* MIP Optimization */ + { + model->lastOptimization = IntegerOptimization; + OsiClpSolverInterface linearProgram(*solver); + CbcModel cbcModel(linearProgram); + try { + /* stored lazy Constraints */ + if (model->lazyConstrs) { + cbcModel.addCutGenerator(model->lazyConstrs, 1, "Stored LazyConstraints", true, 1); + model->cutCBAtSol = 1; + } + + Cbc_EventHandler *cbc_eh = NULL; + if (model->inc_callback!=NULL || model->progr_callback!=NULL) + { + cbc_eh = new Cbc_EventHandler(&cbcModel); +#ifdef CBC_THREAD + cbc_eh->cbcMutex = &(model->cbcMutexEvent); +#endif + + if (model->inc_callback) { + cbc_eh->inc_callback = model->inc_callback; + cbc_eh->appData = model->icAppData; + } + if (model->progr_callback) { + cbc_eh->progr_callback = model->progr_callback; + cbc_eh->pgAppData = model->pgrAppData; + } + + cbcModel.passInEventHandler(cbc_eh); + } // callbacks + + /* initial solution */ + if (model->iniSol) + cbcModel.setBestSolution(&((*model->iniSol)[0]), Cbc_getNumCols(model), model->iniObj, true); + + // add cut generator if necessary + if (model->cut_callback) { + cbcModel.setKeepNamesPreproc(true); + + CglCallback cglCb; + cglCb.appdata = model->cutCBData; + cglCb.cut_callback_ = model->cut_callback; +#ifdef CBC_THREAD + cglCb.cbcMutex = &(model->cbcMutexCG); +#endif + cbcModel.addCutGenerator( &cglCb, model->cutCBhowOften, model->cutCBName.c_str(), true, model->cutCBAtSol ); + } + + if (model->cutCBAtSol) { + /* lazy constraints require no pre-processing and no heuristics */ + Cbc_setParameter(model, "preprocess", "off"); + Cbc_setParameter(model, "heur", "off"); + Cbc_setParameter(model, "cgraph", "off"); + Cbc_setParameter(model, "clqstr", "off"); + } else { + switch (model->int_param[INT_PARAM_CGRAPH]) { + case 0: + Cbc_setParameter(model, "cgraph", "off"); + break; + case 2: + Cbc_setParameter(model, "cgraph", "on"); + break; + case 3: + Cbc_setParameter(model, "cgraph", "clq"); + break; + } + } + + switch (model->int_param[INT_PARAM_CLIQUE_MERGING]) { + case 0: + Cbc_setParameter(model, "clqstr", "off"); + break; + case 2: + Cbc_setParameter(model, "clqstr", "before"); + break; + case 3: + Cbc_setParameter(model, "clqstr", "after"); + break; + } + + if (model->dbl_param[DBL_PARAM_MAX_SECS_NOT_IMPROV_FS] != COIN_DBL_MAX) { + char str[256]; sprintf(str, "%g", model->dbl_param[DBL_PARAM_MAX_SECS_NOT_IMPROV_FS]); + Cbc_setParameter(model, "secnifs", str); + } + if (model->int_param[INT_PARAM_MAX_NODES_NOT_IMPROV_FS] != INT_MAX) { + char str[256]; sprintf(str, "%d", model->int_param[INT_PARAM_MAX_NODES_NOT_IMPROV_FS]); + Cbc_setParameter(model, "maxNIFS", str); + } + + Cbc_MessageHandler *cbcmh = NULL; + + if (model->userCallBack) { + cbcmh = new Cbc_MessageHandler( model ); + cbcmh->setCallBack(model->userCallBack); + cbcmh->setModel(model); + cbcModel.passInMessageHandler(cbcmh); + } + + CbcSolverUsefulData cbcData; + CbcMain0(cbcModel, cbcData); + //cbcData.printWelcome_ = false; + + // adds SOSs if any + Cbc_addAllSOS(model, cbcModel); + + // adds MIPStart if any + Cbc_addMS(model, cbcModel); + + // stopping criteria + if ( model->dbl_param[DBL_PARAM_TIME_LIMIT] != COIN_DBL_MAX ) + cbcModel.setMaximumSeconds( model->dbl_param[DBL_PARAM_TIME_LIMIT] ); + if (model->int_param[INT_PARAM_MAX_SOLS] != INT_MAX) + cbcModel.setMaximumSolutions( model->int_param[INT_PARAM_MAX_SOLS] ); + if (model->int_param[INT_PARAM_MAX_NODES] != INT_MAX) + cbcModel.setMaximumNodes( model->int_param[INT_PARAM_MAX_NODES] ); + + // cutoff + if (model->dbl_param[DBL_PARAM_CUTOFF] != COIN_DBL_MAX) + cbcModel.setCutoff( model->dbl_param[DBL_PARAM_CUTOFF] ); + + // tolerances + cbcModel.setAllowableGap( model->dbl_param[DBL_PARAM_ALLOWABLE_GAP] ); + cbcModel.setAllowableFractionGap( model->dbl_param[DBL_PARAM_GAP_RATIO] ); + cbcModel.setIntegerTolerance( model->dbl_param[DBL_PARAM_INT_TOL] ); + + cbcModel.setLogLevel( model->int_param[INT_PARAM_LOG_LEVEL] ); + + // aditional parameters specified by user as strings + std::vector< string > argv; + argv.push_back("Cbc_C_Interface"); + for ( size_t i=0 ; ivcbcOptions.size() ; ++i ) { + string param = model->vcbcOptions[i]; + string val = model->cbcOptions[param]; + if (val.size()) { + stringstream ss; + ss << "-" << param << "=" << val; + argv.push_back(ss.str().c_str()); + } else { + stringstream ss; + ss << "-" << param; + argv.push_back(ss.str()); + } + } + + argv.push_back("-solve"); + argv.push_back("-quit"); + + char **charCbcOpts = to_char_vec(argv); + const int nargs = (int) argv.size(); + const char **args = (const char **)charCbcOpts; + + OsiBabSolver defaultC; + if (model->cutCBAtSol) { + defaultC.setSolverType(4); + cbcModel.solver()->setAuxiliaryInfo(&defaultC); + cbcModel.passInSolverCharacteristics(&defaultC); + } + + if (model->int_param[INT_PARAM_LOG_LEVEL] >= 1) { + printf("\nStarting MIP optimization\n"); + fflush(stdout); + } +#ifdef CBC_THREAD + { + int numberThreads = model->int_param[INT_PARAM_THREADS]; + if (numberThreads >= 1) { + cbcModel.setNumberThreads(numberThreads); + cbcModel.setThreadMode(CoinMin(numberThreads / 100, 7)); + } + } +#endif + cbcModel.setRoundIntegerVariables( model->int_param[INT_PARAM_ROUND_INT_VARS] ); + cbcModel.setRandomSeed(model->int_param[INT_PARAM_RANDOM_SEED]); + cbcModel.setUseElapsedTime( (model->int_param[INT_PARAM_ELAPSED_TIME] == 1) ); + + CbcMain1( nargs, args, cbcModel, cbc_callb, cbcData ); + + Cbc_getMIPOptimizationResults( model, cbcModel ); + + free(charCbcOpts); + + if (cbc_eh) + delete cbc_eh; + + if (cbcmh) + delete cbcmh; + } catch (CoinError &e) { + fprintf( stderr, "%s ERROR: %s::%s, %s\n", "Cbc_solve", + e.className().c_str(), e.methodName().c_str(), e.message().c_str()); + fflush(stderr); + abort(); + } + } /* end of MIP optimization */ + + return model->mipStatus; +} + +void CBC_LINKAGE Cbc_addIncCallback( + Cbc_Model *model, cbc_incumbent_callback inccb, + void *appData ) +{ + model->inc_callback = inccb; + model->icAppData = appData; +} + +void CBC_LINKAGE Cbc_addProgrCallback( + Cbc_Model *model, cbc_progress_callback prgcbc, + void *appData) +{ + model->progr_callback = prgcbc; + model->pgrAppData = appData; +} + +void CBC_LINKAGE Cbc_addCutCallback( + Cbc_Model *model, + cbc_cut_callback cutcb, + const char *name, + void *appData, + int howOften, + char atSolution ) +{ + model->cut_callback = cutcb; + model->cutCBName = string(name); + model->cutCBData = appData; + model->cutCBhowOften = howOften; + model->cutCBAtSol = atSolution; +} + +int CBC_LINKAGE +Cbc_getNumCols(Cbc_Model *model) +{ + return model->solver_->getNumCols() + model->nCols; +} + +int CBC_LINKAGE +Cbc_getNumRows(Cbc_Model *model) +{ + return model->solver_->getNumRows() + model->nRows; +} + + +int CBC_LINKAGE +Cbc_getIterationCount(Cbc_Model *model) { + return model->mipIterationCount; +} + +/** Number of non-zero entries in a row */ +int CBC_LINKAGE +Cbc_getRowNz(Cbc_Model *model, int row) +{ + VALIDATE_ROW_INDEX( row, model); + Cbc_flush(model); + + const CoinPackedMatrix *cpmRow = model->solver_->getMatrixByRow(); + return cpmRow->getVectorLengths()[row]; +} + +/** Indices of variables that appear on this row */ +const int *CBC_LINKAGE +Cbc_getRowIndices(Cbc_Model *model, int row) +{ + VALIDATE_ROW_INDEX( row, model); + Cbc_flush(model); + + const CoinPackedMatrix *cpmRow = model->solver_->getMatrixByRow(); + const CoinBigIndex *starts = cpmRow->getVectorStarts(); + const int *ridx = cpmRow->getIndices() + starts[row]; + return ridx; +} + +/** Coefficients of variables that appear on this row */ +const double *CBC_LINKAGE +Cbc_getRowCoeffs(Cbc_Model *model, int row) +{ + VALIDATE_ROW_INDEX( row, model); + Cbc_flush(model); + + const CoinPackedMatrix *cpmRow = model->solver_->getMatrixByRow(); + const CoinBigIndex *starts = cpmRow->getVectorStarts(); + const double *rcoef = cpmRow->getElements() + starts[row]; + return rcoef; +} + +/** Number of non-zero entries in a column */ +int CBC_LINKAGE +Cbc_getColNz(Cbc_Model *model, int col) +{ + VALIDATE_COL_INDEX( col, model ); + Cbc_flush(model); + + const CoinPackedMatrix *cpmCol = model->solver_->getMatrixByCol(); + return cpmCol->getVectorLengths()[col]; +} + +/** Indices of rows that a column appears */ +const int *CBC_LINKAGE +Cbc_getColIndices(Cbc_Model *model, int col) +{ + VALIDATE_COL_INDEX( col, model ); + Cbc_flush(model); + + const CoinPackedMatrix *cpmCol = model->solver_->getMatrixByCol(); + const CoinBigIndex *starts = cpmCol->getVectorStarts(); + const int *cidx = cpmCol->getIndices() + starts[col]; + return cidx; +} + +/** Coefficients that a column appear in rows */ +const double *CBC_LINKAGE +Cbc_getColCoeffs(Cbc_Model *model, int col) +{ + VALIDATE_COL_INDEX( col, model ); + Cbc_flush(model); + + const CoinPackedMatrix *cpmCol = model->solver_->getMatrixByCol(); + const CoinBigIndex *starts = cpmCol->getVectorStarts(); + const double *ccoef = cpmCol->getElements() + starts[col]; + return ccoef; +} + +/** Right hand side of a row */ +double CBC_LINKAGE +Cbc_getRowRHS(Cbc_Model *model, int row) +{ + VALIDATE_ROW_INDEX( row, model ); + + if (rowsolver_->getNumRows()) { + return model->solver_->getRightHandSide()[row]; + } else { + int idxRowBuffer = row - model->solver_->getNumRows(); + if (model->rUB[idxRowBuffer] < COIN_DBL_MAX) + return model->rUB[idxRowBuffer]; + else + return model->rLB[idxRowBuffer]; + } +} + +/** Sense a row */ +char CBC_LINKAGE +Cbc_getRowSense(Cbc_Model *model, int row) +{ + VALIDATE_ROW_INDEX( row, model ); + + if (rowsolver_->getNumRows()) { + return model->solver_->getRowSense()[row]; + } else { + int idxRowBuffer = row - model->solver_->getNumRows(); + if (fabs(model->rLB[idxRowBuffer]-model->rUB[idxRowBuffer]) <= 1e-15) + return 'E'; + if (model->rUB[idxRowBuffer] == COIN_DBL_MAX) + return 'G'; + if (model->rLB[idxRowBuffer] == -COIN_DBL_MAX) + return 'L'; + + return 'R'; + } +} + +/** Are there a numerical difficulties? */ +int CBC_LINKAGE +Cbc_isAbandoned(Cbc_Model *model) +{ + switch (model->lastOptimization) { + case ModelNotOptimized: + fprintf( stderr, "Information not available, model was not optimized yet.\n"); + abort(); + break; + case ContinuousOptimization: + return model->solver_->isAbandoned(); + break; + case IntegerOptimization: + return model->mipIsAbandoned; + } + + return false; +} + +/** Is optimality proven? */ +int CBC_LINKAGE +Cbc_isProvenOptimal(Cbc_Model *model) +{ + switch (model->lastOptimization) { + case ModelNotOptimized: + fprintf( stderr, "Information not available, model was not optimized yet.\n"); + abort(); + break; + case ContinuousOptimization: + return model->solver_->isProvenOptimal(); + case IntegerOptimization: + return model->mipIsProvenOptimal; + } + + return false; +} + +int CBC_LINKAGE +Cbc_isProvenInfeasible(Cbc_Model *model) +{ + switch (model->lastOptimization) { + case ModelNotOptimized: + fprintf( stderr, "Information not available, model was not optimized yet.\n"); + abort(); + break; + case ContinuousOptimization: + return model->solver_->isProvenPrimalInfeasible(); + case IntegerOptimization: + if (model->mipStatus == -1) + return model->solver_->isProvenPrimalInfeasible(); + return model->mipIsProvenInfeasible; + } + + return false; +} + +double CBC_LINKAGE +Cbc_getObjValue(Cbc_Model *model) +{ + return model->obj_value; +} + +const double *CBC_LINKAGE +Cbc_getReducedCost(Cbc_Model *model) +{ + switch (model->lastOptimization) { + case ModelNotOptimized: + fprintf( stderr, "Information not available, model was not optimized yet.\n"); + abort(); + break; + case ContinuousOptimization: + return model->solver_->getReducedCost(); + case IntegerOptimization: + fprintf( stderr, "Information only available when optimizing continuous models.\n"); + abort(); + break; + } + + return NULL; +} + +const double *CBC_LINKAGE +Cbc_getRowPrice(Cbc_Model *model) +{ + switch (model->lastOptimization) { + case ModelNotOptimized: + fprintf( stderr, "Information not available, model was not optimized yet.\n"); + abort(); + break; + case ContinuousOptimization: + return model->solver_->getRowPrice(); + case IntegerOptimization: + fprintf( stderr, "Information only available when optimizing continuous models.\n"); + abort(); + break; + } + + return NULL; +} + +int CBC_LINKAGE +Cbc_numberSavedSolutions(Cbc_Model *model) +{ + switch (model->lastOptimization) { + case ModelNotOptimized: + fprintf( stderr, "Information not available, model was not optimized yet.\n"); + abort(); + break; + case ContinuousOptimization: + if (model->solver_->isProvenOptimal()) + return 1; + else + return 0; + case IntegerOptimization: + return model->mipNumSavedSolutions; + } + + return 0; +} + +const double *CBC_LINKAGE +Cbc_savedSolution(Cbc_Model *model, int whichSol) +{ + switch (model->lastOptimization) { + case ModelNotOptimized: + fprintf( stderr, "Information not available, model was not optimized yet.\n"); + abort(); + break; + case ContinuousOptimization: + fprintf( stderr, "Information only available when optimizing integer models.\n"); + abort(); + break; + case IntegerOptimization: + if (model->mipNumSavedSolutions == 0) { + fprintf(stderr, "No solution found in last optimization.\n"); + fflush(stderr); + abort(); + } + if (whichSol>=model->mipNumSavedSolutions || whichSol<0) { + fprintf(stderr, "Invalid solution number, should be in [0,%d]", model->mipNumSavedSolutions-1); + fflush(stderr); + abort(); + } + return &((*model->mipSavedSolution)[whichSol][0]); + } + + return NULL; +} + +double CBC_LINKAGE +Cbc_savedSolutionObj(Cbc_Model *model, int whichSol) +{ + switch (model->lastOptimization) { + case ModelNotOptimized: + fprintf( stderr, "Information not available, model was not optimized yet.\n"); + abort(); + break; + case ContinuousOptimization: + fprintf( stderr, "Information only available when optimizing integer models.\n"); + abort(); + break; + case IntegerOptimization: + if (model->mipNumSavedSolutions == 0) { + fprintf(stderr, "No solution found in last optimization.\n"); + fflush(stderr); + abort(); + } + if (whichSol>=model->mipNumSavedSolutions || whichSol<0) { + fprintf(stderr, "Invalid solution number, should be in [0,%d]", model->mipNumSavedSolutions-1); + fflush(stderr); + abort(); + } + return (*model->mipSavedSolutionObj)[whichSol]; + } + + return COIN_DBL_MAX; +} + +const double *CBC_LINKAGE +Cbc_getColSolution(Cbc_Model *model) +{ + if (model->lastOptimization == ModelNotOptimized) { + fprintf( stderr, "Information not available, model was not optimized yet.\n"); + abort(); + } + + return model->x; +} + +/** @brief Upper bound of ranged constraint + * + * @param model problem object + * @param row row index + * @return row upper bound + **/ +double CBC_LINKAGE +Cbc_getRowUB(Cbc_Model *model, int row) { + if (rowsolver_->getNumRows()) { + return model->solver_->getRowUpper()[row]; + } else { + int nridx = row - model->solver_->getNumRows(); + return model->rUB[nridx]; + } +} + +/** @brief Lower bound of ranged constraint + * + * @param model problem object + * @param row row index + * @return row lower bound + **/ +double CBC_LINKAGE Cbc_getRowLB(Cbc_Model *model, int row) { + if (rowsolver_->getNumRows()) { + return model->solver_->getRowLower()[row]; + } else { + int nridx = row - model->solver_->getNumRows(); + return model->rLB[nridx]; + } +} + +char CBC_LINKAGE Cbc_checkFeasibility(Cbc_Model *model, const double x[], + double *maxViolRow, int *rowIdx, + double *maxViolCol, int *colIdx) { + *maxViolRow = *maxViolCol = -1.0; + *rowIdx = *colIdx = -1; + const double primalTol = model->dbl_param[DBL_PARAM_PRIMAL_TOL]; + const double intTol = model->dbl_param[DBL_PARAM_INT_TOL]; + + char feasible = 1; + int nRows = Cbc_getNumRows(model); + for ( int i=0 ; (irowUB) { + viol = lhs-rowUB; + } else { + if (lhs(*maxViolRow)) { + if (viol>primalTol) + feasible = 0; + *maxViolRow = viol; + *rowIdx = i; + } + } // all rows + + int nCols = Cbc_getNumCols(model); + for ( int j=0 ; (jcub) { + viol = x[j] - cub; + } else { + if (x[j]primalTol) + feasible = 0; + + if (Cbc_isInteger(model, j)) { + double vint = floor(x[j] + 0.5); + double intviol = fabs(x[j]-vint); + if (intviol > intTol) + feasible = 0; + viol = std::max(viol, intTol); + } + + if ( viol > *maxViolCol ) { + *maxViolCol = viol; + *colIdx = j; + } + } // all columns + + return feasible; +} + +int CBC_LINKAGE +Cbc_isContinuousUnbounded(Cbc_Model *model) { + switch (model->lastOptimization) { + case ModelNotOptimized: + fprintf( stderr, "Information not available, model was not optimized yet.\n"); + abort(); + break; + case ContinuousOptimization: + return model->solver_->isProvenDualInfeasible(); + case IntegerOptimization: + return model->mipIsContinuousUnbounded; + } + + return false; +} + + +int CBC_LINKAGE +Cbc_isNodeLimitReached(Cbc_Model *model) { + switch (model->lastOptimization) { + case ModelNotOptimized: + fprintf( stderr, "Information not available, model was not optimized yet.\n"); + abort(); + break; + case ContinuousOptimization: + fprintf( stderr, "Information not available when optimizing continuous models.\n"); + abort(); + break; + case IntegerOptimization: + return model->mipIsNodeLimitReached; + } + + return false; +} + + +int CBC_LINKAGE +Cbc_isSecondsLimitReached(Cbc_Model *model) { + switch (model->lastOptimization) { + case ModelNotOptimized: + fprintf( stderr, "Information not available, model was not optimized yet.\n"); + abort(); + break; + case ContinuousOptimization: + fprintf( stderr, "Information only available when optimizing integer models.\n"); + abort(); + break; + case IntegerOptimization: + return model->mipIsSecondsLimitReached; + } + + return false; +} + +int CBC_LINKAGE +Cbc_isSolutionLimitReached(Cbc_Model *model) { + switch (model->lastOptimization) { + case ModelNotOptimized: + fprintf( stderr, "Information not available, model was not optimized yet.\n"); + abort(); + break; + case ContinuousOptimization: + fprintf( stderr, "Information only available when optimizing integer models.\n"); + abort(); + break; + case IntegerOptimization: + return model->mipIsSolutionLimitReached; + } + + return false; +} + +int CBC_LINKAGE +Cbc_isInitialSolveAbandoned(Cbc_Model *model) { + switch (model->lastOptimization) { + case ModelNotOptimized: + fprintf( stderr, "Information not available, model was not optimized yet.\n"); + abort(); + break; + case ContinuousOptimization: + fprintf( stderr, "Information only available when optimizing integer models.\n"); + abort(); + break; + case IntegerOptimization: + return model->mipIsInitialSolveAbandoned; + } + + return false; +} + +int CBC_LINKAGE +Cbc_isInitialSolveProvenOptimal(Cbc_Model *model) { + switch (model->lastOptimization) { + case ModelNotOptimized: + fprintf( stderr, "Information not available, model was not optimized yet.\n"); + abort(); + break; + case ContinuousOptimization: + fprintf( stderr, "Information only available when optimizing integer models.\n"); + abort(); + break; + case IntegerOptimization: + return model->mipIsInitialSolveProvenOptimal; + } + + return false; +} + + +int CBC_LINKAGE +Cbc_isInitialSolveProvenPrimalInfeasible(Cbc_Model *model) { + switch (model->lastOptimization) { + case ModelNotOptimized: + fprintf( stderr, "Information not available, model was not optimized yet.\n"); + abort(); + break; + case ContinuousOptimization: + fprintf( stderr, "Information only available when optimizing integer models.\n"); + abort(); + break; + case IntegerOptimization: + return model->mipIsInitialSolveProvenPrimalInfeasible; + } + + return false; + +} + +double CBC_LINKAGE +Cbc_getObjSense(Cbc_Model *model) { + return model->solver_->getObjSense(); +} + +void CBC_LINKAGE +Cbc_setObjSense(Cbc_Model *model, double sense) +{ + Cbc_flush(model); + model->solver_->setObjSense(sense); +} + +void CBC_LINKAGE +Cbc_setRowLower(Cbc_Model *model, int index, double value) +{ + Cbc_flush(model); + VALIDATE_ROW_INDEX(index, model); + + OsiClpSolverInterface *solver = model->solver_; + solver->setRowLower(index, value); +} + +void CBC_LINKAGE +Cbc_setRowUpper(Cbc_Model *model, int index, double value) +{ + Cbc_flush(model); + VALIDATE_ROW_INDEX(index, model); + OsiClpSolverInterface *solver = model->solver_; + solver->setRowUpper(index, value); +} + +void CBC_LINKAGE +Cbc_setRowRHS(Cbc_Model *model, int row, double rhs) +{ + VALIDATE_ROW_INDEX(row, model); + + Cbc_flush(model); + char sense = Cbc_getRowSense(model, row); + switch (sense) + { + case 'L': + Cbc_setRowUpper(model, row, rhs); + break; + case 'G': + Cbc_setRowLower(model, row, rhs); + break; + case 'E': + Cbc_setRowLower(model, row, rhs); + Cbc_setRowUpper(model, row, rhs); + break; + default: + fprintf(stderr, "Could not change RHS in row %d to %g in row with sense: %c\n", + row, rhs, sense); + abort(); + } +} + +/** @brief Constraint lower bounds + * + * @param model problem object + * @return vector with lower bounds of constraints + **/ +const double *CBC_LINKAGE +Cbc_getRowLower(Cbc_Model *model) +{ + Cbc_flush(model); + OsiClpSolverInterface *solver = model->solver_; + return solver->getRowLower(); +} + +/** @brief Constraint upper bounds + * + * @param model problem object + * @return constraint upper bounds + **/ +const double *CBC_LINKAGE +Cbc_getRowUpper(Cbc_Model *model) +{ + Cbc_flush(model); + OsiClpSolverInterface *solver = model->solver_; + return solver->getRowUpper(); +} + + +const double *CBC_LINKAGE +Cbc_getRowActivity(Cbc_Model *model) { + if ( model->lastOptimization == ModelNotOptimized ) { + fprintf( stderr, "Information not available, model was not optimized yet.\n"); + abort(); + } + + return model->rActv; +} + + +const double *CBC_LINKAGE +Cbc_getRowSlack(Cbc_Model *model) { + if (model->lastOptimization==ModelNotOptimized) { + fprintf( stderr, "Information not available, model was not optimized yet.\n"); + abort(); + } + + return model->rSlk; +} + +const double *CBC_LINKAGE +Cbc_getColLower(Cbc_Model *model) +{ + Cbc_flush(model); + return model->solver_->getColLower(); +} + +const double *CBC_LINKAGE +Cbc_getColUpper(Cbc_Model *model) +{ + Cbc_flush(model); + return model->solver_->getColUpper(); +} + +double CBC_LINKAGE Cbc_getColObj(Cbc_Model *model, int colIdx) { + VALIDATE_COL_INDEX(colIdx, model); + + if (colIdx < model->solver_->getNumCols()) { + return model->solver_->getObjCoefficients()[colIdx]; + } else { + int ncIdx = colIdx - model->solver_->getNumCols(); + return model->cObj[ncIdx]; + } +} + +double CBC_LINKAGE Cbc_getColLB(Cbc_Model *model, int colIdx) { + VALIDATE_COL_INDEX(colIdx, model); + + if (colIdx < model->solver_->getNumCols()) { + return model->solver_->getColLower()[colIdx]; + } else { + int ncIdx = colIdx - model->solver_->getNumCols(); + return model->cLB[ncIdx]; + } +} + +double CBC_LINKAGE Cbc_getColUB(Cbc_Model *model, int colIdx) { + VALIDATE_COL_INDEX(colIdx, model); + + if (colIdx < model->solver_->getNumCols()) { + return model->solver_->getColUpper()[colIdx]; + } else { + int ncIdx = colIdx - model->solver_->getNumCols(); + return model->cUB[ncIdx]; + } +} + +double CBC_LINKAGE +Cbc_getBestPossibleObjValue(Cbc_Model *model) { + switch (model->lastOptimization) { + case ModelNotOptimized: + fprintf( stderr, "Information not available, model was not optimized yet.\n"); + abort(); + break; + case ContinuousOptimization: + return model->solver_->getObjValue(); + case IntegerOptimization: + return model->mipBestPossibleObjValue; + } + + return COIN_DBL_MIN; +} + +const double *CBC_LINKAGE +Cbc_getObjCoefficients(Cbc_Model *model) +{ + Cbc_flush(model); + return model->solver_->getObjCoefficients(); +} + +void CBC_LINKAGE +Cbc_setObjCoeff(Cbc_Model *model, int index, double value) +{ + Cbc_flush( model); + VALIDATE_COL_INDEX(index, model); + + model->solver_->setObjCoeff( index, value ); +} + +void CBC_LINKAGE +Cbc_setColLower(Cbc_Model *model, int index, double value) +{ + Cbc_flush(model); + VALIDATE_COL_INDEX(index, model); + model->solver_->setColLower( index, value ); +} + +void CBC_LINKAGE +Cbc_setColUpper(Cbc_Model *model, int index, double value) +{ + Cbc_flush(model); + VALIDATE_COL_INDEX(index, model); + model->solver_->setColUpper( index, value ); +} + + +const double *CBC_LINKAGE +Cbc_bestSolution(Cbc_Model *model) +{ + switch (model->lastOptimization) { + case ModelNotOptimized: + fprintf( stderr, "Information not available, model was not optimized yet.\n"); + abort(); + break; + case ContinuousOptimization: + return model->solver_->getColSolution(); + case IntegerOptimization: + if (model->mipBestSolution) + return VEC_PTR(model->mipBestSolution); + else + return NULL; + } + + return NULL; +} + +int CBC_LINKAGE +Cbc_isInteger(Cbc_Model *model, int i) +{ + Cbc_flush(model); + VALIDATE_COL_INDEX( i, model ); + return model->solver_->isInteger(i); +} + +int CBC_LINKAGE +Cbc_getNodeCount(Cbc_Model *model) { + switch (model->lastOptimization) { + case ModelNotOptimized: + fprintf( stderr, "Information not available, model was not optimized yet.\n"); + abort(); + break; + case ContinuousOptimization: + fprintf( stderr, "Information only available when optimizing integer models.\n"); + abort(); + break; + case IntegerOptimization: + return model->mipNodeCount; + } + + return false; +} + + +/** Return a copy of this model */ +Cbc_Model *CBC_LINKAGE +Cbc_clone(Cbc_Model *model) +{ + Cbc_flush(model); + Cbc_Model *result = new Cbc_Model(); + + result->solver_ = new OsiClpSolverInterface(*model->solver_); + result->solver_->setIntParam(OsiNameDiscipline, 1); + + result->relax_ = model->relax_; + + result->inc_callback = model->inc_callback; + result->progr_callback = model->progr_callback; + result->userCallBack = model->userCallBack; + + result->cut_callback = model->cut_callback; + result->cutCBData = model->cutCBData; + result->cutCBhowOften = model->cutCBhowOften; + result->cutCBAtSol = model->cutCBAtSol; + + result->obj_value = model->obj_value; + + result->lastOptimization = model->lastOptimization; + + if (model->slack) { + result->slack = new vector(model->slack->begin(), model->slack->end()); + } + else { + result->slack = NULL; + } + + result->icAppData = model->icAppData; + result->pgrAppData = model->pgrAppData; + + if (model->colNameIndex) { + Cbc_storeNameIndexes(result, 1); + fillAllNameIndexes(result); + } else { + result->colNameIndex = NULL; + result->rowNameIndex = NULL; + } + + Cbc_iniBuffer(result); + + if (model->iniSol) { + result->iniSol = new vector( model->iniSol->begin(), model->iniSol->end() ); + result->iniObj = model->iniObj; + } + else + { + result->iniSol = NULL; + result->iniObj = COIN_DBL_MAX; + } + + /* MIPStart */ + if (model->nColsMS) { + result->nColsMS = model->nColsMS; + result->colNamesMS = (char **) xmalloc( sizeof(char *)*model->nColsMS ); + result->charSpaceMS = model->charSpaceMS; + result->colNamesMS[0] = (char *) xmalloc( result->charSpaceMS ); + memcpy( result->colNamesMS[0], model->colNamesMS[0], model->charSpaceMS ); + for ( int i=1 ; (inColsMS) ; ++i ) + result->colNamesMS[i] = result->colNamesMS[i-1] + strlen(result->colNamesMS[i-1]) + 1; + result->colValuesMS = (double*)xmalloc(sizeof(double)*result->nColsMS); + memcpy(result->colValuesMS, model->colValuesMS, sizeof(double)*result->nColsMS); + } + else + { + result->nColsMS = 0; + result->colNamesMS = NULL; + result->colValuesMS = NULL; + result->charSpaceMS = 0; + } + + /* SOSs */ + if ( model->nSos ) { + result->nSos = model->nSos; + result->sosSize = model->sosSize; + result->sosElSize = model->sosElSize; + + result->sosCap = result->nSos; + result->sosElCap = model->sosElCap; + + result->sosRowStart = (int*) xmalloc( sizeof(int)*(result->sosCap+1) ); + result->sosEl = (int*) xmalloc( sizeof(int)*(result->sosElCap) ); + result->sosElWeight = (double*) xmalloc( sizeof(double)*(result->sosElCap) ); + + memcpy( result->sosRowStart, model->sosRowStart, sizeof(int)*(result->nSos+1) ); + memcpy( result->sosEl, model->sosEl, sizeof(int)*(result->sosElSize) ); + memcpy( result->sosElWeight, model->sosElWeight, sizeof(double)*(result->sosElSize) ); + } + +#ifdef CBC_THREAD + pthread_mutex_init(&(result->cbcMutexCG), NULL); + pthread_mutex_init(&(result->cbcMutexEvent), NULL); +#endif + + // copying parameters + result->lp_method = model->lp_method; + result->dualp = model->dualp; + + memcpy(result->int_param, model->int_param, sizeof(result->int_param)); + memcpy(result->dbl_param, model->dbl_param, sizeof(result->dbl_param)); + + result->vcbcOptions = model->vcbcOptions; + result->cbcOptions = model->cbcOptions; + + result->mipStatus = model->mipStatus; + result->mipSecStatus = model->mipSecStatus; + result->mipIsAbandoned = model->mipIsAbandoned; + result->mipIsProvenOptimal = model->mipIsProvenOptimal; + result->mipIsProvenInfeasible = model->mipIsProvenInfeasible; + result->mipIsContinuousUnbounded = model->mipIsContinuousUnbounded; + result->mipIsNodeLimitReached = model->mipIsNodeLimitReached; + result->mipIsSecondsLimitReached = model->mipIsSecondsLimitReached; + result->mipIsSolutionLimitReached = model->mipIsSolutionLimitReached; + result->mipIsInitialSolveAbandoned = model->mipIsInitialSolveAbandoned; + result->mipIsInitialSolveProvenOptimal = model->mipIsInitialSolveProvenOptimal; + result->mipIsInitialSolveProvenPrimalInfeasible = model->mipIsInitialSolveProvenPrimalInfeasible; + result-> mipBestPossibleObjValue = model-> mipBestPossibleObjValue; + result->mipNumSavedSolutions = model->mipNumSavedSolutions; + result->mipNodeCount = model->mipNodeCount; + + if (model->mipSavedSolution) { + result->mipSavedSolution = new vector< vector >(model->mipSavedSolution->begin(), model->mipSavedSolution->end()); + result->mipSavedSolutionObj = new vector(model->mipSavedSolutionObj->begin(), model->mipSavedSolutionObj->end()); + result->mipBestSolution = new vector(model->mipBestSolution->begin(), model->mipBestSolution->end()); + result->mipRowActivity = new vector(model->mipRowActivity->begin(), model->mipRowActivity->end()); + } else { + result->mipSavedSolution = NULL; + result->mipSavedSolutionObj = NULL; + result->mipBestSolution = NULL; + result->mipRowActivity = NULL; + } + + return result; +} + +/* returns a copy of solver, without copying the current solution */ +OsiClpSolverInterface* Cbc_cloneSolver(OsiClpSolverInterface *solver) { + OsiClpSolverInterface *newSolver = new OsiClpSolverInterface(); + + newSolver->setIntParam(OsiNameDiscipline, 1); + newSolver->loadProblem(*solver->getMatrixByCol(), solver->getColLower(), solver->getColUpper(), + solver->getObjCoefficients(), solver->getRowLower(), solver->getRowUpper()); + + for (int i = 0; i < solver->getNumCols(); i++) { + newSolver->setColName(i, solver->getColName(i)); + + if (solver->isInteger(i)) { + newSolver->setInteger(i); + } else { + newSolver->setContinuous(i); + } + } + + for (int i = 0; i < solver->getNumRows(); i++) { + newSolver->setRowName(i, solver->getRowName(i)); + } + + std::string probName; + solver->getStrParam(OsiProbName, probName); + newSolver->setStrParam(OsiProbName, probName); + + return newSolver; +} + + +/** Discards the current solution, putting the model to an unsolved state */ +void CBC_LINKAGE +Cbc_reset(Cbc_Model *model) +{ + Cbc_flush(model); + + OsiClpSolverInterface *newSolver = Cbc_cloneSolver(model->solver_); + delete model->solver_; + model->solver_ = newSolver; + + model->lastOptimization = ModelNotOptimized; + Cbc_cleanOptResults(model); + + if (model->mipSavedSolution) { + delete model->mipSavedSolution; + delete model->mipSavedSolutionObj; + delete model->mipBestSolution; + delete model->mipRowActivity; + model->mipSavedSolution = NULL; + model->mipSavedSolutionObj = NULL; + model->mipBestSolution = NULL; + model->mipRowActivity = NULL; + } +} + +/** Set this the variable to be continuous */ +void CBC_LINKAGE +Cbc_setContinuous(Cbc_Model *model, int iColumn) +{ + Cbc_flush(model); + VALIDATE_COL_INDEX( iColumn, model ); + + model->solver_->setContinuous(iColumn); +} + +/** Set this the variable to be integer */ +void CBC_LINKAGE +Cbc_setInteger(Cbc_Model *model, int iColumn) +{ + Cbc_flush(model); + VALIDATE_COL_INDEX( iColumn, model ); + + model->solver_->setInteger(iColumn); +} + +/** Adds a new column */ +void CBC_LINKAGE +Cbc_addCol(Cbc_Model *model, const char *name, double lb, + double ub, double obj, char isInteger, + int nz, int *rows, double *coefs) +{ + OsiClpSolverInterface *solver = model->solver_; + + if (nz >= 1 && model->rStart && model->rStart[model->nRows] >= 1) { + // new columns have reference to rows which have references to columns, flushing + Cbc_flush(model); + } + + Cbc_addColBuffer( model, name, nz, rows, coefs, lb, ub, obj, isInteger ); + + if (model->colNameIndex) + { + NameIndex &colNameIndex = *((NameIndex *)model->colNameIndex); + colNameIndex[std::string(name)] = Cbc_getNumCols(model)-1; + } +} + +/** Adds a new row */ +void CBC_LINKAGE +Cbc_addRow(Cbc_Model *model, const char *name, int nz, + const int *cols, const double *coefs, char sense, double rhs) +{ + if (nz == 0) + return; + + if (nz >= 1 && model->cStart && model->cStart[model->nCols] >= 1) { + // new rows have reference to columns which have references to rows, flushing + Cbc_flush(model); + } + + double rowLB = -DBL_MAX, rowUB = DBL_MAX; + switch (toupper(sense)) { + case '=': + rowLB = rowUB = rhs; + break; + case 'E': + rowLB = rowUB = rhs; + break; + case '<': + rowUB = rhs; + break; + case 'L': + rowUB = rhs; + break; + case '>': + rowLB = rhs; + break; + case 'G': + rowLB = rhs; + break; + default: + fprintf(stderr, "unknown row sense %c.", toupper(sense)); + abort(); + } + + Cbc_addRowBuffer(model, nz, cols, coefs, rowLB, rowUB, name); + + if (model->rowNameIndex) + { + NameIndex &rowNameIndex = *((NameIndex *)model->rowNameIndex); + rowNameIndex[std::string(name)] = Cbc_getNumRows(model)-1; + } +} + + +void CBC_LINKAGE +Cbc_addLazyConstraint(Cbc_Model *model, int nz, + int *cols, double *coefs, char sense, double rhs) +{ + if (model->lazyConstrs==NULL) + model->lazyConstrs = new CglStored(); + + OsiRowCut orc; + orc.setRow( nz, cols, coefs ); + + orc.setLb(-DBL_MAX); + orc.setUb(DBL_MAX); + + switch (toupper(sense)) { + case '=': + orc.setLb(rhs); + orc.setUb(rhs); + break; + case 'E': + orc.setLb(rhs); + orc.setUb(rhs); + break; + case '<': + orc.setUb(rhs); + break; + case 'L': + orc.setUb(rhs); + break; + case '>': + orc.setLb(rhs); + break; + case 'G': + orc.setLb(rhs); + break; + default: + fprintf(stderr, "unknown row sense %c.", toupper(sense)); + abort(); + } + + model->lazyConstrs->addCut(orc); +} + +void CBC_LINKAGE +Cbc_readMIPStart(Cbc_Model *model, const char fileName[]) { + std::vector< std::pair< std::string, double > > colValues; + double obj; + CoinMessages generalMessages = model->solver_->getModelPtr()->messages(); + CoinMessageHandler *messHandler = model->solver_->messageHandler(); + CbcMipStartIO::read(model->solver_, fileName, colValues, obj, messHandler, &generalMessages); + + char **cnames = new char*[colValues.size()]; + size_t charSpace = 0; + for ( int i=0 ; (i<(int)colValues.size()) ; ++i ) + charSpace += colValues[i].first.size() + 1; + cnames[0] = new char[charSpace]; + for ( int i=1 ; (i<(int)colValues.size()) ; ++i ) + cnames[i] = cnames[i-1] + colValues[i-1].first.size() + 1; + + double *cval = new double[colValues.size()]; + for ( int i=0 ; (i<(int)colValues.size()) ; ++i ) { + cval[i] = colValues[i].second; + strcpy(cnames[i], colValues[i].first.c_str()); + } + + Cbc_setMIPStart(model, colValues.size(), (const char **) cnames, cval); + delete[] cnames[0]; + delete[] cnames; + delete[] cval; +} + +void CBC_LINKAGE +Osi_addRow(void *osi, const char *name, int nz, + const int *cols, const double *coefs, char sense, double rhs) +{ + OsiSolverInterface *solver = (OsiSolverInterface *) osi; + double rowLB = -DBL_MAX, rowUB = DBL_MAX; + switch (toupper(sense)) { + case '=': + rowLB = rowUB = rhs; + break; + case 'E': + rowLB = rowUB = rhs; + break; + case '<': + rowUB = rhs; + break; + case 'L': + rowUB = rhs; + break; + case '>': + rowLB = rhs; + break; + case 'G': + rowLB = rhs; + break; + default: + fprintf(stderr, "unknown row sense %c.", toupper(sense)); + abort(); + } + + solver->addRow(nz, cols, coefs, rowLB, rowUB); + solver->setRowName(solver->getNumRows()-1, std::string(name)); +} + +void CBC_LINKAGE +Osi_setObjSense(void *osi, double sense) +{ + OsiSolverInterface *solver = (OsiSolverInterface *) osi; + solver->setObjSense(sense); +} + +void CBC_LINKAGE +Cbc_deleteRows(Cbc_Model *model, int numRows, const int rows[]) +{ + Cbc_flush(model); + OsiSolverInterface *solver = model->solver_; + + if (model->rowNameIndex) + { + NameIndex &rowNameIndex = *((NameIndex *)model->rowNameIndex); + for ( int i=0 ; igetRowName(rows[i])); + } + + solver->deleteRows(numRows, rows); + + if (model->rowNameIndex) { + int nRows = Cbc_getNumRows(model); + NameIndex &rowNameIndex = *((NameIndex *)model->rowNameIndex); + for ( int i=0 ; igetRowName(i)] = i; + } + } // updating row indexes +} + +void CBC_LINKAGE +Cbc_deleteCols(Cbc_Model *model, int numCols, const int cols[]) +{ + Cbc_flush(model); + OsiSolverInterface *solver = model->solver_; + + if (model->colNameIndex) + { + NameIndex &colNameIndex = *((NameIndex *)model->colNameIndex); + for ( int i=0 ; igetColName(cols[i])); + } + + solver->deleteCols(numCols, cols); + + if (model->colNameIndex) { + int nCols = Cbc_getNumCols(model); + NameIndex &colNameIndex = *((NameIndex *)model->colNameIndex); + for ( int i=0 ; igetColName(i)] = i; + } + } // updating column indexes + +} + +Cbc_Column CBC_LINKAGE Cbc_getColumn(Cbc_Model *model, int colIdx ) { + Cbc_Column result; + + result.nz = Cbc_getColNz(model, colIdx); + result.idx = Cbc_getColIndices(model, colIdx); + result.coef = Cbc_getColCoeffs(model, colIdx); + result.lb = Cbc_getColLB(model, colIdx); + result.ub = Cbc_getColUB(model, colIdx); + result.integer = Cbc_isInteger(model, colIdx); + + return result; +} + + +Cbc_Row CBC_LINKAGE Cbc_getRow( Cbc_Model *model, int rowIdx ) { + Cbc_Row result; + + result.nz = Cbc_getRowNz( model, rowIdx ); + result.idx = Cbc_getRowIndices( model, rowIdx ); + result.coef = Cbc_getRowCoeffs( model, rowIdx ); + result.rhs = Cbc_getRowRHS( model, rowIdx ); + result.lb = Cbc_getRowLB( model, rowIdx ); + result.ub = Cbc_getRowUB( model, rowIdx ); + result.sense = Cbc_getRowSense( model, rowIdx ); + + return result; +} + + + +/** Add SOS constraints to the model using row-order matrix */ +void CBC_LINKAGE +Cbc_addSOS(Cbc_Model *model, int numRows, const int *rowStarts, + const int *colIndices, const double *weights, const int type) +{ + int newEl = rowStarts[numRows] - rowStarts[0]; + + if (numRows + model->nSos > model->sosCap) { + int prevCap = model->sosCap; + if (prevCap) { + model->sosCap = std::max( 2*model->sosCap, numRows + model->nSos); + model->sosRowStart = (int *) xrealloc(model->sosRowStart, sizeof(int)*(model->sosCap+1) ); + model->sosType = (int *) xrealloc(model->sosRowStart, sizeof(int)*(model->sosCap) ); + } else { + model->sosCap = max(1024, numRows); + model->sosRowStart = (int *) xmalloc(sizeof(int)*(model->sosCap+1) ); + model->sosType = (int *) xmalloc(sizeof(int)*(model->sosCap) ); + model->sosRowStart[0] = 0; + model->sosElCap = std::max(8192, newEl); + model->sosEl = (int *) xmalloc( sizeof(int)*model->sosElCap ); + model->sosElWeight = (double *) xmalloc( sizeof(double)*model->sosElCap ); + model->sosElSize = 0; + model->nSos = 0; + } + } + + for ( int i=0 ; isosType[model->nSos+i] = type; + + if ( model->sosElSize + newEl > model->sosElCap ) { + model->sosElCap = max( 2*model->sosElCap, model->sosElSize + newEl ); + model->sosEl = (int *) xrealloc( model->sosEl, sizeof(int)*model->sosElCap ); + model->sosElWeight = (double *) xrealloc( model->sosElWeight, sizeof(double)*model->sosElCap ); + } + + memcpy( model->sosEl + model->sosElSize, colIndices, sizeof(int)*newEl ); + memcpy( model->sosElWeight + model->sosElSize, weights, sizeof(double)*newEl ); + + for ( int i=0 ; (isosRowStart[model->nSos+1] = model->sosRowStart[model->nSos] + size; + model->nSos++; + } + + model->sosElSize += newEl; +} + + +/** @brief Queries the number os SOS objects */ +int CBC_LINKAGE Cbc_numberSOS(Cbc_Model *model) { + return model->nSos; +} + +void CBC_LINKAGE +Cbc_setMIPStart(Cbc_Model *model, int count, const char **colNames, const double colValues[]) +{ + if (model->nColsMS) { + if (model->colNamesMS) { + free( model->colNamesMS[0]); + free( model->colNamesMS); + model->colNamesMS = NULL; + } + free( model->colValuesMS ); + model->colValuesMS = NULL; + } + + int nameSpace = 0; + for ( int i=0 ; (icolValuesMS = (double *) xmalloc( sizeof(double)*count ); + model->colNamesMS = (char **) xmalloc( sizeof(char*)*count ); + model->charSpaceMS = sizeof(char)*nameSpace; + model->colNamesMS[0] = (char *) xmalloc( model->charSpaceMS ); + + + for ( int i=1 ; (icolNamesMS[i] = model->colNamesMS[i-1] + 1 + strlen(colNames[i-1]); + + for ( int i=0 ; (icolNamesMS[i], colNames[i] ); + + memcpy(model->colValuesMS, colValues, sizeof(double)*count ); + model->nColsMS = count; +} + +void CBC_LINKAGE +Cbc_setMIPStartI(Cbc_Model *model, int count, const int colIdxs[], const double colValues[]) +{ + OsiSolverInterface *solver = model->solver_; + + if (model->nColsMS) { + if (model->colNamesMS) { + free( model->colNamesMS[0]); + free( model->colNamesMS); + model->colNamesMS = NULL; + } + free( model->colValuesMS ); + model->colValuesMS = NULL; + } + + int nameSpace = 0; + for ( int i=0 ; (igetColName(colIdxs[i]).size(); + nameSpace += count; + + model->colValuesMS = (double *) xmalloc( sizeof(double)*count ); + model->colNamesMS = (char **) xmalloc( sizeof(char*)*count ); + model->charSpaceMS = sizeof(char)*nameSpace; + model->colNamesMS[0] = (char *) xmalloc( model->charSpaceMS ); + + for ( int i=1 ; (icolNamesMS[i] = model->colNamesMS[i-1] + 1 + solver->getColName(colIdxs[i-1]).size(); + + for ( int i=0 ; (icolNamesMS[i], solver->getColName(colIdxs[i]).c_str() ); + model->colValuesMS[i] = colValues[i]; + } + + memcpy(model->colValuesMS, colValues, sizeof(double)*count ); + model->nColsMS = count; +} + + +/** @brief Creates a new OsiClpSolverInterface and returns a pointer to an OsiSolverInterface object */ +void * CBC_LINKAGE +Osi_newSolver() +{ + OsiClpSolverInterface *clp = new OsiClpSolverInterface(); + + return dynamic_cast(clp); +} + +void CBC_LINKAGE +Osi_setObjCoef(void *osi, int index, double obj) +{ + OsiSolverInterface *osis = (OsiSolverInterface *)osi; + osis->setObjCoeff( index, obj ); +} + +/** @brief Solves initial LP relaxation */ +void CBC_LINKAGE +Osi_initialSolve(void *osi) +{ + OsiSolverInterface *osis = ( OsiSolverInterface *)osi; + osis->initialSolve(); +} + +/** @brief Reoptimizes linear program */ +void CBC_LINKAGE +Osi_resolve(void *osi) +{ + OsiSolverInterface *osis = ( OsiSolverInterface *)osi; + osis->resolve(); +} + +/** @brief Performs branch and bound */ +void CBC_LINKAGE +Osi_branchAndBound(void *osi) +{ + OsiSolverInterface *osis = ( OsiSolverInterface *)osi; + osis->branchAndBound(); +} + +// solution query methods +/** @brief Checks if optimization was abandoned */ +char CBC_LINKAGE +Osi_isAbandoned(void *osi) +{ + OsiSolverInterface *osis = ( OsiSolverInterface *)osi; + return (char)osis->isAbandoned(); +} + +/** @brief Checks if optimal solution was found */ +char CBC_LINKAGE +Osi_isProvenOptimal(void *osi) +{ + OsiSolverInterface *osis = ( OsiSolverInterface *)osi; + return (char)osis->isProvenOptimal(); +} + +/** @brief Checks if problem is primal infeasible */ +char CBC_LINKAGE +Osi_isProvenPrimalInfeasible(void *osi) +{ + OsiSolverInterface *osis = ( OsiSolverInterface *)osi; + return (char)osis->isProvenPrimalInfeasible(); +} + +/** @brief Checks if problem is dual infeasible */ +char CBC_LINKAGE +Osi_isProvenDualInfeasible(void *osi) +{ + OsiSolverInterface *osis = ( OsiSolverInterface *)osi; + return (char)osis->isProvenDualInfeasible(); +} + +/** @brief Checks if primal objective limit was reached */ +char CBC_LINKAGE +Osi_isPrimalObjectiveLimitReached(void *osi) +{ + OsiSolverInterface *osis = ( OsiSolverInterface *)osi; + return (char)osis->isPrimalObjectiveLimitReached(); +} + +/** @brief Checks if dual objective limit was reached */ +char CBC_LINKAGE +Osi_isDualObjectiveLimitReached(void *osi) +{ + OsiSolverInterface *osis = ( OsiSolverInterface *)osi; + return (char)osis->isDualObjectiveLimitReached(); +} + +/** @brief Checks if iteration limit was reached */ +char CBC_LINKAGE +Osi_isIterationLimitReached(void *osi) +{ + OsiSolverInterface *osis = ( OsiSolverInterface *)osi; + return (char)osis->isIterationLimitReached(); +} + + +int CBC_LINKAGE +Osi_getNumCols( void *osi ) +{ + OsiSolverInterface *osiSolver = (OsiSolverInterface *) osi; + return osiSolver->getNumCols(); +} + +/** @brief Computes instance features (can be used in machine learning methods) */ +void CBC_LINKAGE Osi_compute_features(void *solver, double *features) { + OsiFeatures::compute(features, (OsiSolverInterface *) solver); +} + +/** @brief Number of instance features available */ +int CBC_LINKAGE Osi_n_features() { + return OsiFeatures::n; +} + +/** @brief Name of feature i */ +const char * CBC_LINKAGE Osi_feature_name(int i); + + +/** @brief Creates (it not yet) the conflict graph */ +void CBC_LINKAGE +Osi_checkCGraph( void *osi ) { + OsiSolverInterface *solver = (OsiSolverInterface *)(osi); + solver->checkCGraph(); +} + +/** @brief Returns the conflict graph */ +const void * CBC_LINKAGE +Osi_CGraph( void *osi ) { + OsiSolverInterface *solver = (OsiSolverInterface *)(osi); + return solver->getCGraph(); +} + +size_t CBC_LINKAGE CG_nodes( void *cgraph ) { + const CoinStaticConflictGraph *cg = (CoinStaticConflictGraph *)cgraph; + return cg->size(); +} + +char CBC_LINKAGE CG_conflicting( void *cgraph, int n1, int n2 ) { + const CoinStaticConflictGraph *cg = (CoinStaticConflictGraph *)cgraph; + return (char) cg->conflicting(n1, n2); +} + +/** @brief Density of the conflict graph */ +double CBC_LINKAGE CG_density( void *cgraph ) { + const CoinStaticConflictGraph *cg = (CoinStaticConflictGraph *)cgraph; + return cg->density(); +} + + +CGNeighbors CBC_LINKAGE CG_conflictingNodes(Cbc_Model *model, void *cgraph, size_t node) { + CGNeighbors result; + +#ifdef CBC_THREAD + pthread_mutex_lock(&model->cbcMutexCG); +#endif + + if (model->cg_space < Cbc_getNumCols(model)*2) { + if (model->cg_space) { + free( model->cg_neighs); + free(model->cg_iv); + } + + model->cg_space = Cbc_getNumCols(model)*2; + + model->cg_neighs = (size_t *) xmalloc( sizeof(size_t)*model->cg_space ); + model->cg_iv = (bool *) xmalloc( sizeof(bool)*model->cg_space ); + memset(model->cg_iv, 0, sizeof(bool)*model->cg_space); + } + + const CoinStaticConflictGraph *cg = (CoinStaticConflictGraph *)cgraph; + + std::pair< size_t, const size_t* > r = cg->conflictingNodes( node, model->cg_neighs, model->cg_iv); +#ifdef CBC_THREAD + pthread_mutex_unlock(&model->cbcMutexCG); +#endif + + result.n = r.first; + result.neigh = r.second; + + return result; +} + + + + + +/** @brief Returns column name in OsiSolverInterface object */ +void CBC_LINKAGE +Osi_getColName( void *osi, int i, char *name, int maxLen ) +{ + OsiSolverInterface *osiSolver = (OsiSolverInterface *) osi; + strncpy( name, osiSolver->getColName(i).c_str(), maxLen ); +} + +/** @brief Returns column lower bounds in OsiSolverInterface object */ +const double * CBC_LINKAGE +Osi_getColLower( void *osi ) +{ + OsiSolverInterface *osiSolver = (OsiSolverInterface *) osi; + return osiSolver->getColLower(); +} + +/** @brief Returns column upper bounds in OsiSolverInterface object */ +const double * CBC_LINKAGE +Osi_getColUpper( void *osi ) +{ + OsiSolverInterface *osiSolver = (OsiSolverInterface *) osi; + return osiSolver->getColUpper(); +} + +/** @brief Returns integrality information for columns in OsiSolverInterface object */ +int CBC_LINKAGE +Osi_isInteger( void *osi, int col ) +{ + OsiSolverInterface *osiSolver = (OsiSolverInterface *) osi; + return osiSolver->isInteger(col); +} + +/** @brief Returns number of rows in OsiSolverInterface object */ +int CBC_LINKAGE +Osi_getNumRows( void *osi ) +{ + OsiSolverInterface *osiSolver = (OsiSolverInterface *) osi; + return osiSolver->getNumRows(); +} + +/** @brief Returns number non-zeros in the constraint matrix */ +int CBC_LINKAGE +Osi_getNumNz( void *osi ) +{ + OsiSolverInterface *osiSolver = (OsiSolverInterface *) osi; + return osiSolver->getNumElements(); +} + +/** @brief Returns number integer/binary variables */ +int CBC_LINKAGE +Osi_getNumIntegers( void *osi ) +{ + OsiSolverInterface *osiSolver = (OsiSolverInterface *) osi; + return osiSolver->getNumIntegers(); +} + +int CBC_LINKAGE +Osi_getRowNz(void *osi, int row) +{ + OsiSolverInterface *osiSolver = (OsiSolverInterface *) osi; + + const CoinPackedMatrix *cpmRow = osiSolver->getMatrixByRow(); + return cpmRow->getVectorLengths()[row]; +} + +/** @brief Indices of variables that appear on a row */ +const int *CBC_LINKAGE +Osi_getRowIndices(void *osi, int row) +{ + OsiSolverInterface *osiSolver = (OsiSolverInterface *) osi; + + const CoinPackedMatrix *cpmRow = osiSolver->getMatrixByRow(); + const CoinBigIndex *starts = cpmRow->getVectorStarts(); + const int *ridx = cpmRow->getIndices() + starts[row]; + return ridx; +} + +/** @brief Coefficients of variables that appear on this row */ +const double *CBC_LINKAGE +Osi_getRowCoeffs(void *osi, int row) +{ + OsiSolverInterface *osiSolver = (OsiSolverInterface *) osi; + + const CoinPackedMatrix *cpmRow = osiSolver->getMatrixByRow(); + const CoinBigIndex *starts = cpmRow->getVectorStarts(); + const double *rcoef = cpmRow->getElements() + starts[row]; + return rcoef; +} + +/** @brief Right hand side of a row */ +double CBC_LINKAGE +Osi_getRowRHS(void *osi, int row) +{ + OsiSolverInterface *osiSolver = (OsiSolverInterface *) osi; + return osiSolver->getRightHandSide()[row]; +} + +/** @brief Sense a row + * @param model problem object + * @param row row index + * @return row sense: E for =, L for <=, G for >= and R for ranged row + **/ +char CBC_LINKAGE +Osi_getRowSense(void *osi, int row) +{ + OsiSolverInterface *osiSolver = (OsiSolverInterface *) osi; + + return osiSolver->getRowSense()[row]; +} + +/** Generates cutting planes */ +void CBC_LINKAGE Cbc_generateCuts( Cbc_Model *cbcModel, enum CutType ct, void *oc, int depth, int pass ) { + assert(cbcModel && oc); + + OsiClpSolverInterface *solver = cbcModel->solver_; + CglCutGenerator *cg = NULL; + OsiCuts *osiCuts = (OsiCuts *) oc; + int *int_param = cbcModel->int_param; + + switch (ct) { + case CT_Probing: + { + CglProbing *probingGen = new CglProbing();; + cg = probingGen; + + // current defaults based on CbcSolver + probingGen->setUsingObjective(1); + probingGen->setMaxPass(1); + probingGen->setMaxPassRoot(1); + // Number of unsatisfied variables to look at + probingGen->setMaxProbe(10); + probingGen->setMaxProbeRoot(50); + // How far to follow the consequences + probingGen->setMaxLook(10); + probingGen->setMaxLookRoot(50); + probingGen->setMaxLookRoot(10); + // Only look at rows with fewer than this number of elements + probingGen->setMaxElements(200); + probingGen->setMaxElementsRoot(300); + probingGen->setRowCuts(3); + } + break; + case CT_Gomory: + { + CglGomory *cglGom = new CglGomory(); + cg = cglGom; + cglGom->setLimitAtRoot(1000); + cglGom->setLimit(50); + break; + } + case CT_GMI: + { + cg = new CglGMI(); + break; + } + case CT_RedSplit: + { + cg = new CglRedSplit(); + break; + } + case CT_RedSplitG: + { + cg = new CglRedSplit2(); + break; + } + case CT_FlowCover: + { + cg = new CglFlowCover(); + break; + } + case CT_MIR: + { + CglMixedIntegerRounding2 *cgMIR = new CglMixedIntegerRounding2(1, true, 1); + cg = cgMIR; + cgMIR->setDoPreproc(1); // safer (and better) + break; + } + case CT_TwoMIR: + { + CglTwomir *cgTwomir = new CglTwomir(); + cg = cgTwomir; + cgTwomir->setMaxElements(250); + break; + } + case CT_LaTwoMIR: + { + CglTwomir *cgTwomir = new CglTwomir(); + cg = cgTwomir; + cgTwomir->setTwomirType(12); + cgTwomir->setMaxElements(250); + break; + } + + case CT_LiftAndProject: + cg = new CglLandP(); + break; + case CT_ResidualCapacity: + { + CglResidualCapacity *cglRC = new CglResidualCapacity(); + cg = cglRC; + cglRC->setDoPreproc(1); + + break; + } + case CT_ZeroHalf: + cg = new CglZeroHalf(); + break; + case CT_Clique: + { + char bkClique = 0; + if (solver->getCGraph()) + bkClique = 1; + if (int_param) { + if (int_param[INT_PARAM_CGRAPH] == 2) + bkClique = 1; + } + + if (bkClique) { + if (!solver->getCGraph()) { + solver->checkCGraph(); + } + cg = new CglBKClique(); + } else { + CglClique *clqgen = new CglClique(); + clqgen->setStarCliqueReport(false); + clqgen->setRowCliqueReport(false); + clqgen->setMinViolation(1e-4); + cg = clqgen; + } + break; + } + case CT_OddWheel: + solver->checkCGraph(); + cg = new CglOddWheel(); + break; + case CT_KnapsackCover: + cg = new CglKnapsackCover(); + break; + } + + CglTreeInfo treeInfo; + treeInfo.level = depth; + treeInfo.pass = pass; + + if (cg != NULL) { + cg->generateCuts(*solver, *osiCuts, treeInfo); + delete cg; + } +} + +/** Creates a new cut pool and returns its pointer */ +void * CBC_LINKAGE +OsiCuts_new() { + OsiCuts *oc = new OsiCuts(); + return (void *) oc; +} + +/** Deletes a cut pool */ +void CBC_LINKAGE +OsiCuts_delete( void *osiCuts ) { + OsiCuts *oc = (OsiCuts *) osiCuts; + delete oc; +} + +/** Returns the number of row cuts stored */ +int CBC_LINKAGE +OsiCuts_sizeRowCuts( void *osiCuts ) { + OsiCuts *oc = (OsiCuts *)osiCuts; + return oc->sizeRowCuts(); +} + +/** Returns the number of row cuts stored */ +int CBC_LINKAGE +OsiCuts_nzRowCut( void *osiCuts, int iRowCut ) { + assert(iRowCut >= 0 && iRowCut < OsiCuts_sizeRowCuts(osiCuts) ); + OsiCuts *oc = (OsiCuts *)osiCuts; + const OsiRowCut &rc = oc->rowCut(iRowCut); + return rc.row().getNumElements(); +} + +/** Returns the variable indexes in a row cut */ +const int * CBC_LINKAGE +OsiCuts_idxRowCut( void *osiCuts, int iRowCut ) { + assert(iRowCut >= 0 && iRowCut < OsiCuts_sizeRowCuts(osiCuts) ); + OsiCuts *oc = (OsiCuts *)osiCuts; + const OsiRowCut &rc = oc->rowCut(iRowCut); + return rc.row().getIndices(); +} + +/** Returns the variable coefficients in a row cut */ +const double * CBC_LINKAGE +OsiCuts_coefRowCut( void *osiCuts, int iRowCut ) { + assert(iRowCut >= 0 && iRowCut < OsiCuts_sizeRowCuts(osiCuts) ); + OsiCuts *oc = (OsiCuts *)osiCuts; + const OsiRowCut &rc = oc->rowCut(iRowCut); + return rc.row().getElements(); +} + +/** Returns the variable coefficients in a row cut */ +double CBC_LINKAGE +OsiCuts_rhsRowCut( void *osiCuts, int iRowCut ) { + assert(iRowCut >= 0 && iRowCut < OsiCuts_sizeRowCuts(osiCuts) ); + OsiCuts *oc = (OsiCuts *)osiCuts; + const OsiRowCut &rc = oc->rowCut(iRowCut); + return rc.rhs(); +} + +/** Returns the sense of a row cut */ +char CBC_LINKAGE +OsiCuts_senseRowCut( void *osiCuts, int iRowCut ) { + assert(iRowCut >= 0 && iRowCut < OsiCuts_sizeRowCuts(osiCuts) ); + OsiCuts *oc = (OsiCuts *)osiCuts; + const OsiRowCut &rc = oc->rowCut(iRowCut); + return rc.sense(); +} + +void CBC_LINKAGE +OsiCuts_addRowCut( void *osiCuts, int nz, const int *idx, const double *coef, char sense, double rhs ) +{ + sense = toupper(sense); + OsiCuts *oc = (OsiCuts *) osiCuts; + + OsiRowCut orc; + orc.setRow( nz, idx, coef ); + + + orc.setLb(-DBL_MAX); + orc.setUb(DBL_MAX); + + switch (toupper(sense)) { + case '=': + orc.setLb(rhs); + orc.setUb(rhs); + break; + case 'E': + orc.setLb(rhs); + orc.setUb(rhs); + break; + case '<': + orc.setUb(rhs); + break; + case 'L': + orc.setUb(rhs); + break; + case '>': + orc.setLb(rhs); + break; + case 'G': + orc.setLb(rhs); + break; + default: + fprintf(stderr, "unknown row sense %c.", toupper(sense)); + abort(); + } + + oc->insert(orc); +} + +/** adds a row cut (used in callback), stating that this is a globally valid cut */ +void CBC_LINKAGE +OsiCuts_addGlobalRowCut( void *osiCuts, int nz, const int *idx, const double *coef, char sense, double rhs ) +{ + sense = toupper(sense); + OsiCuts *oc = (OsiCuts *) osiCuts; + + OsiRowCut orc; + orc.setRow( nz, idx, coef ); + + + orc.setLb(-DBL_MAX); + orc.setUb(DBL_MAX); + + switch (toupper(sense)) { + case '=': + orc.setLb(rhs); + orc.setUb(rhs); + break; + case 'E': + orc.setLb(rhs); + orc.setUb(rhs); + break; + case '<': + orc.setUb(rhs); + break; + case 'L': + orc.setUb(rhs); + break; + case '>': + orc.setLb(rhs); + break; + case 'G': + orc.setLb(rhs); + break; + default: + fprintf(stderr, "unknown row sense %c.", toupper(sense)); + abort(); + } + + orc.setGloballyValid(true); + oc->insert(orc); +} + + +/** @brief Sets a variable to integer */ +void CBC_LINKAGE +Osi_setInteger(void *osi, int index) +{ + OsiSolverInterface *osiSolver = (OsiSolverInterface *) osi; + + osiSolver->setInteger(index); +} + +/** @brief Sets a variable to continuous */ +void CBC_LINKAGE +Osi_setContinuous(void *osi, int index) +{ + OsiSolverInterface *osiSolver = (OsiSolverInterface *) osi; + + osiSolver->setContinuous(index); +} + +int CBC_LINKAGE +Osi_getColNz(void *osi, int col) +{ + OsiSolverInterface *osiSolver = (OsiSolverInterface *) osi; + const CoinPackedMatrix *cpmCol = osiSolver->getMatrixByCol(); + return cpmCol->getVectorLengths()[col]; +} + +/** @brief Indices of rows that a column appears + * + * @param model problem object + * @param col column index + * @return indices of rows that this column appears + **/ +const int *CBC_LINKAGE +Osi_getColIndices(void *osi, int col) +{ + OsiSolverInterface *osiSolver = (OsiSolverInterface *) osi; + const CoinPackedMatrix *cpmCol = osiSolver->getMatrixByCol(); + const CoinBigIndex *starts = cpmCol->getVectorStarts(); + const int *cidx = cpmCol->getIndices() + starts[col]; + return cidx; +} + +/** @brief Coefficients that a column appear in rows + * + * @param model problem object + * @param col column index + * @return coefficients of this column in rows + **/ +const double *CBC_LINKAGE +Osi_getColCoeffs(void *osi, int col) +{ + OsiSolverInterface *osiSolver = (OsiSolverInterface *) osi; + + const CoinPackedMatrix *cpmCol = osiSolver->getMatrixByCol(); + const CoinBigIndex *starts = cpmCol->getVectorStarts(); + const double *rcoef = cpmCol->getElements() + starts[col]; + return rcoef; +} + +/** @brief Returns solution vector in OsiSolverInterface object */ +const double * CBC_LINKAGE +Osi_getColSolution( void *osi ) +{ + OsiSolverInterface *osiSolver = (OsiSolverInterface *) osi; + + return osiSolver->getColSolution(); +} + +/** Adds a new column */ +void CBC_LINKAGE +Osi_addCol(void *osi, const char *name, double lb, + double ub, double obj, char isInteger, + int nz, int *rows, double *coefs) +{ + OsiSolverInterface *osiSolver = (OsiSolverInterface *) osi; + + osiSolver->addCol(nz, rows, coefs, lb, ub, obj, std::string(name)); + if (isInteger) + osiSolver->setInteger(osiSolver->getNumCols() - 1); +} + +/** @brief Returns vector of reduced costs */ +const double * CBC_LINKAGE +Osi_getReducedCost( void *osi ) +{ + OsiSolverInterface *osiSolver = (OsiSolverInterface *) osi; + + return osiSolver->getColSolution(); +} + +/** @brief Returns vector dual variables */ +const double * CBC_LINKAGE +Osi_getRowPrice( void *osi ) +{ + OsiSolverInterface *osiSolver = (OsiSolverInterface *) osi; + + return osiSolver->getRowPrice(); +} + +double CBC_LINKAGE +Osi_getObjValue( void *osi ) +{ + OsiSolverInterface *osiSolver = (OsiSolverInterface *) osi; + + return osiSolver->getObjValue(); +} + +/** @brief Sets column upper bound */ +void CBC_LINKAGE +Osi_setColUpper (void *osi, int elementIndex, double ub) +{ + OsiSolverInterface *osiSolver = (OsiSolverInterface *) osi; + osiSolver->setColUpper(elementIndex, ub); +} + +/** @brief Sets column upper bound */ +void CBC_LINKAGE +Osi_setColLower(void *osi, int elementIndex, double lb) +{ + OsiSolverInterface *osiSolver = (OsiSolverInterface *) osi; + osiSolver->setColLower(elementIndex, lb); +} + +/** @brief integer tolerance */ +double CBC_LINKAGE +Osi_getIntegerTolerance(void *osi) +{ + OsiSolverInterface *osiSolver = (OsiSolverInterface *) osi; + return osiSolver->getIntegerTolerance(); +} + +double CBC_LINKAGE +Cbc_getAllowableGap(Cbc_Model* model) +{ + return model->dbl_param[DBL_PARAM_ALLOWABLE_GAP]; +} + +void CBC_LINKAGE +Cbc_setAllowableGap(Cbc_Model* model, double allowedGap) +{ + model->dbl_param[DBL_PARAM_ALLOWABLE_GAP] = allowedGap; +} + +double CBC_LINKAGE +Cbc_getAllowableFractionGap(Cbc_Model* model) +{ + return model->dbl_param[DBL_PARAM_GAP_RATIO]; +} + +void CBC_LINKAGE +Cbc_setAllowableFractionGap(Cbc_Model* model, double allowedFracionGap) +{ + model->dbl_param[DBL_PARAM_GAP_RATIO] = allowedFracionGap; +} + +/** returns the maximum number of nodes that can be explored in the search tree + */ +int CBC_LINKAGE +Cbc_getMaximumNodes(Cbc_Model *model) +{ + return model->int_param[INT_PARAM_MAX_NODES]; +} + +/** sets the maximum number of nodes that can be explored in the search tree + */ +void CBC_LINKAGE +Cbc_setMaximumNodes(Cbc_Model *model, int maxNodes) +{ + model->int_param[INT_PARAM_MAX_NODES] = maxNodes; +} + +/** returns solution limit for the search process + */ +int CBC_LINKAGE +Cbc_getMaximumSolutions(Cbc_Model *model) +{ + return model->int_param[INT_PARAM_MAX_SOLS]; +} + +/** sets a solution limit as a stopping criterion + */ +void CBC_LINKAGE +Cbc_setMaximumSolutions(Cbc_Model *model, int maxSolutions) +{ + model->int_param[INT_PARAM_MAX_SOLS] = maxSolutions; +} + +/** returns the current log leven + */ +int CBC_LINKAGE +Cbc_getLogLevel(Cbc_Model *model) +{ + return model->int_param[INT_PARAM_LOG_LEVEL]; +} + +/** sets the log level + */ +void CBC_LINKAGE +Cbc_setLogLevel(Cbc_Model *model, int logLevel) +{ + model->int_param[INT_PARAM_LOG_LEVEL] = logLevel; +} + +/** gets the tolerance for infeasibility in the LP solver + */ +double CBC_LINKAGE +Cbc_getPrimalTolerance(Cbc_Model *model) +{ + return model->dbl_param[DBL_PARAM_PRIMAL_TOL]; +} + +/** sets the tolerance for infeasibility in the LP solver + */ +void CBC_LINKAGE +Cbc_setPrimalTolerance(Cbc_Model *model, double tol) +{ + model->dbl_param[DBL_PARAM_PRIMAL_TOL] = tol; +} + +/** gets the tolerance for optimality in the LP solver + */ +double CBC_LINKAGE +Cbc_getDualTolerance(Cbc_Model *model) +{ + return model->dbl_param[DBL_PARAM_DUAL_TOL]; +} + +/** sets the tolerance for optimality in the LP solver + */ +void CBC_LINKAGE +Cbc_setDualTolerance(Cbc_Model *model, double tol) +{ + model->dbl_param[DBL_PARAM_DUAL_TOL] = tol; +} + +double CBC_LINKAGE +Cbc_getCutoff(Cbc_Model* model) +{ + return model->dbl_param[DBL_PARAM_CUTOFF]; +} + +void CBC_LINKAGE +Cbc_setCutoff(Cbc_Model* model, double cutoff) +{ + model->dbl_param[DBL_PARAM_CUTOFF] = cutoff; +} + +void CBC_LINKAGE +Cbc_setLPmethod(Cbc_Model *model, enum LPMethod lpm ) { + model->lp_method = lpm; +} + + +void * CBC_LINKAGE +Cbc_getSolverPtr(Cbc_Model *model) { + return model->solver_; +} + +void CBC_LINKAGE +Cbc_setDualPivot(Cbc_Model *model, enum DualPivot dp ) { + model->dualp = dp; +} + +double CBC_LINKAGE +Cbc_getMaximumSeconds(Cbc_Model *model) +{ + return model->dbl_param[DBL_PARAM_TIME_LIMIT]; +} + +void CBC_LINKAGE +Cbc_setMaximumSeconds(Cbc_Model *model, double maxSeconds) +{ + model->dbl_param[DBL_PARAM_TIME_LIMIT] = maxSeconds; +} + +void CBC_LINKAGE +Cbc_storeNameIndexes(Cbc_Model *model, char _store) +{ + if (_store) + { + if (model->colNameIndex==NULL) + { + assert(model->rowNameIndex==NULL); + model->colNameIndex = new NameIndex(); + model->rowNameIndex = new NameIndex(); + } + } + else + { + if (model->colNameIndex!=NULL) + { + NameIndex *m = (NameIndex *)model->colNameIndex; + delete m; + m = (NameIndex *)model->rowNameIndex; + assert( m != NULL ); + delete m; + + model->colNameIndex = model->rowNameIndex = NULL; + } + } +} + +int CBC_LINKAGE +Cbc_getColNameIndex(Cbc_Model *model, const char *name) +{ + if (!model->colNameIndex) + { + fprintf(stderr, "Call Cbc_storeNameIndex to enable name index search."); + abort(); + } + + NameIndex &colNameIndex = *((NameIndex *)model->colNameIndex); + NameIndex::iterator it = colNameIndex.find(std::string(name)); + if (it == colNameIndex.end()) + return -1; + + return it->second; +} + +int CBC_LINKAGE +Cbc_getRowNameIndex(Cbc_Model *model, const char *name) +{ + if (!model->rowNameIndex) + { + fprintf(stderr, "Call Cbc_storeNameIndex to enable name index search."); + abort(); + } + + NameIndex &rowNameIndex = *((NameIndex *)model->rowNameIndex); + NameIndex::iterator it = rowNameIndex.find(std::string(name)); + if (it == rowNameIndex.end()) + return -1; + + return it->second; +} + +static char **to_char_vec( const vector< string > &names ) +{ + size_t spaceVec = (sizeof(char*)*names.size()); + size_t totLen = names.size(); // all \0 + for ( int i=0 ; (i<(int)names.size()) ; ++i ) + totLen += names[i].size(); + totLen *= sizeof(char); + + char **r = (char **)xmalloc(spaceVec+totLen); + assert( r ); + r[0] = (char *)(r + names.size()); + for ( size_t i=1 ; (inSos == 0) + return; + + vector< CbcObject *> objects; + objects.reserve( model->nSos ); + for ( int i=0 ; inSos ; ++i ) { + objects.push_back( + new CbcSOS( + &cbcModel, + model->sosRowStart[i+1]-model->sosRowStart[i], + model->sosEl + model->sosRowStart[i], + model->sosElWeight + model->sosRowStart[i], + (int)objects.size(), + model->sosType[i] + ) + ); // add in objects + } + + cbcModel.addObjects( (int) objects.size(), &objects[0] ); + + for ( int i=0 ; inSos ; ++i ) + delete objects[i]; +} + +static void Cbc_addMS( Cbc_Model *model, CbcModel &cbcModel ) { + if ( model->nColsMS == 0 ) + return; + + cbcModel.setMIPStart( model->nColsMS, (const char **)model->colNamesMS, model->colValuesMS ); +} + +void Cbc_iniParams( Cbc_Model *model ) { + model->lp_method = LPM_Auto; + model->dualp = DP_Auto; + model->cg_space = 0; + model->cg_iv = NULL; + model->cg_neighs = NULL; + memset(model->int_param, 0, sizeof(model->int_param) ); + for ( int i=0 ; (idbl_param[i] = 0.0; + + model->int_param[INT_PARAM_PERT_VALUE] = 50; + model->int_param[INT_PARAM_IDIOT] = -1; + model->int_param[INT_PARAM_STRONG_BRANCHING] = 5; + model->int_param[INT_PARAM_CUT_DEPTH] = -1; + model->int_param[INT_PARAM_MAX_NODES] = INT_MAX; + model->int_param[INT_PARAM_NUMBER_BEFORE] = 5; + model->int_param[INT_PARAM_FPUMP_ITS] = 30; + model->int_param[INT_PARAM_MAX_SOLS] = INT_MAX; + model->int_param[INT_PARAM_CUT_PASS_IN_TREE] = 1; + model->int_param[INT_PARAM_LOG_LEVEL] = 1; + model->int_param[INT_PARAM_MAX_SAVED_SOLS] = 10; + model->int_param[INT_PARAM_MULTIPLE_ROOTS] = 0; + model->int_param[INT_PARAM_THREADS] = -1; + model->int_param[INT_PARAM_ROUND_INT_VARS] = 1; + model->int_param[INT_PARAM_RANDOM_SEED] = 1; + model->int_param[INT_PARAM_ELAPSED_TIME] = 1; + model->int_param[INT_PARAM_CGRAPH] = 1; + model->int_param[INT_PARAM_CLIQUE_MERGING] = -1; // not set + model->int_param[INT_PARAM_MAX_NODES_NOT_IMPROV_FS] = INT_MAX; + + model->dbl_param[DBL_PARAM_PRIMAL_TOL] = 1e-6; + model->dbl_param[DBL_PARAM_DUAL_TOL] = 1e-6; + model->dbl_param[DBL_PARAM_ZERO_TOL] = 1e-20; + model->dbl_param[DBL_PARAM_INT_TOL] = 1e-6; + model->dbl_param[DBL_PARAM_PRESOLVE_TOL] = 1e-8; + model->dbl_param[DBL_PARAM_TIME_LIMIT] = COIN_DBL_MAX; + model->dbl_param[DBL_PARAM_PSI] = -1.0; + model->dbl_param[DBL_PARAM_CUTOFF] = COIN_DBL_MAX; + model->dbl_param[DBL_PARAM_ALLOWABLE_GAP] = 1e-10; + model->dbl_param[DBL_PARAM_GAP_RATIO] = 0.0001; + model->dbl_param[DBL_PARAM_MAX_SECS_NOT_IMPROV_FS] = COIN_DBL_MAX; +} + +void CBC_LINKAGE Cbc_getBuildInfo(char *str) { + sprintf(str, "Cbc version: %s\n", CBC_VERSION); + char s[128]; + sprintf(s, "Build date: %s\n", __DATE__); + strcat(str, s); + strcat(str, "Build type: "); +#ifdef NDEBUG + strcat(str, "Release\n"); +#else + strcat(str, "Debug\n"); +#endif + +#ifdef __GNUC__ + sprintf(s, "Built with G++ version %s\n", __VERSION__); + strcat(str, s); +#endif + strcat(str, "Components:\n"); +#ifdef CBC_HAS_NAUTY + strcat(str, " nauty: yes\n"); +#else + strcat(str, " nauty: no\n"); +#endif +#ifdef CBC_THREAD + strcat(str, " threads: yes\n"); +#else + strcat(str, " threads: no\n"); +#endif + strcat(str, " compression formats:"); + if (Cbc_supportsGzip()) + strcat(str, " gz"); + if (Cbc_supportsBzip2()) + strcat(str, " bz2"); + + strcat(str, "\n"); +} + +#if defined(__MWERKS__) +#pragma export off +#endif diff --git a/src/Attic/CoinSolve.cpp b/src/Attic/CoinSolve.cpp new file mode 100644 index 000000000..c4860a5e3 --- /dev/null +++ b/src/Attic/CoinSolve.cpp @@ -0,0 +1,400 @@ +// Copyright (C) 2007, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +/*! \file CbcSolver.cpp + \brief Main routine for the cbc stand-alone solver. +*/ + +#undef CBCSOLVERLIB_BUILD + +/* would normally be a separate config header file, but the cbc exe has only one source file */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#else /* HAVE_CONFIG_H */ +#include "config_default.h" +#endif /* HAVE_CONFIG_H */ +#define __CBCCONFIG_H__ +#define COIN_HAS_CBC + +#include "CoinPragma.hpp" +#include "CbcModel.hpp" +#include "CbcSolver.hpp" +#include "OsiClpSolverInterface.hpp" +/* + We have the following compile-time symbols. + + CBC_OTHER_SOLVER CoinSolve.cpp, CbcSolver.[cpp,hpp], CbcModel.cpp + + A value of 1 says `cplex'. Other values not defined. The intent with + cplex is to apply all of cbc's smarts at the root, then hand the problem + over to cplex to finish. Cplex is not used as an alternate lp solver + under cbc control. + + Usage in CbcModel is a fake; a small bit of code that's now `#if 0'. + + + CLP_DEBUG_MALLOC + + This ties in with the functions clp_malloc, clp_free, and clp_memory, + which are defined in CoinOslFactorization.cpp. (Right where you'd expect + to find them, eh?). Looks to be a relatively nice debugging wrapper for + standard C malloc. Calls standard C malloc/free directly if + CLP_DEBUG_MALLOC is not defined. Worth consideration for breaking out as + a separate utility. The hooks for new and delete defined here should be + incorporated. + + Absolutely not thread safe --- lots of static variables. + + Hmmm ... is it still the case that standard C malloc and C++ new/delete + do not play well together? 'Cause the hooks here for new and delete will + not escape from this file. +*/ + +#if CBC_OTHER_SOLVER == 1 +#ifndef CBC_HAS_OSICPX +#error "Configuration did not detect OsiCpx installation." +#else +#include "OsiCpxSolverInterface.hpp" +#endif +#endif + +/* + Hooks for a debugging wrapper for malloc/free. This bit of definition hooks + C++ new / delete and diverts them into the debugging wrapper. +*/ +//#define CLP_DEBUG_MALLOC +#ifdef CLP_DEBUG_MALLOC +/*extern "C" */ void clp_memory(int type); +/*extern "C" */ +void *clp_malloc(int length); +/*extern "C" */ +void clp_free(void *array); +#include +#include +#include +void *operator new(size_t size) throw(std::bad_alloc) +{ + void *p = clp_malloc(size); + return p; +} +void operator delete(void *p) throw() +{ + clp_free(p); +} +#endif // CLP_DEBUG_MALLOC + +#include +#include +#include +#include +#include +#include + +// define TEST_MESSAGE_HANDLER to check works on all messages +// #define TEST_MESSAGE_HANDLER +#ifdef TEST_MESSAGE_HANDLER +// This driver shows how to trap messages - this is just as in unitTest.cpp +// ****** THis code is similar to MyMessageHandler.hpp and MyMessagehandler.cpp +#include "CoinMessageHandler.hpp" + +/** This just adds a model to CoinMessage and a void pointer so + user can trap messages and do useful stuff. + This is used in Clp/Test/unitTest.cpp + + The file pointer is just there as an example of user stuff. + + -- lh 071026 -- An accurate summary. Nothing is actually happening here + except that messages will be prefixed with "==", which serves the purpose + of demonstrating that this message handler is active. The extra parameters + (CbcModel, FILE) are unused. + +*/ +class CbcModel; + +class MyMessageHandler2 : public CoinMessageHandler { + +public: + /**@name Overrides */ + //@{ + virtual int print(); + //@} + /**@name set and get */ + //@{ + /// Model + const CbcModel *model() const; + void setModel(CbcModel *model); + //@} + + /**@name Constructors, destructor */ + //@{ + /** Default constructor. */ + MyMessageHandler2(); + /// Constructor with pointer to model + MyMessageHandler2(CbcModel *model, + FILE *userPointer = NULL); + /** Destructor */ + virtual ~MyMessageHandler2(); + //@} + + /**@name Copy method */ + //@{ + /** The copy constructor. */ + MyMessageHandler2(const MyMessageHandler2 &); + /** The copy constructor from an CoinSimplexMessageHandler. */ + MyMessageHandler2(const CoinMessageHandler &); + + MyMessageHandler2 &operator=(const MyMessageHandler2 &); + /// Clone + virtual CoinMessageHandler *clone() const; + //@} + +protected: + /**@name Data members + The data members are protected to allow access for derived classes. */ + //@{ + /// Pointer back to model + CbcModel *model_; + //@} +}; + +//############################################################################# +// Constructors / Destructor / Assignment +//############################################################################# + +//------------------------------------------------------------------- +// Default Constructor +//------------------------------------------------------------------- +MyMessageHandler2::MyMessageHandler2() + : CoinMessageHandler() + , model_(NULL) +{ +} + +//------------------------------------------------------------------- +// Copy constructor +//------------------------------------------------------------------- +MyMessageHandler2::MyMessageHandler2(const MyMessageHandler2 &rhs) + : CoinMessageHandler(rhs) + , model_(rhs.model_) +{ +} + +MyMessageHandler2::MyMessageHandler2(const CoinMessageHandler &rhs) + : CoinMessageHandler() + , model_(NULL) +{ +} + +// Constructor with pointer to model +MyMessageHandler2::MyMessageHandler2(CbcModel *model, + FILE *userPointer) + : CoinMessageHandler() + , model_(model) +{ +} + +//------------------------------------------------------------------- +// Destructor +//------------------------------------------------------------------- +MyMessageHandler2::~MyMessageHandler2() +{ +} + +//---------------------------------------------------------------- +// Assignment operator +//------------------------------------------------------------------- +MyMessageHandler2 & +MyMessageHandler2::operator=(const MyMessageHandler2 &rhs) +{ + if (this != &rhs) { + CoinMessageHandler::operator=(rhs); + model_ = rhs.model_; + } + return *this; +} +//------------------------------------------------------------------- +// Clone +//------------------------------------------------------------------- +CoinMessageHandler *MyMessageHandler2::clone() const +{ + return new MyMessageHandler2(*this); +} +int MyMessageHandler2::print() +{ + // Just add == + fprintf(fp_, " == "); + fprintf(fp_, "%s\n", messageBuffer_); + return 0; +} +const CbcModel * +MyMessageHandler2::model() const +{ + return model_; +} +void MyMessageHandler2::setModel(CbcModel *model) +{ + model_ = model; +} +#endif /* TEST_MESSAGE_HANDLER */ + +//############################################################################# + +// To use USERCBC or USERCLP change 0 to 1 in defines and add in your fake main program(s) and any other code +//#define USER_HAS_FAKE_CBC +//#define USER_HAS_FAKE_CLP + +#ifdef USER_HAS_FAKE_CBC +#endif +void fakeMain(ClpSimplex &model, OsiSolverInterface & /*osiSolver*/, CbcModel &babSolver) +{ +#ifdef USER_HAS_FAKE_CBC +#else + printf("Dummy user cbc code - model has %d rows and %d columns\n", + model.getNumRows(), model.getNumCols()); + // Reduce printout + babSolver.solver()->setHintParam(OsiDoReducePrint, true, OsiHintTry); + // Do complete search + babSolver.branchAndBound(); +#endif +} + +// Clp stuff +#ifdef USER_HAS_FAKE_CLP +#endif +void fakeMain2(ClpSimplex & /*model*/, + OsiClpSolverInterface &osiSolver, + int /*options*/) +{ +#ifdef USER_HAS_FAKE_CLP +#else + ClpSimplex *lpSolver = osiSolver.getModelPtr(); + printf("Dummy user clp code - model has %d rows and %d columns\n", + lpSolver->numberRows(), lpSolver->numberColumns()); + osiSolver.initialSolve(); +#endif +} +// End any fake main program + +//############################################################################# + +// void CbcClpUnitTest (const CbcModel & saveModel); + +#ifdef CBC_STATISTICS +int osi_crunch = 0; +static int cbc_resolve = 0; +int osi_primal = 0; +int osi_dual = 0; +int osi_hot = 0; +void cbc_resolve_check(const OsiSolverInterface *solver) +{ + cbc_resolve++; + printf("R %d stats %d %d %d\n", + cbc_resolve, solver->getNumRows(), solver->getNumCols(), + solver->getMatrixByCol()->getNumElements()); + if ((cbc_resolve % 1000) == 0) + printf("RR %d resolve crunch %d primal %d dual %d hot %d\n", + cbc_resolve, osi_crunch, osi_primal, osi_dual, osi_hot); +} +#endif + +/* + Somehow with some BLAS we get multithreaded by default + For 99.99% of problems this is not a good idea. + The openblas_set_num_threads(1) seems to work even with other blas + */ +#if CLP_USE_OPENBLAS +extern "C" { +void openblas_set_num_threads(int num_threads); +} +#endif + +static int dummyCallBack(CbcModel * /*model*/, int /*whereFrom*/) +{ + return 0; +} + +int main(int argc, const char *argv[]) +{ + int returnCode = 0; +#ifdef CLP_DEBUG_MALLOC + clp_memory(0); +#endif + { +#ifndef CBC_OTHER_SOLVER + OsiClpSolverInterface solver1; +#if CLP_USE_OPENBLAS + openblas_set_num_threads(CLP_USE_OPENBLAS); +#endif +#elif CBC_OTHER_SOLVER == 1 + OsiCpxSolverInterface solver1; +#endif + CbcModel model(solver1); + + // define TEST_MESSAGE_HANDLER at top of file to check works on all messages +#ifdef TEST_MESSAGE_HANDLER + MyMessageHandler2 messageHandler(&model); + std::cout << "Testing derived message handler" << std::endl; + model.passInMessageHandler(&messageHandler); + OsiClpSolverInterface *clpSolver = dynamic_cast< OsiClpSolverInterface * >(model.solver()); + // Could use different handlers (if different log levels) + clpSolver->passInMessageHandler(&messageHandler); + //clpSolver->getModelPtr()->passInMessageHandler(&messageHandler); +#endif + + CbcSolverUsefulData cbcData; +#ifndef CBC_NO_INTERRUPT + cbcData.useSignalHandler_ = true; +#endif + cbcData.noPrinting_ = false; + // initialize + CbcMain0(model, cbcData); + +#ifdef TEST_MESSAGE_HANDLER + // Set log levels same so can use one message handler + clpSolver->messageHandler()->setLogLevel(1); + model.messageHandler()->setLogLevel(1); + // switch off some printing + void setCbcOrClpPrinting(bool yesNo); + setCbcOrClpPrinting(false); +#endif + + returnCode = CbcMain1(argc, argv, model, dummyCallBack, cbcData); + } + +#ifdef CLP_DEBUG_MALLOC + clp_memory(1); +#endif + + if (returnCode != 777) { + return returnCode; + } else { + return 0; + } +} + +/* + Version 1.00.00 November 16 2005. + This is to stop me (JJF) messing about too much. + Tuning changes should be noted here. + The testing next version may be activated by CBC_NEXT_VERSION + This applies to OsiClp, Clp etc + Version 1.00.01 November 24 2005 + Added several classes for advanced users. This can't affect code (if you don't use it) + Made some tiny changes (for N way branching) which should not change anything. + CbcNWay object class - for N way branching this also allows use of CbcConsequence class. + CbcBranchAllDifferent object class - for branching on general integer variables + to stop them having same value so branches are x >= y+1 and x <= y-1. + Added two new Cgl classes - CglAllDifferent which does column fixing (too slowly) + and CglStored which just has a list of cuts which can be activated. + Modified preprocess option to SOS + Version 1.00.02 December 9 2005 + Added use of CbcStrategy to do clean preprocessing + Added use of referenceSolver for cleaner repetition of Cbc + Version 1.01.00 February 2 2006 + Added first try at Ampl interface + Made dummy program so real main can be called from other programs +*/ +#define COIN_HAS_CBC +#define COIN_HAS_CLP +#include "CbcOrClpParam.cpp" diff --git a/src/Attic/unitTestClp.cpp b/src/Attic/unitTestClp.cpp new file mode 100644 index 000000000..54da40a94 --- /dev/null +++ b/src/Attic/unitTestClp.cpp @@ -0,0 +1,1010 @@ +// Copyright (C) 2002, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#include +#include +#include +#include +#include +#include "CoinTime.hpp" +#include "CoinFileIO.hpp" +#include "CbcModel.hpp" +#include "CbcHeuristic.hpp" +#include "CbcCutGenerator.hpp" +#include "CbcBranchCut.hpp" +#include "CglProbing.hpp" +#include "OsiClpSolverInterface.hpp" +#include "ClpFactorization.hpp" +#include "OsiRowCutDebugger.hpp" +#include "CbcSolver.hpp" +//############################################################################# + +#ifdef NDEBUG +#undef NDEBUG +#endif + +//############################################################################# + +// Display message on stdout and stderr +void testingMessage(const char *const msg) +{ + std::cout << msg; + //cout <> lo; + if (lo>30 || lo <0) { + std::cout << "Unable to convert to integer " << sub.substr(found) + << std::endl; + break; + } + found = foundm+1; + foundc = sub.find(",",found); + int hi; + std::istringstream(sub.substr(found,foundc)) >> hi; + if (hi>30 || hi <0) { + std::cout << "Unable to convert to integer " << sub.substr(found) + << std::endl; + break; + } + if (lo > hi) { + int i = lo; + lo = hi; + hi = i; + } + for (int i=lo;i<=hi;i++) + doThisSet[i] = 1; + } else if (foundm > foundc) { + std::istringstream(sub.substr(found,foundc)) >> level; + if (level>30 || level <0) { + std::cout << "Unable to convert to integer " << sub.substr(found) + << std::endl; + break; + } else { + doThisSet[level]=1; + } + } else { + // end + std::istringstream(sub.substr(found)) >> level; + if (level>30 || level <0) { + std::cout << "Unable to convert to integer " << sub.substr(found) + << std::endl; + break; + } else { + doThisSet[level]=1; + } + } + if (foundc > length) + break; + found = foundc+1; + } + testSwitch = 100000; + std::cout << " testing sets "; + for (int i=0;i<30;i++) { + if (doThisSet[i]) { + std::cout << i << " "; + if (i > 20) + testSwitch = 1000001; // user stuff + hiSet = i; + } + } + std::cout << std::endl; + } + // Do an existence check. + std::string test1 = dirMiplib + "p0033"; + bool doTest = CbcTestMpsFile(test1); + if (!doTest) { + if (testSwitch >=1000000) { + // miplib2010 or user + test1 = dirMiplib + ((testSwitch==1000000) ? "mzzv11" : "usertest1"); + doTest = CbcTestMpsFile(test1); + if (!doTest) { + std::cout + << "Not doing miplib run as can't find mps files." << std::endl + << "Perhaps you're trying to read gzipped (.gz) files without libz?" + << std::endl; + return (0); + } + } + } + // See if we want to use CbcMain0/1 + if (testSwitch==-3) { + oldStyle = false; + testSwitch=-1; + } + if (testSwitch >=1000000) { + oldStyle = false; + } + int dfltPrecision = static_cast< int >(std::cout.precision()); + /* + Set the range of problems to be tested. testSwitch = -2 is special and is + picked up below. + */ + /* + Vectors to hold test problem names and characteristics. +*/ + std::vector< std::string > mpsName; + std::vector< int > nRows; + std::vector< int > nCols; + std::vector< double > objValueC; + std::vector< double > objValue; + std::vector< int > testSet; + std::vector< bool > rowCutDebugger; +/* + A macro to make the vector creation marginally readable. Parameters are + name, rows, columns, integer objective, continuous objective, set ID, + row cut debugger + + To enable the row cut debugger for a given problem, change the last + parameter to true. Don't forget to turn it off before committing changes! +*/ +#define PUSH_MPS(zz_mpsName_zz, \ + zz_nRows_zz, zz_nCols_zz, zz_objValue_zz, zz_objValueC_zz, \ + zz_testSet_zz, zz_rcDbg_zz) \ + mpsName.push_back(zz_mpsName_zz); \ + nRows.push_back(zz_nRows_zz); \ + nCols.push_back(zz_nCols_zz); \ + objValueC.push_back(zz_objValueC_zz); \ + testSet.push_back(zz_testSet_zz); \ + objValue.push_back(zz_objValue_zz); \ + rowCutDebugger.push_back(zz_rcDbg_zz); + /* + Push the miplib problems. Except for -2 (unitTest), push all, even if we're + not going to do all of them. +*/ + if (testSwitch == -2) { + PUSH_MPS("p0033", 16, 33, 3089, 2520.57, 0, false); + PUSH_MPS("p0201", 133, 201, 7615, 6875.0, 0, false); + // PUSH_MPS("flugpl", 18, 18, 1201500, 1167185.7, 0, false); + } else { +/* + Load up the problem vector. Note that the row counts here include the + objective function. +*/ + PUSH_MPS("10teams", 230, 2025, 924, 917, 1, false); + PUSH_MPS("air03", 124, 10757, 340160, 338864.25, 0, false); + PUSH_MPS("air04", 823, 8904, 56137, 55535.436, 2, false); + PUSH_MPS("air05", 426, 7195, 26374, 25877.609, 2, false); + PUSH_MPS("arki001", 1048, 1388, 7580813.0459, 7579599.80787, 7, false); + PUSH_MPS("bell3a", 123, 133, 878430.32, 862578.64, 0, false); + PUSH_MPS("bell5", 91, 104, 8966406.49, 8608417.95, 1, false); + PUSH_MPS("blend2", 274, 353, 7.598985, 6.9156751140, 0, false); + PUSH_MPS("cap6000", 2176, 6000, -2451377, -2451537.325, 1, false); + PUSH_MPS("dano3mip", 3202, 13873, 728.1111, 576.23162474, 7, false); + PUSH_MPS("danoint", 664, 521, 65.666667, 62.637280418, 6, false); + PUSH_MPS("dcmulti", 290, 548, 188182, 183975.5397, 0, false); + PUSH_MPS("dsbmip", 1182, 1886, -305.19817501, -305.19817501, 0, false); + PUSH_MPS("egout", 98, 141, 568.101, 149.589, 0, false); + PUSH_MPS("enigma", 21, 100, 0.0, 0.0, 0, false); + PUSH_MPS("fast0507", 507, 63009, 174, 172.14556668, 5, false); + PUSH_MPS("fiber", 363, 1298, 405935.18000, 156082.51759, 0, false); + PUSH_MPS("fixnet6", 478, 878, 3983, 1200.88, 1, false); + PUSH_MPS("flugpl", 18, 18, 1201500, 1167185.7, 0, false); + PUSH_MPS("gen", 780, 870, 112313, 112130.0, 0, false); + PUSH_MPS("gesa2", 1392, 1224, 25779856.372, 25476489.678, 1, false); + PUSH_MPS("gesa2_o", 1248, 1224, 25779856.372, 25476489.678, 1, false); + PUSH_MPS("gesa3", 1368, 1152, 27991042.648, 27833632.451, 0, false); + PUSH_MPS("gesa3_o", 1224, 1152, 27991042.648, 27833632.451, 0, false); + PUSH_MPS("gt2", 29, 188, 21166.000, 13460.233074, 0, false); + PUSH_MPS("harp2", 112, 2993, -73899798.00, -74353341.502, 6, false); + PUSH_MPS("khb05250", 101, 1350, 106940226, 95919464.0, 0, false); + PUSH_MPS("l152lav", 97, 1989, 4722, 4656.36, 1, false); + PUSH_MPS("lseu", 28, 89, 1120, 834.68, 0, false); + PUSH_MPS("mas74", 13, 151, 11801.18573, 10482.79528, 3, false); + PUSH_MPS("mas76", 12, 151, 40005.05414, 38893.9036, 2, false); + PUSH_MPS("misc03", 96, 160, 3360, 1910., 0, false); + PUSH_MPS("misc06", 820, 1808, 12850.8607, 12841.6, 0, false); + PUSH_MPS("misc07", 212, 260, 2810, 1415.0, 1, false); + PUSH_MPS("mitre", 2054, 10724, 115155, 114740.5184, 1, false); + PUSH_MPS("mkc", 3411, 5325, -563.84601, -611.85, 7, false); + PUSH_MPS("mod008", 6, 319, 307, 290.9, 0, false); + PUSH_MPS("mod010", 146, 2655, 6548, 6532.08, 0, false); + PUSH_MPS("mod011", 4480, 10958, -54558535, -62121982.55, 2, false); + PUSH_MPS("modglob", 291, 422, 20740508, 20430947., 2, false); + PUSH_MPS("noswot", 182, 128, -41, -43.0, 6, false); + PUSH_MPS("nw04", 36, 87482, 16862, 16310.66667, 1, false); + PUSH_MPS("p0033", 16, 33, 3089, 2520.57, 0, false); + PUSH_MPS("p0201", 133, 201, 7615, 6875.0, 0, false); + PUSH_MPS("p0282", 241, 282, 258411, 176867.50, 0, false); + PUSH_MPS("p0548", 176, 548, 8691, 315.29, 0, false); + PUSH_MPS("p2756", 755, 2756, 3124, 2688.75, 0, false); + PUSH_MPS("pk1", 45, 86, 11.0, 0.0, 2, false); + PUSH_MPS("pp08a", 136, 240, 7350.0, 2748.3452381, 1, false); + PUSH_MPS("pp08aCUTS", 246, 240, 7350.0, 5480.6061563, 1, false); + PUSH_MPS("qiu", 1192, 840, -132.873137, -931.638857, 3, false); + PUSH_MPS("qnet1", 503, 1541, 16029.692681, 14274.102667, 0, false); + PUSH_MPS("qnet1_o", 456, 1541, 16029.692681, 12095.571667, 0, false); + PUSH_MPS("rentacar", 6803, 9557, 30356761, 28806137.644, 0, false); + PUSH_MPS("rgn", 24, 180, 82.1999, 48.7999, 0, false); + PUSH_MPS("rout", 291, 556, 1077.56, 981.86428571, 3, false); + PUSH_MPS("set1ch", 492, 712, 54537.75, 32007.73, 5, false); + PUSH_MPS("seymour", 4944, 1372, 423, 403.84647413, 7, false); + PUSH_MPS("stein27", 118, 27, 18, 13.0, 0, false); + PUSH_MPS("stein45", 331, 45, 30, 22.0, 1, false); + PUSH_MPS("swath", 884, 6805, 497.603, 334.4968581, 7, false); + PUSH_MPS("vpm1", 234, 378, 20, 15.4167, 0, false); + PUSH_MPS("vpm2", 234, 378, 13.75, 9.8892645972, 0, false); + /* + The user can add some miplib2010 models to a unit test. + You do this by using something like + -dirmiplib ../miplib2010++level10-12 .... -unittest + This will do ones with difficulty 10, 11 and 12 + other example swould be ..++level11, ++level12,14 etc + Difficulty 10-13 not too bad + 14-17 harder + 18 large may run out of memory when threaded + 20 infeasible problems + 21 - 28 user problems + If the user wants to check that usertest1 has value 12345.0 then + -DCBC_USER_UNIT_TEST1=12345.0 in build + */ + PUSH_MPS("30n20b8", 576, 18380, 302, 1.56641,12,false); + PUSH_MPS("acc-tight5", 3052, 1339, 0, 0,10,false); + PUSH_MPS("aflow40b", 1442, 2728, 1168, 1005.66,12,false); + PUSH_MPS("air04", 823, 8904, 56137, 55535.3,10,false); + PUSH_MPS("app1-2", 53467, 26871, -41, -264.602,12,false); + PUSH_MPS("ash608gpia-3col", 24748, 3651,1.0e50, 2,20,false); // infeasible + PUSH_MPS("bab5", 4964, 21600, -106411.8401, -124658,12,false); + PUSH_MPS("beasleyC3", 1750, 2500, 754, 40.4268,12,false); + PUSH_MPS("biella1", 1203, 7328, 3.06500578e+6, 3.06004e+06,12,false); + PUSH_MPS("bienst2", 576, 505, 54.6, 11.7241,10,false); + PUSH_MPS("binkar10_1", 1026, 2298, 6742.2, 6637.19,10,false); + PUSH_MPS("bley_xl1", 175620, 5831, 190, 140,12,false); + PUSH_MPS("bnatt350", 4923, 3150, 0, 0,12,false); + PUSH_MPS("core2536-691", 2539, 15293, 689, 688.476,11,false); + PUSH_MPS("cov1075", 637, 120, 20, 17.1429,11,false); + PUSH_MPS("csched010", 351, 1758, 408, 332.423,12,false); + PUSH_MPS("danoint", 664, 521, 65.6666667, 62.6373,12,false); + PUSH_MPS("dfn-gwin-UUM", 158, 938, 38752, 27467.3,11,false); + PUSH_MPS("eil33-2", 32, 4516, 934.007916, 811.279,12,false); + PUSH_MPS("eilB101", 100, 2818, 1216.92017, 1075.25,10,false); + PUSH_MPS("enlight13", 169, 338, 71, 0,12,false); + PUSH_MPS("enlight14", 196, 392, 1.0e50, 0,20,false); // infeasible + PUSH_MPS("ex9", 40962, 10404, 81, 81,10,false); // likes heavy probing + PUSH_MPS("glass4", 396, 322, 1.2000126e+09, 8.00002e+08,12,false); + PUSH_MPS("gmu-35-40", 424, 1205, -2.49673337e+06, -2.40694e+06,12,false); + PUSH_MPS("iis-100-0-cov", 3831, 100, 29, 16.6667,12,false); + PUSH_MPS("iis-bupa-cov", 4803, 345, 36, 26.4972,12,false); + PUSH_MPS("iis-pima-cov", 7201, 768, 33, 26.6204,12,false); + PUSH_MPS("lectsched-4-obj", 14163, 7901, 4, 0,10,false); + PUSH_MPS("m100n500k4r1", 100, 500, -25, -25,12,false); + PUSH_MPS("macrophage", 3164, 2260, 374, 0,11,false); + PUSH_MPS("map18", 328818, 164547, -847, -932.783,12,false); + PUSH_MPS("map20", 328818, 164547, -922, -998.836,12,false); + PUSH_MPS("mcsched", 2107, 1747, 211913, 193775,11,false); + PUSH_MPS("mik-250-1-100-1", 151, 251, -66729, -79842.4,10,false); + PUSH_MPS("mine-166-5", 8429, 830, -5.66396e+08, -8.21764e+08,10,false); + PUSH_MPS("mine-90-10", 6270, 900, -7.843023e+08, -8.87165e+08,12,false); + PUSH_MPS("msc98-ip", 15850, 21143, 1.9839497e+07, 1.9521e+07,12,false); + PUSH_MPS("mspp16", 561657, 29280, 363, 341,18,false); + PUSH_MPS("mzzv11", 9499, 10240, -21718, -22945.2,12,false); + PUSH_MPS("n3div36", 4484, 22120, 130800, 114333,11,false); + PUSH_MPS("n3seq24", 6044, 119856, 52200, 52000,12,false); + PUSH_MPS("n4-3", 1236, 3596, 8993, 4080.88,12,false); + PUSH_MPS("neos-1109824", 28979, 1520, 378, 278,11,false); + PUSH_MPS("neos-1337307", 5687, 2840, -202319, -203124,12,false); + PUSH_MPS("neos-1396125", 1494, 1161, 3000.04534, 388.552,11,false); + PUSH_MPS("neos13", 20852, 1827, -95.47481, -126.178,11,false); + PUSH_MPS("neos-1601936", 3131, 4446, 3, 1,12,false); + PUSH_MPS("neos18", 11402, 3312, 16, 7,11,false); + PUSH_MPS("neos-476283", 10015, 11915, 406.363, 406.245,12,false); + PUSH_MPS("neos-686190", 3664, 3660, 6730, 5134.81,10,false); + PUSH_MPS("neos-849702", 1041, 1737, 0, 0,11,false); + PUSH_MPS("neos-916792", 1909, 1474, 31.870398, 26.2036,12,false); + PUSH_MPS("neos-934278", 11495, 23123, 260, 259.5,12,false); + PUSH_MPS("net12", 14021, 14115, 214, 17.2495,11,false); + PUSH_MPS("netdiversion", 119589, 129180, 242, 230.8,12,false); + PUSH_MPS("newdano", 576, 505, 65.666667, 11.7241,12,false); + PUSH_MPS("noswot", 182, 128, -41, -43,12,false); + PUSH_MPS("ns1208400", 4289, 2883, 2, 0,12,false); + PUSH_MPS("ns1688347", 4191, 2685, 27, 2,12,false); + PUSH_MPS("ns1758913", 624166, 17956, -1454.67, -1501.18,12,false); + PUSH_MPS("ns1766074", 182, 100, 1.0e50, 5833.8,20,false); // infeasible + PUSH_MPS("ns1830653", 2932, 1629, 20622, 6153,12,false); + PUSH_MPS("opm2-z7-s2", 31798, 2023, -10280, -12879.7,11,false); + PUSH_MPS("pg5_34", 225, 2600, -14339.35, -16646.6,11,false); + PUSH_MPS("pigeon-10", 931, 490, -9000, -10000,11,false); + PUSH_MPS("pw-myciel4", 8164, 1059, 10, 0,11,false); + PUSH_MPS("qiu", 1192, 840, -132.873, -931.639,10,false); + PUSH_MPS("rail507", 509, 63019, 174, 172.146,11,false); + PUSH_MPS("ran16x16", 288, 512, 3823, 3116.43,11,false); + PUSH_MPS("reblock67", 2523, 670, -3.4630648e+07, -3.93399e+07,12,false); + PUSH_MPS("rmatr100-p10", 7260, 7359, 423, 360.593,10,false); + PUSH_MPS("rmatr100-p5", 8685, 8784, 976, 762.04,10,false); + PUSH_MPS("rmine6", 7078, 1096, -457.186, -462.306,11,false); + PUSH_MPS("rocII-4-11", 21738, 9234, -6.65276, -11.9372,12,false); + PUSH_MPS("rococoC10-001000", 1293, 3117, 11460, 7515.27,11,false); + PUSH_MPS("roll3000", 2295, 1166, 12890, 11097.1,10,false); + PUSH_MPS("satellites1-25", 5996, 9013, -5, -20,11,false); + PUSH_MPS("sp98ic", 825, 10894, 4.49145e+08, 4.44278e+08,12,false); + PUSH_MPS("sp98ir", 1531, 1680, 2.19677e+08, 2.16663e+08,10,false); + PUSH_MPS("tanglegram1", 68342, 34759, 5182, 0,12,false); + PUSH_MPS("tanglegram2", 8980, 4714, 443, 0,10,false); + PUSH_MPS("timtab1", 171, 397, 764772, 28694,12,false); + PUSH_MPS("triptim1", 15706, 30055, 22.8681, 22.8681,11,false); + PUSH_MPS("unitcal_7", 48939, 25755, 1.96356e+07, 1.93876e+07,12,false); + PUSH_MPS("vpphard", 47280, 51471, 5, -2.94558e-09,12,false); + PUSH_MPS("zib54-UUE", 1809, 5150, 1.0334e+07, 3.87586e+06,12,false); +#ifndef CBC_USER_UNIT_TEST1 +#define CBC_USER_UNIT_TEST1 -1.0e50 +#endif + PUSH_MPS("usertest1", 0, 0, CBC_USER_UNIT_TEST1, 0, 21,false); +#ifndef CBC_USER_UNIT_TEST2 +#define CBC_USER_UNIT_TEST2 -1.0e50 +#endif + PUSH_MPS("usertest2", 0, 0, CBC_USER_UNIT_TEST2, 0, 22,false); +#ifndef CBC_USER_UNIT_TEST3 +#define CBC_USER_UNIT_TEST3 -1.0e50 +#endif + PUSH_MPS("usertest3", 0, 0, CBC_USER_UNIT_TEST3, 0, 23,false); +#ifndef CBC_USER_UNIT_TEST4 +#define CBC_USER_UNIT_TEST4 -1.0e50 +#endif + PUSH_MPS("usertest4", 0, 0, CBC_USER_UNIT_TEST4, 0, 24,false); +#ifndef CBC_USER_UNIT_TEST5 +#define CBC_USER_UNIT_TEST5 -1.0e50 +#endif + PUSH_MPS("usertest5", 0, 0, CBC_USER_UNIT_TEST5, 0, 25,false); +#ifndef CBC_USER_UNIT_TEST6 +#define CBC_USER_UNIT_TEST6 -1.0e50 +#endif + PUSH_MPS("usertest6", 0, 0, CBC_USER_UNIT_TEST6, 0, 26,false); +#ifndef CBC_USER_UNIT_TEST7 +#define CBC_USER_UNIT_TEST7 -1.0e50 +#endif + PUSH_MPS("usertest7", 0, 0, CBC_USER_UNIT_TEST7, 0, 27,false); +#ifndef CBC_USER_UNIT_TEST8 +#define CBC_USER_UNIT_TEST8 -1.0e50 +#endif + PUSH_MPS("usertest8", 0, 0, CBC_USER_UNIT_TEST8, 0, 28,false); + } +#undef PUSH_MPS + + /* + Normally the problems are executed in order. Define RANDOM_ORDER below to + randomize. + + #define RANDOM_ORDER +*/ + int which[200]; + int nLoop = static_cast< int >(mpsName.size()); + assert(nLoop <= 200); + for (int i = 0; i < nLoop; i++) + which[i] = i; + +#ifdef RANDOM_ORDER + unsigned int iTime = static_cast< unsigned int >(CoinGetTimeOfDay() - 1.256e9); + std::cout << "Time (seed) " << iTime << "." << std::endl; + double sort[100]; + CoinDrand48(true, iTime); + for (int i = 0; i < nLoop; i++) + sort[i] = CoinDrand48(); + CoinSort_2(sort, sort + nLoop, which); +#endif + + int problemCnt = 0; + for (m = 0; m < mpsName.size(); m++) { + int setID = testSet[m]; + if (doThisSet[setID]) + problemCnt++; + } + + int numberFailures = 0; + int numberAttempts = 0; + int numProbSolved = 0; + double timeTaken = 0.0; + +//#define CLP_FACTORIZATION_INSTRUMENT +#ifdef CLP_FACTORIZATION_INSTRUMENT + double timeTakenFac = 0.0; +#endif + /* + Open the main loop to step through the MPS problems. + */ + for (unsigned int mw = 0; mw < mpsName.size(); mw++) { + m = which[mw]; + int setID = testSet[m]; + // Skip if problem is not in specified problem set(s) + if (!doThisSet[setID]) + continue; + + numberAttempts++; + std::cout << " processing mps file: " << mpsName[m] + << " (" << numberAttempts << " out of " + << problemCnt << ")" << std::endl; + /* + Stage 1: Read the MPS and make sure the size of the constraint matrix + is correct. +*/ + CbcModel *model = NULL; + std::string fn = dirMiplib + mpsName[m]; + if (!CbcTestMpsFile(fn)) { + std::cout << "ERROR: Cannot find MPS file " << fn << "." << std::endl; + continue; + } + // Careful! We're initialising for the benefit of other code. + CoinDrand48(true, 123456); + double startTime = CoinCpuTime() + CoinCpuTimeJustChildren(); + if (oldStyle) { + model = new CbcModel(saveModel); + model->solver()->readMps(fn.c_str(), ""); + } else { + OsiClpSolverInterface solver1; + const char * newArgv[200]; + char replace[100]; + int newArgc = 2; + newArgv[0] = "unitTestCbc"; + newArgv[1] = fn.c_str(); + for (int i = 3;i < argc-1; i++) { + if (!strstr(argv[i],"++")) { + if (testSwitch >=1000000) { + // take out dextra3 + if (strstr(argv[i],"dextra3")) { + i++; + continue; + } + } + newArgv[newArgc++] = argv[i]; + } else { + int n = strstr(argv[i],"++")-argv[i]; + strncpy(replace,argv[i],n); + const char * mipname = mpsName[m].c_str(); + int n1 = n; + for (int j=0;jgetNumRows() != nRows[m] || + model->getNumCols() != nCols[m]) && model->getNumRows()) + printf("WARNING - model has %d row, %d columns - expected %d, %d\n", + model->getNumRows(),model->getNumCols(), + nRows[m],nCols[m]); + + if (oldStyle) { + + // Higher limits for the serious problems. + int testMaximumNodes = 200000; + if (hiSet > 1) + testMaximumNodes = 20000000; + if (model->getMaximumNodes() > testMaximumNodes) { + model->setMaximumNodes(testMaximumNodes); + } + /* + Stage 2: Call solver to solve the problem. + */ + +#ifdef CLP_FACTORIZATION_INSTRUMENT + extern double factorization_instrument(int type); + double facTime1 = factorization_instrument(0); + std::cout + << "Factorization - initial solve " << facTime1 << " seconds." + << std::endl; + timeTakenFac += facTime1; +#endif + + + // Setup specific to clp + OsiClpSolverInterface *siClp = dynamic_cast< OsiClpSolverInterface * >(model->solver()); + ClpSimplex *modelC = NULL; + if (siClp) { + modelC = siClp->getModelPtr(); + ClpMatrixBase *matrix = modelC->clpMatrix(); + ClpPackedMatrix *clpMatrix = dynamic_cast< ClpPackedMatrix * >(matrix); + if (stuff && stuff[9] && clpMatrix) { + // vector matrix! + clpMatrix->makeSpecialColumnCopy(); + } + +#ifdef JJF_ZERO + if (clpMatrix) { + int numberRows = clpMatrix->getNumRows(); + int numberColumns = clpMatrix->getNumCols(); + double *elements = clpMatrix->getMutableElements(); + const int *row = clpMatrix->getIndices(); + const CoinBigIndex *columnStart = clpMatrix->getVectorStarts(); + const int *columnLength = clpMatrix->getVectorLengths(); + double *smallest = new double[numberRows]; + double *largest = new double[numberRows]; + char *flag = new char[numberRows]; + CoinZeroN(flag, numberRows); + for (int i = 0; i < numberRows; i++) { + smallest[i] = COIN_DBL_MAX; + largest[i] = 0.0; + } + for (int iColumn = 0; iColumn < numberColumns; iColumn++) { + bool isInteger = modelC->isInteger(iColumn); + CoinBigIndex j; + for (j = columnStart[iColumn]; + j < columnStart[iColumn] + columnLength[iColumn]; j++) { + int iRow = row[j]; + double value = fabs(elements[j]); + if (!isInteger) + flag[iRow] = 1; + smallest[iRow] = CoinMin(smallest[iRow], value); + largest[iRow] = CoinMax(largest[iRow], value); + } + } + double *rowLower = modelC->rowLower(); + double *rowUpper = modelC->rowUpper(); + bool changed = false; + for (int i = 0; i < numberRows; i++) { + if (flag[i] && smallest[i] > 10.0 && false) { + smallest[i] = 1.0 / smallest[i]; + if (rowLower[i] > -1.0e20) + rowLower[i] *= smallest[i]; + if (rowUpper[i] < 1.0e20) + rowUpper[i] *= smallest[i]; + changed = true; + } else { + smallest[i] = 0.0; + } + } + if (changed) { + printf("SCALED\n"); + for (int iColumn = 0; iColumn < numberColumns; iColumn++) { + CoinBigIndex j; + for (j = columnStart[iColumn]; + j < columnStart[iColumn] + columnLength[iColumn]; j++) { + int iRow = row[j]; + if (smallest[iRow]) + elements[j] *= smallest[iRow]; + } + } + } + delete[] smallest; + delete[] largest; + delete[] flag; + } +#endif // JJF_ZERO + + model->checkModel(); + OsiClpSolverInterface *clpSolver = dynamic_cast< OsiClpSolverInterface * >(model); + if (clpSolver) { + ClpSimplex *clps = clpSolver->getModelPtr(); + if (clps) + clps->setPerturbation(50); + } + + modelC->tightenPrimalBounds(0.0, 0, true); + model->initialSolve(); + if (modelC->dualBound() == 1.0e10) { + // user did not set - so modify + // get largest scaled away from bound + ClpSimplex temp = *modelC; + temp.dual(0, 7); + double largestScaled = 1.0e-12; + double largest = 1.0e-12; + int numberRows = temp.numberRows(); + const double *rowPrimal = temp.primalRowSolution(); + const double *rowLower = temp.rowLower(); + const double *rowUpper = temp.rowUpper(); + const double *rowScale = temp.rowScale(); + int iRow; + for (iRow = 0; iRow < numberRows; iRow++) { + double value = rowPrimal[iRow]; + double above = value - rowLower[iRow]; + double below = rowUpper[iRow] - value; + if (above < 1.0e12) { + largest = CoinMax(largest, above); + } + if (below < 1.0e12) { + largest = CoinMax(largest, below); + } + if (rowScale) { + double multiplier = rowScale[iRow]; + above *= multiplier; + below *= multiplier; + } + if (above < 1.0e12) { + largestScaled = CoinMax(largestScaled, above); + } + if (below < 1.0e12) { + largestScaled = CoinMax(largestScaled, below); + } + } + + int numberColumns = temp.numberColumns(); + const double *columnPrimal = temp.primalColumnSolution(); + const double *columnLower = temp.columnLower(); + const double *columnUpper = temp.columnUpper(); + const double *columnScale = temp.columnScale(); + int iColumn; + for (iColumn = 0; iColumn < numberColumns; iColumn++) { + double value = columnPrimal[iColumn]; + double above = value - columnLower[iColumn]; + double below = columnUpper[iColumn] - value; + if (above < 1.0e12) { + largest = CoinMax(largest, above); + } + if (below < 1.0e12) { + largest = CoinMax(largest, below); + } + if (columnScale) { + double multiplier = 1.0 / columnScale[iColumn]; + above *= multiplier; + below *= multiplier; + } + if (above < 1.0e12) { + largestScaled = CoinMax(largestScaled, above); + } + if (below < 1.0e12) { + largestScaled = CoinMax(largestScaled, below); + } + } + std::cout << "Largest (scaled) away from bound " << largestScaled + << " unscaled " << largest << std::endl; +#ifdef JJF_ZERO + modelC->setDualBound(CoinMax(1.0001e8, + CoinMin(1000.0 * largestScaled, 1.00001e10))); +#else + modelC->setDualBound(CoinMax(1.0001e9, + CoinMin(1000.0 * largestScaled, 1.0001e10))); +#endif + } + } // end clp-specific setup + /* + Cut passes: For small models (n < 500) always do 100 passes, if possible + (-100). For larger models, use minimum drop to stop (100, 20). + */ + model->setMinimumDrop(CoinMin(5.0e-2, + fabs(model->getMinimizationObjValue()) * 1.0e-3 + 1.0e-4)); + if (CoinAbs(model->getMaximumCutPassesAtRoot()) <= 100) { + if (model->getNumCols() < 500) { + model->setMaximumCutPassesAtRoot(-100); + } else if (model->getNumCols() < 5000) { + model->setMaximumCutPassesAtRoot(100); + } else { + model->setMaximumCutPassesAtRoot(20); + } + } + // If defaults then increase trust for small models + if (model->numberStrong() == 5 && model->numberBeforeTrust() == 10) { + int numberColumns = model->getNumCols(); + if (numberColumns <= 50) { + model->setNumberBeforeTrust(1000); + } else if (numberColumns <= 100) { + model->setNumberBeforeTrust(100); + } else if (numberColumns <= 300) { + model->setNumberBeforeTrust(50); + } + } + //if (model->getNumCols()>=500) { + // switch off Clp stuff + //model->setFastNodeDepth(-1); + //} + /* + Activate the row cut debugger, if requested. + */ + if (rowCutDebugger[m] == true) { + std::string probName; + model->solver()->getStrParam(OsiProbName, probName); + model->solver()->activateRowCutDebugger(probName.c_str()); + if (model->solver()->getRowCutDebugger()) + std::cout << "Row cut debugger activated for "; + else + std::cout << "Failed to activate row cut debugger for "; + std::cout << mpsName[m] << "." << std::endl; + } + setCutAndHeuristicOptions(*model); + /* + More clp-specific setup. + */ + if (siClp) { +#ifdef CLP_MULTIPLE_FACTORIZATIONS + if (!modelC->factorization()->isDenseOrSmall()) { + int denseCode = stuff ? static_cast< int >(stuff[4]) : -1; + int smallCode = stuff ? static_cast< int >(stuff[10]) : -1; + if (stuff && stuff[8] >= 1) { + if (denseCode < 0) + denseCode = 40; + if (smallCode < 0) + smallCode = 40; + } + if (denseCode > 0) + modelC->factorization()->setGoDenseThreshold(denseCode); + if (smallCode > 0) + modelC->factorization()->setGoSmallThreshold(smallCode); + if (denseCode >= modelC->numberRows()) { + //printf("problem going dense\n"); + //modelC->factorization()->goDenseOrSmall(modelC->numberRows()); + } + } +#endif + if (stuff && stuff[8] >= 1) { + printf("Fast node size Columns %d rows %d - depth %d\n", + modelC->numberColumns(), modelC->numberRows(), + model->fastNodeDepth()); + if (modelC->numberColumns() + modelC->numberRows() <= 10000 && model->fastNodeDepth() == -1) + model->setFastNodeDepth(-10 /*-9*/); + } + } +#ifdef CONFLICT_CUTS + { + model->setCutoffAsConstraint(true); // very slow on bell5 ?? + int moreOptions = model->moreSpecialOptions(); + model->setMoreSpecialOptions(moreOptions | 4194304); + } +#endif + /* + Finally, the actual call to solve the MIP with branch-and-cut. + */ + model->setDblParam( CbcModel::CbcAllowableGap, 0.0001 ); + model->branchAndBound(); + +#ifdef CLP_FACTORIZATION_INSTRUMENT + double facTime = factorization_instrument(0); + std::cout << "Factorization " << facTime << " seconds." << std::endl, + timeTakenFac += facTime; +#endif + } + /* + Stage 3: Do the statistics and check the answer. + */ + double timeOfSolution = CoinCpuTime() + CoinCpuTimeJustChildren() - startTime; + std::cout + << "Cuts at root node changed objective from " + << model->getContinuousObjective() << " to " + << model->rootObjectiveAfterCuts() << std::endl; + int numberGenerators = model->numberCutGenerators(); + for (int iGenerator = 0; iGenerator < numberGenerators; iGenerator++) { + CbcCutGenerator *generator = model->cutGenerator(iGenerator); +#ifdef CLIQUE_ANALYSIS +#ifndef CLP_INVESTIGATE + CglImplication *implication = dynamic_cast< CglImplication * >(generator->generator()); + if (implication) + continue; +#endif +#endif + std::cout + << generator->cutGeneratorName() << " was tried " + << generator->numberTimesEntered() << " times and created " + << generator->numberCutsInTotal() << " cuts of which " + << generator->numberCutsActive() + << " were active after adding rounds of cuts"; + if (generator->timing()) + std::cout << " (" << generator->timeInCutGenerator() << " seconds)"; + std::cout << "." << std::endl; + } + std::cout + << model->getNumberHeuristicSolutions() + << " solutions found by heuristics." << std::endl; + int numberHeuristics = model->numberHeuristics(); + for (int iHeuristic = 0; iHeuristic < numberHeuristics; iHeuristic++) { + CbcHeuristic *heuristic = model->heuristic(iHeuristic); + if (heuristic->numRuns()) { + std::cout + << heuristic->heuristicName() << " was tried " + << heuristic->numRuns() << " times out of " + << heuristic->numCouldRun() << " and created " + << heuristic->numberSolutionsFound() << " solutions." << std::endl; + } + } + /* + Check for the correct answer. +*/ + double objActual = model->getObjValue(); + double objExpect = objValue[m]; + double tolerance = CoinMin(fabs(objActual), fabs(objExpect)); + tolerance = CoinMax(1.0e-4, 1.0e-5 * tolerance); + if (!model->status()) { + + //CoinRelFltEq eq(1.0e-3) ; + + std::cout + << "cbc_clp (" << mpsName[m] << ") " + << std::setprecision(10) << objActual; + if (fabs(objActual - objExpect) < tolerance) { + std::cout << std::setprecision(dfltPrecision) << "; okay"; + numProbSolved++; + } else if (objExpect!=-1.0e50) { + std::cout + << " != " << objExpect << std::setprecision(dfltPrecision) + << "; error = " << fabs(objExpect - objActual); + numberFailures++; + //#ifdef COIN_DEVELOP + //abort(); + //#endif + } else { + std::cout + << " - user model "; + } + } else { + std::cout + << "cbc_clp (" << mpsName[m] << ") status not optimal; " + << "assuming too many nodes"; + if (fabs(objActual - objExpect) < tolerance) { + std::cout + << " (on the bright side solution is correct) "; + } + } + timeTaken += timeOfSolution; + std::cout + << " -- (" << model->getNodeCount() << " n / " + << model->getIterationCount() << " i / " + << timeOfSolution << " s) (subtotal " << timeTaken << " seconds)" + << std::endl << std::flush; + delete model; + } + /* + End main loop on MPS problems. Print a summary and calculate the return + value. +*/ + int returnCode = 0; + std::cout + << "cbc_clp solved " << numProbSolved << " out of " << numberAttempts; + int numberOnNodes = numberAttempts - numProbSolved - numberFailures; + if (numberFailures || numberOnNodes) { + if (numberOnNodes) { + std::cout << " (" << numberOnNodes << " stopped on nodes)"; + returnCode = numberOnNodes; + } + if (numberFailures) { + std::cout << " (" << numberFailures << " gave bad answer!)"; + returnCode += 100 * numberFailures; + } + } + std::cout + << " and took " << timeTaken << " seconds." << std::endl; + + if (testSwitch == -2) { + if (numberFailures || numberOnNodes) { + std::cout << "****** Unit Test failed." << std::endl; + std::cerr << "****** Unit Test failed." << std::endl; + } else { + std::cerr << "****** Unit Test succeeded." << std::endl; + } + } +#ifdef CLP_FACTORIZATION_INSTRUMENT + std::cout + << "Total factorization time " << timeTakenFac << "seconds." << std::endl; +#endif + return (returnCode); +} diff --git a/src/CbcGenBaB.cpp b/src/CbcBab.cpp similarity index 60% rename from src/CbcGenBaB.cpp rename to src/CbcBab.cpp index a3130694a..7b0b0d889 100644 --- a/src/CbcGenBaB.cpp +++ b/src/CbcBab.cpp @@ -13,19 +13,19 @@ #include "CoinTime.hpp" -#include "OsiSolverInterface.hpp" #include "OsiChooseVariable.hpp" +#include "OsiSolverInterface.hpp" #include "CglPreProcess.hpp" -#include "CbcModel.hpp" -#include "CbcCutGenerator.hpp" #include "CbcBranchActual.hpp" +#include "CbcCutGenerator.hpp" +#include "CbcModel.hpp" #include "CbcStrategy.hpp" -#include "CbcGenCtlBlk.hpp" -#include "CbcGenParam.hpp" -#include "CbcGenCbcParam.hpp" +#include "CbcParam.hpp" +#include "CbcParamUtils.hpp" +#include "CbcParameters.hpp" #define CBC_TRACK_SOLVERS 1 // #define COIN_CBC_VERBOSITY 5 @@ -36,7 +36,6 @@ namespace { - /* A hack to fix variables based on reduced cost prior to branch-and-cut. Note that we're *not* looking at the integrality gap here. Given the reduced costs @@ -60,8 +59,8 @@ void reducedCostHack(OsiSolverInterface *osi, double threshold) const double *dj = osi->getReducedCost(); /* First task: scan the columns looking for variables that are at their - favourable bound and have reduced cost that exceeds the threshold. Remember - the column index and the value. + favourable bound and have reduced cost that exceeds the threshold. + Remember the column index and the value. */ double *chgBnds = new double[numCols]; int *chgCols = new int[numCols]; @@ -83,11 +82,11 @@ void reducedCostHack(OsiSolverInterface *osi, double threshold) } /* Second task: For variables that we want to fix, we need to: - * Prepare an array with the new lower and upper bounds for variables that - will be fixed. setColSetBounds requires an array with column indices and - an array with new values for both bounds. - * Set the correct value in a copy of the current solution. setColSolution - requires a complete solution. + * Prepare an array with the new lower and upper bounds for variables + that will be fixed. setColSetBounds requires an array with column indices + and an array with new values for both bounds. + * Set the correct value in a copy of the current solution. + setColSolution requires a complete solution. */ if (numFixed > 0) { double *newSoln = CoinCopyOfArray(solution, numCols); @@ -103,9 +102,8 @@ void reducedCostHack(OsiSolverInterface *osi, double threshold) osi->setColSetBounds(&chgCols[0], &chgCols[numFixed], &newBnds[0]); osi->setColSolution(&newSoln[0]); - std::cout - << "Reduced cost fixing prior to B&C: " << numFixed - << " columns fixed." << std::endl; + std::cout << "Reduced cost fixing prior to B&C: " << numFixed + << " columns fixed." << std::endl; delete[] newSoln; delete[] newBnds; @@ -133,28 +131,23 @@ bool solveRelaxation(CbcModel *model) if (!(osi->isProvenOptimal())) { bool reason = false; if (osi->isProvenPrimalInfeasible()) { - std::cout - << "Continuous relaxation is primal infeasible." << std::endl; + std::cout << "Continuous relaxation is primal infeasible." << std::endl; reason = true; } if (osi->isProvenDualInfeasible()) { - std::cout - << "Continuous relaxation is dual infeasible." << std::endl; + std::cout << "Continuous relaxation is dual infeasible." << std::endl; reason = true; } if (osi->isIterationLimitReached()) { - std::cout - << "Continuous solver reached iteration limit." << std::endl; + std::cout << "Continuous solver reached iteration limit." << std::endl; reason = true; } if (osi->isAbandoned()) { - std::cout - << "Continuous solver abandoned the problem." << std::endl; + std::cout << "Continuous solver abandoned the problem." << std::endl; reason = true; } if (reason == false) { - std::cout - << "Continuous solver failed for unknown reason." << std::endl; + std::cout << "Continuous solver failed for unknown reason." << std::endl; } return (false); } @@ -166,7 +159,7 @@ bool solveRelaxation(CbcModel *model) Helper routine to establish a priority vector. */ -void setupPriorities(CbcModel *model, CbcGenCtlBlk::BPControl how) +void setupPriorities(CbcModel *model, CbcParameters::BPMode how) { int numCols = model->getNumCols(); @@ -181,14 +174,13 @@ void setupPriorities(CbcModel *model, CbcGenCtlBlk::BPControl how) for (iColumn = 0; iColumn < numCols; iColumn++) { if (model->isInteger(iColumn)) { sort[n] = n; - if (how == CbcGenCtlBlk::BPCost) { + if (how == CbcParameters::BPCost) { dsort[n++] = -objective[iColumn]; - } else if (how == CbcGenCtlBlk::BPOrder) { + } else if (how == CbcParameters::BPOrder) { dsort[n++] = iColumn; } else { - std::cerr - << "setupPriorities: Unrecognised priority specification." - << std::endl; + std::cerr << "setupPriorities: Unrecognised priority specification." + << std::endl; priorityOK = false; } } @@ -224,41 +216,41 @@ void setupPriorities(CbcModel *model, CbcGenCtlBlk::BPControl how) enabled. */ -void installHeuristics(CbcGenCtlBlk *ctlBlk, CbcModel *model) +void installHeuristics(CbcParameters *parameters, CbcModel *model) { - CbcGenCtlBlk::CGControl action; + CbcParameters::HeurMode mode; CbcHeuristic *gen; CbcTreeLocal *localTree; /* - FPump goes first because it only works before there's a solution. + FeasPump goes first because it only works before there's a solution. */ - action = ctlBlk->getFPump(gen, model); - if (action != CbcGenCtlBlk::CGOff) { - model->addHeuristic(gen, "FPump"); + mode = parameters->getFeasPump(gen, model); + if (mode != CbcParameters::HeurOff) { + model->addHeuristic(gen, "FeasPump"); } - action = ctlBlk->getRounding(gen, model); - if (action != CbcGenCtlBlk::CGOff) { + mode = parameters->getRounding(gen, model); + if (mode != CbcParameters::HeurOff) { model->addHeuristic(gen, "Rounding"); } - action = ctlBlk->getCombine(gen, model); - if (action != CbcGenCtlBlk::CGOff) { + mode = parameters->getCombine(gen, model); + if (mode != CbcParameters::HeurOff) { model->addHeuristic(gen, "Combine"); } - action = ctlBlk->getGreedyCover(gen, model); - if (action != CbcGenCtlBlk::CGOff) { + mode = parameters->getGreedyCover(gen, model); + if (mode != CbcParameters::HeurOff) { model->addHeuristic(gen, "GCov"); } - action = ctlBlk->getGreedyEquality(gen, model); - if (action != CbcGenCtlBlk::CGOff) { + mode = parameters->getGreedyEquality(gen, model); + if (mode != CbcParameters::HeurOff) { model->addHeuristic(gen, "GEq"); } /* - This one's a bit different. We acquire the local tree and install it in the - model. + This one's a bit different. We acquire the local tree and install it in + the model. */ - action = ctlBlk->getTreeLocal(localTree, model); - if (action != CbcGenCtlBlk::CGOff) { + mode = parameters->getLocalTree(localTree, model); + if (mode != CbcParameters::HeurOff) { model->passInTreeHandler(*localTree); } @@ -272,83 +264,85 @@ void installHeuristics(CbcGenCtlBlk *ctlBlk, CbcModel *model) figure out stored cuts. */ -void installCutGenerators(CbcGenCtlBlk *ctlBlk, CbcModel *model) +void installCutGenerators(CbcParameters *parameters, CbcModel *model) { int switches[20]; int genCnt = 0; - CbcGenCtlBlk::CGControl action; + CbcParameters::CGMode mode; CglCutGenerator *gen; /* The magic numbers for the howOften parameter that determines how often the generator is invoked. -100 is disabled, -99 is root only, -98 will stay - active only so long as it generates cuts that improve the objective. A value - 1 <= k <= 90 means the generator will be called every k nodes. If k is - negative, then it can be switched off if unproductive. If k is positive, + active only so long as it generates cuts that improve the objective. A + value 1 <= k <= 90 means the generator will be called every k nodes. If k + is negative, then it can be switched off if unproductive. If k is positive, it'll carry on regardless. */ - int howOften[CbcGenCtlBlk::CGMarker]; - howOften[CbcGenCtlBlk::CGOff] = -100; - howOften[CbcGenCtlBlk::CGOn] = -1; - howOften[CbcGenCtlBlk::CGRoot] = -99; - howOften[CbcGenCtlBlk::CGIfMove] = -98; - howOften[CbcGenCtlBlk::CGForceOn] = 1; - howOften[CbcGenCtlBlk::CGForceBut] = 1; + + int howOften[CbcParameters::CGEndMarker]; + howOften[CbcParameters::CGOff] = -100; + howOften[CbcParameters::CGOn] = -1; + howOften[CbcParameters::CGRoot] = -99; + howOften[CbcParameters::CGIfMove] = -98; + howOften[CbcParameters::CGForceOn] = 1; + howOften[CbcParameters::CGForceOnBut] = 1; /* - A negative value for rowCuts means that the specified actions happen only at + A negative value for rowCuts means that the specified modes happen only at the root. */ - action = ctlBlk->getProbing(gen); - if (action != CbcGenCtlBlk::CGOff) { - if (action == CbcGenCtlBlk::CGForceBut) { - CglProbing *probingGen = dynamic_cast< CglProbing * >(gen); + mode = parameters->getProbing(gen); + if (mode != CbcParameters::CGOff) { + if (mode == CbcParameters::CGForceOnBut) { + CglProbing *probingGen = dynamic_cast(gen); probingGen->setRowCuts(-3); } - model->addCutGenerator(gen, howOften[action], "Probing"); + model->addCutGenerator(gen, howOften[mode], "Probing"); switches[genCnt++] = 0; } - action = ctlBlk->getGomory(gen); - if (action != CbcGenCtlBlk::CGOff) { - model->addCutGenerator(gen, howOften[action], "Gomory"); + mode = parameters->getGomory(gen); + if (mode != CbcParameters::CGOff) { + model->addCutGenerator(gen, howOften[mode], "Gomory"); switches[genCnt++] = -1; } - action = ctlBlk->getKnapsack(gen); - if (action != CbcGenCtlBlk::CGOff) { - model->addCutGenerator(gen, howOften[action], "Knapsack"); + mode = parameters->getKnapsack(gen); + if (mode != CbcParameters::CGOff) { + model->addCutGenerator(gen, howOften[mode], "Knapsack"); switches[genCnt++] = 0; } - action = ctlBlk->getRedSplit(gen); - if (action != CbcGenCtlBlk::CGOff) { - model->addCutGenerator(gen, howOften[action], "RedSplit"); + mode = parameters->getRedSplit(gen); + if (mode != CbcParameters::CGOff) { + model->addCutGenerator(gen, howOften[mode], "RedSplit"); switches[genCnt++] = 1; } - action = ctlBlk->getClique(gen); - if (action != CbcGenCtlBlk::CGOff) { - model->addCutGenerator(gen, howOften[action], "Clique"); + mode = parameters->getClique(gen); + if (mode != CbcParameters::CGOff) { + model->addCutGenerator(gen, howOften[mode], "Clique"); switches[genCnt++] = 0; } - action = ctlBlk->getMir(gen); - if (action != CbcGenCtlBlk::CGOff) { - model->addCutGenerator(gen, howOften[action], "MIR2"); + mode = parameters->getMir(gen); + if (mode != CbcParameters::CGOff) { + model->addCutGenerator(gen, howOften[mode], "MIR2"); switches[genCnt++] = -1; } - action = ctlBlk->getFlow(gen); - if (action != CbcGenCtlBlk::CGOff) { - model->addCutGenerator(gen, howOften[action], "Flow"); + mode = parameters->getFlow(gen); + if (mode != CbcParameters::CGOff) { + model->addCutGenerator(gen, howOften[mode], "Flow"); switches[genCnt++] = 1; } - action = ctlBlk->getTwomir(gen); - if (action != CbcGenCtlBlk::CGOff) { - model->addCutGenerator(gen, howOften[action], "2-MIR"); + mode = parameters->getTwomir(gen); + if (mode != CbcParameters::CGOff) { + model->addCutGenerator(gen, howOften[mode], "2-MIR"); switches[genCnt++] = 1; } /* - Set control parameters on cut generators. cutDepth says `use this generator - when (depth in tree) mod cutDepth == 0'. setSwitchOffIfLessThan says `switch - this generator off if the number of cuts at the root is less than the given - value'. Sort of. I need to document the magic numbers for howOften , etc. + Set control parameters on cut generators. cutDepth says `use this + generator when (depth in tree) mod cutDepth == 0'. setSwitchOffIfLessThan + says `switch this generator off if the number of cuts at the root is less + than the given value'. Sort of. I need to document the magic numbers for + howOften , etc. */ genCnt = model->numberCutGenerators(); int iGen; @@ -359,17 +353,18 @@ void installCutGenerators(CbcGenCtlBlk *ctlBlk, CbcModel *model) generator->setSwitchOffIfLessThan(switches[iGen]); } generator->setTiming(true); - int cutDepth = ctlBlk->getCutDepth(); + int cutDepth = parameters->getCutDepth(); if (cutDepth >= 0) { generator->setWhatDepth(cutDepth); } } /* - Now some additional control parameters that affect cut generation activity. + Now some additional control parameters that affect cut generation + activity. - Minimum drop is the minimum objective degradation required to continue with - cut passes. We want at least .05 unless the objective is tiny, in which - case we'll drop down to a floor of .0001. + Minimum drop is the minimum objective degradation required to continue + with cut passes. We want at least .05 unless the objective is tiny, in + which case we'll drop down to a floor of .0001. */ { double objFrac = fabs(model->getMinimizationObjValue()) * .001 + .0001; @@ -377,10 +372,10 @@ void installCutGenerators(CbcGenCtlBlk *ctlBlk, CbcModel *model) model->setMinimumDrop(minDrop); } /* - Set the maximum number of rounds of cut generation at the root and at nodes - in the tree. If the value is positive, cut generation will terminate early - if the objective degradation doesn't meet the minimum drop requirement. If - the value is negatie, minimum drop is not considered. + Set the maximum number of rounds of cut generation at the root and at + nodes in the tree. If the value is positive, cut generation will terminate + early if the objective degradation doesn't meet the minimum drop + requirement. If the value is negatie, minimum drop is not considered. At the root, for small problems, push for 100 passes (really we're betting that we'll stop because no cuts were generated). For medium size problems, @@ -390,7 +385,7 @@ void installCutGenerators(CbcGenCtlBlk *ctlBlk, CbcModel *model) Once we're in the tree, aim for one pass per activation. */ - if (ctlBlk->setByUser_[CbcCbcParam::CUTPASS] == false) { + if (!parameters->setByUser(CbcParam::CUTPASS)) { int numCols = model->getNumCols(); if (numCols < 500) model->setMaximumCutPassesAtRoot(-100); @@ -412,8 +407,7 @@ void installCutGenerators(CbcGenCtlBlk *ctlBlk, CbcModel *model) OsiObjects in cbc-generic. */ -void setupObjects(OsiSolverInterface *osi, - bool didIPP, CglPreProcess *ippObj) +void setupObjects(OsiSolverInterface *osi, bool didIPP, CglPreProcess *ippObj) { int numInts = osi->getNumIntegers(); @@ -456,7 +450,8 @@ void setupObjects(OsiSolverInterface *osi, for (iSOS = 0; iSOS < numSOS; iSOS++) { int iStart = starts[iSOS]; int sosLen = starts[iSOS + 1] - iStart; - sosObjs[iSOS] = new OsiSOS(osi, sosLen, which + iStart, weight + iStart, type[iSOS]); + sosObjs[iSOS] = + new OsiSOS(osi, sosLen, which + iStart, weight + iStart, type[iSOS]); sosObjs[iSOS]->setPriority(numCols - sosLen); } osi->addObjects(numSOS, sosObjs); @@ -469,39 +464,38 @@ void setupObjects(OsiSolverInterface *osi, return; } -} // end local namespace +} // namespace -namespace CbcGenParamUtils { +namespace CbcParamUtils { /* Run branch-and-cut. */ -int doBaCParam(CoinParam *param) +int doBaCParam(CoinParam ¶m) { - assert(param != 0); - CbcGenParam *genParam = dynamic_cast< CbcGenParam * >(param); - assert(genParam != 0); - CbcGenCtlBlk *ctlBlk = genParam->obj(); - assert(ctlBlk != 0); - CbcModel *model = ctlBlk->model_; + CbcParam &cbcParam = dynamic_cast(param); + CbcParameters *parameters = cbcParam.parameters(); + assert(parameters != 0); + CbcModel *model = parameters->getModel(); assert(model != 0); /* Setup to return nonfatal/fatal error (1/-1) by default. */ int retval; - if (CoinParamUtils::isInteractive()) { - retval = 1; - } else { + //if (CoinParamUtils::isInteractive()) { + // retval = 1; + //} else { retval = -1; - } - ctlBlk->setBaBStatus(CbcGenCtlBlk::BACAbandon, CbcGenCtlBlk::BACmInvalid, - CbcGenCtlBlk::BACwNotStarted, false, 0); + //} + parameters->setBaBStatus(CbcParameters::BACAbandon, + CbcParameters::BACmInvalid, + CbcParameters::BACwNotStarted, false, 0); /* We ain't gonna do squat without a good model. */ - if (!ctlBlk->goodModel_) { + if (!parameters->goodModel()) { std::cout << "** Current model not valid!" << std::endl; return (retval); } @@ -518,29 +512,26 @@ int doBaCParam(CoinParam *param) OsiSolverInterface *babSolver = babModel.solver(); assert(babSolver != 0); #if CBC_TRACK_SOLVERS > 0 - std::cout - << "doBaCParam: initial babSolver is " - << std::hex << babSolver << std::dec - << ", log level " << babSolver->messageHandler()->logLevel() - << "." << std::endl; + std::cout << "doBaCParam: initial babSolver is " << std::hex << babSolver + << std::dec << ", log level " + << babSolver->messageHandler()->logLevel() << "." << std::endl; #endif /* Solve the root relaxation. Bail unless it solves to optimality. */ if (!solveRelaxation(&babModel)) { - ctlBlk->setBaBStatus(&babModel, CbcGenCtlBlk::BACwBareRoot); + parameters->setBaBStatus(CbcParameters::BACwBareRoot); return (0); } #if COIN_CBC_VERBOSITY > 0 - std::cout - << "doBaCParam: initial relaxation z = " - << babSolver->getObjValue() << "." << std::endl; + std::cout << "doBaCParam: initial relaxation z = " << babSolver->getObjValue() + << "." << std::endl; #endif /* Are we up for fixing variables based on reduced cost alone? */ - if (ctlBlk->djFix_.action_ == true) { - reducedCostHack(babSolver, ctlBlk->djFix_.threshold_); + if (parameters->getDjFixMode() == CbcParameters::ParamOff) { + reducedCostHack(babSolver, parameters->getDjFixThreshold()); } /* Time to consider preprocessing. We'll do a bit of setup before getting to @@ -559,18 +550,17 @@ int doBaCParam(CoinParam *param) int numberChanged = 0; int numberOriginalColumns = babSolver->getNumCols(); - CbcGenCtlBlk::IPPControl ippAction = ctlBlk->getIPPAction(); + CbcParameters::IPPMode ippMode = parameters->getIPPMode(); - if (!(ippAction == CbcGenCtlBlk::IPPOff || ippAction == CbcGenCtlBlk::IPPStrategy)) { + if (!(ippMode == CbcParameters::IPPOff || + ippMode == CbcParameters::IPPStrategy)) { double timeLeft = babModel.getMaximumSeconds(); preIppSolver = babSolver->clone(); OsiSolverInterface *ippSolver; #if CBC_TRACK_SOLVERS > 0 - std::cout - << "doBaCParam: clone made prior to IPP is " - << std::hex << preIppSolver << std::dec - << ", log level " << preIppSolver->messageHandler()->logLevel() - << "." << std::endl; + std::cout << "doBaCParam: clone made prior to IPP is " << std::hex + << preIppSolver << std::dec << ", log level " + << preIppSolver->messageHandler()->logLevel() << "." << std::endl; #endif preIppSolver->setHintParam(OsiDoInBranchAndCut, true, OsiHintDo); @@ -591,134 +581,126 @@ int doBaCParam(CoinParam *param) respectively. */ int convert = 0; - if (ippAction == CbcGenCtlBlk::IPPEqual) { + if (ippMode == CbcParameters::IPPEqual) { convert = -1; - } else if (ippAction == CbcGenCtlBlk::IPPEqualAll) { + } else if (ippMode == CbcParameters::IPPEqualAll) { convert = -2; - } else if (ippAction == CbcGenCtlBlk::IPPSOS) { + } else if (ippMode == CbcParameters::IPPSOS) { convert = 2; - } else if (ippAction == CbcGenCtlBlk::IPPTrySOS) { + } else if (ippMode == CbcParameters::IPPTrySOS) { convert = 3; } ippSolver = ippObj.preProcessNonDefault(*preIppSolver, convert, 10); #if CBC_TRACK_SOLVERS > 0 - std::cout - << "doBaCParam: solver returned from IPP is " - << std::hex << ippSolver << std::dec; + std::cout << "doBaCParam: solver returned from IPP is " << std::hex + << ippSolver << std::dec; if (ippSolver) { - std::cout - << ", log level " << ippSolver->messageHandler()->logLevel(); + std::cout << ", log level " << ippSolver->messageHandler()->logLevel(); } std::cout << "." << std::endl; #endif /* - ippSolver == 0 is success of a sort --- integer preprocess has found the - problem to be infeasible or unbounded. Need to think about how to indicate - status. + ippSolver == 0 is success of a sort --- integer preprocess has found + the problem to be infeasible or unbounded. Need to think about how to + indicate status. */ if (!ippSolver) { - std::cout - << "Integer preprocess says infeasible or unbounded" << std::endl; + std::cout << "Integer preprocess says infeasible or unbounded" + << std::endl; delete preIppSolver; - ctlBlk->setBaBStatus(&babModel, CbcGenCtlBlk::BACwIPP); + parameters->setBaBStatus(CbcParameters::BACwIPP); return (0); } #if COIN_CBC_VERBOSITY > 0 else { - std::cout - << "After integer preprocessing, model has " - << ippSolver->getNumRows() - << " rows, " << ippSolver->getNumCols() << " columns, and " - << ippSolver->getNumElements() << " elements." << std::endl; + std::cout << "After integer preprocessing, model has " + << ippSolver->getNumRows() << " rows, " + << ippSolver->getNumCols() << " columns, and " + << ippSolver->getNumElements() << " elements." << std::endl; } #endif preIppSolver->setHintParam(OsiDoInBranchAndCut, false, OsiHintDo); ippSolver->setHintParam(OsiDoInBranchAndCut, false, OsiHintDo); - if (ippAction == CbcGenCtlBlk::IPPSave) { + if (ippMode == CbcParameters::IPPSave) { ippSolver->writeMps("presolved", "mps", 1.0); - std::cout - << "Integer preprocessed model written to `presolved.mps' " - << "as minimisation problem." << std::endl; + std::cout << "Integer preprocessed model written to `presolved.mps' " + << "as minimisation problem." << std::endl; } OsiSolverInterface *osiTmp = ippSolver->clone(); babModel.assignSolver(osiTmp); babSolver = babModel.solver(); #if CBC_TRACK_SOLVERS > 0 - std::cout - << "doBaCParam: clone of IPP solver passed to babModel is " - << std::hex << babSolver << std::dec - << ", log level " << babSolver->messageHandler()->logLevel() - << "." << std::endl; + std::cout << "doBaCParam: clone of IPP solver passed to babModel is " + << std::hex << babSolver << std::dec << ", log level " + << babSolver->messageHandler()->logLevel() << "." << std::endl; #endif if (!solveRelaxation(&babModel)) { delete preIppSolver; - ctlBlk->setBaBStatus(&babModel, CbcGenCtlBlk::BACwIPPRelax); + parameters->setBaBStatus(CbcParameters::BACwIPPRelax); return (0); } #if COIN_CBC_VERBOSITY > 0 - std::cout - << "doBaCParam: presolved relaxation z = " - << babSolver->getObjValue() << "." << std::endl; + std::cout << "doBaCParam: presolved relaxation z = " + << babSolver->getObjValue() << "." << std::endl; #endif babModel.setMaximumSeconds(timeLeft - (CoinCpuTime() - time1)); didIPP = true; } /* At this point, babModel and babSolver hold the constraint system we'll use - for B&C (either the original system or the preprocessed system) and we have - a solution to the lp relaxation. + for B&C (either the original system or the preprocessed system) and we + have a solution to the lp relaxation. If we're using the COSTSTRATEGY option, set up priorities here and pass them to the babModel. */ - if (ctlBlk->priorityAction_ != CbcGenCtlBlk::BPOff) { - setupPriorities(&babModel, ctlBlk->priorityAction_); + if (parameters->getBranchingPriorityMode() != CbcParameters::BPOff) { + setupPriorities(&babModel, parameters->getBranchingPriorityMode()); } /* Install heuristics and cutting planes. */ - installHeuristics(ctlBlk, &babModel); - installCutGenerators(ctlBlk, &babModel); + installHeuristics(parameters, &babModel); + installCutGenerators(parameters, &babModel); /* Set up status print frequency for babModel. */ - if (babModel.getNumCols() > 2000 || babModel.getNumRows() > 1500 || babModel.messageHandler()->logLevel() > 1) + if (babModel.getNumCols() > 2000 || babModel.getNumRows() > 1500 || + babModel.messageHandler()->logLevel() > 1) babModel.setPrintFrequency(100); /* If we've read in a known good solution for debugging, activate the row cut debugger. */ - if (ctlBlk->debugSol_.values_) { - if (ctlBlk->debugSol_.numCols_ == babModel.getNumCols()) { - babSolver->activateRowCutDebugger(ctlBlk->debugSol_.values_); + if (parameters->getDebugSolValues()) { + if (parameters->getDebugSolNumCols() == babModel.getNumCols()) { + babSolver->activateRowCutDebugger(parameters->getDebugSolValues()); } else { - std::cout - << "doBaCParam: debug file has incorrect number of columns." - << std::endl; + std::cout << "doBaCParam: debug file has incorrect number of columns." + << std::endl; } } /* Set ratio-based integrality gap, if specified by user. */ - if (ctlBlk->setByUser_[CbcCbcParam::GAPRATIO] == true) { + if (parameters->setByUser(CbcParam::GAPRATIO)) { double obj = babSolver->getObjValue(); double gapRatio = babModel.getDblParam(CbcModel::CbcAllowableFractionGap); double gap = gapRatio * (1.0e-5 + fabs(obj)); babModel.setAllowableGap(gap); - std::cout - << "doBaCParam: Continuous objective = " << obj - << ", so allowable gap set to " << gap << std::endl; + std::cout << "doBaCParam: Continuous objective = " << obj + << ", so allowable gap set to " << gap << std::endl; } /* - A bit of mystery code. As best I can figure, setSpecialOptions(2) suppresses - the removal of warm start information when checkSolution runs an lp to check - a solution. John's comment, ``probably faster to use a basis to get integer - solutions'' makes some sense in this context. Didn't try to track down - moreMipOptions just yet. + A bit of mystery code. As best I can figure, setSpecialOptions(2) + suppresses the removal of warm start information when checkSolution runs an + lp to check a solution. John's comment, ``probably faster to use a basis to + get integer solutions'' makes some sense in this context. Didn't try to + track down moreMipOptions just yet. */ babModel.setSpecialOptions(babModel.specialOptions() | 2); /* @@ -731,40 +713,40 @@ int doBaCParam(CoinParam *param) /* Begin the final run-up to branch-and-cut. - Make sure that objects are set up in the solver. It's possible that whoever - loaded the model into the solver also set up objects. But it's also - entirely likely that none exist to this point (and interesting to note that - IPP doesn't need to know anything about objects). + Make sure that objects are set up in the solver. It's possible that + whoever loaded the model into the solver also set up objects. But it's also + entirely likely that none exist to this point (and interesting to note + that IPP doesn't need to know anything about objects). */ setupObjects(babSolver, didIPP, &ippObj); /* Set the branching method. We can't do this until we establish objects, because the constructor will set up arrays based on the number of objects, - and there's no provision to set this information after creation. Arguably not - good --- it'd be nice to set this in the prototype model that's cloned for - this routine. In CoinSolve, shadowPriceMode is handled with the TESTOSI + and there's no provision to set this information after creation. Arguably + not good --- it'd be nice to set this in the prototype model that's cloned + for this routine. In CoinSolve, shadowPriceMode is handled with the TESTOSI option. */ OsiChooseStrong strong(babSolver); strong.setNumberBeforeTrusted(babModel.numberBeforeTrust()); strong.setNumberStrong(babModel.numberStrong()); - strong.setShadowPriceMode(ctlBlk->chooseStrong_.shadowPriceMode_); + strong.setShadowPriceMode(parameters->getShadowPriceMode()); CbcBranchDefaultDecision decision; decision.setChooseMethod(strong); babModel.setBranchingMethod(decision); /* - Here I've deleted a huge block of code that deals with external priorities, - branch direction, pseudocosts, and solution. (PRIORITYIN) Also a block of - code that generates C++ code. + Here I've deleted a huge block of code that deals with external + priorities, branch direction, pseudocosts, and solution. (PRIORITYIN) Also + a block of code that generates C++ code. */ /* Set up strategy for branch-and-cut. Note that the integer code supplied to - setupPreProcessing is *not* compatible with the IPPAction enum. But at least + setupPreProcessing is *not* compatible with the IPPMode enum. But at least it's documented. See desiredPreProcess_ in CbcStrategyDefault. `1' is accidentally equivalent to IPPOn. */ - if (ippAction == CbcGenCtlBlk::IPPStrategy) { + if (ippMode == CbcParameters::IPPStrategy) { CbcStrategyDefault strategy(true, 5, 5); strategy.setupPreProcessing(1); babModel.setStrategy(strategy); @@ -774,46 +756,44 @@ int doBaCParam(CoinParam *param) general, the solver used to return the solution will not be the solver we passed in, so reset babSolver here. */ - int statistics = (ctlBlk->printOpt_ > 0) ? ctlBlk->printOpt_ : 0; + int statistics = (parameters->getPrintOptions() > 0) ? + parameters->getPrintOptions() : 0; #if CBC_TRACK_SOLVERS > 0 - std::cout - << "doBaCParam: solver at call to branchAndBound is " - << std::hex << babModel.solver() << std::dec - << ", log level " << babModel.solver()->messageHandler()->logLevel() - << "." << std::endl; + std::cout << "doBaCParam: solver at call to branchAndBound is " << std::hex + << babModel.solver() << std::dec << ", log level " + << babModel.solver()->messageHandler()->logLevel() << "." + << std::endl; #endif babModel.branchAndBound(statistics); babSolver = babModel.solver(); #if CBC_TRACK_SOLVERS > 0 - std::cout - << "doBaCParam: solver at return from branchAndBound is " - << std::hex << babModel.solver() << std::dec - << ", log level " << babModel.solver()->messageHandler()->logLevel() - << "." << std::endl; + std::cout << "doBaCParam: solver at return from branchAndBound is " + << std::hex << babModel.solver() << std::dec << ", log level " + << babModel.solver()->messageHandler()->logLevel() << "." + << std::endl; #endif /* Write out solution to preprocessed model. */ - if (ctlBlk->debugCreate_ == "createAfterPre" && babModel.bestSolution()) { - CbcGenParamUtils::saveSolution(babSolver, "debug.file"); + if (parameters->getDebugCreate() == "createAfterPre" && + babModel.bestSolution()) { + CbcParamUtils::saveSolution(babSolver, "debug.file"); } /* Print some information about branch-and-cut. */ #if COIN_CBC_VERBOSITY > 0 - std::cout - << "Cuts at root node changed objective from " - << babModel.getContinuousObjective() - << " to " << babModel.rootObjectiveAfterCuts() << std::endl; + std::cout << "Cuts at root node changed objective from " + << babModel.getContinuousObjective() << " to " + << babModel.rootObjectiveAfterCuts() << std::endl; for (int iGen = 0; iGen < babModel.numberCutGenerators(); iGen++) { CbcCutGenerator *generator = babModel.cutGenerator(iGen); - std::cout - << generator->cutGeneratorName() << " was tried " - << generator->numberTimesEntered() << " times and created " - << generator->numberCutsInTotal() << " cuts of which " - << generator->numberCutsActive() - << " were active after adding rounds of cuts"; + std::cout << generator->cutGeneratorName() << " was tried " + << generator->numberTimesEntered() << " times and created " + << generator->numberCutsInTotal() << " cuts of which " + << generator->numberCutsActive() + << " were active after adding rounds of cuts"; if (generator->timing()) { std::cout << " ( " << generator->timeInCutGenerator() << " seconds)"; } @@ -822,30 +802,28 @@ int doBaCParam(CoinParam *param) #endif time2 = CoinCpuTime(); - ctlBlk->totalTime_ += time2 - time1; + parameters->setTotalTime(parameters->getTotalTime() + time2 - time1); /* If we performed integer preprocessing, time to back it out. */ - if (ippAction != CbcGenCtlBlk::IPPOff) { + if (ippMode != CbcParameters::IPPOff) { #if CBC_TRACK_SOLVERS > 0 - std::cout - << "doBaCParam: solver passed to IPP postprocess is " - << std::hex << babSolver << std::dec << "." << std::endl; + std::cout << "doBaCParam: solver passed to IPP postprocess is " << std::hex + << babSolver << std::dec << "." << std::endl; #endif ippObj.postProcess(*babSolver); babModel.assignSolver(preIppSolver); babSolver = babModel.solver(); #if CBC_TRACK_SOLVERS > 0 - std::cout - << "doBaCParam: solver in babModel after IPP postprocess is " - << std::hex << babSolver << std::dec << "." << std::endl; + std::cout << "doBaCParam: solver in babModel after IPP postprocess is " + << std::hex << babSolver << std::dec << "." << std::endl; #endif } /* Write out postprocessed solution to debug file, if requested. */ - if (ctlBlk->debugCreate_ == "create" && babModel.bestSolution()) { - CbcGenParamUtils::saveSolution(babSolver, "debug.file"); + if (parameters->getDebugCreate() == "create" && babModel.bestSolution()) { + CbcParamUtils::saveSolution(babSolver, "debug.file"); } /* If we have a good solution, detach the solver with the answer. Fill in the @@ -858,26 +836,24 @@ int doBaCParam(CoinParam *param) keepAnswerSolver = true; answerSolver = babSolver; } - ctlBlk->setBaBStatus(&babModel, CbcGenCtlBlk::BACwBAC, - keepAnswerSolver, answerSolver); + parameters->setBaBStatus(CbcParameters::BACwBAC, + keepAnswerSolver, answerSolver); /* And one last bit of information & statistics. */ - ctlBlk->printBaBStatus(); + parameters->printBaBStatus(); std::cout << " "; if (keepAnswerSolver) { - std::cout - << "objective " << babModel.getObjValue() << "; "; + std::cout << "objective " << babModel.getObjValue() << "; "; } - std::cout - << babModel.getNodeCount() << " nodes and " - << babModel.getIterationCount() << " iterations - took " - << time2 - time1 << " seconds" << std::endl; + std::cout << babModel.getNodeCount() << " nodes and " + << babModel.getIterationCount() << " iterations - took " + << time2 - time1 << " seconds" << std::endl; return (0); } -} // end namespace CbcGenParamutils +} // namespace CbcParamUtils /* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 -*/ + */ diff --git a/src/CbcCbcParam.cpp b/src/CbcCbcParam.cpp index 78e125b51..bfb52f9f5 100644 --- a/src/CbcCbcParam.cpp +++ b/src/CbcCbcParam.cpp @@ -2,7 +2,6 @@ // Corporation and others. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). -#include "CbcSolverConfig.h" #ifndef COIN_HAS_CBC #define COIN_HAS_CBC #endif diff --git a/src/CbcCutGenerator.cpp b/src/CbcCutGenerator.cpp index dcee2abab..4a54cde13 100644 --- a/src/CbcCutGenerator.cpp +++ b/src/CbcCutGenerator.cpp @@ -209,7 +209,7 @@ bool CbcCutGenerator::generateCuts(OsiCuts &cs, int fullScan, OsiSolverInterface howOften = 1; // do anyway } } - if (howOften == -100) + if (howOften <= -100) return false; int pass = model_->getCurrentPassNumber() - 1; if (maximumTries_ > 0) { @@ -259,7 +259,7 @@ bool CbcCutGenerator::generateCuts(OsiCuts &cs, int fullScan, OsiSolverInterface if (howOften == 100) doThis = false; // Switch off if special setting - if (whenCutGeneratorInSub_ == -200 && model_->parentModel()) { + if (whenCutGeneratorInSub_ == -200 && !model_->inSmallBranchAndBound()) { fullScan = 0; doThis = false; } @@ -300,6 +300,14 @@ bool CbcCutGenerator::generateCuts(OsiCuts &cs, int fullScan, OsiSolverInterface //#define CBC_DEBUG int numberRowCutsBefore = cs.sizeRowCuts(); int numberColumnCutsBefore = cs.sizeColCuts(); +#ifdef CGL_DEBUG + const OsiRowCutDebugger *debugger2 = solver->getRowCutDebugger(); + if (debugger2 && debugger2->onOptimalPath(*solver)) { + printf("On optimal path cbcgen\n"); + } else { + debugger2 = NULL; + } +#endif #ifdef JJF_ZERO int cutsBefore = cs.sizeCuts(); #endif @@ -373,7 +381,7 @@ bool CbcCutGenerator::generateCuts(OsiCuts &cs, int fullScan, OsiSolverInterface #define TRY_NOW_AND_THEN #ifdef TRY_NOW_AND_THEN if ((numberTimes_ == 200 || (numberTimes_ > 200 && (numberTimes_ % 2000) == 0)) - && !model_->parentModel() && info.formulation_rows > 200) { + && !model_->inSmallBranchAndBound() && info.formulation_rows > 200) { /* In tree, every now and then try various combinations maxStack, maxProbe (last 5 digits) 123 is special and means CglProbing will try and @@ -448,8 +456,10 @@ bool CbcCutGenerator::generateCuts(OsiCuts &cs, int fullScan, OsiSolverInterface } #endif if (generator->getMaxLook() > 0 && !doCuts) { - generator->generateCutsAndModify(*solver, cs, &info); - doCuts = true; + if (info.level<4||(info.level&2)==0) { + generator->generateCutsAndModify(*solver, cs, &info); + doCuts = true; + } } } else { // at root - don't always do @@ -629,6 +639,45 @@ bool CbcCutGenerator::generateCuts(OsiCuts &cs, int fullScan, OsiSolverInterface delete[] mark; #endif } +#ifdef CGL_DEBUG + if (debugger2) { + int numberRowCutsAfter = cs.sizeRowCuts(); + for (int k = numberRowCutsAfter - 1; k >= numberRowCutsBefore; k--) { + OsiRowCut &thisCut = cs.rowCut(k); + if (debugger2->invalidCut(thisCut)) + abort(); + } + } +#endif + //#define CBC_CLEAN_CUTS +#ifdef CBC_CLEAN_CUTS + // take out ones with small elements + { + int numberRowCutsAfter = cs.sizeRowCuts(); + for (int k = numberRowCutsAfter - 1; k >= numberRowCutsBefore; k--) { + OsiRowCut &thisCut = cs.rowCut(k); + CoinPackedVector rpv = thisCut.row(); + const int n = rpv.getNumElements(); + const int *indices = rpv.getIndices(); + const double *elements = rpv.getElements(); + double tolerance = 2.0*model_->getIntegerTolerance(); + bool bad = false; + double badValue=0.0; + for (int i=0;iisInteger(indices[i])) { + bad = true; + badValue = elements[i]; + break; + } + } + if (bad) { + cs.eraseRowCut(k); + printf("bad cut %s with %d elements - %g\n", + generatorName_,n,badValue); + } + } + } +#endif CbcCutModifier *modifier = model_->cutModifier(); if (modifier) { int numberRowCutsAfter = cs.sizeRowCuts(); @@ -853,7 +902,7 @@ bool CbcCutGenerator::generateCuts(OsiCuts &cs, int fullScan, OsiSolverInterface CoinBigIndex nAdd; CoinBigIndex nAdd2; CoinBigIndex nReasonable; - if (!model_->parentModel() && depth < 2) { + if (!model_->inSmallBranchAndBound() && depth < 2) { if (inaccuracy_ < 3) { nAdd = 10000; if (pass > 0 && numberColumns > -500) @@ -1322,6 +1371,430 @@ bool CbcCutGenerator::generateCuts(OsiCuts &cs, int fullScan, OsiSolverInterface } return returnCode; } +#ifdef CBC_LAGRANGEAN_SOLVERS +#include "CglGomory.hpp" +#include "CglTwomir.hpp" +// create a lagrangean solver +static OsiClpSolverInterface * lagrangeanSolver(OsiSolverInterface *solver, + OsiSolverInterface *baseSolver, + int &typeGenerate) { + if (solver->getNumRows()==baseSolver->getNumRows()) { + typeGenerate=-1; + return new OsiClpSolverInterface(); + } + // create + OsiSolverInterface *lagrangeanSolver = baseSolver->clone(); + OsiClpSolverInterface * clpSolver = dynamic_cast(lagrangeanSolver); + ClpSimplex * simplex = clpSolver->getModelPtr(); + int numberOriginalRows = simplex->numberRows(); + int numberRows = solver->getNumRows(); + int numberColumns = solver->getNumCols(); + // bounds + memcpy(simplex->columnLower(), + solver->getColLower(),numberColumns*sizeof(double)); + memcpy(simplex->columnUpper(), + solver->getColUpper(),numberColumns*sizeof(double)); + double * obj = simplex->objective(); + const double * pi = solver->getRowPrice(); + const CoinPackedMatrix * rowCopy = solver->getMatrixByRow(); + const int * column = rowCopy->getIndices(); + const CoinBigIndex * rowStart = rowCopy->getVectorStarts(); + const int * rowLength = rowCopy->getVectorLengths(); + const double * rowElements = rowCopy->getElements(); + const double * rowLower = solver->getRowLower(); + const double * rowUpper = solver->getRowUpper(); + int numberCopy = 0; + int numberAdd = 0; + double * rowLower2 = NULL; + double * rowUpper2 = NULL; + int * column2 = NULL; + CoinBigIndex * rowStart2 = NULL; + double * rowElements2 = NULL; + char * copy = new char [numberRows-numberOriginalRows]; + memset(copy,0,numberRows-numberOriginalRows); + if (typeGenerate==2) { + for (int iRow=numberOriginalRows;iRowgetRowActivity(); + double offset=0.0; + for (int iRow=numberOriginalRows;iRowaddRows(numberCopy, + rowStart2,column2,rowElements2, + rowLower2,rowUpper2); + delete [] rowLower2 ; + delete [] rowUpper2 ; + delete [] column2 ; + delete [] rowStart2 ; + delete [] rowElements2 ; + } + delete [] copy; + memcpy(simplex->primalColumnSolution(),solver->getColSolution(), + numberColumns*sizeof(double)); + CoinWarmStart * warmstart = solver->getWarmStart(); + CoinWarmStartBasis* warm = + dynamic_cast(warmstart); + warm->resize(numberOriginalRows,numberColumns); + clpSolver->setBasis(*warm); + delete warm; + simplex->setDualObjectiveLimit(COIN_DBL_MAX); + simplex->setObjectiveOffset(simplex->objectiveOffset()-offset); + simplex->setLogLevel(0); + simplex->primal(1); + // check basis + int numberTotal=simplex->numberRows()+simplex->numberColumns(); + int superbasic=0; + for (int i=0;igetStatus(i)==ClpSimplex::superBasic) + superbasic++; + } + if (superbasic) { + //printf("%d superbasic!\n",superbasic); + simplex->dual(); + superbasic=0; + for (int i=0;igetStatus(i)==ClpSimplex::superBasic) + superbasic++; + } + assert (!superbasic); + } + if (!simplex->status()) { + clpSolver->setWarmStart(NULL); + clpSolver->setLastAlgorithm(2); + return clpSolver; + } else { + typeGenerate=-1; + return new OsiClpSolverInterface(); + } +} +bool +CbcCutGenerator::generateCuts(OsiCuts &cs, int fullScan, OsiSolverInterface *solver, + CbcNode *node, + OsiSolverInterface **baseSolver, + OsiSolverInterface **cleanSolver) +{ + if (node) + return generateCuts(cs, fullScan, solver, node); + bool returnCode = false; + OsiSolverInterface *baseLagrangeanSolver = + *baseSolver; + OsiSolverInterface *cleanLagrangeanSolver = + *cleanSolver; + int nCutsBefore = cs.sizeRowCuts(); +#if 0 + //returnCode = generateCuts(cs, fullScan, solver, node); + if (!returnCode && whatLagrangean() && + solver->getNumRows()>model_->continuousSolver()->getNumRows()) { + int typeGenerate; + if (whatLagrangean()&2) { + if (!cleanLagrangeanSolver) { + typeGenerate = 2; + cleanLagrangeanSolver = + lagrangeanSolver(solver,model_->continuousSolver(),typeGenerate); + *cleanSolver = cleanLagrangeanSolver; + if (cleanLagrangeanSolver->getNumRows()== + model_->continuousSolver()->getNumRows()) { + // fake base to skip + if (!baseLagrangeanSolver) { + baseLagrangeanSolver = new OsiClpSolverInterface(); + *baseSolver = baseLagrangeanSolver; + } + } + } + returnCode = generateCuts(cs, fullScan, cleanLagrangeanSolver, node); + //int nCutsAfter = cs.sizeRowCuts(); + //if (nCutsAfter>nCutsBefore) + //printf("clean %s added %d\n",generatorName_,nCutsAfter-nCutsBefore); + } + if (whatLagrangean()&4) { + if (!baseLagrangeanSolver) { + typeGenerate = 1; + baseLagrangeanSolver = + lagrangeanSolver(solver,model_->continuousSolver(),typeGenerate); + *baseSolver = baseLagrangeanSolver; + } + if (baseLagrangeanSolver->getNumRows()) { + returnCode = generateCuts(cs, fullScan, baseLagrangeanSolver, node); + //int nCutsAfter = cs.sizeRowCuts(); + //if (nCutsAfter>nCutsBefore) + //printf("base %s added %d\n",generatorName_,nCutsAfter-nCutsBefore); + } + } + } + *baseSolver = baseLagrangeanSolver; + *cleanSolver = cleanLagrangeanSolver; + return returnCode; +#endif + /* + If wants base - + if base empty - create base from originalSolver_ as in generator + set flags to say don't want base and pass in base as solver + Same for clean + */ + if (!cleanLagrangean() && !originalLagrangean()) { + returnCode = generateCuts(cs, fullScan, solver, node); + } else { + // 0 - skip, 1 - do normal, 2 - do clean, 3 - do base + int typeGenerate = cleanLagrangean() ? 3 : 2; + // later take out code from Cgl? + // also move originalSolver_ so only one copy (use continuousSolver_) + CglGomory * gomory = dynamic_cast(generator_); + CglTwomir * twomir = dynamic_cast(generator_); + OsiSolverInterface * originalSolver; + int saveType; + if (gomory) { + originalSolver = gomory->swapOriginalSolver(NULL); + saveType = gomory->gomoryType(); + gomory->setGomoryType(0); + } else if (twomir) { + originalSolver = twomir->swapOriginalSolver(NULL); + saveType = twomir->twomirType(); + twomir->setTwomirType(0); + } + if (solver->getNumRows()==model_->continuousSolver()->getNumRows()) + typeGenerate = 1; + // but skip if already done + if (typeGenerate==2 && cleanLagrangeanSolver) { + returnCode = generateCuts(cs, fullScan, cleanLagrangeanSolver, node); + } else if (typeGenerate==3 && baseLagrangeanSolver) { + returnCode = generateCuts(cs, fullScan, baseLagrangeanSolver, node); + } else if (typeGenerate==1) { + returnCode = generateCuts(cs, fullScan, solver, node); + } else { + // create +#if 1 + OsiClpSolverInterface * clpSolver = + lagrangeanSolver(solver,model_->continuousSolver(), + typeGenerate); + if (typeGenerate == 2) { + cleanLagrangeanSolver = clpSolver; + *cleanSolver = cleanLagrangeanSolver; + } else { + baseLagrangeanSolver = clpSolver; + *baseSolver = baseLagrangeanSolver; + } + if (typeGenerate) { + clpSolver->resolve(); + returnCode = generateCuts(cs, fullScan, clpSolver, node); + //int nCutsAfter = cs.sizeRowCuts(); + //if (nCutsAfter>nCutsBefore) + //printf("clean/base %s added %d zgen %d\n", + // generatorName_,nCutsAfter-nCutsBefore,typeGenerate); + } + } +#else + OsiClpSolverInterface * clpSolver; + if (typeGenerate==2) { + cleanLagrangeanSolver = model_->continuousSolver()->clone(); + clpSolver = dynamic_cast(cleanLagrangeanSolver); + *cleanSolver = cleanLagrangeanSolver; + } else { + baseLagrangeanSolver = model_->continuousSolver()->clone(); + *baseSolver = baseLagrangeanSolver; + clpSolver = dynamic_cast(baseLagrangeanSolver); + } + ClpSimplex * simplex = clpSolver->getModelPtr(); + int numberOriginalRows = simplex->numberRows(); + int numberRows = solver->getNumRows(); + int numberColumns = solver->getNumCols(); + // bounds + memcpy(simplex->columnLower(), + solver->getColLower(),numberColumns*sizeof(double)); + memcpy(simplex->columnUpper(), + solver->getColUpper(),numberColumns*sizeof(double)); + double * obj = simplex->objective(); + //objective = CoinCopyOfArray(obj,numberColumns); + const double * pi = solver->getRowPrice(); + const CoinPackedMatrix * rowCopy = solver->getMatrixByRow(); + const int * column = rowCopy->getIndices(); + const CoinBigIndex * rowStart = rowCopy->getVectorStarts(); + const int * rowLength = rowCopy->getVectorLengths(); + const double * rowElements = rowCopy->getElements(); + const double * rowLower = solver->getRowLower(); + const double * rowUpper = solver->getRowUpper(); + int numberCopy = 0; + int numberAdd = 0; + double * rowLower2 = NULL; + double * rowUpper2 = NULL; + int * column2 = NULL; + CoinBigIndex * rowStart2 = NULL; + double * rowElements2 = NULL; + char * copy = new char [numberRows-numberOriginalRows]; + memset(copy,0,numberRows-numberOriginalRows); + if (typeGenerate==2) { + for (int iRow=numberOriginalRows;iRowgetRowActivity(); + double offset=0.0; + for (int iRow=numberOriginalRows;iRowaddRows(numberCopy, + rowStart2,column2,rowElements2, + rowLower2,rowUpper2); + delete [] rowLower2 ; + delete [] rowUpper2 ; + delete [] column2 ; + delete [] rowStart2 ; + delete [] rowElements2 ; + } + delete [] copy; + simplex->setObjectiveOffset(simplex->objectiveOffset()-offset); + memcpy(simplex->primalColumnSolution(),solver->getColSolution(), + numberColumns*sizeof(double)); + CoinWarmStart * warmstart = solver->getWarmStart(); + CoinWarmStartBasis* warm = + dynamic_cast(warmstart); + warm->resize(numberOriginalRows,numberColumns); + clpSolver->setBasis(*warm); + delete warm; + simplex->setDualObjectiveLimit(COIN_DBL_MAX); + simplex->setLogLevel(0); + simplex->primal(1); + // check basis + int numberTotal=simplex->numberRows()+simplex->numberColumns(); + int superbasic=0; + for (int i=0;igetStatus(i)==ClpSimplex::superBasic) + superbasic++; + } + if (superbasic) { + //printf("%d superbasic!\n",superbasic); + simplex->dual(); + superbasic=0; + for (int i=0;igetStatus(i)==ClpSimplex::superBasic) + superbasic++; + } + assert (!superbasic); + } + if (!simplex->status()) { + clpSolver->setWarmStart(NULL); + } else { + //printf("BAD status %d\n",simplex->status()); + //clpSolver->writeMps("clp"); + //solver->writeMps("si"); + typeGenerate=0; + } + } else { + delete [] copy; + } + if (typeGenerate) { + returnCode = generateCuts(cs, fullScan, clpSolver, node); + } + } +#endif + if (gomory) { + gomory->swapOriginalSolver(originalSolver); + gomory->setGomoryType(saveType); + } else if (twomir) { + twomir->swapOriginalSolver(originalSolver); + twomir->setTwomirType(saveType); + } + } + return returnCode; +} +#endif void CbcCutGenerator::setHowOften(int howOften) { @@ -1388,6 +1861,233 @@ void CbcCutGenerator::scaleBackStatistics(int factor) // Number of short cuts at root numberShortCutsAtRoot_ = (numberShortCutsAtRoot_ + factor - 1) / factor; } +#ifdef CBC_LAGRANGEAN_SOLVERS +#include "CglLandP.hpp" +#include "CglGMI.hpp" +#include "CglRedSplit2.hpp" +#include "CglResidualCapacity.hpp" +#include "OsiRowCutDebugger.hpp" +// less used cut generators +// One last (or first) go at cuts +int +CbcModel::oneLastGoAtCuts(OsiCuts &cuts, int typeGo) +{ + // Get clean solver + int typeGenerate = 2; // clean + bool doCut[4]={1,1,1,1}; + { + int nNodes = 2000010; //getMaximumNodes(); + if (nNodes>=2000000 && nNodes<2000050) + typeGenerate = 3; // base + if ((nNodes>=1000000&&nNodes<1000033) || + (nNodes>=2000000&&nNodes<2000033)) { + nNodes %= 100; + for (int i=0;i<4;i++) { + doCut[i] = nNodes&1; + nNodes = nNodes >> 1; + } + } + solver_->resolve(); + } + OsiClpSolverInterface *lSolver; + if (typeGo==2) { + lSolver = lagrangeanSolver(solver_,continuousSolver_,typeGenerate); + } else { + lSolver = dynamic_cast(solver_); + } + // cuts seem to dislike a pointer + OsiClpSolverInterface solver = *lSolver; + if (typeGo==2) + delete lSolver; + if (!solver.getNumRows()) { + return 0; + } + solver.setLastAlgorithm(2);// as copy sets to 0 + solver.getModelPtr()->setProblemStatus(0); + int numberColCutsBefore = cuts.sizeColCuts(); + int numberCutsBefore = cuts.sizeRowCuts(); + CglTreeInfo info; + info.level = 0; + info.pass = 0; + info.formulation_rows = numberRowsAtContinuous(); + info.inTree = false; +#ifdef TIME_LAST_GO + int numberCuts = numberCutsBefore; + double time1 = CoinCpuTime(); + double time2 = time1; + double time3; +#endif +#if 0 + // less used + bool alreadyThere; + // CglLandP + alreadyThere = false; + for (int i = 0; i < numberCutGenerators_; i++) { + if (dynamic_cast(generator_[i]->generator())) { + alreadyThere = true; + break; + } + } + if (!alreadyThere && doCut[0]) { + CglLandP generator; + generator.generateCuts(solver,cuts,info); +#ifdef TIME_LAST_GO + int nCuts = cuts.sizeRowCuts(); + time3 = CoinCpuTime(); + printf("CglLandP generated %d cuts %.6f\n", + nCuts-numberCuts,time3-time2); + time2 = time3; + numberCuts = nCuts; +#endif + } + // CglGMI + alreadyThere = false; + for (int i = 0; i < numberCutGenerators_; i++) { + if (dynamic_cast(generator_[i]->generator())) { + alreadyThere = true; + break; + } + } + if (!alreadyThere && doCut[1]) { + CglGMI generator; + generator.generateCuts(solver,cuts,info); +#ifdef TIME_LAST_GO + int nCuts = cuts.sizeRowCuts(); + time3 = CoinCpuTime(); + printf("CglGMI generated %d cuts %.6f\n", + nCuts-numberCuts,time3-time2); + time2 = time3; + numberCuts = nCuts; +#endif + } + // CglRedSplit2 + alreadyThere = false; + for (int i = 0; i < numberCutGenerators_; i++) { + if (dynamic_cast(generator_[i]->generator())) { + alreadyThere = true; + break; + } + } + if (!alreadyThere && doCut[2]) { + CglRedSplit2 generator; + generator.generateCuts(solver,cuts,info); +#ifdef TIME_LAST_GO + int nCuts = cuts.sizeRowCuts(); + time3 = CoinCpuTime(); + printf("CglRedSplit2 generated %d cuts %.6f\n", + nCuts-numberCuts,time3-time2); + time2 = time3; + numberCuts = nCuts; +#endif + } + // CglResidualCapacity + alreadyThere = false; + for (int i = 0; i < numberCutGenerators_; i++) { + if (dynamic_cast(generator_[i]->generator())) { + alreadyThere = true; + break; + } + } + if (!alreadyThere && doCut[3]) { + CglResidualCapacity generator; + generator.generateCuts(solver,cuts,info); +#ifdef TIME_LAST_GO + int nCuts = cuts.sizeRowCuts(); + time3 = CoinCpuTime(); + printf("CglResidualCapacity generated %d cuts %.6f\n", + nCuts-numberCuts,time3-time2); + time2 = time3; + numberCuts = nCuts; +#endif + } + // and now others + for (int i = 0; i < numberCutGenerators_; i++) { + generator_[i]->generateCuts(cuts,1,&solver,NULL); +#ifdef TIME_LAST_GO + int nCuts = cuts.sizeRowCuts(); + time3 = CoinCpuTime(); + if (nCuts>numberCuts) { + printf("%s generated %d cuts %.6f*\n",generator_[i]->cutGeneratorName(), + nCuts-numberCuts,time3-time2); + numberCuts = nCuts; + } else if (time3>time2+0.01) { + printf("%s generated no cuts %.6f*\n",generator_[i]->cutGeneratorName(), + time3-time2); + } + time2 = time3; +#endif + } +#else + if (typeGo==1) { + // see if there + for (int i = 0; i < numberCutGenerators_; i++) { + if (dynamic_cast(generator_[i]->generator())) + doCut[0] = 0; + else if (dynamic_cast(generator_[i]->generator())) + doCut[1] = 0; + else if (dynamic_cast(generator_[i]->generator())) + doCut[2] = 0; + else if (dynamic_cast(generator_[i]->generator())) + doCut[3] = 0; + } + } + if (doCut[0]) { + CglLandP generator; + generator.generateCuts(solver,cuts,info); +#ifdef TIME_LAST_GO + int nCuts = cuts.sizeRowCuts(); + time3 = CoinCpuTime(); + printf("CglLandP generated %d cuts %.6f\n", + nCuts-numberCuts,time3-time2); + time2 = time3; + numberCuts = nCuts; +#endif + } + if (doCut[1]) { + CglGMI generator; + generator.generateCuts(solver,cuts,info); +#ifdef TIME_LAST_GO + int nCuts = cuts.sizeRowCuts(); + time3 = CoinCpuTime(); + printf("CglGMI generated %d cuts %.6f\n", + nCuts-numberCuts,time3-time2); + time2 = time3; + numberCuts = nCuts; +#endif + } + if (doCut[2]) { + CglRedSplit2 generator; + generator.generateCuts(solver,cuts,info); +#ifdef TIME_LAST_GO + int nCuts = cuts.sizeRowCuts(); + time3 = CoinCpuTime(); + printf("CglRedSplit2 generated %d cuts %.6f\n", + nCuts-numberCuts,time3-time2); + time2 = time3; + numberCuts = nCuts; +#endif + } + if (doCut[3]) { + CglResidualCapacity generator; + generator.generateCuts(solver,cuts,info); +#ifdef TIME_LAST_GO + int nCuts = cuts.sizeRowCuts(); + time3 = CoinCpuTime(); + printf("CglResidualCapacity generated %d cuts %.6f\n", + nCuts-numberCuts,time3-time2); + time2 = time3; + numberCuts = nCuts; +#endif + } +#endif +#ifdef TIME_LAST_GO + printf("Total cuts %d in time %.6f\n",numberCuts-numberCutsBefore,time2-time1); +#else + int numberCuts = cuts.sizeRowCuts(); +#endif + return numberCuts-numberCutsBefore; +} +#endif // Create C++ lines to get to current state void CbcCutGenerator::generateTuning(FILE *fp) { @@ -1411,6 +2111,3 @@ void CbcCutGenerator::generateTuning(FILE *fp) if (whetherToUse()) fprintf(fp, " generator->setWhetherToUse(true);\n"); } - -/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 -*/ diff --git a/src/CbcCutGenerator.hpp b/src/CbcCutGenerator.hpp index af6d26d68..402882424 100644 --- a/src/CbcCutGenerator.hpp +++ b/src/CbcCutGenerator.hpp @@ -69,6 +69,12 @@ class CBCLIB_EXPORT CbcCutGenerator { */ bool generateCuts(OsiCuts &cs, int fullScan, OsiSolverInterface *solver, CbcNode *node); +#ifdef CBC_LAGRANGEAN_SOLVERS + bool generateCuts(OsiCuts &cs, int fullScan, OsiSolverInterface *solver, + CbcNode *node, + OsiSolverInterface **baseLagrangeanSolver, + OsiSolverInterface **cleanLagrangeanSolver); +#endif //@} /**@name Constructors and destructors */ @@ -249,6 +255,43 @@ class CBCLIB_EXPORT CbcCutGenerator { { timeInCutGenerator_ += value; } + /// Get whether the cut generator uses clean lagrangean + inline bool cleanLagrangean() const + { + return (switches_ & 16384) != 0; + } + /// Set whether the cut generator uses clean lagrangean + inline void setCleanLagrangean(bool value) + { + switches_ &= ~16384; + switches_ |= value ? 16384 : 0; + } + /// Get whether the cut generator uses continuous lagrangean + inline bool originalLagrangean() const + { + return (switches_ & 32768) != 0; + } + /// Set whether the cut generator uses continuous lagrangean + inline void setOriginalLagrangean(bool value) + { + switches_ &= ~32768; + switches_ |= value ? 32768 : 0; + } + /** Get what cut generator is to do - + 0 - normal + 65536*7 - 1 normal + 65536*7 - 2 clean + 65536*7 - 4 base */ + inline int whatLagrangean() const + { + return (switches_ & (65536*7)) >> 16; + } + /// Set what generator should do (lagrangeanwise) + inline void setWhatLagrangean(int value) + { + switches_ &= ~(65536*7); + switches_ |= value*65536; + } /// Get the \c CglCutGenerator corresponding to this \c CbcCutGenerator. inline CglCutGenerator *generator() const { diff --git a/src/CbcDebug.hpp b/src/CbcDebug.hpp new file mode 100644 index 000000000..729187dbf --- /dev/null +++ b/src/CbcDebug.hpp @@ -0,0 +1,168 @@ +#ifndef CbcDebug_H +#define CbcDebug_H + +#ifdef CLP_DEBUG_MALLOC + +/*extern "C" */ void clp_memory(int type); +/*extern "C" */ +void *clp_malloc(int length); +/*extern "C" */ +void clp_free(void *array); +#include +#include +#include + +#endif + +// define TEST_MESSAGE_HANDLER to check works on all messages +// #define TEST_MESSAGE_HANDLER +#ifdef TEST_MESSAGE_HANDLER +// This driver shows how to trap messages - this is just as in unitTest.cpp +// ****** THis code is similar to MyMessageHandler.hpp and MyMessagehandler.cpp +#include "CoinMessageHandler.hpp" +#include "OsiClpSolverInterface.hpp" +#include "CbcModel.hpp" + +/** This just adds a model to CoinMessage and a void pointer so + user can trap messages and do useful stuff. + This is used in Clp/Test/unitTest.cpp + + The file pointer is just there as an example of user stuff. + + -- lh 071026 -- An accurate summary. Nothing is actually happening here + except that messages will be prefixed with "==", which serves the purpose + of demonstrating that this message handler is active. The extra parameters + (CbcModel, FILE) are unused. + +*/ + +class MyMessageHandler2 : public CoinMessageHandler { + +public: + /**@name Overrides */ + //@{ + virtual int print(); + //@} + /**@name set and get */ + //@{ + /// Model + const CbcModel *model() const; + void setModel(CbcModel *model); + //@} + + /**@name Constructors, destructor */ + //@{ + /** Default constructor. */ + MyMessageHandler2(); + /// Constructor with pointer to model + MyMessageHandler2(CbcModel *model, + FILE *userPointer = NULL); + /** Destructor */ + virtual ~MyMessageHandler2(); + //@} + + /**@name Copy method */ + //@{ + /** The copy constructor. */ + MyMessageHandler2(const MyMessageHandler2 &); + /** The copy constructor from an CoinSimplexMessageHandler. */ + MyMessageHandler2(const CoinMessageHandler &); + + MyMessageHandler2 &operator=(const MyMessageHandler2 &); + /// Clone + virtual CoinMessageHandler *clone() const; + //@} + +protected: + /**@name Data members + The data members are protected to allow access for derived classes. */ + //@{ + /// Pointer back to model + CbcModel *model_; + //@} +}; + +//############################################################################# +// Constructors / Destructor / Assignment +//############################################################################# + +//------------------------------------------------------------------- +// Default Constructor +//------------------------------------------------------------------- +MyMessageHandler2::MyMessageHandler2() + : CoinMessageHandler() + , model_(NULL) +{ +} + +//------------------------------------------------------------------- +// Copy constructor +//------------------------------------------------------------------- +MyMessageHandler2::MyMessageHandler2(const MyMessageHandler2 &rhs) + : CoinMessageHandler(rhs) + , model_(rhs.model_) +{ +} + +MyMessageHandler2::MyMessageHandler2(const CoinMessageHandler &rhs) + : CoinMessageHandler() + , model_(NULL) +{ +} + +// Constructor with pointer to model +MyMessageHandler2::MyMessageHandler2(CbcModel *model, + FILE *userPointer) + : CoinMessageHandler() + , model_(model) +{ +} + +//------------------------------------------------------------------- +// Destructor +//------------------------------------------------------------------- +MyMessageHandler2::~MyMessageHandler2() +{ +} + +//---------------------------------------------------------------- +// Assignment operator +//------------------------------------------------------------------- +MyMessageHandler2 & +MyMessageHandler2::operator=(const MyMessageHandler2 &rhs) +{ + if (this != &rhs) { + CoinMessageHandler::operator=(rhs); + model_ = rhs.model_; + } + return *this; +} +//------------------------------------------------------------------- +// Clone +//------------------------------------------------------------------- +CoinMessageHandler *MyMessageHandler2::clone() const +{ + return new MyMessageHandler2(*this); +} +int MyMessageHandler2::print() +{ + // Just add == + fprintf(fp_, " == "); + fprintf(fp_, "%s\n", messageBuffer_); + return 0; +} +const CbcModel * +MyMessageHandler2::model() const +{ + return model_; +} +void MyMessageHandler2::setModel(CbcModel *model) +{ + model_ = model; +} + +void test_message_handler(CbcModel &model); + +#endif /* TEST_MESSAGE_HANDLER */ + +#endif diff --git a/src/CbcGenCbcParam.cpp b/src/CbcGenCbcParam.cpp deleted file mode 100644 index d4f1b1f12..000000000 --- a/src/CbcGenCbcParam.cpp +++ /dev/null @@ -1,160 +0,0 @@ -/* - Copyright (C) 2007, Lou Hafer, International Business Machines Corporation - and others. All Rights Reserved. - - This code is licensed under the terms of the Eclipse Public License (EPL). - -*/ -/* - This file is part of cbc-generic. -*/ - -#if defined(_MSC_VER) -// Turn off compiler warning about long names -#pragma warning(disable : 4786) -#endif - -#include -#include - -#include "CoinParam.hpp" - -#include "CbcModel.hpp" - -#include "CbcGenCtlBlk.hpp" -#include "CbcGenParam.hpp" -#include "CbcGenCbcParam.hpp" - -namespace { - - -} - -/* - Constructors and destructors - - There's a generic constructor and one for integer, double, keyword, string, - and action parameters. -*/ - -/* - Default constructor. -*/ -CbcCbcParam::CbcCbcParam() - : CoinParam() - , paramCode_(CbcCbcParamCode(0)) - , obj_(0) -{ - /* Nothing to be done here */ -} - -/* - Constructor for double parameter -*/ -CbcCbcParam::CbcCbcParam(CbcCbcParamCode code, - std::string name, std::string help, - double lower, double upper, double dflt, - bool display) - : CoinParam(name, help, lower, upper, dflt, display) - , paramCode_(code) - , obj_(0) -{ - /* Nothing to be done here */ -} - -/* - Constructor for integer parameter -*/ -CbcCbcParam::CbcCbcParam(CbcCbcParamCode code, - std::string name, std::string help, - int lower, int upper, int dflt, - bool display) - : CoinParam(name, help, lower, upper, dflt, display) - , paramCode_(code) - , obj_(0) -{ - /* Nothing to be done here */ -} - -/* - Constructor for keyword parameter. -*/ -CbcCbcParam::CbcCbcParam(CbcCbcParamCode code, - std::string name, std::string help, - std::string firstValue, int dflt, - bool display) - : CoinParam(name, help, firstValue, dflt, display) - , paramCode_(code) - , obj_(0) -{ - /* Nothing to be done here */ -} - -/* - Constructor for string parameter. -*/ -CbcCbcParam::CbcCbcParam(CbcCbcParamCode code, - std::string name, std::string help, - std::string dflt, - bool display) - : CoinParam(name, help, dflt, display) - , paramCode_(code) - , obj_(0) -{ - /* Nothing to be done here */ -} - -/* - Constructor for action parameter. -*/ -CbcCbcParam::CbcCbcParam(CbcCbcParamCode code, - std::string name, std::string help, - bool display) - : CoinParam(name, help, display) - , paramCode_(code) - , obj_(0) -{ - /* Nothing to be done here */ -} - -/* - Copy constructor. -*/ -CbcCbcParam::CbcCbcParam(const CbcCbcParam &orig) - : CoinParam(orig) - , paramCode_(orig.paramCode_) - , obj_(orig.obj_) -{ - /* Nothing to be done here */ -} - -/* - Clone -*/ - -CbcCbcParam *CbcCbcParam::clone() -{ - return (new CbcCbcParam(*this)); -} - -CbcCbcParam &CbcCbcParam::operator=(const CbcCbcParam &rhs) -{ - if (this != &rhs) { - CoinParam::operator=(rhs); - - paramCode_ = rhs.paramCode_; - obj_ = rhs.obj_; - } - - return *this; -} - -/* - Destructor -*/ -CbcCbcParam::~CbcCbcParam() -{ /* Nothing more to do */ -} - -/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 -*/ diff --git a/src/CbcGenCbcParamUtils.cpp b/src/CbcGenCbcParamUtils.cpp deleted file mode 100644 index ac5617fa4..000000000 --- a/src/CbcGenCbcParamUtils.cpp +++ /dev/null @@ -1,386 +0,0 @@ -/* - Copyright (C) 2007, Lou Hafer, International Business Machines Corporation - and others. All Rights Reserved. - - This code is licensed under the terms of the Eclipse Public License (EPL). - -*/ -/* - This file is part of cbc-generic. -*/ - -#if defined(_MSC_VER) -// Turn off compiler warning about long names -#pragma warning(disable : 4786) -#endif - -#include -#include - -#include "CoinFinite.hpp" -#include "CoinParam.hpp" - -#include "CbcModel.hpp" - -#include "CbcGenCtlBlk.hpp" -#include "CbcGenParam.hpp" -#include "CbcGenCbcParam.hpp" - -/*! \file CbcGenParamUtils - \brief Implementation functions for CbcGenParam parameters. -*/ - -namespace { - - -} - -namespace CbcCbcParamUtils { - -/* Function to set up cbc (CbcModel) parameters. */ - -void addCbcCbcParams(int &numberParameters, CoinParamVec ¶meters, - CbcModel *model) - -{ - CbcCbcParam *param; - - param = new CbcCbcParam(CbcCbcParam::ALLOWABLEGAP, - "allow!ableGap", - "Stop when gap between best possible and incumbent is less than this", - 0.0, 1.0e20); - param->setDblVal(0.0); - param->setPushFunc(pushCbcCbcDbl); - param->setObj(model); - param->setLongHelp( - "If the gap between best solution and best possible solution is less than this then the search will be terminated. Also see ratioGap."); - parameters.push_back(param); - - param = new CbcCbcParam(CbcCbcParam::CUTOFF, - "cuto!ff", "All solutions must be better than this", -1.0e60, 1.0e60); - param->setDblVal(1.0e50); - param->setPushFunc(pushCbcCbcDbl); - param->setObj(model); - param->setLongHelp( - "All solutions must be better than this value (in a minimization sense). This is also set by cbc whenever it obtains a solution and is set to the value of the objective for the solution minus the cutoff increment."); - parameters.push_back(param); - - param = new CbcCbcParam(CbcCbcParam::DIRECTION, - "direction", "Minimize or maximize", "min!imize", 0); - param->appendKwd("max!imize"); - param->appendKwd("zero"); - param->setObj(model); - param->setLongHelp( - "The default is minimize - use 'direction maximize' for maximization.\nYou can also use the parameters 'maximize' or 'minimize'."); - parameters.push_back(param); - - param = new CbcCbcParam(CbcCbcParam::INCREMENT, - "inc!rement", - "A new solution must be at least this much better than the incumbent", - -1.0e20, 1.0e20, model->getDblParam(CbcModel::CbcCutoffIncrement)); - param->setPushFunc(pushCbcCbcDbl); - param->setObj(model); - param->setLongHelp( - "Whenever a solution is found the bound on future solutions is set to the objective of the solution (in a minimization sense) plus the specified increment. If this option is not specified, the code will try and work out an increment. E.g., if all objective coefficients are multiples of 0.01 and only integer variables have entries in objective then the increment can be set to 0.01. Be careful if you set this negative!"); - parameters.push_back(param); - - param = new CbcCbcParam(CbcCbcParam::INFEASIBILITYWEIGHT, - "inf!easibilityWeight", - "Each integer infeasibility is expected to cost this much", - 0.0, 1.0e20, model->getDblParam(CbcModel::CbcInfeasibilityWeight)); - param->setPushFunc(pushCbcCbcDbl); - param->setObj(model); - param->setLongHelp( - "A primitive way of deciding which node to explore next. Satisfying each integer infeasibility is expected to cost this much."); - parameters.push_back(param); - - param = new CbcCbcParam(CbcCbcParam::INTEGERTOLERANCE, - "integerT!olerance", - "For an optimal solution, no integer variable may be farther than this from an integer value", - 1.0e-20, 0.5, model->getDblParam(CbcModel::CbcIntegerTolerance)); - param->setPushFunc(pushCbcCbcDbl); - param->setObj(model); - param->setLongHelp( - "When checking a solution for feasibility, if the difference between the value of a variable and the nearest integer is less than the integer tolerance, the value is considered to be integral. Beware of setting this smaller than the primal tolerance."); - parameters.push_back(param); - - param = new CbcCbcParam(CbcCbcParam::LOGLEVEL, - "bclog!Level", "Level of detail in Coin branch and Cut output", - -1, 63, model->messageHandler()->logLevel()); - param->setPushFunc(pushCbcCbcInt); - param->setObj(model); - param->setLongHelp( - "If set to 0 then there should be no output in normal circumstances. A value of 1 is probably the best value for most uses, while 2 and 3 give more information."); - parameters.push_back(param); - - param = new CbcCbcParam(CbcCbcParam::MAXIMIZE, - "max!imize", "Set optimization direction to maximize"); - param->setObj(model); - param->setLongHelp( - "The default is minimize - use 'maximize' for maximization.\n A synonym for 'direction maximize'."); - parameters.push_back(param); - - param = new CbcCbcParam(CbcCbcParam::MAXNODES, - "maxN!odes", "Maximum number of nodes to evaluate", 1, 2147483647); - param->setObj(model); - param->setLongHelp( - "This is a repeatable way to limit search. Normally using time is easier but then the results may not be repeatable."); - parameters.push_back(param); - - param = new CbcCbcParam(CbcCbcParam::MINIMIZE, - "min!imize", "Set optimization direction to minimize"); - param->setObj(model); - param->setLongHelp( - "The default is minimize - use 'maximize' for maximization.\nThis should only be necessary if you have previously set maximization. A synonym for 'direction minimize'."); - parameters.push_back(param); - - param = new CbcCbcParam(CbcCbcParam::MIPOPTIONS, - "mipO!ptions", "Dubious options for mip", 0, COIN_INT_MAX, 0, false); - parameters.push_back(param); - - param = new CbcCbcParam(CbcCbcParam::MOREMIPOPTIONS, - "more!MipOptions", "More dubious options for mip", -1, COIN_INT_MAX, 0, false); - parameters.push_back(param); - - param = new CbcCbcParam(CbcCbcParam::NUMBERMINI, - "miniT!ree", "Size of fast mini tree", 0, COIN_INT_MAX, 0, false); - param->setObj(model); - param->setLongHelp( - "The idea is that I can do a small tree fast. This is a first try and will hopefully become more sophisticated."); - parameters.push_back(param); - - param = new CbcCbcParam(CbcCbcParam::NUMBERANALYZE, - "numberA!nalyze", - "Number of analysis iterations", -COIN_INT_MAX, COIN_INT_MAX, false); - param->setObj(model); - param->setLongHelp( - "This says how many iterations to spend at the root node analyzing the problem. This is a first try and will hopefully become more sophisticated."); - parameters.push_back(param); - - param = new CbcCbcParam(CbcCbcParam::CUTPASS, - "passC!uts", "Number of cut passes at root node", - -999999, 999999, model->getMaximumCutPassesAtRoot()); - param->setObj(model); - param->setLongHelp( - "The default is 100 passes if less than 500 columns, 100 passes (but stop if the drop is small) if less than 5000 columns, 20 otherwise."); - parameters.push_back(param); - - param = new CbcCbcParam(CbcCbcParam::GAPRATIO, - "ratio!Gap", - "Stop when the gap between the best possible solution and the incumbent is less than this fraction of the larger of the two", - 0.0, 1.0e20, model->getDblParam(CbcModel::CbcAllowableFractionGap)); - param->setPushFunc(pushCbcCbcDbl); - param->setObj(model); - param->setLongHelp( - "If the gap between the best solution and the best possible solution is less than this fraction of the objective value at the root node then the search will terminate. See 'allowableGap' for a way of using absolute value rather than fraction."); - parameters.push_back(param); - - param = new CbcCbcParam(CbcCbcParam::TIMELIMIT_BAB, - "sec!onds", "Maximum seconds for branch and cut", -1.0, 1.0e12); - param->setPushFunc(pushCbcCbcDbl); - param->setObj(model); - param->setLongHelp( - "After this many seconds the program will act as if maximum nodes had been reached."); - parameters.push_back(param); - - param = new CbcCbcParam(CbcCbcParam::STRONGBRANCHING, - "strong!Branching", - "Number of variables to look at in strong branching", 0, 999999, - model->numberStrong()); - param->setObj(model); - param->setLongHelp( - "In order to decide which variable to branch on, the code will choose up to this number of unsatisfied variables and try mini up and down branches. The most effective one is chosen. If a variable is branched on many times then the previous average up and down costs may be used - see number before trust."); - parameters.push_back(param); - - param = new CbcCbcParam(CbcCbcParam::NUMBERBEFORE, - "trust!PseudoCosts", "Number of branches before we trust pseudocosts", - -1, 2000000, model->numberBeforeTrust()); - param->setObj(model); - param->setPushFunc(pushCbcCbcInt); - param->setLongHelp( - "Using strong branching computes pseudo-costs. After this many times for a variable we just trust the pseudo costs and do not do any more strong branching."); - parameters.push_back(param); - - numberParameters = parameters.size(); - - assert(numberParameters <= parameters.capacity()); -} - -void loadCbcParamObj(const CoinParamVec paramVec, int first, int last, - CbcModel *obj) - -{ - int i; - - /* - Load the CbcModel object into the parameters - */ - for (i = first; i <= last; i++) { - CbcCbcParam *cbcParam = dynamic_cast< CbcCbcParam * >(paramVec[i]); - assert(cbcParam != 0); - cbcParam->setObj(obj); - } - - return; -} - -/* - Set CbcModel defaults appropriate for cbc-generic. -*/ - -void setCbcModelDefaults(CbcModel *model) - -{ - model->setIntParam(CbcModel::CbcMaxNumNode, (COIN_INT_MAX / 2)); - model->setIntParam(CbcModel::CbcMaxNumSol, 999999); - model->setIntParam(CbcModel::CbcFathomDiscipline, 0); - - model->setDblParam(CbcModel::CbcIntegerTolerance, 1.0e-6); - model->setDblParam(CbcModel::CbcInfeasibilityWeight, 0.0); - model->setDblParam(CbcModel::CbcCutoffIncrement, 1.0e-5); - model->setDblParam(CbcModel::CbcAllowableGap, 1.0e-10); - model->setDblParam(CbcModel::CbcAllowableFractionGap, 0.0); - // One year is 60x60x24x365 = 31,536,000 seconds. - model->setDblParam(CbcModel::CbcMaximumSeconds, 3.0e7); - model->setDblParam(CbcModel::CbcCurrentCutoff, 1.0e100); - model->setDblParam(CbcModel::CbcOptimizationDirection, 1.0); - model->setDblParam(CbcModel::CbcCurrentObjectiveValue, 1.0e100); - model->setDblParam(CbcModel::CbcCurrentMinimizationObjectiveValue, 1.0e100); - model->setDblParam(CbcModel::CbcStartSeconds, 0.0); - - model->setNumberBeforeTrust(5); - model->setNumberStrong(5); - - return; -} - -/* - Function to push a double parameter. -*/ - -int pushCbcCbcDbl(CoinParam *param) - -{ - assert(param != 0); - - CbcCbcParam *cbcParam = dynamic_cast< CbcCbcParam * >(param); - assert(cbcParam != 0); - - CbcModel *model = cbcParam->obj(); - double val = cbcParam->dblVal(); - CbcCbcParam::CbcCbcParamCode code = cbcParam->paramCode(); - - assert(model != 0); - - int retval = 0; - /* - Translate the parameter code from CbcCbcParamCode into the correct key for - CbcDblParam. - */ - CbcModel::CbcDblParam key; - switch (code) { - case CbcCbcParam::INTEGERTOLERANCE: { - key = CbcModel::CbcIntegerTolerance; - break; - } - case CbcCbcParam::INFEASIBILITYWEIGHT: { - key = CbcModel::CbcInfeasibilityWeight; - break; - } - case CbcCbcParam::INCREMENT: { - key = CbcModel::CbcCutoffIncrement; - break; - } - case CbcCbcParam::ALLOWABLEGAP: { - key = CbcModel::CbcAllowableGap; - break; - } - case CbcCbcParam::GAPRATIO: { - key = CbcModel::CbcAllowableFractionGap; - break; - } - case CbcCbcParam::TIMELIMIT_BAB: { - key = CbcModel::CbcMaximumSeconds; - break; - } - case CbcCbcParam::CUTOFF: { - key = CbcModel::CbcCurrentCutoff; - break; - } - default: { - std::cerr << "pushCbcCbcDbl: no equivalent CbcDblParam for " - << "parameter code `" << code << "'." << std::endl; - retval = -1; - break; - } - } - - bool result = model->setDblParam(key, val); - if (result == false) { - retval = -1; - } - - return (retval); -} - -/* - Function to push an integer parameter. -*/ - -int pushCbcCbcInt(CoinParam *param) - -{ - assert(param != 0); - - CbcCbcParam *cbcParam = dynamic_cast< CbcCbcParam * >(param); - assert(cbcParam != 0); - - CbcModel *model = cbcParam->obj(); - int val = cbcParam->intVal(); - CbcCbcParam::CbcCbcParamCode code = cbcParam->paramCode(); - - assert(model != 0); - - int retval = 0; - /* - Translate the parameter code from CbcCbcParamCode into the correct key for - CbcIntParam, or call the appropriate method directly. - */ - CbcModel::CbcIntParam key = CbcModel::CbcLastIntParam; - switch (code) { - case CbcCbcParam::CUTPASS: { - model->setMaximumCutPassesAtRoot(val); - break; - } - case CbcCbcParam::LOGLEVEL: { - CoinMessageHandler *hndl = model->messageHandler(); - assert(hndl != 0); - hndl->setLogLevel(val); - break; - } - case CbcCbcParam::NUMBERBEFORE: { - model->setNumberBeforeTrust(val); - break; - } - default: { - std::cerr << "pushCbcCbcInt: no equivalent CbcIntParam for " - << "parameter code `" << code << "'." << std::endl; - retval = -1; - break; - } - } - - if (key != CbcModel::CbcLastIntParam) { - bool result = model->setIntParam(key, val); - if (result == false) { - retval = -1; - } - } - - return (retval); -} - -} // end namespace CbcCbcParamUtils - -/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 -*/ diff --git a/src/CbcGenCtlBlk.cpp b/src/CbcGenCtlBlk.cpp deleted file mode 100644 index 1872f16dd..000000000 --- a/src/CbcGenCtlBlk.cpp +++ /dev/null @@ -1,682 +0,0 @@ -/* - Copyright (C) 2007, Lou Hafer, International Business Machines Corporation - and others. All Rights Reserved. - - This code is licensed under the terms of the Eclipse Public License (EPL). - -*/ -/* - This file is part of cbc-generic. -*/ - -#include "CbcGenConfig.h" -#include "CoinPragma.hpp" - -#include - -#include "CbcGenCtlBlk.hpp" - -namespace { - - -} - -/* - Constructor for cbc-generic control block. - - Set up defaults for the cbc-generic control block. Note that prototypes for - cut generators and heuristics will be created on demand; see the access - functions. - - Once this structure settles down, simple intialisation should move up to - the standard `:' block. In the meantime, this avoids complaints about - ordering. -*/ - -CbcGenCtlBlk::CbcGenCtlBlk() - -{ - version_ = CBC_GENERIC_VERSION; - /* - It's unclear to me that this is a good choice for dfltDirectory. Makes - sense for commands, but seems unnecessary for data files. Perhaps a null - string instead? - */ - char dirsep = CoinFindDirSeparator(); - dfltDirectory_ = (dirsep == '/' ? "./" : ".\\"); - lastMpsIn_ = ""; - allowImportErrors_ = false; - lastSolnOut_ = "stdout"; - printMode_ = 0; - printMask_ = ""; - - paramVec_ = 0; - genParams_.first_ = 0; - genParams_.last_ = 0; - cbcParams_.first_ = 0; - cbcParams_.last_ = 0; - osiParams_.first_ = 0; - osiParams_.last_ = 0; - - verbose_ = 0; - paramsProcessed_ = 0; - defaultSettings_ = true; - - debugCreate_ = ""; - debugFile_ = ""; - debugSol_.numCols_ = -1; - debugSol_.values_ = 0; - - printOpt_ = 0; - - /* - Assigning us_en to cur_lang_ is entirely bogus, but CoinMessages::Language - does not provide an `unspecified' code. - */ - msgHandler_ = new CoinMessageHandler(); - ourMsgHandler_ = true; - cur_lang_ = CoinMessages::us_en; - msgs_ = 0; - logLvl_ = 0; - - totalTime_ = 0.0; - - model_ = 0; - dfltSolver_ = 0; - goodModel_ = false; - bab_.majorStatus_ = BACInvalid; - bab_.minorStatus_ = BACmInvalid; - bab_.where_ = BACwInvalid; - bab_.haveAnswer_ = false; - bab_.answerSolver_ = 0; - - preProcess_ = CbcGenCtlBlk::IPPSOS; - cutDepth_ = -1; - - probing_.action_ = CbcGenCtlBlk::CGIfMove; - probing_.proto_ = 0; - probing_.usingObjective_ = true; - probing_.maxPass_ = 3; - probing_.maxPassRoot_ = 3; - probing_.maxProbe_ = 10; - probing_.maxProbeRoot_ = 50; - probing_.maxLook_ = 10; - probing_.maxLookRoot_ = 50; - probing_.maxElements_ = 200; - probing_.rowCuts_ = 3; - - clique_.action_ = CbcGenCtlBlk::CGIfMove; - clique_.proto_ = 0; - clique_.starCliqueReport_ = false; - clique_.rowCliqueReport_ = false; - clique_.minViolation_ = 0.1; - - flow_.action_ = CbcGenCtlBlk::CGIfMove; - flow_.proto_ = 0; - - gomory_.action_ = CbcGenCtlBlk::CGIfMove; - gomory_.proto_ = 0; - gomory_.limit_ = 50; - gomory_.limitAtRoot_ = 512; - - knapsack_.action_ = CbcGenCtlBlk::CGIfMove; - knapsack_.proto_ = 0; - - // landp_action_ = CbcGenCtlBlk::CGOff ; - // landp_.proto_ = 0 ; - - mir_.action_ = CbcGenCtlBlk::CGIfMove; - mir_.proto_ = 0; - - oddHole_.action_ = CbcGenCtlBlk::CGOff; - oddHole_.proto_ = 0; - - redSplit_.action_ = CbcGenCtlBlk::CGRoot; - redSplit_.proto_ = 0; - - twomir_.action_ = CbcGenCtlBlk::CGRoot; - twomir_.proto_ = 0; - twomir_.maxElements_ = 250; - - fpump_.action_ = CbcGenCtlBlk::CGOn; - fpump_.proto_ = 0; - - combine_.action_ = CbcGenCtlBlk::CGOn; - combine_.proto_ = 0; - combine_.trySwap_ = 1; - - greedyCover_.action_ = CbcGenCtlBlk::CGOn; - greedyCover_.proto_ = 0; - greedyEquality_.action_ = CbcGenCtlBlk::CGOn; - greedyEquality_.proto_ = 0; - - localTree_.action_ = CbcGenCtlBlk::CGOff; - localTree_.proto_ = 0; - localTree_.soln_ = 0; - localTree_.range_ = 10; - localTree_.typeCuts_ = 0; - localTree_.maxDiverge_ = 0; - localTree_.timeLimit_ = 10000; - localTree_.nodeLimit_ = 2000; - localTree_.refine_ = true; - - rounding_.action_ = CbcGenCtlBlk::CGOn; - rounding_.proto_ = 0; - - djFix_.action_ = false; - djFix_.threshold_ = 1.0e100; - - priorityAction_ = CbcGenCtlBlk::BPOff; - /* - The value for numBeforeTrust is as recommended by Achterberg. Cbc's - implementation doesn't really have a parameter equivalent to Achterberg's - dynamic limit on number of strong branching evaluations, so go with a fairly - large default. As of 06.12.16, the magic number for shadow price mode meant - `use shadow prices (penalties, I think) if there's no strong branching info'. - */ - chooseStrong_.numBeforeTrust_ = 8; - chooseStrong_.numStrong_ = 100; - chooseStrong_.shadowPriceMode_ = 1; - - return; -} - -/* - Note that we don't want to delete dfltSolver_ here because it's just a - copy of the pointer held in the solvers map over in CbcGenSolvers.cpp. -*/ -CbcGenCtlBlk::~CbcGenCtlBlk() - -{ - if (model_) - delete model_; - if (bab_.answerSolver_) - delete bab_.answerSolver_; - - if (probing_.proto_) - delete probing_.proto_; - if (clique_.proto_) - delete clique_.proto_; - if (flow_.proto_) - delete flow_.proto_; - if (gomory_.proto_) - delete gomory_.proto_; - if (knapsack_.proto_) - delete knapsack_.proto_; - if (mir_.proto_) - delete mir_.proto_; - if (oddHole_.proto_) - delete oddHole_.proto_; - if (redSplit_.proto_) - delete redSplit_.proto_; - if (twomir_.proto_) - delete twomir_.proto_; - - if (fpump_.proto_) - delete fpump_.proto_; - if (combine_.proto_) - delete combine_.proto_; - if (greedyCover_.proto_) - delete greedyCover_.proto_; - if (greedyEquality_.proto_) - delete greedyEquality_.proto_; - if (rounding_.proto_) - delete rounding_.proto_; - - if (msgHandler_ && ourMsgHandler_) - delete msgHandler_; - if (msgs_) - delete msgs_; - - return; -} - -/* - Access functions for cut generators and heuristics. These support lazy - creation --- if action_ is other than CGOff, an object is created if - necessary and a pointer is stored in proto_. The pointer is returned as - a generic CglCutGenerator or CbcHeuristic. The return value of the function - is the value of action_. - - Because the model may have changed, the default for heuristics is to delete - any existing object and create a new one. This can be suppressed if desired. -*/ - -CbcGenCtlBlk::CGControl CbcGenCtlBlk::getProbing(CglCutGenerator *&gen) - -{ - if (probing_.action_ != CbcGenCtlBlk::CGOff && probing_.proto_ == 0) { - probing_.proto_ = new CglProbing(); - probing_.proto_->setUsingObjective(probing_.usingObjective_); - probing_.proto_->setMaxPass(probing_.maxPass_); - probing_.proto_->setMaxPassRoot(probing_.maxPassRoot_); - probing_.proto_->setMaxProbe(probing_.maxProbe_); - probing_.proto_->setMaxProbeRoot(probing_.maxProbeRoot_); - probing_.proto_->setMaxLook(probing_.maxLook_); - probing_.proto_->setMaxLookRoot(probing_.maxLookRoot_); - probing_.proto_->setMaxElements(probing_.maxElements_); - probing_.proto_->setRowCuts(probing_.rowCuts_); - } - gen = dynamic_cast< CglCutGenerator * >(probing_.proto_); - - return (probing_.action_); -} - -CbcGenCtlBlk::CGControl CbcGenCtlBlk::getClique(CglCutGenerator *&gen) - -{ - if (clique_.action_ != CbcGenCtlBlk::CGOff && clique_.proto_ == 0) { - clique_.proto_ = new CglClique(); - clique_.proto_->setStarCliqueReport(clique_.starCliqueReport_); - clique_.proto_->setRowCliqueReport(clique_.rowCliqueReport_); - clique_.proto_->setMinViolation(clique_.minViolation_); - } - gen = dynamic_cast< CglCutGenerator * >(clique_.proto_); - - return (clique_.action_); -} - -CbcGenCtlBlk::CGControl CbcGenCtlBlk::getFlow(CglCutGenerator *&gen) - -{ - if (flow_.action_ != CbcGenCtlBlk::CGOff && flow_.proto_ == 0) { - flow_.proto_ = new CglFlowCover(); - } - gen = dynamic_cast< CglCutGenerator * >(flow_.proto_); - - return (flow_.action_); -} - -CbcGenCtlBlk::CGControl CbcGenCtlBlk::getGomory(CglCutGenerator *&gen) - -{ - if (gomory_.action_ != CbcGenCtlBlk::CGOff && gomory_.proto_ == 0) { - gomory_.proto_ = new CglGomory(); - gomory_.proto_->setLimitAtRoot(gomory_.limitAtRoot_); - gomory_.proto_->setLimit(gomory_.limit_); - } - gen = dynamic_cast< CglCutGenerator * >(gomory_.proto_); - - return (gomory_.action_); -} - -CbcGenCtlBlk::CGControl CbcGenCtlBlk::getKnapsack(CglCutGenerator *&gen) - -{ - if (knapsack_.action_ != CbcGenCtlBlk::CGOff && knapsack_.proto_ == 0) { - knapsack_.proto_ = new CglKnapsackCover(); - } - gen = dynamic_cast< CglCutGenerator * >(knapsack_.proto_); - - return (knapsack_.action_); -} - -CbcGenCtlBlk::CGControl CbcGenCtlBlk::getMir(CglCutGenerator *&gen) - -{ - if (mir_.action_ != CbcGenCtlBlk::CGOff && mir_.proto_ == 0) { - mir_.proto_ = new CglMixedIntegerRounding2(); - } - gen = dynamic_cast< CglCutGenerator * >(mir_.proto_); - - return (mir_.action_); -} - -CbcGenCtlBlk::CGControl CbcGenCtlBlk::getRedSplit(CglCutGenerator *&gen) - -{ - if (redSplit_.action_ != CbcGenCtlBlk::CGOff && redSplit_.proto_ == 0) { - redSplit_.proto_ = new CglRedSplit(); - } - gen = dynamic_cast< CglCutGenerator * >(redSplit_.proto_); - - return (redSplit_.action_); -} - -CbcGenCtlBlk::CGControl CbcGenCtlBlk::getTwomir(CglCutGenerator *&gen) - -{ - if (twomir_.action_ != CbcGenCtlBlk::CGOff && twomir_.proto_ == 0) { - twomir_.proto_ = new CglTwomir(); - twomir_.proto_->setMaxElements(twomir_.maxElements_); - } - gen = dynamic_cast< CglCutGenerator * >(twomir_.proto_); - - return (twomir_.action_); -} - -CbcGenCtlBlk::CGControl -CbcGenCtlBlk::getFPump(CbcHeuristic *&gen, CbcModel *model, - bool alwaysCreate) - -{ - if (fpump_.action_ != CbcGenCtlBlk::CGOff && (fpump_.proto_ == 0 || alwaysCreate)) { - if (fpump_.proto_) { - delete fpump_.proto_; - } - fpump_.proto_ = new CbcHeuristicFPump(*model); - fpump_.proto_->setMaximumPasses(fpump_.iters_); - } - gen = dynamic_cast< CbcHeuristic * >(fpump_.proto_); - - return (fpump_.action_); -} - -CbcGenCtlBlk::CGControl -CbcGenCtlBlk::getCombine(CbcHeuristic *&gen, CbcModel *model, - bool alwaysCreate) - -{ - if (combine_.action_ != CbcGenCtlBlk::CGOff && (combine_.proto_ == 0 || alwaysCreate)) { - if (combine_.proto_) { - delete combine_.proto_; - } - combine_.proto_ = new CbcHeuristicLocal(*model); - combine_.proto_->setSearchType(combine_.trySwap_); - } - gen = dynamic_cast< CbcHeuristic * >(combine_.proto_); - - return (combine_.action_); -} - -CbcGenCtlBlk::CGControl -CbcGenCtlBlk::getGreedyCover(CbcHeuristic *&gen, CbcModel *model, - bool alwaysCreate) - -{ - if (greedyCover_.action_ != CbcGenCtlBlk::CGOff && (greedyCover_.proto_ == 0 || alwaysCreate)) { - if (greedyCover_.proto_) { - delete greedyCover_.proto_; - } - greedyCover_.proto_ = new CbcHeuristicGreedyCover(*model); - } - gen = dynamic_cast< CbcHeuristic * >(greedyCover_.proto_); - - return (greedyCover_.action_); -} - -CbcGenCtlBlk::CGControl -CbcGenCtlBlk::getGreedyEquality(CbcHeuristic *&gen, CbcModel *model, - bool alwaysCreate) - -{ - if (greedyEquality_.action_ != CbcGenCtlBlk::CGOff && (greedyEquality_.proto_ == 0 || alwaysCreate)) { - if (greedyEquality_.proto_) { - delete greedyEquality_.proto_; - } - greedyEquality_.proto_ = new CbcHeuristicGreedyEquality(*model); - } - gen = dynamic_cast< CbcHeuristic * >(greedyEquality_.proto_); - - return (greedyEquality_.action_); -} - -CbcGenCtlBlk::CGControl -CbcGenCtlBlk::getRounding(CbcHeuristic *&gen, CbcModel *model, - bool alwaysCreate) - -{ - if (rounding_.action_ != CbcGenCtlBlk::CGOff && (rounding_.proto_ == 0 || alwaysCreate)) { - if (rounding_.proto_) { - delete rounding_.proto_; - } - rounding_.proto_ = new CbcRounding(*model); - } - gen = dynamic_cast< CbcHeuristic * >(rounding_.proto_); - - return (rounding_.action_); -} - -CbcGenCtlBlk::CGControl -CbcGenCtlBlk::getTreeLocal(CbcTreeLocal *&localTree, CbcModel *model, - bool alwaysCreate) - -{ - if (localTree_.action_ != CbcGenCtlBlk::CGOff && (localTree_.proto_ == 0 || alwaysCreate)) { - if (localTree_.proto_) { - delete localTree_.proto_; - } - localTree_.proto_ = new CbcTreeLocal(model, localTree_.soln_, localTree_.range_, - localTree_.typeCuts_, localTree_.maxDiverge_, - localTree_.timeLimit_, localTree_.nodeLimit_, - localTree_.refine_); - } - localTree = localTree_.proto_; - - return (localTree_.action_); -} - -/* - A bunch of little translation helper routines leading up to a version of - setBaBStatus that figures it all out given a CbcModel and BACWhere code. - This translation needs to be centralised to avoid sprinkling magic numbers - all through the code. - - Be a bit careful with the translation routines --- they aren't sensitive to - where the search stopped. -*/ - -CbcGenCtlBlk::BACMajor CbcGenCtlBlk::translateMajor(int status) - -{ - switch (status) { - case -1: { - return (BACNotRun); - } - case 0: { - return (BACFinish); - } - case 1: { - return (BACStop); - } - case 2: { - return (BACAbandon); - } - case 5: { - return (BACUser); - } - default: { - return (BACInvalid); - } - } -} - -CbcGenCtlBlk::BACMinor CbcGenCtlBlk::translateMinor(int status) - -{ - switch (status) { - case -1: { - return (BACmInvalid); - } - case 0: { - return (BACmFinish); - } - case 1: { - return (BACmInfeas); - } - case 2: { - return (BACmGap); - } - case 3: { - return (BACmNodeLimit); - } - case 4: { - return (BACmTimeLimit); - } - case 5: { - return (BACmUser); - } - case 6: { - return (BACmSolnLimit); - } - case 7: { - return (BACmUbnd); - } - default: { - return (BACmOther); - } - } -} - -/* - A bit different --- given an OSI, use its interrogation functions to choose - an appropriate BACMinor code. Not everything matches up, eh? -*/ -CbcGenCtlBlk::BACMinor -CbcGenCtlBlk::translateMinor(const OsiSolverInterface *osi) - -{ - if (osi->isProvenOptimal()) { - return (BACmFinish); - } else if (osi->isProvenPrimalInfeasible()) { - return (BACmInfeas); - } else if (osi->isProvenDualInfeasible()) { - return (BACmUbnd); - } else { - return (BACmOther); - } -} - -/* - A routine to set the bab_ status block given a CbcModel and an indication - of where we're at in the search. Really, this is just a big mapping from - CbcModel codes to CbcGeneric codes. -*/ - -void CbcGenCtlBlk::setBaBStatus(const CbcModel *model, BACWhere where, - bool haveAnswer, - OsiSolverInterface *answerSolver) - -{ - CbcGenCtlBlk::BACMajor major; - CbcGenCtlBlk::BACMinor minor; - - major = translateMajor(model->status()); - - if (where == CbcGenCtlBlk::BACwBareRoot || where == CbcGenCtlBlk::BACwIPPRelax) { - minor = translateMinor(model->solver()); - } else { - minor = translateMinor(model->secondaryStatus()); - } - - setBaBStatus(major, minor, where, haveAnswer, answerSolver); - - return; -} - -/* - Last, but not least, a routine to print the result. -*/ - -void CbcGenCtlBlk::printBaBStatus() - -{ - std::cout << "BAC result: stopped "; - - switch (bab_.where_) { - case BACwNotStarted: { - std::cout << "before root relaxation"; - break; - } - case BACwBareRoot: { - std::cout << "after root relaxation"; - break; - } - case BACwIPP: { - std::cout << "after integer preprocessing"; - break; - } - case BACwIPPRelax: { - std::cout << "after solving preprocessed relaxation"; - break; - } - case BACwBAC: { - std::cout << "after branch-and-cut"; - break; - } - default: { - std::cout << "!!invalid phase code!!"; - break; - } - } - - std::cout << std::endl - << " Branch-and-cut "; - - switch (bab_.majorStatus_) { - case BACNotRun: { - std::cout << "never got started"; - break; - } - case BACFinish: { - std::cout << "finished"; - break; - } - case BACStop: { - std::cout << "stopped on a limit"; - break; - } - case BACAbandon: { - std::cout << "was abandoned"; - break; - } - case BACUser: { - std::cout << "stopped due to a user event"; - break; - } - default: { - std::cout << "!!invalid major status code!!"; - break; - } - } - - std::cout << "; minor status is "; - - switch (bab_.minorStatus_) { - case BACmFinish: { - std::cout << "optimal"; - break; - } - case BACmInfeas: { - std::cout << "infeasible"; - break; - } - case BACmUbnd: { - std::cout << "unbounded"; - break; - } - case BACmGap: { - std::cout << "reached specified integrality gap."; - break; - } - case BACmNodeLimit: { - std::cout << "reached node limit"; - break; - } - case BACmTimeLimit: { - std::cout << "reached time limit"; - break; - } - case BACmSolnLimit: { - std::cout << "reached limit on number of solutions"; - break; - } - case BACmUser: { - std::cout << "stopped due to a user event"; - break; - } - case BACmOther: { - std::cout << "other"; - break; - } - default: { - std::cout << "!!invalid minor status code!!"; - break; - } - } - - std::cout << "." << std::endl; -} - -/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 -*/ diff --git a/src/CbcGenCtlBlk.hpp b/src/CbcGenCtlBlk.hpp deleted file mode 100644 index 07c1d5844..000000000 --- a/src/CbcGenCtlBlk.hpp +++ /dev/null @@ -1,1000 +0,0 @@ -/* - Copyright (C) 2007, Lou Hafer, International Business Machines Corporation - and others. All Rights Reserved. - - This code is licensed under the terms of the Eclipse Public License (EPL). - -*/ -/* - This file is part of cbc-generic. -*/ - -#ifndef CbcGenCtlBlk_H -#define CbcGenCtlBlk_H - -/* \file CbcGenCtlBlk.hpp - \brief Declarations for parameters of the cbc-generic main program. -*/ - -#include "CoinParam.hpp" -#include "CoinMessageHandler.hpp" - -#include "CglCutGenerator.hpp" -#include "CglProbing.hpp" -#include "CglClique.hpp" -#include "CglFlowCover.hpp" -#include "CglGomory.hpp" -#include "CglKnapsackCover.hpp" -#include "CglMixedIntegerRounding2.hpp" -#include "CglOddHole.hpp" -#include "CglRedSplit.hpp" -#include "CglTwomir.hpp" - -#include "CbcModel.hpp" - -#include "CbcHeuristic.hpp" -#include "CbcHeuristicFPump.hpp" -#include "CbcHeuristicGreedy.hpp" -#include "CbcHeuristicLocal.hpp" -#include "CbcTreeLocal.hpp" - -#include "CbcGenMessages.hpp" - -/* - It turns out that doxygen is not good with anonymous structures. Hence the - `struct nameCtl_struct' style used for structured fields in CbcGenCtlBlk. -*/ - -/* -*/ - -#define CBC_GENERIC_VERSION "00.01.00" - -class CbcGenCtlBlk; -namespace CbcGenParamUtils { -void addCbcGenParams(int &numParams, CoinParamVec ¶mVec, - CbcGenCtlBlk *ctlBlk); -} - -/* \brief cbc-generic algorithm control class - - This class defines values and methods used to control the operation of the - cbc-generic main program. -*/ - -class CbcGenCtlBlk { - - friend void CbcGenParamUtils::addCbcGenParams(int &numParams, - CoinParamVec ¶mVec, CbcGenCtlBlk *ctlBlk); - -public: - /*! \name Enumeration types used for cbc-generic control variables */ - //@{ - - /* - In order for initialisation to work properly, the order of declaration of - the enum constants here must match the order of keyword declaration for - the PREPROCESS parameter in CbcGenParamUtils::addCbcGenParams - */ - /*! \brief Codes to control integer preprocessing - - - IPPOff: Integer preprocessing is off. - - IPPOn: Integer preprocessing is on. - - IPPSave: IPPOn, plus preprocessed system will be saved to presolved.mps. - - IPPEqual: IPPOn, plus `<=' cliques are converted to `=' cliques. - - IPPSOS: IPPOn, plus will create SOS sets (see below). - - IPPTrySOS: IPPOn, plus will create SOS sets (see below). - - IPPEqualAll: IPPOn, plus turns all valid inequalities into equalities - with integer slacks. - - IPPStrategy: look to CbcStrategy object for instructions. - - IPPSOS will create SOS sets if all binary variables (except perhaps one) - can be covered by SOS sets with no overlap between sets. IPPTrySOS will - allow any number of binary variables to be uncovered. - */ - - typedef enum { IPPOff = 0, - IPPOn, - IPPSave, - IPPEqual, - IPPSOS, - IPPTrySOS, - IPPEqualAll, - IPPStrategy - } IPPControl; - - /* - In order for initialisation to work properly, the order of declaration of - the enum constants here must match the order of keyword declaration for - the various cut and heuristic control parameters in - CbcGenParamUtils::addCbcGenParams - */ - /*! \brief Codes to control the use of cut generators and heuristics - - - CGOff: the cut generator will not be installed - - CGOn: the cut generator will be installed; exactly how often it's - activated depends on the settings at installation - - CGRoot: the cut generator will be installed with settings that restrict - it to activation at the root node only. - - CGIfMove: the cut generator will be installed with settings that allow - it to remain active only so long as it's generating cuts that - tighten the relaxation. - - CGForceOn: the cut generator will be installed with settings that force - it to be called at every node - - CGForceBut: the cut generator will be installed with settings that force - it to be called at every node, but more active at root (probing - only) - - CGMarker: a convenience to mark the end of the codes. - - The same codes are used for heuristics. - */ - - typedef enum { CGOff, - CGOn, - CGRoot, - CGIfMove, - CGForceOn, - CGForceBut, - CGMarker - } CGControl; - - /*! \brief Codes to specify the assignment of branching priorities - - - BPOff: no priorities are passed to cbc - - BPCost: a priority vector is constructed based on objective coefficients - - BPOrder: a priority vector is constructed based on column order - - BPExt: the user has provided a priority vector - */ - - typedef enum { BPOff, - BPCost, - BPOrder, - BPExt } BPControl; - - /*! \brief Major status codes for branch-and-cut - - - BACInvalid: status not yet set - - BACNotRun: branch-and-cut has not yet run for the current problem - - BACFinish: branch-and-cut has finished normally - - BACStop: branch-and-cut has stopped on a limit - - BACAbandon: branch-and-cut abandoned the problem - - BACUser: branch-and-cut stopped on user signal - - Consult minorStatus_ for details. - - These codes are (mostly) set to match the codes used by CbcModel. Additions - to CbcModel codes should be reflected here and in translateMajor. - */ - - typedef enum { BACInvalid = -1, - BACFinish = 0, - BACStop = 1, - BACAbandon = 2, - BACNotRun, - BACUser = 5 - } BACMajor; - - /*! \brief Minor status codes - - - BACmInvalid status not yet set - - BACmFinish search exhausted the tree; optimal solution found - - BACmInfeas problem is infeasible - - BACmUbnd problem is unbounded - - BACmGap stopped on integrality gap - - BACmNodeLimit stopped on node limit - - BACmTimeLimit stopped on time limit - - BACmSolnLimit stopped on number of solutions limit - - BACmUser stopped due to user event - - BACmOther nothing else is appropriate - - It's not possible to make these codes agree with CbcModel. The meaning varies - according to context: if the BACWhere code specifies a relaxation, then the - minor status reflects the underlying OSI solver. Otherwise, it reflects the - integer problem. - */ - - typedef enum { BACmInvalid = -1, - BACmFinish = 0, - BACmInfeas, - BACmUbnd, - BACmGap, - BACmNodeLimit, - BACmTimeLimit, - BACmSolnLimit, - BACmUser, - BACmOther - } BACMinor; - - /*! \brief Codes to specify where branch-and-cut stopped - - - BACwNotStarted stopped before we ever got going - - BACwBareRoot stopped after initial solve of root relaxation - - BACwIPP stopped after integer preprocessing - - BACwIPPRelax stopped after initial solve of preprocessed problem - - BACwBAC stopped at some point in branch-and-cut - */ - - typedef enum { BACwInvalid = -1, - BACwNotStarted = 0, - BACwBareRoot, - BACwIPP, - BACwIPPRelax, - BACwBAC - } BACWhere; - - //@} - - /*! \name Constructors and destructors */ - //@{ - - /*! \brief Default constructor */ - - CbcGenCtlBlk(); - - /*! \brief Destructor */ - - ~CbcGenCtlBlk(); - //@} - - /*! \name Access and Control Functions for Cut Generators and Heuristics - \brief Control functions, plus lazy creation functions for cut generators - and heuristics - - cbc-generic avoids creating objects for cut generators and heuristics - unless they're actually used. For cut generators, a prototype is created - and reused. For heuristics, the default is to create a new object with each - call, because the model may have changed. The object is returned through - the reference parameter. The return value of the function is the current - action state. - - Cut generator and heuristic objects created by these calls will be deleted - with the destruction of the CbcGenCtlBlk object. - */ - //@{ - - /*! \brief Get cut depth setting - - The name is a bit of a misnomer. Essentially, this overrides the - `every so many nodes' control with `execute when (depth in tree) - mod (cut depth) == 0'. - */ - - inline int getCutDepth() - { - return cutDepth_; - } - - /*! \brief Set cut depth setting. - - See comments for getCutDepth(). - */ - - inline void setCutDepth(int cutDepth) - { - cutDepth_ = cutDepth; - } - - /*1 \brief Get action state for use of integer preprocessing */ - - inline IPPControl getIPPAction() - { - return (preProcess_); - } - - /*! \brief Set action state for use of integer preprocessing */ - - inline void setIPPAction(IPPControl action) - { - preProcess_ = action; - } - - /*! \brief Obtain a prototype for a probing cut generator. */ - - CGControl getProbing(CglCutGenerator *&gen); - - /*! \brief Set action state for use of probing cut generator. */ - - inline void setProbingAction(CGControl action) - { - probing_.action_ = action; - } - - /*! \brief Obtain a prototype for a clique cut generator. */ - - CGControl getClique(CglCutGenerator *&gen); - - /*! \brief Set action state for use of clique cut generator. */ - - inline void setCliqueAction(CGControl action) - { - clique_.action_ = action; - } - - /*! \brief Obtain a prototype for a flow cover cut generator. */ - - CGControl getFlow(CglCutGenerator *&gen); - - /*! \brief Set action state for use of flow cover cut generator. */ - - inline void setFlowAction(CGControl action) - { - flow_.action_ = action; - } - - /*! \brief Obtain a prototype for a Gomory cut generator. */ - - CGControl getGomory(CglCutGenerator *&gen); - - /*! \brief Set action state for use of Gomory cut generator. */ - - inline void setGomoryAction(CGControl action) - { - gomory_.action_ = action; - } - - /*! \brief Obtain a prototype for a knapsack cover cut generator. */ - - CGControl getKnapsack(CglCutGenerator *&gen); - - /*! \brief Set action state for use of knapsack cut generator. */ - - inline void setKnapsackAction(CGControl action) - { - knapsack_.action_ = action; - } - - /* \brief Obtain a prototype for a lift-and-project cut generator. - - CGControl getLandP(CglCutGenerator *&gen) ; - - \brief Set action state for use of lift-and-project cut generator. - - inline void setLandPAction(CGControl action) - { landp_.action_ = action ; } - */ - - /*! \brief Obtain a prototype for a mixed integer rounding (MIR) - cut generator. - */ - - CGControl getMir(CglCutGenerator *&gen); - - /*! \brief Set action state for use of MIR cut generator. */ - - inline void setMirAction(CGControl action) - { - mir_.action_ = action; - } - - /*! \brief Obtain a prototype for a reduce and split cut generator. */ - - CGControl getRedSplit(CglCutGenerator *&gen); - - /*! \brief Set action state for use of reduce and split cut generator. */ - - inline void setRedSplitAction(CGControl action) - { - redSplit_.action_ = action; - } - - /*! \brief Obtain a prototype for a 2-MIR cut generator. */ - - CGControl getTwomir(CglCutGenerator *&gen); - - /*! \brief Set action state for use of 2-MIR cut generator. */ - - inline void setTwomirAction(CGControl action) - { - twomir_.action_ = action; - } - - /*! \brief Obtain a feasibility pump heuristic. - - By default, any existing object is deleted and a new object is created and - loaded with \c model. Set alwaysCreate = false to return an existing object - if one exists. - */ - - CGControl getFPump(CbcHeuristic *&gen, CbcModel *model, - bool alwaysCreate = true); - - /*! \brief Set action state for use of feasibility pump heuristic. */ - - inline void setFPumpAction(CGControl action) - { - fpump_.action_ = action; - } - - /*! \brief Obtain a local search/combine heuristic. - - By default, any existing object is deleted and a new object is created and - loaded with \c model. Set alwaysCreate = false to return an existing object - if one exists. - */ - - CGControl getCombine(CbcHeuristic *&gen, CbcModel *model, - bool alwaysCreate = true); - - /*! \brief Set action state for use of local search/combine heuristic. */ - - inline void setCombineAction(CGControl action) - { - combine_.action_ = action; - } - - /*! \brief Obtain a greedy cover heuristic. - - By default, any existing object is deleted and a new object is created and - loaded with \c model. Set alwaysCreate = false to return an existing object - if one exists. - */ - - CGControl getGreedyCover(CbcHeuristic *&gen, CbcModel *model, - bool alwaysCreate = true); - - /*! \brief Set action state for use of greedy cover heuristic. */ - - inline void setGreedyCoverAction(CGControl action) - { - greedyCover_.action_ = action; - } - - /*! \brief Obtain a greedy equality heuristic. - - By default, any existing object is deleted and a new object is created and - loaded with \c model. Set alwaysCreate = false to return an existing object - if one exists. - */ - - CGControl getGreedyEquality(CbcHeuristic *&gen, CbcModel *model, - bool alwaysCreate = true); - - /*! \brief Set action state for use of greedy equality heuristic. */ - - inline void setGreedyEqualityAction(CGControl action) - { - greedyEquality_.action_ = action; - } - - /*! \brief Obtain a simple rounding heuristic. - - By default, any existing object is deleted and a new object is created and - loaded with \c model. Set alwaysCreate = false to return an existing object - if one exists. - */ - - CGControl getRounding(CbcHeuristic *&gen, CbcModel *model, - bool alwaysCreate = true); - - /*! \brief Set action state for use of simple rounding heuristic. */ - - inline void setRoundingAction(CGControl action) - { - rounding_.action_ = action; - } - - /*! \brief Obtain a local search tree object - - By default, any existing object is deleted and a new object is created and - loaded with \c model. Set alwaysCreate = false to return an existing object - if one exists. - */ - - CGControl getTreeLocal(CbcTreeLocal *&localTree, CbcModel *model, - bool alwaysCreate = true); - - /*! \brief Set action state for use of local tree. */ - - inline void setTreeLocalAction(CGControl action) - { - localTree_.action_ = action; - } - - //@} - - /*! \name Status Functions - \brief Convenience routines for status codes. - */ - //@{ - - /*! \brief Set the result of branch-and-cut search */ - - inline void setBaBStatus(BACMajor majorStatus, BACMinor minorStatus, - BACWhere where, bool haveAnswer, - OsiSolverInterface *answerSolver) - { - bab_.majorStatus_ = majorStatus; - bab_.minorStatus_ = minorStatus; - bab_.where_ = where; - bab_.haveAnswer_ = haveAnswer; - bab_.answerSolver_ = answerSolver; - } - - /*! \brief Set the result of branch-and-cut search - - This version will extract the necessary information from the CbcModel - object and set appropriate status based on the value passed for where. - */ - void setBaBStatus(const CbcModel *model, BACWhere where, - bool haveAnswer = false, - OsiSolverInterface *answerSolver = 0); - - /*! \brief Translate CbcModel major status to #BACMajor - - See the #BACMajor enum for details. - */ - BACMajor translateMajor(int status); - - /*!\brief Translate CbcModel minor status to #BACMinor - - See the #BACMinor enum for details. - */ - BACMinor translateMinor(int status); - - /*!\brief Translate OsiSolverInterface status to #BACMinor - - See the #BACMinor enum for details. Optimal, infeasible, and unbounded - get their own codes; everything else maps to BACmOther. - */ - BACMinor translateMinor(const OsiSolverInterface *osi); - - /*! \brief Print the status block */ - - void printBaBStatus(); - - //@} - - /*! \name Messages and statistics */ - //@{ - - /*! \brief Print a message - - Uses the current message handler and messages. - */ - CoinMessageHandler &message(CbcGenMsgCode inID); - - /*! \brief Supply a new message handler. - - Replaces the current message handler. The current handler is destroyed - if ourMsgHandler_ is true, and the call will set ourMsgHandler_ = true. - */ - void passInMessageHandler(CoinMessageHandler *handler); - - /*! \brief Return a pointer to the message handler */ - inline CoinMessageHandler *messageHandler() const - { - return msgHandler_; - } - - /*! \brief Set up messages in the specified language. - - Building a set of messages in a given language implies rebuilding the - whole set of messages, for reasons explained in the body of the code. - Hence there's no separate setLanguage routine. Use this routine for the - initial setup of messages and any subsequent change in language. Note - that the constructor gives you a message handler by default, but \e not - messages. You need to call setMessages explicitly. - - The default value specified here for lang effectively sets the default - language. - */ - void setMessages(CoinMessages::Language lang = CoinMessages::us_en); - - /*! \brief Set log level */ - inline void setLogLevel(int lvl) - { - logLvl_ = lvl; - if (msgHandler_) - msgHandler_->setLogLevel(lvl); - } - - /*! \brief Get log level */ - inline int logLevel() const - { - return (logLvl_); - } - - /*! \brief When greater than 0, integer presolve gives more information and - branch-and-cut provides statistics. - */ - int printOpt_; - - //@} - - /*! \name Parameter parsing and input/output. */ - //@{ - /*! \brief cbc-generic version */ - - std::string version_; - - /*! \brief Default directory prefix */ - - std::string dfltDirectory_; - - /*! \brief Last MPS input file */ - - std::string lastMpsIn_; - - /*! \brief Allow/disallow errors when importing a model */ - bool allowImportErrors_; - - /*! \brief Last solution output file */ - - std::string lastSolnOut_; - - /*! \brief Solution printing mode - - Controls the amount of information printed when printing a solution. - Coding is set by the keyword declarations for the printingOptions - command. - */ - int printMode_; - - /*! \brief Print mask - - Used to specify row/column names to be printed. Not implemented as of - 060920. - */ - std::string printMask_; - - /*! \brief The parameter vector */ - - CoinParamVec *paramVec_; - - /*! \brief Start and end of cbc-generic parameters in parameter vector */ - - struct genParamsInfo_struct { - int first_; - int last_; - } genParams_; - - /*! \brief Start and end of CbcModel parameters in parameter vector */ - - struct cbcParamsInfo_struct { - int first_; - int last_; - } cbcParams_; - - /*! \brief Start and end of OsiSolverInterface parameters in parameter - vector - */ - - struct osiParamsInfo_struct { - int first_; - int last_; - } osiParams_; - - /*! \brief Verbosity level for help messages. - - Interpretation is bitwise: - - (0): short help - - (1): long help - - (2): unused (for compatibility with cbc; indicates AMPL) - - (3): show parameters with display = false. - */ - - int verbose_; - - /*! \brief Number of parameters processed */ - - int paramsProcessed_; - - /*! \brief Record of parameters changed by user command */ - - std::vector< bool > setByUser_; - - /*! \brief False if the user has made nontrivial modifications to the - default control settings. - - Initially true. Specifying DJFIX, TIGHTENFACTOR, or any cut or heuristic - parameter will set this to false. - */ - bool defaultSettings_; - - /*! \brief Control debug file creation - - At the conclusion of branch-and-cut, dump the full solution in a binary - format to debug.file in the current directory. When set to - "createAfterPre", the solution is dumped before integer presolve - transforms are removed. When set to "create", the solution is dumped - after integer presolve transforms are backed out. - */ - std::string debugCreate_; - - /*! \brief Last debug input file - - The file is expected to be in a binary format understood by - activateRowCutDebugger. - */ - - std::string debugFile_; - - /*! \brief Array of primal variable values for debugging - - Used to provide a known optimal solution to activateRowCutDebugger(). - */ - - struct debugSolInfo_struct { - int numCols_; - double *values_; - } debugSol_; - //@} - - /* \name Timing */ - //@{ - - /*! \brief Total elapsed time for this run. */ - - double totalTime_; - - //@} - - /*! \name Models of various flavours */ - //@{ - - /*! \brief The reference CbcModel object. - - This is the CbcModel created when cbc-generic boots up. It holds the - default solver with the current constraint system. CbcCbcParam parameters - are applied here, and CbcOsiParam parameters are applied to the solver. - Major modifications for branch-and-cut (integer preprocessing, - installation of heuristics and cut generators) are performed on a clone. - The solution is transferred back into this object. - */ - - CbcModel *model_; - - /*! \brief The current default LP solver - - This is a pointer to a reference copy. If you want the solver associated - with #model_, ask for it directly. - */ - - OsiSolverInterface *dfltSolver_; - - /*! \brief True if we have a valid model loaded, false otherwise. */ - - bool goodModel_; - - /*! \brief State of branch-and-cut - - Major and minor status codes, and a solver holding the answer, assuming - we have a valid answer. See the documentation with the BACMajor, - BACMinor, and BACWhere enums for the meaning of the codes. - */ - - struct babState_struct { - BACMajor majorStatus_; - BACMinor minorStatus_; - BACWhere where_; - bool haveAnswer_; - OsiSolverInterface *answerSolver_; - } bab_; - - //@} - - /*! \name Various algorithm control variables and settings */ - //@{ - - /*! \brief Control use of reduced cost fixing prior to B&C - - This heuristic fixes variables whose reduced cost for the root - relaxtion exceeds the specified threshold. This is purely a heuristic, - performed before there's any incumbent solution. It may well fix variables - at the wrong bound! - */ - - struct djFixCtl_struct { - bool action_; - double threshold_; - } djFix_; - - /*! \brief Control the assignment of branching priorities to integer - variables. - */ - BPControl priorityAction_; - - //@} - - /*! \name Branching Method Control - \brief Usage control and prototypes for branching methods. - - Looking to the future, this covers only OsiChoose methods. - */ - //@{ - - /*! \brief Control variables for a strong branching method. - - Consult OsiChooseVariable and CbcModel for details. An artifact of the - changeover from CbcObjects to OsiObjects is that the number of uses before - pseudo costs are trusted (numBeforeTrust_) and the number of variables - evaluated with strong branching (numStrong_) are parameters of CbcModel. - */ - struct chooseStrongCtl_struct { - int numBeforeTrust_; - int numStrong_; - int shadowPriceMode_; - } chooseStrong_; - //@} - -private: - /*! \name Cut Generator and Heuristic Control - \brief Usage control and prototypes for cut generators and heuristics. - */ - //@{ - - /*! \brief Control integer preprocessing. */ - - IPPControl preProcess_; - - /*! \brief Control cut generator activity - - Generators that are active in the tree will be activated when - (depth) mod (cutDepth) == 0. - */ - - int cutDepth_; - - /*! \brief Control variable and prototype for probing cut generator */ - struct probingCtl_struct { - CGControl action_; - CglProbing *proto_; - bool usingObjective_; - int maxPass_; - int maxPassRoot_; - int maxProbe_; - int maxProbeRoot_; - int maxLook_; - int maxLookRoot_; - int maxElements_; - int rowCuts_; - } probing_; - - /*! \brief Control variable and prototype for clique cut generator */ - struct cliqueCtl_struct { - CGControl action_; - CglClique *proto_; - bool starCliqueReport_; - bool rowCliqueReport_; - double minViolation_; - } clique_; - - /*! \brief Control variable and prototype for flow cover cut generator */ - struct flowCtl_struct { - CGControl action_; - CglFlowCover *proto_; - } flow_; - - /*! \brief Control variable and prototype for Gomory cut generator */ - struct gomoryCtl_struct { - CGControl action_; - CglGomory *proto_; - int limit_; - int limitAtRoot_; - } gomory_; - - /* \brief Control variable and prototype for lift-and-project cut - generator - struct landpCtl_struct - { CGControl action_ ; - CglLandP *proto_ ; } landp_ ; - */ - - /*! \brief Control variable and prototype for knapsack cover cut generator */ - struct knapsackCtl_struct { - CGControl action_; - CglKnapsackCover *proto_; - } knapsack_; - - /*! \brief Control variable and prototype for MIR cut generator */ - struct mirCtl_struct { - CGControl action_; - CglMixedIntegerRounding2 *proto_; - } mir_; - - /*! \brief Control variable and prototype for odd hole cut generator */ - struct oddHoleCtl_struct { - CGControl action_; - CglOddHole *proto_; - } oddHole_; - - /*! \brief Control variable and prototype for reduce-and-split - cut generator - */ - struct redSplitCtl_struct { - CGControl action_; - CglRedSplit *proto_; - } redSplit_; - - /*! \brief Control variable and prototype for Two-MIR cut generator */ - struct twomirCtl_struct { - CGControl action_; - CglTwomir *proto_; - int maxElements_; - } twomir_; - - /*! \brief Control variable and prototype for feasibility pump heuristic */ - struct fpumpCtl_struct { - CGControl action_; - CbcHeuristicFPump *proto_; - int iters_; - } fpump_; - - /*! \brief Control variable and prototype for combine heuristic */ - struct combineCtl_struct { - CGControl action_; - CbcHeuristicLocal *proto_; - int trySwap_; - } combine_; - - /*! \brief Control variable and prototype for greedy cover heuristic */ - struct greedyCoverCtl_struct { - CGControl action_; - CbcHeuristicGreedyCover *proto_; - } greedyCover_; - - /*! \brief Control variable and prototype for greedy equality heuristic */ - struct greedyEqualityCtl_struct { - CGControl action_; - CbcHeuristicGreedyEquality *proto_; - } greedyEquality_; - - /*! \brief Control variable and prototype for simple rounding heuristic */ - struct roundingCtl_struct { - CGControl action_; - CbcRounding *proto_; - } rounding_; - - /*! \brief Control variables for local tree - - This is a bit different --- getTreeLocal() takes a CbcModel as a parameter - and installs a local tree object. But we can keep the parameters here and - hide the details. Consult CbcTreeLocal.hpp for details. - */ - struct localTreeCtl_struct { - CGControl action_; - CbcTreeLocal *proto_; - double *soln_; - int range_; - int typeCuts_; - int maxDiverge_; - int timeLimit_; - int nodeLimit_; - bool refine_; - } localTree_; - - //@} - - /*! \name Messages and statistics (private) - \brief Data and objects related to messages and statistics that should be - protected from direct manipulation. - */ - //@{ - - /*! \brief Message handler. */ - CoinMessageHandler *msgHandler_; - - /*! \brief Ownership of message handler. - - If true, the control block owns the message handler and it will be destroyed - with the control block. If false, the client is responsible for the message - handler. - */ - bool ourMsgHandler_; - - /*! \brief The current language */ - CoinMessages::Language cur_lang_; - - /*! \brief The current set of messages. */ - CoinMessages *msgs_; - - /*! \brief The current log level */ - int logLvl_; - - //@} -}; - -#endif - -/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 -*/ diff --git a/src/CbcGenParam.cpp b/src/CbcGenParam.cpp deleted file mode 100644 index 6870f24de..000000000 --- a/src/CbcGenParam.cpp +++ /dev/null @@ -1,159 +0,0 @@ -/* - Copyright (C) 2007, Lou Hafer, International Business Machines Corporation - and others. All Rights Reserved. - - This code is licensed under the terms of the Eclipse Public License (EPL). - -*/ -/* - This file is part of cbc-generic. -*/ - -#if defined(_MSC_VER) -// Turn off compiler warning about long names -#pragma warning(disable : 4786) -#endif - -#include -#include - -#include "CoinParam.hpp" - -#include "CbcModel.hpp" - -#include "CbcGenCtlBlk.hpp" -#include "CbcGenParam.hpp" - -namespace { - - -} - -/* - Constructors and destructors - - There's a generic constructor and one for integer, double, keyword, string, - and action parameters. -*/ - -/* - Default constructor. -*/ -CbcGenParam::CbcGenParam() - : CoinParam() - , paramCode_(CbcGenParamCode(0)) - , obj_(0) -{ - /* Nothing to be done here */ -} - -/* - Constructor for double parameter -*/ -CbcGenParam::CbcGenParam(CbcGenParamCode code, - std::string name, std::string help, - double lower, double upper, double dflt, - bool display) - : CoinParam(name, help, lower, upper, dflt, display) - , paramCode_(code) - , obj_(0) -{ - /* Nothing to be done here */ -} - -/* - Constructor for integer parameter -*/ -CbcGenParam::CbcGenParam(CbcGenParamCode code, - std::string name, std::string help, - int lower, int upper, int dflt, - bool display) - : CoinParam(name, help, lower, upper, dflt, display) - , paramCode_(code) - , obj_(0) -{ - /* Nothing to be done here */ -} - -/* - Constructor for keyword parameter. -*/ -CbcGenParam::CbcGenParam(CbcGenParamCode code, - std::string name, std::string help, - std::string firstValue, int dflt, - bool display) - : CoinParam(name, help, firstValue, dflt, display) - , paramCode_(code) - , obj_(0) -{ - /* Nothing to be done here */ -} - -/* - Constructor for string parameter. -*/ -CbcGenParam::CbcGenParam(CbcGenParamCode code, - std::string name, std::string help, - std::string dflt, - bool display) - : CoinParam(name, help, dflt, display) - , paramCode_(code) - , obj_(0) -{ - /* Nothing to be done here */ -} - -/* - Constructor for action parameter. -*/ -CbcGenParam::CbcGenParam(CbcGenParamCode code, - std::string name, std::string help, - bool display) - : CoinParam(name, help, display) - , paramCode_(code) - , obj_(0) -{ - /* Nothing to be done here */ -} - -/* - Copy constructor. -*/ -CbcGenParam::CbcGenParam(const CbcGenParam &orig) - : CoinParam(orig) - , paramCode_(orig.paramCode_) - , obj_(orig.obj_) -{ - /* Nothing to be done here */ -} - -/* - Clone -*/ - -CbcGenParam *CbcGenParam::clone() -{ - return (new CbcGenParam(*this)); -} - -CbcGenParam &CbcGenParam::operator=(const CbcGenParam &rhs) -{ - if (this != &rhs) { - CoinParam::operator=(rhs); - - paramCode_ = rhs.paramCode_; - obj_ = rhs.obj_; - } - - return *this; -} - -/* - Destructor -*/ -CbcGenParam::~CbcGenParam() -{ /* Nothing more to do */ -} - -/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 -*/ diff --git a/src/CbcGenParam.hpp b/src/CbcGenParam.hpp deleted file mode 100644 index b356ea118..000000000 --- a/src/CbcGenParam.hpp +++ /dev/null @@ -1,267 +0,0 @@ -/* - Copyright (C) 2007, Lou Hafer, International Business Machines Corporation - and others. All Rights Reserved. - - This code is licensed under the terms of the Eclipse Public License (EPL). - -*/ -/* - This file is part of cbc-generic. -*/ - -#ifndef CbcGenParam_H -#define CbcGenParam_H - -/* \file CbcGenParam.hpp - \brief Declarations for parameters that control the cbc-generic main - program. -*/ - -/* -*/ - -class CbcGenCtlBlk; - -/*! \class CbcGenParam - \brief Class for cbc-generic control parameters - - Adds parameter type codes and push/pull functions to the generic parameter - object. -*/ - -class CbcGenParam : public CoinParam { - -public: - /*! \name Subtypes */ - //@{ - - /*! \enum CbcGenParamCode - \brief Enumeration for cbc-generic parameters - - These are parameters that control the operation of the cbc-generic main - program by operating on a CbcGenCtlBlk object. CBCGEN_FIRSTPARAM and - CBCGEN_LASTPARM are markers to allow convenient separation of parameter - groups. - */ - typedef enum { CBCGEN_FIRSTPARAM = 0, - - GENERALQUERY, - FULLGENERALQUERY, - HELP, - BAB, - CLEARCUTS, - CLIQUECUTS, - COMBINE, - COSTSTRATEGY, - CPP, - CUTDEPTH, - CUTSTRATEGY, - DEBUG, - DIRECTORY, - DJFIX, - DUMMY, - ERRORSALLOWED, - EXIT, - EXPORT, - FLOWCUTS, - FPUMP, - FPUMPITS, - GOMORYCUTS, - GREEDY, - HEURISTICSTRATEGY, - IMPORT, - INTPRINT, - KNAPSACKCUTS, - LOCALTREE, - LOGLEVEL, - MESSAGES, - MIPLIB, - MIXEDCUTS, - ODDHOLECUTS, - OUTDUPROWS, - OUTPUTFORMAT, - PREPROCESS, - PRINTMASK, - PRINTOPTIONS, - PRINTVERSION, - PRIORITYIN, - PROBINGCUTS, - REDSPLITCUTS, - ROUNDING, - SOLUTION, - SOLVECONTINUOUS, - SOLVER, - SOS, - STDIN, - STRENGTHEN, - TIGHTENFACTOR, - TWOMIRCUTS, - UNITTEST, - USERCBC, - USESOLUTION, - VERBOSE, - SHOWUNIMP, - - CBCGEN_LASTPARAM - - } CbcGenParamCode; - - //@} - - /*! \name Constructors and Destructors - - Be careful how you specify parameters for the constructors! There's great - potential for confusion. - */ - //@{ - /*! \brief Default constructor */ - - CbcGenParam(); - - /*! \brief Constructor for a parameter with a double value - - The default value is 0.0. Be careful to clearly indicate that \p lower and - \p upper are real (double) values to distinguish this constructor from the - constructor for an integer parameter. - */ - CbcGenParam(CbcGenParamCode code, std::string name, std::string help, - double lower, double upper, double dflt = 0.0, - bool display = true); - - /*! \brief Constructor for a parameter with an integer value - - The default value is 0. - */ - CbcGenParam(CbcGenParamCode code, std::string name, std::string help, - int lower, int upper, int dflt = 0, - bool display = true); - - /*! \brief Constructor for a parameter with keyword values - - The string supplied as \p firstValue becomes the first keyword. - Additional keywords can be added using appendKwd(). Keywords are numbered - from zero. It's necessary to specify both the first keyword (\p - firstValue) and the default keyword index (\p dflt) in order to - distinguish this constructor from the string and action parameter - constructors. - */ - CbcGenParam(CbcGenParamCode code, std::string name, std::string help, - std::string firstValue, int dflt, bool display = true); - - /*! \brief Constructor for a string parameter - - The default string value must be specified explicitly to distinguish - a string constructor from an action parameter constructor. - */ - - CbcGenParam(CbcGenParamCode code, std::string name, std::string help, - std::string dflt, bool display = true); - - /*! \brief Constructor for an action parameter */ - - CbcGenParam(CbcGenParamCode code, std::string name, std::string help, - bool display = true); - - /*! \brief Copy constructor */ - - CbcGenParam(const CbcGenParam &orig); - - /*! \brief Clone */ - - CbcGenParam *clone(); - - /*! \brief Assignment */ - - CbcGenParam &operator=(const CbcGenParam &rhs); - - /*! \brief Destructor */ - - ~CbcGenParam(); - - //@} - - /*! \name Methods to query and manipulate a parameter object */ - //@{ - - /*! \brief Get the parameter code */ - - inline CbcGenParamCode paramCode() const - { - return (paramCode_); - } - - /*! \brief Set the parameter code */ - - inline void setParamCode(CbcGenParamCode code) - { - paramCode_ = code; - } - - /*! \brief Get the underlying cbc-generic control object */ - - inline CbcGenCtlBlk *obj() const - { - return (obj_); - } - - /*! \brief Set the underlying cbc-generic control object */ - - inline void setObj(CbcGenCtlBlk *obj) - { - obj_ = obj; - } - - //@} - -private: - /*! \name Data */ - //@{ - - /// Parameter code - CbcGenParamCode paramCode_; - - /// cbc-generic control object - CbcGenCtlBlk *obj_; - - //@} -}; - -/* - Declare the utility functions. -*/ - -namespace CbcGenParamUtils { -void addCbcGenParams(int &numParams, CoinParamVec ¶mVec, - CbcGenCtlBlk *ctlBlk); -void loadGenParamObj(const CoinParamVec paramVec, int first, int last, - CbcGenCtlBlk *ctlBlk); - -void saveSolution(const OsiSolverInterface *osi, std::string fileName); -bool readSolution(std::string fileName, - int &numRows, int &numCols, double &objVal, - double **rowActivity, double **dualVars, - double **primalVars, double **reducedCosts); - -int doBaCParam(CoinParam *param); -int doDebugParam(CoinParam *param); -int doExitParam(CoinParam *param); -int doHelpParam(CoinParam *param); -int doImportParam(CoinParam *param); -int doPrintMaskParam(CoinParam *param); -int doNothingParam(CoinParam *param); -int doSolutionParam(CoinParam *param); -int doUnimplementedParam(CoinParam *param); -int doVersionParam(CoinParam *param); - -int pushCbcGenDblParam(CoinParam *param); -int pushCbcGenIntParam(CoinParam *param); -int pushCbcGenKwdParam(CoinParam *param); -int pushCbcGenStrParam(CoinParam *param); - -int pushCbcGenCutParam(CoinParam *param); -} - -#endif - -/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 -*/ diff --git a/src/CbcGenParamUtils.cpp b/src/CbcGenParamUtils.cpp deleted file mode 100644 index e04829d6f..000000000 --- a/src/CbcGenParamUtils.cpp +++ /dev/null @@ -1,1444 +0,0 @@ -/* - Copyright (C) 2007, Lou Hafer, International Business Machines Corporation - and others. All Rights Reserved. - - This code is licensed under the terms of the Eclipse Public License (EPL). - -*/ -/* - This file is part of cbc-generic. -*/ - -#if defined(_MSC_VER) -// Turn off compiler warning about long names -#pragma warning(disable : 4786) -#endif - -#include -#include - -#include "CoinUtilsConfig.h" -#include "CoinFileIO.hpp" - -#include "CoinFinite.hpp" -#include "CoinParam.hpp" - -#include "CbcModel.hpp" - -#include "CbcGenParam.hpp" -#include "CbcGenCtlBlk.hpp" - -/*! \file CbcGenParamUtils - \brief Implementation functions for CbcGenParam parameters. -*/ - -namespace { - - -} - -namespace CbcGenSolvers { -void setupSolverParam(CbcGenParam &solverParam); -} - -namespace CbcGenParamUtils { - -/* - Function to add cbc-generic control parameters to the cbc-generic parameter - vector. Were needed, defaults are drawn from ctlBlk-> This function is a - friend of CbcGenCtlBlk. -*/ - -void addCbcGenParams(int &numberParameters, CoinParamVec ¶meters, - CbcGenCtlBlk *ctlBlk) - -{ - CbcGenParam *param; - std::string empty = ""; - - param = new CbcGenParam(CbcGenParam::GENERALQUERY, "?", - "Print a list of commands", false); - param->setPushFunc(doHelpParam); - param->setObj(ctlBlk); - parameters.push_back(param); - - param = new CbcGenParam(CbcGenParam::FULLGENERALQUERY, "???", - "Print a list with *all* commands, even those hidden with `?'", false); - param->setPushFunc(doHelpParam); - param->setObj(ctlBlk); - parameters.push_back(param); - - param = new CbcGenParam(CbcGenParam::PRINTVERSION, - "version", "Print version"); - param->setPushFunc(doVersionParam); - param->setObj(ctlBlk); - parameters.push_back(param); - - /* - Built into CoinParam parsing. No additional actions required. doNothingParam - simply prevents them from being reported as unimplemented. - */ - param = new CbcGenParam(CbcGenParam::STDIN, "-", - "Switch to interactive command line mode", false); - param->setPushFunc(doNothingParam); - parameters.push_back(param); - param = new CbcGenParam(CbcGenParam::STDIN, "stdin", - "Switch to interactive command line mode", false); - param->setPushFunc(doNothingParam); - param->setObj(ctlBlk); - parameters.push_back(param); - - param = new CbcGenParam(CbcGenParam::BAB, - "branch!AndCut", "Do Branch and Cut"); - param->setPushFunc(doBaCParam); - param->setObj(ctlBlk); - param->setLongHelp( - "This does branch and cut. There are many parameters which can affect the performance. First just try with default settings and look carefully at the log file. Did cuts help? Did they take too long? Look at output to see which cuts were effective and then do some tuning. You will see that the options for cuts are off, on, root and ifmove. Off is obvious, on means that this cut generator will be tried in the branch and cut tree (you can fine tune using 'depth'). Root means just at the root node while 'ifmove' means that cuts will be used in the tree if they look as if they are doing some good and moving the objective value. If pre-processing reduced the size of the problem or strengthened many coefficients then it is probably wise to leave it on. Switch off heuristics which did not provide solutions. The other major area to look at is the search. Hopefully good solutions were obtained fairly early in the search so the important point is to select the best variable to branch on. See whether strong branching did a good job - or did it just take a lot of iterations. Adjust the strongBranching and trustPseudoCosts parameters."); - parameters.push_back(param); - - param = new CbcGenParam(CbcGenParam::CPP, - "cpp!Generate", "Generates C++ code", -1, 50000); - param->setObj(ctlBlk); - param->setLongHelp( - "Once you like what the stand-alone solver does then this allows you to generate user_driver.cpp which approximates the code. 0 gives simplest driver, 1 generates saves and restores, 2 generates saves and restores even for variables at default value. 4 bit in cbc generates size dependent code rather than computed values."); - parameters.push_back(param); - - param = new CbcGenParam(CbcGenParam::CLIQUECUTS, - "clique!Cuts", "Whether to use clique cuts", "off", - ctlBlk->clique_.action_); - param->appendKwd("on"); - param->appendKwd("root"); - param->appendKwd("ifmove"); - param->appendKwd("forceOn"); - param->setObj(ctlBlk); - param->setPushFunc(pushCbcGenCutParam); - param->setLongHelp( - "This switches on clique cuts (either at root or in entire tree). See branchAndCut for information on options."); - parameters.push_back(param); - - param = new CbcGenParam(CbcGenParam::CUTDEPTH, - "cutD!epth", "Depth in tree at which to do cuts", - -1, 999999, ctlBlk->cutDepth_); - param->setObj(ctlBlk); - param->setPushFunc(pushCbcGenIntParam); - param->setLongHelp( - "Cut generators may be off, on only at the root, on if they look useful, and on at some interval. If they are done every node then that is that, but it may be worth doing them every so often. The original method was every so many nodes but it is more logical to do it whenever depth in tree is a multiple of K. This option does that and defaults to -1 (off)."); - parameters.push_back(param); - - param = new CbcGenParam(CbcGenParam::CUTSTRATEGY, - "cuts!OnOff", "Switches all cuts on or off", "off", 0); - param->appendKwd("on"); - param->appendKwd("root"); - param->appendKwd("ifmove"); - param->appendKwd("forceOn"); - param->setObj(ctlBlk); - param->setLongHelp( - "This can be used to switch on or off all cuts (apart from Reduce and Split). Then you can set individual ones off or on. See branchAndCut for information on options."); - parameters.push_back(param); - - param = new CbcGenParam(CbcGenParam::COMBINE, - "combine!Solutions", - "Whether to use combine solution heuristic", "off", - ctlBlk->combine_.action_); - param->appendKwd("on"); - param->setObj(ctlBlk); - param->setLongHelp( - "This switches on a heuristic which does branch and cut on the problem given by just using variables which have appeared in one or more solutions. It is obviously only tried after two or more solutions."); - parameters.push_back(param); - - param = new CbcGenParam(CbcGenParam::COSTSTRATEGY, - "cost!Strategy", "Whether to use costs or column order as priorities", - "off", 0); - param->appendKwd("pri!orities"); - param->appendKwd("column!Order"); - param->setObj(ctlBlk); - param->setLongHelp( - "This orders the variables in order of their absolute costs - with largest cost ones being branched on first. This primitive strategy can be surprisingly effective. The column order option is obviously not on costs but it's easy to implement."); - parameters.push_back(param); - - param = new CbcGenParam(CbcGenParam::DEBUG, - "debug!In", "Read/write valid solution from/to file", "", false); - param->setObj(ctlBlk); - param->setPushFunc(doDebugParam); - param->setLongHelp( - "This will read a solution file from the given file name. It will use the default directory given by 'directory'. A name of '$' will use the previous value for the name. This is initialized to '', i.e. it must be set.\n\nIf set to create it will create a file called debug.file after B&C search; if set to createAfterPre it will create the file before undoing preprocessing.\n\nThe idea is that if you suspect a bad cut generator and you did not use preprocessing you can do a good run with debug set to 'create' and then switch on the cuts you suspect and re-run with debug set to 'debug.file' Similarly if you do use preprocessing, but use createAfterPre. The create case has the same effect as saveSolution."); - parameters.push_back(param); - - param = new CbcGenParam(CbcGenParam::DIRECTORY, - "directory", "Set Default directory for import etc.", - ctlBlk->dfltDirectory_); - param->setObj(ctlBlk); - param->setLongHelp( - "This sets the directory which import, export, saveModel, restoreModel etc. will use. It is initialized to the current directory."); - param->setPushFunc(pushCbcGenStrParam); - parameters.push_back(param); - - param = new CbcGenParam(CbcGenParam::EXIT, "end", "Stops execution"); - param->setPushFunc(doExitParam); - param->setObj(ctlBlk); - param->setLongHelp( - "This stops execution; end, exit, quit and stop are synonyms."); - parameters.push_back(param); - - param = new CbcGenParam(CbcGenParam::ERRORSALLOWED, - "error!sAllowed", "Whether to allow import errors", "off", 0); - param->appendKwd("on"); - param->setObj(ctlBlk); - param->setLongHelp( - "The default is not to use any model which had errors when reading the mps file. Setting this to 'on' will allow all errors from which the code can recover simply by ignoring the error. There are some errors from which the code can not recover, e.g., no ENDATA. This has to be set before import, i.e., -errorsAllowed on -import xxxxxx.mps."); - parameters.push_back(param); - - param = new CbcGenParam(CbcGenParam::EXIT, "exit", "Stops execution"); - param->setPushFunc(doExitParam); - param->setObj(ctlBlk); - param->setLongHelp( - "This stops execution; end, exit, quit and stop are synonyms."); - parameters.push_back(param); - - param = new CbcGenParam(CbcGenParam::EXPORT, - "export", "Export model as mps file", - std::string("default.mps")); - param->setObj(ctlBlk); - param->setLongHelp( - "This will write an MPS format file to the given file name. It will use the default directory given by 'directory'. A name of '$' will use the previous value for the name. This is initialized to 'default.mps'."); - parameters.push_back(param); - - param = new CbcGenParam(CbcGenParam::DJFIX, "fix!OnDj", - "Try heuristic that fixes variables based on reduced costs", - -1.0e20, 1.0e20, ctlBlk->djFix_.threshold_); - param->setPushFunc(pushCbcGenDblParam); - param->setObj(ctlBlk); - param->setLongHelp( - "If set, integer variables with reduced costs greater than the specified value will be fixed before branch and bound - use with extreme caution!"); - parameters.push_back(param); - - param = new CbcGenParam(CbcGenParam::FPUMP, - "feas!ibilityPump", "Whether to try Feasibility Pump", "off", - ctlBlk->fpump_.action_); - param->appendKwd("on"); - param->setObj(ctlBlk); - param->setLongHelp( - "This switches on feasibility pump heuristic at root. This is due to Fischetti and Lodi and uses a sequence of LPs to try and get an integer feasible solution. Some fine tuning is available by passFeasibilityPump."); - parameters.push_back(param); - - param = new CbcGenParam(CbcGenParam::FPUMPITS, - "passF!easibilityPump", "How many passes in feasibility pump", - 0, 10000, ctlBlk->fpump_.iters_); - param->setObj(ctlBlk); - param->setLongHelp( - "This fine tunes the Feasibility Pump heuristic by doing more or fewer passes."); - parameters.push_back(param); - - param = new CbcGenParam(CbcGenParam::FLOWCUTS, - "flow!CoverCuts", "Whether to use Flow Cover cuts", "off", - ctlBlk->flow_.action_); - param->appendKwd("on"); - param->appendKwd("root"); - param->appendKwd("ifmove"); - param->appendKwd("forceOn"); - param->setObj(ctlBlk); - param->setPushFunc(pushCbcGenCutParam); - param->setLongHelp( - "This switches on flow cover cuts (either at root or in entire tree). See branchAndCut for information on options."); - parameters.push_back(param); - - param = new CbcGenParam(CbcGenParam::GOMORYCUTS, "gomory!Cuts", - "Whether to use Gomory cuts", "off", - ctlBlk->gomory_.action_); - param->appendKwd("on"); - param->appendKwd("root"); - param->appendKwd("ifmove"); - param->appendKwd("forceOn"); - param->setObj(ctlBlk); - param->setPushFunc(pushCbcGenCutParam); - param->setLongHelp( - "The original cuts - beware of imitations! Having gone out of favor, they are now more fashionable as LP solvers are more robust and they interact well with other cuts. They will almost always give cuts (although in this executable they are limited as to number of variables in cut). However the cuts may be dense so it is worth experimenting. See branchAndCut for information on options."); - parameters.push_back(param); - - param = new CbcGenParam(CbcGenParam::GREEDY, - "greedy!Heuristic", "Whether to use a greedy heuristic", "off", - ctlBlk->greedyCover_.action_); - param->appendKwd("on"); - param->appendKwd("root"); - param->setObj(ctlBlk); - param->setLongHelp( - "Switches on a pair of greedy heuristic which will try and obtain a solution. It may just fix a percentage of variables and then try a small branch and cut run."); - parameters.push_back(param); - - param = new CbcGenParam(CbcGenParam::HEURISTICSTRATEGY, - "heur!isticsOnOff", "Switches most heuristics on or off", "off", 0); - param->appendKwd("on"); - param->setObj(ctlBlk); - param->setLongHelp( - "This can be used to switch on or off all heuristics. Then you can set individual ones off or on. CbcTreeLocal is not included as it dramatically alters search."); - parameters.push_back(param); - - param = new CbcGenParam(CbcGenParam::KNAPSACKCUTS, - "knapsack!Cuts", "Whether to use Knapsack cuts", "off", - ctlBlk->knapsack_.action_); - param->appendKwd("on"); - param->appendKwd("root"); - param->appendKwd("ifmove"); - param->appendKwd("forceOn"); - param->setObj(ctlBlk); - param->setPushFunc(pushCbcGenCutParam); - param->setLongHelp( - "This switches on knapsack cuts (either at root or in entire tree). See branchAndCut for information on options."); - parameters.push_back(param); - - /* - param = new CbcGenParam(CbcGenParam::LANDPCUTS, - "lift!AndProjectCuts","Whether to use lift-and-project cuts","off", - ctlBlk->landp_.action_) ; - param->appendKwd("on") ; - param->appendKwd("root") ; - param->appendKwd("ifmove") ; - param->appendKwd("forceOn") ; - param->setObj(ctlBlk) ; - param->setLongHelp( - "This switches on lift-and-project cuts (either at root or in entire tree). See branchAndCut for information on options." - ) ; - parameters.push_back(param) ; - */ - - param = new CbcGenParam(CbcGenParam::LOCALTREE, - "local!TreeSearch", "Whether to use local tree search", "off", - ctlBlk->localTree_.action_); - param->appendKwd("on"); - param->setObj(ctlBlk); - param->setLongHelp( - "This switches on a local search algorithm when a solution is found. This is from Fischetti and Lodi and is not really a heuristic although it can be used as one. When used from this program it has limited functionality. It is not controlled by heuristicsOnOff."); - parameters.push_back(param); - - param = new CbcGenParam(CbcGenParam::LOGLEVEL, - "log!Level", "Level of detail in cbc-generic output.", - -1, 999999, ctlBlk->logLvl_); - param->setObj(ctlBlk); - param->setPushFunc(pushCbcGenIntParam); - param->setLongHelp( - "If set to 0 then there should be no output in normal circumstances. A value of 1 is probably the best value for most uses, while 2 and 3 give more information."); - parameters.push_back(param); - - param = new CbcGenParam(CbcGenParam::MIXEDCUTS, - "mixed!IntegerRoundingCuts", - "Whether to use Mixed Integer Rounding cuts", "off", - ctlBlk->mir_.action_); - param->appendKwd("on"); - param->appendKwd("root"); - param->appendKwd("ifmove"); - param->appendKwd("forceOn"); - param->setObj(ctlBlk); - param->setPushFunc(pushCbcGenCutParam); - param->setLongHelp( - "This switches on mixed integer rounding cuts (either at root or in entire tree). See branchAndCut for information on options."); - parameters.push_back(param); - - param = new CbcGenParam(CbcGenParam::USESOLUTION, - "force!Solution", - "Whether to use given solution as crash for BAB", "off", 0); - param->appendKwd("on"); - param->setObj(ctlBlk); - param->setLongHelp( - "If on then tries to branch to solution given by AMPL or priorities file."); - parameters.push_back(param); - - param = new CbcGenParam(CbcGenParam::HELP, "help", - "Print out version, non-standard options and some help"); - param->setPushFunc(doHelpParam); - param->setObj(ctlBlk); - param->setLongHelp( - "This prints out some help to get a user started. If you're seeing this message, you should be past that stage."); - parameters.push_back(param); - - param = new CbcGenParam(CbcGenParam::IMPORT, - "import", "Import model from mps file", - ctlBlk->lastMpsIn_); - param->setPushFunc(doImportParam); - param->setObj(ctlBlk); - param->setLongHelp( - "This will read an MPS format file from the given file name. It will use the default directory given by 'directory'. A name of '$' will use the previous value for the name. This is initialized to '', i.e., it must be set. If you have libgz then it can read compressed files 'xxxxxxxx.gz'."); - parameters.push_back(param); - - param = new CbcGenParam(CbcGenParam::SOLVECONTINUOUS, "initialS!olve", - "Solve to continuous optimum"); - param->setObj(ctlBlk); - param->setLongHelp( - "This just solves the problem to the continuous optimum, without adding any cuts."); - parameters.push_back(param); - - param = new CbcGenParam(CbcGenParam::MESSAGES, "mess!ages", - "Controls whether standardised message prefix is printed", "off", 0); - param->appendKwd("on"); - param->setObj(ctlBlk); - param->setLongHelp( - "By default, messages have a standard prefix, such as:\n Clp0005 2261 Objective 109.024 Primal infeas 944413 (758)\nbut this program turns this off to make it look more friendly. It can be useful to turn them back on if you want to be able to 'grep' for particular messages or if you intend to override the behavior of a particular message."); - parameters.push_back(param); - - param = new CbcGenParam(CbcGenParam::MIPLIB, - "miplib", "Do some of miplib test set"); - parameters.push_back(param); - - param = new CbcGenParam(CbcGenParam::OUTDUPROWS, - "outDup!licates", - "Takes duplicate rows, etc., out of the integer model", false); - parameters.push_back(param); - - param = new CbcGenParam(CbcGenParam::OUTPUTFORMAT, - "output!Format", "Which output format to use", 1, 6, 2); - param->setObj(ctlBlk); - param->setLongHelp( - "Normally export will be done using normal representation for numbers and two values per line. You may want to do just one per line (for grep or suchlike) and you may wish to save with absolute accuracy using a coded version of the IEEE value. A value of 2 is normal. Otherwise, odd values give one value per line, even values two. Values of 1 and 2 give normal format, 3 and 4 give greater precision, 5 and 6 give IEEE values. When exporting a basis, 1 does not save values, 2 saves values, 3 saves with greater accuracy and 4 saves in IEEE format."); - parameters.push_back(param); - - /* - In order for initialisation to work properly, the order of the keywords here - must match the order of the enum IPPControl in CbcGenCtlBlk.hpp. - */ - param = new CbcGenParam(CbcGenParam::PREPROCESS, - "preprocess", "Whether to use integer preprocessing", "off", - ctlBlk->preProcess_); - param->appendKwd("on"); - param->appendKwd("save"); - param->appendKwd("equal"); - param->appendKwd("sos"); - param->appendKwd("trysos"); - param->appendKwd("equalall"); - param->appendKwd("strategy"); - param->setObj(ctlBlk); - param->setPushFunc(pushCbcGenKwdParam); - param->setLongHelp( - "This tries to reduce size of the model in a similar way to presolve and it also tries to strengthen the model. This can be very useful and is worth trying. save option saves on file presolved.mps. equal will turn <= cliques into ==. sos will create sos sets if all 0-1 in sets (well one extra is allowed) and no overlaps. trysos is same but allows any number extra. equalall will turn all valid inequalities into equalities with integer slacks. strategy is as on but uses CbcStrategy."); - parameters.push_back(param); - - param = new CbcGenParam(CbcGenParam::PRINTOPTIONS, - "pO!ptions", "Dubious print options", 0, COIN_INT_MAX, 0, false); - param->setObj(ctlBlk); - param->setPushFunc(pushCbcGenIntParam); - param->setLongHelp( - "If this is greater than 0 then presolve will give more information and branch and cut will give statistics"); - parameters.push_back(param); - - param = new CbcGenParam(CbcGenParam::PROBINGCUTS, - "probing!Cuts", "Whether to use Probing cuts", "off", - ctlBlk->probing_.action_); - param->appendKwd("on"); - param->appendKwd("root"); - param->appendKwd("ifmove"); - param->appendKwd("forceOn"); - param->appendKwd("forceOnBut"); - param->setObj(ctlBlk); - param->setPushFunc(pushCbcGenCutParam); - param->setLongHelp( - "This switches on probing cuts (either at root or in entire tree). See branchAndCut for information on options."); - parameters.push_back(param); - - param = new CbcGenParam(CbcGenParam::INTPRINT, - "printi!ngOptions", "Print options", "normal", 0); - param->appendKwd("integer"); - param->appendKwd("special"); - param->appendKwd("rows"); - param->appendKwd("all"); - param->setPushFunc(pushCbcGenKwdParam); - param->setObj(ctlBlk); - param->setLongHelp( - "This changes the amount and format of printing a solution:\nnormal - nonzero column variables \ninteger - nonzero integer column variables\nspecial - in format suitable for OsiRowCutDebugger\nrows - nonzero column variables and row activities\nall - all column variables and row activities.\n\nFor non-integer problems 'integer' and 'special' act like 'normal'. Also see printMask for controlling output."); - parameters.push_back(param); - - param = new CbcGenParam(CbcGenParam::PRINTMASK, - "printM!ask", - "Control printing of solution with a regular expression", empty); - param->setPushFunc(doPrintMaskParam); - param->setObj(ctlBlk); - param->setLongHelp( - "If set then only those names which match mask are printed in a solution. '?' matches any character and '*' matches any set of characters. The default is '' (unset) so all variables are printed. This is only active if model has names."); - parameters.push_back(param); - - param = new CbcGenParam(CbcGenParam::PRIORITYIN, - "prio!rityIn", "Import priorities etc from file", empty); - param->setObj(ctlBlk); - param->setLongHelp( - "This will read a file with priorities from the given file name. It will use the default directory given by 'directory'. A name of '$' will use the previous value for the name. This is initialized to '', i.e. it must be set. This can not read from compressed files. File is in csv format with allowed headings - name, number, priority, direction, up, down, solution. Exactly one of name and number must be given."); - parameters.push_back(param); - - param = new CbcGenParam(CbcGenParam::REDSPLITCUTS, - "reduce!AndSplitCuts", - "Whether to use Reduce-and-Split cuts", "off", - ctlBlk->redSplit_.action_); - param->appendKwd("on"); - param->appendKwd("root"); - param->appendKwd("ifmove"); - param->appendKwd("forceOn"); - param->setObj(ctlBlk); - param->setPushFunc(pushCbcGenCutParam); - param->setLongHelp( - "This switches on reduce and split cuts (either at root or in entire tree). See branchAndCut for information on options."); - parameters.push_back(param); - - param = new CbcGenParam(CbcGenParam::ROUNDING, - "round!ingHeuristic", "Whether to use Rounding heuristic", "off", - ctlBlk->rounding_.action_); - param->appendKwd("on"); - param->setObj(ctlBlk); - param->setLongHelp( - "This switches on a simple (but effective) rounding heuristic at each node of tree."); - parameters.push_back(param); - - param = new CbcGenParam(CbcGenParam::EXIT, "quit", "Stops execution"); - param->setPushFunc(doExitParam); - param->setObj(ctlBlk); - param->setLongHelp( - "This stops execution; end, exit, quit and stop are synonyms."); - parameters.push_back(param); - - param = new CbcGenParam(CbcGenParam::DUMMY, - "sleep", "for debug", 0, 9999, 0, false); - param->setObj(ctlBlk); - param->setLongHelp( - "If passed to solver from ampl, then ampl will wait so that you can copy .nl file for debug."); - parameters.push_back(param); - - param = new CbcGenParam(CbcGenParam::SOLUTION, - "solu!tion", "Prints solution to file", - std::string("stdout")); - param->setPushFunc(doSolutionParam); - param->setObj(ctlBlk); - param->setLongHelp( - "This will write a primitive solution file to the given file name. It will use the default directory given by 'directory'. A name of '$' will use the previous value for the name. This is initialized to 'stdout'. The amount of output can be varied using printi!ngOptions or printMask."); - parameters.push_back(param); - - param = new CbcGenParam; - CbcGenSolvers::setupSolverParam(*param); - param->setObj(ctlBlk); - parameters.push_back(param); - - param = new CbcGenParam(CbcGenParam::SOS, - "sos!Options", "Whether to use SOS from AMPL", "off", 0); - param->appendKwd("on"); - param->setObj(ctlBlk); - param->setLongHelp( - "Normally if AMPL says there are SOS variables they should be used, but sometimes they should be turned off - this does so."); - parameters.push_back(param); - - param = new CbcGenParam(CbcGenParam::EXIT, "stop", "Stops execution"); - param->setPushFunc(doExitParam); - param->setObj(ctlBlk); - param->setLongHelp( - "This stops execution; end, exit, quit and stop are synonyms."); - parameters.push_back(param); - - param = new CbcGenParam(CbcGenParam::STRENGTHEN, - "strengthen", "Create strengthened problem"); - param->setObj(ctlBlk); - param->setLongHelp( - "This creates a new problem by applying the root node cuts. All tight constraints will be in resulting problem."); - parameters.push_back(param); - - param = new CbcGenParam(CbcGenParam::TIGHTENFACTOR, "tighten!Factor", - "Tighten bounds using value times largest activity at continuous solution", - 1.0, 1.0e20); - param->setObj(ctlBlk); - param->setLongHelp( - "This sleazy trick can help on some problems."); - parameters.push_back(param); - - param = new CbcGenParam(CbcGenParam::TWOMIRCUTS, - "two!MirCuts", - "Whether to use Two phase Mixed Integer Rounding cuts", "off", - ctlBlk->twomir_.action_); - param->appendKwd("on"); - param->appendKwd("root"); - param->appendKwd("ifmove"); - param->appendKwd("forceOn"); - param->setObj(ctlBlk); - param->setPushFunc(pushCbcGenCutParam); - param->setLongHelp( - "This switches on two phase mixed integer rounding cuts (either at root or in entire tree). See branchAndCut for information on options."); - parameters.push_back(param); - - param = new CbcGenParam(CbcGenParam::UNITTEST, "unitTest", "Do unit test"); - param->setObj(ctlBlk); - param->setLongHelp( - "This exercises the unit test."); - parameters.push_back(param); - - param = new CbcGenParam(CbcGenParam::USERCBC, - "userCbc", "Hand coded Cbc stuff", 0, COIN_INT_MAX, 0, false); - param->setObj(ctlBlk); - param->setLongHelp( - "There are times (e.g., when using AMPL interface) when you may wish to do something unusual. Look for USERCBC in main driver and modify sample code."); - parameters.push_back(param); - - param = new CbcGenParam(CbcGenParam::VERBOSE, - "verbose", "Switches on longer help on single ?", - 0, 15, ctlBlk->verbose_, false); - param->setPushFunc(pushCbcGenIntParam); - param->setObj(ctlBlk); - param->setLongHelp( - "Set to 1 to get short help with ? list, 2 to get long help."); - parameters.push_back(param); - - param = new CbcGenParam(CbcGenParam::SHOWUNIMP, - "unimp!lemented", "Report unimplemented commands.", false); - param->setPushFunc(doUnimplementedParam); - param->setObj(ctlBlk); - parameters.push_back(param); - - numberParameters = parameters.size(); - assert(((unsigned)numberParameters) <= parameters.capacity()); - - return; -} - -void loadGenParamObj(const CoinParamVec paramVec, int first, int last, - CbcGenCtlBlk *ctlBlk) - -{ - int i; - /* - Load the cbc-generic object into the parameters - */ - for (i = first; i <= last; i++) { - CbcGenParam *genParam = dynamic_cast< CbcGenParam * >(paramVec[i]); - assert(genParam != 0); - genParam->setObj(ctlBlk); - } - - return; -} - -/* Functions to implement cbc-generic (CbcGenParam) parameters */ - -/* - Maintainer's utility, scan the parameters and report the ones that are - unimplemented (i.e., have no pushFunc). -*/ - -int doUnimplementedParam(CoinParam *param) - -{ - assert(param != 0); - - CbcGenParam *genParam = dynamic_cast< CbcGenParam * >(param); - assert(genParam != 0); - - CbcGenCtlBlk *ctlBlk = genParam->obj(); - assert(ctlBlk != 0); - - assert(ctlBlk->paramVec_ != 0); - CoinParamVec ¶mVec = *ctlBlk->paramVec_; - - int unimpCnt = 0; - int maxAcross = 5; - for (unsigned i = 0; i < paramVec.size(); i++) { - CoinParam *param = paramVec[i]; - if (param->pushFunc() == 0) { - if (unimpCnt % maxAcross == 0) { - std::cout << std::endl; - } else { - std::cout << " "; - } - std::cout << param->name(); - unimpCnt++; - } - } - if (unimpCnt % maxAcross != 1) { - std::cout << std::endl; - } - std::cout << unimpCnt << " unimplemented parameters." << std::endl; - - return (0); -} - -/* - Noop function. Mainly to eliminate commands from the list returned by - doUnimplmentedParam. -*/ - -int doNothingParam(CoinParam *param) -{ - return (0); -} - -/* - Function to terminate command parsing by returning -1. -*/ - -int doExitParam(CoinParam *param) - -{ - return (-1); -} - -/* - Function to print the current version. -*/ - -int doVersionParam(CoinParam *param) - -{ - assert(param != 0); - CbcGenParam *genParam = dynamic_cast< CbcGenParam * >(param); - assert(genParam != 0); - CbcGenCtlBlk *ctlBlk = genParam->obj(); - assert(ctlBlk != 0); - - std::cout << "cbc-generic version " << ctlBlk->version_ << std::endl; - std::cout - << "cbc-generic is experimental software. If you want a stable MIP " - << "solver, please" << std::endl - << "use cbc. If you discover bugs while using cbc-generic " - << "please specify" << std::endl - << "cbc-generic in the ticket description or email subject line." - << std::endl; - - return (0); -} - -/* - Function to handle help (HELP), `?' (GENERALQUERY), and `???' - (FULLGENERALQUERY). -*/ - -int doHelpParam(CoinParam *param) - -{ - assert(param != 0); - CbcGenParam *genParam = dynamic_cast< CbcGenParam * >(param); - assert(genParam != 0); - CbcGenCtlBlk *ctlBlk = genParam->obj(); - assert(ctlBlk != 0); - - CbcGenParam::CbcGenParamCode code = genParam->paramCode(); - - int verbose = ctlBlk->verbose_; - bool shortHelp = ((verbose & 0x01) ? true : false); - bool longHelp = ((verbose & 0x02) ? true : false); - bool hidden = ((verbose & 0x08) ? true : false); - - CoinParamVec *paramVec = ctlBlk->paramVec_; - assert(paramVec != 0); - /* - Tune up the initial settings. FULLGENERALQUERY will print normally hidden - params, and a request for long help overrules a request for short help. - */ - if (code == CbcGenParam::FULLGENERALQUERY) { - hidden = true; - } - if (longHelp) { - shortHelp = false; - } - - CoinParamUtils::printGenericHelp(); - - std::cout << "\nAvailable commands are:"; - std::string pfx(" "); - CoinParamUtils::printHelp(*paramVec, 0, paramVec->size() - 1, pfx, - shortHelp, longHelp, hidden); - - return (0); -} - -/* - Function to push a double-valued parameter. -*/ - -int pushCbcGenDblParam(CoinParam *param) - -{ - assert(param != 0); - CbcGenParam *genParam = dynamic_cast< CbcGenParam * >(param); - assert(genParam != 0); - CbcGenCtlBlk *ctlBlk = genParam->obj(); - assert(ctlBlk != 0); - - double val = genParam->dblVal(); - CbcGenParam::CbcGenParamCode code = genParam->paramCode(); - - int retval = 0; - /* - Figure out what we're doing and set the relevant field. - */ - switch (code) { - case CbcGenParam::DJFIX: { - ctlBlk->djFix_.action_ = true; - ctlBlk->djFix_.threshold_ = val; - break; - } - default: { - std::cerr << "pushCbcGenDbl: no equivalent CbcGenCtlBlk field for " - << "parameter code `" << code << "'." << std::endl; - retval = -1; - break; - } - } - - return (retval); -} - -/* - Function to push an integer-valued parameter. -*/ - -int pushCbcGenIntParam(CoinParam *param) - -{ - assert(param != 0); - CbcGenParam *genParam = dynamic_cast< CbcGenParam * >(param); - assert(genParam != 0); - CbcGenCtlBlk *ctlBlk = genParam->obj(); - assert(ctlBlk != 0); - - int val = genParam->intVal(); - CbcGenParam::CbcGenParamCode code = genParam->paramCode(); - - int retval = 0; - /* - Figure out what we're doing and set the relevant field. - */ - switch (code) { - case CbcGenParam::CUTDEPTH: { - ctlBlk->setCutDepth(val); - break; - } - case CbcGenParam::LOGLEVEL: { - ctlBlk->setLogLevel(val); - break; - } - case CbcGenParam::PRINTOPTIONS: { - ctlBlk->printOpt_ = val; - break; - } - case CbcGenParam::VERBOSE: { - ctlBlk->verbose_ = val; - break; - } - default: { - std::cerr << "pushCbcGenInt: no equivalent CbcGenCtlBlk field for " - << "parameter code `" << code << "'." << std::endl; - retval = -1; - break; - } - } - - return (retval); -} - -/* - Function to push a keyword-valued parameter. This is the catch-all function - for keyword parameters that don't belong to any other useful grouping. -*/ - -int pushCbcGenKwdParam(CoinParam *param) - -{ - assert(param != 0); - CbcGenParam *genParam = dynamic_cast< CbcGenParam * >(param); - assert(genParam != 0); - CbcGenCtlBlk *ctlBlk = genParam->obj(); - assert(ctlBlk != 0); - - std::string str = genParam->kwdVal(); - CbcGenParam::CbcGenParamCode code = genParam->paramCode(); - - int retval = 0; - /* - Figure out what we're doing and set the relevant field. - */ - switch (code) { - case CbcGenParam::PREPROCESS: { - if (str == "off") { - ctlBlk->setIPPAction(CbcGenCtlBlk::IPPOff); - } else if (str == "on") { - ctlBlk->setIPPAction(CbcGenCtlBlk::IPPOn); - } else if (str == "save") { - ctlBlk->setIPPAction(CbcGenCtlBlk::IPPSave); - } else if (str == "equal") { - ctlBlk->setIPPAction(CbcGenCtlBlk::IPPEqual); - } else if (str == "sos") { - ctlBlk->setIPPAction(CbcGenCtlBlk::IPPSOS); - } else if (str == "trysos") { - ctlBlk->setIPPAction(CbcGenCtlBlk::IPPTrySOS); - } else if (str == "equalall") { - ctlBlk->setIPPAction(CbcGenCtlBlk::IPPEqualAll); - } else if (str == "strategy") { - ctlBlk->setIPPAction(CbcGenCtlBlk::IPPStrategy); - } else { - std::cerr - << "pushCbcGenKwdParam(PREPROCESS): unrecognised keyword `" - << str << "'." << std::endl; - retval = -1; - } - break; - } - case CbcGenParam::COSTSTRATEGY: { - if (str == "off") { - ctlBlk->priorityAction_ = CbcGenCtlBlk::BPOff; - } else if (str == "priorities") { - ctlBlk->priorityAction_ = CbcGenCtlBlk::BPCost; - } - if (str == "columnOrder") { - ctlBlk->priorityAction_ = CbcGenCtlBlk::BPOrder; - } else { - std::cerr - << "pushCbcGenKwdParam(COSTSTRATEGY): unrecognised keyword `" - << str << "'." << std::endl; - retval = -1; - } - break; - } - case CbcGenParam::INTPRINT: { - if (str == "normal") { - ctlBlk->printMode_ = 0; - } else if (str == "integer") { - ctlBlk->printMode_ = 1; - } else if (str == "special") { - ctlBlk->printMode_ = 2; - } else if (str == "rows") { - ctlBlk->printMode_ = 3; - } else if (str == "all") { - ctlBlk->printMode_ = 4; - } else { - std::cerr - << "pushCbcGenKwdParam(INTPRINT): unrecognised keyword `" - << str << "'." << std::endl; - retval = -1; - } - break; - } - default: { - std::cerr - << "pushCbcGenKwdParam: unrecognised parameter code `" - << code << "'." << std::endl; - retval = -1; - break; - } - } - - return (retval); -} - -/* - Function to push a string-valued parameter -*/ - -int pushCbcGenStrParam(CoinParam *param) - -{ - assert(param != 0); - CbcGenParam *genParam = dynamic_cast< CbcGenParam * >(param); - assert(genParam != 0); - CbcGenCtlBlk *ctlBlk = genParam->obj(); - assert(ctlBlk != 0); - - std::string str = genParam->strVal(); - CbcGenParam::CbcGenParamCode code = genParam->paramCode(); - - int retval = 0; - /* - Figure out what we're doing and set the relevant field. - */ - switch (code) { - case CbcGenParam::DIRECTORY: { - char dirSep = CoinFindDirSeparator(); - if (str[str.length() - 1] != dirSep) { - str += dirSep; - } - ctlBlk->dfltDirectory_ = str; - break; - } - default: { - std::cerr << "pushCbcGenStr: no equivalent CbcGenCtlBlk field for " - << "parameter code `" << code << "'." << std::endl; - retval = -1; - break; - } - } - - return (retval); -} - -/* - The various parameters to control cut generators can be - grouped, as they all use the same set of keywords. -*/ -int pushCbcGenCutParam(CoinParam *param) - -{ - assert(param != 0); - CbcGenParam *genParam = dynamic_cast< CbcGenParam * >(param); - assert(genParam != 0); - CbcGenCtlBlk *ctlBlk = genParam->obj(); - assert(ctlBlk != 0); - - std::string str = genParam->kwdVal(); - CbcGenParam::CbcGenParamCode code = genParam->paramCode(); - /* - Setup to return nonfatal/fatal error (1/-1) by default, so that all we need - to do is correct to 0 (no error) if we're successful. - */ - int retval; - if (CoinParamUtils::isInteractive()) { - retval = 1; - } else { - retval = -1; - } - /* - First translate the keyword into the correct CGControl enum value. - */ - CbcGenCtlBlk::CGControl action; - if (str == "off") { - action = CbcGenCtlBlk::CGOff; - } else if (str == "on") { - action = CbcGenCtlBlk::CGOn; - } else if (str == "root") { - action = CbcGenCtlBlk::CGRoot; - } else if (str == "ifmove") { - action = CbcGenCtlBlk::CGIfMove; - } else if (str == "forceOn") { - action = CbcGenCtlBlk::CGForceOn; - } else if (str == "forceOnBut") { - action = CbcGenCtlBlk::CGForceBut; - } else { - std::cerr - << "pushCbcGenCutParam: unrecognised keyword `" - << str << "'." << std::endl; - return (retval); - } - /* - Validate the parameter code and set a variable to separate cuts from - heuristics. - */ - bool isCut = false; - bool isHeuristic = false; - switch (code) { - case CbcGenParam::CLIQUECUTS: - case CbcGenParam::FLOWCUTS: - case CbcGenParam::GOMORYCUTS: - case CbcGenParam::KNAPSACKCUTS: - case CbcGenParam::MIXEDCUTS: - case CbcGenParam::PROBINGCUTS: - case CbcGenParam::REDSPLITCUTS: - case CbcGenParam::TWOMIRCUTS: - case CbcGenParam::CUTSTRATEGY: { - isCut = true; - break; - } - case CbcGenParam::COMBINE: - case CbcGenParam::FPUMP: - case CbcGenParam::ROUNDING: - case CbcGenParam::LOCALTREE: - case CbcGenParam::HEURISTICSTRATEGY: { - isHeuristic = true; - break; - } - default: { - std::cerr - << "pushCbcGenCutParam: unrecognised parameter code `" - << code << "'." << std::endl; - return (retval); - } - } - /* - See if the action is valid for the specified type. Heuristics are on or - off; cuts can be any of the other codes. Only probing can use forceOnBut. - */ - if (isHeuristic) { - if (!(action == CbcGenCtlBlk::CGOff || action == CbcGenCtlBlk::CGOn)) { - std::cerr - << "pushCbcGenCutParam: only on or off is valid for a heuristic." - << std::endl; - return (retval); - } - } else if (isCut) { - if (action == CbcGenCtlBlk::CGForceBut && code != CbcGenParam::PROBINGCUTS) { - std::cerr - << "pushCbcGenCutParam: forceOnBut is valid only for probing." - << std::endl; - return (retval); - } - } - /* - We've done the basic checks; go ahead and set the relevant field in the - control block. We shouldn't need the default case, but some compilers will - complain if it's missing. - */ - switch (code) { - case CbcGenParam::CLIQUECUTS: { - ctlBlk->setCliqueAction(action); - break; - } - case CbcGenParam::FLOWCUTS: { - ctlBlk->setFlowAction(action); - break; - } - case CbcGenParam::GOMORYCUTS: { - ctlBlk->setGomoryAction(action); - break; - } - case CbcGenParam::KNAPSACKCUTS: { - ctlBlk->setKnapsackAction(action); - break; - } - case CbcGenParam::MIXEDCUTS: { - ctlBlk->setMirAction(action); - break; - } - case CbcGenParam::PROBINGCUTS: { - ctlBlk->setProbingAction(action); - break; - } - case CbcGenParam::REDSPLITCUTS: { - ctlBlk->setRedSplitAction(action); - break; - } - case CbcGenParam::TWOMIRCUTS: { - ctlBlk->setTwomirAction(action); - break; - } - case CbcGenParam::CUTSTRATEGY: { - ctlBlk->setCliqueAction(action); - ctlBlk->setFlowAction(action); - ctlBlk->setGomoryAction(action); - ctlBlk->setKnapsackAction(action); - ctlBlk->setMirAction(action); - ctlBlk->setProbingAction(action); - ctlBlk->setRedSplitAction(action); - ctlBlk->setTwomirAction(action); - break; - } - case CbcGenParam::COMBINE: { - ctlBlk->setCombineAction(action); - break; - } - case CbcGenParam::FPUMP: { - ctlBlk->setFPumpAction(action); - break; - } - case CbcGenParam::GREEDY: { - ctlBlk->setGreedyCoverAction(action); - ctlBlk->setGreedyEqualityAction(action); - break; - } - case CbcGenParam::LOCALTREE: { - ctlBlk->setTreeLocalAction(action); - break; - } - case CbcGenParam::ROUNDING: { - ctlBlk->setRoundingAction(action); - break; - } - case CbcGenParam::HEURISTICSTRATEGY: { - ctlBlk->setCombineAction(action); - ctlBlk->setFPumpAction(action); - ctlBlk->setGreedyCoverAction(action); - ctlBlk->setRoundingAction(action); - ctlBlk->setTreeLocalAction(action); - break; - } - default: { - std::cerr - << "pushCbcGenCutParam: internal confusion!" << std::endl; - return (-1); - } - } - - return (0); -} - -/* - This routine imports a new constraint system into the solver. -*/ - -int doImportParam(CoinParam *param) - -{ - assert(param != 0); - CbcGenParam *genParam = dynamic_cast< CbcGenParam * >(param); - assert(genParam != 0); - CbcGenCtlBlk *ctlBlk = genParam->obj(); - assert(ctlBlk != 0); - /* - Setup to return nonfatal/fatal error (1/-1) by default, so that all we need - to do is correct to 0 (no error) if we're successful. - */ - int retval; - if (CoinParamUtils::isInteractive()) { - retval = 1; - } else { - retval = -1; - } - /* - Figure out where we're going to acquire this new model. As special cases, - `$' says `use the previous input source' and `-' says `use stdin'. - */ - std::string field = genParam->strVal(); - std::string fileName; - if (field == "$") { - fileName = ctlBlk->lastMpsIn_; - field = fileName; - } else if (field == "-") { - fileName = "stdin"; - field = fileName; - } else { - fileName = field; - } - /* - See if we can open a file. fileCoinReadable understands a fair bit about - platforms and compressed files and will try variations of the file name - (see the doxygen doc'n for details). The file name returned in field wil - be the one that actually worked. - */ - bool canOpen = fileCoinReadable(fileName, ctlBlk->dfltDirectory_); - if (canOpen == false) { - std::cout - << "Unable to open file `" << fileName - << "', original name '" << genParam->strVal() << "'." << std::endl; - return (retval); - } - /* - We can find the file. Record the name. This requires a little finesse: what - we want is the base file name (and extension(s), if present) but not the - prefix, unless it's an absolute path. - */ - if (!fileAbsPath(fileName)) { - std::string::size_type pos = fileName.rfind(field); - ctlBlk->lastMpsIn_ = fileName.substr(pos); - } else { - ctlBlk->lastMpsIn_ = fileName; - } - /* - Try to read the file. Standard OSI doesn't support the Clp extensions for - keepImportNames and allowImportErrors. It should at least support - keepImportNames. Status will be zero for a successful read. - */ - OsiSolverInterface *lpSolver = ctlBlk->model_->solver(); - int status = lpSolver->readMps(fileName.c_str(), ""); - if (status) { - std::cout - << "There were " << status << " errors on input." << std::endl; - return (retval); - } - /* - We have a model! Return success. - */ - ctlBlk->goodModel_ = true; - - return (0); -} - -/* - This routine imports a debug file into the solver, or arranges for its - creation. Import works in the standard way, using the file name provided - with the command. - - As special cases, if the file name is `create' or `createAfterPre', the - action here sets up to cause a debug file containing the solution to be - dumped after branch-and-cut is completed. `createAfterPre' will dump the - solution before undoing the presolve transforms. `create' will dump the - solution after integer presolve is backed out. -*/ - -int doDebugParam(CoinParam *param) - -{ - assert(param != 0); - CbcGenParam *genParam = dynamic_cast< CbcGenParam * >(param); - assert(genParam != 0); - CbcGenCtlBlk *ctlBlk = genParam->obj(); - assert(ctlBlk != 0); - /* - Setup to return nonfatal/fatal error (1/-1) by default, so that all we need - to do is correct to 0 (no error) if we're successful. - */ - int retval; - if (CoinParamUtils::isInteractive()) { - retval = 1; - } else { - retval = -1; - } - /* - If the file name is `create' or `createAfterPre', we're just setting up to - make a debug file the next time we do branch-and-cut. - */ - std::string field = genParam->strVal(); - if (field == "create" || field == "createAfterPre") { - ctlBlk->debugCreate_ = field; - return (0); - } - /* - Figure out where we're going to acquire the debug file. As special cases, - `$' says `use the previous input source' and `-' says `use stdin'. - */ - std::string fileName; - if (field == "$") { - fileName = ctlBlk->debugFile_; - field = fileName; - } else if (field == "-") { - fileName = "stdin"; - field = fileName; - } else { - fileName = field; - } - /* - See if we can open a file. fileCoinReadable understands a fair bit about - platforms and compressed files and will try variations of the file name - (see the doxygen doc'n for details). The file name returned in field wil be - the one that actually worked. No default prefix --- a debug file is assumed - to always be in the current directory. - */ - bool canOpen = fileCoinReadable(fileName, ctlBlk->dfltDirectory_); - if (canOpen == false) { - std::cout - << "Unable to open file `" << fileName - << "', original name '" << genParam->strVal() << "'." << std::endl; - return (retval); - } - /* - We can find the file. Record the name. This requires a little finesse: what - we want is the base file name (and extension(s), if present) but not the - prefix, unless it's an absolute path. - */ - if (!fileAbsPath(fileName)) { - std::string::size_type pos = fileName.rfind(field); - ctlBlk->lastMpsIn_ = fileName.substr(pos); - } else { - ctlBlk->lastMpsIn_ = fileName; - } - /* - Load the primal variable values into the debug solution vector. - */ - int intUnused, numCols; - double dblUnused; - double *primals; - - bool readOK = readSolution(fileName, - intUnused, numCols, dblUnused, 0, 0, &primals, 0); - - if (readOK) { - if (ctlBlk->debugSol_.values_) { - delete[] ctlBlk->debugSol_.values_; - } - ctlBlk->debugSol_.numCols_ = numCols; - ctlBlk->debugSol_.values_ = primals; - retval = 0; - } else { - if (primals) { - delete[] primals; - } - } - - return (retval); -} - -/* - Utility routine to save the current solution to a file. No formatting, and - not intended to be portable in any way, shape, or form. -*/ - -void saveSolution(const OsiSolverInterface *osi, std::string fileName) - -{ - FILE *fp = fopen(fileName.c_str(), "wb"); - - if (fp) { - int numberRows = osi->getNumRows(); - int numberColumns = osi->getNumCols(); - double objectiveValue = osi->getObjValue(); - - fwrite(&numberRows, sizeof(int), 1, fp); - fwrite(&numberColumns, sizeof(int), 1, fp); - fwrite(&objectiveValue, sizeof(double), 1, fp); - - const double *primalRowSolution = osi->getRowActivity(); - const double *dualRowSolution = osi->getRowPrice(); - const double *primalColumnSolution = osi->getColSolution(); - const double *dualColumnSolution = osi->getReducedCost(); - - fwrite(primalRowSolution, sizeof(double), numberRows, fp); - fwrite(dualRowSolution, sizeof(double), numberRows, fp); - fwrite(primalColumnSolution, sizeof(double), numberColumns, fp); - fwrite(dualColumnSolution, sizeof(double), numberColumns, fp); - - fclose(fp); - } else { - std::cout - << "saveSolution: Unable to open file `" - << fileName << "'." << std::endl; - } - - return; -} - -/* - Utility routine to read in a solution dump created by saveSolution. Generally - we don't need all the info in this file, so the routine accepts a bunch of - reference/pointer paramaters and fills in any that are non-null. It's the - client's responsibility to dispose of space allocated for solution vectors. - The parameters fileName, numRows, numCols, and objVal are mandatory. The rest - can be null. -*/ -bool readSolution(std::string fileName, - int &numRows, int &numCols, double &objVal, - double **rowActivity, double **dualVars, - double **primalVars, double **reducedCosts) - -{ - FILE *fp = fopen(fileName.c_str(), "rb"); - bool retval = true; - - numRows = -1; - numCols = -1; - objVal = 0; - *rowActivity = 0; - *dualVars = 0; - *primalVars = 0; - *reducedCosts = 0; - - if (fp) { - fread(&numRows, sizeof(int), 1, fp); - fread(&numCols, sizeof(int), 1, fp); - fread(&objVal, sizeof(double), 1, fp); - - if (rowActivity != NULL) { - *rowActivity = new double[numRows]; - fread(*rowActivity, sizeof(double), numRows, fp); - } else { - fseek(fp, numRows * sizeof(double), SEEK_CUR); - } - - if (dualVars != NULL) { - *dualVars = new double[numRows]; - fread(*dualVars, sizeof(double), numRows, fp); - } else { - fseek(fp, numRows * sizeof(double), SEEK_CUR); - } - - if (primalVars != NULL) { - *primalVars = new double[numCols]; - fread(*primalVars, sizeof(double), numCols, fp); - } else { - fseek(fp, numCols * sizeof(double), SEEK_CUR); - } - - if (reducedCosts != NULL) { - *reducedCosts = new double[numCols]; - fread(*reducedCosts, sizeof(double), numCols, fp); - } else { - fseek(fp, numCols * sizeof(double), SEEK_CUR); - } - - fclose(fp); - } else { - std::cout - << "readSolution: Unable to open file `" - << fileName << "'." << std::endl; - retval = false; - } - - return (retval); -} - -} // end namespace CbcGenParamUtils - -/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 -*/ diff --git a/src/CbcGeneralDepth.cpp b/src/CbcGeneralDepth.cpp index 7ed35f7e2..651b1949e 100644 --- a/src/CbcGeneralDepth.cpp +++ b/src/CbcGeneralDepth.cpp @@ -191,6 +191,7 @@ CbcGeneralDepth::infeasibility(const OsiBranchingInformation * /*info*/, info->presolveType_ = 1; delete[] down; delete[] up; + delete[] priority; delete[] numberDown; delete[] numberUp; delete[] numberDownInfeasible; diff --git a/src/CbcHeuristic.cpp b/src/CbcHeuristic.cpp index 0f396d14a..d7138b2d8 100644 --- a/src/CbcHeuristic.cpp +++ b/src/CbcHeuristic.cpp @@ -959,6 +959,10 @@ int CbcHeuristic::smallBranchAndBound(OsiSolverInterface *solver, int numberNode #endif #ifdef CBC_HAS_CLP OsiClpSolverInterface *clpSolver = dynamic_cast< OsiClpSolverInterface * >(solver); + if (clpSolver) { + clpSolver->getModelPtr()->cleanSolver(); + clpSolver->getModelPtr()->setWhatsChanged(0); + } // See if SOS if (clpSolver && clpSolver->numberSOS()) { // SOS @@ -2209,7 +2213,6 @@ int CbcRounding::solution(double &solutionValue, } } - double penalty = 0.0; // see if feasible - just using singletons for (i = 0; i < numberRows; i++) { double value = rowActivity[i]; @@ -2296,9 +2299,16 @@ int CbcRounding::solution(double &solutionValue, newSolutionValue += addCost; rowActivity[i] += changeRowActivity; } - penalty += fabs(thisInfeasibility); } } + double penalty = 0.0; + // integer variables may have wandered + for (i = 0; i < numberIntegers; i++) { + int iColumn = integerVariable[i]; + double value = newSolution[iColumn]; + if (fabs(floor(value + 0.5) - value) > integerTolerance) + penalty += fabs(floor(value + 0.5) - value); + } if (penalty) { // see if feasible using any // first continuous diff --git a/src/CbcHeuristicPivotAndFix.cpp b/src/CbcHeuristicPivotAndFix.cpp index 93aea59d1..286216803 100644 --- a/src/CbcHeuristicPivotAndFix.cpp +++ b/src/CbcHeuristicPivotAndFix.cpp @@ -84,7 +84,7 @@ int CbcHeuristicPivotAndFix::solution(double & /*solutionValue*/, { numCouldRun_++; // Todo: Ask JJHF what this for. - std::cout << "Entering Pivot-and-Fix Heuristic" << std::endl; + //std::cout << "Entering Pivot-and-Fix Heuristic" << std::endl; #ifdef HEURISTIC_INFORM printf("Entering heuristic %s - nRuns %d numCould %d when %d\n", diff --git a/src/CbcLinked.cpp b/src/CbcLinked.cpp index d5b6d5473..5a6e2276e 100644 --- a/src/CbcLinked.cpp +++ b/src/CbcLinked.cpp @@ -2,7 +2,7 @@ // Corporation and others. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). -#include "CbcSolverConfig.h" +#include "CbcConfig.h" #include "CoinTime.hpp" @@ -5216,7 +5216,7 @@ void OsiBiLinear::addExtraRow(int row, double multiplier) delete[] multiplier_; multiplier_ = tempD; } -static bool testCoarse = true; +static const bool testCoarse = true; // Infeasibility - large is 0.5 double OsiBiLinear::infeasibility(const OsiBranchingInformation *info, int &whichWay) const diff --git a/src/CbcLinked.hpp b/src/CbcLinked.hpp index a381641c6..82524fb11 100644 --- a/src/CbcLinked.hpp +++ b/src/CbcLinked.hpp @@ -13,7 +13,7 @@ #include "OsiClpSolverInterface.hpp" #include "OsiChooseVariable.hpp" #include "CbcFathom.hpp" -#include "CbcSolverConfig.h" +#include "CbcConfig.h" class CbcModel; class CoinPackedMatrix; class OsiLinkedBound; @@ -26,7 +26,7 @@ This is to allow the user to replace initialSolve and resolve This version changes coefficients */ -class CBCSOLVERLIB_EXPORT OsiSolverLink : public CbcOsiSolver { +class CBCLIB_EXPORT OsiSolverLink : public CbcOsiSolver { public: //--------------------------------------------------------------------------- @@ -311,7 +311,7 @@ class CBCSOLVERLIB_EXPORT OsiSolverLink : public CbcOsiSolver { List of bounds which depend on other bounds */ -class CBCSOLVERLIB_EXPORT OsiLinkedBound { +class CBCLIB_EXPORT OsiLinkedBound { public: //--------------------------------------------------------------------------- @@ -390,7 +390,7 @@ class CBCSOLVERLIB_EXPORT OsiLinkedBound { /** heuristic - just picks up any good solution */ -class CBCSOLVERLIB_EXPORT CbcHeuristicDynamic3 : public CbcHeuristic { +class CBCLIB_EXPORT CbcHeuristicDynamic3 : public CbcHeuristic { public: // Default Constructor CbcHeuristicDynamic3(); @@ -444,7 +444,7 @@ class CBCSOLVERLIB_EXPORT CbcHeuristicDynamic3 : public CbcHeuristic { */ class CoinWarmStartBasis; -class CBCSOLVERLIB_EXPORT OsiOldLink : public OsiSOS { +class CBCLIB_EXPORT OsiOldLink : public OsiSOS { public: // Default Constructor @@ -530,7 +530,7 @@ class CBCSOLVERLIB_EXPORT OsiOldLink : public OsiSOS { /** Branching object for Linked ordered sets */ -class CBCSOLVERLIB_EXPORT OsiOldLinkBranchingObject : public OsiSOSBranchingObject { +class CBCLIB_EXPORT OsiOldLinkBranchingObject : public OsiSOSBranchingObject { public: // Default Constructor @@ -569,7 +569,7 @@ class CBCSOLVERLIB_EXPORT OsiOldLinkBranchingObject : public OsiSOSBranchingObje */ -class CBCSOLVERLIB_EXPORT OsiOneLink { +class CBCLIB_EXPORT OsiOneLink { public: // Default Constructor @@ -609,7 +609,7 @@ class CBCSOLVERLIB_EXPORT OsiOneLink { */ -class CBCSOLVERLIB_EXPORT OsiLink : public OsiSOS { +class CBCLIB_EXPORT OsiLink : public OsiSOS { public: // Default Constructor @@ -689,7 +689,7 @@ class CBCSOLVERLIB_EXPORT OsiLink : public OsiSOS { /** Branching object for Linked ordered sets */ -class CBCSOLVERLIB_EXPORT OsiLinkBranchingObject : public OsiTwoWayBranchingObject { +class CBCLIB_EXPORT OsiLinkBranchingObject : public OsiTwoWayBranchingObject { public: // Default Constructor @@ -730,7 +730,7 @@ class CBCSOLVERLIB_EXPORT OsiLinkBranchingObject : public OsiTwoWayBranchingObje */ -class CBCSOLVERLIB_EXPORT OsiBiLinear : public OsiObject2 { +class CBCLIB_EXPORT OsiBiLinear : public OsiObject2 { public: // Default Constructor @@ -1028,7 +1028,7 @@ class CBCSOLVERLIB_EXPORT OsiBiLinear : public OsiObject2 { /** Branching object for BiLinear objects */ -class CBCSOLVERLIB_EXPORT OsiBiLinearBranchingObject : public OsiTwoWayBranchingObject { +class CBCLIB_EXPORT OsiBiLinearBranchingObject : public OsiTwoWayBranchingObject { public: // Default Constructor @@ -1074,7 +1074,7 @@ class CBCSOLVERLIB_EXPORT OsiBiLinearBranchingObject : public OsiTwoWayBranching */ -class CBCSOLVERLIB_EXPORT OsiBiLinearEquality : public OsiBiLinear { +class CBCLIB_EXPORT OsiBiLinearEquality : public OsiBiLinear { public: // Default Constructor @@ -1125,7 +1125,7 @@ class CBCSOLVERLIB_EXPORT OsiBiLinearEquality : public OsiBiLinear { }; /// Define a single integer class - but one where you keep branching until fixed even if satisfied -class CBCSOLVERLIB_EXPORT OsiSimpleFixedInteger : public OsiSimpleInteger { +class CBCLIB_EXPORT OsiSimpleFixedInteger : public OsiSimpleInteger { public: /// Default Constructor @@ -1173,7 +1173,7 @@ class CBCSOLVERLIB_EXPORT OsiSimpleFixedInteger : public OsiSimpleInteger { even if not an integer variable. If not then need to duplicate code. */ -class CBCSOLVERLIB_EXPORT OsiUsesBiLinear : public OsiSimpleInteger { +class CBCLIB_EXPORT OsiUsesBiLinear : public OsiSimpleInteger { public: /// Default Constructor @@ -1237,7 +1237,7 @@ class CBCSOLVERLIB_EXPORT OsiUsesBiLinear : public OsiSimpleInteger { */ -class CBCSOLVERLIB_EXPORT OsiChooseStrongSubset : public OsiChooseStrong { +class CBCLIB_EXPORT OsiChooseStrongSubset : public OsiChooseStrong { public: /// Default Constructor @@ -1301,7 +1301,7 @@ class CBCSOLVERLIB_EXPORT OsiChooseStrongSubset : public OsiChooseStrong { class CoinWarmStartBasis; /** Stored Temporary Cut Generator Class - destroyed after first use */ -class CBCSOLVERLIB_EXPORT CglTemporary : public CglStored { +class CBCLIB_EXPORT CglTemporary : public CglStored { public: /**@name Generate Cuts */ @@ -1349,7 +1349,7 @@ class CBCSOLVERLIB_EXPORT CglTemporary : public CglStored { This is to allow the user to replace initialSolve and resolve */ -class CBCSOLVERLIB_EXPORT OsiSolverLinearizedQuadratic : public OsiClpSolverInterface { +class CBCLIB_EXPORT OsiSolverLinearizedQuadratic : public OsiClpSolverInterface { public: //--------------------------------------------------------------------------- diff --git a/src/CbcLinkedUtils.cpp b/src/CbcLinkedUtils.cpp index d8cf60b07..b3d144d2a 100644 --- a/src/CbcLinkedUtils.cpp +++ b/src/CbcLinkedUtils.cpp @@ -18,7 +18,6 @@ */ #include "ClpConfig.h" -#include "CbcSolverConfig.h" #ifdef CBC_HAS_ASL #include "CoinPragma.hpp" #include "CoinHelperFunctions.hpp" diff --git a/src/CbcMessage.hpp b/src/CbcMessage.hpp index af62061c2..524fb5a54 100644 --- a/src/CbcMessage.hpp +++ b/src/CbcMessage.hpp @@ -72,6 +72,7 @@ enum CBC_Message { CBC_RELAXED2, CBC_RESTART, CBC_GENERAL, + CBC_GENERAL_WARNING, CBC_ROOT_DETAIL, #ifndef NO_FATHOM_PRINT CBC_FATHOM_CHANGE, diff --git a/src/CbcMipStartIO.hpp b/src/CbcMipStartIO.hpp index 6bf92ca72..9da27c0c5 100644 --- a/src/CbcMipStartIO.hpp +++ b/src/CbcMipStartIO.hpp @@ -5,14 +5,14 @@ #include #include -#include "CbcSolverConfig.h" +#include "CbcConfig.h" class CbcModel; class OsiSolverInterface; class CoinMessageHandler; class CoinMessages; -class CBCSOLVERLIB_EXPORT CbcMipStartIO{ +class CBCLIB_EXPORT CbcMipStartIO{ public: /* tries to read mipstart (solution file) from fileName, filling colValues and obj diff --git a/src/CbcModel.cpp b/src/CbcModel.cpp index b0291c428..ff539e229 100644 --- a/src/CbcModel.cpp +++ b/src/CbcModel.cpp @@ -20,62 +20,62 @@ extern int gomory_try; #endif #include -#include #include +#include #ifdef CBC_HAS_CLP // include Presolve from Clp -#include "ClpPresolve.hpp" -#include "OsiClpSolverInterface.hpp" -#include "ClpNode.hpp" #include "ClpDualRowDantzig.hpp" +#include "ClpNode.hpp" +#include "ClpPresolve.hpp" #include "ClpSimplexPrimal.hpp" +#include "OsiClpSolverInterface.hpp" #endif #include "CbcEventHandler.hpp" -#include "OsiSolverInterface.hpp" -#include "OsiAuxInfo.hpp" -#include "OsiSolverBranch.hpp" -#include "OsiChooseVariable.hpp" -#include "CoinWarmStartBasis.hpp" -#include "CoinPackedMatrix.hpp" -#include "CoinHelperFunctions.hpp" #include "CbcBranchActual.hpp" #include "CbcBranchDynamic.hpp" +#include "CbcCountRowCut.hpp" +#include "CbcCutGenerator.hpp" +#include "CbcFathom.hpp" +#include "CbcFeasibilityBase.hpp" +#include "CbcFullNodeInfo.hpp" #include "CbcHeuristic.hpp" +#include "CbcHeuristicDive.hpp" #include "CbcHeuristicFPump.hpp" #include "CbcHeuristicRINS.hpp" -#include "CbcHeuristicDive.hpp" +#include "CbcMessage.hpp" #include "CbcModel.hpp" -#include "CbcTreeLocal.hpp" #include "CbcStatistics.hpp" #include "CbcStrategy.hpp" -#include "CbcMessage.hpp" -#include "OsiRowCut.hpp" +#include "CbcTreeLocal.hpp" +#include "CoinHelperFunctions.hpp" +#include "CoinPackedMatrix.hpp" +#include "CoinWarmStartBasis.hpp" +#include "OsiAuxInfo.hpp" +#include "OsiChooseVariable.hpp" #include "OsiColCut.hpp" -#include "OsiRowCutDebugger.hpp" #include "OsiCuts.hpp" -#include "CbcCountRowCut.hpp" -#include "CbcCutGenerator.hpp" -#include "CbcFeasibilityBase.hpp" -#include "CbcFathom.hpp" -#include "CbcFullNodeInfo.hpp" +#include "OsiRowCut.hpp" +#include "OsiRowCutDebugger.hpp" +#include "OsiSolverBranch.hpp" +#include "OsiSolverInterface.hpp" #ifdef CBC_HAS_NAUTY #include "CbcSymmetry.hpp" #endif // include Probing -#include "CglProbing.hpp" #include "CglGomory.hpp" +#include "CglProbing.hpp" #include "CglTwomir.hpp" // include preprocessing -#include "CglPreProcess.hpp" -#include "CglDuplicateRow.hpp" -#include "CglStored.hpp" #include "CglClique.hpp" +#include "CglDuplicateRow.hpp" #include "CglKnapsackCover.hpp" +#include "CglPreProcess.hpp" +#include "CglStored.hpp" -#include "CoinTime.hpp" #include "CoinMpsIO.hpp" +#include "CoinTime.hpp" #include "CbcCompareActual.hpp" #include "CbcCompareObjective.hpp" @@ -98,8 +98,7 @@ namespace { // Returns the greatest common denominator of two // positive integers, a and b, found using Euclid's algorithm //------------------------------------------------------------------- -static int gcd(int a, int b) -{ +static int gcd(int a, int b) { int remainder = -1; // make sure a<=b (will always remain so) if (a > b) { @@ -153,14 +152,14 @@ void verifyTreeNodes(const CbcTree *branchingTree, const CbcModel &model) CbcNodeInfo **info = new CbcNodeInfo *[MAXINFO]; int nInfo = 0; /* - Collect all CbcNodeInfo objects in info, by starting from each live node and - traversing back to the root. Nodes in the live set should have unexplored - branches remaining. + Collect all CbcNodeInfo objects in info, by starting from each live node + and traversing back to the root. Nodes in the live set should have + unexplored branches remaining. TODO: The `while (nodeInfo)' loop could be made to break on reaching a - common ancester (nodeInfo is found in info[k]). Alternatively, the - check could change to signal an error if nodeInfo is not found above a - common ancestor. + common ancester (nodeInfo is found in info[k]). Alternatively, the + check could change to signal an error if nodeInfo is not found above a + common ancestor. */ for (j = 0; j < nNodes; j++) { CbcNode *node = branchingTree->nodePointer(j); @@ -214,11 +213,10 @@ void verifyTreeNodes(const CbcTree *branchingTree, const CbcModel &model) for (k = 0; k < nInfo; k++) if (nodeInfo == info[k]) break; - printf("Nodeinfo %x - %d left, %d count\n", - nodeInfo, - nodeInfo->numberBranchesLeft(), - nodeInfo->numberPointingToThis()); - assert(nodeInfo->numberPointingToThis() == count[k] + nodeInfo->numberBranchesLeft()); + printf("Nodeinfo %x - %d left, %d count\n", nodeInfo, + nodeInfo->numberBranchesLeft(), nodeInfo->numberPointingToThis()); + assert(nodeInfo->numberPointingToThis() == + count[k] + nodeInfo->numberBranchesLeft()); } } @@ -244,9 +242,9 @@ void verifyCutCounts(const CbcTree *branchingTree, CbcModel &model) int nNodes = branchingTree->size(); /* - cut.tempNumber_ exists for the purpose of doing this verification. Clear it - in all cuts. We traverse the tree by starting from each live node and working - back to the root. At each CbcNodeInfo, check for cuts. + cut.tempNumber_ exists for the purpose of doing this verification. Clear + it in all cuts. We traverse the tree by starting from each live node and + working back to the root. At each CbcNodeInfo, check for cuts. */ for (j = 0; j < nNodes; j++) { CbcNode *node = branchingTree->nodePointer(j); @@ -263,9 +261,10 @@ void verifyCutCounts(const CbcTree *branchingTree, CbcModel &model) } } /* - Walk the live set again, this time collecting the list of cuts in use at each - node. addCuts1 will collect the cuts in model.addedCuts_. Take into account - that when we recreate the basis for a node, we compress out the slack cuts. + Walk the live set again, this time collecting the list of cuts in use at + each node. addCuts1 will collect the cuts in model.addedCuts_. Take into + account that when we recreate the basis for a node, we compress out the + slack cuts. */ for (j = 0; j < nNodes; j++) { CoinWarmStartBasis *debugws = model.getEmptyBasis(); @@ -273,8 +272,8 @@ void verifyCutCounts(const CbcTree *branchingTree, CbcModel &model) CbcNodeInfo *nodeInfo = node->nodeInfo(); int change = node->nodeInfo()->numberBranchesLeft(); printf("Node %d %x (info %x) var %d way %d obj %g", j, node, - node->nodeInfo(), node->columnNumber(), node->way(), - node->objectiveValue()); + node->nodeInfo(), node->columnNumber(), node->way(), + node->objectiveValue()); model.addCuts1(node, debugws); @@ -282,7 +281,8 @@ void verifyCutCounts(const CbcTree *branchingTree, CbcModel &model) int numberRowsAtContinuous = model.numberRowsAtContinuous(); CbcCountRowCut **addedCuts = model.addedCuts(); for (i = 0; i < model.currentNumberCuts(); i++) { - CoinWarmStartBasis::Status status = debugws->getArtifStatus(i + numberRowsAtContinuous); + CoinWarmStartBasis::Status status = + debugws->getArtifStatus(i + numberRowsAtContinuous); if (status != CoinWarmStartBasis::basic && addedCuts[i]) { addedCuts[i]->tempNumber_ += change; } @@ -297,7 +297,8 @@ void verifyCutCounts(const CbcTree *branchingTree, CbcModel &model) delete debugws; } /* - The moment of truth: We've tallied up the references by direct scan of the search tree. Check for agreement with the count in the cut. + The moment of truth: We've tallied up the references by direct scan of the + search tree. Check for agreement with the count in the cut. TODO: Rewrite to check and print mismatch only when tempNumber_ == 0? */ @@ -310,11 +311,11 @@ void verifyCutCounts(const CbcTree *branchingTree, CbcModel &model) CbcCountRowCut *cut = nodeInfo->cuts()[k]; if (cut && cut->tempNumber_ >= 0) { if (cut->tempNumber_ != cut->numberPointingToThis()) - printf("mismatch %x %d %x %d %d\n", nodeInfo, k, - cut, cut->tempNumber_, cut->numberPointingToThis()); + printf("mismatch %x %d %x %d %d\n", nodeInfo, k, cut, + cut->tempNumber_, cut->numberPointingToThis()); else - printf(" match %x %d %x %d %d\n", nodeInfo, k, - cut, cut->tempNumber_, cut->numberPointingToThis()); + printf(" match %x %d %x %d %d\n", nodeInfo, k, cut, + cut->tempNumber_, cut->numberPointingToThis()); cut->tempNumber_ = -1; } } @@ -332,17 +333,16 @@ void verifyCutCounts(const CbcTree *branchingTree, CbcModel &model) /* Routine to verify that cut reference counts are correct. */ -void verifyCutSize(const CbcTree *branchingTree, CbcModel &model) -{ +void verifyCutSize(const CbcTree *branchingTree, CbcModel &model) { int j; int nNodes = branchingTree->size(); int totalCuts = 0; /* - cut.tempNumber_ exists for the purpose of doing this verification. Clear it - in all cuts. We traverse the tree by starting from each live node and working - back to the root. At each CbcNodeInfo, check for cuts. + cut.tempNumber_ exists for the purpose of doing this verification. Clear + it in all cuts. We traverse the tree by starting from each live node and + working back to the root. At each CbcNodeInfo, check for cuts. */ for (j = 0; j < nNodes; j++) { CbcNode *node = branchingTree->nodePointer(j); @@ -353,13 +353,14 @@ void verifyCutSize(const CbcTree *branchingTree, CbcModel &model) nodeInfo = nodeInfo->parent(); } } - printf("*** CHECKING cuts (size) after %d nodes - %d cuts\n", model.getNodeCount(), totalCuts); + printf("*** CHECKING cuts (size) after %d nodes - %d cuts\n", + model.getNodeCount(), totalCuts); return; } #endif /* CHECK_CUT_SIZE */ -} +} // namespace /* End unnamed namespace for CbcModel.cpp */ @@ -403,7 +404,8 @@ void CbcModel::analyzeObjective() int problemType = -1; const double *element = solver_->getMatrixByCol()->getElements(); const int *row = solver_->getMatrixByCol()->getIndices(); - const CoinBigIndex *columnStart = solver_->getMatrixByCol()->getVectorStarts(); + const CoinBigIndex *columnStart = + solver_->getMatrixByCol()->getVectorStarts(); const int *columnLength = solver_->getMatrixByCol()->getVectorLengths(); int numberInteger = 0; int numberIntegerObj = 0; @@ -434,7 +436,7 @@ void CbcModel::analyzeObjective() cost = objValue; else if (cost != objValue) cost = -COIN_DBL_MAX; - int gap = static_cast< int >(upper[iColumn] - lower[iColumn]); + int gap = static_cast(upper[iColumn] - lower[iColumn]); if (gap > 1) { numberGeneralIntegerObj++; numberIntegerWeight += gap; @@ -587,25 +589,36 @@ void CbcModel::analyzeObjective() #endif #endif int iType = 0; - if (!numberContinuousObj && numberIntegerObj <= 5 && numberIntegerWeight <= 100 && numberIntegerObj * 3 < numberObjects_ && !parentModel_ && solver_->getNumRows() > 100) + if (!numberContinuousObj && numberIntegerObj <= 5 && + numberIntegerWeight <= 100 && numberIntegerObj * 3 < numberObjects_ && + !parentModel_ && solver_->getNumRows() > 100) iType = 1 + 4 + (((moreSpecialOptions_ & 536870912) == 0) ? 2 : 0); - else if (!numberContinuousObj && numberIntegerObj <= 100 && numberIntegerObj * 5 < numberObjects_ && numberIntegerWeight <= 100 && !parentModel_ && solver_->getNumRows() > 100 && cost != -COIN_DBL_MAX) + else if (!numberContinuousObj && numberIntegerObj <= 100 && + numberIntegerObj * 5 < numberObjects_ && + numberIntegerWeight <= 100 && !parentModel_ && + solver_->getNumRows() > 100 && cost != -COIN_DBL_MAX) iType = 4 + (((moreSpecialOptions_ & 536870912) == 0) ? 2 : 0); - else if (!numberContinuousObj && numberIntegerObj <= 100 && numberIntegerObj * 5 < numberObjects_ && !parentModel_ && solver_->getNumRows() > 100 && cost != -COIN_DBL_MAX) + else if (!numberContinuousObj && numberIntegerObj <= 100 && + numberIntegerObj * 5 < numberObjects_ && !parentModel_ && + solver_->getNumRows() > 100 && cost != -COIN_DBL_MAX) iType = 8; int iTest = getMaximumNodes(); - if (iTest >= 987654320 && iTest < 987654330 && numberObjects_ && !parentModel_) { + if (iTest >= 987654320 && iTest < 987654330 && numberObjects_ && + !parentModel_) { iType = iTest - 987654320; - printf("Testing %d integer variables out of %d objects (%d integer) have cost of %g - %d continuous\n", - numberIntegerObj, numberObjects_, numberInteger, cost, numberContinuousObj); + printf("Testing %d integer variables out of %d objects (%d integer) have " + "cost of %g - %d continuous\n", + numberIntegerObj, numberObjects_, numberInteger, cost, + numberContinuousObj); if (iType == 9) exit(77); if (numberContinuousObj) iType = 0; } - //if (!numberContinuousObj&&(numberIntegerObj<=5||cost!=-COIN_DBL_MAX)&& - //numberIntegerObj*3getNumRows()>100) { + // if (!numberContinuousObj&&(numberIntegerObj<=5||cost!=-COIN_DBL_MAX)&& + // numberIntegerObj*3getNumRows()>100) + // { if (iType) { /* A) put high priority on (if none) @@ -625,31 +638,37 @@ void CbcModel::analyzeObjective() if (iPriority >= 0) { char general[200]; if (cost == -COIN_DBL_MAX) { - sprintf(general, "%d integer variables out of %d objects (%d integer) have costs - high priority", - numberIntegerObj, numberObjects_, numberInteger); + sprintf(general, + "%d integer variables out of %d objects (%d integer) have " + "costs - high priority", + numberIntegerObj, numberObjects_, numberInteger); } else if (cost == COIN_DBL_MAX) { - sprintf(general, "No integer variables out of %d objects (%d integer) have costs", - numberObjects_, numberInteger); + sprintf( + general, + "No integer variables out of %d objects (%d integer) have costs", + numberObjects_, numberInteger); branchOnSatisfied = false; } else { - sprintf(general, "%d integer variables out of %d objects (%d integer) have cost of %g - high priority", - numberIntegerObj, numberObjects_, numberInteger, cost); + sprintf(general, + "%d integer variables out of %d objects (%d integer) have " + "cost of %g - high priority", + numberIntegerObj, numberObjects_, numberInteger, cost); } - messageHandler()->message(CBC_GENERAL, - messages()) - << general << CoinMessageEol; - sprintf(general, "branch on satisfied %c create fake objective %c random cost %c", - branchOnSatisfied ? 'Y' : 'N', - createFake ? 'Y' : 'N', - randomCost ? 'Y' : 'N'); - messageHandler()->message(CBC_GENERAL, - messages()) - << general << CoinMessageEol; + messageHandler()->message(CBC_GENERAL, messages()) + << general << CoinMessageEol; + sprintf( + general, + "branch on satisfied %c create fake objective %c random cost %c", + branchOnSatisfied ? 'Y' : 'N', createFake ? 'Y' : 'N', + randomCost ? 'Y' : 'N'); + messageHandler()->message(CBC_GENERAL, messages()) + << general << CoinMessageEol; // switch off clp type branching // no ? fastNodeDepth_ = -1; int highPriority = (branchOnSatisfied) ? -999 : 100; for (int i = 0; i < numberObjects_; i++) { - CbcSimpleInteger *thisOne = dynamic_cast< CbcSimpleInteger * >(object_[i]); + CbcSimpleInteger *thisOne = + dynamic_cast(object_[i]); object_[i]->setPriority(1000); if (thisOne) { int iColumn = thisOne->columnNumber(); @@ -659,17 +678,17 @@ void CbcModel::analyzeObjective() } } #ifdef CBC_HAS_CLP - OsiClpSolverInterface *clpSolver - = dynamic_cast< OsiClpSolverInterface * >(solver_); + OsiClpSolverInterface *clpSolver = + dynamic_cast(solver_); if (clpSolver && createFake) { // Create artificial objective to be used when all else fixed int numberColumns = clpSolver->getNumCols(); double *fakeObj = new double[numberColumns]; // Column copy const CoinPackedMatrix *matrixByCol = clpSolver->getMatrixByCol(); - //const double * element = matrixByCol.getElements(); - //const int * row = matrixByCol.getIndices(); - //const CoinBigIndex * columnStart = matrixByCol.getVectorStarts(); + // const double * element = matrixByCol.getElements(); + // const int * row = matrixByCol.getIndices(); + // const CoinBigIndex * columnStart = matrixByCol.getVectorStarts(); const int *columnLength = matrixByCol->getVectorLengths(); const double *solution = clpSolver->getColSolution(); #ifdef JJF_ZERO @@ -687,9 +706,9 @@ void CbcModel::analyzeObjective() } #endif /* - Generate a random objective function for problems where the given objective - function is not terribly useful. (Nearly feasible, single integer variable, - that sort of thing. + Generate a random objective function for problems where the + given objective function is not terribly useful. (Nearly feasible, + single integer variable, that sort of thing. */ CoinDrand48(true, 1234567); for (int i = 0; i < numberColumns; i++) { @@ -698,7 +717,7 @@ void CbcModel::analyzeObjective() double value = (randomCost) ? ceil((CoinDrand48() + 0.5) * 1000) : i + 1 + columnLength[i] * 1000; value *= 0.001; - //value += columnLength[i]; + // value += columnLength[i]; if (lowerValue > -1.0e5 || upperValue < 1.0e5) { if (fabs(lowerValue) > fabs(upperValue)) value = -value; @@ -706,7 +725,7 @@ void CbcModel::analyzeObjective() double solValue = solution[i]; // Better to add in 0.5 or 1.0?? if (solValue < lowerValue + 1.0e-6) - value = fabs(value) + 0.5; //fabs(value*1.5); + value = fabs(value) + 0.5; // fabs(value*1.5); else if (solValue > upperValue - 1.0e-6) value = -fabs(value) - 0.5; //-fabs(value*1.5); } @@ -720,7 +739,9 @@ void CbcModel::analyzeObjective() delete[] fakeObj; } #endif - } else if (largestObj < smallestObj * 5.0 && !parentModel_ && !numberContinuousObj && !numberGeneralIntegerObj && numberIntegerObj * 2 < CoinMin(numberColumns, 20)) { + } else if (largestObj < smallestObj * 5.0 && !parentModel_ && + !numberContinuousObj && !numberGeneralIntegerObj && + numberIntegerObj * 2 < CoinMin(numberColumns, 20)) { // up priorities on costed int iPriority = -1; for (int i = 0; i < numberObjects_; i++) { @@ -735,7 +756,7 @@ void CbcModel::analyzeObjective() printf("Setting variables with obj to high priority\n"); #endif for (int i = 0; i < numberObjects_; i++) { - CbcSimpleInteger *obj = dynamic_cast< CbcSimpleInteger * >(object_[i]); + CbcSimpleInteger *obj = dynamic_cast(object_[i]); if (obj) { int iColumn = obj->columnNumber(); if (objective[iColumn]) @@ -746,11 +767,15 @@ void CbcModel::analyzeObjective() } int iRow; for (iRow = 0; iRow < numberRows; iRow++) { - if (rowLower[iRow] > -1.0e20 && fabs(rowLower[iRow] - rhs[iRow] - floor(rowLower[iRow] - rhs[iRow] + 0.5)) > 1.0e-10) { + if (rowLower[iRow] > -1.0e20 && + fabs(rowLower[iRow] - rhs[iRow] - + floor(rowLower[iRow] - rhs[iRow] + 0.5)) > 1.0e-10) { continuousMultiplier = 0.0; break; } - if (rowUpper[iRow] < 1.0e20 && fabs(rowUpper[iRow] - rhs[iRow] - floor(rowUpper[iRow] - rhs[iRow] + 0.5)) > 1.0e-10) { + if (rowUpper[iRow] < 1.0e20 && + fabs(rowUpper[iRow] - rhs[iRow] - + floor(rowUpper[iRow] - rhs[iRow] + 0.5)) > 1.0e-10) { continuousMultiplier = 0.0; break; } @@ -964,10 +989,14 @@ void CbcModel::analyzeObjective() CoinBigIndex end = start + columnLength[iColumn]; if (objValue > 0.0) { // wants to be as low as possible - if (lower[iColumn] < -1.0e10 || fabs(lower[iColumn] - floor(lower[iColumn] + 0.5)) > 1.0e-10) { + if (lower[iColumn] < -1.0e10 || + fabs(lower[iColumn] - floor(lower[iColumn] + 0.5)) > + 1.0e-10) { allGood = false; break; - } else if (upper[iColumn] < 1.0e10 && fabs(upper[iColumn] - floor(upper[iColumn] + 0.5)) > 1.0e-10) { + } else if (upper[iColumn] < 1.0e10 && + fabs(upper[iColumn] - floor(upper[iColumn] + 0.5)) > + 1.0e-10) { allGood = false; break; } @@ -988,20 +1017,23 @@ void CbcModel::analyzeObjective() if (upperValue < 1.0e20) upperValue -= rhsValue; } - if (fabs(rhsValue) > 1.0e20 || fabs(rhsValue - floor(rhsValue + 0.5)) > 1.0e-10 - || fabs(element[j]) != 1.0) { + if (fabs(rhsValue) > 1.0e20 || + fabs(rhsValue - floor(rhsValue + 0.5)) > 1.0e-10 || + fabs(element[j]) != 1.0) { // no good allGood = false; break; } if (element[j] > 0.0) { - if (lowerValue > -1.0e20 && fabs(lowerValue - floor(lowerValue + 0.5)) > 1.0e-10) { + if (lowerValue > -1.0e20 && + fabs(lowerValue - floor(lowerValue + 0.5)) > 1.0e-10) { // no good allGood = false; break; } } else { - if (upperValue < 1.0e20 && fabs(upperValue - floor(upperValue + 0.5)) > 1.0e-10) { + if (upperValue < 1.0e20 && + fabs(upperValue - floor(upperValue + 0.5)) > 1.0e-10) { // no good allGood = false; break; @@ -1014,10 +1046,14 @@ void CbcModel::analyzeObjective() break; } else { // wants to be as high as possible - if (upper[iColumn] > 1.0e10 || fabs(upper[iColumn] - floor(upper[iColumn] + 0.5)) > 1.0e-10) { + if (upper[iColumn] > 1.0e10 || + fabs(upper[iColumn] - floor(upper[iColumn] + 0.5)) > + 1.0e-10) { allGood = false; break; - } else if (lower[iColumn] > -1.0e10 && fabs(lower[iColumn] - floor(lower[iColumn] + 0.5)) > 1.0e-10) { + } else if (lower[iColumn] > -1.0e10 && + fabs(lower[iColumn] - floor(lower[iColumn] + 0.5)) > + 1.0e-10) { allGood = false; break; } @@ -1038,20 +1074,23 @@ void CbcModel::analyzeObjective() if (upperValue < 1.0e20) upperValue -= rhsValue; } - if (fabs(rhsValue) > 1.0e20 || fabs(rhsValue - floor(rhsValue + 0.5)) > 1.0e-10 - || fabs(element[j]) != 1.0) { + if (fabs(rhsValue) > 1.0e20 || + fabs(rhsValue - floor(rhsValue + 0.5)) > 1.0e-10 || + fabs(element[j]) != 1.0) { // no good allGood = false; break; } if (element[j] < 0.0) { - if (lowerValue > -1.0e20 && fabs(lowerValue - floor(lowerValue + 0.5)) > 1.0e-10) { + if (lowerValue > -1.0e20 && + fabs(lowerValue - floor(lowerValue + 0.5)) > 1.0e-10) { // no good allGood = false; break; } } else { - if (upperValue < 1.0e20 && fabs(upperValue - floor(upperValue + 0.5)) > 1.0e-10) { + if (upperValue < 1.0e20 && + fabs(upperValue - floor(upperValue + 0.5)) > 1.0e-10) { // no good allGood = false; break; @@ -1070,7 +1109,8 @@ void CbcModel::analyzeObjective() if (allGood) { #if COIN_DEVELOP > 1 if (numberObj) - printf("YYYY analysis says all continuous with costs will be integer\n"); + printf( + "YYYY analysis says all continuous with costs will be integer\n"); #endif continuousMultiplier = 1.0; } @@ -1079,14 +1119,15 @@ void CbcModel::analyzeObjective() } /* Take a first scan to see if there are unfixed continuous variables in the - objective. If so, the minimum objective change could be arbitrarily small. - Also pick off the maximum coefficient of an unfixed integer variable. + objective. If so, the minimum objective change could be arbitrarily + small. Also pick off the maximum coefficient of an unfixed integer + variable. If the objective is found to contain only integer variables, set the fathoming discipline to strict. */ double maximumCost = 0.0; - //double trueIncrement=0.0; + // double trueIncrement=0.0; int iColumn; int numberColumns = getNumCols(); double scaleFactor = 1.0; // due to rhs etc @@ -1132,8 +1173,8 @@ void CbcModel::analyzeObjective() } setIntParam(CbcModel::CbcFathomDiscipline, possibleMultiple); /* - If a nontrivial increment is possible, try and figure it out. We're looking - for gcd(c) for all c that are coefficients of unfixed integer + If a nontrivial increment is possible, try and figure it out. We're + looking for gcd(c) for all c that are coefficients of unfixed integer variables. Since the c might not be integers, try and inflate them sufficiently that they look like integers (and we'll deflate the gcd later). @@ -1158,7 +1199,7 @@ void CbcModel::analyzeObjective() if (objValue) { double value = objValue * multiplier; if (value < 2.1e9) { - int nearest = static_cast< int >(floor(value + 0.5)); + int nearest = static_cast(floor(value + 0.5)); if (fabs(value - floor(value + 0.5)) > 1.0e-8) { increment = 0; break; @@ -1180,34 +1221,35 @@ void CbcModel::analyzeObjective() } } if (coeffMultiplier) { - delete[] coeffMultiplier; - coeffMultiplier = NULL; + delete[] coeffMultiplier; + coeffMultiplier = NULL; } /* - If the increment beats the current value for objective change, install it. + If the increment beats the current value for objective change, install + it. */ if (increment) { double value = increment; double cutoff = getDblParam(CbcModel::CbcCutoffIncrement); if (bigIntegers) { // allow for 1.0 - increment = gcd(increment, static_cast< int >(multiplier)); + increment = gcd(increment, static_cast(multiplier)); value = increment; } value /= multiplier; value *= scaleFactor; - //trueIncrement=CoinMax(cutoff,value);; + // trueIncrement=CoinMax(cutoff,value);; if (value * 0.999 > cutoff) { - messageHandler()->message(CBC_INTEGERINCREMENT, - messages()) - << value << CoinMessageEol; - setDblParam(CbcModel::CbcCutoffIncrement, CoinMax(value * 0.999, value - 1.0e-4)); + messageHandler()->message(CBC_INTEGERINCREMENT, messages()) + << value << CoinMessageEol; + setDblParam(CbcModel::CbcCutoffIncrement, + CoinMax(value * 0.999, value - 1.0e-4)); } } } if (coeffMultiplier) - delete[] coeffMultiplier; + delete[] coeffMultiplier; return; } @@ -1215,22 +1257,23 @@ void CbcModel::analyzeObjective() /* saveModel called (carved out of) BranchandBound */ -void CbcModel::saveModel(OsiSolverInterface *saveSolver, double *checkCutoffForRestart, bool *feasible) -{ +void CbcModel::saveModel(OsiSolverInterface *saveSolver, + double *checkCutoffForRestart, bool *feasible) { if (saveSolver && (specialOptions_ & 32768) != 0) { // See if worth trying reduction *checkCutoffForRestart = getCutoff(); bool tryNewSearch = solverCharacteristics_->reducedCostsAccurate() - /*&& (*checkCutoffForRestart < 1.0e20)*/; + /*&& (*checkCutoffForRestart < 1.0e20)*/; int numberColumns = getNumCols(); if (tryNewSearch) { #if CBC_USEFUL_PRINTING > 1 - printf("after %d nodes, cutoff %g - looking\n", - numberNodes_, getCutoff()); + printf("after %d nodes, cutoff %g - looking\n", numberNodes_, + getCutoff()); #endif saveSolver->resolve(); double direction = saveSolver->getObjSense(); - double gap = *checkCutoffForRestart - saveSolver->getObjValue() * direction; + double gap = + *checkCutoffForRestart - saveSolver->getObjValue() * direction; double tolerance; saveSolver->getDblParam(OsiDualTolerance, tolerance); if (gap <= 0.0) @@ -1267,10 +1310,12 @@ void CbcModel::saveModel(OsiSolverInterface *saveSolver, double *checkCutoffForR int iColumn = integerVariable_[i]; double djValue = direction * reducedCost[iColumn]; if (upper[iColumn] - lower[iColumn] > integerTolerance) { - if (solution[iColumn] < lower[iColumn] + integerTolerance && djValue > gap) { + if (solution[iColumn] < lower[iColumn] + integerTolerance && + djValue > gap) { saveSolver->setColUpper(iColumn, lower[iColumn]); numberFixed++; - } else if (solution[iColumn] > upper[iColumn] - integerTolerance && -djValue > gap) { + } else if (solution[iColumn] > upper[iColumn] - integerTolerance && + -djValue > gap) { saveSolver->setColLower(iColumn, upper[iColumn]); numberFixed++; } @@ -1307,7 +1352,7 @@ void CbcModel::saveModel(OsiSolverInterface *saveSolver, double *checkCutoffForR } } printf("Restart could fix %d integers (%d already fixed)\n", - numberFixed + numberFixed2, numberFixed2); + numberFixed + numberFixed2, numberFixed2); #endif #ifdef CBC_HAS_NAUTY2 if (rootSymmetryInfo_ && (moreSpecialOptions2_ & 131072) != 0) { @@ -1349,14 +1394,13 @@ void CbcModel::saveModel(OsiSolverInterface *saveSolver, double *checkCutoffForR { int iGenerator; for (iGenerator = 0; iGenerator < numberCutGenerators_; iGenerator++) { - CglCutGenerator *generator = - generator_[iGenerator]->generator(); - - if (generator->needsOriginalModel()) - break; + CglCutGenerator *generator = generator_[iGenerator]->generator(); + + if (generator->needsOriginalModel()) + break; } if (iGenerator < numberCutGenerators_) - tryNewSearch=false; + tryNewSearch = false; } if (tryNewSearch) { // back to solver without cuts? @@ -1372,22 +1416,21 @@ void CbcModel::saveModel(OsiSolverInterface *saveSolver, double *checkCutoffForR double *newSolution = new double[numberColumns]; double objectiveValue = *checkCutoffForRestart; CbcSerendipity heuristic(*this); - if (bestSolution_) + if (bestSolution_) heuristic.setInputSolution(bestSolution_, bestObjective_); - if ((specialOptions_&512) != 0) - heuristic.setFractionSmall(100.0); + if ((specialOptions_ & 512) != 0) + heuristic.setFractionSmall(100.0); heuristic.setFeasibilityPumpOptions(1008013); // Use numberNodes to say how many are original rows heuristic.setNumberNodes(continuousSolver_->getNumRows()); #ifdef COIN_DEVELOP if (continuousSolver_->getNumRows() < solver2->getNumRows()) printf("%d rows added ZZZZZ\n", - solver_->getNumRows() - continuousSolver_->getNumRows()); + solver_->getNumRows() - continuousSolver_->getNumRows()); #endif - int returnCode = heuristic.smallBranchAndBound(solver2, - -1, newSolution, - objectiveValue, - *checkCutoffForRestart, "Reduce"); + int returnCode = heuristic.smallBranchAndBound( + solver2, -1, newSolution, objectiveValue, *checkCutoffForRestart, + "Reduce"); delete solver2; if (returnCode < 0) { #ifdef COIN_DEVELOP @@ -1428,8 +1471,7 @@ void CbcModel::saveModel(OsiSolverInterface *saveSolver, double *checkCutoffForR /* Adds integers, called from BranchandBound() */ -void CbcModel::AddIntegers() -{ +void CbcModel::AddIntegers() { int numberColumns = continuousSolver_->getNumCols(); int numberRows = continuousSolver_->getNumRows(); int numberOriginalIntegers = numberIntegers_; @@ -1457,12 +1499,12 @@ void CbcModel::AddIntegers() possible = true; } else { double value = rowUpper[i]; - if (rowLower[i] == rowUpper[i] && fabs(value - floor(value + 0.5)) < 1.0e-8) + if (rowLower[i] == rowUpper[i] && + fabs(value - floor(value + 0.5)) < 1.0e-8) possible = true; } double allSame = (possible) ? 0.0 : -1.0; - for (CoinBigIndex j = rowStart[i]; - j < rowStart[i] + rowLength[i]; j++) { + for (CoinBigIndex j = rowStart[i]; j < rowStart[i] + rowLength[i]; j++) { int iColumn = column[j]; if (continuousSolver_->isInteger(iColumn)) { if (fabs(element[j]) != 1.0) @@ -1495,8 +1537,10 @@ void CbcModel::AddIntegers() // we must not exclude current best solution (rounding errors) // also not if large values const int *row = continuousSolver_->getMatrixByCol()->getIndices(); - const CoinBigIndex *columnStart = continuousSolver_->getMatrixByCol()->getVectorStarts(); - const int *columnLength = continuousSolver_->getMatrixByCol()->getVectorLengths(); + const CoinBigIndex *columnStart = + continuousSolver_->getMatrixByCol()->getVectorStarts(); + const int *columnLength = + continuousSolver_->getMatrixByCol()->getVectorLengths(); const double *solution = continuousSolver_->getColSolution(); for (int iColumn = 0; iColumn < numberColumns; iColumn++) { if (!continuousSolver_->isInteger(iColumn)) { @@ -1576,7 +1620,8 @@ void CbcModel::AddIntegers() } else { // treat rhs as multiple of 1 unless elements all same double value = ((possibleRow[i] == 2) ? rowUpper[i] : 1.0) * mult; - if (rowLower[i] == rowUpper[i] && fabs(value - floor(value + 0.5)) < 1.0e-8) { + if (rowLower[i] == rowUpper[i] && + fabs(value - floor(value + 0.5)) < 1.0e-8) { del[nDel++] = i; copy2->setInteger(iColumn); int kOrig = original[iColumn]; @@ -1597,12 +1642,13 @@ void CbcModel::AddIntegers() possible = true; } else { double value = rowUpper[i]; - if (rowLower[i] == rowUpper[i] && fabs(value - floor(value + 0.5)) < 1.0e-8) + if (rowLower[i] == rowUpper[i] && + fabs(value - floor(value + 0.5)) < 1.0e-8) possible = true; } if (possible) { - for (CoinBigIndex j = rowStart[i]; - j < rowStart[i] + rowLength[i]; j++) { + for (CoinBigIndex j = rowStart[i]; j < rowStart[i] + rowLength[i]; + j++) { int iColumn = column[j]; if (columnLength[iColumn] != 1 || fabs(element[j]) != 1.0) { possible = false; @@ -1610,8 +1656,8 @@ void CbcModel::AddIntegers() } } if (possible) { - for (CoinBigIndex j = rowStart[i]; - j < rowStart[i] + rowLength[i]; j++) { + for (CoinBigIndex j = rowStart[i]; j < rowStart[i] + rowLength[i]; + j++) { int iColumn = column[j]; if (!copy2->isInteger(iColumn)) { copy2->setInteger(iColumn); @@ -1655,8 +1701,8 @@ void CbcModel::AddIntegers() bool couldBeNetwork = false; if (copy1->getNumRows() && copy1->getNumCols()) { #ifdef CBC_HAS_CLP - OsiClpSolverInterface *clpSolver - = dynamic_cast< OsiClpSolverInterface * >(copy1); + OsiClpSolverInterface *clpSolver = + dynamic_cast(copy1); if (false && clpSolver) { numberRows = clpSolver->getNumRows(); char *rotate = new char[numberRows]; @@ -1686,11 +1732,13 @@ void CbcModel::AddIntegers() const double *rowUpper = copy1->getRowUpper(); couldBeNetwork = true; for (int i = 0; i < numberRows; i++) { - if (rowLower[i] > -1.0e20 && fabs(rowLower[i] - floor(rowLower[i] + 0.5)) > 1.0e-12) { + if (rowLower[i] > -1.0e20 && + fabs(rowLower[i] - floor(rowLower[i] + 0.5)) > 1.0e-12) { couldBeNetwork = false; break; } - if (rowUpper[i] < 1.0e20 && fabs(rowUpper[i] - floor(rowUpper[i] + 0.5)) > 1.0e-12) { + if (rowUpper[i] < 1.0e20 && + fabs(rowUpper[i] - floor(rowUpper[i] + 0.5)) > 1.0e-12) { couldBeNetwork = false; break; } @@ -1702,7 +1750,7 @@ void CbcModel::AddIntegers() if (couldBeNetwork) { const CoinPackedMatrix *matrixByCol = copy1->getMatrixByCol(); const double *element = matrixByCol->getElements(); - //const int * row = matrixByCol->getIndices(); + // const int * row = matrixByCol->getIndices(); const CoinBigIndex *columnStart = matrixByCol->getVectorStarts(); const int *columnLength = matrixByCol->getVectorLengths(); for (int iColumn = 0; iColumn < numberColumns; iColumn++) { @@ -1752,21 +1800,20 @@ void CbcModel::AddIntegers() } #if CBC_USEFUL_PRINTING > 1 if (couldBeNetwork || nExtra) - printf("INTA %d extra integers, %d left%s\n", nExtra, - numberColumns, - couldBeNetwork ? ", all network" : ""); + printf("INTA %d extra integers, %d left%s\n", nExtra, numberColumns, + couldBeNetwork ? ", all network" : ""); #endif findIntegers(true, 2); convertToDynamic(); } #if CBC_USEFUL_PRINTING > 1 if (!couldBeNetwork && copy1->getNumCols() && copy1->getNumRows()) { - printf("INTA %d rows and %d columns remain\n", - copy1->getNumRows(), copy1->getNumCols()); + printf("INTA %d rows and %d columns remain\n", copy1->getNumRows(), + copy1->getNumCols()); if (copy1->getNumCols() < 200) { copy1->writeMps("moreint"); printf("INTA Written remainder to moreint.mps.gz %d rows %d cols\n", - copy1->getNumRows(), copy1->getNumCols()); + copy1->getNumRows(), copy1->getNumCols()); } } #endif @@ -1819,10 +1866,10 @@ static double lengthConflictCuts = 0.0; void CbcModel::branchAndBound(int doStatistics) { - //randomNumberGenerator_.setSeed(987654321); + // randomNumberGenerator_.setSeed(987654321); if (!parentModel_) { - /* - Capture a time stamp before we start (unless set). + /* + Capture a time stamp before we start (unless set). */ if (!dblParam_[CbcStartSeconds]) { if (!useElapsedTime()) @@ -1843,8 +1890,16 @@ void CbcModel::branchAndBound(int doStatistics) int nextCheckRestart = 50; // Force minimization !!!! bool flipObjective = (solver_->getObjSense() < 0.0); - if (flipObjective) + if (flipObjective) { + // In solver_ cutoff is correct with sign reversed + double cutoff; + solver_->getDblParam(OsiDblParam::OsiDualObjectiveLimit,cutoff); + // treat as if minimize + assert(fabs(dblParam_[CbcCurrentCutoff]) == fabs(cutoff) || + fabs(cutoff)>1.0e40); + dblParam_[CbcCurrentCutoff] = -cutoff; flipModel(); + } dblParam_[CbcOptimizationDirection] = 1.0; // was solver_->getObjSense(); strongInfo_[0] = 0; strongInfo_[1] = 0; @@ -1862,12 +1917,12 @@ void CbcModel::branchAndBound(int doStatistics) specialOptions_ |= 4096; } int saveMoreSpecialOptions = moreSpecialOptions_; - if (dynamic_cast< CbcTreeLocal * >(tree_)) + if (dynamic_cast(tree_)) specialOptions_ |= 4096 + 8192; #ifdef CBC_HAS_CLP { - OsiClpSolverInterface *clpSolver - = dynamic_cast< OsiClpSolverInterface * >(solver_); + OsiClpSolverInterface *clpSolver = + dynamic_cast(solver_); if (clpSolver) { // pass in disaster handler CbcDisasterHandler handler(this); @@ -1883,7 +1938,8 @@ void CbcModel::branchAndBound(int doStatistics) #ifdef JJF_ZERO // reduce factorization frequency int frequency = clpSolver->getModelPtr()->factorizationFrequency(); - clpSolver->getModelPtr()->setFactorizationFrequency(CoinMin(frequency, 120)); + clpSolver->getModelPtr()->setFactorizationFrequency( + CoinMin(frequency, 120)); #endif } } @@ -1896,13 +1952,13 @@ void CbcModel::branchAndBound(int doStatistics) bool noObjects = (numberObjects_ == 0); // Set up strategies /* - See if the user has supplied a strategy object and deal with it if present. - The call to setupOther will set numberStrong_ and numberBeforeTrust_, and - perform integer preprocessing, if requested. + See if the user has supplied a strategy object and deal with it if + present. The call to setupOther will set numberStrong_ and + numberBeforeTrust_, and perform integer preprocessing, if requested. We need to hang on to a pointer to solver_. setupOther will assign a - preprocessed solver to model, but will instruct assignSolver not to trash the - existing one. + preprocessed solver to model, but will instruct assignSolver not to trash + the existing one. */ if (strategy_) { // May do preprocessing @@ -1917,9 +1973,7 @@ void CbcModel::branchAndBound(int doStatistics) handler_->message(CBC_INFEAS, messages_) << CoinMessageEol; secondaryStatus_ = 1; } else { - handler_->message(CBC_UNBOUNDED, - messages_) - << CoinMessageEol; + handler_->message(CBC_UNBOUNDED, messages_) << CoinMessageEol; secondaryStatus_ = 7; } originalContinuousObjective_ = COIN_DBL_MAX; @@ -1938,7 +1992,8 @@ void CbcModel::branchAndBound(int doStatistics) // allow for cliques etc nOrig = CoinMax(nOrig, originalColumns[numberColumns - 1] + 1); // try and redo debugger - OsiRowCutDebugger *debugger = const_cast< OsiRowCutDebugger * >(solver_->getRowCutDebuggerAlways()); + OsiRowCutDebugger *debugger = + const_cast(solver_->getRowCutDebuggerAlways()); if (debugger) { if (numberColumns <= debugger->numberColumns()) debugger->redoSolution(numberColumns, originalColumns); @@ -1977,7 +2032,8 @@ void CbcModel::branchAndBound(int doStatistics) int jColumn = originalColumns[iColumn]; if (temp[jColumn] >= 0) { int iObject = temp[jColumn]; - CbcSimpleInteger *obj = dynamic_cast< CbcSimpleInteger * >(originalObject[iObject]); + CbcSimpleInteger *obj = + dynamic_cast(originalObject[iObject]); if (obj) numberOldIntegers++; else @@ -1987,17 +2043,18 @@ void CbcModel::branchAndBound(int doStatistics) } } /* - Allocate an array to hold the indices of the integer variables. - Make a large enough array for all objects + Allocate an array to hold the indices of the integer + variables. Make a large enough array for all objects */ - numberObjects_ = numberNewIntegers + numberOldIntegers + numberOldOther + nNonInt; + numberObjects_ = + numberNewIntegers + numberOldIntegers + numberOldOther + nNonInt; object_ = new OsiObject *[numberObjects_]; delete[] integerVariable_; integerVariable_ = new int[numberNewIntegers + numberOldIntegers]; /* - Walk the variables again, filling in the indices and creating objects for - the integer variables. Initially, the objects hold the index and upper & - lower bounds. + Walk the variables again, filling in the indices and creating + objects for the integer variables. Initially, the objects hold the + index and upper & lower bounds. */ numberIntegers_ = 0; int n = originalColumns[numberColumns - 1] + 1; @@ -2011,12 +2068,14 @@ void CbcModel::branchAndBound(int doStatistics) int jColumn = originalColumns[iColumn]; if (temp[jColumn] >= 0) { int iObject = temp[jColumn]; - CbcSimpleInteger *obj = dynamic_cast< CbcSimpleInteger * >(originalObject[iObject]); + CbcSimpleInteger *obj = + dynamic_cast(originalObject[iObject]); if (obj) { object_[numberIntegers_] = originalObject[iObject]->clone(); // redo ids etc - //object_[numberIntegers_]->resetSequenceEtc(numberColumns,originalColumns); - object_[numberIntegers_]->resetSequenceEtc(numberColumns, backward); + // object_[numberIntegers_]->resetSequenceEtc(numberColumns,originalColumns); + object_[numberIntegers_]->resetSequenceEtc(numberColumns, + backward); integerVariable_[numberIntegers_++] = iColumn; } } else if (isInteger(iColumn)) { @@ -2031,11 +2090,13 @@ void CbcModel::branchAndBound(int doStatistics) int jColumn = originalColumns[iColumn]; if (temp[jColumn] >= 0) { int iObject = temp[jColumn]; - CbcSimpleInteger *obj = dynamic_cast< CbcSimpleInteger * >(originalObject[iObject]); + CbcSimpleInteger *obj = + dynamic_cast(originalObject[iObject]); if (!obj) { object_[numberObjects_] = originalObject[iObject]->clone(); // redo ids etc - CbcObject *obj = dynamic_cast< CbcObject * >(object_[numberObjects_]); + CbcObject *obj = + dynamic_cast(object_[numberObjects_]); assert(obj); obj->redoSequenceEtc(this, numberColumns, originalColumns); numberObjects_++; @@ -2050,7 +2111,7 @@ void CbcModel::branchAndBound(int doStatistics) object_[numberObjects_] = originalObject[iObject]->clone(); #ifdef JJF_ZERO // redo ids etc - CbcObject *obj = dynamic_cast< CbcObject * >(object_[numberObjects_]); + CbcObject *obj = dynamic_cast(object_[numberObjects_]); assert(obj); obj->redoSequenceEtc(this, numberColumns, originalColumns); #endif @@ -2066,12 +2127,13 @@ void CbcModel::branchAndBound(int doStatistics) assert(process); const int *originalColumns = process->originalColumns(); // try and redo debugger - OsiRowCutDebugger *debugger = const_cast< OsiRowCutDebugger * >(solver_->getRowCutDebuggerAlways()); + OsiRowCutDebugger *debugger = + const_cast(solver_->getRowCutDebuggerAlways()); if (debugger) debugger->redoSolution(numberColumns, originalColumns); } } else { - //no preprocessing + // no preprocessing originalSolver = NULL; } strategy_->setupCutGenerators(*this); @@ -2102,8 +2164,8 @@ void CbcModel::branchAndBound(int doStatistics) CglStored *storedCuts = dupcuts.outDuplicates(solver_); if (storedCuts) { COIN_DETAIL_PRINT(printf("adding dup cuts\n")); - addCutGenerator(storedCuts, 1, "StoredCuts from dominated", - true, false, false, -200); + addCutGenerator(storedCuts, 1, "StoredCuts from dominated", true, false, + false, -200); } } if (!nodeCompare_) @@ -2181,7 +2243,7 @@ void CbcModel::branchAndBound(int doStatistics) if (preferredWay_) { // set all unset ones for (int iObject = 0; iObject < numberObjects_; iObject++) { - CbcObject *obj = dynamic_cast< CbcObject * >(object_[iObject]); + CbcObject *obj = dynamic_cast(object_[iObject]); if (obj && !obj->preferredWay()) obj->setPreferredWay(preferredWay_); } @@ -2192,14 +2254,16 @@ void CbcModel::branchAndBound(int doStatistics) */ synchronizeModel(); if (!solverCharacteristics_) { - OsiBabSolver *solverCharacteristics = dynamic_cast< OsiBabSolver * >(solver_->getAuxiliaryInfo()); + OsiBabSolver *solverCharacteristics = + dynamic_cast(solver_->getAuxiliaryInfo()); if (solverCharacteristics) { solverCharacteristics_ = solverCharacteristics; } else { // replace in solver OsiBabSolver defaultC; solver_->setAuxiliaryInfo(&defaultC); - solverCharacteristics_ = dynamic_cast< OsiBabSolver * >(solver_->getAuxiliaryInfo()); + solverCharacteristics_ = + dynamic_cast(solver_->getAuxiliaryInfo()); } } @@ -2209,20 +2273,20 @@ void CbcModel::branchAndBound(int doStatistics) /* Solve the relaxation. - Apparently there are circumstances where this will be non-trivial --- i.e., - we've done something since initialSolve that's trashed the solution to the - continuous relaxation. + Apparently there are circumstances where this will be non-trivial --- + i.e., we've done something since initialSolve that's trashed the solution + to the continuous relaxation. */ /* Tell solver we are in Branch and Cut Could use last parameter for subtle differences */ solver_->setHintParam(OsiDoInBranchAndCut, true, OsiHintDo, NULL); #ifdef CBC_HAS_CLP { - OsiClpSolverInterface *clpSolver - = dynamic_cast< OsiClpSolverInterface * >(solver_); + OsiClpSolverInterface *clpSolver = + dynamic_cast(solver_); if (clpSolver) { - if ( this->keepNamesPreproc == false ) - solver_->setIntParam( OsiNameDiscipline, 0 ); + if (this->keepNamesPreproc == false) + solver_->setIntParam(OsiNameDiscipline, 0); ClpSimplex *clpSimplex = clpSolver->getModelPtr(); if ((specialOptions_ & 32) == 0) { // take off names (unless going to be saving) @@ -2257,41 +2321,43 @@ void CbcModel::branchAndBound(int doStatistics) int numberOdd = 0; int numberSOS = 0; for (int i = 0; i < numberObjects_; i++) { - CbcSimpleInteger *obj = dynamic_cast< CbcSimpleInteger * >(object_[i]); + CbcSimpleInteger *obj = dynamic_cast(object_[i]); if (!obj) { numberOdd++; - if (dynamic_cast< CbcSOS * >(object_[i])) - numberSOS++; + if (dynamic_cast(object_[i])) + numberSOS++; } } if (numberOdd) { moreSpecialOptions_ |= 1073741824; // also switch off checking for restart (as preprocessing may be odd) -#ifdef CBC_EXPERIMENT7 +#ifdef CBC_EXPERIMENT_JJF if (numberOdd > numberSOS) #endif - specialOptions_ &= ~(512|32768); + specialOptions_ &= ~(512 | 32768); } moreSpecialOptions2_ &= ~65536; // say no lazy constraints if (!numberOdd && !parentModel_) { // see if lazy constraints bool needCuts = false; for (int i = 0; i < numberCutGenerators_; i++) { - bool generate = generator_[i]->atSolution(); - if (generate) { - needCuts = true; - } + bool generate = generator_[i]->atSolution(); + if (generate) { + needCuts = true; + } } if (needCuts) - moreSpecialOptions2_ |= 65536; // lazy constraints + moreSpecialOptions2_ |= 65536; // lazy constraints } } // If NLP then we assume already solved outside branchAndbound - if (!solverCharacteristics_->solverType() || solverCharacteristics_->solverType() == 4) { + if (!solverCharacteristics_->solverType() || + solverCharacteristics_->solverType() == 4) { feasible = resolve(NULL, 0) != 0; } else { // pick up given status - feasible = (solver_->isProvenOptimal() && !solver_->isDualObjectiveLimitReached()); + feasible = + (solver_->isProvenOptimal() && !solver_->isDualObjectiveLimitReached()); } if (problemFeasibility_->feasible(this, 0) < 0) { feasible = false; // pretend infeasible @@ -2300,8 +2366,8 @@ void CbcModel::branchAndBound(int doStatistics) int saveNumberStrong = numberStrong_; int saveNumberBeforeTrust = numberBeforeTrust_; /* - If the linear relaxation of the root is infeasible, bail out now. Otherwise, - continue with processing the root node. + If the linear relaxation of the root is infeasible, bail out now. + Otherwise, continue with processing the root node. */ if (!feasible) { status_ = 0; @@ -2313,14 +2379,14 @@ void CbcModel::branchAndBound(int doStatistics) secondaryStatus_ = 7; } originalContinuousObjective_ = COIN_DBL_MAX; - if (bestSolution_ && ((specialOptions_ & 8388608) == 0 || (specialOptions_ & 2048) != 0)) { + if (bestSolution_ && + ((specialOptions_ & 8388608) == 0 || (specialOptions_ & 2048) != 0)) { // best solution found by various heuristics - set solution char general[200]; sprintf(general, "Solution of %g already found by heuristic", - bestObjective_); - messageHandler()->message(CBC_GENERAL, - messages()) - << general << CoinMessageEol; + bestObjective_); + messageHandler()->message(CBC_GENERAL, messages()) + << general << CoinMessageEol; setCutoff(1.0e50); // As best solution should be worse than cutoff // change cutoff as constraint if wanted if (cutoffRowNumber_ >= 0) { @@ -2331,14 +2397,16 @@ void CbcModel::branchAndBound(int doStatistics) if (continuousSolver_) { // Solvers know about direction double direction = solver_->getObjSense(); - continuousSolver_->setDblParam(OsiDualObjectiveLimit, 1.0e50 * direction); + continuousSolver_->setDblParam(OsiDualObjectiveLimit, + 1.0e50 * direction); } else { continuousSolver_ = solver_->clone(); } phase_ = 5; double increment = getDblParam(CbcModel::CbcCutoffIncrement); if ((specialOptions_ & 4) == 0) - bestObjective_ += 100.0 * increment + 1.0e-3; // only set if we are going to solve + bestObjective_ += + 100.0 * increment + 1.0e-3; // only set if we are going to solve setBestSolution(CBC_END_SOLUTION, bestObjective_, bestSolution_, 1); continuousSolver_->resolve(); if (!continuousSolver_->isProvenOptimal()) { @@ -2417,31 +2485,32 @@ void CbcModel::branchAndBound(int doStatistics) solver's list. 080417 The conversion code here (the block protected by `if (obj)') cannot - possibly be correct. On the Osi side, descent is OsiObject -> OsiObject2 -> - all other Osi object classes. On the Cbc side, it's OsiObject -> CbcObject + possibly be correct. On the Osi side, descent is OsiObject -> OsiObject2 + -> all other Osi object classes. On the Cbc side, it's OsiObject -> + CbcObject -> all other Cbc object classes. It's structurally impossible for any Osi object to descend from CbcObject. The only thing I can see is that this is really dead code, and object detection is now handled from the Osi side. */ // Convert to Osi if wanted - //OsiBranchingInformation * persistentInfo = NULL; + // OsiBranchingInformation * persistentInfo = NULL; if (branchingMethod_ && branchingMethod_->chooseMethod()) { - //persistentInfo = new OsiBranchingInformation(solver_); + // persistentInfo = new OsiBranchingInformation(solver_); if (numberOriginalObjects) { for (int iObject = 0; iObject < numberObjects_; iObject++) { - CbcObject *obj = dynamic_cast< CbcObject * >(object_[iObject]); + CbcObject *obj = dynamic_cast(object_[iObject]); if (obj) { - CbcSimpleInteger *obj2 = dynamic_cast< CbcSimpleInteger * >(obj); + CbcSimpleInteger *obj2 = dynamic_cast(obj); if (obj2) { // back to Osi land object_[iObject] = obj2->osiObject(); delete obj; } else { - OsiSimpleInteger *obj3 = dynamic_cast< OsiSimpleInteger * >(obj); + OsiSimpleInteger *obj3 = dynamic_cast(obj); if (!obj3) { - OsiSOS *obj4 = dynamic_cast< OsiSOS * >(obj); + OsiSOS *obj4 = dynamic_cast(obj); if (!obj4) { - CbcSOS *obj5 = dynamic_cast< CbcSOS * >(obj); + CbcSOS *obj5 = dynamic_cast(obj); if (obj5) { // back to Osi land object_[iObject] = obj5->osiObject(solver_); @@ -2455,12 +2524,12 @@ void CbcModel::branchAndBound(int doStatistics) } } // and add to solver - //if (!solver_->numberObjects()) { + // if (!solver_->numberObjects()) { solver_->addObjects(numberObjects_, object_); //} else { - //if (solver_->numberObjects()!=numberOriginalObjects) { - //printf("should have trapped that solver has objects before\n"); - //abort(); + // if (solver_->numberObjects()!=numberOriginalObjects) { + // printf("should have trapped that solver has objects before\n"); + // abort(); //} //} } else { @@ -2485,7 +2554,7 @@ void CbcModel::branchAndBound(int doStatistics) for (int i = 0; i < numberObjects_; i++) { if (!object_[i]->canDoHeuristics()) numberOdd++; - CbcSOS *obj = dynamic_cast< CbcSOS * >(object_[i]); + CbcSOS *obj = dynamic_cast(object_[i]); if (obj) numberSOS++; } @@ -2503,7 +2572,8 @@ void CbcModel::branchAndBound(int doStatistics) heuristic_ = NULL; } numberHeuristics_ = k; - handler_->message(CBC_HEURISTICS_OFF, messages_) << numberOdd << CoinMessageEol; + handler_->message(CBC_HEURISTICS_OFF, messages_) + << numberOdd << CoinMessageEol; } // If odd switch off AddIntegers specialOptions_ &= ~65536; @@ -2517,22 +2587,34 @@ void CbcModel::branchAndBound(int doStatistics) moreSpecialOptions_ &= ~33554432; // no diving } if (numberThreads_ > 0) { - /* switch off fast nodes for now - Trouble is that by time mini bab finishes code is - looking at a different node - */ - fastNodeDepth_ = -1; + /* switch off fast nodes for now (unless user really wants) + Trouble is that by time mini bab finishes code is + looking at a different node + */ + bool switchOff = true; +#ifdef CBC_HAS_CLP + OsiClpSolverInterface *clpSolver + = dynamic_cast< OsiClpSolverInterface * >(solver_); + if (clpSolver) { + ClpSimplex *clpSimplex = clpSolver->getModelPtr(); + if ((clpSimplex->moreSpecialOptions()&2048) != 0) + switchOff = false; + } +#endif + if (switchOff) + fastNodeDepth_ = -1; } } // Save objective (just so user can access it) - originalContinuousObjective_ = solver_->getObjValue() * solver_->getObjSense(); + originalContinuousObjective_ = + solver_->getObjValue() * solver_->getObjSense(); bestPossibleObjective_ = originalContinuousObjective_; sumChangeObjective1_ = 0.0; sumChangeObjective2_ = 0.0; /* OsiRowCutDebugger knows an optimal answer for a subset of MIP problems. - Assuming it recognises the problem, when called upon it will check a cut to - see if it cuts off the optimal answer. + Assuming it recognises the problem, when called upon it will check a cut + to see if it cuts off the optimal answer. */ // If debugger exists set specialOptions_ bit if (solver_->getRowCutDebuggerAlways()) { @@ -2566,9 +2648,8 @@ void CbcModel::branchAndBound(int doStatistics) double direction = solver_->getObjSense(); dblParam_[CbcOptimizationDirection] = direction; if (cutoff < 1.0e20 && direction < 0.0) - messageHandler()->message(CBC_CUTOFF_WARNING1, - messages()) - << cutoff << -cutoff << CoinMessageEol; + messageHandler()->message(CBC_CUTOFF_WARNING1, messages()) + << cutoff << -cutoff << CoinMessageEol; if (cutoff > bestObjective_) cutoff = bestObjective_; setCutoff(cutoff); @@ -2588,15 +2669,17 @@ void CbcModel::branchAndBound(int doStatistics) #ifdef CONFLICT_CUTS if ((moreSpecialOptions_ & 4194304) != 0) { #ifdef CBC_HAS_CLP - OsiClpSolverInterface *clpSolver - = dynamic_cast< OsiClpSolverInterface * >(solver_); + OsiClpSolverInterface *clpSolver = + dynamic_cast(solver_); if (clpSolver) { int specialOptions = clpSolver->getModelPtr()->specialOptions(); // 2097152 switches on rays in crunch if (!parentModel_) - clpSolver->getModelPtr()->setSpecialOptions(specialOptions | 32 | 2097152); + clpSolver->getModelPtr()->setSpecialOptions(specialOptions | 32 | + 2097152); else - clpSolver->getModelPtr()->setSpecialOptions(specialOptions & ~(32 | 2097152)); + clpSolver->getModelPtr()->setSpecialOptions(specialOptions & + ~(32 | 2097152)); } } #endif @@ -2604,22 +2687,23 @@ void CbcModel::branchAndBound(int doStatistics) #ifdef CBC_HAS_NAUTY // maybe allow on fix and restart later if ((moreSpecialOptions2_ & (128 | 256)) != 0) { - if ((specialOptions_&2048)==0) { + if ((specialOptions_ & 2048) == 0) { symmetryInfo_ = new CbcSymmetry(); symmetryInfo_->setupSymmetry(this); int numberGenerators = symmetryInfo_->statsOrbits(this, 0); - if (!symmetryInfo_->numberUsefulOrbits() && (moreSpecialOptions2_ & (128 | 256)) != (128 | 256)) { - delete symmetryInfo_; - symmetryInfo_ = NULL; - moreSpecialOptions2_ &= ~(128 | 256 | 131072); + if (!symmetryInfo_->numberUsefulOrbits() && + (moreSpecialOptions2_ & (128 | 256)) != (128 | 256)) { + delete symmetryInfo_; + symmetryInfo_ = NULL; + moreSpecialOptions2_ &= ~(128 | 256 | 131072); } if ((moreSpecialOptions2_ & (128 | 256)) == (128 | 256)) { - if ((moreSpecialOptions2_&131072) != 0) { - // keep it simple - moreSpecialOptions2_ &= ~(128 | 256); - rootSymmetryInfo_ = symmetryInfo_; - symmetryInfo_ = NULL; - } + if ((moreSpecialOptions2_ & 131072) != 0) { + // keep it simple + moreSpecialOptions2_ &= ~(128 | 256); + rootSymmetryInfo_ = symmetryInfo_; + symmetryInfo_ = NULL; + } } } else { // small B&B @@ -2632,7 +2716,8 @@ void CbcModel::branchAndBound(int doStatistics) if (cutoffRowNumber_ == -2) { if (!parentModel_) { int numberColumns = solver_->getNumCols(); - double *obj = CoinCopyOfArray(solver_->getObjCoefficients(), numberColumns); + double *obj = + CoinCopyOfArray(solver_->getObjCoefficients(), numberColumns); int *indices = new int[numberColumns]; int n = 0; for (int i = 0; i < numberColumns; i++) { @@ -2648,7 +2733,8 @@ void CbcModel::branchAndBound(int doStatistics) double offset; solver_->getDblParam(OsiObjOffset, offset); cutoffRowNumber_ = solver_->getNumRows(); - solver_->addRow(n, indices, obj, -COIN_DBL_MAX, CoinMin(cutoff, 1.0e25) + offset); + solver_->addRow(n, indices, obj, -COIN_DBL_MAX, + CoinMin(cutoff, 1.0e25) + offset); } else { // no objective! cutoffRowNumber_ = -1; @@ -2683,8 +2769,8 @@ void CbcModel::branchAndBound(int doStatistics) ClpDualRowPivot *savePivotMethod = NULL; { // pass tolerance and increment to solver - OsiClpSolverInterface *clpSolver - = dynamic_cast< OsiClpSolverInterface * >(solver_); + OsiClpSolverInterface *clpSolver = + dynamic_cast(solver_); if (clpSolver) clpSolver->setStuff(getIntegerTolerance(), getCutoffIncrement()); #ifdef CLP_RESOLVE @@ -2695,9 +2781,9 @@ void CbcModel::branchAndBound(int doStatistics) } #endif /* - Set up for cut generation. addedCuts_ holds the cuts which are relevant for - the active subproblem. whichGenerator will be used to record the generator - that produced a given cut. + Set up for cut generation. addedCuts_ holds the cuts which are relevant + for the active subproblem. whichGenerator will be used to record the + generator that produced a given cut. */ #define INITIAL_MAXIMUM_WHICH 1000 maximumWhich_ = INITIAL_MAXIMUM_WHICH; @@ -2716,8 +2802,8 @@ void CbcModel::branchAndBound(int doStatistics) Set up an empty heap and associated data structures to hold the live set (problems which require further exploration). */ - CbcCompareDefault *compareActual - = dynamic_cast< CbcCompareDefault * >(nodeCompare_); + CbcCompareDefault *compareActual = + dynamic_cast(nodeCompare_); if (compareActual) { compareActual->setBestPossible(direction * solver_->getObjValue()); compareActual->setCutoff(getCutoff()); @@ -2732,8 +2818,9 @@ void CbcModel::branchAndBound(int doStatistics) } tree_->setComparison(*nodeCompare_); /* - Used to record the path from a node to the root of the search tree, so that - we can then traverse from the root to the node when restoring a subproblem. + Used to record the path from a node to the root of the search tree, so + that we can then traverse from the root to the node when restoring a + subproblem. */ maximumDepth_ = 10; delete[] walkback_; @@ -2741,10 +2828,10 @@ void CbcModel::branchAndBound(int doStatistics) lastDepth_ = 0; delete[] lastNodeInfo_; lastNodeInfo_ = new CbcNodeInfo *[maximumDepth_]; - memset(lastNodeInfo_,0,maximumDepth_*sizeof(CbcNodeInfo*)); + memset(lastNodeInfo_, 0, maximumDepth_ * sizeof(CbcNodeInfo *)); delete[] lastNumberCuts_; lastNumberCuts_ = new int[maximumDepth_]; - memset(lastNumberCuts_,0,maximumDepth_*sizeof(int)); + memset(lastNumberCuts_, 0, maximumDepth_ * sizeof(int)); maximumCuts_ = 100; lastNumberCuts2_ = 0; delete[] lastCut_; @@ -2766,10 +2853,10 @@ void CbcModel::branchAndBound(int doStatistics) doHeurisiticsAtRoot is called to run heuristics outside of the main cut / heurisitc / reoptimise loop in solveWithCuts? - Generate cuts at the root node and reoptimise. solveWithCuts does the heavy - lifting. It will iterate a generate/reoptimise loop (including reduced cost - fixing) until no cuts are generated, the change in objective falls off, or - the limit on the number of rounds of cut generation is exceeded. + Generate cuts at the root node and reoptimise. solveWithCuts does the + heavy lifting. It will iterate a generate/reoptimise loop (including reduced + cost fixing) until no cuts are generated, the change in objective falls off, + or the limit on the number of rounds of cut generation is exceeded. At the end of all this, any cuts will be recorded in cuts and also installed in the solver's constraint system. We'll have reoptimised, and @@ -2783,7 +2870,8 @@ void CbcModel::branchAndBound(int doStatistics) */ phase_ = 1; int iCutGenerator; - for (iCutGenerator = 0; iCutGenerator < numberCutGenerators_; iCutGenerator++) { + for (iCutGenerator = 0; iCutGenerator < numberCutGenerators_; + iCutGenerator++) { // If parallel switch off global cuts if (numberThreads_) { generator_[iCutGenerator]->setGlobalCuts(false); @@ -2814,13 +2902,13 @@ void CbcModel::branchAndBound(int doStatistics) if (!parentModel_) { if ((specialOptions_ & 262144) != 0) { // create empty stored cuts - //storedRowCuts_ = new CglStored(solver_->getNumCols()); + // storedRowCuts_ = new CglStored(solver_->getNumCols()); } else if ((specialOptions_ & 524288) != 0 && storedRowCuts_) { // tighten and set best solution // A) tight bounds on integer variables /* - storedRowCuts_ are coming in from outside, probably for nonlinear. - John was unsure about origin. + storedRowCuts_ are coming in from outside, probably for + nonlinear. John was unsure about origin. */ const double *lower = solver_->getColLower(); const double *upper = solver_->getColUpper(); @@ -2839,17 +2927,17 @@ void CbcModel::branchAndBound(int doStatistics) } } if (nTightened) - COIN_DETAIL_PRINT(printf("%d tightened by alternate cuts\n", nTightened)); + COIN_DETAIL_PRINT( + printf("%d tightened by alternate cuts\n", nTightened)); if (storedRowCuts_->bestObjective() < bestObjective_) { // B) best solution double objValue = storedRowCuts_->bestObjective(); - setBestSolution(CBC_SOLUTION, objValue, - storedRowCuts_->bestSolution()); + setBestSolution(CBC_SOLUTION, objValue, storedRowCuts_->bestSolution()); // Do heuristics // Allow RINS for (int i = 0; i < numberHeuristics_; i++) { - CbcHeuristicRINS *rins - = dynamic_cast< CbcHeuristicRINS * >(heuristic_[i]); + CbcHeuristicRINS *rins = + dynamic_cast(heuristic_[i]); if (rins) { rins->setLastNode(-100); } @@ -2874,9 +2962,9 @@ void CbcModel::branchAndBound(int doStatistics) double startTimeRoot = CoinGetTimeOfDay(); int numberRootThreads = 1; /* undocumented fine tuning - aabbcc where cc is number of tries - bb if nonzero is number of threads - aa if nonzero just do heuristics + aabbcc where cc is number of tries + bb if nonzero is number of threads + aa if nonzero just do heuristics */ int numberModels = multipleRootTries_ % 100; #ifdef CBC_THREAD @@ -2896,18 +2984,19 @@ void CbcModel::branchAndBound(int doStatistics) double time = fabs(CoinGetTimeOfDay()); while (time >= COIN_INT_MAX) time *= 0.5; - newSeed = static_cast< unsigned int >(time); + newSeed = static_cast(time); } else if (newSeed < 0) { newSeed = 123456789; #ifdef CBC_HAS_CLP - OsiClpSolverInterface *clpSolver - = dynamic_cast< OsiClpSolverInterface * >(solver_); + OsiClpSolverInterface *clpSolver = + dynamic_cast(solver_); if (clpSolver) { newSeed += clpSolver->getModelPtr()->randomNumberGenerator()->getSeed(); } #endif } - CoinWarmStartBasis *basis = dynamic_cast< CoinWarmStartBasis * >(solver_->getEmptyWarmStart()); + CoinWarmStartBasis *basis = + dynamic_cast(solver_->getEmptyWarmStart()); for (int i = 0; i < numberModels; i++) { rootModels[i] = new CbcModel(*this); if ((moreSpecialOptions2_&4194304) != 0) { @@ -2920,20 +3009,32 @@ void CbcModel::branchAndBound(int doStatistics) rootModels[i]->setRandomSeed(newSeed + 10000000 * i); rootModels[i]->randomNumberGenerator()->setSeed(newSeed + 50000000 * i); rootModels[i]->setMultipleRootTries(0); +#ifdef CBC_NAMES_FOR_COMPARE + OsiClpSolverInterface * solver = + dynamic_cast(rootModels[i]->solver()); + ClpSimplex * simplex = solver->getModelPtr(); + simplex->setStrParam(ClpStrParam::ClpProbName,""); +#endif #ifdef CBC_HAS_NAUTY rootModels[i]->zapSymmetry(); rootModels[i]->moreSpecialOptions2_ &= ~(128 | 256); // off nauty #endif // use seed - rootModels[i]->setSpecialOptions(specialOptions_ | (4194304 | 8388608)); - rootModels[i]->setMoreSpecialOptions(moreSpecialOptions_ & (~(134217728 | 4194304))); + rootModels[i]->setSpecialOptions((specialOptions_ | (4194304 | 8388608)) & + ~(512 | 32768)); + rootModels[i]->setMoreSpecialOptions(moreSpecialOptions_ & + (~(134217728 | 4194304))); // dual tightening may be bad because of degeneracy and random bases rootModels[i]->setMoreSpecialOptions(moreSpecialOptions_ | 1073741824); - rootModels[i]->setMoreSpecialOptions2(moreSpecialOptions2_ & (~(128 | 256))); + rootModels[i]->setMoreSpecialOptions2(moreSpecialOptions2_ & + (~(128 | 256))); + // also keep globalCuts_ + rootModels[i]->setMoreSpecialOptions2(moreSpecialOptions2_ | + 16777216); rootModels[i]->solver_->setWarmStart(basis); #ifdef CBC_HAS_CLP - OsiClpSolverInterface *clpSolver - = dynamic_cast< OsiClpSolverInterface * >(rootModels[i]->solver_); + OsiClpSolverInterface *clpSolver = + dynamic_cast(rootModels[i]->solver_); #define NEW_RANDOM_BASIS #ifdef NEW_RANDOM_BASIS if (i == 0) @@ -2951,10 +3052,10 @@ void CbcModel::branchAndBound(int doStatistics) if (i != 0) { #ifdef NEW_RANDOM_BASIS int numberRows = simplex->numberRows(); - int throwOut = 20; //2+numberRows/100; + int throwOut = 20; // 2+numberRows/100; for (int iThrow = 0; iThrow < throwOut; iThrow++) { double random = simplex->randomNumberGenerator()->randomDouble(); - int iStart = static_cast< int >(random * numberRows); + int iStart = static_cast(random * numberRows); for (int j = iStart; j < numberRows; j++) { if (simplex->getRowStatus(j) != ClpSimplex::basic) { simplex->setRowStatus(j, ClpSimplex::basic); @@ -2965,7 +3066,7 @@ void CbcModel::branchAndBound(int doStatistics) clpSolver->setWarmStart(NULL); #else double random = simplex->randomNumberGenerator()->randomDouble(); - int bias = static_cast< int >(random * (numberIterations / 4)); + int bias = static_cast(random * (numberIterations / 4)); simplex->setMaximumIterations(numberIterations / 2 + bias); simplex->primal(); simplex->setMaximumIterations(COIN_INT_MAX); @@ -2983,13 +3084,16 @@ void CbcModel::branchAndBound(int doStatistics) #endif } for (int j = 0; j < numberHeuristics_; j++) - rootModels[i]->heuristic_[j]->setSeed(rootModels[i]->heuristic_[j]->getSeed() + 100000000 * i); + rootModels[i]->heuristic_[j]->setSeed( + rootModels[i]->heuristic_[j]->getSeed() + 100000000 * i); for (int j = 0; j < numberCutGenerators_; j++) - rootModels[i]->generator_[j]->generator()->refreshSolver(rootModels[i]->solver_); + rootModels[i]->generator_[j]->generator()->refreshSolver( + rootModels[i]->solver_); } -#ifdef CBC_EXPERIMENT7 - if (numberModels>1 && numberHeuristics_) { - rootModels[0]->setMoreSpecialOptions(rootModels[0]->moreSpecialOptions()|512); +#ifdef CBC_EXPERIMENT_JJF + if (numberModels > 1 && numberHeuristics_) { + rootModels[0]->setMoreSpecialOptions(rootModels[0]->moreSpecialOptions() | + 512); } #endif delete basis; @@ -3027,7 +3131,9 @@ void CbcModel::branchAndBound(int doStatistics) bundle+iModel); } // wait - for (int iModel = kModel; iModel < CoinMin(numberModels, kModel + numberRootThreads); iModel++) { + for (int iModel = kModel; + iModel < CoinMin(numberModels, kModel + numberRootThreads); + iModel++) { pthread_join(threadId[iModel - kModel].thr, NULL); } // Find best objective @@ -3063,20 +3169,22 @@ void CbcModel::branchAndBound(int doStatistics) rootModels[iModel]->setCutoff(1.0e50); if (rootModels[iModel]->bestSolution()) { which[numberSolutions] = iModel; - value[numberSolutions++] = -rootModels[iModel]->getMinimizationObjValue(); + value[numberSolutions++] = + -rootModels[iModel]->getMinimizationObjValue(); } } char general[100]; rootTimeCpu = CoinCpuTime() - rootTimeCpu; if (numberRootThreads == 1) sprintf(general, "Multiple root solvers took a total of %.2f seconds\n", - rootTimeCpu); + rootTimeCpu); else - sprintf(general, "Multiple root solvers took a total of %.2f seconds (%.2f elapsed)\n", - rootTimeCpu, CoinGetTimeOfDay() - startTimeRoot); - messageHandler()->message(CBC_GENERAL, - messages()) - << general << CoinMessageEol; + sprintf( + general, + "Multiple root solvers took a total of %.2f seconds (%.2f elapsed)\n", + rootTimeCpu, CoinGetTimeOfDay() - startTimeRoot); + messageHandler()->message(CBC_GENERAL, messages()) + << general << CoinMessageEol; CoinSort_2(value, value + numberSolutions, which); // to get name CbcHeuristicRINS dummyHeuristic; @@ -3110,8 +3218,7 @@ void CbcModel::branchAndBound(int doStatistics) User hook, says John. */ - if (intParam_[CbcMaxNumNode] < 0 - || numberSolutions_ >= getMaximumSolutions()) + if (intParam_[CbcMaxNumNode] < 0 || numberSolutions_ >= getMaximumSolutions()) eventHappened_ = true; // stop as fast as possible stoppedOnGap_ = false; // See if can stop on gap @@ -3120,7 +3227,7 @@ void CbcModel::branchAndBound(int doStatistics) if (bestPossibleObjective_ < getCutoff()) stoppedOnGap_ = true; feasible = false; - //eventHappened_=true; // stop as fast as possible + // eventHappened_=true; // stop as fast as possible } /* Set up for statistics collection, if requested. Standard values are @@ -3136,7 +3243,8 @@ void CbcModel::branchAndBound(int doStatistics) memset(statistics_, 0, maximumStatistics_ * sizeof(CbcStatistics *)); } // See if we can add integers - if (noObjects && numberIntegers_ < solver_->getNumCols() && (specialOptions_ & 65536) != 0 && !parentModel_ && false) { + if (noObjects && numberIntegers_ < solver_->getNumCols() && + (specialOptions_ & 65536) != 0 && !parentModel_ && false) { int numberIntegers1 = 0; int numberColumns = solver_->getNumCols(); for (int i = 0; i < numberColumns; i++) { @@ -3158,13 +3266,13 @@ void CbcModel::branchAndBound(int doStatistics) /* Do an initial round of cut generation for the root node. Depending on the - type of underlying solver, we may want to do this even if the initial query - to the objects indicates they're satisfied. + type of underlying solver, we may want to do this even if the initial + query to the objects indicates they're satisfied. - solveWithCuts does the heavy lifting. It will iterate a generate/reoptimise - loop (including reduced cost fixing) until no cuts are generated, the - change in objective falls off, or the limit on the number of rounds of cut - generation is exceeded. + solveWithCuts does the heavy lifting. It will iterate a + generate/reoptimise loop (including reduced cost fixing) until no cuts are + generated, the change in objective falls off, or the limit on the number + of rounds of cut generation is exceeded. At the end of all this, any cuts will be recorded in cuts and also installed in the solver's constraint system. We'll have reoptimised, and @@ -3177,7 +3285,7 @@ void CbcModel::branchAndBound(int doStatistics) currentSolution_ = new double[numberColumns]; testSolution_ = currentSolution_; memcpy(currentSolution_, solver_->getColSolution(), - numberColumns * sizeof(double)); + numberColumns * sizeof(double)); // point to useful information OsiBranchingInformation usefulInfo = usefulInformation(); @@ -3186,10 +3294,10 @@ void CbcModel::branchAndBound(int doStatistics) if (infeasibility) numberUnsatisfied++; } - if (!numberUnsatisfied&&(moreSpecialOptions2_&65536)!=0) { + if (!numberUnsatisfied && (moreSpecialOptions2_ & 65536) != 0) { // lazy constraints - see if OK if (!reallyValid(&cuts)) - numberUnsatisfied=1; + numberUnsatisfied = 1; } // replace solverType double *tightBounds = NULL; @@ -3211,16 +3319,19 @@ void CbcModel::branchAndBound(int doStatistics) } } int numberModels = multipleRootTries_ % 100; - const OsiSolverInterface **solvers = new const OsiSolverInterface *[numberModels]; + const OsiSolverInterface **solvers = + new const OsiSolverInterface *[numberModels]; int numberRows = continuousSolver_->getNumRows(); - int maxCuts = 0; + int maxCuts = 0; for (int i = 0; i < numberModels; i++) { solvers[i] = rootModels[i]->solver(); const double *lower = solvers[i]->getColLower(); const double *upper = solvers[i]->getColUpper(); for (int j = 0; j < numberColumns; j++) { - tightBounds[2 * j + 0] = CoinMax(lower[j], tightBounds[2 * j + 0]); - tightBounds[2 * j + 1] = CoinMin(upper[j], tightBounds[2 * j + 1]); + tightBounds[2 * j + 0] = + CoinMax(lower[j], tightBounds[2 * j + 0]); + tightBounds[2 * j + 1] = + CoinMin(upper[j], tightBounds[2 * j + 1]); } int numberRows2 = solvers[i]->getNumRows(); assert(numberRows2 >= numberRows); @@ -3233,7 +3344,7 @@ void CbcModel::branchAndBound(int doStatistics) for (int j = 0; j < numberCutGenerators_; j++) { generator_[j]->scaleBackStatistics(numberModels); } - //CbcRowCuts rowCut(maxCuts); + // CbcRowCuts rowCut(maxCuts); const OsiRowCutDebugger *debugger = NULL; if ((specialOptions_ & 1) != 0) debugger = solver_->getRowCutDebugger(); @@ -3251,20 +3362,33 @@ void CbcModel::branchAndBound(int doStatistics) rc.setLb(rowLower[iRow]); rc.setUb(rowUpper[iRow]); CoinBigIndex start = rowStart[iRow]; - rc.setRow(rowLength[iRow], column + start, elements + start, false); + rc.setRow(rowLength[iRow], column + start, elements + start, + false); if (debugger) CoinAssert(!debugger->invalidCut(rc)); globalCuts_.addCutIfNotDuplicate(rc); } - //int cutsAdded=globalCuts_.numberCuts()-numberCuts; - //numberCuts += cutsAdded; - //printf("Model %d gave %d cuts (out of %d possible)\n", + + // add in global cuts from root model + { + CbcRowCuts * rootGlobalCuts = rootModels[iModel]->globalCuts(); + int numberCuts = rootGlobalCuts->sizeRowCuts(); + for (int i = 0; i < numberCuts; i++) { + OsiRowCut2 *cut = rootGlobalCuts->cut(i); + int returnCode = globalCuts_.addCutIfNotDuplicate(*cut); + if (!returnCode) + maxCuts++; + } + } + // int cutsAdded=globalCuts_.numberCuts()-numberCuts; + // numberCuts += cutsAdded; + // printf("Model %d gave %d cuts (out of %d possible)\n", // iModel,cutsAdded,numberRows2-numberRows); } // normally replace global cuts - //if (!globalCuts_.()) - //globalCuts_=rowCutrowCut.addCuts(globalCuts_); - //rowCut.addCuts(globalCuts_); + // if (!globalCuts_.()) + // globalCuts_=rowCutrowCut.addCuts(globalCuts_); + // rowCut.addCuts(globalCuts_); int nTightened = 0; assert(feasible); { @@ -3275,10 +3399,13 @@ void CbcModel::branchAndBound(int doStatistics) if (tightBounds[2 * i + 0] > tightBounds[2 * i + 1] + 1.0e-9) { feasible = false; char general[200]; - sprintf(general, "Solvers give infeasible bounds on %d %g,%g was %g,%g - search finished\n", - i, tightBounds[2 * i + 0], tightBounds[2 * i + 1], lower[i], upper[i]); + sprintf(general, + "Solvers give infeasible bounds on %d %g,%g was %g,%g " + "- search finished\n", + i, tightBounds[2 * i + 0], tightBounds[2 * i + 1], + lower[i], upper[i]); messageHandler()->message(CBC_GENERAL, messages()) - << general << CoinMessageEol; + << general << CoinMessageEol; break; } double oldLower = lower[i]; @@ -3296,15 +3423,15 @@ void CbcModel::branchAndBound(int doStatistics) delete[] tightBounds; tightBounds = NULL; char printBuffer[200]; - sprintf(printBuffer, "%d solvers added %d different cuts out of pool of %d", - numberModels, globalCuts_.sizeRowCuts(), maxCuts); + sprintf(printBuffer, + "%d solvers added %d different cuts out of pool of %d", + numberModels, globalCuts_.sizeRowCuts(), maxCuts); messageHandler()->message(CBC_GENERAL, messages()) - << printBuffer << CoinMessageEol; + << printBuffer << CoinMessageEol; if (nTightened) { - sprintf(printBuffer, "%d bounds were tightened", - nTightened); + sprintf(printBuffer, "%d bounds were tightened", nTightened); messageHandler()->message(CBC_GENERAL, messages()) - << printBuffer << CoinMessageEol; + << printBuffer << CoinMessageEol; } delete[] solvers; } @@ -3338,18 +3465,18 @@ void CbcModel::branchAndBound(int doStatistics) double randomNumber = randomNumberGenerator_.randomDouble(); if (numberEntries > 0) { initialCuts++; - nRead = fread(elements, sizeof(double), numberEntries + 2, fp); - if (nRead != static_cast< size_t >(numberEntries + 2)) + nRead = + fread(elements, sizeof(double), numberEntries + 2, fp); + if (nRead != static_cast(numberEntries + 2)) throw("Error in fread"); nRead = fread(indices, sizeof(int), numberEntries, fp); - if (nRead != static_cast< size_t >(numberEntries)) + if (nRead != static_cast(numberEntries)) throw("Error in fread"); if (randomNumber > threshold) { OsiRowCut rc; rc.setLb(elements[numberEntries]); rc.setUb(elements[numberEntries + 1]); - rc.setRow(numberEntries, indices, elements, - false); + rc.setRow(numberEntries, indices, elements, false); rc.setGloballyValidAsInteger(2); globalCuts_.addCutIfNotDuplicate(rc); } @@ -3365,7 +3492,7 @@ void CbcModel::branchAndBound(int doStatistics) throw("Error in fread"); if (numberColumns != indices[0]) { printf("Mismatch on columns %d %d\n", numberColumns, - indices[0]); + indices[0]); } else { indices[0] = 1; while (indices[0] >= 0) { @@ -3387,19 +3514,20 @@ void CbcModel::branchAndBound(int doStatistics) if (fp) fclose(fp); char printBuffer[200]; - sprintf(printBuffer, "%d cuts read in of which %d were unique, %d bounds tightened", - initialCuts, - globalCuts_.sizeRowCuts() - initialGlobal, nTightened); + sprintf(printBuffer, + "%d cuts read in of which %d were unique, %d bounds " + "tightened", + initialCuts, globalCuts_.sizeRowCuts() - initialGlobal, + nTightened); messageHandler()->message(CBC_GENERAL, messages()) - << printBuffer << CoinMessageEol; + << printBuffer << CoinMessageEol; delete[] elements; delete[] indices; } } } if (feasible) - feasible = solveWithCuts(cuts, maximumCutPassesAtRoot_, - NULL); + feasible = solveWithCuts(cuts, maximumCutPassesAtRoot_, NULL); if (multipleRootTries_ && (moreSpecialOptions_ & 134217728) != 0) { FILE *fp = NULL; size_t nRead; @@ -3433,10 +3561,10 @@ void CbcModel::branchAndBound(int doStatistics) if (numberEntries > 0) { initialCuts++; nRead = fread(elements, sizeof(double), numberEntries + 2, fp); - if (nRead != static_cast< size_t >(numberEntries + 2)) + if (nRead != static_cast(numberEntries + 2)) throw("Error in fread"); nRead = fread(indices, sizeof(int), numberEntries, fp); - if (nRead != static_cast< size_t >(numberEntries)) + if (nRead != static_cast(numberEntries)) throw("Error in fread"); } else { // end @@ -3455,7 +3583,7 @@ void CbcModel::branchAndBound(int doStatistics) int numberC = continuousSolver_->getNumRows(); int numberRows = solver_->getNumRows(); printf("Saving %d cuts (up from %d)\n", - initialCuts + numberRows - numberC, initialCuts); + initialCuts + numberRows - numberC, initialCuts); const double *rowLower = solver_->getRowLower(); const double *rowUpper = solver_->getRowUpper(); // Row copy @@ -3476,10 +3604,10 @@ void CbcModel::branchAndBound(int doStatistics) if (nWrite != 1) throw("Error in fwrite"); nWrite = fwrite(elements, sizeof(double), n + 2, fp); - if (nWrite != static_cast< size_t >(n + 2)) + if (nWrite != static_cast(n + 2)) throw("Error in fwrite"); nWrite = fwrite(indices, sizeof(int), n, fp); - if (nWrite != static_cast< size_t >(n)) + if (nWrite != static_cast(n)) throw("Error in fwrite"); } // eof marker @@ -3548,8 +3676,8 @@ void CbcModel::branchAndBound(int doStatistics) delete[] elements; delete[] indices; } - if ((specialOptions_ & 524288) != 0 && !parentModel_ - && storedRowCuts_) { + if ((specialOptions_ & 524288) != 0 && !parentModel_ && + storedRowCuts_) { if (feasible) { /* pick up stuff and try again add cuts, maybe keep around @@ -3575,17 +3703,18 @@ void CbcModel::branchAndBound(int doStatistics) } } if (nTightened) - COIN_DETAIL_PRINT(printf("%d tightened by alternate cuts\n", nTightened)); + COIN_DETAIL_PRINT( + printf("%d tightened by alternate cuts\n", nTightened)); if (storedRowCuts_->bestObjective() < bestObjective_) { // B) best solution double objValue = storedRowCuts_->bestObjective(); setBestSolution(CBC_SOLUTION, objValue, - storedRowCuts_->bestSolution()); + storedRowCuts_->bestSolution()); // Do heuristics // Allow RINS for (int i = 0; i < numberHeuristics_; i++) { - CbcHeuristicRINS *rins - = dynamic_cast< CbcHeuristicRINS * >(heuristic_[i]); + CbcHeuristicRINS *rins = + dynamic_cast(heuristic_[i]); if (rins) { rins->setLastNode(-100); } @@ -3602,8 +3731,8 @@ void CbcModel::branchAndBound(int doStatistics) globalCuts_.insert(newCut); } #else - addCutGenerator(storedRowCuts_, -99, "Stored from previous run", - true, false, false, -200); + addCutGenerator(storedRowCuts_, -99, "Stored from previous run", true, + false, false, -200); #endif // Set cuts as active delete[] addedCuts_; @@ -3614,13 +3743,12 @@ void CbcModel::branchAndBound(int doStatistics) addedCuts_ = NULL; } for (int i = 0; i < maximumNumberCuts_; i++) - addedCuts_[i] = new CbcCountRowCut(*cuts.rowCutPtr(i), - NULL, -1, -1, 2); + addedCuts_[i] = + new CbcCountRowCut(*cuts.rowCutPtr(i), NULL, -1, -1, 2); COIN_DETAIL_PRINT(printf("size %d\n", cuts.sizeRowCuts())); cuts = OsiCuts(); currentNumberCuts_ = maximumNumberCuts_; - feasible = solveWithCuts(cuts, maximumCutPassesAtRoot_, - NULL); + feasible = solveWithCuts(cuts, maximumCutPassesAtRoot_, NULL); for (int i = 0; i < maximumNumberCuts_; i++) delete addedCuts_[i]; } @@ -3630,11 +3758,11 @@ void CbcModel::branchAndBound(int doStatistics) } else { feasible = false; } - } else if (solverCharacteristics_->solutionAddsCuts() || solverCharacteristics_->alwaysTryCutsAtRootNode()) { + } else if (solverCharacteristics_->solutionAddsCuts() || + solverCharacteristics_->alwaysTryCutsAtRootNode()) { // may generate cuts and turn the solution - //to an infeasible one - feasible = solveWithCuts(cuts, 2, - NULL); + // to an infeasible one + feasible = solveWithCuts(cuts, 2, NULL); } } if (rootModels) { @@ -3652,25 +3780,27 @@ void CbcModel::branchAndBound(int doStatistics) if (feasible) feasible = false; else - setMaximumNodes(1); //allow to stop on success + setMaximumNodes(1); // allow to stop on success } topOfTree_ = NULL; #ifdef CLP_RESOLVE if ((moreSpecialOptions_ & 2097152) != 0 && !parentModel_ && feasible) { - OsiClpSolverInterface *clpSolver - = dynamic_cast< OsiClpSolverInterface * >(solver_); + OsiClpSolverInterface *clpSolver = + dynamic_cast(solver_); if (clpSolver) resolveClp(clpSolver, 0); } #endif // make cut generators less aggressive - for (iCutGenerator = 0; iCutGenerator < numberCutGenerators_; iCutGenerator++) { + for (iCutGenerator = 0; iCutGenerator < numberCutGenerators_; + iCutGenerator++) { CglCutGenerator *generator = generator_[iCutGenerator]->generator(); generator->setAggressiveness(generator->getAggressiveness() - 100); } currentNumberCuts_ = numberNewCuts_; if (solverCharacteristics_->solutionAddsCuts()) { - // With some heuristics solver needs a resolve here (don't know if this is bug in heuristics) + // With some heuristics solver needs a resolve here (don't know if this is + // bug in heuristics) solver_->resolve(); if (!isProvenOptimal()) { solver_->initialSolve(); @@ -3691,11 +3821,12 @@ void CbcModel::branchAndBound(int doStatistics) This is the notion of using Cbc stuff to get going, then calling cplex to finish off. */ - if (feasible && (specialOptions_ & 16384) != 0 && fastNodeDepth_ == -2 && !parentModel_) { + if (feasible && (specialOptions_ & 16384) != 0 && fastNodeDepth_ == -2 && + !parentModel_) { // Use Cplex to do search! double time1 = CoinCpuTime(); - OsiClpSolverInterface *clpSolver - = dynamic_cast< OsiClpSolverInterface * >(solver_); + OsiClpSolverInterface *clpSolver = + dynamic_cast(solver_); OsiCpxSolverInterface cpxSolver; double direction = clpSolver->getObjSense(); cpxSolver.setObjSense(direction); @@ -3706,8 +3837,8 @@ void CbcModel::branchAndBound(int doStatistics) const double *columnLower = continuousSolver_->getColLower(); const double *columnUpper = continuousSolver_->getColUpper(); const double *objective = continuousSolver_->getObjCoefficients(); - cpxSolver.loadProblem(*matrix, columnLower, columnUpper, - objective, rowLower, rowUpper); + cpxSolver.loadProblem(*matrix, columnLower, columnUpper, objective, + rowLower, rowUpper); double *setSol = new double[numberIntegers_]; int *setVar = new int[numberIntegers_]; // cplex doesn't know about objective offset @@ -3728,7 +3859,8 @@ void CbcModel::branchAndBound(int doStatistics) CPXcopymipstart(env, lpPtr, numberIntegers_, setVar, setSol); #else int zero = 0; - CPXaddmipstarts(env, lpPtr, 1, numberIntegers_, &zero, setVar, setSol, NULL, NULL); + CPXaddmipstarts(env, lpPtr, 1, numberIntegers_, &zero, setVar, setSol, + NULL, NULL); #endif } if (clpSolver->getNumRows() > continuousSolver_->getNumRows() && false) { @@ -3757,12 +3889,11 @@ void CbcModel::branchAndBound(int doStatistics) nAdd++; rmatbeg[nAdd] = size; } - CPXaddlazyconstraints(env, lpPtr, nAdd, size, - rhs, rowSense, rmatbeg, - rmatind, rmatval, NULL); + CPXaddlazyconstraints(env, lpPtr, nAdd, size, rhs, rowSense, rmatbeg, + rmatind, rmatval, NULL); CPXsetintparam(env, CPX_PARAM_REDUCE, - // CPX_PREREDUCE_NOPRIMALORDUAL (0) - CPX_PREREDUCE_PRIMALONLY); + // CPX_PREREDUCE_NOPRIMALORDUAL (0) + CPX_PREREDUCE_PRIMALONLY); } if (getCutoff() < 1.0e50) { double useCutoff = getCutoff() + offset; @@ -3780,17 +3911,16 @@ void CbcModel::branchAndBound(int doStatistics) char printBuffer[200]; if (offset) { sprintf(printBuffer, "Add %g to all Cplex messages for true objective", - -offset); + -offset); messageHandler()->message(CBC_GENERAL, messages()) - << printBuffer << CoinMessageEol; + << printBuffer << CoinMessageEol; cpxSolver.setDblParam(OsiObjOffset, offset); } cpxSolver.branchAndBound(); double timeTaken = CoinCpuTime() - time1; - sprintf(printBuffer, "Cplex took %g seconds", - timeTaken); + sprintf(printBuffer, "Cplex took %g seconds", timeTaken); messageHandler()->message(CBC_GENERAL, messages()) - << printBuffer << CoinMessageEol; + << printBuffer << CoinMessageEol; numberExtraNodes_ = CPXgetnodecnt(env, lpPtr); numberExtraIterations_ = CPXgetmipitcnt(env, lpPtr); double value = cpxSolver.getObjValue() * direction; @@ -3798,8 +3928,8 @@ void CbcModel::branchAndBound(int doStatistics) feasible = true; clpSolver->setWarmStart(NULL); // try and do solution - double *newSolution = CoinCopyOfArray(cpxSolver.getColSolution(), - getNumCols()); + double *newSolution = + CoinCopyOfArray(cpxSolver.getColSolution(), getNumCols()); setBestSolution(CBC_STRONGSOL, value, newSolution); delete[] newSolution; } @@ -3817,7 +3947,8 @@ void CbcModel::branchAndBound(int doStatistics) /* A hook to use clp to quickly explore some part of the tree. */ - if (fastNodeDepth_ == 1000 && /*!parentModel_*/ (specialOptions_ & 2048) == 0) { + if (fastNodeDepth_ == 1000 && + /*!parentModel_*/ (specialOptions_ & 2048) == 0) { fastNodeDepth_ = -1; CbcObject *obj = new CbcFollowOn(this); obj->setPriority(1); @@ -3826,10 +3957,11 @@ void CbcModel::branchAndBound(int doStatistics) } int saveNumberSolves = numberSolves_; int saveNumberIterations = numberIterations_; - if ((fastNodeDepth_ >= 0 || (moreSpecialOptions_ & 33554432) != 0) - && /*!parentModel_*/ (specialOptions_ & 2048) == 0) { + if ((fastNodeDepth_ >= 0 || (moreSpecialOptions_ & 33554432) != 0) && + /*!parentModel_*/ (specialOptions_ & 2048) == 0) { // add in a general depth object doClp - int type = (fastNodeDepth_ <= 100) ? fastNodeDepth_ : -(fastNodeDepth_ - 100); + int type = + (fastNodeDepth_ <= 100) ? fastNodeDepth_ : -(fastNodeDepth_ - 100); if ((moreSpecialOptions_ & 33554432) != 0) type = 12; else @@ -3842,7 +3974,7 @@ void CbcModel::branchAndBound(int doStatistics) if (parallelMode() < -1) { // But make sure position is correct OsiObject *obj2 = object_[numberObjects_]; - obj = dynamic_cast< CbcObject * >(obj2); + obj = dynamic_cast(obj2); assert(obj); obj->setPosition(numberObjects_); } @@ -3850,12 +3982,12 @@ void CbcModel::branchAndBound(int doStatistics) #ifdef CBC_HAS_CLP #ifdef NO_CRUNCH if (true) { - OsiClpSolverInterface *clpSolver - = dynamic_cast< OsiClpSolverInterface * >(solver_); + OsiClpSolverInterface *clpSolver = + dynamic_cast(solver_); if (clpSolver && !parentModel_) { ClpSimplex *clpSimplex = clpSolver->getModelPtr(); clpSimplex->setSpecialOptions(clpSimplex->specialOptions() | 131072); - //clpSimplex->startPermanentArrays(); + // clpSimplex->startPermanentArrays(); clpSimplex->setPersistenceFlag(2); } } @@ -3865,17 +3997,15 @@ void CbcModel::branchAndBound(int doStatistics) OsiSolverInterface *saveSolver = NULL; if (!parentModel_ && (specialOptions_ & (512 + 32768)) != 0) saveSolver = solver_->clone(); - else if (parentModel_ && - !(specialOptions_&2048) && - (specialOptions_ & (512 + 32768)) == 512) + else if (parentModel_ && !(specialOptions_ & 2048) && + (specialOptions_ & (512 + 32768)) == 512) saveSolver = solver_->clone(); double checkCutoffForRestart = 1.0e100; saveModel(saveSolver, &checkCutoffForRestart, &feasible); if ((specialOptions_ & 262144) != 0 && !parentModel_) { // Save stuff and return! storedRowCuts_->saveStuff(bestObjective_, bestSolution_, - solver_->getColLower(), - solver_->getColUpper()); + solver_->getColLower(), solver_->getColUpper()); delete[] lowerBefore; delete[] upperBefore; delete saveSolver; @@ -3892,8 +4022,8 @@ void CbcModel::branchAndBound(int doStatistics) == -2) when forced to integer values, it returns here immediately. Monotone variables trigger a call to resolve(). If the problem remains - feasible, try again to choose a branching variable. At the end of the loop, - resolved == true indicates that some variables were fixed. + feasible, try again to choose a branching variable. At the end of the + loop, resolved == true indicates that some variables were fixed. Loss of feasibility will result in the deletion of newNode. */ @@ -3904,8 +4034,8 @@ void CbcModel::branchAndBound(int doStatistics) numberFixedNow_ = 0; if (!parentModel_ && (moreSpecialOptions2_ & 2) != 0) { #ifdef CBC_HAS_CLP - OsiClpSolverInterface *clpSolver - = dynamic_cast< OsiClpSolverInterface * >(solver_); + OsiClpSolverInterface *clpSolver = + dynamic_cast(solver_); if (clpSolver) { if (getCutoff() > 1.0e20) { printf("Zapping costs\n"); @@ -3929,7 +4059,7 @@ void CbcModel::branchAndBound(int doStatistics) #endif } int numberIterationsAtContinuous = numberIterations_; - //solverCharacteristics_->setSolver(solver_); + // solverCharacteristics_->setSolver(solver_); if (feasible) { // mark all cuts as globally valid int numberCuts = cuts.sizeRowCuts(); @@ -3940,7 +4070,8 @@ void CbcModel::branchAndBound(int doStatistics) } #define HOTSTART -1 #if HOTSTART < 0 - if (bestSolution_ && !parentModel_ && !hotstartSolution_ && (moreSpecialOptions_ & 1024) != 0 && (specialOptions_ & 2048) == 0) { + if (bestSolution_ && !parentModel_ && !hotstartSolution_ && + (moreSpecialOptions_ & 1024) != 0 && (specialOptions_ & 2048) == 0) { // Set priorities so only branch on ones we need to // use djs and see if only few branches needed #ifndef NDEBUG @@ -3950,7 +4081,8 @@ void CbcModel::branchAndBound(int doStatistics) const double *saveLower = continuousSolver_->getColLower(); const double *saveUpper = continuousSolver_->getColUpper(); for (int i = 0; i < numberObjects_; i++) { - const CbcSimpleInteger *thisOne = dynamic_cast< const CbcSimpleInteger * >(object_[i]); + const CbcSimpleInteger *thisOne = + dynamic_cast(object_[i]); if (thisOne) { int iColumn = thisOne->columnNumber(); if (saveUpper[iColumn] > saveLower[iColumn] + 1.5) { @@ -3963,7 +4095,7 @@ void CbcModel::branchAndBound(int doStatistics) } } int numberColumns = solver_->getNumCols(); - if (possible==3) { + if (possible == 3) { OsiSolverInterface *solver = continuousSolver_->clone(); for (int iColumn = 0; iColumn < numberColumns; iColumn++) { double value = bestSolution_[iColumn]; @@ -3979,7 +4111,8 @@ void CbcModel::branchAndBound(int doStatistics) // objlim and all slack double direction = solver->getObjSense(); solver->setDblParam(OsiDualObjectiveLimit, 1.0e50 * direction); - CoinWarmStartBasis *basis = dynamic_cast< CoinWarmStartBasis * >(solver->getEmptyWarmStart()); + CoinWarmStartBasis *basis = + dynamic_cast(solver->getEmptyWarmStart()); solver->setWarmStart(basis); delete basis; bool changed = true; @@ -4037,26 +4170,27 @@ void CbcModel::branchAndBound(int doStatistics) } #if CBC_USEFUL_PRINTING > 1 printf("%d forced, %d naturally at lower, %d at upper - %d zero dj\n", - nForced, nAtLbNatural, nAtUbNatural, nZeroDj); + nForced, nAtLbNatural, nAtUbNatural, nZeroDj); #endif if (nAtLbNatural || nAtUbNatural) { changed = true; } else { - if (nForced + nZeroDj > 5000 || (nForced + nZeroDj) * 2 > numberIntegers_) + if (nForced + nZeroDj > 5000 || + (nForced + nZeroDj) * 2 > numberIntegers_) possible = false; } } delete solver; } else if (possible) { - // general integers - not so good - int * prioritiesIn = new int [numberColumns]; - memset(prioritiesIn,0,numberColumns*sizeof(int)); - for (int i = 0; i < numberObjects_; i++) { - OsiObject *object = object_[i]; - prioritiesIn[object->columnNumber()] = object->priority(); - } + // general integers - not so good + int *prioritiesIn = new int[numberColumns]; + memset(prioritiesIn, 0, numberColumns * sizeof(int)); + for (int i = 0; i < numberObjects_; i++) { + OsiObject *object = object_[i]; + prioritiesIn[object->columnNumber()] = object->priority(); + } } else { - moreSpecialOptions_ &= ~1024; + moreSpecialOptions_ &= ~1024; } if (possible) { setHotstartSolution(bestSolution_); @@ -4066,7 +4200,7 @@ void CbcModel::branchAndBound(int doStatistics) // depth first nodeCompare_ = new CbcCompareDepth(); tree_->setComparison(*nodeCompare_); - hotstartObjectiveValue = getCutoff(); + hotstartObjectiveValue = getCutoff(); } } else { delete[] hotstartPriorities_; @@ -4090,16 +4224,18 @@ void CbcModel::branchAndBound(int doStatistics) OsiBranchingInformation usefulInfo = usefulInformation(); testSolution_ = saveSolution; /* - Run through the objects and use feasibleRegion() to set variable bounds - so as to fix the variables specified in the objects at their value in this - solution. Since the object list contains (at least) one object for every - integer variable, this has the effect of fixing all integer variables. + Run through the objects and use feasibleRegion() to set variable + bounds so as to fix the variables specified in the objects at their + value in this solution. Since the object list contains (at least) one + object for every integer variable, this has the effect of fixing all + integer variables. */ for (int i = 0; i < numberObjects_; i++) object_[i]->feasibleRegion(solver, &usefulInfo); solver->resolve(); assert(solver->isProvenOptimal()); - double gap = CoinMax((solver->getObjValue() - solver_->getObjValue()) * direction, 0.0); + double gap = CoinMax( + (solver->getObjValue() - solver_->getObjValue()) * direction, 0.0); const double *dj = solver->getReducedCost(); const double *colLower = solver->getColLower(); const double *colUpper = solver->getColUpper(); @@ -4130,7 +4266,7 @@ void CbcModel::branchAndBound(int doStatistics) double value2 = floor(value + 0.5); if (dj[iColumn] < -1.0e-6) { // negative dj - //assert (value2==colUpper[iColumn]); + // assert (value2==colUpper[iColumn]); if (saveUpper[iColumn] == colUpper[iColumn]) { nAtUbNatural++; sortValue = 0.0; @@ -4149,14 +4285,15 @@ void CbcModel::branchAndBound(int doStatistics) } else { nAtOther++; sortValue = 0.0; - if (saveLower[iColumn] != colLower[iColumn] && saveUpper[iColumn] != colUpper[iColumn]) { + if (saveLower[iColumn] != colLower[iColumn] && + saveUpper[iColumn] != colUpper[iColumn]) { nNotNeeded++; sortValue = 1.0e20; } } } else if (dj[iColumn] > 1.0e-6) { // positive dj - //assert (value2==colLower[iColumn]); + // assert (value2==colLower[iColumn]); if (saveLower[iColumn] == colLower[iColumn]) { nAtLbNatural++; sortValue = 0.0; @@ -4175,7 +4312,8 @@ void CbcModel::branchAndBound(int doStatistics) } else { nAtOther++; sortValue = 0.0; - if (saveLower[iColumn] != colLower[iColumn] && saveUpper[iColumn] != colUpper[iColumn]) { + if (saveLower[iColumn] != colLower[iColumn] && + saveUpper[iColumn] != colUpper[iColumn]) { nNotNeeded++; sortValue = 1.0e20; } @@ -4195,7 +4333,8 @@ void CbcModel::branchAndBound(int doStatistics) } else { nAtOtherNatural++; sortValue = 0.0; - if (saveLower[iColumn] != colLower[iColumn] && saveUpper[iColumn] != colUpper[iColumn]) { + if (saveLower[iColumn] != colLower[iColumn] && + saveUpper[iColumn] != colUpper[iColumn]) { nNotNeeded++; sortValue = 1.0e20; } @@ -4209,8 +4348,9 @@ void CbcModel::branchAndBound(int doStatistics) saveLower[iColumn] = sortValue; order[iColumn] = iColumn; } - COIN_DETAIL_PRINT(printf("** can fix %d columns - best ratio for others is %g on gap of %g\n", - nFix, bestRatio, gap)); + COIN_DETAIL_PRINT(printf( + "** can fix %d columns - best ratio for others is %g on gap of %g\n", + nFix, bestRatio, gap)); int nNeg = 0; CoinSort_2(saveLower, saveLower + numberColumns, order); for (int i = 0; i < numberColumns; i++) { @@ -4230,15 +4370,11 @@ void CbcModel::branchAndBound(int doStatistics) hotstartPriorities_[order[i]] = -(i + 1); #endif } - COIN_DETAIL_PRINT(printf("nAtLbNat %d,nAtUbNat %d,nAtLbNatZero %d,nAtUbNatZero %d,nAtLbFixed %d,nAtUbFixed %d,nAtOther %d,nAtOtherNat %d, useless %d %d\n", - nAtLbNatural, - nAtUbNatural, - nAtLbNaturalZero, - nAtUbNaturalZero, - nAtLbFixed, - nAtUbFixed, - nAtOther, - nAtOtherNatural, nNotNeeded, nNeg)); + COIN_DETAIL_PRINT(printf( + "nAtLbNat %d,nAtUbNat %d,nAtLbNatZero %d,nAtUbNatZero %d,nAtLbFixed " + "%d,nAtUbFixed %d,nAtOther %d,nAtOtherNat %d, useless %d %d\n", + nAtLbNatural, nAtUbNatural, nAtLbNaturalZero, nAtUbNaturalZero, + nAtLbFixed, nAtUbFixed, nAtOther, nAtOtherNatural, nNotNeeded, nNeg)); delete[] saveLower; delete[] saveUpper; if (!saveCompare) { @@ -4247,7 +4383,7 @@ void CbcModel::branchAndBound(int doStatistics) // depth first nodeCompare_ = new CbcCompareDepth(); tree_->setComparison(*nodeCompare_); - hotstartObjectiveValue = getCutoff(); + hotstartObjectiveValue = getCutoff(); } } #endif @@ -4263,7 +4399,7 @@ void CbcModel::branchAndBound(int doStatistics) // This is first crude step if (numberAnalyzeIterations_ && !parentModel_) { delete[] analyzeResults_; - //int numberColumns = solver_->getNumCols(); + // int numberColumns = solver_->getNumCols(); analyzeResults_ = new double[5 * numberIntegers_]; numberFixedAtRoot_ = newNode->analyze(this, analyzeResults_); if (numberFixedAtRoot_ > 0) { @@ -4281,7 +4417,7 @@ void CbcModel::branchAndBound(int doStatistics) OsiSolverBranch *branches = NULL; if (feasible) anyAction = chooseBranch(newNode, numberPassesLeft, NULL, cuts, resolved, - NULL, NULL, NULL, branches); + NULL, NULL, NULL, branches); if (anyAction == -2 || newNode->objectiveValue() >= cutoff) { if (anyAction != -2) { // zap parent nodeInfo @@ -4298,17 +4434,17 @@ void CbcModel::branchAndBound(int doStatistics) } if (newNode && probingInfo_) { int number01 = probingInfo_->numberIntegers(); - //const fixEntry * entry = probingInfo_->fixEntries(); + // const fixEntry * entry = probingInfo_->fixEntries(); const int *toZero = probingInfo_->toZero(); - //const int * toOne = probingInfo_->toOne(); - //const int * integerVariable = probingInfo_->integerVariable(); + // const int * toOne = probingInfo_->toOne(); + // const int * integerVariable = probingInfo_->integerVariable(); if (toZero[number01]) { CglTreeProbingInfo info(*probingInfo_); if ((moreSpecialOptions2_ & 64) != 0 && !parentModel_) { /* - Marginal idea. Further exploration probably good. Build some extra - cliques from probing info. Not quite worth the effort? - */ + Marginal idea. Further exploration probably good. Build some + extra cliques from probing info. Not quite worth the effort? + */ CglProbing generator1; generator1.setUsingObjective(false); generator1.setMaxPass(1); @@ -4318,7 +4454,7 @@ void CbcModel::branchAndBound(int doStatistics) generator1.setMaxElements(300); generator1.setMaxProbeRoot(solver_->getNumCols()); CoinThreadRandom randomGenerator; - //CglTreeProbingInfo info(solver_); + // CglTreeProbingInfo info(solver_); info.level = 0; info.formulation_rows = solver_->getNumRows(); info.inTree = false; @@ -4368,15 +4504,17 @@ void CbcModel::branchAndBound(int doStatistics) fake = info.analyze(*solver_, 1); } if (fake) { - //fake->writeMps("fake"); + // fake->writeMps("fake"); CglFakeClique cliqueGen(fake); cliqueGen.setStarCliqueReport(false); cliqueGen.setRowCliqueReport(false); cliqueGen.setMinViolation(0.1); - addCutGenerator(&cliqueGen, 1, "Fake cliques", true, false, false, -200); + addCutGenerator(&cliqueGen, 1, "Fake cliques", true, false, false, + -200); generator_[numberCutGenerators_ - 1]->setTiming(true); for (int i = 0; i < numberCutGenerators_; i++) { - CglKnapsackCover *cutGen = dynamic_cast< CglKnapsackCover * >(generator_[i]->generator()); + CglKnapsackCover *cutGen = + dynamic_cast(generator_[i]->generator()); if (cutGen) { cutGen->createCliques(*fake, 2, 200, false); } @@ -4387,9 +4525,11 @@ void CbcModel::branchAndBound(int doStatistics) #if CBC_USEFUL_PRINTING > 1 printf("%d implications on %d 0-1\n", toZero[number01], number01); #endif - // Create a cut generator that remembers implications discovered at root. + // Create a cut generator that remembers implications discovered at + // root. CglImplication implication(probingInfo_); - addCutGenerator(&implication, 1, "ImplicationCuts", true, false, false, -200); + addCutGenerator(&implication, 1, "ImplicationCuts", true, false, false, + -200); generator_[numberCutGenerators_ - 1]->setGlobalCuts(true); generator_[numberCutGenerators_ - 1]->setTiming(true); } else { @@ -4404,20 +4544,20 @@ void CbcModel::branchAndBound(int doStatistics) } /* At this point, the root subproblem is infeasible or fathomed by bound - (newNode == NULL), or we're live with an objective value that satisfies the - current objective cutoff. + (newNode == NULL), or we're live with an objective value that satisfies + the current objective cutoff. */ assert(!newNode || newNode->objectiveValue() <= cutoff); // Save address of root node as we don't want to delete it /* The common case is that the lp relaxation is feasible but doesn't satisfy - integrality (i.e., newNode->branchingObject(), indicating we've been able to - select a branching variable). Remove any cuts that have gone slack due to - forcing monotone variables. Then tack on an CbcFullNodeInfo object and full - basis (via createInfo()) and stash the new cuts in the nodeInfo (via + integrality (i.e., newNode->branchingObject(), indicating we've been able + to select a branching variable). Remove any cuts that have gone slack due + to forcing monotone variables. Then tack on an CbcFullNodeInfo object and + full basis (via createInfo()) and stash the new cuts in the nodeInfo (via addCuts()). If, by some miracle, we have an integral solution at the root - (newNode->branchingObject() is NULL), takeOffCuts() will ensure that the solver holds - a valid solution for use by setBestSolution(). + (newNode->branchingObject() is NULL), takeOffCuts() will ensure that the + solver holds a valid solution for use by setBestSolution(). */ CoinWarmStartBasis *lastws = NULL; if (feasible && newNode->branchingObject()) { @@ -4427,19 +4567,20 @@ void CbcModel::branchAndBound(int doStatistics) { printf("Number of rows after chooseBranch fix (root)" "(active only) %d\n", - numberRowsAtContinuous_ + numberNewCuts_ + numberOldActiveCuts_); - const CoinWarmStartBasis *debugws = dynamic_cast< const CoinWarmStartBasis * >(solver_->getWarmStart()); + numberRowsAtContinuous_ + numberNewCuts_ + numberOldActiveCuts_); + const CoinWarmStartBasis *debugws = + dynamic_cast(solver_->getWarmStart()); debugws->print(); delete debugws; } #endif } - //newNode->createInfo(this,NULL,NULL,NULL,NULL,0,0) ; - //newNode->nodeInfo()->addCuts(cuts, + // newNode->createInfo(this,NULL,NULL,NULL,NULL,0,0) ; + // newNode->nodeInfo()->addCuts(cuts, // newNode->numberBranches(),whichGenerator_) ; if (lastws) delete lastws; - lastws = dynamic_cast< CoinWarmStartBasis * >(solver_->getWarmStart()); + lastws = dynamic_cast(solver_->getWarmStart()); } /* Continuous data to be used later @@ -4449,8 +4590,8 @@ void CbcModel::branchAndBound(int doStatistics) if (newNode) { continuousObjective_ = newNode->objectiveValue(); delete[] continuousSolution_; - continuousSolution_ = CoinCopyOfArray(solver_->getColSolution(), - numberColumns); + continuousSolution_ = + CoinCopyOfArray(solver_->getColSolution(), numberColumns); continuousInfeasibilities_ = newNode->numberUnsatisfied(); } /* @@ -4475,7 +4616,7 @@ void CbcModel::branchAndBound(int doStatistics) tree_->push(newNode); // save pointer to root node - so can pick up bounds if (!topOfTree_) - topOfTree_ = dynamic_cast< CbcFullNodeInfo * >(newNode->nodeInfo()); + topOfTree_ = dynamic_cast(newNode->nodeInfo()); if (statistics_) { if (numberNodes2_ == maximumStatistics_) { maximumStatistics_ = 2 * maximumStatistics_; @@ -4495,8 +4636,7 @@ void CbcModel::branchAndBound(int doStatistics) } else { // continuous is integer double objectiveValue = newNode->objectiveValue(); - setBestSolution(CBC_SOLUTION, objectiveValue, - solver_->getColSolution()); + setBestSolution(CBC_SOLUTION, objectiveValue, solver_->getColSolution()); if (eventHandler) { // we are stopping anyway so no need to test return code eventHandler->event(CbcEventHandler::solution); @@ -4507,8 +4647,9 @@ void CbcModel::branchAndBound(int doStatistics) } /* - It is possible that strong branching fixes one variable and then the code goes round - again and again. This can take too long. So we need to warn user - just once. + It is possible that strong branching fixes one variable and then the code + goes round again and again. This can take too long. So we need to warn + user - just once. */ numberLongStrong_ = 0; CbcNode *createdNode = NULL; @@ -4517,15 +4658,14 @@ void CbcModel::branchAndBound(int doStatistics) numberThreads_ = 0; if (numberThreads_) { nodeCompare_->sayThreaded(); // need to use addresses - master_ = new CbcBaseModel(*this, - (parallelMode() < -1) ? 1 : 0); + master_ = new CbcBaseModel(*this, (parallelMode() < -1) ? 1 : 0); masterThread_ = master_->masterThread(); } #endif #ifdef CBC_HAS_CLP { - OsiClpSolverInterface *clpSolver - = dynamic_cast< OsiClpSolverInterface * >(solver_); + OsiClpSolverInterface *clpSolver = + dynamic_cast(solver_); if (clpSolver && !parentModel_) { clpSolver->computeLargestAway(); } @@ -4534,15 +4674,16 @@ void CbcModel::branchAndBound(int doStatistics) /* At last, the actual branch-and-cut search loop, which will iterate until the live set is empty or we hit some limit (integrality gap, time, node - count, etc.). The overall flow is to rebuild a subproblem, reoptimise using - solveWithCuts(), choose a branching pattern with chooseBranch(), and finally - add the node to the live set. + count, etc.). The overall flow is to rebuild a subproblem, reoptimise + using solveWithCuts(), choose a branching pattern with chooseBranch(), and + finally add the node to the live set. The first action is to winnow the live set to remove nodes which are worse than the current objective cutoff. */ if (solver_->getRowCutDebuggerAlways()) { - OsiRowCutDebugger *debuggerX = const_cast< OsiRowCutDebugger * >(solver_->getRowCutDebuggerAlways()); + OsiRowCutDebugger *debuggerX = + const_cast(solver_->getRowCutDebuggerAlways()); const OsiRowCutDebugger *debugger = solver_->getRowCutDebugger(); if (!debugger) { // infeasible!! @@ -4553,13 +4694,13 @@ void CbcModel::branchAndBound(int doStatistics) int numberColumns = solver_->getNumCols(); for (int i = 0; i < numberColumns; i++) { if (solver_->isInteger(i)) { - if (solution[i] < lower[i] - 1.0e-6 || solution[i] > upper[i] + 1.0e-6) + if (solution[i] < lower[i] - 1.0e-6 || + solution[i] > upper[i] + 1.0e-6) printf("**** "); - printf("%d %g <= %g <= %g\n", - i, lower[i], solution[i], upper[i]); + printf("%d %g <= %g <= %g\n", i, lower[i], solution[i], upper[i]); } } - //abort(); + // abort(); } } { @@ -4595,7 +4736,8 @@ void CbcModel::branchAndBound(int doStatistics) #endif //#define REPORT_DYNAMIC 2 #if REPORT_DYNAMIC - if (numberNodes_ && !parentModel_ && (tree_->empty() || (numberNodes_ % 10000) == 0)) { + if (numberNodes_ && !parentModel_ && + (tree_->empty() || (numberNodes_ % 10000) == 0)) { // Get average up and down costs double averageUp = 0.0; double averageDown = 0.0; @@ -4617,10 +4759,12 @@ void CbcModel::branchAndBound(int doStatistics) int numberDown2 = 0; for (i = 0; i < numberObjects_; i++) { OsiObject *object = object_[i]; - CbcSimpleIntegerDynamicPseudoCost *dynamicObject = dynamic_cast< CbcSimpleIntegerDynamicPseudoCost * >(object); + CbcSimpleIntegerDynamicPseudoCost *dynamicObject = + dynamic_cast(object); if (dynamicObject) { numberInts++; - if (dynamicObject->numberTimesUp() || dynamicObject->numberTimesDown()) { + if (dynamicObject->numberTimesUp() || + dynamicObject->numberTimesDown()) { int nUp = 0; int nDown = 0; double up = 0.0; @@ -4670,31 +4814,35 @@ void CbcModel::branchAndBound(int doStatistics) #else { #endif - printf("col %d - never branched on\n", dynamicObject->columnNumber()); + printf("col %d - never branched on\n", + dynamicObject->columnNumber()); } #endif } } } if (numberUp) - averageUp /= static_cast< double >(numberUp); + averageUp /= static_cast(numberUp); else averageUp = 0.0; if (numberDown) - averageDown /= static_cast< double >(numberDown); + averageDown /= static_cast(numberDown); else averageDown = 0.0; - printf("Report for %d variables (%d never branched on) after %d nodes - total solves down %d up %d\n", - numberInts, neverBranched, numberNodes_, numberDown2, numberUp2); + printf("Report for %d variables (%d never branched on) after %d nodes - " + "total solves down %d up %d\n", + numberInts, neverBranched, numberNodes_, numberDown2, numberUp2); if ((neverBranchedDown || neverBranchedUp) && endOfSearch) printf("odd %d never branched down and %d never branched up\n", - neverBranchedDown, neverBranchedUp); - printf("down average %g times (%d infeasible) average increase %g min/max times (%d,%d)\n", - static_cast< double >(numberDown2) / numberDown, infeasibleTimesDown, averageDown, - minTimesDown, maxTimesDown); - printf("up average %g times (%d infeasible) average increase %g min/max times (%d,%d)\n", - static_cast< double >(numberUp2) / numberUp, infeasibleTimesUp, averageUp, - minTimesUp, maxTimesUp); + neverBranchedDown, neverBranchedUp); + printf("down average %g times (%d infeasible) average increase %g " + "min/max times (%d,%d)\n", + static_cast(numberDown2) / numberDown, infeasibleTimesDown, + averageDown, minTimesDown, maxTimesDown); + printf("up average %g times (%d infeasible) average increase %g min/max " + "times (%d,%d)\n", + static_cast(numberUp2) / numberUp, infeasibleTimesUp, + averageUp, minTimesUp, maxTimesUp); } #endif if (tree_->empty()) { @@ -4721,17 +4869,18 @@ void CbcModel::branchAndBound(int doStatistics) else nextCheckRestart = COIN_INT_MAX; #ifdef CBC_HAS_CLP - OsiClpSolverInterface *clpSolver - = dynamic_cast< OsiClpSolverInterface * >(solver_); + OsiClpSolverInterface *clpSolver = + dynamic_cast(solver_); if (clpSolver && ((specialOptions_ & 131072) == 0) && true) { ClpSimplex *simplex = clpSolver->getModelPtr(); int perturbation = simplex->perturbation(); #if CBC_USEFUL_PRINTING > 1 printf("Testing its n,s %d %d solves n,s %d %d - pert %d\n", - numberIterations_, saveNumberIterations, - numberSolves_, saveNumberSolves, perturbation); + numberIterations_, saveNumberIterations, numberSolves_, + saveNumberSolves, perturbation); #endif - if (perturbation == 50 && (numberIterations_ - saveNumberIterations) < 8 * (numberSolves_ - saveNumberSolves)) { + if (perturbation == 50 && (numberIterations_ - saveNumberIterations) < + 8 * (numberSolves_ - saveNumberSolves)) { // switch off perturbation simplex->setPerturbation(100); #if CBC_USEFUL_PRINTING > 1 @@ -4751,12 +4900,13 @@ void CbcModel::branchAndBound(int doStatistics) // adding increment back allows current best - tiny bit weaker checkCutoffForRestart = getCutoff() + getCutoffIncrement(); #if CBC_USEFUL_PRINTING > 1 - printf("after %d nodes, cutoff %g - looking\n", - numberNodes_, getCutoff()); + printf("after %d nodes, cutoff %g - looking\n", numberNodes_, + getCutoff()); #endif saveSolver->resolve(); double direction = saveSolver->getObjSense(); - double gap = checkCutoffForRestart - saveSolver->getObjValue() * direction; + double gap = + checkCutoffForRestart - saveSolver->getObjValue() * direction; double tolerance; saveSolver->getDblParam(OsiDualTolerance, tolerance); if (gap <= 0.0) @@ -4778,19 +4928,22 @@ void CbcModel::branchAndBound(int doStatistics) int iColumn = integerVariable_[i]; double djValue = direction * reducedCost[iColumn]; if (upper[iColumn] - lower[iColumn] > integerTolerance) { - if (solution[iColumn] < lower[iColumn] + integerTolerance && djValue > gap) { - //printf("%d to lb on dj of %g - bounds %g %g\n", + if (solution[iColumn] < lower[iColumn] + integerTolerance && + djValue > gap) { + // printf("%d to lb on dj of %g - bounds %g %g\n", // iColumn,djValue,lower[iColumn],upper[iColumn]); saveSolver->setColUpper(iColumn, lower[iColumn]); numberFixed++; - } else if (solution[iColumn] > upper[iColumn] - integerTolerance && -djValue > gap) { - //printf("%d to ub on dj of %g - bounds %g %g\n", + } else if (solution[iColumn] > + upper[iColumn] - integerTolerance && + -djValue > gap) { + // printf("%d to ub on dj of %g - bounds %g %g\n", // iColumn,djValue,lower[iColumn],upper[iColumn]); saveSolver->setColLower(iColumn, upper[iColumn]); numberFixed++; } } else { - //printf("%d has dj of %g - already fixed to %g\n", + // printf("%d has dj of %g - already fixed to %g\n", // iColumn,djValue,lower[iColumn]); numberFixed2++; } @@ -4821,29 +4974,30 @@ void CbcModel::branchAndBound(int doStatistics) } } printf("Restart could fix %d integers (%d already fixed)\n", - numberFixed + numberFixed2, numberFixed2); + numberFixed + numberFixed2, numberFixed2); #endif numberFixed += numberFixed2; - if (numberFixed * 10 < numberColumns && numberFixed * 4 < numberIntegers_) + if (numberFixed * 10 < numberColumns && + numberFixed * 4 < numberIntegers_) + tryNewSearch = false; + } + // check for odd cuts + { + int iGenerator; + for (iGenerator = 0; iGenerator < numberCutGenerators_; + iGenerator++) { + CglCutGenerator *generator = generator_[iGenerator]->generator(); + + if (generator->needsOriginalModel()) + break; + } + if (iGenerator < numberCutGenerators_) tryNewSearch = false; } - // check for odd cuts - { - int iGenerator; - for (iGenerator = 0; iGenerator < numberCutGenerators_; iGenerator++) { - CglCutGenerator *generator = - generator_[iGenerator]->generator(); - - if (generator->needsOriginalModel()) - break; - } - if (iGenerator < numberCutGenerators_) - tryNewSearch=false; - } #ifdef CONFLICT_CUTS // temporary - //if ((moreSpecialOptions_&4194304)!=0) - //tryNewSearch=false; + // if ((moreSpecialOptions_&4194304)!=0) + // tryNewSearch=false; #endif if (tryNewSearch) { // back to solver without cuts? @@ -4873,12 +5027,11 @@ void CbcModel::branchAndBound(int doStatistics) #ifdef COIN_DEVELOP if (continuousSolver_->getNumRows() < solver_->getNumRows()) printf("%d rows added ZZZZZ\n", - solver_->getNumRows() - continuousSolver_->getNumRows()); + solver_->getNumRows() - continuousSolver_->getNumRows()); #endif - int returnCode = heuristic.smallBranchAndBound(saveSolver, - -1, newSolution, - objectiveValue, - checkCutoffForRestart, "Reduce"); + int returnCode = heuristic.smallBranchAndBound( + saveSolver, -1, newSolution, objectiveValue, + checkCutoffForRestart, "Reduce"); if (returnCode < 0) { #ifdef COIN_DEVELOP printf("Restart - not small enough to do search after fixing\n"); @@ -4902,7 +5055,7 @@ void CbcModel::branchAndBound(int doStatistics) lockThread(); double dummyBest; tree_->cleanTree(this, -COIN_DBL_MAX, dummyBest); - //unlockThread(); + // unlockThread(); } } else { double dummyBest; @@ -4925,25 +5078,28 @@ void CbcModel::branchAndBound(int doStatistics) saveSolver = NULL; } } - /* Check for abort on limits: node count, solution count, time, integrality gap. */ + /* Check for abort on limits: node count, solution count, time, integrality + * gap. */ if (stoppingCriterionReached()) break; #ifdef BONMIN - assert(!solverCharacteristics_->solutionAddsCuts() || solverCharacteristics_->mipFeasible()); + assert(!solverCharacteristics_->solutionAddsCuts() || + solverCharacteristics_->mipFeasible()); #endif -// Sets percentage of time when we try diving. Diving requires a bit of heap reorganisation, because -// we need to replace the comparison function to dive, and that requires reordering to retain the -// heap property. +// Sets percentage of time when we try diving. Diving requires a bit of heap +// reorganisation, because we need to replace the comparison function to dive, +// and that requires reordering to retain the heap property. #define DIVE_WHEN 1000 #define DIVE_STOP 2000 int kNode = numberNodes_ % 4000; if (numberNodes_ < 100000 && kNode > DIVE_WHEN && kNode <= DIVE_STOP) { if (!parallelMode()) { if (kNode == DIVE_WHEN + 1 || numberConsecutiveInfeasible > 1) { - CbcCompareDefault *compare = dynamic_cast< CbcCompareDefault * >(nodeCompare_); + CbcCompareDefault *compare = + dynamic_cast(nodeCompare_); // Don't interfere if user has replaced the compare function. if (compare) { - //printf("Redoing tree\n"); + // printf("Redoing tree\n"); compare->startDive(this); numberConsecutiveInfeasible = 0; } @@ -4992,7 +5148,8 @@ void CbcModel::branchAndBound(int doStatistics) if (newCutoff == -COIN_DBL_MAX) { COIN_DETAIL_PRINT(printf("Root analysis says finished\n")); } else if (n > numberFixedNow_) { - COIN_DETAIL_PRINT(printf("%d more fixed by analysis - now %d\n", n - numberFixedNow_, n)); + COIN_DETAIL_PRINT(printf("%d more fixed by analysis - now %d\n", + n - numberFixedNow_, n)); numberFixedNow_ = n; } } @@ -5009,7 +5166,9 @@ void CbcModel::branchAndBound(int doStatistics) call setComparison for the side effect of rebuilding the heap. */ tree_->cleanTree(this, newCutoff, bestPossibleObjective_); - if (nodeCompare_->newSolution(this) || nodeCompare_->newSolution(this, continuousObjective_, continuousInfeasibilities_)) { + if (nodeCompare_->newSolution(this) || + nodeCompare_->newSolution(this, continuousObjective_, + continuousInfeasibilities_)) { tree_->setComparison(*nodeCompare_); } if (tree_->empty()) { @@ -5030,19 +5189,19 @@ void CbcModel::branchAndBound(int doStatistics) // See if we want dantzig row choice goToDantzig(1000, savePivotMethod); #endif - if ((specialOptions_&2048)==0 || true) { - if (numberNodes_ < 100) - lastEvery1000 = numberNodes_ + 10; - else if (numberNodes_ < 1000) - lastEvery1000 = numberNodes_ + 100; - else if (numberNodes_ < 2000) - lastEvery1000 = numberNodes_ + 200; - else if (numberNodes_ < 4000) - lastEvery1000 = numberNodes_ + 500; - else - lastEvery1000 = numberNodes_ + 1000; + if ((specialOptions_ & 2048) == 0 || true) { + if (numberNodes_ < 100) + lastEvery1000 = numberNodes_ + 10; + else if (numberNodes_ < 1000) + lastEvery1000 = numberNodes_ + 100; + else if (numberNodes_ < 2000) + lastEvery1000 = numberNodes_ + 200; + else if (numberNodes_ < 4000) + lastEvery1000 = numberNodes_ + 500; + else + lastEvery1000 = numberNodes_ + 1000; } else { - lastEvery1000 = numberNodes_ + 1000; + lastEvery1000 = numberNodes_ + 1000; } bool redoTree = nodeCompare_->every1000Nodes(this, numberNodes_); #ifdef CHECK_CUT_SIZE @@ -5054,9 +5213,10 @@ void CbcModel::branchAndBound(int doStatistics) unlockThread(); } // Had hotstart before, now switched off - if (saveCompare && (!hotstartSolution_ || getCutoff()setComparison(*nodeCompare_); unlockThread(); } - if (numberNodes_ >= lastPrintEvery && CoinWallclockTime()-lastSecPrintProgress_ > secsPrintFrequency_) { + if (numberNodes_ >= lastPrintEvery && + CoinWallclockTime() - lastSecPrintProgress_ > secsPrintFrequency_) { lastPrintEvery = numberNodes_ + printFrequency_; lockThread(); int nNodes = tree_->size(); - //MODIF PIERRE + // MODIF PIERRE bestPossibleObjective_ = tree_->getBestPossibleObjective(); #ifdef CBC_THREAD if (parallelMode() > 0 && master_) { @@ -5092,10 +5253,13 @@ void CbcModel::branchAndBound(int doStatistics) unlockThread(); #if CBC_USEFUL_PRINTING > 1 if (getCutoff() < 1.0e20) { - if (fabs(getCutoff() - (bestObjective_ - getCutoffIncrement())) > 1.0e-6 && !parentModel_) + if (fabs(getCutoff() - (bestObjective_ - getCutoffIncrement())) > + 1.0e-6 && + !parentModel_) printf("model cutoff in status %g, best %g, increment %g\n", - getCutoff(), bestObjective_, getCutoffIncrement()); - assert(getCutoff() < bestObjective_ - getCutoffIncrement() + 1.0e-6 + 1.0e-10 * fabs(bestObjective_)); + getCutoff(), bestObjective_, getCutoffIncrement()); + assert(getCutoff() < bestObjective_ - getCutoffIncrement() + 1.0e-6 + + 1.0e-10 * fabs(bestObjective_)); } #endif if (!intParam_[CbcPrinting]) { @@ -5105,29 +5269,26 @@ void CbcModel::branchAndBound(int doStatistics) else lastBestPossibleObjective = bestPossibleObjective_; messageHandler()->message(CBC_STATUS, messages()) - << numberNodes_ << CoinMax(nNodes, 1) << bestObjective_ << bestPossibleObjective_ - << getCurrentSeconds() - << CoinMessageEol; + << numberNodes_ << CoinMax(nNodes, 1) << bestObjective_ + << bestPossibleObjective_ << getCurrentSeconds() << CoinMessageEol; } else if (intParam_[CbcPrinting] == 1) { messageHandler()->message(CBC_STATUS2, messages()) - << numberNodes_ << nNodes << bestObjective_ << bestPossibleObjective_ - << tree_->lastDepth() << tree_->lastUnsatisfied() - << tree_->lastObjective() << numberIterations_ - << getCurrentSeconds() - << CoinMessageEol; + << numberNodes_ << nNodes << bestObjective_ + << bestPossibleObjective_ << tree_->lastDepth() + << tree_->lastUnsatisfied() << tree_->lastObjective() + << numberIterations_ << getCurrentSeconds() << CoinMessageEol; } else if (!numberExtraIterations_) { messageHandler()->message(CBC_STATUS2, messages()) - << numberNodes_ << nNodes << bestObjective_ << bestPossibleObjective_ - << tree_->lastDepth() << tree_->lastUnsatisfied() << numberIterations_ - << getCurrentSeconds() - << CoinMessageEol; + << numberNodes_ << nNodes << bestObjective_ + << bestPossibleObjective_ << tree_->lastDepth() + << tree_->lastUnsatisfied() << numberIterations_ + << getCurrentSeconds() << CoinMessageEol; } else { messageHandler()->message(CBC_STATUS3, messages()) - << numberNodes_ << numberFathoms_ << numberExtraNodes_ << nNodes - << bestObjective_ << bestPossibleObjective_ - << tree_->lastDepth() << tree_->lastUnsatisfied() << numberIterations_ << numberExtraIterations_ - << getCurrentSeconds() - << CoinMessageEol; + << numberNodes_ << numberFathoms_ << numberExtraNodes_ << nNodes + << bestObjective_ << bestPossibleObjective_ << tree_->lastDepth() + << tree_->lastUnsatisfied() << numberIterations_ + << numberExtraIterations_ << getCurrentSeconds() << CoinMessageEol; } #ifdef CBC_HAS_NAUTY if (symmetryInfo_) @@ -5137,8 +5298,8 @@ void CbcModel::branchAndBound(int doStatistics) if (numberConflictCuts > lastNumberConflictCuts) { double length = lengthConflictCuts / numberConflictCuts; printf("%d new conflict cuts - total %d - average length %g\n", - numberConflictCuts - lastNumberConflictCuts, - numberConflictCuts, length); + numberConflictCuts - lastNumberConflictCuts, numberConflictCuts, + length); lastNumberConflictCuts = numberConflictCuts; } #endif @@ -5159,29 +5320,30 @@ void CbcModel::branchAndBound(int doStatistics) verifyCutCounts(tree_, *this); #endif /* - Now we come to the meat of the loop. To create the active subproblem, we'll - pop the most promising node in the live set, rebuild the subproblem it - represents, and then execute the current arm of the branch to create the - active subproblem. + Now we come to the meat of the loop. To create the active subproblem, + we'll pop the most promising node in the live set, rebuild the subproblem + it represents, and then execute the current arm of the branch to create + the active subproblem. */ CbcNode *node = NULL; #ifdef CBC_THREAD if (!parallelMode() || parallelMode() == -1) { #endif -#ifdef CBC_EXPERIMENT7 - int multiplier = (moreSpecialOptions_>>3)&31; - if (tree_->size()<16*multiplier&&numberNodes_>-100 && (specialOptions_&2048)==0) { +#ifdef CBC_EXPERIMENT_JJF + int multiplier = (moreSpecialOptions_ >> 3) & 31; + if (tree_->size() < 16 * multiplier && numberNodes_ > -100 && + (specialOptions_ & 2048) == 0) { // create breadth first comparison - //printf("breadth as tree size %d\n",tree_->size()); + // printf("breadth as tree size %d\n",tree_->size()); CbcCompareObjective breadth; tree_->setComparison(breadth); - node = tree_->bestNode(cutoff); + node = tree_->bestNode(cutoff); tree_->setComparison(*nodeCompare_); } else { - node = tree_->bestNode(cutoff); + node = tree_->bestNode(cutoff); } #else - node = tree_->bestNode(cutoff); + node = tree_->bestNode(cutoff); #endif // Possible one on tree worse than cutoff // Weird comparison function can leave ineligible nodes on tree @@ -5192,29 +5354,29 @@ void CbcModel::branchAndBound(int doStatistics) #ifdef JJF_ZERO if (node) { if (createdNode) { - printf("Node %d depth %d, created %d depth %d\n", - node->nodeNumber(), node->depth(), - createdNode->nodeNumber(), createdNode->depth()); + printf("Node %d depth %d, created %d depth %d\n", node->nodeNumber(), + node->depth(), createdNode->nodeNumber(), + createdNode->depth()); } else { - printf("Node %d depth %d, no created node\n", - node->nodeNumber(), node->depth()); + printf("Node %d depth %d, no created node\n", node->nodeNumber(), + node->depth()); } } else if (createdNode) { printf("Node exhausted, created %d depth %d\n", - createdNode->nodeNumber(), createdNode->depth()); + createdNode->nodeNumber(), createdNode->depth()); } else { printf("Node exhausted, no created node\n"); numberConsecutiveInfeasible = 2; } #endif - //if (createdNode) - //numberConsecutiveInfeasible=0; - //else - //numberConsecutiveInfeasible++; + // if (createdNode) + // numberConsecutiveInfeasible=0; + // else + // numberConsecutiveInfeasible++; #ifdef CBC_THREAD } else if (parallelMode() > 0) { - //lockThread(); - //node = tree_->bestNode(cutoff) ; + // lockThread(); + // node = tree_->bestNode(cutoff) ; // Possible one on tree worse than cutoff if (true || !node || node->objectiveValue() > cutoff) { assert(master_); @@ -5228,14 +5390,15 @@ void CbcModel::branchAndBound(int doStatistics) } } } - //unlockThread(); + // unlockThread(); } else { // Deterministic parallel - if ((tree_->size() < CoinMax(numberThreads_, 8) || hotstartSolution_) && !goneParallel) { + if ((tree_->size() < CoinMax(numberThreads_, 8) || hotstartSolution_) && + !goneParallel) { node = tree_->bestNode(cutoff); #ifdef SAVE_NODE_INFO - // Save parent node (for user) - parentNode_ = node; + // Save parent node (for user) + parentNode_ = node; #endif // Possible one on tree worse than cutoff if (!node || node->objectiveValue() > cutoff) @@ -5270,9 +5433,9 @@ void CbcModel::branchAndBound(int doStatistics) } if (nDeleteNode >= MAX_DEL_NODE) { for (int i = 0; i < nDeleteNode; i++) { - //printf("trying to del %d %x\n",i,delNode[i]); + // printf("trying to del %d %x\n",i,delNode[i]); delete delNode[i]; - //printf("done to del %d %x\n",i,delNode[i]); + // printf("done to del %d %x\n",i,delNode[i]); } nDeleteNode = 0; } @@ -5295,15 +5458,15 @@ void CbcModel::branchAndBound(int doStatistics) master_->stopThreads(-1); master_->waitForThreadsInTree(2); // adjust time to allow for children on some systems - //dblParam_[CbcStartSeconds] -= CoinCpuTimeJustChildren(); + // dblParam_[CbcStartSeconds] -= CoinCpuTimeJustChildren(); } #endif /* End of the non-abort actions. The next block of code is executed if we've - aborted because we hit one of the limits. Clean up by deleting the live set - and break out of the node processing loop. Note that on an abort, node may - have been pushed back onto the tree for further processing, in which case - it'll be deleted in cleanTree. We need to check. + aborted because we hit one of the limits. Clean up by deleting the live + set and break out of the node processing loop. Note that on an abort, node + may have been pushed back onto the tree for further processing, in which + case it'll be deleted in cleanTree. We need to check. */ if (stoppingCriterionReached()) { if (tree_->size()) { @@ -5324,17 +5487,17 @@ void CbcModel::branchAndBound(int doStatistics) } delete nextRowCut_; /* order is important here: - * maximumSecondsReached() should be checked before eventHappened_ and - * isNodeLimitReached() should be checked after eventHappened_ - * reason is, that at timelimit, eventHappened_ is set to true to make Cbc stop fast - * and if Ctrl+C is hit, then the nodelimit is set to -1 to make Cbc stop - */ + * maximumSecondsReached() should be checked before eventHappened_ and + * isNodeLimitReached() should be checked after eventHappened_ + * reason is, that at timelimit, eventHappened_ is set to true to make Cbc + * stop fast and if Ctrl+C is hit, then the nodelimit is set to -1 to make + * Cbc stop + */ if (stoppedOnGap_) { messageHandler()->message(CBC_GAP, messages()) - << bestObjective_ - bestPossibleObjective_ - << dblParam_[CbcAllowableGap] - << dblParam_[CbcAllowableFractionGap] * 100.0 - << CoinMessageEol; + << bestObjective_ - bestPossibleObjective_ + << dblParam_[CbcAllowableGap] + << dblParam_[CbcAllowableFractionGap] * 100.0 << CoinMessageEol; secondaryStatus_ = 2; status_ = 0; } else if (maximumSecondsReached()) { @@ -5349,7 +5512,8 @@ void CbcModel::branchAndBound(int doStatistics) handler_->message(CBC_MAXNODES, messages_) << CoinMessageEol; secondaryStatus_ = 3; status_ = 1; - } else if (maximumNumberIterations_ >= 0 && numberIterations_ >= maximumNumberIterations_) { + } else if (maximumNumberIterations_ >= 0 && + numberIterations_ >= maximumNumberIterations_) { handler_->message(CBC_MAXITERS, messages_) << CoinMessageEol; secondaryStatus_ = 8; status_ = 1; @@ -5375,8 +5539,8 @@ void CbcModel::branchAndBound(int doStatistics) } #endif /* - That's it, we've exhausted the search tree, or broken out of the loop because - we hit some limit on evaluation. + That's it, we've exhausted the search tree, or broken out of the loop + because we hit some limit on evaluation. We may have got an intelligent tree so give it one more chance */ @@ -5392,21 +5556,20 @@ void CbcModel::branchAndBound(int doStatistics) eventHandler->event(CbcEventHandler::endSearch); } #ifdef CBC_HAS_NAUTY - if (rootSymmetryInfo_) - rootSymmetryInfo_->statsOrbits(this, 2); + if (rootSymmetryInfo_) + rootSymmetryInfo_->statsOrbits(this, 2); #endif if (!status_) { // Set best possible unless stopped on gap if (secondaryStatus_ != 2) bestPossibleObjective_ = bestObjective_; handler_->message(CBC_END_GOOD, messages_) - << bestObjective_ << numberIterations_ << numberNodes_ << getCurrentSeconds() - << CoinMessageEol; + << bestObjective_ << numberIterations_ << numberNodes_ + << getCurrentSeconds() << CoinMessageEol; } else { handler_->message(CBC_END, messages_) - << bestObjective_ << bestPossibleObjective_ - << numberIterations_ << numberNodes_ << getCurrentSeconds() - << CoinMessageEol; + << bestObjective_ << bestPossibleObjective_ << numberIterations_ + << numberNodes_ << getCurrentSeconds() << CoinMessageEol; } if ((moreSpecialOptions_ & 4194304) != 0) { // Conflict cuts @@ -5424,25 +5587,22 @@ void CbcModel::branchAndBound(int doStatistics) sizeConflict /= nConflict; char general[200]; sprintf(general, "%d conflict cuts generated - average length %g", - nConflict, sizeConflict); - messageHandler()->message(CBC_GENERAL, - messages()) - << general << CoinMessageEol; + nConflict, sizeConflict); + messageHandler()->message(CBC_GENERAL, messages()) + << general << CoinMessageEol; } } if (numberStrongIterations_) handler_->message(CBC_STRONG_STATS, messages_) - << strongInfo_[0] << numberStrongIterations_ << strongInfo_[2] - << strongInfo_[1] << CoinMessageEol; + << strongInfo_[0] << numberStrongIterations_ << strongInfo_[2] + << strongInfo_[1] << CoinMessageEol; if (!numberExtraNodes_) handler_->message(CBC_OTHER_STATS, messages_) - << maximumDepthActual_ - << numberDJFixed_ << CoinMessageEol; + << maximumDepthActual_ << numberDJFixed_ << CoinMessageEol; else handler_->message(CBC_OTHER_STATS2, messages_) - << maximumDepthActual_ - << numberDJFixed_ << numberFathoms_ << numberExtraNodes_ << numberExtraIterations_ - << CoinMessageEol; + << maximumDepthActual_ << numberDJFixed_ << numberFathoms_ + << numberExtraNodes_ << numberExtraIterations_ << CoinMessageEol; #ifdef CBC_HAS_NAUTY if (symmetryInfo_) symmetryInfo_->statsOrbits(this, 1); @@ -5451,7 +5611,8 @@ void CbcModel::branchAndBound(int doStatistics) #endif if (doStatistics == 100) { for (int i = 0; i < numberObjects_; i++) { - CbcSimpleIntegerDynamicPseudoCost *obj = dynamic_cast< CbcSimpleIntegerDynamicPseudoCost * >(object_[i]); + CbcSimpleIntegerDynamicPseudoCost *obj = + dynamic_cast(object_[i]); if (obj) obj->print(); } @@ -5462,7 +5623,7 @@ void CbcModel::branchAndBound(int doStatistics) int i; for (i = 0; i < numberObjects_; i++) lookup[i] = -1; - bool goodIds = false; //true; + bool goodIds = false; // true; for (i = 0; i < numberObjects_; i++) { int iColumn = object_[i]->columnNumber(); if (iColumn >= 0 && iColumn < numberColumns) { @@ -5482,7 +5643,8 @@ void CbcModel::branchAndBound(int doStatistics) lookup = NULL; } if (doStatistics >= 3) { - printf(" node parent depth column value obj inf\n"); + printf(" node parent depth column value obj " + "inf\n"); for (i = 0; i < numberNodes2_; i++) { statistics_[i]->print(lookup); } @@ -5491,7 +5653,8 @@ void CbcModel::branchAndBound(int doStatistics) // Find last solution int k; for (k = numberNodes2_ - 1; k >= 0; k--) { - if (statistics_[k]->endingObjective() != COIN_DBL_MAX && !statistics_[k]->endingInfeasibility()) + if (statistics_[k]->endingObjective() != COIN_DBL_MAX && + !statistics_[k]->endingInfeasibility()) break; } if (k >= 0) { @@ -5501,7 +5664,8 @@ void CbcModel::branchAndBound(int doStatistics) which[i] = k; k = statistics_[k]->parentNode(); } - printf(" node parent depth column value obj inf\n"); + printf(" node parent depth column value obj " + "inf\n"); for (i = 0; i <= depth; i++) { statistics_[which[i]]->print(lookup); } @@ -5576,42 +5740,48 @@ void CbcModel::branchAndBound(int doStatistics) } // Now print if (numberSolutions) - averageSolutionDepth /= static_cast< double >(numberSolutions); + averageSolutionDepth /= static_cast(numberSolutions); int numberSolved = numberNodes2_ - numberCutoff; - double averageNumberIterations2 = numberIterations_ - averageNumberIterations1 - - numberIterationsAtContinuous; + double averageNumberIterations2 = numberIterations_ - + averageNumberIterations1 - + numberIterationsAtContinuous; if (numberCutoff) { - averageCutoffDepth /= static_cast< double >(numberCutoff); - averageNumberIterations2 /= static_cast< double >(numberCutoff); + averageCutoffDepth /= static_cast(numberCutoff); + averageNumberIterations2 /= static_cast(numberCutoff); } if (numberNodes2_) - averageValue /= static_cast< double >(numberNodes2_); + averageValue /= static_cast(numberNodes2_); if (numberSolved) { - averageNumberIterations1 /= static_cast< double >(numberSolved); - averageSolvedDepth /= static_cast< double >(numberSolved); + averageNumberIterations1 /= static_cast(numberSolved); + averageSolvedDepth /= static_cast(numberSolved); } - printf("%d solution(s) were found (by branching) at an average depth of %g\n", - numberSolutions, averageSolutionDepth); + printf( + "%d solution(s) were found (by branching) at an average depth of %g\n", + numberSolutions, averageSolutionDepth); printf("average value of variable being branched on was %g\n", - averageValue); - printf("%d nodes were cutoff at an average depth of %g with iteration count of %g\n", - numberCutoff, averageCutoffDepth, averageNumberIterations2); - printf("%d nodes were solved at an average depth of %g with iteration count of %g\n", - numberSolved, averageSolvedDepth, averageNumberIterations1); + averageValue); + printf("%d nodes were cutoff at an average depth of %g with iteration " + "count of %g\n", + numberCutoff, averageCutoffDepth, averageNumberIterations2); + printf("%d nodes were solved at an average depth of %g with iteration " + "count of %g\n", + numberSolved, averageSolvedDepth, averageNumberIterations1); if (numberDown) { - averageInfDown /= static_cast< double >(numberDown); - averageObjDown /= static_cast< double >(numberDown); + averageInfDown /= static_cast(numberDown); + averageObjDown /= static_cast(numberDown); } - printf("Down %d nodes (%d first, %d second) - %d cutoff, rest decrease numinf %g increase obj %g\n", - numberDown, numberFirstDown, numberDown - numberFirstDown, numberCutoffDown, - averageInfDown, averageObjDown); + printf("Down %d nodes (%d first, %d second) - %d cutoff, rest decrease " + "numinf %g increase obj %g\n", + numberDown, numberFirstDown, numberDown - numberFirstDown, + numberCutoffDown, averageInfDown, averageObjDown); if (numberUp) { - averageInfUp /= static_cast< double >(numberUp); - averageObjUp /= static_cast< double >(numberUp); + averageInfUp /= static_cast(numberUp); + averageObjUp /= static_cast(numberUp); } - printf("Up %d nodes (%d first, %d second) - %d cutoff, rest decrease numinf %g increase obj %g\n", - numberUp, numberFirstUp, numberUp - numberFirstUp, numberCutoffUp, - averageInfUp, averageObjUp); + printf("Up %d nodes (%d first, %d second) - %d cutoff, rest decrease " + "numinf %g increase obj %g\n", + numberUp, numberFirstUp, numberUp - numberFirstUp, numberCutoffUp, + averageInfUp, averageObjUp); for (i = 0; i < numberNodes2_; i++) delete statistics_[i]; delete[] statistics_; @@ -5636,7 +5806,10 @@ void CbcModel::branchAndBound(int doStatistics) Don't replace if we are trying to save cuts */ - if (bestSolution_ && (solverCharacteristics_->solverType() < 2 || solverCharacteristics_->solverType() == 4) && ((specialOptions_ & 8388608) == 0 || (specialOptions_ & 2048) != 0)) { + if (bestSolution_ && + (solverCharacteristics_->solverType() < 2 || + solverCharacteristics_->solverType() == 4) && + ((specialOptions_ & 8388608) == 0 || (specialOptions_ & 2048) != 0)) { setCutoff(1.0e50); // As best solution should be worse than cutoff // change cutoff as constraint if wanted if (cutoffRowNumber_ >= 0) { @@ -5652,19 +5825,20 @@ void CbcModel::branchAndBound(int doStatistics) phase_ = 5; double increment = getDblParam(CbcModel::CbcCutoffIncrement); if ((specialOptions_ & 4) == 0) - bestObjective_ += 100.0 * increment + 1.0e-3; // only set if we are going to solve + bestObjective_ += + 100.0 * increment + 1.0e-3; // only set if we are going to solve // if lazy constraints need solver with constraints if (atSolutionSolver_) { delete solver_; solver_ = atSolutionSolver_; solverCharacteristics_ = - dynamic_cast< OsiBabSolver * >(solver_->getAuxiliaryInfo()); + dynamic_cast(solver_->getAuxiliaryInfo()); delete continuousSolver_; continuousSolver_ = solver_->clone(); atSolutionSolver_ = NULL; } // was not a good idea to set max time on solvers anyway -#if 0 //def CBC_HAS_CLP +#if 0 // def CBC_HAS_CLP OsiClpSolverInterface *clpSolver = dynamic_cast< OsiClpSolverInterface * >(solver_); // Reset max time on solvers if possibility of stopping @@ -5719,7 +5893,7 @@ void CbcModel::branchAndBound(int doStatistics) lastCut_ = NULL; delete[] addedCuts_; addedCuts_ = NULL; - //delete persistentInfo; + // delete persistentInfo; // Get rid of characteristics solverCharacteristics_ = NULL; if (continuousSolver_) { @@ -5729,7 +5903,8 @@ void CbcModel::branchAndBound(int doStatistics) /* Destroy global cuts by replacing with an empty OsiCuts object. */ - globalCuts_ = CbcRowCuts(); + if ((moreSpecialOptions2_&16777216)==0) + globalCuts_ = CbcRowCuts(); delete globalConflictCuts_; globalConflictCuts_ = NULL; if (!bestSolution_ && (specialOptions_ & 8388608) == 0 && false) { @@ -5745,8 +5920,8 @@ void CbcModel::branchAndBound(int doStatistics) } #ifdef CBC_HAS_CLP { - OsiClpSolverInterface *clpSolver - = dynamic_cast< OsiClpSolverInterface * >(solver_); + OsiClpSolverInterface *clpSolver = + dynamic_cast(solver_); if (clpSolver) { // Possible restore of pivot method if (savePivotMethod) { @@ -5759,8 +5934,8 @@ void CbcModel::branchAndBound(int doStatistics) } } #endif - if ((fastNodeDepth_ >= 1000000 || (moreSpecialOptions_ & 33554432) != 0) - && !parentModel_) { + if ((fastNodeDepth_ >= 1000000 || (moreSpecialOptions_ & 33554432) != 0) && + (specialOptions_&2048) == 0) { // delete object off end delete object_[numberObjects_]; if ((moreSpecialOptions_ & 33554432) == 0) @@ -5813,10 +5988,10 @@ void CbcModel::branchAndBound(int doStatistics) flipModel(); #ifdef CBC_HAS_CLP { - OsiClpSolverInterface *clpSolver - = dynamic_cast< OsiClpSolverInterface * >(solver_); + OsiClpSolverInterface *clpSolver = + dynamic_cast(solver_); if (clpSolver) - clpSolver->setFakeObjective(static_cast< double * >(NULL)); + clpSolver->setFakeObjective(reinterpret_cast(NULL)); } #endif moreSpecialOptions_ = saveMoreSpecialOptions; @@ -5824,29 +5999,30 @@ void CbcModel::branchAndBound(int doStatistics) } // Solve the initial LP relaxation -void CbcModel::initialSolve() -{ +void CbcModel::initialSolve() { assert(solver_); // Double check optimization directions line up dblParam_[CbcOptimizationDirection] = solver_->getObjSense(); // Check if bounds are all integral (as may get messed up later) checkModel(); if (!solverCharacteristics_) { - OsiBabSolver *solverCharacteristics = dynamic_cast< OsiBabSolver * >(solver_->getAuxiliaryInfo()); + OsiBabSolver *solverCharacteristics = + dynamic_cast(solver_->getAuxiliaryInfo()); if (solverCharacteristics) { solverCharacteristics_ = solverCharacteristics; } else { // replace in solver OsiBabSolver defaultC; solver_->setAuxiliaryInfo(&defaultC); - solverCharacteristics_ = dynamic_cast< OsiBabSolver * >(solver_->getAuxiliaryInfo()); + solverCharacteristics_ = + dynamic_cast(solver_->getAuxiliaryInfo()); } } solverCharacteristics_->setSolver(solver_); solver_->setHintParam(OsiDoInBranchAndCut, true, OsiHintDo, NULL); // doesn't seem to be uniform time limit // NOT a good idea as can stop in cleanup -#if 0 //def CBC_HAS_CLP +#if 0 // def CBC_HAS_CLP OsiClpSolverInterface *clpSolver = dynamic_cast< OsiClpSolverInterface * >(solver_); if (clpSolver) { @@ -5864,13 +6040,14 @@ void CbcModel::initialSolve() // But set up so Jon Lee will be happy status_ = -1; secondaryStatus_ = -1; - originalContinuousObjective_ = solver_->getObjValue() * solver_->getObjSense(); + originalContinuousObjective_ = + solver_->getObjValue() * solver_->getObjSense(); bestPossibleObjective_ = originalContinuousObjective_; if (solver_->isProvenDualInfeasible()) originalContinuousObjective_ = -COIN_DBL_MAX; delete[] continuousSolution_; - continuousSolution_ = CoinCopyOfArray(solver_->getColSolution(), - solver_->getNumCols()); + continuousSolution_ = + CoinCopyOfArray(solver_->getColSolution(), solver_->getNumCols()); setPointers(solver_); solverCharacteristics_ = NULL; } @@ -5893,22 +6070,23 @@ CoinWarmStartBasis *CbcModel::getEmptyBasis(int ns, int na) const */ if (emptyWarmStart_ == 0) { if (solver_ == 0) { - throw CoinError("Cannot construct basis without solver!", - "getEmptyBasis", "CbcModel"); + throw CoinError("Cannot construct basis without solver!", "getEmptyBasis", + "CbcModel"); } - emptyBasis = dynamic_cast< CoinWarmStartBasis * >(solver_->getEmptyWarmStart()); + emptyBasis = + dynamic_cast(solver_->getEmptyWarmStart()); if (emptyBasis == 0) { throw CoinError( - "Solver does not appear to use a basis-oriented warm start.", - "getEmptyBasis", "CbcModel"); + "Solver does not appear to use a basis-oriented warm start.", + "getEmptyBasis", "CbcModel"); } emptyBasis->setSize(0, 0); - emptyWarmStart_ = dynamic_cast< CoinWarmStart * >(emptyBasis); + emptyWarmStart_ = dynamic_cast(emptyBasis); } /* Clone the empty basis object, resize it as requested, and return. */ - emptyBasis = dynamic_cast< CoinWarmStartBasis * >(emptyWarmStart_->clone()); + emptyBasis = dynamic_cast(emptyWarmStart_->clone()); assert(emptyBasis); if (ns != 0 || na != 0) emptyBasis->setSize(ns, na); @@ -5922,155 +6100,72 @@ CoinWarmStartBasis *CbcModel::getEmptyBasis(int ns, int na) const */ CbcModel::CbcModel() - : solver_(NULL) - , ownership_(0x80000000) - , continuousSolver_(NULL) - , referenceSolver_(NULL) - , atSolutionSolver_(NULL) - , defaultHandler_(true) - , emptyWarmStart_(NULL) - , bestObjective_(COIN_DBL_MAX) - , bestPossibleObjective_(COIN_DBL_MAX) - , sumChangeObjective1_(0.0) - , sumChangeObjective2_(0.0) - , bestSolution_(NULL) - , savedSolutions_(NULL) - , currentSolution_(NULL) - , testSolution_(NULL) - , globalConflictCuts_(NULL) - , minimumDrop_(1.0e-7) - , numberSolutions_(0) - , numberSavedSolutions_(0) - , maximumSavedSolutions_(0) - , stateOfSearch_(0) - , whenCuts_(-1) - , hotstartSolution_(NULL) - , hotstartPriorities_(NULL) - , numberHeuristicSolutions_(0) - , numberNodes_(0) - , lastNodeImprovingFeasSol_(-1) - , lastTimeImprovingFeasSol_(0) - , numberNodes2_(0) - , numberIterations_(0) - , numberSolves_(0) - , status_(-1) - , secondaryStatus_(-1) - , numberIntegers_(0) - , numberRowsAtContinuous_(0) - , cutoffRowNumber_(-1) - , maximumNumberCuts_(0) - , phase_(0) - , currentNumberCuts_(0) - , maximumDepth_(0) - , walkback_(NULL) - , preProcess_(NULL) - , lastNodeInfo_(NULL) - , lastCut_(NULL) - , lastDepth_(0) - , lastNumberCuts2_(0) - , maximumCuts_(0) - , lastNumberCuts_(NULL) - , addedCuts_(NULL) - , nextRowCut_(NULL) - , currentNode_(NULL) - , integerVariable_(NULL) - , integerInfo_(NULL) - , continuousSolution_(NULL) - , usedInSolution_(NULL) - , specialOptions_(0) - , moreSpecialOptions_(0) - , moreSpecialOptions2_(0) - , topOfTree_(NULL) - , subTreeModel_(NULL) - , heuristicModel_(NULL) - , numberStoppedSubTrees_(0) - , presolve_(0) - , numberStrong_(5) - , numberBeforeTrust_(10) - , numberPenalties_(20) - , stopNumberIterations_(-1) - , penaltyScaleFactor_(3.0) - , numberAnalyzeIterations_(0) - , analyzeResults_(NULL) - , numberInfeasibleNodes_(0) - , problemType_(0) - , printFrequency_(1) - , secsPrintFrequency_(1) - , lastSecPrintProgress_( 0.0 ) - , numberCutGenerators_(0) - , generator_(NULL) - , virginGenerator_(NULL) - , numberHeuristics_(0) - , heuristic_(NULL) - , lastHeuristic_(NULL) - , fastNodeDepth_(-1) - , eventHandler_(NULL) + : solver_(NULL), ownership_(0x80000000), continuousSolver_(NULL), + referenceSolver_(NULL), atSolutionSolver_(NULL), defaultHandler_(true), + emptyWarmStart_(NULL), bestObjective_(COIN_DBL_MAX), + bestPossibleObjective_(COIN_DBL_MAX), sumChangeObjective1_(0.0), + sumChangeObjective2_(0.0), bestSolution_(NULL), savedSolutions_(NULL), + currentSolution_(NULL), testSolution_(NULL), globalConflictCuts_(NULL), + minimumDrop_(1.0e-7), numberSolutions_(0), numberSavedSolutions_(0), + maximumSavedSolutions_(0), stateOfSearch_(0), whenCuts_(-1), + hotstartSolution_(NULL), hotstartPriorities_(NULL), + numberHeuristicSolutions_(0), numberNodes_(0), + lastNodeImprovingFeasSol_(-1), lastTimeImprovingFeasSol_(0), + numberNodes2_(0), numberIterations_(0), numberSolves_(0), status_(-1), + secondaryStatus_(-1), numberIntegers_(0), numberRowsAtContinuous_(0), + cutoffRowNumber_(-1), maximumNumberCuts_(0), phase_(0), + currentNumberCuts_(0), maximumDepth_(0), walkback_(NULL), + preProcess_(NULL), lastNodeInfo_(NULL), lastCut_(NULL), lastDepth_(0), + lastNumberCuts2_(0), maximumCuts_(0), lastNumberCuts_(NULL), + addedCuts_(NULL), nextRowCut_(NULL), currentNode_(NULL), + integerVariable_(NULL), integerInfo_(NULL), continuousSolution_(NULL), + usedInSolution_(NULL), specialOptions_(0), moreSpecialOptions_(0), + moreSpecialOptions2_(0), topOfTree_(NULL), subTreeModel_(NULL), + heuristicModel_(NULL), numberStoppedSubTrees_(0), presolve_(0), + numberStrong_(5), numberBeforeTrust_(10), numberPenalties_(20), + stopNumberIterations_(-1), penaltyScaleFactor_(3.0), + numberAnalyzeIterations_(0), analyzeResults_(NULL), + numberInfeasibleNodes_(0), problemType_(0), printFrequency_(1), + secsPrintFrequency_(1), lastSecPrintProgress_(0.0), + numberCutGenerators_(0), generator_(NULL), virginGenerator_(NULL), + numberHeuristics_(0), heuristic_(NULL), lastHeuristic_(NULL), + fastNodeDepth_(-1), eventHandler_(NULL) #ifdef CBC_HAS_NAUTY - , symmetryInfo_(NULL) - , rootSymmetryInfo_(NULL) -#endif - , numberObjects_(0) - , object_(NULL) - , ownObjects_(true) - , originalColumns_(NULL) - , howOftenGlobalScan_(3) - , numberGlobalViolations_(0) - , numberExtraIterations_(0) - , numberExtraNodes_(0) - , numberFathoms_(0) - , continuousObjective_(COIN_DBL_MAX) - , originalContinuousObjective_(COIN_DBL_MAX) - , continuousInfeasibilities_(COIN_INT_MAX) - , maximumCutPassesAtRoot_(20) - , maximumCutPasses_(10) - , preferredWay_(0) - , currentPassNumber_(0) - , maximumWhich_(INITIAL_MAXIMUM_WHICH) - , maximumRows_(0) - , randomSeed_(-1) - , multipleRootTries_(0) - , currentDepth_(0) - , whichGenerator_(NULL) - , maximumStatistics_(0) - , statistics_(NULL) - , maximumDepthActual_(0) - , numberDJFixed_(0.0) - , probingInfo_(NULL) - , numberFixedAtRoot_(0) - , numberFixedNow_(0) - , stoppedOnGap_(false) - , eventHappened_(false) - , numberLongStrong_(0) - , numberOldActiveCuts_(0) - , numberNewCuts_(0) - , searchStrategy_(-1) - , strongStrategy_(0) - , numberStrongIterations_(0) - , resolveAfterTakeOffCuts_(true) - , maximumNumberIterations_(-1) - , continuousPriority_(COIN_INT_MAX) - , numberUpdateItems_(0) - , maximumNumberUpdateItems_(0) - , updateItems_(NULL) - , storedRowCuts_(NULL) - , numberThreads_(0) - , threadMode_(0) - , numberGlobalCutsIn_(0) - , roundIntVars_(false) - , master_(NULL) - , masterThread_(NULL) -{ + , + symmetryInfo_(NULL), rootSymmetryInfo_(NULL) +#endif + , + numberObjects_(0), object_(NULL), ownObjects_(true), + originalColumns_(NULL), howOftenGlobalScan_(3), + numberGlobalViolations_(0), numberExtraIterations_(0), + numberExtraNodes_(0), numberFathoms_(0), + continuousObjective_(COIN_DBL_MAX), + originalContinuousObjective_(COIN_DBL_MAX), + continuousInfeasibilities_(COIN_INT_MAX), maximumCutPassesAtRoot_(20), + maximumCutPasses_(10), preferredWay_(0), currentPassNumber_(0), + maximumWhich_(INITIAL_MAXIMUM_WHICH), maximumRows_(0), randomSeed_(-1), + multipleRootTries_(0), currentDepth_(0), whichGenerator_(NULL), + maximumStatistics_(0), statistics_(NULL), maximumDepthActual_(0), + numberDJFixed_(0.0), probingInfo_(NULL), numberFixedAtRoot_(0), + numberFixedNow_(0), stoppedOnGap_(false), eventHappened_(false), + numberLongStrong_(0), numberOldActiveCuts_(0), numberNewCuts_(0), + searchStrategy_(-1), strongStrategy_(0), numberStrongIterations_(0), + resolveAfterTakeOffCuts_(true), maximumNumberIterations_(-1), + continuousPriority_(COIN_INT_MAX), numberUpdateItems_(0), + maximumNumberUpdateItems_(0), updateItems_(NULL), storedRowCuts_(NULL), + numberThreads_(0), threadMode_(0), numberGlobalCutsIn_(0), + roundIntVars_(false), master_(NULL), masterThread_(NULL) { memset(intParam_, 0, sizeof(intParam_)); intParam_[CbcMaxNumNode] = COIN_INT_MAX; - intParam_[CbcMaxNodesNotImprovingFeasSol] = COIN_INT_MAX; - intParam_[CbcMaxNumSol] = COIN_INT_MAX/2; + intParam_[CbcMaxNodesNotImproving] = COIN_INT_MAX; + intParam_[CbcMaxNumSol] = COIN_INT_MAX / 2; memset(dblParam_, 0, sizeof(dblParam_)); dblParam_[CbcIntegerTolerance] = 1e-6; dblParam_[CbcCutoffIncrement] = 1e-4; dblParam_[CbcAllowableGap] = 1.0e-10; dblParam_[CbcMaximumSeconds] = 1.0e100; - dblParam_[CbcMaximumSecondsNotImprovingFeasSol] = 1.0e100; + dblParam_[CbcMaxSecondsNotImproving] = 1.0e100; dblParam_[CbcCurrentCutoff] = 1.0e100; dblParam_[CbcOptimizationDirection] = 1.0; dblParam_[CbcCurrentObjectiveValue] = 1.0e100; @@ -6103,7 +6198,7 @@ CbcModel::CbcModel() handler_ = new CoinMessageHandler(); handler_->setLogLevel(2); messages_ = CbcMessage(); - //eventHandler_ = new CbcEventHandler() ; + // eventHandler_ = new CbcEventHandler() ; } /** Constructor from solver. @@ -6112,146 +6207,68 @@ CbcModel::CbcModel() */ CbcModel::CbcModel(const OsiSolverInterface &rhs) - : ownership_(0x80000000) - , continuousSolver_(NULL) - , referenceSolver_(NULL) - , atSolutionSolver_(NULL) - , defaultHandler_(true) - , emptyWarmStart_(NULL) - , bestObjective_(COIN_DBL_MAX) - , bestPossibleObjective_(COIN_DBL_MAX) - , sumChangeObjective1_(0.0) - , sumChangeObjective2_(0.0) - , globalConflictCuts_(NULL) - , minimumDrop_(1.0e-7) - , numberSolutions_(0) - , numberSavedSolutions_(0) - , maximumSavedSolutions_(0) - , stateOfSearch_(0) - , whenCuts_(-1) - , hotstartSolution_(NULL) - , hotstartPriorities_(NULL) - , numberHeuristicSolutions_(0) - , numberNodes_(0) - , lastNodeImprovingFeasSol_(-1) - , lastTimeImprovingFeasSol_(0) - , numberNodes2_(0) - , numberIterations_(0) - , numberSolves_(0) - , status_(-1) - , secondaryStatus_(-1) - , numberRowsAtContinuous_(0) - , cutoffRowNumber_(-1) - , maximumNumberCuts_(0) - , phase_(0) - , currentNumberCuts_(0) - , maximumDepth_(0) - , walkback_(NULL) - , preProcess_(NULL) - , lastNodeInfo_(NULL) - , lastCut_(NULL) - , lastDepth_(0) - , lastNumberCuts2_(0) - , maximumCuts_(0) - , lastNumberCuts_(NULL) - , addedCuts_(NULL) - , nextRowCut_(NULL) - , currentNode_(NULL) - , integerInfo_(NULL) - , specialOptions_(0) - , moreSpecialOptions_(0) - , moreSpecialOptions2_(0) - , topOfTree_(NULL) - , subTreeModel_(NULL) - , heuristicModel_(NULL) - , numberStoppedSubTrees_(0) - , presolve_(0) - , numberStrong_(5) - , numberBeforeTrust_(10) - , numberPenalties_(20) - , stopNumberIterations_(-1) - , penaltyScaleFactor_(3.0) - , numberAnalyzeIterations_(0) - , analyzeResults_(NULL) - , numberInfeasibleNodes_(0) - , problemType_(0) - , printFrequency_(1) - , secsPrintFrequency_(1) - , lastSecPrintProgress_( 0.0 ) - , numberCutGenerators_(0) - , generator_(NULL) - , virginGenerator_(NULL) - , numberHeuristics_(0) - , heuristic_(NULL) - , lastHeuristic_(NULL) - , fastNodeDepth_(-1) - , eventHandler_(NULL) + : ownership_(0x80000000), continuousSolver_(NULL), referenceSolver_(NULL), + atSolutionSolver_(NULL), defaultHandler_(true), emptyWarmStart_(NULL), + bestObjective_(COIN_DBL_MAX), bestPossibleObjective_(COIN_DBL_MAX), + sumChangeObjective1_(0.0), sumChangeObjective2_(0.0), + globalConflictCuts_(NULL), minimumDrop_(1.0e-7), numberSolutions_(0), + numberSavedSolutions_(0), maximumSavedSolutions_(0), stateOfSearch_(0), + whenCuts_(-1), hotstartSolution_(NULL), hotstartPriorities_(NULL), + numberHeuristicSolutions_(0), numberNodes_(0), + lastNodeImprovingFeasSol_(-1), lastTimeImprovingFeasSol_(0), + numberNodes2_(0), numberIterations_(0), numberSolves_(0), status_(-1), + secondaryStatus_(-1), numberRowsAtContinuous_(0), cutoffRowNumber_(-1), + maximumNumberCuts_(0), phase_(0), currentNumberCuts_(0), maximumDepth_(0), + walkback_(NULL), preProcess_(NULL), lastNodeInfo_(NULL), lastCut_(NULL), + lastDepth_(0), lastNumberCuts2_(0), maximumCuts_(0), + lastNumberCuts_(NULL), addedCuts_(NULL), nextRowCut_(NULL), + currentNode_(NULL), integerInfo_(NULL), specialOptions_(0), + moreSpecialOptions_(0), moreSpecialOptions2_(0), topOfTree_(NULL), + subTreeModel_(NULL), heuristicModel_(NULL), numberStoppedSubTrees_(0), + presolve_(0), numberStrong_(5), numberBeforeTrust_(10), + numberPenalties_(20), stopNumberIterations_(-1), penaltyScaleFactor_(3.0), + numberAnalyzeIterations_(0), analyzeResults_(NULL), + numberInfeasibleNodes_(0), problemType_(0), printFrequency_(1), + secsPrintFrequency_(1), lastSecPrintProgress_(0.0), + numberCutGenerators_(0), generator_(NULL), virginGenerator_(NULL), + numberHeuristics_(0), heuristic_(NULL), lastHeuristic_(NULL), + fastNodeDepth_(-1), eventHandler_(NULL) #ifdef CBC_HAS_NAUTY - , symmetryInfo_(NULL) - , rootSymmetryInfo_(NULL) -#endif - , numberObjects_(0) - , object_(NULL) - , ownObjects_(true) - , originalColumns_(NULL) - , howOftenGlobalScan_(3) - , numberGlobalViolations_(0) - , numberExtraIterations_(0) - , numberExtraNodes_(0) - , numberFathoms_(0) - , continuousObjective_(COIN_DBL_MAX) - , originalContinuousObjective_(COIN_DBL_MAX) - , continuousInfeasibilities_(COIN_INT_MAX) - , maximumCutPassesAtRoot_(20) - , maximumCutPasses_(10) - , preferredWay_(0) - , currentPassNumber_(0) - , maximumWhich_(INITIAL_MAXIMUM_WHICH) - , maximumRows_(0) - , randomSeed_(-1) - , multipleRootTries_(0) - , currentDepth_(0) - , whichGenerator_(NULL) - , maximumStatistics_(0) - , statistics_(NULL) - , maximumDepthActual_(0) - , numberDJFixed_(0.0) - , probingInfo_(NULL) - , numberFixedAtRoot_(0) - , numberFixedNow_(0) - , stoppedOnGap_(false) - , eventHappened_(false) - , numberLongStrong_(0) - , numberOldActiveCuts_(0) - , numberNewCuts_(0) - , searchStrategy_(-1) - , strongStrategy_(0) - , numberStrongIterations_(0) - , resolveAfterTakeOffCuts_(true) - , maximumNumberIterations_(-1) - , continuousPriority_(COIN_INT_MAX) - , numberUpdateItems_(0) - , maximumNumberUpdateItems_(0) - , updateItems_(NULL) - , storedRowCuts_(NULL) - , numberThreads_(0) - , threadMode_(0) - , numberGlobalCutsIn_(0) - , roundIntVars_(false) - , master_(NULL) - , masterThread_(NULL) -{ + , + symmetryInfo_(NULL), rootSymmetryInfo_(NULL) +#endif + , + numberObjects_(0), object_(NULL), ownObjects_(true), + originalColumns_(NULL), howOftenGlobalScan_(3), + numberGlobalViolations_(0), numberExtraIterations_(0), + numberExtraNodes_(0), numberFathoms_(0), + continuousObjective_(COIN_DBL_MAX), + originalContinuousObjective_(COIN_DBL_MAX), + continuousInfeasibilities_(COIN_INT_MAX), maximumCutPassesAtRoot_(20), + maximumCutPasses_(10), preferredWay_(0), currentPassNumber_(0), + maximumWhich_(INITIAL_MAXIMUM_WHICH), maximumRows_(0), randomSeed_(-1), + multipleRootTries_(0), currentDepth_(0), whichGenerator_(NULL), + maximumStatistics_(0), statistics_(NULL), maximumDepthActual_(0), + numberDJFixed_(0.0), probingInfo_(NULL), numberFixedAtRoot_(0), + numberFixedNow_(0), stoppedOnGap_(false), eventHappened_(false), + numberLongStrong_(0), numberOldActiveCuts_(0), numberNewCuts_(0), + searchStrategy_(-1), strongStrategy_(0), numberStrongIterations_(0), + resolveAfterTakeOffCuts_(true), maximumNumberIterations_(-1), + continuousPriority_(COIN_INT_MAX), numberUpdateItems_(0), + maximumNumberUpdateItems_(0), updateItems_(NULL), storedRowCuts_(NULL), + numberThreads_(0), threadMode_(0), numberGlobalCutsIn_(0), + roundIntVars_(false), master_(NULL), masterThread_(NULL) { memset(intParam_, 0, sizeof(intParam_)); intParam_[CbcMaxNumNode] = COIN_INT_MAX; - intParam_[CbcMaxNodesNotImprovingFeasSol] = COIN_INT_MAX; - intParam_[CbcMaxNumSol] = COIN_INT_MAX/2; + intParam_[CbcMaxNodesNotImproving] = COIN_INT_MAX; + intParam_[CbcMaxNumSol] = COIN_INT_MAX / 2; memset(dblParam_, 0, sizeof(dblParam_)); dblParam_[CbcIntegerTolerance] = 1e-6; dblParam_[CbcCutoffIncrement] = 1e-4; dblParam_[CbcAllowableGap] = 1.0e-10; dblParam_[CbcMaximumSeconds] = 1.0e100; - dblParam_[CbcMaximumSecondsNotImprovingFeasSol] = 1.0e100; + dblParam_[CbcMaxSecondsNotImproving] = 1.0e100; dblParam_[CbcCurrentCutoff] = 1.0e100; dblParam_[CbcOptimizationDirection] = 1.0; dblParam_[CbcCurrentObjectiveValue] = 1.0e100; @@ -6276,11 +6293,12 @@ CbcModel::CbcModel(const OsiSolverInterface &rhs) solver_ = rhs.clone(); ownership_ |= 0x80000000; // model now owns solver handler_ = new CoinMessageHandler(); - if (!solver_->defaultHandler() && solver_->messageHandler() && solver_->messageHandler()->logLevel(0) != -1000) + if (!solver_->defaultHandler() && solver_->messageHandler() && + solver_->messageHandler()->logLevel(0) != -1000) passInMessageHandler(solver_->messageHandler()); handler_->setLogLevel(2); messages_ = CbcMessage(); - //eventHandler_ = new CbcEventHandler() ; + // eventHandler_ = new CbcEventHandler() ; referenceSolver_ = solver_->clone(); atSolutionSolver_ = NULL; ownership_ = 0x80000000; @@ -6302,7 +6320,8 @@ CbcModel::CbcModel(const OsiSolverInterface &rhs) if (numberColumns) { // Space for current solution currentSolution_ = new double[numberColumns]; - continuousSolution_ = CoinCopyOfArray(solver_->getColSolution(), numberColumns); + continuousSolution_ = + CoinCopyOfArray(solver_->getColSolution(), numberColumns); usedInSolution_ = new int[numberColumns]; CoinZeroN(usedInSolution_, numberColumns); for (iColumn = 0; iColumn < numberColumns; iColumn++) { @@ -6328,8 +6347,7 @@ CbcModel::CbcModel(const OsiSolverInterface &rhs) } } -static int *resizeInt(int *array, int oldLength, int newLength) -{ +static int *resizeInt(int *array, int oldLength, int newLength) { if (!array) return NULL; assert(newLength > oldLength); @@ -6339,8 +6357,7 @@ static int *resizeInt(int *array, int oldLength, int newLength) memset(newArray + oldLength, 0, (newLength - oldLength) * sizeof(int)); return newArray; } -static double *resizeDouble(double *array, int oldLength, int newLength) -{ +static double *resizeDouble(double *array, int oldLength, int newLength) { if (!array) return NULL; assert(newLength > oldLength); @@ -6360,14 +6377,14 @@ static double *resizeDouble(double *array, int oldLength, int newLength) (cf. assignProblem, loadProblem). TODO: What to do about solver parameters? A simple copy likely won't do it, - because the SI must push the settings into the underlying solver. In - the context of switching solvers in cbc, this means that command line - settings will get lost. Stash the command line somewhere and reread it - here, maybe? + because the SI must push the settings into the underlying solver. In + the context of switching solvers in cbc, this means that command line + settings will get lost. Stash the command line somewhere and reread it + here, maybe? TODO: More generally, how much state should be transferred from the old - solver to the new solver? Best perhaps to see how usage develops. - What's done here mimics the CbcModel(OsiSolverInterface) constructor. + solver to the new solver? Best perhaps to see how usage develops. + What's done here mimics the CbcModel(OsiSolverInterface) constructor. */ void CbcModel::assignSolver(OsiSolverInterface *&solver, bool deleteSolver) @@ -6391,7 +6408,8 @@ void CbcModel::assignSolver(OsiSolverInterface *&solver, bool deleteSolver) } // Keep the current message level for solver (if solver exists) if (solver_) - solver->messageHandler()->setLogLevel(solver_->messageHandler()->logLevel()); + solver->messageHandler()->setLogLevel( + solver_->messageHandler()->logLevel()); if (modelOwnsSolver() && deleteSolver) { solverCharacteristics_ = NULL; @@ -6435,108 +6453,80 @@ void CbcModel::assignSolver(OsiSolverInterface *&solver, bool deleteSolver) // Cloning method -CbcModel *CbcModel::clone(bool cloneHandler) -{ +CbcModel *CbcModel::clone(bool cloneHandler) { return new CbcModel(*this, cloneHandler); } // Copy constructor. CbcModel::CbcModel(const CbcModel &rhs, bool cloneHandler) - : continuousSolver_(NULL) - , referenceSolver_(NULL) - , atSolutionSolver_(NULL) - , defaultHandler_(rhs.defaultHandler_) - , emptyWarmStart_(NULL) - , bestObjective_(rhs.bestObjective_) - , bestPossibleObjective_(rhs.bestPossibleObjective_) - , sumChangeObjective1_(rhs.sumChangeObjective1_) - , sumChangeObjective2_(rhs.sumChangeObjective2_) - , globalConflictCuts_(NULL) - , minimumDrop_(rhs.minimumDrop_) - , numberSolutions_(rhs.numberSolutions_) - , numberSavedSolutions_(rhs.numberSavedSolutions_) - , maximumSavedSolutions_(rhs.maximumSavedSolutions_) - , stateOfSearch_(rhs.stateOfSearch_) - , whenCuts_(rhs.whenCuts_) - , numberHeuristicSolutions_(rhs.numberHeuristicSolutions_) - , numberNodes_(rhs.numberNodes_) - , lastNodeImprovingFeasSol_(rhs.lastNodeImprovingFeasSol_) - , lastTimeImprovingFeasSol_(rhs.lastTimeImprovingFeasSol_) - , numberNodes2_(rhs.numberNodes2_) - , numberIterations_(rhs.numberIterations_) - , numberSolves_(rhs.numberSolves_) - , status_(rhs.status_) - , secondaryStatus_(rhs.secondaryStatus_) - , preProcess_(rhs.preProcess_) - , specialOptions_(rhs.specialOptions_) - , moreSpecialOptions_(rhs.moreSpecialOptions_) - , moreSpecialOptions2_(rhs.moreSpecialOptions2_) - , topOfTree_(NULL) - , subTreeModel_(rhs.subTreeModel_) - , heuristicModel_(NULL) - , numberStoppedSubTrees_(rhs.numberStoppedSubTrees_) - , presolve_(rhs.presolve_) - , numberStrong_(rhs.numberStrong_) - , numberBeforeTrust_(rhs.numberBeforeTrust_) - , numberPenalties_(rhs.numberPenalties_) - , stopNumberIterations_(rhs.stopNumberIterations_) - , penaltyScaleFactor_(rhs.penaltyScaleFactor_) - , numberAnalyzeIterations_(rhs.numberAnalyzeIterations_) - , analyzeResults_(NULL) - , numberInfeasibleNodes_(rhs.numberInfeasibleNodes_) - , problemType_(rhs.problemType_) - , printFrequency_(rhs.printFrequency_) - , secsPrintFrequency_(rhs.secsPrintFrequency_) - , lastSecPrintProgress_(rhs.lastSecPrintProgress_) - , fastNodeDepth_(rhs.fastNodeDepth_) - , howOftenGlobalScan_(rhs.howOftenGlobalScan_) - , numberGlobalViolations_(rhs.numberGlobalViolations_) - , numberExtraIterations_(rhs.numberExtraIterations_) - , numberExtraNodes_(rhs.numberExtraNodes_) - , numberFathoms_(rhs.numberFathoms_) - , continuousObjective_(rhs.continuousObjective_) - , originalContinuousObjective_(rhs.originalContinuousObjective_) - , continuousInfeasibilities_(rhs.continuousInfeasibilities_) - , maximumCutPassesAtRoot_(rhs.maximumCutPassesAtRoot_) - , maximumCutPasses_(rhs.maximumCutPasses_) - , preferredWay_(rhs.preferredWay_) - , currentPassNumber_(rhs.currentPassNumber_) - , maximumWhich_(rhs.maximumWhich_) - , maximumRows_(0) - , randomSeed_(rhs.randomSeed_) - , multipleRootTries_(rhs.multipleRootTries_) - , currentDepth_(0) - , whichGenerator_(NULL) - , maximumStatistics_(0) - , statistics_(NULL) - , maximumDepthActual_(0) - , numberDJFixed_(0.0) - , probingInfo_(NULL) - , numberFixedAtRoot_(rhs.numberFixedAtRoot_) - , numberFixedNow_(rhs.numberFixedNow_) - , stoppedOnGap_(rhs.stoppedOnGap_) - , eventHappened_(rhs.eventHappened_) - , numberLongStrong_(rhs.numberLongStrong_) - , numberOldActiveCuts_(rhs.numberOldActiveCuts_) - , numberNewCuts_(rhs.numberNewCuts_) - , searchStrategy_(rhs.searchStrategy_) - , strongStrategy_(rhs.strongStrategy_) - , numberStrongIterations_(rhs.numberStrongIterations_) - , resolveAfterTakeOffCuts_(rhs.resolveAfterTakeOffCuts_) - , maximumNumberIterations_(rhs.maximumNumberIterations_) - , continuousPriority_(rhs.continuousPriority_) - , numberUpdateItems_(rhs.numberUpdateItems_) - , maximumNumberUpdateItems_(rhs.maximumNumberUpdateItems_) - , updateItems_(NULL) - , storedRowCuts_(NULL) - , numberThreads_(rhs.numberThreads_) - , threadMode_(rhs.threadMode_) - , numberGlobalCutsIn_(rhs.numberGlobalCutsIn_) - , roundIntVars_(rhs.roundIntVars_) - , master_(NULL) - , masterThread_(NULL) -{ + : continuousSolver_(NULL), referenceSolver_(NULL), atSolutionSolver_(NULL), + defaultHandler_(rhs.defaultHandler_), emptyWarmStart_(NULL), + bestObjective_(rhs.bestObjective_), + bestPossibleObjective_(rhs.bestPossibleObjective_), + sumChangeObjective1_(rhs.sumChangeObjective1_), + sumChangeObjective2_(rhs.sumChangeObjective2_), globalConflictCuts_(NULL), + minimumDrop_(rhs.minimumDrop_), numberSolutions_(rhs.numberSolutions_), + numberSavedSolutions_(rhs.numberSavedSolutions_), + maximumSavedSolutions_(rhs.maximumSavedSolutions_), + stateOfSearch_(rhs.stateOfSearch_), whenCuts_(rhs.whenCuts_), + numberHeuristicSolutions_(rhs.numberHeuristicSolutions_), + numberNodes_(rhs.numberNodes_), + lastNodeImprovingFeasSol_(rhs.lastNodeImprovingFeasSol_), + lastTimeImprovingFeasSol_(rhs.lastTimeImprovingFeasSol_), + numberNodes2_(rhs.numberNodes2_), + numberIterations_(rhs.numberIterations_), + numberSolves_(rhs.numberSolves_), status_(rhs.status_), + secondaryStatus_(rhs.secondaryStatus_), preProcess_(rhs.preProcess_), + specialOptions_(rhs.specialOptions_), + moreSpecialOptions_(rhs.moreSpecialOptions_), + moreSpecialOptions2_(rhs.moreSpecialOptions2_), topOfTree_(NULL), + subTreeModel_(rhs.subTreeModel_), heuristicModel_(NULL), + numberStoppedSubTrees_(rhs.numberStoppedSubTrees_), + presolve_(rhs.presolve_), numberStrong_(rhs.numberStrong_), + numberBeforeTrust_(rhs.numberBeforeTrust_), + numberPenalties_(rhs.numberPenalties_), + stopNumberIterations_(rhs.stopNumberIterations_), + penaltyScaleFactor_(rhs.penaltyScaleFactor_), + numberAnalyzeIterations_(rhs.numberAnalyzeIterations_), + analyzeResults_(NULL), numberInfeasibleNodes_(rhs.numberInfeasibleNodes_), + problemType_(rhs.problemType_), printFrequency_(rhs.printFrequency_), + secsPrintFrequency_(rhs.secsPrintFrequency_), + lastSecPrintProgress_(rhs.lastSecPrintProgress_), + fastNodeDepth_(rhs.fastNodeDepth_), + howOftenGlobalScan_(rhs.howOftenGlobalScan_), + numberGlobalViolations_(rhs.numberGlobalViolations_), + numberExtraIterations_(rhs.numberExtraIterations_), + numberExtraNodes_(rhs.numberExtraNodes_), + numberFathoms_(rhs.numberFathoms_), + continuousObjective_(rhs.continuousObjective_), + originalContinuousObjective_(rhs.originalContinuousObjective_), + continuousInfeasibilities_(rhs.continuousInfeasibilities_), + maximumCutPassesAtRoot_(rhs.maximumCutPassesAtRoot_), + maximumCutPasses_(rhs.maximumCutPasses_), + preferredWay_(rhs.preferredWay_), + currentPassNumber_(rhs.currentPassNumber_), + maximumWhich_(rhs.maximumWhich_), maximumRows_(0), + randomSeed_(rhs.randomSeed_), multipleRootTries_(rhs.multipleRootTries_), + currentDepth_(0), whichGenerator_(NULL), maximumStatistics_(0), + statistics_(NULL), maximumDepthActual_(0), numberDJFixed_(0.0), + probingInfo_(NULL), numberFixedAtRoot_(rhs.numberFixedAtRoot_), + numberFixedNow_(rhs.numberFixedNow_), stoppedOnGap_(rhs.stoppedOnGap_), + eventHappened_(rhs.eventHappened_), + numberLongStrong_(rhs.numberLongStrong_), + numberOldActiveCuts_(rhs.numberOldActiveCuts_), + numberNewCuts_(rhs.numberNewCuts_), searchStrategy_(rhs.searchStrategy_), + strongStrategy_(rhs.strongStrategy_), + numberStrongIterations_(rhs.numberStrongIterations_), + resolveAfterTakeOffCuts_(rhs.resolveAfterTakeOffCuts_), + maximumNumberIterations_(rhs.maximumNumberIterations_), + continuousPriority_(rhs.continuousPriority_), + numberUpdateItems_(rhs.numberUpdateItems_), + maximumNumberUpdateItems_(rhs.maximumNumberUpdateItems_), + updateItems_(NULL), storedRowCuts_(NULL), + numberThreads_(rhs.numberThreads_), threadMode_(rhs.threadMode_), + numberGlobalCutsIn_(rhs.numberGlobalCutsIn_), + roundIntVars_(rhs.roundIntVars_), master_(NULL), masterThread_(NULL) { memcpy(intParam_, rhs.intParam_, sizeof(intParam_)); memcpy(dblParam_, rhs.dblParam_, sizeof(dblParam_)); strongInfo_[0] = rhs.strongInfo_[0]; @@ -6595,7 +6585,7 @@ CbcModel::CbcModel(const CbcModel &rhs, bool cloneHandler) int i; for (i = 0; i < numberObjects_; i++) { object_[i] = (rhs.object_[i])->clone(); - CbcObject *obj = dynamic_cast< CbcObject * >(object_[i]); + CbcObject *obj = dynamic_cast(object_[i]); // Could be OsiObjects if (obj) obj->setModel(this); @@ -6668,7 +6658,8 @@ CbcModel::CbcModel(const CbcModel &rhs, bool cloneHandler) randomNumberGenerator_ = rhs.randomNumberGenerator_; if (numberIntegers_) { integerVariable_ = new int[numberIntegers_]; - memcpy(integerVariable_, rhs.integerVariable_, numberIntegers_ * sizeof(int)); + memcpy(integerVariable_, rhs.integerVariable_, + numberIntegers_ * sizeof(int)); integerInfo_ = CoinCopyOfArray(rhs.integerInfo_, solver_->getNumCols()); } else { integerVariable_ = NULL; @@ -6677,7 +6668,8 @@ CbcModel::CbcModel(const CbcModel &rhs, bool cloneHandler) if (rhs.hotstartSolution_) { int numberColumns = solver_->getNumCols(); hotstartSolution_ = CoinCopyOfArray(rhs.hotstartSolution_, numberColumns); - hotstartPriorities_ = CoinCopyOfArray(rhs.hotstartPriorities_, numberColumns); + hotstartPriorities_ = + CoinCopyOfArray(rhs.hotstartPriorities_, numberColumns); } else { hotstartSolution_ = NULL; hotstartPriorities_ = NULL; @@ -6693,14 +6685,16 @@ CbcModel::CbcModel(const CbcModel &rhs, bool cloneHandler) if (maximumSavedSolutions_ && rhs.savedSolutions_) { savedSolutions_ = new double *[maximumSavedSolutions_]; for (int i = 0; i < maximumSavedSolutions_; i++) - savedSolutions_[i] = CoinCopyOfArray(rhs.savedSolutions_[i], numberColumns + 2); + savedSolutions_[i] = + CoinCopyOfArray(rhs.savedSolutions_[i], numberColumns + 2); } else { savedSolutions_ = NULL; } // Space for current solution if (numberColumns) { currentSolution_ = new double[numberColumns]; - continuousSolution_ = CoinCopyOfArray(solver_->getColSolution(), numberColumns); + continuousSolution_ = + CoinCopyOfArray(solver_->getColSolution(), numberColumns); usedInSolution_ = new int[numberColumns]; CoinZeroN(usedInSolution_, numberColumns); } else { @@ -6727,9 +6721,9 @@ CbcModel::CbcModel(const CbcModel &rhs, bool cloneHandler) if (maximumDepth_) { walkback_ = new CbcNodeInfo *[maximumDepth_]; lastNodeInfo_ = new CbcNodeInfo *[maximumDepth_]; - memset(lastNodeInfo_,0,maximumDepth_*sizeof(CbcNodeInfo*)); + memset(lastNodeInfo_, 0, maximumDepth_ * sizeof(CbcNodeInfo *)); lastNumberCuts_ = new int[maximumDepth_]; - memset(lastNumberCuts_,0,maximumDepth_*sizeof(int)); + memset(lastNumberCuts_, 0, maximumDepth_ * sizeof(int)); } else { walkback_ = NULL; lastNodeInfo_ = NULL; @@ -6755,8 +6749,8 @@ CbcModel::CbcModel(const CbcModel &rhs, bool cloneHandler) if (cloneHandler && !defaultHandler_) { delete handler_; /* We have to clone handlers - otherwise will all be - writing to same buffer. So if threads user will - have to sychronize */ + writing to same buffer. So if threads user will + have to sychronize */ CoinMessageHandler *handler = rhs.handler_->clone(); passInMessageHandler(handler); defaultHandler_ = true; @@ -6764,9 +6758,7 @@ CbcModel::CbcModel(const CbcModel &rhs, bool cloneHandler) } // Assignment operator -CbcModel & -CbcModel::operator=(const CbcModel &rhs) -{ +CbcModel &CbcModel::operator=(const CbcModel &rhs) { if (this != &rhs) { if (modelOwnsSolver()) { solverCharacteristics_ = NULL; @@ -6805,7 +6797,7 @@ CbcModel::operator=(const CbcModel &rhs) } else { referenceSolver_ = NULL; } - + delete atSolutionSolver_; if (rhs.atSolutionSolver_) { atSolutionSolver_ = rhs.atSolutionSolver_->clone(); @@ -6840,7 +6832,8 @@ CbcModel::operator=(const CbcModel &rhs) if (numberColumns) { // Space for current solution currentSolution_ = new double[numberColumns]; - continuousSolution_ = CoinCopyOfArray(solver_->getColSolution(), numberColumns); + continuousSolution_ = + CoinCopyOfArray(solver_->getColSolution(), numberColumns); usedInSolution_ = new int[numberColumns]; CoinZeroN(usedInSolution_, numberColumns); } else { @@ -6851,7 +6844,8 @@ CbcModel::operator=(const CbcModel &rhs) if (maximumSavedSolutions_) { savedSolutions_ = new double *[maximumSavedSolutions_]; for (int i = 0; i < maximumSavedSolutions_; i++) - savedSolutions_[i] = CoinCopyOfArray(rhs.savedSolutions_[i], numberColumns + 2); + savedSolutions_[i] = + CoinCopyOfArray(rhs.savedSolutions_[i], numberColumns + 2); } else { savedSolutions_ = NULL; } @@ -6945,8 +6939,7 @@ CbcModel::operator=(const CbcModel &rhs) continuousPriority_ = rhs.continuousPriority_; numberUpdateItems_ = rhs.numberUpdateItems_; maximumNumberUpdateItems_ = rhs.maximumNumberUpdateItems_; - if (updateItems_ != NULL) - delete[] updateItems_; + delete[] updateItems_; if (maximumNumberUpdateItems_) { updateItems_ = new CbcObjectUpdateData[maximumNumberUpdateItems_]; for (i = 0; i < maximumNumberUpdateItems_; i++) @@ -6990,7 +6983,7 @@ CbcModel::operator=(const CbcModel &rhs) if (numberHeuristics_) { heuristic_ = new CbcHeuristic *[numberHeuristics_]; memcpy(heuristic_, rhs.heuristic_, - numberHeuristics_ * sizeof(CbcHeuristic *)); + numberHeuristics_ * sizeof(CbcHeuristic *)); } else { heuristic_ = NULL; } @@ -7025,7 +7018,8 @@ CbcModel::operator=(const CbcModel &rhs) if (rhs.originalColumns_) { int numberColumns = rhs.getNumCols(); originalColumns_ = new int[numberColumns]; - memcpy(originalColumns_, rhs.originalColumns_, numberColumns * sizeof(int)); + memcpy(originalColumns_, rhs.originalColumns_, + numberColumns * sizeof(int)); } else { originalColumns_ = NULL; } @@ -7043,7 +7037,7 @@ CbcModel::operator=(const CbcModel &rhs) cutModifier_ = NULL; if (strategy_) - delete strategy_; + delete strategy_; if (rhs.strategy_) strategy_ = rhs.strategy_->clone(); else @@ -7056,7 +7050,7 @@ CbcModel::operator=(const CbcModel &rhs) if (numberIntegers_) { integerVariable_ = new int[numberIntegers_]; memcpy(integerVariable_, rhs.integerVariable_, - numberIntegers_ * sizeof(int)); + numberIntegers_ * sizeof(int)); integerInfo_ = CoinCopyOfArray(rhs.integerInfo_, rhs.getNumCols()); } else { integerVariable_ = NULL; @@ -7065,7 +7059,8 @@ CbcModel::operator=(const CbcModel &rhs) if (rhs.hotstartSolution_) { int numberColumns = solver_->getNumCols(); hotstartSolution_ = CoinCopyOfArray(rhs.hotstartSolution_, numberColumns); - hotstartPriorities_ = CoinCopyOfArray(rhs.hotstartPriorities_, numberColumns); + hotstartPriorities_ = + CoinCopyOfArray(rhs.hotstartPriorities_, numberColumns); } else { hotstartSolution_ = NULL; hotstartPriorities_ = NULL; @@ -7095,9 +7090,9 @@ CbcModel::operator=(const CbcModel &rhs) if (maximumDepth_) { walkback_ = new CbcNodeInfo *[maximumDepth_]; lastNodeInfo_ = new CbcNodeInfo *[maximumDepth_]; - memset(lastNodeInfo_,0,maximumDepth_*sizeof(CbcNodeInfo*)); + memset(lastNodeInfo_, 0, maximumDepth_ * sizeof(CbcNodeInfo *)); lastNumberCuts_ = new int[maximumDepth_]; - memset(lastNumberCuts_,0,maximumDepth_*sizeof(int)); + memset(lastNumberCuts_, 0, maximumDepth_ * sizeof(int)); } else { walkback_ = NULL; lastNodeInfo_ = NULL; @@ -7132,8 +7127,7 @@ CbcModel::operator=(const CbcModel &rhs) return *this; } // Destructor -CbcModel::~CbcModel() -{ +CbcModel::~CbcModel() { if (defaultHandler_) { delete handler_; handler_ = NULL; @@ -7153,8 +7147,7 @@ CbcModel::~CbcModel() #endif } // Clears out as much as possible (except solver) -void CbcModel::gutsOfDestructor() -{ +void CbcModel::gutsOfDestructor() { delete referenceSolver_; referenceSolver_ = NULL; delete atSolutionSolver_; @@ -7179,16 +7172,14 @@ void CbcModel::gutsOfDestructor() delete[] originalColumns_; originalColumns_ = NULL; delete strategy_; - if (updateItems_ != NULL) - delete[] updateItems_; + delete[] updateItems_; updateItems_ = NULL; numberUpdateItems_ = 0; maximumNumberUpdateItems_ = 0; gutsOfDestructor2(); } // Clears out enough to reset CbcModel -void CbcModel::gutsOfDestructor2() -{ +void CbcModel::gutsOfDestructor2() { delete[] integerInfo_; integerInfo_ = NULL; delete[] integerVariable_; @@ -7219,8 +7210,7 @@ void CbcModel::gutsOfDestructor2() #endif } // Clears out enough to reset CbcModel -void CbcModel::resetModel() -{ +void CbcModel::resetModel() { delete emptyWarmStart_; emptyWarmStart_ = NULL; delete continuousSolver_; @@ -7272,7 +7262,7 @@ void CbcModel::resetModel() int n = 0; for (int i = 0; i < numberCutGenerators_; i++) { CglImplication *cutGen; - cutGen = dynamic_cast< CglImplication * >(generator_[i]->generator()); + cutGen = dynamic_cast(generator_[i]->generator()); if (!cutGen) { generator_[n] = generator_[i]; virginGenerator_[n] = virginGenerator_[i]; @@ -7280,7 +7270,8 @@ void CbcModel::resetModel() } else { cutGen->setProbingInfo(NULL); delete generator_[i]; - cutGen = dynamic_cast< CglImplication * >(virginGenerator_[i]->generator()); + cutGen = + dynamic_cast(virginGenerator_[i]->generator()); assert(cutGen); cutGen->setProbingInfo(NULL); delete virginGenerator_[i]; @@ -7352,10 +7343,9 @@ void CbcModel::resetModel() /* Most of copy constructor mode - 0 copy but don't delete before 1 copy and delete before - 2 copy and delete before (but use virgin generators) + 2 copy and delete before (but use virgin generators) */ -void CbcModel::gutsOfCopy(const CbcModel &rhs, int mode) -{ +void CbcModel::gutsOfCopy(const CbcModel &rhs, int mode) { minimumDrop_ = rhs.minimumDrop_; specialOptions_ = rhs.specialOptions_; moreSpecialOptions_ = rhs.moreSpecialOptions_; @@ -7364,6 +7354,7 @@ void CbcModel::gutsOfCopy(const CbcModel &rhs, int mode) numberBeforeTrust_ = rhs.numberBeforeTrust_; numberPenalties_ = rhs.numberPenalties_; printFrequency_ = rhs.printFrequency_; + secsPrintFrequency_ = rhs.secsPrintFrequency_; fastNodeDepth_ = rhs.fastNodeDepth_; howOftenGlobalScan_ = rhs.howOftenGlobalScan_; maximumCutPassesAtRoot_ = rhs.maximumCutPassesAtRoot_; @@ -7453,8 +7444,7 @@ void CbcModel::gutsOfCopy(const CbcModel &rhs, int mode) synchronizeModel(); } // Move status, nodes etc etc across -void CbcModel::moveInfo(const CbcModel &rhs) -{ +void CbcModel::moveInfo(const CbcModel &rhs) { bestObjective_ = rhs.bestObjective_; bestPossibleObjective_ = rhs.bestPossibleObjective_; numberSolutions_ = rhs.numberSolutions_; @@ -7490,15 +7480,13 @@ void CbcModel::moveInfo(const CbcModel &rhs) maximumDepth_ = rhs.maximumDepth_; } // Save a copy of the current solver so can be reset to -void CbcModel::saveReferenceSolver() -{ +void CbcModel::saveReferenceSolver() { delete referenceSolver_; referenceSolver_ = solver_->clone(); } // Uses a copy of reference solver to be current solver -void CbcModel::resetToReferenceSolver() -{ +void CbcModel::resetToReferenceSolver() { delete solver_; solver_ = referenceSolver_->clone(); // clear many things @@ -7512,99 +7500,84 @@ void CbcModel::resetToReferenceSolver() } // Are there a numerical difficulties? -bool CbcModel::isAbandoned() const -{ - return status_ == 2; -} +bool CbcModel::isAbandoned() const { return status_ == 2; } // Is optimality proven? -bool CbcModel::isProvenOptimal() const -{ +bool CbcModel::isProvenOptimal() const { if (!status_ && bestObjective_ < 1.0e30) return true; else return false; } // Is infeasiblity proven (or none better than cutoff)? -bool CbcModel::isProvenInfeasible() const -{ - if (!status_ && (bestObjective_ >= 1.0e30 && (secondaryStatus_ == 0 || secondaryStatus_ == 1))) +bool CbcModel::isProvenInfeasible() const { + if (!status_ && (bestObjective_ >= 1.0e30 && + (secondaryStatus_ == 0 || secondaryStatus_ == 1))) return true; else return false; } // Was continuous solution unbounded -bool CbcModel::isContinuousUnbounded() const -{ +bool CbcModel::isContinuousUnbounded() const { if (!status_ && secondaryStatus_ == 7) return true; else return false; } // Was continuous solution unbounded -bool CbcModel::isProvenDualInfeasible() const -{ +bool CbcModel::isProvenDualInfeasible() const { if (!status_ && secondaryStatus_ == 7) return true; else return false; } // Node limit reached? -bool CbcModel::isNodeLimitReached() const -{ +bool CbcModel::isNodeLimitReached() const { return numberNodes_ >= intParam_[CbcMaxNumNode]; } // Time limit reached? -bool CbcModel::isSecondsLimitReached() const -{ +bool CbcModel::isSecondsLimitReached() const { if (status_ == 1 && secondaryStatus_ == 4) return true; else return false; } // Solution limit reached? -bool CbcModel::isSolutionLimitReached() const -{ +bool CbcModel::isSolutionLimitReached() const { return numberSolutions_ >= intParam_[CbcMaxNumSol]; } // Set language -void CbcModel::newLanguage(CoinMessages::Language language) -{ +void CbcModel::newLanguage(CoinMessages::Language language) { messages_ = CbcMessage(language); } -void CbcModel::setNumberStrong(int number) -{ +void CbcModel::setNumberStrong(int number) { if (number < 0) numberStrong_ = 0; else numberStrong_ = number; } -void CbcModel::setNumberBeforeTrust(int number) -{ +void CbcModel::setNumberBeforeTrust(int number) { if (number < -3) { numberBeforeTrust_ = 0; } else { numberBeforeTrust_ = number; - //numberStrong_ = CoinMax(numberStrong_,1); + // numberStrong_ = CoinMax(numberStrong_,1); } } -void CbcModel::setNumberPenalties(int number) -{ +void CbcModel::setNumberPenalties(int number) { if (number <= 0) { numberPenalties_ = 0; } else { numberPenalties_ = number; } } -void CbcModel::setPenaltyScaleFactor(double value) -{ +void CbcModel::setPenaltyScaleFactor(double value) { if (value <= 0) { penaltyScaleFactor_ = 3.0; } else { penaltyScaleFactor_ = value; } } -void CbcModel::setHowOftenGlobalScan(int number) -{ +void CbcModel::setHowOftenGlobalScan(int number) { if (number < -1) howOftenGlobalScan_ = 0; else @@ -7612,37 +7585,35 @@ void CbcModel::setHowOftenGlobalScan(int number) } // Add one generator -void CbcModel::addCutGenerator(CglCutGenerator *generator, - int howOften, const char *name, - bool normal, bool atSolution, - bool whenInfeasible, int howOftenInSub, - int whatDepth, int whatDepthInSub) -{ +void CbcModel::addCutGenerator(CglCutGenerator *generator, int howOften, + const char *name, bool normal, bool atSolution, + bool whenInfeasible, int howOftenInSub, + int whatDepth, int whatDepthInSub) { CbcCutGenerator **temp = generator_; generator_ = new CbcCutGenerator *[numberCutGenerators_ + 1]; if (temp != NULL) { memcpy(generator_, temp, numberCutGenerators_ * sizeof(CbcCutGenerator *)); delete[] temp; } - generator_[numberCutGenerators_] = new CbcCutGenerator(this, generator, howOften, name, - normal, atSolution, whenInfeasible, howOftenInSub, - whatDepth, whatDepthInSub); + generator_[numberCutGenerators_] = new CbcCutGenerator( + this, generator, howOften, name, normal, atSolution, whenInfeasible, + howOftenInSub, whatDepth, whatDepthInSub); // and before any changes temp = virginGenerator_; virginGenerator_ = new CbcCutGenerator *[numberCutGenerators_ + 1]; - memcpy(virginGenerator_, temp, numberCutGenerators_ * sizeof(CbcCutGenerator *)); + memcpy(virginGenerator_, temp, + numberCutGenerators_ * sizeof(CbcCutGenerator *)); delete[] temp; - virginGenerator_[numberCutGenerators_++] = new CbcCutGenerator(this, generator, howOften, name, - normal, atSolution, whenInfeasible, howOftenInSub, - whatDepth, whatDepthInSub); + virginGenerator_[numberCutGenerators_++] = new CbcCutGenerator( + this, generator, howOften, name, normal, atSolution, whenInfeasible, + howOftenInSub, whatDepth, whatDepthInSub); } // Add one heuristic void CbcModel::addHeuristic(CbcHeuristic *generator, const char *name, - int before) -{ + int before) { CbcHeuristic **temp = heuristic_; heuristic_ = new CbcHeuristic *[numberHeuristics_ + 1]; - if (temp!= NULL) { + if (temp != NULL) { memcpy(heuristic_, temp, numberHeuristics_ * sizeof(CbcHeuristic *)); delete[] temp; } @@ -7685,8 +7656,7 @@ void CbcModel::addHeuristic(CbcHeuristic *generator, const char *name, Certainly in the contexts where all we need is a list of cuts, there's no point in passing in a valid basis --- an empty basis will do just fine. */ -bool CbcModel::addCuts1(CbcNode *node, CoinWarmStartBasis *&lastws) -{ +bool CbcModel::addCuts1(CbcNode *node, CoinWarmStartBasis *&lastws) { int nNode = 0; CbcNodeInfo *nodeInfo = node->nodeInfo(); int numberColumns = getNumCols(); @@ -7700,7 +7670,7 @@ bool CbcModel::addCuts1(CbcNode *node, CoinWarmStartBasis *&lastws) */ int currentNumberCuts = 0; while (nodeInfo) { - //printf("nNode = %d, nodeInfo = %x\n",nNode,nodeInfo); + // printf("nNode = %d, nodeInfo = %x\n",nNode,nodeInfo); walkback_[nNode++] = nodeInfo; currentNumberCuts += nodeInfo->numberCuts(); nodeInfo = nodeInfo->parent(); @@ -7770,7 +7740,7 @@ bool CbcModel::addCuts1(CbcNode *node, CoinWarmStartBasis *&lastws) } } assert(i < n || lastDepth_ == 0); - //printf("lastDepth %d thisDepth %d match at %d, rows+-= %d %d\n", + // printf("lastDepth %d thisDepth %d match at %d, rows+-= %d %d\n", // lastDepth_,nNode,n-i,nAdd,nDel); sameProblem = (!nAdd) && (!nDel); if (lastDepth_) { @@ -7807,8 +7777,7 @@ bool CbcModel::addCuts1(CbcNode *node, CoinWarmStartBasis *&lastws) currentNumberCuts = 0; while (nNode) { --nNode; - walkback_[nNode]->applyToModel(this, lastws, - addedCuts_, currentNumberCuts); + walkback_[nNode]->applyToModel(this, lastws, addedCuts_, currentNumberCuts); } #ifndef NDEBUG if (lastws && !lastws->fullBasis()) { @@ -7836,8 +7805,7 @@ bool CbcModel::addCuts1(CbcNode *node, CoinWarmStartBasis *&lastws) reference counts to reflect that we're about to prune this node and its descendants. */ -int CbcModel::addCuts(CbcNode *node, CoinWarmStartBasis *&lastws) -{ +int CbcModel::addCuts(CbcNode *node, CoinWarmStartBasis *&lastws) { /* addCuts1 performs step 1 of restoring the subproblem at this node; see the comments there. @@ -7860,20 +7828,18 @@ int CbcModel::addCuts(CbcNode *node, CoinWarmStartBasis *&lastws) if (node->objectiveValue() < cutoff || numberThreads_) { //# define CBC_CHECK_BASIS #ifdef CBC_CHECK_BASIS - printf("addCuts: expanded basis; rows %d+%d\n", - numberRowsAtContinuous_, currentNumberCuts); + printf("addCuts: expanded basis; rows %d+%d\n", numberRowsAtContinuous_, + currentNumberCuts); lastws->print(); #endif /* - Adjust the basis and constraint system so that we retain only active cuts. - There are three steps: - 1) Scan the basis. Sort the cuts into effective cuts to be kept and - loose cuts to be dropped. - 2) Drop the loose cuts and resize the basis to fit. - 3) Install the tight cuts in the constraint system (applyRowCuts) and - and install the basis (setWarmStart). - Use of compressRows conveys we're compressing the basis and not just - tweaking the artificialStatus_ array. + Adjust the basis and constraint system so that we retain only active + cuts. There are three steps: 1) Scan the basis. Sort the cuts into + effective cuts to be kept and loose cuts to be dropped. 2) Drop the loose + cuts and resize the basis to fit. 3) Install the tight cuts in the + constraint system (applyRowCuts) and and install the basis + (setWarmStart). Use of compressRows conveys we're compressing the basis + and not just tweaking the artificialStatus_ array. */ if (currentNumberCuts > 0) { int numberToAdd = 0; @@ -7882,14 +7848,22 @@ int CbcModel::addCuts(CbcNode *node, CoinWarmStartBasis *&lastws) int *cutsToDrop; addCuts = new const OsiRowCut *[currentNumberCuts]; cutsToDrop = new int[currentNumberCuts]; - assert(currentNumberCuts + numberRowsAtContinuous_ <= lastws->getNumArtificial()); - assert(currentNumberCuts <= maximumWhich_); // we will read from whichGenerator_[0..currentNumberCuts-1] below, so should have all these entries + assert(currentNumberCuts + numberRowsAtContinuous_ <= + lastws->getNumArtificial()); + assert(currentNumberCuts <= + maximumWhich_); // we will read from + // whichGenerator_[0..currentNumberCuts-1] below, + // so should have all these entries for (i = 0; i < currentNumberCuts; i++) { - CoinWarmStartBasis::Status status = lastws->getArtifStatus(i + numberRowsAtContinuous_); - if (addedCuts_[i] && (status != CoinWarmStartBasis::basic || (addedCuts_[i]->effectiveness() > 1.0e10 && !addedCuts_[i]->canDropCut(solver_, i + numberRowsAtContinuous_)))) { + CoinWarmStartBasis::Status status = + lastws->getArtifStatus(i + numberRowsAtContinuous_); + if (addedCuts_[i] && (status != CoinWarmStartBasis::basic || + (addedCuts_[i]->effectiveness() > 1.0e10 && + !addedCuts_[i]->canDropCut( + solver_, i + numberRowsAtContinuous_)))) { #ifdef CHECK_CUT_COUNTS printf("Using cut %d %x as row %d\n", i, addedCuts_[i], - numberRowsAtContinuous_ + numberToAdd); + numberRowsAtContinuous_ + numberToAdd); #endif assert(i < maximumWhich_); whichGenerator_[numberToAdd] = whichGenerator_[i]; @@ -7913,7 +7887,8 @@ int CbcModel::addCuts(CbcNode *node, CoinWarmStartBasis *&lastws) int numberRowsNow = numberRowsAtContinuous_ + numberToAdd; lastws->compressRows(numberToDrop, cutsToDrop); lastws->resize(numberRowsNow, numberColumns); - // Take out as local search can give bad basisassert (lastws->fullBasis()); + // Take out as local search can give bad basisassert + // (lastws->fullBasis()); bool canMissStuff = false; if ((specialOptions_ & 4096) == 0) { bool redoCuts = true; @@ -7977,9 +7952,11 @@ int CbcModel::addCuts(CbcNode *node, CoinWarmStartBasis *&lastws) if (numberRowsAtContinuous_ + numberToAdd != solver_->getNumRows()) canMissStuff = false; } else { - //printf("add now %d add last %d NO2\n",numberToAdd,lastNumberCuts2_); + // printf("add now %d add last %d + // NO2\n",numberToAdd,lastNumberCuts2_); } - assert(lastws->fullBasis() && numberRowsAtContinuous_ + numberToAdd == numberRowsNow); + assert(lastws->fullBasis() && + numberRowsAtContinuous_ + numberToAdd == numberRowsNow); if (redoCuts) { if (numberToAdd > maximumCuts_) { delete[] lastCut_; @@ -7992,10 +7969,10 @@ int CbcModel::addCuts(CbcNode *node, CoinWarmStartBasis *&lastws) } } if (!canMissStuff) { - //if (canMissStuff) - //solver_->writeMps("before"); - //printf("Not Skipped\n"); - //int n1=solver_->getNumRows(); + // if (canMissStuff) + // solver_->writeMps("before"); + // printf("Not Skipped\n"); + // int n1=solver_->getNumRows(); if ((specialOptions_ & 4096) == 0) { solver_->restoreBaseModel(numberRowsAtContinuous_); } else { @@ -8014,15 +7991,15 @@ int CbcModel::addCuts(CbcNode *node, CoinWarmStartBasis *&lastws) if (debugger) { for (int j = 0; j < numberToAdd; j++) CoinAssert(!debugger->invalidCut(*addCuts[j])); - //addCuts[j]->print(); + // addCuts[j]->print(); } } #endif solver_->applyRowCuts(numberToAdd, addCuts); } #ifdef CBC_CHECK_BASIS - printf("addCuts: stripped basis; rows %d + %d\n", - numberRowsAtContinuous_, numberToAdd); + printf("addCuts: stripped basis; rows %d + %d\n", numberRowsAtContinuous_, + numberToAdd); lastws->print(); #endif delete[] addCuts; @@ -8039,10 +8016,10 @@ int CbcModel::addCuts(CbcNode *node, CoinWarmStartBasis *&lastws) return 0; } /* - This node has been fathomed by bound as we try to revive it out of the live - set. Adjust the cut reference counts to reflect that we no longer need to - explore the remaining branch arms, hence they will no longer reference any - cuts. Cuts whose reference count falls to zero are deleted. + This node has been fathomed by bound as we try to revive it out of the + live set. Adjust the cut reference counts to reflect that we no longer need + to explore the remaining branch arms, hence they will no longer reference + any cuts. Cuts whose reference count falls to zero are deleted. */ else { int i; @@ -8065,23 +8042,22 @@ int CbcModel::addCuts(CbcNode *node, CoinWarmStartBasis *&lastws) /* Makes all handlers same. If makeDefault 1 then makes top level default and rest point to that. If 2 then each is copy */ -void CbcModel::synchronizeHandlers(int /*makeDefault*/) -{ +void CbcModel::synchronizeHandlers(int /*makeDefault*/) { bool defaultHandler = defaultHandler_; if (!defaultHandler_) { // Must have clone - handler_ = handler_->clone(); // Not sure - worst is small memory leak + handler_ = handler_->clone(); // Not sure - worst is small memory leak defaultHandler_ = true; } #ifdef CBC_HAS_CLP if (!defaultHandler) { OsiClpSolverInterface *solver; - solver = dynamic_cast< OsiClpSolverInterface * >(solver_); + solver = dynamic_cast(solver_); if (solver) { solver->passInMessageHandler(handler_); solver->getModelPtr()->passInMessageHandler(handler_); } - solver = dynamic_cast< OsiClpSolverInterface * >(continuousSolver_); + solver = dynamic_cast(continuousSolver_); if (solver) { solver->passInMessageHandler(handler_); solver->getModelPtr()->passInMessageHandler(handler_); @@ -8100,14 +8076,14 @@ int CbcModel::reducedCostFix() { if (!solverCharacteristics_->reducedCostsAccurate()) - return 0; //NLP + return 0; // NLP double cutoff = getCutoff(); double direction = solver_->getObjSense(); double gap = cutoff - solver_->getObjValue() * direction; double tolerance; solver_->getDblParam(OsiDualTolerance, tolerance); if (gap <= 0.0) - gap = tolerance; //return 0; + gap = tolerance; // return 0; gap += 100.0 * tolerance; double integerTolerance = getDblParam(CbcIntegerTolerance); @@ -8120,8 +8096,8 @@ int CbcModel::reducedCostFix() int numberTightened = 0; #ifdef CBC_HAS_CLP - OsiClpSolverInterface *clpSolver - = dynamic_cast< OsiClpSolverInterface * >(solver_); + OsiClpSolverInterface *clpSolver = + dynamic_cast(solver_); ClpSimplex *clpSimplex = NULL; if (clpSolver) clpSimplex = clpSolver->getModelPtr(); @@ -8131,19 +8107,21 @@ int CbcModel::reducedCostFix() double djValue = direction * reducedCost[iColumn]; double boundGap = upper[iColumn] - lower[iColumn]; if (boundGap > integerTolerance) { - if (solution[iColumn] < lower[iColumn] + integerTolerance - && djValue * boundGap > gap) { + if (solution[iColumn] < lower[iColumn] + integerTolerance && + djValue * boundGap > gap) { #ifdef CBC_HAS_CLP // may just have been fixed before if (clpSimplex) { if (clpSimplex->getColumnStatus(iColumn) == ClpSimplex::basic) { #ifdef COIN_DEVELOP printf("DJfix %d has status of %d, dj of %g gap %g, bounds %g %g\n", - iColumn, clpSimplex->getColumnStatus(iColumn), - djValue, gap, lower[iColumn], upper[iColumn]); + iColumn, clpSimplex->getColumnStatus(iColumn), djValue, gap, + lower[iColumn], upper[iColumn]); #endif } else { - assert(clpSimplex->getColumnStatus(iColumn) == ClpSimplex::atLowerBound || clpSimplex->getColumnStatus(iColumn) == ClpSimplex::isFixed); + assert(clpSimplex->getColumnStatus(iColumn) == + ClpSimplex::atLowerBound || + clpSimplex->getColumnStatus(iColumn) == ClpSimplex::isFixed); } } #endif @@ -8152,24 +8130,27 @@ int CbcModel::reducedCostFix() boundGap = gap / djValue + 1.0e-4 * boundGap; newBound = lower[iColumn] + floor(boundGap); numberTightened++; - //if (newBound) - //printf("tighter - gap %g dj %g newBound %g\n", + // if (newBound) + // printf("tighter - gap %g dj %g newBound %g\n", // gap,djValue,newBound); } solver_->setColUpper(iColumn, newBound); numberFixed++; - } else if (solution[iColumn] > upper[iColumn] - integerTolerance && -djValue > boundGap * gap) { + } else if (solution[iColumn] > upper[iColumn] - integerTolerance && + -djValue > boundGap * gap) { #ifdef CBC_HAS_CLP // may just have been fixed before if (clpSimplex) { if (clpSimplex->getColumnStatus(iColumn) == ClpSimplex::basic) { #ifdef COIN_DEVELOP printf("DJfix %d has status of %d, dj of %g gap %g, bounds %g %g\n", - iColumn, clpSimplex->getColumnStatus(iColumn), - djValue, gap, lower[iColumn], upper[iColumn]); + iColumn, clpSimplex->getColumnStatus(iColumn), djValue, gap, + lower[iColumn], upper[iColumn]); #endif } else { - assert(clpSimplex->getColumnStatus(iColumn) == ClpSimplex::atUpperBound || clpSimplex->getColumnStatus(iColumn) == ClpSimplex::isFixed); + assert(clpSimplex->getColumnStatus(iColumn) == + ClpSimplex::atUpperBound || + clpSimplex->getColumnStatus(iColumn) == ClpSimplex::isFixed); } } #endif @@ -8177,8 +8158,8 @@ int CbcModel::reducedCostFix() if (boundGap > 1.99) { boundGap = -gap / djValue + 1.0e-4 * boundGap; newBound = upper[iColumn] - floor(boundGap); - //if (newBound) - //printf("tighter - gap %g dj %g newBound %g\n", + // if (newBound) + // printf("tighter - gap %g dj %g newBound %g\n", // gap,djValue,newBound); numberTightened++; } @@ -8195,21 +8176,23 @@ int CbcModel::reducedCostFix() return numberFixed; } // Collect coding to replace whichGenerator -void CbcModel::resizeWhichGenerator(int numberNow, int numberAfter) -{ +void CbcModel::resizeWhichGenerator(int numberNow, int numberAfter) { if (numberAfter > maximumWhich_) { #define MAXIMUM_WHICH_INCREMENT 100 #define MAXIMUM_WHICH_MULTIPLIER 2 - //printf("maximumWhich from %d to %d (%d needed)\n",maximumWhich_, - // CoinMax(maximumWhich_ * MAXIMUM_WHICH_MULTIPLIER + MAXIMUM_WHICH_INCREMENT, numberAfter), - // numberAfter); - maximumWhich_ = CoinMax(maximumWhich_ * MAXIMUM_WHICH_MULTIPLIER + MAXIMUM_WHICH_INCREMENT, numberAfter); - //maximumWhich_ = numberAfter ; + // printf("maximumWhich from %d to %d (%d needed)\n",maximumWhich_, + // CoinMax(maximumWhich_ * MAXIMUM_WHICH_MULTIPLIER + + // MAXIMUM_WHICH_INCREMENT, numberAfter), numberAfter); + maximumWhich_ = CoinMax(maximumWhich_ * MAXIMUM_WHICH_MULTIPLIER + + MAXIMUM_WHICH_INCREMENT, + numberAfter); + // maximumWhich_ = numberAfter ; int *temp = new int[2 * maximumWhich_]; memcpy(temp, whichGenerator_, numberNow * sizeof(int)); delete[] whichGenerator_; whichGenerator_ = temp; - memset(whichGenerator_ + numberNow, 0, (maximumWhich_ - numberNow) * sizeof(int)); + memset(whichGenerator_ + numberNow, 0, + (maximumWhich_ - numberNow) * sizeof(int)); } } @@ -8229,7 +8212,7 @@ bool CbcModel::solveWithCuts(OsiCuts &cuts, int numberTries, CbcNode *node) /* Parameters: numberTries: (i) the maximum number of iterations for this round of cut - generation; if negative then we don't mind if drop is tiny. + generation; if negative then we don't mind if drop is tiny. cuts: (o) all cuts generated in this round of cut generation @@ -8245,24 +8228,49 @@ bool CbcModel::solveWithCuts(OsiCuts &cuts, int numberTries, CbcNode *node) numberTries *= 2; // boost } #endif +#if 0 + if ((specialOptions_&2048)==0) { + if (node && numberTries > 1) { + // in main model + if (currentDepth_==0) { + } else if (currentDepth_<8) { + numberTries = CoinMin(numberTries,4); + } else if ((currentDepth_%2)==0) { + numberTries = 1; + } else { + numberTries = 0; + } + } else { + // in sub model + if (currentDepth_==0) { + } else if (currentDepth_<4) { + numberTries = CoinMin(numberTries,2); + } else if ((currentDepth_%4)==0) { + numberTries = 1; + } else { + numberTries = 0; + } + } + } +#endif #define CUT_HISTORY 7 double cut_obj[CUT_HISTORY]; for (int j = 0; j < CUT_HISTORY; j++) cut_obj[j] = -COIN_DBL_MAX; #ifdef CBC_HAS_CLP - OsiClpSolverInterface *clpSolver - = dynamic_cast< OsiClpSolverInterface * >(solver_); + OsiClpSolverInterface *clpSolver = + dynamic_cast(solver_); int saveClpOptions = 0; if (clpSolver) saveClpOptions = clpSolver->specialOptions(); #endif - //solver_->writeMps("saved"); + // solver_->writeMps("saved"); #ifdef CBC_THREAD /* Thread mode makes a difference here only when it specifies using separate - threads to generate cuts at the root (bit 2^1 set in threadMode_). In which - case we'll create an array of empty CbcModels (!). Solvers will be cloned - later. + threads to generate cuts at the root (bit 2^1 set in threadMode_). In + which case we'll create an array of empty CbcModels (!). Solvers will be + cloned later. Don't start up threads here if we're already threaded. */ @@ -8274,7 +8282,7 @@ bool CbcModel::solveWithCuts(OsiCuts &cuts, int numberTries, CbcNode *node) bool feasible = true; int violated = 0; int numberRowsAtStart = solver_->getNumRows(); - //printf("solver had %d rows\n",numberRowsAtStart); + // printf("solver had %d rows\n",numberRowsAtStart); int numberColumns = solver_->getNumCols(); CoinBigIndex numberElementsAtStart = solver_->getNumElements(); @@ -8305,18 +8313,19 @@ bool CbcModel::solveWithCuts(OsiCuts &cuts, int numberTries, CbcNode *node) const OsiRowCutDebugger *debugger = NULL; if ((specialOptions_ & 1) != 0) { /* - See OsiRowCutDebugger for details. In a nutshell, make sure that current - variable values do not conflict with a known optimal solution. (Obviously - this can be fooled when there are multiple solutions.) + See OsiRowCutDebugger for details. In a nutshell, make sure that + current variable values do not conflict with a known optimal solution. + (Obviously this can be fooled when there are multiple solutions.) */ debugger = solver_->getRowCutDebugger(); if (debugger) onOptimalPath = (debugger->onOptimalPath(*solver_)); } /* - As the final action in each round of cut generation (the numberTries loop), - we'll call takeOffCuts to remove slack cuts. These are saved into slackCuts - and rechecked immediately after the cut generation phase of the loop. + As the final action in each round of cut generation (the numberTries + loop), we'll call takeOffCuts to remove slack cuts. These are saved into + slackCuts and rechecked immediately after the cut generation phase of the + loop. */ OsiCuts slackCuts; /* @@ -8347,16 +8356,17 @@ bool CbcModel::solveWithCuts(OsiCuts &cuts, int numberTries, CbcNode *node) #ifdef CONFLICT_CUTS #ifdef CBC_HAS_CLP // if infeasible conflict analysis - if (solver_->isProvenPrimalInfeasible() && !parentModel_ && (moreSpecialOptions_ & 4194304) != 0 && clpSolver) { + if (solver_->isProvenPrimalInfeasible() && !parentModel_ && + (moreSpecialOptions_ & 4194304) != 0 && clpSolver) { if (!topOfTree_ && masterThread_) topOfTree_ = masterThread_->master_->baseModel_->topOfTree_; assert(topOfTree_); int iType = 0; - OsiRowCut *cut = clpSolver->modelCut(topOfTree_->lower(), - topOfTree_->upper(), - numberRowsAtContinuous_, whichGenerator_, iType); + OsiRowCut *cut = + clpSolver->modelCut(topOfTree_->lower(), topOfTree_->upper(), + numberRowsAtContinuous_, whichGenerator_, iType); if (cut) { - //cut->print(); + // cut->print(); if (!iType) { int badCut = makeGlobalCut(cut); if (!badCut) { @@ -8367,8 +8377,8 @@ bool CbcModel::solveWithCuts(OsiCuts &cuts, int numberTries, CbcNode *node) #if PRINT_CONFLICT < 2 if (handler_->logLevel() > 1) { #endif - printf("Conflict cut at depth %d (%d elements)\n", - currentDepth_, cut->row().getNumElements()); + printf("Conflict cut at depth %d (%d elements)\n", currentDepth_, + cut->row().getNumElements()); if (cut->row().getNumElements() < 3) cut->print(); #if PRINT_CONFLICT < 2 @@ -8391,20 +8401,23 @@ bool CbcModel::solveWithCuts(OsiCuts &cuts, int numberTries, CbcNode *node) delete cut; } } - if ((moreSpecialOptions_ & 4194304) != 0 && solver_->isProvenPrimalInfeasible() - && clpSolver && clpSolver->lastAlgorithm() == 2 && clpSolver->getModelPtr()->infeasibilityRay() && !parentModel_) { + if ((moreSpecialOptions_ & 4194304) != 0 && + solver_->isProvenPrimalInfeasible() && clpSolver && + clpSolver->lastAlgorithm() == 2 && + clpSolver->getModelPtr()->infeasibilityRay() && !parentModel_) { printf("ray exists\n"); } #endif #endif double lastObjective = solver_->getObjValue() * solver_->getObjSense(); cut_obj[CUT_HISTORY - 1] = lastObjective; - //double firstObjective = lastObjective+1.0e-8+1.0e-12*fabs(lastObjective); + // double firstObjective = lastObjective+1.0e-8+1.0e-12*fabs(lastObjective); /* Contemplate the result of the resolve. - CbcModel::resolve() has a hook that calls CbcStrategy::status to look over the solution. The net result is that resolve can return - 0 (infeasible), 1 (feasible), or -1 (feasible, but do no further work). + 0 (infeasible), 1 (feasible), or -1 (feasible, but do no further + work). - CbcFeasbililityBase::feasible() can return 0 (no comment), 1 (pretend this is an integer solution), or -1 (pretend this is infeasible). As of 080104, this seems to be a stub to allow overrides, @@ -8431,14 +8444,14 @@ bool CbcModel::solveWithCuts(OsiCuts &cuts, int numberTries, CbcNode *node) } #endif /* - NEW_UPDATE_OBJECT is defined to 0 when unthreaded (CBC_THREAD undefined), 2 - when threaded. No sign of 1 as of 071220. + NEW_UPDATE_OBJECT is defined to 0 when unthreaded (CBC_THREAD undefined), + 2 when threaded. No sign of 1 as of 071220. At present, there are two sets of hierarchies for branching classes. Call them CbcHier and OsiHier. For example, we have OsiBranchingObject, with children CbcBranchingObject and OsiTwoWayBranchingObject. All - specialisations descend from one of these two children. Similarly, there is - OsiObject, with children CbcObject and OsiObject2. + specialisations descend from one of these two children. Similarly, there + is OsiObject, with children CbcObject and OsiObject2. In the original setup, there's a single CbcBranchDecision object attached to CbcModel (branchingMethod_). It has a field to hold the current CbcHier @@ -8452,33 +8465,35 @@ bool CbcModel::solveWithCuts(OsiCuts &cuts, int numberTries, CbcNode *node) default CbcBranchDefaultDecision, updateInformation is a noop (actually defined in the base CbcBranchDecision class). - NEW_UPDATE_OBJECT = 2 looks like it's prepared to cope with either CbcHier or - OsiHier, but it'll be executed only when threads are activated. See the + NEW_UPDATE_OBJECT = 2 looks like it's prepared to cope with either CbcHier + or OsiHier, but it'll be executed only when threads are activated. See the comments below. The setup is scary. But ... if the OsiHier update actually reaches right through to the object list in the solver, it should work just fine in unthreaded mode. It would - seem that the appropriate thing to do in unthreaded mode would be to choose - between the existing code for NEW_UPDATE_OBJECT = 0 and the OsiHier code for - NEW_UPDATE_OBJECT = 2. But I'm going to let John hash that out. The worst - that can happen is inefficiency because I'm not properly updating an object. + seem that the appropriate thing to do in unthreaded mode would be to + choose between the existing code for NEW_UPDATE_OBJECT = 0 and the OsiHier + code for NEW_UPDATE_OBJECT = 2. But I'm going to let John hash that out. + The worst that can happen is inefficiency because I'm not properly updating + an object. */ // Update branching information if wanted if (node && branchingMethod_) { OsiBranchingObject *bobj = node->modifiableBranchingObject(); - CbcBranchingObject *cbcobj = dynamic_cast< CbcBranchingObject * >(bobj); + CbcBranchingObject *cbcobj = dynamic_cast(bobj); if (cbcobj && cbcobj->object()) { CbcObject *object = cbcobj->object(); - CbcObjectUpdateData update = object->createUpdateInformation(solver_, node, cbcobj); + CbcObjectUpdateData update = + object->createUpdateInformation(solver_, node, cbcobj); // have to compute object number as not saved - CbcSimpleInteger *simpleObject = static_cast< CbcSimpleInteger * >(object); + CbcSimpleInteger *simpleObject = static_cast(object); int iObject = simpleObject->position(); #ifndef NDEBUG int iColumn = simpleObject->columnNumber(); int jObject; for (jObject = 0; jObject < numberObjects_; jObject++) { - simpleObject = static_cast< CbcSimpleInteger * >(object_[jObject]); + simpleObject = static_cast(object_[jObject]); if (simpleObject->columnNumber() == iColumn) break; } @@ -8489,11 +8504,12 @@ bool CbcModel::solveWithCuts(OsiCuts &cuts, int numberTries, CbcNode *node) #endif #endif update.objectNumber_ = iObject; - // Care! We must be careful not to update the same variable in parallel threads. + // Care! We must be careful not to update the same variable in parallel + // threads. addUpdateInformation(update); // update here { - CbcObject *object = dynamic_cast< CbcObject * >(update.object_); + CbcObject *object = dynamic_cast(update.object_); if (object) object->updateInformation(update); } @@ -8505,11 +8521,12 @@ bool CbcModel::solveWithCuts(OsiCuts &cuts, int numberTries, CbcNode *node) // way is what will be taken next way = -way; double value = cbcobj->value(); - //const double * lower = solver_->getColLower(); - //const double * upper = solver_->getColUpper(); + // const double * lower = solver_->getColLower(); + // const double * upper = solver_->getColUpper(); double objectiveChange = lastObjective - objectiveValue; if (objectiveChange > 1.0e-5) { - CbcIntegerBranchingObject *branch = dynamic_cast< CbcIntegerBranchingObject * >(cbcobj); + CbcIntegerBranchingObject *branch = + dynamic_cast(cbcobj); assert(branch); if (way < 0) { double down = value - floor(value); @@ -8520,9 +8537,9 @@ bool CbcModel::solveWithCuts(OsiCuts &cuts, int numberTries, CbcNode *node) double newLower = ceil(value - distance); const double *downBounds = branch->downBounds(); if (newLower > downBounds[0]) { - //printf("%d way %d bounds %g %g value %g\n", + // printf("%d way %d bounds %g %g value %g\n", // iColumn,way,lower[iColumn],upper[iColumn],value); - //printf("B Could increase lower bound on %d from %g to %g\n", + // printf("B Could increase lower bound on %d from %g to %g\n", // iColumn,downBounds[0],newLower); solver_->setColLower(iColumn, newLower); } @@ -8536,9 +8553,9 @@ bool CbcModel::solveWithCuts(OsiCuts &cuts, int numberTries, CbcNode *node) double newUpper = floor(value + distance); const double *upBounds = branch->upBounds(); if (newUpper < upBounds[1]) { - //printf("%d way %d bounds %g %g value %g\n", + // printf("%d way %d bounds %g %g value %g\n", // iColumn,way,lower[iColumn],upper[iColumn],value); - //printf("B Could decrease upper bound on %d from %g to %g\n", + // printf("B Could decrease upper bound on %d from %g to %g\n", // iColumn,upBounds[1],newUpper); solver_->setColUpper(iColumn, newUpper); } @@ -8548,7 +8565,8 @@ bool CbcModel::solveWithCuts(OsiCuts &cuts, int numberTries, CbcNode *node) } #endif } else { - OsiIntegerBranchingObject *obj = dynamic_cast< OsiIntegerBranchingObject * >(bobj); + OsiIntegerBranchingObject *obj = + dynamic_cast(bobj); if (obj) { const OsiObject *object = obj->originalObject(); // have to compute object number as not saved @@ -8572,8 +8590,9 @@ bool CbcModel::solveWithCuts(OsiCuts &cuts, int numberTries, CbcNode *node) movement = ceil(value) - value; else movement = value - floor(value); - branchingMethod_->chooseMethod()->updateInformation(iObject, branch, changeInObjective, - movement, 0 /*(feasible) ? 0 : 1; */); + branchingMethod_->chooseMethod()->updateInformation( + iObject, branch, changeInObjective, movement, + 0 /*(feasible) ? 0 : 1; */); } } } @@ -8581,8 +8600,8 @@ bool CbcModel::solveWithCuts(OsiCuts &cuts, int numberTries, CbcNode *node) #ifdef CBC_DEBUG if (feasible) { printf("Obj value %g (%s) %d rows\n", solver_->getObjValue(), - (solver_->isProvenOptimal()) ? "proven" : "unproven", - solver_->getNumRows()); + (solver_->isProvenOptimal()) ? "proven" : "unproven", + solver_->getNumRows()); } else { @@ -8591,15 +8610,17 @@ bool CbcModel::solveWithCuts(OsiCuts &cuts, int numberTries, CbcNode *node) #endif if ((specialOptions_ & 1) != 0) { /* - If the RowCutDebugger said we were compatible with the optimal solution, - and now we're suddenly infeasible, we might be confused. Then again, we - may have fathomed by bound, heading for a rediscovery of an optimal solution. + If the RowCutDebugger said we were compatible with the optimal + solution, and now we're suddenly infeasible, we might be confused. Then + again, we may have fathomed by bound, heading for a rediscovery of an + optimal solution. */ if (onOptimalPath && !solver_->isDualObjectiveLimitReached()) { if (!feasible) { solver_->writeMpsNative("infeas.mps", NULL, NULL, 2); solver_->getRowCutDebuggerAlways()->printOptimalSolution(*solver_); - CoinWarmStartBasis *slack = dynamic_cast< CoinWarmStartBasis * >(solver_->getEmptyWarmStart()); + CoinWarmStartBasis *slack = + dynamic_cast(solver_->getEmptyWarmStart()); solver_->setWarmStart(slack); delete slack; solver_->setHintParam(OsiDoReducePrint, false, OsiHintDo, 0); @@ -8619,13 +8640,14 @@ bool CbcModel::solveWithCuts(OsiCuts &cuts, int numberTries, CbcNode *node) } double change = lastObjective - objectiveValue; if (change > 1.0e-10) { - dblParam_[CbcSmallestChange] = CoinMin(dblParam_[CbcSmallestChange], change); + dblParam_[CbcSmallestChange] = + CoinMin(dblParam_[CbcSmallestChange], change); dblParam_[CbcSumChange] += change; dblParam_[CbcLargestChange] = CoinMax(dblParam_[CbcLargestChange], change); intParam_[CbcNumberBranches]++; } - sumChangeObjective1_ += solver_->getObjValue() * solver_->getObjSense() - - objectiveValue; + sumChangeObjective1_ += + solver_->getObjValue() * solver_->getObjSense() - objectiveValue; if (maximumSecondsReached()) numberTries = 0; // exit if ((moreSpecialOptions2_ & (2048 | 4096)) != 0 && currentDepth_ > 5) { @@ -8649,8 +8671,8 @@ bool CbcModel::solveWithCuts(OsiCuts &cuts, int numberTries, CbcNode *node) numberTries = 0; } } - //if ((numberNodes_%100)==0) - //printf("XXa sum obj changed by %g\n",sumChangeObjective1_); + // if ((numberNodes_%100)==0) + // printf("XXa sum obj changed by %g\n",sumChangeObjective1_); objectiveValue = solver_->getObjValue() * solver_->getObjSense(); // Return at once if numberTries zero if (!numberTries) { @@ -8672,8 +8694,8 @@ bool CbcModel::solveWithCuts(OsiCuts &cuts, int numberTries, CbcNode *node) reducedCostFix(); /* Set up for at most numberTries rounds of cut generation. If numberTries is - negative, we'll ignore the minimumDrop_ cutoff and keep generating cuts for - the specified number of rounds. + negative, we'll ignore the minimumDrop_ cutoff and keep generating cuts + for the specified number of rounds. */ double minimumDrop = minimumDrop_; bool allowZeroIterations = false; @@ -8682,10 +8704,10 @@ bool CbcModel::solveWithCuts(OsiCuts &cuts, int numberTries, CbcNode *node) numberTries = -numberTries; // minimumDrop *= 1.0e-5 ; // if (numberTries >= -1000000) { - //numberTries=100; + // numberTries=100; minimumDrop = -1.0; // } - //numberTries=CoinMax(numberTries,100); + // numberTries=CoinMax(numberTries,100); allowZeroIterations = true; } int saveNumberTries = numberTries; @@ -8707,7 +8729,7 @@ bool CbcModel::solveWithCuts(OsiCuts &cuts, int numberTries, CbcNode *node) currentPassNumber_ = 0; // Really primalIntegerTolerance; relates to an illposed problem with various // integer solutions depending on integer tolerance. - //double primalTolerance = 1.0e-7 ; + // double primalTolerance = 1.0e-7 ; // We may need to keep going on bool keepGoing = false; // Say we have not tried one last time @@ -8757,18 +8779,20 @@ bool CbcModel::solveWithCuts(OsiCuts &cuts, int numberTries, CbcNode *node) useful. */ int numberViolated = 0; - if ((currentPassNumber_ == 1 || !numberNodes_) && howOftenGlobalScan_ > 0 && (numberNodes_ % howOftenGlobalScan_) == 0 && (doCutsNow(1) || true)) { + if ((currentPassNumber_ == 1 || !numberNodes_) && howOftenGlobalScan_ > 0 && + (numberNodes_ % howOftenGlobalScan_) == 0 && (doCutsNow(1) || true)) { // global column cuts now done in node at top of tree int numberCuts = numberCutGenerators_ ? globalCuts_.sizeRowCuts() : 0; if (numberCuts) { // possibly extend whichGenerator - resizeWhichGenerator(numberViolated, numberViolated + numberCuts); + resizeWhichGenerator(0, numberCuts); // only add new cuts up to 10% of current elements CoinBigIndex numberElements = solver_->getNumElements(); int numberColumns = solver_->getNumCols(); - CoinBigIndex maximumAdd = CoinMax(numberElements / 10, - static_cast< CoinBigIndex >(2 * numberColumns)) - + 100; + CoinBigIndex maximumAdd = + CoinMax(numberElements / 10, + static_cast(2 * numberColumns)) + + 100; double *violations = new double[numberCuts]; int *which = new int[numberCuts]; int numberPossible = 0; @@ -8784,8 +8808,8 @@ bool CbcModel::solveWithCuts(OsiCuts &cuts, int numberTries, CbcNode *node) } if (j == currentNumberCuts_) violation = COIN_DBL_MAX; - //else - //printf("already done??\n"); + // else + // printf("already done??\n"); } if (violation > 0.005) { violations[numberPossible] = -violation; @@ -8796,14 +8820,17 @@ bool CbcModel::solveWithCuts(OsiCuts &cuts, int numberTries, CbcNode *node) for (int i = 0; i < numberPossible; i++) { int k = which[i]; OsiRowCut *thisCut = globalCuts_.rowCutPtr(k); - assert(thisCut->violated(cbcColSolution_) > 0.005 /*primalTolerance*/ || thisCut->effectiveness() == COIN_DBL_MAX); + assert( + thisCut->violated(cbcColSolution_) > 0.005 /*primalTolerance*/ || + thisCut->effectiveness() == COIN_DBL_MAX); #define CHECK_DEBUGGER #ifdef CHECK_DEBUGGER if ((specialOptions_ & 1) != 0 && !parentModel_) { - CoinAssert(!solver_->getRowCutDebuggerAlways()->invalidCut(*thisCut)); + CoinAssert( + !solver_->getRowCutDebuggerAlways()->invalidCut(*thisCut)); } #endif -#if 0 //ndef NDEBUG +#if 0 // ndef NDEBUG printf("Global cut added - violation %g\n", thisCut->violated(cbcColSolution_)) ; #endif @@ -8829,39 +8856,40 @@ bool CbcModel::solveWithCuts(OsiCuts &cuts, int numberTries, CbcNode *node) variables. At present, CglProbing is the only case where generateCuts will return - true. generateCuts actually modifies variable bounds in the solver when - CglProbing indicates that it can fix a variable. Reoptimisation is required - to take full advantage. - - The need to resolve here should only happen after a heuristic solution. - optimalBasisIsAvailable resolves to basisIsAvailable, which seems to be part - of the old OsiSimplex API. Doc'n says `Returns true if a basis is available - and the problem is optimal. Should be used to see if the BinvARow type - operations are possible and meaningful.' Which means any solver other the clp - is probably doing a lot of unnecessary resolves right here. - (Note default OSI implementation of optimalBasisIsAvailable always returns - false.) + true. generateCuts actually modifies variable bounds in the solver + when CglProbing indicates that it can fix a variable. Reoptimisation is + required to take full advantage. + + The need to resolve here should only happen after a heuristic + solution. optimalBasisIsAvailable resolves to basisIsAvailable, which + seems to be part of the old OsiSimplex API. Doc'n says `Returns true if a + basis is available and the problem is optimal. Should be used to see if + the BinvARow type operations are possible and meaningful.' Which means + any solver other the clp is probably doing a lot of unnecessary resolves + right here. (Note default OSI implementation of optimalBasisIsAvailable + always returns false.) */ - if (solverCharacteristics_->warmStart() && !solver_->optimalBasisIsAvailable()) { - //printf("XXXXYY no opt basis\n"); -#ifdef JJF_ZERO //def CBC_HAS_CLP - //OsiClpSolverInterface * clpSolver + if (solverCharacteristics_->warmStart() && + !solver_->optimalBasisIsAvailable()) { + // printf("XXXXYY no opt basis\n"); +#ifdef JJF_ZERO // def CBC_HAS_CLP + // OsiClpSolverInterface * clpSolver //= dynamic_cast (solver_); int save = 0; if (clpSolver) { save = clpSolver->specialOptions(); - clpSolver->setSpecialOptions(save | 2048 /*4096*/); // Bonmin + clpSolver->setSpecialOptions(save | + 2048 /*4096*/); // Bonmin } #endif resolve(node ? node->nodeInfo() : NULL, 3); -#ifdef JJF_ZERO //def CBC_HAS_CLP +#ifdef JJF_ZERO // def CBC_HAS_CLP if (clpSolver) clpSolver->setSpecialOptions(save); #if CBC_USEFUL_PRINTING > 1 if (clpSolver->getModelPtr()->numberIterations()) - printf("ITS %d pass %d\n", - clpSolver->getModelPtr()->numberIterations(), - currentPassNumber_); + printf("ITS %d pass %d\n", clpSolver->getModelPtr()->numberIterations(), + currentPassNumber_); #endif #endif } @@ -8880,8 +8908,8 @@ bool CbcModel::solveWithCuts(OsiCuts &cuts, int numberTries, CbcNode *node) for (int i = 0; i < n; i++) { int iColumn = column[i]; double value = element[i]; - //if (cbcColSolution_[iColumn]>1.0e-7) - //printf("value of %d is %g\n",iColumn,cbcColSolution_[iColumn]); + // if (cbcColSolution_[iColumn]>1.0e-7) + // printf("value of %d is %g\n",iColumn,cbcColSolution_[iColumn]); sum += value * cbcColSolution_[iColumn]; } delete nextRowCut_; @@ -8895,45 +8923,47 @@ bool CbcModel::solveWithCuts(OsiCuts &cuts, int numberTries, CbcNode *node) } // reset probing info - //if (probingInfo_) - //probingInfo_->initializeFixing(); + // if (probingInfo_) + // probingInfo_->initializeFixing(); int i; // If necessary make cut generators work harder - bool strongCuts = (!node && cut_obj[CUT_HISTORY - 1] != -COIN_DBL_MAX && fabs(cut_obj[CUT_HISTORY - 1] - cut_obj[CUT_HISTORY - 2]) < 1.0e-7 + 1.0e-6 * fabs(cut_obj[CUT_HISTORY - 1])); + bool strongCuts = + (!node && cut_obj[CUT_HISTORY - 1] != -COIN_DBL_MAX && + fabs(cut_obj[CUT_HISTORY - 1] - cut_obj[CUT_HISTORY - 2]) < + 1.0e-7 + 1.0e-6 * fabs(cut_obj[CUT_HISTORY - 1])); for (i = 0; i < numberCutGenerators_; i++) generator_[i]->setIneffectualCuts(strongCuts); // Print details if (!node) { handler_->message(CBC_ROOT_DETAIL, messages_) - << currentPassNumber_ - << solver_->getNumRows() - << solver_->getNumRows() - numberRowsAtContinuous_ - << solver_->getObjValue() - << CoinMessageEol; + << currentPassNumber_ << solver_->getNumRows() + << solver_->getNumRows() - numberRowsAtContinuous_ + << solver_->getObjValue() << CoinMessageEol; } // see if looks like solution bool lazy = false; - if ((moreSpecialOptions2_&65536)!= 0) { - const double * solution = solver_->getColSolution(); - const double * lower = solver_->getColLower(); - const double * upper = solver_->getColUpper(); + if ((moreSpecialOptions2_ & 65536) != 0) { + const double *solution = solver_->getColSolution(); + const double *lower = solver_->getColLower(); + const double *upper = solver_->getColUpper(); double integerTolerance = getIntegerTolerance(); int iLook; - for (iLook=0;iLookintegerTolerance) - break; + for (iLook = 0; iLook < numberIntegers_; iLook++) { + int iColumn = integerVariable_[iLook]; + double value = solution[iColumn]; + value = CoinMax(value, lower[iColumn]); + value = CoinMin(value, upper[iColumn]); + double nearest = floor(value + 0.5); + if (fabs(value - nearest) > integerTolerance) + break; } - if (iLook==numberIntegers_) { - keepGoing = true; // say must go round - lazy = true; + if (iLook == numberIntegers_) { + keepGoing = true; // say must go round + lazy = true; } } - //Is Necessary for Bonmin? Always keepGoing if cuts have been generated in last iteration (taken from similar code in Cbc-2.4) + // Is Necessary for Bonmin? Always keepGoing if cuts have been generated in + // last iteration (taken from similar code in Cbc-2.4) if (solverCharacteristics_->solutionAddsCuts() && numberViolated) { for (i = 0; i < numberCutGenerators_; i++) { if (generator_[i]->mustCallAgain()) { @@ -8946,15 +8976,16 @@ bool CbcModel::solveWithCuts(OsiCuts &cuts, int numberTries, CbcNode *node) // Status for single pass of cut generation int status = 0; /* - threadMode with bit 2^1 set indicates we should use threads for root cut - generation. + threadMode with bit 2^1 set indicates we should use threads for root + cut generation. */ if ((threadMode_ & 2) == 0 || numberNodes_) { status = serialCuts(theseCuts, node, slackCuts, lastNumberCuts); } else { // do cuts independently #ifdef CBC_THREAD - status = parallelCuts(master, theseCuts, node, slackCuts, lastNumberCuts); + status = + parallelCuts(master, theseCuts, node, slackCuts, lastNumberCuts); #endif } // Do we need feasible and violated? @@ -8966,13 +8997,14 @@ bool CbcModel::solveWithCuts(OsiCuts &cuts, int numberTries, CbcNode *node) if (!feasible) violated = -2; } - //if (!feasible) - //break; + // if (!feasible) + // break; /* End of the loop to exercise each generator - try heuristics - unless at root node and first pass */ - if ((numberNodes_ || currentPassNumber_ != 1) && (!this->maximumSecondsReached())) { + if ((numberNodes_ || currentPassNumber_ != 1) && + (!this->maximumSecondsReached())) { double *newSolution = new double[numberColumns]; double heuristicValue = getCutoff(); int found = -1; // no solution found @@ -8983,9 +9015,8 @@ bool CbcModel::solveWithCuts(OsiCuts &cuts, int numberTries, CbcNode *node) continue; // see if heuristic will do anything double saveValue = heuristicValue; - int ifSol = heuristic_[i]->solution(heuristicValue, - newSolution); - //theseCuts) ; + int ifSol = heuristic_[i]->solution(heuristicValue, newSolution); + // theseCuts) ; if (ifSol > 0) { // better solution found heuristic_[i]->incrementNumberSolutionsFound(); @@ -8993,8 +9024,8 @@ bool CbcModel::solveWithCuts(OsiCuts &cuts, int numberTries, CbcNode *node) incrementUsed(newSolution); lastHeuristic_ = heuristic_[found]; #ifdef HEURISTIC_INFORM - printf("HEUR %s where %d A\n", - lastHeuristic_->heuristicName(), whereFrom); + printf("HEUR %s where %d A\n", lastHeuristic_->heuristicName(), + whereFrom); #endif // CBC_ROUNDING is symbolic; just says found by heuristic setBestSolution(CBC_ROUNDING, heuristicValue, newSolution); @@ -9004,13 +9035,12 @@ bool CbcModel::solveWithCuts(OsiCuts &cuts, int numberTries, CbcNode *node) } } /* - Did any of the heuristics turn up a new solution? Record it before we free - the vector. + Did any of the heuristics turn up a new solution? Record it before + we free the vector. */ if (found >= 0) { phase_ = 4; - CbcTreeLocal *tree - = dynamic_cast< CbcTreeLocal * >(tree_); + CbcTreeLocal *tree = dynamic_cast(tree_); if (tree) tree->passInSolution(bestSolution_, heuristicValue); } @@ -9035,19 +9065,19 @@ bool CbcModel::solveWithCuts(OsiCuts &cuts, int numberTries, CbcNode *node) if (violated >= 0) violated = numberRowCuts + numberColumnCuts; /* - Apply column cuts (aka bound tightening). This may be partially redundant - for column cuts returned by CglProbing, as generateCuts installs bounds - from CglProbing when it determines it can fix a variable. - - TODO: Looks like the use of violated has evolved. The value set above is - completely ignored. All that's left is violated == -1 indicates some - cut is violated, violated == -2 indicates infeasibility. Only - infeasibility warrants exceptional action. - - TODO: Strikes me that this code will fail to detect infeasibility, because - the breaks escape the inner loops but the outer loop keeps going. - Infeasibility in an early cut will be overwritten if a later cut is - merely violated. + Apply column cuts (aka bound tightening). This may be partially + redundant for column cuts returned by CglProbing, as generateCuts + installs bounds from CglProbing when it determines it can fix a variable. + + TODO: Looks like the use of violated has evolved. The value set above + is completely ignored. All that's left is violated == -1 indicates some + cut is violated, violated == -2 indicates infeasibility. Only + infeasibility warrants exceptional action. + + TODO: Strikes me that this code will fail to detect infeasibility, + because the breaks escape the inner loops but the outer loop keeps going. + Infeasibility in an early cut will be overwritten if a later cut + is merely violated. */ if (numberColumnCuts) { @@ -9075,7 +9105,7 @@ bool CbcModel::solveWithCuts(OsiCuts &cuts, int numberTries, CbcNode *node) double value = cbcColSolution_[iColumn]; #if CBC_DEBUG > 1 printf("%d %g %g %g %g\n", iColumn, oldLower[iColumn], - cbcColSolution_[iColumn], oldUpper[iColumn], values[j]); + cbcColSolution_[iColumn], oldUpper[iColumn], values[j]); #endif solver_->setColLower(iColumn, values[j]); if (value < values[j] - integerTolerance) @@ -9094,7 +9124,7 @@ bool CbcModel::solveWithCuts(OsiCuts &cuts, int numberTries, CbcNode *node) double value = cbcColSolution_[iColumn]; #if CBC_DEBUG > 1 printf("%d %g %g %g %g\n", iColumn, oldLower[iColumn], - cbcColSolution_[iColumn], oldUpper[iColumn], values[j]); + cbcColSolution_[iColumn], oldUpper[iColumn], values[j]); #endif solver_->setColUpper(iColumn, values[j]); if (value > values[j] + integerTolerance) @@ -9112,25 +9142,23 @@ bool CbcModel::solveWithCuts(OsiCuts &cuts, int numberTries, CbcNode *node) #endif } /* - End installation of column cuts. The break here escapes the numberTries - loop. + End installation of column cuts. The break here escapes the + numberTries loop. */ if (violated == -2 || !feasible) { // infeasible feasible = false; violated = -2; if (!numberNodes_) - messageHandler()->message(CBC_INFEAS, - messages()) - << CoinMessageEol; + messageHandler()->message(CBC_INFEAS, messages()) << CoinMessageEol; break; } /* - Now apply the row (constraint) cuts. This is a bit more work because we need - to obtain and augment the current basis. + Now apply the row (constraint) cuts. This is a bit more work because + we need to obtain and augment the current basis. - TODO: Why do this work, if there are no row cuts? The current basis will do - just fine. + TODO: Why do this work, if there are no row cuts? The current basis + will do just fine. */ int numberRowsNow = solver_->getNumRows(); #ifndef NDEBUG @@ -9138,10 +9166,14 @@ bool CbcModel::solveWithCuts(OsiCuts &cuts, int numberTries, CbcNode *node) #else // ? maybe clue to threaded problems if (numberRowsNow != numberRowsAtStart + lastNumberCuts) { - fprintf(stderr, "*** threaded error - numberRowsNow(%d) != numberRowsAtStart(%d)+lastNumberCuts(%d)\n", - numberRowsNow, numberRowsAtStart, lastNumberCuts); - fprintf(stdout, "*** threaded error - numberRowsNow(%d) != numberRowsAtStart(%d)+lastNumberCuts(%d)\n", - numberRowsNow, numberRowsAtStart, lastNumberCuts); + fprintf(stderr, + "*** threaded error - numberRowsNow(%d) != " + "numberRowsAtStart(%d)+lastNumberCuts(%d)\n", + numberRowsNow, numberRowsAtStart, lastNumberCuts); + fprintf(stdout, + "*** threaded error - numberRowsNow(%d) != " + "numberRowsAtStart(%d)+lastNumberCuts(%d)\n", + numberRowsNow, numberRowsAtStart, lastNumberCuts); abort(); } #endif @@ -9153,19 +9185,19 @@ bool CbcModel::solveWithCuts(OsiCuts &cuts, int numberTries, CbcNode *node) Now actually add the row cuts and reoptimise. Install the cuts in the solver using applyRowCuts and - augment the basis with the corresponding slack. We also add each row cut to - the set of row cuts (cuts.insert()) supplied as a parameter. The new basis - must be set with setWarmStart(). + augment the basis with the corresponding slack. We also add each row + cut to the set of row cuts (cuts.insert()) supplied as a parameter. The + new basis must be set with setWarmStart(). - TODO: Seems to me the original code could allocate addCuts with size 0, if - numberRowCuts was 0 and numberColumnCuts was nonzero. That might - explain the memory fault noted in the comment by AJK. Unfortunately, - just commenting out the delete[] results in massive memory leaks. Try - a revision to separate the row cut case. Why do we need addCuts at - all? A typing issue, apparently: OsiCut vs. OsiRowCut. + TODO: Seems to me the original code could allocate addCuts with size + 0, if numberRowCuts was 0 and numberColumnCuts was nonzero. That might + explain the memory fault noted in the comment by AJK. + Unfortunately, just commenting out the delete[] results in massive memory + leaks. Try a revision to separate the row cut case. Why do we need + addCuts at all? A typing issue, apparently: OsiCut vs. OsiRowCut. - TODO: It looks to me as if numberToAdd and numberRowCuts are identical at - this point. Confirm & get rid of one of them. + TODO: It looks to me as if numberToAdd and numberRowCuts are identical + at this point. Confirm & get rid of one of them. TODO: Any reason why the three loops can't be consolidated? */ @@ -9181,32 +9213,32 @@ bool CbcModel::solveWithCuts(OsiCuts &cuts, int numberTries, CbcNode *node) whichGenerator[i] = 90; } if ((specialOptions_ & 262144) != 0 && !parentModel_) { - //save + // save for (i = 0; i < numberToAdd; i++) storedRowCuts_->addCut(*addCuts[i]); } solver_->applyRowCuts(numberToAdd, addCuts); - CoinWarmStartBasis *basis = dynamic_cast< CoinWarmStartBasis * >(solver_->getWarmStart()); + CoinWarmStartBasis *basis = + dynamic_cast(solver_->getWarmStart()); assert(basis != NULL); // make sure not volume /* dylp bug - Consistent size used by OsiDylp as sanity check. Implicit resize seen - as an error. Hence this call to resize is necessary. + Consistent size used by OsiDylp as sanity check. Implicit + resize seen as an error. Hence this call to resize is necessary. */ basis->resize(numberRowsAtStart + numberNewCuts_, numberColumns); for (i = 0; i < numberToAdd; i++) { - basis->setArtifStatus(numberRowsNow + i, - CoinWarmStartBasis::basic); + basis->setArtifStatus(numberRowsNow + i, CoinWarmStartBasis::basic); } if (solver_->setWarmStart(basis) == false) { throw CoinError("Fail setWarmStart() after cut installation.", - "solveWithCuts", "CbcModel"); + "solveWithCuts", "CbcModel"); } delete basis; } - //solver_->setHintParam(OsiDoDualInResolve,false,OsiHintTry); + // solver_->setHintParam(OsiDoDualInResolve,false,OsiHintTry); feasible = (resolve(node ? node->nodeInfo() : NULL, 2) != 0); - //solver_->setHintParam(OsiDoDualInResolve,true,OsiHintTry); + // solver_->setHintParam(OsiDoDualInResolve,true,OsiHintTry); if (maximumSecondsReached()) { numberTries = -1000; // exit feasible = false; @@ -9215,7 +9247,7 @@ bool CbcModel::solveWithCuts(OsiCuts &cuts, int numberTries, CbcNode *node) } #ifdef CBC_DEBUG printf("Obj value after cuts %g %d rows\n", solver_->getObjValue(), - solver_->getNumRows()); + solver_->getNumRows()); if (onOptimalPath && !solver_->isDualObjectiveLimitReached()) assert(feasible); #endif @@ -9227,44 +9259,46 @@ bool CbcModel::solveWithCuts(OsiCuts &cuts, int numberTries, CbcNode *node) numberTries = 0; } /* - If the problem is still feasible, first, call takeOffCuts() to remove cuts - that are now slack. takeOffCuts() will call the solver to reoptimise if - that's needed to restore a valid solution. + If the problem is still feasible, first, call takeOffCuts() to remove + cuts that are now slack. takeOffCuts() will call the solver to reoptimise + if that's needed to restore a valid solution. Next, see if we should quit due to diminishing returns: * we've tried three rounds of cut generation and we're getting insufficient improvement in the objective; or * we generated no cuts; or - * the solver declared optimality with 0 iterations after we added the - cuts generated in this round. - If we decide to keep going, prep for the next iteration. + * the solver declared optimality with 0 iterations after we added + the cuts generated in this round. If we decide to keep going, prep for + the next iteration. - It just seems more safe to tell takeOffCuts() to call resolve(), even if - we're not continuing cut generation. Otherwise code executed between here - and final disposition of the node will need to be careful not to access the - lp solution. It can happen that we lose feasibility in takeOffCuts --- - numerical jitters when the cutoff bound is epsilon less than the current - best, and we're evaluating an alternative optimum. + It just seems more safe to tell takeOffCuts() to call resolve(), even + if we're not continuing cut generation. Otherwise code executed between + here and final disposition of the node will need to be careful not to + access the lp solution. It can happen that we lose feasibility in + takeOffCuts --- numerical jitters when the cutoff bound is epsilon less + than the current best, and we're evaluating an alternative optimum. TODO: After successive rounds of code motion, there seems no need to - distinguish between the two checks for aborting the cut generation - loop. Confirm and clean up. + distinguish between the two checks for aborting the cut + generation loop. Confirm and clean up. */ if (feasible) { int cutIterations = solver_->getIterationCount(); - if (numberOldActiveCuts_ + numberNewCuts_ - && (numberNewCuts_ || doCutsNow(1))) { + if (numberOldActiveCuts_ + numberNewCuts_ && + (numberNewCuts_ || doCutsNow(1))) { OsiCuts *saveCuts = node ? NULL : &slackCuts; - int nDel = takeOffCuts(cuts, resolveAfterTakeOffCuts_, saveCuts, numberToAdd, addCuts); + int nDel = takeOffCuts(cuts, resolveAfterTakeOffCuts_, saveCuts, + numberToAdd, addCuts); if (nDel) lastNumberCuts2_ = 0; - if (solver_->isDualObjectiveLimitReached() && resolveAfterTakeOffCuts_) { + if (solver_->isDualObjectiveLimitReached() && + resolveAfterTakeOffCuts_) { feasible = false; #ifdef CBC_DEBUG double z = solver_->getObjValue(); double cut = getCutoff(); printf("Lost feasibility by %g in takeOffCuts; z = %g, cutoff = %g\n", - z - cut, z, cut); + z - cut, z, cut); #endif } } @@ -9273,8 +9307,9 @@ bool CbcModel::solveWithCuts(OsiCuts &cuts, int numberTries, CbcNode *node) numberRowsAtStart = numberOldActiveCuts_ + numberRowsAtContinuous_; lastNumberCuts = numberNewCuts_; double thisObj = direction * solver_->getObjValue(); - bool badObj = (allowZeroIterations) ? thisObj < cut_obj[0] + minimumDrop - : thisObj < cut_obj[CUT_HISTORY - 1] + minimumDrop; + bool badObj = (allowZeroIterations) + ? thisObj < cut_obj[0] + minimumDrop + : thisObj < cut_obj[CUT_HISTORY - 1] + minimumDrop; #ifdef JJF_ZERO // probably not a good idea if (!badObj) numberLastAttempts = CoinMax(0, numberLastAttempts - 1); @@ -9299,7 +9334,8 @@ bool CbcModel::solveWithCuts(OsiCuts &cuts, int numberTries, CbcNode *node) if (thisObj - cut_obj[j] < test) { nBadPasses++; } else { - goodDrop = (thisObj - cut_obj[j]) / static_cast< double >(nBadPasses + 1); + goodDrop = (thisObj - cut_obj[j]) / + static_cast(nBadPasses + 1); break; } } @@ -9308,10 +9344,11 @@ bool CbcModel::solveWithCuts(OsiCuts &cuts, int numberTries, CbcNode *node) badObj = false; // carry on } else { // Experimental escape calculations - //if (currentPassNumber_==13||currentPassNumber_>50) - //minimumDrop = CoinMax(1.5*minimumDrop,1.0e-5*fabs(thisObj)); + // if (currentPassNumber_==13||currentPassNumber_>50) + // minimumDrop = CoinMax(1.5*minimumDrop,1.0e-5*fabs(thisObj)); double test = 0.1 * minimumDrop; - double goodDrop = (thisObj - cut_obj[0]) / static_cast< double >(CUT_HISTORY); + double goodDrop = + (thisObj - cut_obj[0]) / static_cast(CUT_HISTORY); double objValue = thisObj; for (int j = CUT_HISTORY - 1; j >= 0; j--) { if (objValue - cut_obj[j] < test) { @@ -9323,11 +9360,11 @@ bool CbcModel::solveWithCuts(OsiCuts &cuts, int numberTries, CbcNode *node) } #if CBC_USEFUL_PRINTING > 12 if (!parentModel_ && !numberNodes_) - printf("badObj %s nBad %d maxBad %d goodDrop %g minDrop %g thisDrop %g obj %g\n", - badObj ? "true" : "false", - nBadPasses, maximumBadPasses, goodDrop, minimumDrop, - thisObj - cut_obj[CUT_HISTORY - 1], - solver_->getObjValue()); + printf("badObj %s nBad %d maxBad %d goodDrop %g minDrop %g " + "thisDrop %g obj %g\n", + badObj ? "true" : "false", nBadPasses, maximumBadPasses, + goodDrop, minimumDrop, thisObj - cut_obj[CUT_HISTORY - 1], + solver_->getObjValue()); #endif maximumBadPasses = CoinMax(maximumBadPasses, nBadPasses); if (nBadPasses < 2 || goodDrop > 2.0 * minimumDrop) { @@ -9338,14 +9375,16 @@ bool CbcModel::solveWithCuts(OsiCuts &cuts, int numberTries, CbcNode *node) numberLastAttempts++; } } - // magic numbers, they seemed reasonable; there's a possibility here of going more than - // nominal number of passes if we're doing really well. + // magic numbers, they seemed reasonable; there's a possibility here of + // going more than nominal number of passes if we're doing really well. if (numberTries == 1 && currentDepth_ < 12 && currentPassNumber_ < 10) { - double drop[12] = { 1.0, 2.0, 3.0, 10.0, 10.0, 10.0, 10.0, 20.0, 100.0, 100.0, 1000.0, 1000.0 }; + double drop[12] = {1.0, 2.0, 3.0, 10.0, 10.0, 10.0, + 10.0, 20.0, 100.0, 100.0, 1000.0, 1000.0}; if (thisObj - lastObjective > drop[currentDepth_] * minimumDrop) { numberTries++; #if CBC_USEFUL_PRINTING > 1 - //printf("drop %g %g %d\n",thisObj,lastObjective,currentPassNumber_); + // printf("drop %g %g + // %d\n",thisObj,lastObjective,currentPassNumber_); #endif } } @@ -9355,18 +9394,27 @@ bool CbcModel::solveWithCuts(OsiCuts &cuts, int numberTries, CbcNode *node) bool allowEarlyTermination = currentPassNumber_ >= 10; if (currentDepth_ > 10 || (currentDepth_ > 5 && numberColumns > 200)) allowEarlyTermination = true; - //if (badObj && (currentPassNumber_ >= 10 || (currentDepth_>10)) - if (badObj && allowEarlyTermination - //&&(currentPassNumber_>=10||lastObjective>firstObjective) - && !keepGoing) { + // if (badObj && (currentPassNumber_ >= 10 || (currentDepth_>10)) + if (badObj && + allowEarlyTermination + //&&(currentPassNumber_>=10||lastObjective>firstObjective) + && !keepGoing) { numberTries = 0; } - if (numberRowCuts + numberColumnCuts == 0 || (cutIterations == 0 && !allowZeroIterations)) { + if (numberRowCuts + numberColumnCuts == 0 || + (cutIterations == 0 && !allowZeroIterations)) { // maybe give it one more try if (numberLastAttempts > 2 || currentDepth_ || experimentBreak < 2) numberTries = 0; else numberLastAttempts++; + if (!currentDepth_ && (specialOptions_&2048)==0 && + (moreSpecialOptions2_&(7*33554432)) == 7*33554432 + && currentPassNumber_ < 99999) { + numberTries= 6; + //printf("Trying lagrangean\n"); + currentPassNumber_ += 100000; + } } if (numberTries > 0) { reducedCostFix(); @@ -9378,8 +9426,8 @@ bool CbcModel::solveWithCuts(OsiCuts &cuts, int numberTries, CbcNode *node) delete[] addCuts; } /* - We've lost feasibility --- this node won't be referencing the cuts we've - been collecting, so decrement the reference counts. + We've lost feasibility --- this node won't be referencing the cuts + we've been collecting, so decrement the reference counts. */ if (!feasible) { int i; @@ -9399,21 +9447,81 @@ bool CbcModel::solveWithCuts(OsiCuts &cuts, int numberTries, CbcNode *node) keepGoing = false; } if (numberRowCuts == 0 && numberColumnCuts == 0 && - (moreSpecialOptions2_&65536) !=0) { + (moreSpecialOptions2_ & 65536) != 0) { numberTries = 0; keepGoing = false; } - if (numberTries == 0 && feasible && !keepGoing && !parentModel_ && !numberNodes_) { + if (numberTries == 0 && feasible && !keepGoing && !parentModel_ && + !numberNodes_) { for (int i = 0; i < numberCutGenerators_; i++) { if (generator_[i]->whetherCallAtEnd() - && !generator_[i]->whetherInMustCallAgainMode()) { + && !generator_[i]->whetherInMustCallAgainMode() + && currentPassNumber_<9999) { // give it some goes and switch off numberTries = (saveNumberTries + 4) / 5; generator_[i]->setWhetherCallAtEnd(false); } } +#ifdef CBC_LAGRANGEAN_SOLVERS + if (!numberTries && (moreSpecialOptions2_&(268435456|536870912)) !=0) { + // one last go or one first go + int typeGo; + if ((moreSpecialOptions2_&536870912)!=0) { + moreSpecialOptions2_ &= ~536870912; + typeGo = 1; + } else { + typeGo = 2; + moreSpecialOptions2_ &= ~268435456; + } + OsiCuts cuts; + int numberNew = oneLastGoAtCuts(cuts,typeGo); + int numberColumnCuts = cuts.sizeColCuts(); + if (numberNew || numberColumnCuts) { + char printLine[100]; + sprintf(printLine,"%d row cuts and %d column cuts created by %s pass",numberNew,numberColumnCuts, typeGo ? "first" : "lagrangean"); + messageHandler()->message(CBC_FPUMP1, messages()) + << printLine << CoinMessageEol ; + } + if (numberColumnCuts) { + double integerTolerance = getDblParam(CbcIntegerTolerance); + for (int i = 0; i < numberColumnCuts; i++) { + const OsiColCut *thisCut = cuts.colCutPtr(i); + const CoinPackedVector &lbs = thisCut->lbs(); + const CoinPackedVector &ubs = thisCut->ubs(); + int j; + int n; + const int *which; + const double *values; + n = lbs.getNumElements(); + which = lbs.getIndices(); + values = lbs.getElements(); + for (j = 0; j < n; j++) { + int iColumn = which[j]; + solver_->setColLower(iColumn, values[j]); + } + n = ubs.getNumElements(); + which = ubs.getIndices(); + values = ubs.getElements(); + for (j = 0; j < n; j++) { + int iColumn = which[j]; + solver_->setColUpper(iColumn, values[j]); + } + } + } + if (typeGo==2) { + if (numberNew) { + // add to global cuts + for (int i=0;i 0 || keepGoing) && (!this->maximumSecondsReached()) ); + } while ((numberTries > 0 || keepGoing) && (!this->maximumSecondsReached())); /* End cut generation loop. */ @@ -9422,12 +9530,13 @@ bool CbcModel::solveWithCuts(OsiCuts &cuts, int numberTries, CbcNode *node) for (int i = 0; i < numberCutGenerators_; i++) generator_[i]->setSwitchedOff(false); } - //check feasibility. - //If solution seems to be integer feasible calling setBestSolution - //will eventually add extra global cuts which we need to install at - //the nodes + // check feasibility. + // If solution seems to be integer feasible calling setBestSolution + // will eventually add extra global cuts which we need to install at + // the nodes - if (feasible && solverCharacteristics_->solutionAddsCuts()) { //check integer feasibility + if (feasible && + solverCharacteristics_->solutionAddsCuts()) { // check integer feasibility bool integerFeasible = true; const double *save = testSolution_; testSolution_ = solver_->getColSolution(); @@ -9439,21 +9548,21 @@ bool CbcModel::solveWithCuts(OsiCuts &cuts, int numberTries, CbcNode *node) integerFeasible = false; } testSolution_ = save; - // Consider the possibility that some alternatives here only make sense in context - // of bonmin. - if (integerFeasible) { //update + // Consider the possibility that some alternatives here only make sense in + // context of bonmin. + if (integerFeasible) { // update double objValue = solver_->getObjValue(); int numberGlobalBefore = globalCuts_.sizeRowCuts(); // SOLUTION2 so won't up cutoff or print message - setBestSolution(CBC_SOLUTION2, objValue, - solver_->getColSolution(), 0); + setBestSolution(CBC_SOLUTION2, objValue, solver_->getColSolution(), 0); int numberGlobalAfter = globalCuts_.sizeRowCuts(); int numberToAdd = numberGlobalAfter - numberGlobalBefore; if (numberToAdd > 0) - //We have added some cuts say they are tight at that node - //Basis and lp should already have been updated + // We have added some cuts say they are tight at that node + // Basis and lp should already have been updated { - feasible = (solver_->isProvenOptimal() && !solver_->isDualObjectiveLimitReached()); + feasible = (solver_->isProvenOptimal() && + !solver_->isDualObjectiveLimitReached()); if (feasible) { int numberCuts = numberNewCuts_ = cuts.sizeRowCuts(); // possibly extend whichGenerator @@ -9469,13 +9578,14 @@ bool CbcModel::solveWithCuts(OsiCuts &cuts, int numberTries, CbcNode *node) #endif } numberNewCuts_ = lastNumberCuts + numberToAdd; - //now take off the cuts which are not tight anymore + // now take off the cuts which are not tight anymore takeOffCuts(cuts, resolveAfterTakeOffCuts_, NULL); - if (solver_->isDualObjectiveLimitReached() && resolveAfterTakeOffCuts_) { + if (solver_->isDualObjectiveLimitReached() && + resolveAfterTakeOffCuts_) { feasible = false; } } - if (!feasible) { //node will be fathomed + if (!feasible) { // node will be fathomed lockThread(); for (int i = 0; i < currentNumberCuts_; i++) { // take off node @@ -9491,11 +9601,11 @@ bool CbcModel::solveWithCuts(OsiCuts &cuts, int numberTries, CbcNode *node) } } /* - End of code block to check for a solution, when cuts may be added as a result - of a feasible solution. + End of code block to check for a solution, when cuts may be added as a + result of a feasible solution. - Reduced cost fix at end. Must also check feasible, in case we've popped out - because a generator indicated we're infeasible. + Reduced cost fix at end. Must also check feasible, in case we've popped + out because a generator indicated we're infeasible. */ if (feasible && solver_->isProvenOptimal()) reducedCostFix(); @@ -9505,13 +9615,14 @@ bool CbcModel::solveWithCuts(OsiCuts &cuts, int numberTries, CbcNode *node) int numberRows = solver_->getNumRows(); int numberAdded = numberRows - numberRowsAtContinuous_; if (numberAdded) { - CoinWarmStartBasis *basis = dynamic_cast< CoinWarmStartBasis * >(solver_->getWarmStart()); + CoinWarmStartBasis *basis = + dynamic_cast(solver_->getWarmStart()); assert(basis != NULL); int *added = new int[numberAdded]; int nDelete = 0; for (int j = numberRowsAtContinuous_; j < numberRows; j++) { if (basis->getArtifStatus(j) == CoinWarmStartBasis::basic) { - //printf("%d slack!\n",j); + // printf("%d slack!\n",j); added[nDelete++] = j; } } @@ -9535,8 +9646,7 @@ bool CbcModel::solveWithCuts(OsiCuts &cuts, int numberTries, CbcNode *node) continue; // see if heuristic will do anything double saveValue = heuristicValue; - int ifSol = heuristic_[i]->solution(heuristicValue, - newSolution); + int ifSol = heuristic_[i]->solution(heuristicValue, newSolution); if (ifSol > 0) { // better solution found heuristic_[i]->incrementNumberSolutionsFound(); @@ -9544,8 +9654,8 @@ bool CbcModel::solveWithCuts(OsiCuts &cuts, int numberTries, CbcNode *node) incrementUsed(newSolution); lastHeuristic_ = heuristic_[found]; #ifdef HEURISTIC_INFORM - printf("HEUR %s where %d B\n", - lastHeuristic_->heuristicName(), whereFrom); + printf("HEUR %s where %d B\n", lastHeuristic_->heuristicName(), + whereFrom); #endif setBestSolution(CBC_ROUNDING, heuristicValue, newSolution); whereFrom |= 8; // say solution found @@ -9562,10 +9672,10 @@ bool CbcModel::solveWithCuts(OsiCuts &cuts, int numberTries, CbcNode *node) } // Up change due to cuts if (feasible) - sumChangeObjective2_ += solver_->getObjValue() * solver_->getObjSense() - - objectiveValue; - //if ((numberNodes_%100)==0) - //printf("XXb sum obj changed by %g\n",sumChangeObjective2_); + sumChangeObjective2_ += + solver_->getObjValue() * solver_->getObjSense() - objectiveValue; + // if ((numberNodes_%100)==0) + // printf("XXb sum obj changed by %g\n",sumChangeObjective2_); /* End of cut generation loop. @@ -9578,12 +9688,11 @@ bool CbcModel::solveWithCuts(OsiCuts &cuts, int numberTries, CbcNode *node) specify that the frequency is adjustable. During cut generation, we recorded the number of cuts produced by each - generator for this node. For all cuts, whichGenerator records the generator - that produced a cut. + generator for this node. For all cuts, whichGenerator records the + generator that produced a cut. - TODO: All this should probably be hidden in a method of the CbcCutGenerator - class. - lh: + TODO: All this should probably be hidden in a method of the + CbcCutGenerator class. lh: TODO: Can the loop that scans over whichGenerator to accumulate per generator counts be replaced by values in countRowCuts and countColumnCuts? @@ -9608,8 +9717,12 @@ bool CbcModel::solveWithCuts(OsiCuts &cuts, int numberTries, CbcNode *node) int fatherNum = (node == NULL) ? -1 : node->nodeNumber(); double value = (node == NULL) ? -1 : node->branchingObject()->value(); string bigOne = (solver_->getIterationCount() > 30) ? "*******" : ""; - string way = (node == NULL) ? "" : (node->branchingObject()->way()) == 1 ? "Down" : "Up"; - std::cout << "Node " << numberNodes_ << ", father " << fatherNum << ", #iterations " << solver_->getIterationCount() << ", sol value : " << solver_->getObjValue() << std::endl; + string way = (node == NULL) + ? "" + : (node->branchingObject()->way()) == 1 ? "Down" : "Up"; + std::cout << "Node " << numberNodes_ << ", father " << fatherNum + << ", #iterations " << solver_->getIterationCount() + << ", sol value : " << solver_->getObjValue() << std::endl; #endif if (fullScan && numberCutGenerators_) { /* If cuts just at root node then it will probably be faster to @@ -9618,23 +9731,28 @@ bool CbcModel::solveWithCuts(OsiCuts &cuts, int numberTries, CbcNode *node) double thisObjective = solver_->getObjValue() * direction; // get sizes int numberRowsAdded = solver_->getNumRows() - numberRowsAtStart; - CoinBigIndex numberElementsAdded = solver_->getNumElements() - numberElementsAtStart; - double densityOld = static_cast< double >(numberElementsAtStart) / static_cast< double >(numberRowsAtStart); - double densityNew = numberRowsAdded ? (static_cast< double >(numberElementsAdded)) / static_cast< double >(numberRowsAdded) - : 0.0; + CoinBigIndex numberElementsAdded = + solver_->getNumElements() - numberElementsAtStart; + double densityOld = static_cast(numberElementsAtStart) / + static_cast(numberRowsAtStart); + double densityNew = numberRowsAdded + ? (static_cast(numberElementsAdded)) / + static_cast(numberRowsAdded) + : 0.0; /* - If we're at the root, and we added cuts, and the cuts haven't changed the - objective, and the cuts resulted in a significant increase (> 20%) in nonzero - coefficients, do no cuts in the tree and ditch the current cuts. They're not - cost-effective. + If we're at the root, and we added cuts, and the cuts haven't changed + the objective, and the cuts resulted in a significant increase (> 20%) in + nonzero coefficients, do no cuts in the tree and ditch the current cuts. + They're not cost-effective. */ if (!numberNodes_) { if (!parentModel_) { - //printf("%d global cuts\n",globalCuts_.sizeRowCuts()) ; + // printf("%d global cuts\n",globalCuts_.sizeRowCuts()) ; if ((specialOptions_ & 1) != 0) { - //specialOptions_ &= ~1; + // specialOptions_ &= ~1; int numberCuts = globalCuts_.sizeRowCuts(); - const OsiRowCutDebugger *debugger = continuousSolver_->getRowCutDebugger(); + const OsiRowCutDebugger *debugger = + continuousSolver_->getRowCutDebugger(); if (debugger) { for (int i = 0; i < numberCuts; i++) { OsiRowCut *cut = globalCuts_.rowCutPtr(i); @@ -9643,22 +9761,22 @@ bool CbcModel::solveWithCuts(OsiCuts &cuts, int numberTries, CbcNode *node) continuousSolver_->writeMps("bad"); printf("BAD cut\n"); } - //CoinAssert (!debugger->invalidCut(*cut)); + // CoinAssert (!debugger->invalidCut(*cut)); } } } } - //solver_->writeMps("second"); + // solver_->writeMps("second"); if (numberRowsAdded) handler_->message(CBC_CUTS_STATS, messages_) - << numberRowsAdded - << densityNew - << CoinMessageEol; - if (thisObjective - startObjective < 1.0e-5 && numberElementsAdded > 0.2 * numberElementsAtStart) + << numberRowsAdded << densityNew << CoinMessageEol; + if (thisObjective - startObjective < 1.0e-5 && + numberElementsAdded > 0.2 * numberElementsAtStart) willBeCutsInTree = -1; int whenC = whenCuts_; if (whenC == 999999 || whenC == 999998) { - int size = continuousSolver_->getNumRows() + continuousSolver_->getNumCols(); + int size = + continuousSolver_->getNumRows() + continuousSolver_->getNumCols(); bool smallProblem = size <= 550; smallProblem = false; #if CBC_USEFUL_PRINTING > 1 @@ -9677,7 +9795,8 @@ bool CbcModel::solveWithCuts(OsiCuts &cuts, int numberTries, CbcNode *node) maximumCutPasses_ = CoinMax(maximumCutPasses_ >> 1, 1); } #ifdef JJF_ZERO - } else if (currentPassNumber_ < CoinMin(CoinAbs(maximumCutPassesAtRoot_), 8)) { + } else if (currentPassNumber_ < + CoinMin(CoinAbs(maximumCutPassesAtRoot_), 8)) { if (whenCuts_ == 999999) { whenCuts_ = 8000008; maximumCutPasses_ = 1; @@ -9685,7 +9804,8 @@ bool CbcModel::solveWithCuts(OsiCuts &cuts, int numberTries, CbcNode *node) whenCuts_ = 10000008; maximumCutPasses_ = 1; } - } else if (currentPassNumber_ < CoinMin(CoinAbs(maximumCutPassesAtRoot_), 50)) { + } else if (currentPassNumber_ < + CoinMin(CoinAbs(maximumCutPassesAtRoot_), 50)) { if (whenCuts_ == 999999) { whenCuts_ = 8000008; maximumCutPasses_ = 1; @@ -9716,7 +9836,8 @@ bool CbcModel::solveWithCuts(OsiCuts &cuts, int numberTries, CbcNode *node) } else { // Objective changed #ifdef JJF_ZERO - if (currentPassNumber_ < CoinMin(CoinAbs(maximumCutPassesAtRoot_), 8)) { + if (currentPassNumber_ < + CoinMin(CoinAbs(maximumCutPassesAtRoot_), 8)) { if (whenCuts_ == 999999) { whenCuts_ = 8000008; maximumCutPasses_ = 1; @@ -9724,7 +9845,8 @@ bool CbcModel::solveWithCuts(OsiCuts &cuts, int numberTries, CbcNode *node) whenCuts_ = 10000008; maximumCutPasses_ = 1; } - } else if (currentPassNumber_ < CoinMin(CoinAbs(maximumCutPassesAtRoot_), 50)) { + } else if (currentPassNumber_ < + CoinMin(CoinAbs(maximumCutPassesAtRoot_), 50)) { if (whenCuts_ == 999999) { whenCuts_ = 8000008; maximumCutPasses_ = 1; @@ -9734,7 +9856,7 @@ bool CbcModel::solveWithCuts(OsiCuts &cuts, int numberTries, CbcNode *node) } } else #endif - if (currentPassNumber_ < CoinAbs(maximumCutPassesAtRoot_)) { + if (currentPassNumber_ < CoinAbs(maximumCutPassesAtRoot_)) { if (whenCuts_ == 999999) { whenCuts_ = 8000008; if (!smallProblem) @@ -9759,36 +9881,40 @@ bool CbcModel::solveWithCuts(OsiCuts &cuts, int numberTries, CbcNode *node) whenCuts_ += 100000; //// end #if CBC_USEFUL_PRINTING > 1 - printf("changing whenCuts from %d to %d and cutPasses from %d to %d objchange %g\n", - whenC, whenCuts_, maxPass, maximumCutPasses_, thisObjective - startObjective); + printf("changing whenCuts from %d to %d and cutPasses from %d to %d " + "objchange %g\n", + whenC, whenCuts_, maxPass, maximumCutPasses_, + thisObjective - startObjective); #endif } } /* Noop block 071219. */ - if ((numberRowsAdded > 100 + 0.5 * numberRowsAtStart - || numberElementsAdded > 0.5 * numberElementsAtStart) - && (densityNew > 200.0 && numberRowsAdded > 100 && densityNew > 2.0 * densityOld)) { + if ((numberRowsAdded > 100 + 0.5 * numberRowsAtStart || + numberElementsAdded > 0.5 * numberElementsAtStart) && + (densityNew > 200.0 && numberRowsAdded > 100 && + densityNew > 2.0 * densityOld)) { // much bigger - //if (thisObjective-startObjective<0.1*fabs(startObjective)+1.0e-5) - //willBeCutsInTree=-1; - //printf("Cuts will be taken off , %d rows added with density %g\n", + // if (thisObjective-startObjective<0.1*fabs(startObjective)+1.0e-5) + // willBeCutsInTree=-1; + // printf("Cuts will be taken off , %d rows added with density %g\n", // numberRowsAdded,densityNew); } /* Noop block 071219. */ - if (densityNew > 100.0 && numberRowsAdded > 2 && densityNew > 2.0 * densityOld) { - //if (thisObjective-startObjective<0.1*fabs(startObjective)+1.0e-5) - //willBeCutsInTree=-2; - //printf("Density says no cuts ? , %d rows added with density %g\n", + if (densityNew > 100.0 && numberRowsAdded > 2 && + densityNew > 2.0 * densityOld) { + // if (thisObjective-startObjective<0.1*fabs(startObjective)+1.0e-5) + // willBeCutsInTree=-2; + // printf("Density says no cuts ? , %d rows added with density %g\n", // numberRowsAdded,densityNew); } // Root node or every so often - see what to turn off /* - Hmmm ... > -90 for any generator will overrule previous decision to do no - cuts in tree and delete existing cuts. + Hmmm ... > -90 for any generator will overrule previous decision to do + no cuts in tree and delete existing cuts. */ int i; for (i = 0; i < numberCutGenerators_; i++) { @@ -9798,10 +9924,28 @@ bool CbcModel::solveWithCuts(OsiCuts &cuts, int numberTries, CbcNode *node) } if (!numberNodes_) { handler_->message(CBC_ROOT, messages_) - << numberNewCuts_ - << startObjective << thisObjective - << currentPassNumber_ - << CoinMessageEol; + << numberNewCuts_ << startObjective << thisObjective + << currentPassNumber_%100000 << CoinMessageEol; +#ifdef CBC_NAMES_FOR_COMPARE + if ((specialOptions_&2048) == 0) { + OsiClpSolverInterface * solver = + dynamic_cast(solver_); + ClpSimplex * simplex = solver->getModelPtr(); + int numberRows = simplex->numberRows(); + int numberColumns = simplex->numberColumns(); + const double *lower = simplex->columnLower(); + const double *upper = simplex->columnUpper(); + int numberFixed = 0; + for (int i=0;iproblemName()!="") // skip if in multiple solvers + printf("CbC %s after cuts %d rows, %d columns fixed, obj %g\n", + simplex->problemName().c_str(),numberRows, + numberFixed,simplex->objectiveValue()); + } +#endif // do heuristics again! if feasibility pump still exists if ((specialOptions_ & 33554432) != 0 && !parentModel_) { specialOptions_ &= ~33554432; @@ -9809,14 +9953,16 @@ bool CbcModel::solveWithCuts(OsiCuts &cuts, int numberTries, CbcNode *node) } } /* - Count the number of cuts produced by each cut generator on this call. Not - clear to me that the accounting is equivalent here. whichGenerator_ records - the generator for column and row cuts. So unless numberNewCuts is row cuts - only, we're double counting for JUST_ACTIVE. Note too the multiplier applied - to column cuts. + Count the number of cuts produced by each cut generator on this call. + Not clear to me that the accounting is equivalent here. whichGenerator_ + records the generator for column and row cuts. So unless numberNewCuts is + row cuts only, we're double counting for JUST_ACTIVE. Note too the + multiplier applied to column cuts. */ if (!numberNodes_) { - double value = CoinMax(minimumDrop_, 0.005 * (thisObjective - startObjective) / static_cast< double >(currentPassNumber_)); + double value = + CoinMax(minimumDrop_, 0.005 * (thisObjective - startObjective) / + static_cast(currentPassNumber_)); if (numberColumns < 200) value = CoinMax(minimumDrop_, 0.1 * value); #if CBC_USEFUL_PRINTING > 1 @@ -9829,7 +9975,7 @@ bool CbcModel::solveWithCuts(OsiCuts &cuts, int numberTries, CbcNode *node) int numberActiveGenerators = 0; for (i = 0; i < numberNewCuts_; i++) { int iGenerator = whichGenerator_[i]; - //assert (iGenerator>=0); + // assert (iGenerator>=0); if (iGenerator >= 0) iGenerator = iGenerator % 10000; if (iGenerator >= 0 && iGenerator < numberCutGenerators_) @@ -9837,7 +9983,8 @@ bool CbcModel::solveWithCuts(OsiCuts &cuts, int numberTries, CbcNode *node) } // add in any active cuts if at root node (for multiple solvers) #ifdef CHECK_KNOWN_SOLUTION - if (onOptimalPath && (solver_->isDualObjectiveLimitReached() || !feasible)) { + if (onOptimalPath && + (solver_->isDualObjectiveLimitReached() || !feasible)) { printf("help 2\n"); } #endif @@ -9848,7 +9995,8 @@ bool CbcModel::solveWithCuts(OsiCuts &cuts, int numberTries, CbcNode *node) double totalCuts = 0.0; //#define JUST_ACTIVE for (i = 0; i < numberCutGenerators_; i++) { - if (generator_[i]->numberCutsInTotal() || generator_[i]->numberColumnCuts()) + if (generator_[i]->numberCutsInTotal() || + generator_[i]->numberColumnCuts()) numberActiveGenerators++; #ifdef JUST_ACTIVE double value = count[i]; @@ -9858,33 +10006,39 @@ bool CbcModel::solveWithCuts(OsiCuts &cuts, int numberTries, CbcNode *node) totalCuts += value; } /* - Open up a loop to step through the cut generators and decide what (if any) - adjustment should be made for calling frequency. + Open up a loop to step through the cut generators and decide what (if + any) adjustment should be made for calling frequency. */ int iProbing = -1; - double smallProblem = (0.2 * totalCuts) / static_cast< double >(numberActiveGenerators + 1.0e-100); + double smallProblem = + (0.2 * totalCuts) / + static_cast(numberActiveGenerators + 1.0e-100); for (i = 0; i < numberCutGenerators_; i++) { int howOften = generator_[i]->howOften(); /* Probing can be set to just do column cuts in treee. But if doing good then leave as on - Ok, let me try to explain this. rowCuts = 3 says do disaggregation (1<<0) and - coefficient (1<<1) cuts. But if the value is negative, there's code at the - entry to generateCuts, and generateCutsAndModify, that temporarily changes - the value to 4 (1<<2) if we're in a search tree. - - Which does nothing to explain this next bit. We set a boolean, convert - howOften to the code for `generate while objective is improving', and change - over to `do everywhere'. Hmmm ... now I write it out, this makes sense in the - context of the original comment. If we're doing well (objective improving) - we'll keep probing fully active. + Ok, let me try to explain this. rowCuts = 3 says do disaggregation + (1<<0) and coefficient (1<<1) cuts. But if the value is negative, + there's code at the entry to generateCuts, and generateCutsAndModify, + that temporarily changes the value to 4 (1<<2) if we're in a search + tree. + + Which does nothing to explain this next bit. We set a boolean, + convert howOften to the code for `generate while objective is + improving', and change over to `do everywhere'. Hmmm ... now I write it + out, this makes sense in the context of the original comment. If we're + doing well (objective improving) we'll keep probing fully active. */ bool probingWasOnBut = false; - CglProbing *probing = dynamic_cast< CglProbing * >(generator_[i]->generator()); + CglProbing *probing = + dynamic_cast(generator_[i]->generator()); if (probing && !numberNodes_) { if (generator_[i]->numberCutsInTotal()) { // If large number of probing - can be biased - smallProblem = (0.2 * (totalCuts - generator_[i]->numberCutsInTotal())) / static_cast< double >(numberActiveGenerators - 1 + 1.0e-100); + smallProblem = + (0.2 * (totalCuts - generator_[i]->numberCutsInTotal())) / + static_cast(numberActiveGenerators - 1 + 1.0e-100); } iProbing = i; if (probing->rowCuts() == -3) { @@ -9894,37 +10048,42 @@ bool CbcModel::solveWithCuts(OsiCuts &cuts, int numberTries, CbcNode *node) } } /* - Convert `as long as objective is improving' into `only at root' if we've - decided cuts just aren't worth it. + Convert `as long as objective is improving' into `only at root' if + we've decided cuts just aren't worth it. */ if (willBeCutsInTree < 0 && howOften == -98) howOften = -99; /* - And check to see if the objective is improving. But don't do the check if - the user has specified some minimum number of cuts. + And check to see if the objective is improving. But don't do the + check if the user has specified some minimum number of cuts. - This exclusion seems bogus, or at least counterintuitive. Why would a user - suspect that setting a minimum cut limit would invalidate the objective - check? Nor do I see the point in comparing the number of rows and columns - in the second test. + This exclusion seems bogus, or at least counterintuitive. Why + would a user suspect that setting a minimum cut limit would invalidate + the objective check? Nor do I see the point in comparing the number of + rows and columns in the second test. */ - if (!probing && howOften == -98 && !generator_[i]->numberShortCutsAtRoot() && generator_[i]->numberCutsInTotal()) { + if (!probing && howOften == -98 && + !generator_[i]->numberShortCutsAtRoot() && + generator_[i]->numberCutsInTotal()) { // switch off as no short cuts generated - //printf("Switch off %s?\n",generator_[i]->cutGeneratorName()); + // printf("Switch off %s?\n",generator_[i]->cutGeneratorName()); howOften = -99; } if (howOften == -98 && generator_[i]->switchOffIfLessThan() > 0) { - if (thisObjective - startObjective < 0.005 * fabs(startObjective) + 1.0e-5) + if (thisObjective - startObjective < + 0.005 * fabs(startObjective) + 1.0e-5) howOften = -99; // switch off - if (thisObjective - startObjective < 0.1 * fabs(startObjective) + 1.0e-5 - && 5 * solver_->getNumRows() < solver_->getNumCols()) + if (thisObjective - startObjective < + 0.1 * fabs(startObjective) + 1.0e-5 && + 5 * solver_->getNumRows() < solver_->getNumCols()) howOften = -99; // switch off } if (generator_[i]->maximumTries() != -1) howOften = CoinMin(howOften, -99); // switch off /* - Below -99, this generator is switched off. There's no need to consider - further. Then again, there was no point in persisting this far! + Below -99, this generator is switched off. There's no need to + consider further. Then again, there was no point in persisting this + far! */ if (howOften < -99) { // may have been switched off - report @@ -9935,18 +10094,13 @@ bool CbcModel::solveWithCuts(OsiCuts &cuts, int numberTries, CbcNode *node) average = generator_[i]->numberElementsInTotal(); average /= n; handler_->message(CBC_GENERATOR, messages_) - << i - << generator_[i]->cutGeneratorName() - << n - << average - << generator_[i]->numberColumnCuts() - << generator_[i]->numberCutsActive() - + generator_[i]->numberColumnCuts(); + << i << generator_[i]->cutGeneratorName() << n << average + << generator_[i]->numberColumnCuts() + << generator_[i]->numberCutsActive() + + generator_[i]->numberColumnCuts(); handler_->printing(generator_[i]->timing()) - << generator_[i]->timeInCutGenerator(); - handler_->message() - << -100 - << CoinMessageEol; + << generator_[i]->timeInCutGenerator(); + handler_->message() << -100 << CoinMessageEol; } } continue; @@ -9957,19 +10111,20 @@ bool CbcModel::solveWithCuts(OsiCuts &cuts, int numberTries, CbcNode *node) if (howOften < 0 || howOften >= 1000000) { if (!numberNodes_) { /* - If root only, or objective improvement but no cuts generated, switch off. If - it's just that the generator found no cuts at the root, give it one more - chance. + If root only, or objective improvement but no cuts + generated, switch off. If it's just that the generator found no + cuts at the root, give it one more chance. */ // If small number switch mostly off #ifdef JUST_ACTIVE double thisCuts = count[i] + 5.0 * generator_[i]->numberColumnCuts(); #else - double thisCuts = generator_[i]->numberCutsInTotal() + 5.0 * generator_[i]->numberColumnCuts(); + double thisCuts = generator_[i]->numberCutsInTotal() + + 5.0 * generator_[i]->numberColumnCuts(); #endif // Allow on smaller number if <-1 if (generator_[i]->switchOffIfLessThan() < 0) { - double multiplier[] = { 2.0, 5.0 }; + double multiplier[] = {2.0, 5.0}; int iSwitch = -generator_[i]->switchOffIfLessThan() - 1; assert(iSwitch >= 0 && iSwitch < 2); thisCuts *= multiplier[iSwitch]; @@ -9989,8 +10144,9 @@ bool CbcModel::solveWithCuts(OsiCuts &cuts, int numberTries, CbcNode *node) /* Not productive, but not zero either. */ - } else if ((thisCuts + generator_[i]->numberColumnCuts() < smallProblem) - && !generator_[i]->whetherToUse()) { + } else if ((thisCuts + generator_[i]->numberColumnCuts() < + smallProblem) && + !generator_[i]->whetherToUse()) { /* Not unadjustable every node, and not strong probing. */ @@ -9999,23 +10155,26 @@ bool CbcModel::solveWithCuts(OsiCuts &cuts, int numberTries, CbcNode *node) No depth spec, or not adjustable every node. */ if (generator_[i]->whatDepth() < 0 || howOften != -1) { - int k = static_cast< int >(sqrt(smallProblem / thisCuts)); + int k = static_cast(sqrt(smallProblem / thisCuts)); /* - Not objective improvement, set to new frequency, otherwise turn off. + Not objective improvement, set to new + frequency, otherwise turn off. */ if (howOften != -98) howOften = k + 1000000; else howOften = -100; /* - Depth spec, or adjustable every node. Force to unadjustable every node. + Depth spec, or adjustable every node. Force to + unadjustable every node. */ } else { howOften = 1; } /* - Unadjustable every node, or strong probing. Force unadjustable every node and - force not strong probing? I don't understand. + Unadjustable every node, or strong probing. Force + unadjustable every node and force not strong probing? I don't + understand. */ } else { howOften = 1; @@ -10023,12 +10182,15 @@ bool CbcModel::solveWithCuts(OsiCuts &cuts, int numberTries, CbcNode *node) probingWasOnBut = false; } /* - Productive cut generator. Say we'll do it every node, adjustable. But if the - objective isn't improving, restrict that to every fifth depth level - (whatDepth overrides howOften in generateCuts). + Productive cut generator. Say we'll do it every node, + adjustable. But if the objective isn't improving, restrict that + to every fifth depth level (whatDepth overrides howOften in + generateCuts). */ } else { - if (thisObjective - startObjective < 0.1 * fabs(startObjective) + 1.0e-5 && generator_[i]->whatDepth() < 0) + if (thisObjective - startObjective < + 0.1 * fabs(startObjective) + 1.0e-5 && + generator_[i]->whatDepth() < 0) generator_[i]->setWhatDepth(5); howOften = 1 + 1000000; } @@ -10036,26 +10198,28 @@ bool CbcModel::solveWithCuts(OsiCuts &cuts, int numberTries, CbcNode *node) /* End root actions. - sumChangeObjective2_ is the objective change due to cuts. If we're getting - much better results from branching over a large number of nodes, switch off - cuts. + sumChangeObjective2_ is the objective change due to cuts. If + we're getting much better results from branching over a large number + of nodes, switch off cuts. - Except it doesn't, really --- it just puts off the decision 'til the - next full scan, when it'll put it off again unless cuts look better. + Except it doesn't, really --- it just puts off the decision + 'til the next full scan, when it'll put it off again unless cuts look + better. */ // If cuts useless switch off - if (numberNodes_ >= 100000 && sumChangeObjective1_ > 2.0e2 * (sumChangeObjective2_ + 1.0e-12)) { + if (numberNodes_ >= 100000 && + sumChangeObjective1_ > 2.0e2 * (sumChangeObjective2_ + 1.0e-12)) { howOften = 1000000 + SCANCUTS; // wait until next time - //printf("switch off cut %d due to lack of use\n",i); + // printf("switch off cut %d due to lack of use\n",i); } } /* Ok, that's the frequency adjustment bit. - Now, if we're at the root, force probing back on at every node, for column - cuts at least, even if it looks useless for row cuts. Notice that if it - looked useful, the values set above mean we'll be doing strong probing in - the tree subject to objective improvement. + Now, if we're at the root, force probing back on at every node, + for column cuts at least, even if it looks useless for row cuts. Notice + that if it looked useful, the values set above mean we'll be doing + strong probing in the tree subject to objective improvement. */ if (!numberNodes_) { if (probingWasOnBut && howOften == -100) { @@ -10065,12 +10229,13 @@ bool CbcModel::solveWithCuts(OsiCuts &cuts, int numberTries, CbcNode *node) if (howOften == 1) generator_[i]->setWhatDepth(1); - if (howOften >= 0 && generator_[i]->generator()->mayGenerateRowCutsInTree()) + if (howOften >= 0 && + generator_[i]->generator()->mayGenerateRowCutsInTree()) willBeCutsInTree = 1; } /* - Set the new frequency in the generator. If this is an adjustable frequency, - use the value to set whatDepth. + Set the new frequency in the generator. If this is an adjustable + frequency, use the value to set whatDepth. Hey! Seems like this could override the user's depth setting. */ @@ -10088,7 +10253,7 @@ bool CbcModel::solveWithCuts(OsiCuts &cuts, int numberTries, CbcNode *node) int newFrequency = generator_[i]->howOften() % 1000000; // increment cut counts generator_[i]->incrementNumberCutsActive(count[i]); - CglStored *stored = dynamic_cast< CglStored * >(generator_[i]->generator()); + CglStored *stored = dynamic_cast(generator_[i]->generator()); if (stored && !generator_[i]->numberCutsInTotal()) continue; double average = 0.0; @@ -10099,19 +10264,15 @@ bool CbcModel::solveWithCuts(OsiCuts &cuts, int numberTries, CbcNode *node) } if (handler_->logLevel() > 1 || !numberNodes_) { handler_->message(CBC_GENERATOR, messages_) - << i - << generator_[i]->cutGeneratorName() - //<numberCutsInTotal()<numberColumnCuts() - << generator_[i]->numberCutsActive() - + generator_[i]->numberColumnCuts(); + << i + << generator_[i]->cutGeneratorName() + //<numberCutsInTotal()<numberColumnCuts() + << generator_[i]->numberCutsActive() + + generator_[i]->numberColumnCuts(); handler_->printing(!numberNodes_ && generator_[i]->timing()) - << generator_[i]->timeInCutGenerator(); - handler_->message() - << newFrequency - << CoinMessageEol; + << generator_[i]->timeInCutGenerator(); + handler_->message() << newFrequency << CoinMessageEol; } } /* @@ -10122,7 +10283,8 @@ bool CbcModel::solveWithCuts(OsiCuts &cuts, int numberTries, CbcNode *node) // save statistics for (i = 0; i < numberCutGenerators_; i++) { generator_[i]->setNumberCutsAtRoot(generator_[i]->numberCutsInTotal()); - generator_[i]->setNumberActiveCutsAtRoot(generator_[i]->numberCutsActive()); + generator_[i]->setNumberActiveCutsAtRoot( + generator_[i]->numberCutsActive()); } /* Garbage code 071219 @@ -10131,19 +10293,22 @@ bool CbcModel::solveWithCuts(OsiCuts &cuts, int numberTries, CbcNode *node) int howOften = iProbing >= 0 ? generator_[iProbing]->howOften() : 0; if ((howOften % 1000000) != 1) howOften = 0; - //if (howOften) { - //CglProbing * probing = dynamic_cast(generator_[iProbing]->generator()); + // if (howOften) { + // CglProbing * probing = + // dynamic_cast(generator_[iProbing]->generator()); //} howOften = 0; if (howOften) { COIN_DETAIL_PRINT(printf("** method 1\n")); - //CglProbing * probing = dynamic_cast(generator_[iProbing]->generator()); + // CglProbing * probing = + // dynamic_cast(generator_[iProbing]->generator()); generator_[iProbing]->setWhatDepth(1); // could set no row cuts - //if (thisObjective-startObjective<0.001*fabs(startObjective)+1.0e-5) + // if (thisObjective-startObjective<0.001*fabs(startObjective)+1.0e-5) // probing->setRowCuts(0); for (int i = 0; i < numberObjects_; i++) { - CbcSimpleIntegerDynamicPseudoCost *obj = dynamic_cast< CbcSimpleIntegerDynamicPseudoCost * >(object_[i]); + CbcSimpleIntegerDynamicPseudoCost *obj = + dynamic_cast(object_[i]); if (obj) obj->setMethod(1); } @@ -10153,17 +10318,18 @@ bool CbcModel::solveWithCuts(OsiCuts &cuts, int numberTries, CbcNode *node) /* End garbage code. - Now I've reached the problem area. This is a problem only at the root node, - so that should simplify the issue of finding a workable basis? Or maybe not. + Now I've reached the problem area. This is a problem only at the + root node, so that should simplify the issue of finding a workable + basis? Or maybe not. */ - if (willBeCutsInTree <= 0) { + if (willBeCutsInTree <= 0 && (moreSpecialOptions2_&16777216) ==0 ) { // Take off cuts cuts = OsiCuts(); numberNewCuts_ = 0; if (!willBeCutsInTree) { // update size of problem numberRowsAtContinuous_ = solver_->getNumRows(); - } else { + } else if ((moreSpecialOptions2_&16777216)==0) { // take off cuts int numberRows = solver_->getNumRows(); int numberAdded = numberRows - numberRowsAtContinuous_; @@ -10178,19 +10344,19 @@ bool CbcModel::solveWithCuts(OsiCuts &cuts, int numberTries, CbcNode *node) } } #ifdef CBC_HAS_CLP - OsiClpSolverInterface *clpSolver - = dynamic_cast< OsiClpSolverInterface * >(solver_); + OsiClpSolverInterface *clpSolver = + dynamic_cast(solver_); if (clpSolver) { // Maybe solver might like to know only column bounds will change - //int options = clpSolver->specialOptions(); - //clpSolver->setSpecialOptions(options|128); + // int options = clpSolver->specialOptions(); + // clpSolver->setSpecialOptions(options|128); clpSolver->synchronizeModel(); } #endif } else { #ifdef CBC_HAS_CLP - OsiClpSolverInterface *clpSolver - = dynamic_cast< OsiClpSolverInterface * >(solver_); + OsiClpSolverInterface *clpSolver = + dynamic_cast(solver_); if (clpSolver) { // make sure factorization can't carry over int options = clpSolver->specialOptions(); @@ -10201,12 +10367,12 @@ bool CbcModel::solveWithCuts(OsiCuts &cuts, int numberTries, CbcNode *node) } } else { #ifdef CBC_HAS_CLP - OsiClpSolverInterface *clpSolver - = dynamic_cast< OsiClpSolverInterface * >(solver_); + OsiClpSolverInterface *clpSolver = + dynamic_cast(solver_); if (clpSolver) { // Maybe solver might like to know only column bounds will change - //int options = clpSolver->specialOptions(); - //clpSolver->setSpecialOptions(options|128); + // int options = clpSolver->specialOptions(); + // clpSolver->setSpecialOptions(options|128); clpSolver->synchronizeModel(); } #endif @@ -10230,9 +10396,10 @@ bool CbcModel::solveWithCuts(OsiCuts &cuts, int numberTries, CbcNode *node) #ifdef CHECK_CUT_COUNTS if (feasible) { - CoinWarmStartBasis *basis = dynamic_cast< CoinWarmStartBasis * >(solver_->getWarmStart()); + CoinWarmStartBasis *basis = + dynamic_cast(solver_->getWarmStart()); printf("solveWithCuts: Number of rows at end (only active cuts) %d\n", - numberRowsAtContinuous_ + numberNewCuts_ + numberOldActiveCuts_); + numberRowsAtContinuous_ + numberNewCuts_ + numberOldActiveCuts_); basis->print(); delete basis; } @@ -10264,8 +10431,8 @@ bool CbcModel::solveWithCuts(OsiCuts &cuts, int numberTries, CbcNode *node) } // Generate one round of cuts - serial mode -int CbcModel::serialCuts(OsiCuts &theseCuts, CbcNode *node, OsiCuts &slackCuts, int lastNumberCuts) -{ +int CbcModel::serialCuts(OsiCuts &theseCuts, CbcNode *node, OsiCuts &slackCuts, + int lastNumberCuts) { /* Is it time to scan the cuts in order to remove redundant cuts? If so, set up to do it. @@ -10277,7 +10444,7 @@ int CbcModel::serialCuts(OsiCuts &theseCuts, CbcNode *node, OsiCuts &slackCuts, fullScan = 2; specialOptions_ &= ~256; // mark as full scan done } -#if 0 //def CBC_HAS_CLP +#if 0 // def CBC_HAS_CLP // check basis OsiClpSolverInterface * clpSolver = dynamic_cast (solver_); @@ -10304,18 +10471,25 @@ int CbcModel::serialCuts(OsiCuts &theseCuts, CbcNode *node, OsiCuts &slackCuts, int switchOff = (!doCutsNow(1) && !fullScan) ? 1 : 0; int status = 0; int i; - for (i = 0; i < numberCutGenerators_ && (!this->maximumSecondsReached()) ; i++) { +#ifdef CBC_LAGRANGEAN_SOLVERS + OsiSolverInterface *baseLagrangeanSolver = NULL; + OsiSolverInterface *cleanLagrangeanSolver = NULL; +#endif + for (i = 0; i < numberCutGenerators_ && (!this->maximumSecondsReached()); + i++) { int numberRowCutsBefore = theseCuts.sizeRowCuts(); int numberColumnCutsBefore = theseCuts.sizeColCuts(); int numberRowCutsAfter = numberRowCutsBefore; int numberColumnCutsAfter = numberColumnCutsBefore; /*printf("GEN %d %s switches %d\n", - i,generator_[i]->cutGeneratorName(), - generator_[i]->switches());*/ + i,generator_[i]->cutGeneratorName(), + generator_[i]->switches());*/ bool generate = generator_[i]->normal(); - // skip if not optimal and should be (maybe a cut generator has fixed variables) - if (generator_[i]->howOften() == -100 || (generator_[i]->needsOptimalBasis() && !solver_->basisIsAvailable()) - || generator_[i]->switchedOff()) + // skip if not optimal and should be (maybe a cut generator has fixed + // variables) + if (generator_[i]->howOften() <= -100 || + (generator_[i]->needsOptimalBasis() && !solver_->basisIsAvailable()) || + generator_[i]->switchedOff()) generate = false; if (switchOff && !generator_[i]->mustCallAgain()) { // switch off if default @@ -10330,29 +10504,46 @@ int CbcModel::serialCuts(OsiCuts &theseCuts, CbcNode *node, OsiCuts &slackCuts, const OsiRowCutDebugger *debugger = NULL; bool onOptimalPath = false; if (generate) { - bool mustResolve = generator_[i]->generateCuts(theseCuts, fullScan, solver_, node); +#ifndef CBC_LAGRANGEAN_SOLVERS + bool mustResolve = + generator_[i]->generateCuts(theseCuts, fullScan, solver_, node); +#else + bool mustResolve; + if (currentPassNumber_ < 99999) + mustResolve = + generator_[i]->generateCuts(theseCuts, fullScan, solver_, node); + else + mustResolve = + generator_[i]->generateCuts(theseCuts, fullScan, solver_, node, + &baseLagrangeanSolver, + &cleanLagrangeanSolver); +#endif numberRowCutsAfter = theseCuts.sizeRowCuts(); if (fullScan && generator_[i]->howOften() == 1000000 + SCANCUTS_PROBING) { - CglProbing *probing = dynamic_cast< CglProbing * >(generator_[i]->generator()); - if (probing && (numberRowCutsBefore < numberRowCutsAfter || numberColumnCutsBefore < theseCuts.sizeColCuts())) { + CglProbing *probing = + dynamic_cast(generator_[i]->generator()); + if (probing && (numberRowCutsBefore < numberRowCutsAfter || + numberColumnCutsBefore < theseCuts.sizeColCuts())) { // switch on generator_[i]->setHowOften(1); } } - if (numberRowCutsBefore < numberRowCutsAfter && generator_[i]->mustCallAgain() && status >= 0) + if (numberRowCutsBefore < numberRowCutsAfter && + generator_[i]->mustCallAgain() && status >= 0) /*printf("%s before %d after %d must %c atend %c off %c endmode %c\n", - generator_[i]->cutGeneratorName(), - numberRowCutsBefore,numberRowCutsAfter, - generator_[i]->mustCallAgain() ? 'Y': 'N', - generator_[i]->whetherCallAtEnd() ? 'Y': 'N', - generator_[i]->switchedOff() ? 'Y': 'N', - generator_[i]->whetherInMustCallAgainMode() ? 'Y': 'N');*/ - if (numberRowCutsBefore < numberRowCutsAfter && generator_[i]->mustCallAgain() && status >= 0) + generator_[i]->cutGeneratorName(), + numberRowCutsBefore,numberRowCutsAfter, + generator_[i]->mustCallAgain() ? 'Y': 'N', + generator_[i]->whetherCallAtEnd() ? 'Y': 'N', + generator_[i]->switchedOff() ? 'Y': 'N', + generator_[i]->whetherInMustCallAgainMode() ? 'Y': 'N');*/ + if (numberRowCutsBefore < numberRowCutsAfter && + generator_[i]->mustCallAgain() && status >= 0) status = 1; // say must go round // Check last cut to see if infeasible /* - The convention is that if the generator proves infeasibility, it should - return as its last cut something with lb > ub. + The convention is that if the generator proves infeasibility, it + should return as its last cut something with lb > ub. */ if (numberRowCutsBefore < numberRowCutsAfter) { const OsiRowCut *thisCut = theseCuts.rowCutPtr(numberRowCutsAfter - 1); @@ -10367,12 +10558,12 @@ int CbcModel::serialCuts(OsiCuts &theseCuts, CbcNode *node, OsiCuts &slackCuts, for (k = numberRowCutsBefore; k < numberRowCutsAfter; k++) { OsiRowCut thisCut = theseCuts.rowCut(k); /* check size of elements. - We can allow smaller but this helps debug generators as it - is unsafe to have small elements */ + We can allow smaller but this helps debug generators as + it is unsafe to have small elements */ int n = thisCut.row().getNumElements(); const int *column = thisCut.row().getIndices(); const double *element = thisCut.row().getElements(); - //assert (n); + // assert (n); for (int i = 0; i < n; i++) { double value = element[i]; assert(fabs(value) > 1.0e-12 && fabs(value) < 1.0e20); @@ -10409,8 +10600,10 @@ int CbcModel::serialCuts(OsiCuts &theseCuts, CbcNode *node, OsiCuts &slackCuts, if (debugger->invalidCut(thisCut)) { solver_->getRowCutDebuggerAlways()->printOptimalSolution(*solver_); solver_->writeMpsNative("badCut.mps", NULL, NULL, 2); - printf("Cut generator %d (%s) produced invalid cut (%dth in this go)\n", - i, generator_[i]->cutGeneratorName(), k - numberRowCutsBefore); + printf("Cut generator %d (%s) produced invalid cut (%dth in this " + "go)\n", + i, generator_[i]->cutGeneratorName(), + k - numberRowCutsBefore); const double *lower = getColLower(); const double *upper = getColUpper(); int numberColumns = solver_->getNumCols(); @@ -10427,17 +10620,19 @@ int CbcModel::serialCuts(OsiCuts &theseCuts, CbcNode *node, OsiCuts &slackCuts, /* The cut generator has done its thing, and maybe it generated some cuts. Do a bit of bookkeeping: load - whichGenerator[i] with the index of the generator responsible for a cut, - and place cuts flagged as global in the global cut pool for the model. + whichGenerator[i] with the index of the generator responsible for a + cut, and place cuts flagged as global in the global cut pool for the + model. - lastNumberCuts is the sum of cuts added in previous iterations; it's the - offset to the proper starting position in whichGenerator. + lastNumberCuts is the sum of cuts added in previous iterations; it's + the offset to the proper starting position in whichGenerator. */ int numberBefore = numberRowCutsBefore + lastNumberCuts; int numberAfter = numberRowCutsAfter + lastNumberCuts; // possibly extend whichGenerator resizeWhichGenerator(numberBefore, numberAfter); - if (!numberRowCutsAfter && !numberColumnCutsAfter && (moreSpecialOptions2_&65536)!=0) + if (!numberRowCutsAfter && !numberColumnCutsAfter && + (moreSpecialOptions2_ & 65536) != 0) break; int j; @@ -10490,7 +10685,7 @@ int CbcModel::serialCuts(OsiCuts &theseCuts, CbcNode *node, OsiCuts &slackCuts, } } for (j = numberColumnCutsBefore; j < numberColumnCutsAfter; j++) { - //whichGenerator_[numberBefore++] = i ; + // whichGenerator_[numberBefore++] = i ; const OsiColCut *thisCut = theseCuts.colCutPtr(j); if (thisCut->globallyValid()) { // fix @@ -10501,6 +10696,10 @@ int CbcModel::serialCuts(OsiCuts &theseCuts, CbcNode *node, OsiCuts &slackCuts, /* End of loop to run each cut generator. */ +#ifdef CBC_LAGRANGEAN_SOLVERS + delete baseLagrangeanSolver; + delete cleanLagrangeanSolver; +#endif if (status >= 0) { // delete null cuts int nCuts = theseCuts.sizeRowCuts(); @@ -10526,7 +10725,7 @@ int CbcModel::serialCuts(OsiCuts &theseCuts, CbcNode *node, OsiCuts &slackCuts, if (thisCut->violated(cbcColSolution_) > 100.0 * primalTolerance) { if (messageHandler()->logLevel() > 2) printf("Old cut added - violation %g\n", - thisCut->violated(cbcColSolution_)); + thisCut->violated(cbcColSolution_)); whichGenerator_[numberOld++] = 20097; theseCuts.insert(*thisCut); } @@ -10562,28 +10761,28 @@ int CbcModel::serialCuts(OsiCuts &theseCuts, CbcNode *node, OsiCuts &slackCuts, node. NOTE: In general, it's necessary to call resolve() after purging slack - cuts. Deleting constraints constitutes a change in the problem, and - an OSI is not required to maintain a valid solution when the problem - is changed. But ... it's really useful to maintain the active basis, - and the OSI is supposed to do that. (Yes, it's splitting hairs.) In - some places, it's possible to know that the solution will never be - consulted after this call, only the basis. (E.g., this routine is - called as a last act before generating info to place the node in the - live set.) For such use, set allowResolve to false. + cuts. Deleting constraints constitutes a change in the problem, and + an OSI is not required to maintain a valid solution when the problem + is changed. But ... it's really useful to maintain the active basis, + and the OSI is supposed to do that. (Yes, it's splitting hairs.) In + some places, it's possible to know that the solution will never be + consulted after this call, only the basis. (E.g., this routine is + called as a last act before generating info to place the node in the + live set.) For such use, set allowResolve to false. TODO: No real harm would be done if we just ignored the rare occasion when - the call to resolve() pivoted a slack back into the basis. It's a - minor inefficiency, at worst. But it does break assertions which - check that there are no loose cuts in the basis. It might be better - to remove the assertions. + the call to resolve() pivoted a slack back into the basis. It's a + minor inefficiency, at worst. But it does break assertions which + check that there are no loose cuts in the basis. It might be better + to remove the assertions. */ -int CbcModel::takeOffCuts(OsiCuts &newCuts, - bool allowResolve, OsiCuts *saveCuts, - int numberNewCuts, const OsiRowCut **addedCuts) +int CbcModel::takeOffCuts(OsiCuts &newCuts, bool allowResolve, + OsiCuts *saveCuts, int numberNewCuts, + const OsiRowCut **addedCuts) { // int resolveIterations = 0 ; - if ((moreSpecialOptions2_&524288)!=0) + if ((moreSpecialOptions2_ & 524288) != 0) return 0; // leaving all root cuts int numberDropped = 0; int firstOldCut = numberRowsAtContinuous_; @@ -10596,29 +10795,29 @@ int CbcModel::takeOffCuts(OsiCuts &newCuts, //#define CBC_HAS_CLP_KEEP_STATUS #ifdef CBC_HAS_CLP_KEEP_STATUS int problemStatus = -1; - OsiClpSolverInterface *clpSolver - = dynamic_cast< OsiClpSolverInterface * >(solver_); + OsiClpSolverInterface *clpSolver = + dynamic_cast(solver_); if (clpSolver) problemStatus = clpSolver->getModelPtr()->status(); #endif bool needPurge = true; /* The outer loop allows repetition of purge in the event that reoptimisation - changes the basis. To start an iteration, clear the deletion counts and grab - the current basis. + changes the basis. To start an iteration, clear the deletion counts and + grab the current basis. */ while (needPurge) { int numberNewToDelete = 0; int numberOldToDelete = 0; int i; int kCut = 0; - ws = dynamic_cast< const CoinWarmStartBasis * >(solver_->getWarmStart()); + ws = dynamic_cast(solver_->getWarmStart()); /* - Scan the basis entries of the old cuts generated prior to this round of cut - generation. Loose cuts are `removed' by decrementing their reference count - and setting the addedCuts_ entry to NULL. (If the reference count falls to - 0, they're really deleted. See CbcModel and CbcCountRowCut doc'n for - principles of cut handling.) + Scan the basis entries of the old cuts generated prior to this round + of cut generation. Loose cuts are `removed' by decrementing their + reference count and setting the addedCuts_ entry to NULL. (If the + reference count falls to 0, they're really deleted. See CbcModel and + CbcCountRowCut doc'n for principles of cut handling.) */ int oldCutIndex = 0; if (numberOldActiveCuts_) { @@ -10629,7 +10828,9 @@ int CbcModel::takeOffCuts(OsiCuts &newCuts, oldCutIndex++; assert(oldCutIndex < currentNumberCuts_); // always leave if from nextRowCut_ - if (status == CoinWarmStartBasis::basic && (addedCuts_[oldCutIndex]->effectiveness() <= 1.0e10 || addedCuts_[oldCutIndex]->canDropCut(solver_, i + firstOldCut))) { + if (status == CoinWarmStartBasis::basic && + (addedCuts_[oldCutIndex]->effectiveness() <= 1.0e10 || + addedCuts_[oldCutIndex]->canDropCut(solver_, i + firstOldCut))) { solverCutIndices[numberOldToDelete++] = i + firstOldCut; if (saveCuts) { // send to cut pool @@ -10655,38 +10856,42 @@ int CbcModel::takeOffCuts(OsiCuts &newCuts, unlockThread(); } /* - Scan the basis entries of the new cuts generated with this round of cut - generation. At this point, newCuts is the only record of the new cuts, so - when we delete loose cuts from newCuts, they're really gone. newCuts is a - vector, so it's most efficient to compress it (eraseRowCut) from back to - front. + Scan the basis entries of the new cuts generated with this round of + cut generation. At this point, newCuts is the only record of the new + cuts, so when we delete loose cuts from newCuts, they're really gone. + newCuts is a vector, so it's most efficient to compress it (eraseRowCut) + from back to front. */ int firstNewCut = firstOldCut + numberOldActiveCuts_; int nCuts = newCuts.sizeRowCuts(); for (i = 0; i < nCuts; i++) { status = ws->getArtifStatus(i + firstNewCut); if (status == CoinWarmStartBasis::basic && - /*whichGenerator_[i]!=-2*/ newCuts.rowCutPtr(i)->effectiveness() < 1.0e20) { - solverCutIndices[numberNewToDelete + numberOldToDelete] = i + firstNewCut; + /*whichGenerator_[i]!=-2*/ newCuts.rowCutPtr(i)->effectiveness() < + 1.0e20) { + solverCutIndices[numberNewToDelete + numberOldToDelete] = + i + firstNewCut; newCutIndices[numberNewToDelete++] = i; } else { // save which generator did it - // 20098 means branch cut! assert (whichGenerator_[i]!=20098); // ?? what if it is - memory leak? + // 20098 means branch cut! assert (whichGenerator_[i]!=20098); // ?? + // what if it is - memory leak? whichGenerator_[kCut++] = whichGenerator_[i]; } } int baseRow = firstNewCut + nCuts; - //OsiRowCut ** mutableAdded = const_cast(addedCuts); + // OsiRowCut ** mutableAdded = const_cast(addedCuts); int numberTotalToDelete = numberNewToDelete + numberOldToDelete; for (i = 0; i < numberNewCuts; i++) { status = ws->getArtifStatus(i + baseRow); if (status != CoinWarmStartBasis::basic || - /*whichGenerator_[i+nCuts]==-2*/ addedCuts[i]->effectiveness() >= 1.0e20) { + /*whichGenerator_[i+nCuts]==-2*/ addedCuts[i]->effectiveness() >= + 1.0e20) { newCuts.insert(*addedCuts[i]); - //newCuts.insert(mutableAdded[i]) ; - //mutableAdded[i]=NULL; - //if (status == CoinWarmStartBasis::basic&&whichGenerator_[i]!=-2) { + // newCuts.insert(mutableAdded[i]) ; + // mutableAdded[i]=NULL; + // if (status == CoinWarmStartBasis::basic&&whichGenerator_[i]!=-2) { // save which generator did it - //whichGenerator_[k++] = whichGenerator_[i+nCuts] ; + // whichGenerator_[k++] = whichGenerator_[i+nCuts] ; //} } else { solverCutIndices[numberTotalToDelete++] = i + baseRow; @@ -10712,21 +10917,20 @@ int CbcModel::takeOffCuts(OsiCuts &newCuts, } } /* - Did we delete anything? If so, delete the cuts from the constraint system - held in the solver and reoptimise unless we're forbidden to do so. If the - call to resolve() results in pivots, there's the possibility we again have - basic slacks. Repeat the purging loop. + Did we delete anything? If so, delete the cuts from the constraint + system held in the solver and reoptimise unless we're forbidden to do so. + If the call to resolve() results in pivots, there's the possibility we + again have basic slacks. Repeat the purging loop. */ if (numberTotalToDelete > 0) { - solver_->deleteRows(numberTotalToDelete, - solverCutIndices); + solver_->deleteRows(numberTotalToDelete, solverCutIndices); numberDropped += numberTotalToDelete; numberNewCuts_ -= numberNewToDelete; assert(numberNewCuts_ == newCuts.sizeRowCuts()); numberOldActiveCuts_ -= numberOldToDelete; #ifdef CBC_DEBUG printf("takeOffCuts: purged %d+%d cuts\n", numberOldToDelete, - numberNewToDelete); + numberNewToDelete); #endif if (allowResolve) { phase_ = 3; @@ -10742,7 +10946,7 @@ int CbcModel::takeOffCuts(OsiCuts &newCuts, #ifdef CBC_DEBUG else { printf("Repeating purging loop. %d iters.\n", - solver_->getIterationCount()); + solver_->getIterationCount()); } #endif } else { @@ -10771,11 +10975,8 @@ int CbcModel::takeOffCuts(OsiCuts &newCuts, 0: infeasible -1: feasible and finished (do no more work on this subproblem) */ -int CbcModel::resolve(CbcNodeInfo *parent, int whereFrom, - double *saveSolution, - double *saveLower, - double *saveUpper) -{ +int CbcModel::resolve(CbcNodeInfo *parent, int whereFrom, double *saveSolution, + double *saveLower, double *saveUpper) { #ifdef CBC_STATISTICS void cbc_resolve_check(const OsiSolverInterface *solver); cbc_resolve_check(solver_); @@ -10800,8 +11001,8 @@ int CbcModel::resolve(CbcNodeInfo *parent, int whereFrom, feasible = false; } // Can't happen if strong branching as would have been found before - if ((!numberStrong_ || (moreSpecialOptions_ & 1073741824) != 0) - && numberObjects_ > numberIntegers_) { + if ((!numberStrong_ || (moreSpecialOptions_ & 1073741824) != 0) && + numberObjects_ > numberIntegers_) { int iColumn; int numberColumns = solver_->getNumCols(); const double *columnLower = solver_->getColLower(); @@ -10812,13 +11013,13 @@ int CbcModel::resolve(CbcNodeInfo *parent, int whereFrom, } } #ifdef CBC_HAS_CLP - OsiClpSolverInterface *clpSolver - = dynamic_cast< OsiClpSolverInterface * >(solver_); + OsiClpSolverInterface *clpSolver = + dynamic_cast(solver_); #endif /* - Reoptimize. Consider the possibility that we should fathom on bounds. But be - careful --- where the objective takes on integral values, we may want to keep - a solution where the objective is right on the cutoff. + Reoptimize. Consider the possibility that we should fathom on bounds. But + be careful --- where the objective takes on integral values, we may want to + keep a solution where the objective is right on the cutoff. */ if (feasible) { int nTightened = 0; @@ -10891,7 +11092,7 @@ int CbcModel::resolve(CbcNodeInfo *parent, int whereFrom, #endif } if (nTightened) { - //printf("%d bounds tightened\n",nTightened); + // printf("%d bounds tightened\n",nTightened); if ((specialOptions_ & 1) != 0 && onOptimalPath) { const OsiRowCutDebugger *debugger = solver_->getRowCutDebugger(); if (!debugger) { @@ -10899,7 +11100,7 @@ int CbcModel::resolve(CbcNodeInfo *parent, int whereFrom, solver_->getRowCutDebuggerAlways()->printOptimalSolution(*solver_); solver_->writeMpsNative("infeas4.mps", NULL, NULL, 2); printf("Not on optimalpath aaaa\n"); - //abort(); + // abort(); onOptimalPath = false; } } @@ -10908,18 +11109,20 @@ int CbcModel::resolve(CbcNodeInfo *parent, int whereFrom, if (nTightened >= 0) { resolve(solver_); numberIterations_ += solver_->getIterationCount(); - feasible = (solver_->isProvenOptimal() && !solver_->isDualObjectiveLimitReached()); + feasible = (solver_->isProvenOptimal() && + !solver_->isDualObjectiveLimitReached()); if (feasible) { // double check double testValue = solver_->getObjSense() * solver_->getObjValue(); - //double cutoff = getCutoff(); + // double cutoff = getCutoff(); if (bestObjective_ - getCutoffIncrement() < testValue) { #if CBC_USEFUL_PRINTING > 1 double value; solver_->getDblParam(OsiDualObjectiveLimit, value); - printf("Should cutoff as obj %.18g, best %.18g, inc %.18g - solver cutoff %.18g model cutoff %.18g\n", - testValue, bestObjective_, getCutoffIncrement(), - value, getCutoff()); + printf("Should cutoff as obj %.18g, best %.18g, inc %.18g - solver " + "cutoff %.18g model cutoff %.18g\n", + testValue, bestObjective_, getCutoffIncrement(), value, + getCutoff()); #endif feasible = false; } @@ -10951,10 +11154,12 @@ int CbcModel::resolve(CbcNodeInfo *parent, int whereFrom, double djValue = direction * dual[iRow]; double lowerValue = rowLower[iRow]; double upperValue = rowUpper[iRow]; - if (rowActivity[iRow] < lowerValue + primalTolerance && djValue > tolerance) { + if (rowActivity[iRow] < lowerValue + primalTolerance && + djValue > tolerance) { rowUpper[iRow] = lowerValue; assert(clpSimplex->getRowStatus(iRow) != ClpSimplex::basic); - } else if (rowActivity[iRow] > upperValue - primalTolerance && djValue < -tolerance) { + } else if (rowActivity[iRow] > upperValue - primalTolerance && + djValue < -tolerance) { rowLower[iRow] = upperValue; assert(clpSimplex->getRowStatus(iRow) != ClpSimplex::basic); } @@ -10969,10 +11174,12 @@ int CbcModel::resolve(CbcNodeInfo *parent, int whereFrom, double djValue = direction * reducedCost[iColumn]; double lowerValue = lower[iColumn]; double upperValue = upper[iColumn]; - if (solution[iColumn] < lowerValue + primalTolerance && djValue > tolerance) { + if (solution[iColumn] < lowerValue + primalTolerance && + djValue > tolerance) { objective[iColumn] = 1.0e8 * direction; assert(clpSimplex->getColumnStatus(iColumn) != ClpSimplex::basic); - } else if (solution[iColumn] > upperValue - primalTolerance && djValue < -tolerance) { + } else if (solution[iColumn] > upperValue - primalTolerance && + djValue < -tolerance) { objective[iColumn] = -1.0e8 * direction; assert(clpSimplex->getColumnStatus(iColumn) != ClpSimplex::basic); } else if (lowerValue > -1.0e20 || upperValue < 1.0e20) { @@ -10997,10 +11204,10 @@ int CbcModel::resolve(CbcNodeInfo *parent, int whereFrom, delete[] saveRowUpper; if (!someFree) { clpSimplex->primal(1); - //assert (clpSimplex->numberIterations()<10); + // assert (clpSimplex->numberIterations()<10); } - //clpSimplex->writeMps("xx"); - //clpSimplex->primal(1); + // clpSimplex->writeMps("xx"); + // clpSimplex->primal(1); clpSolver->setWarmStart(NULL); } #endif @@ -11009,9 +11216,9 @@ int CbcModel::resolve(CbcNodeInfo *parent, int whereFrom, // tighten did something??? solver_->getRowCutDebuggerAlways()->printOptimalSolution(*solver_); solver_->writeMpsNative("infeas4.mps", NULL, NULL, 2); - //assert (solver_->getRowCutDebugger()) ; + // assert (solver_->getRowCutDebugger()) ; printf("Not on optimalpath e\n"); - //abort(); + // abort(); } } } else { @@ -11047,7 +11254,7 @@ int CbcModel::resolve(CbcNodeInfo *parent, int whereFrom, } #ifdef JJF_ZERO if (cutModifier_ && feasible && !solverCharacteristics_->solutionAddsCuts()) { - //double increment = getDblParam(CbcModel::CbcCutoffIncrement) ; + // double increment = getDblParam(CbcModel::CbcCutoffIncrement) ; double cutoff; solver_->getDblParam(OsiDualObjectiveLimit, cutoff); double distance = fabs(cutoff - solver_->getObjValue()); @@ -11076,7 +11283,7 @@ int CbcModel::resolve(CbcNodeInfo *parent, int whereFrom, objValue += value * cost; value = fabs(cost) * multiplier; if (value < 2.1e9) { - int nearest = static_cast< int >(floor(value + 0.5)); + int nearest = static_cast(floor(value + 0.5)); assert(fabs(value - floor(value + 0.5)) < 1.0e-8); if (!increment) increment = nearest; @@ -11101,11 +11308,11 @@ int CbcModel::resolve(CbcNodeInfo *parent, int whereFrom, double x = objValue / value; x = ceil(x - 1.0e-5); x *= value; - //printf("fixed %g, variable %g -> %g, sum %g - cutoff %g\n", + // printf("fixed %g, variable %g -> %g, sum %g - cutoff %g\n", // objFixedValue,objValue,x,x+objFixedValue,cutoff); x += objFixedValue; if (x > cutoff + 1.0e-5 * fabs(cutoff) + 1.0e-5) { - //printf("Node cutoff\n"); + // printf("Node cutoff\n"); feasible = false; } } else { @@ -11115,7 +11322,7 @@ int CbcModel::resolve(CbcNodeInfo *parent, int whereFrom, x *= value; x += objFixedValue; if (x > cutoff + 1.0e-5 * fabs(cutoff) + 1.0e-5) { - //printf("Node cutoff\n"); + // printf("Node cutoff\n"); feasible = false; } } @@ -11130,7 +11337,8 @@ int CbcModel::resolve(CbcNodeInfo *parent, int whereFrom, assert(saveLower); assert(saveUpper); int numberColumns = solver_->getNumCols(); - memcpy(saveSolution, solver_->getColSolution(), numberColumns * sizeof(double)); + memcpy(saveSolution, solver_->getColSolution(), + numberColumns * sizeof(double)); reserveCurrentSolution(saveSolution); memcpy(saveLower, solver_->getColLower(), numberColumns * sizeof(double)); memcpy(saveUpper, solver_->getColUpper(), numberColumns * sizeof(double)); @@ -11185,11 +11393,8 @@ int CbcModel::resolve(CbcNodeInfo *parent, int whereFrom, Could use Probing at continuous to extend objects */ -CbcModel * -CbcModel::findCliques(bool makeEquality, - int atLeastThisMany, int lessThanThis, - int /*defaultValue*/) -{ +CbcModel *CbcModel::findCliques(bool makeEquality, int atLeastThisMany, + int lessThanThis, int /*defaultValue*/) { // No objects are allowed to exist assert(numberObjects_ == numberIntegers_ || !numberObjects_); CoinPackedMatrix matrixByRow(*solver_->getMatrixByRow()); @@ -11247,9 +11452,10 @@ CbcModel::findCliques(bool makeEquality, bool good = true; int slack = -1; /* - Does this row qualify? All variables must be binary and all coefficients - +/- 1.0. Variables with positive coefficients are recorded at the low end of - which, variables with negative coefficients the high end. + Does this row qualify? All variables must be binary and all + coefficients + +/- 1.0. Variables with positive coefficients are recorded at the low + end of which, variables with negative coefficients the high end. */ for (j = rowStart[iRow]; j < rowStart[iRow] + rowLength[iRow]; j++) { int iColumn = column[j]; @@ -11279,14 +11485,14 @@ CbcModel::findCliques(bool makeEquality, which[numberIntegers_ - numberM1] = iInteger; } } - int iUpper = static_cast< int >(floor(upperValue + 1.0e-5)); - int iLower = static_cast< int >(ceil(lowerValue - 1.0e-5)); + int iUpper = static_cast(floor(upperValue + 1.0e-5)); + int iLower = static_cast(ceil(lowerValue - 1.0e-5)); /* - What do we have? If the row upper bound is greater than 1-numberM1, this - isn't a clique. If the row upper bound is 1-numberM1, we have the classic - clique (an SOS1 on binary variables, if numberM1 = 0). If the upper bound - equals numberM1, we can fix all variables. If the upper bound is less than - numberM1, we're infeasible. + What do we have? If the row upper bound is greater than 1-numberM1, + this isn't a clique. If the row upper bound is 1-numberM1, we have the + classic clique (an SOS1 on binary variables, if numberM1 = 0). If the + upper bound equals numberM1, we can fix all variables. If the upper bound + is less than numberM1, we're infeasible. A similar analysis applies using numberP1 against the lower bound. */ @@ -11308,8 +11514,9 @@ CbcModel::findCliques(bool makeEquality, state = -3; } /* - What to do? If we learned nothing, move on to the next iteration. If we're - infeasible, we're outta here. If we decided we can fix variables, do it. + What to do? If we learned nothing, move on to the next iteration. If + we're infeasible, we're outta here. If we decided we can fix variables, + do it. */ if (good && state) { if (abs(state) == 3) { @@ -11324,20 +11531,20 @@ CbcModel::findCliques(bool makeEquality, for (i = 0; i < numberP1; i++) solver_->setColUpper(integerVariable_[which[i]], 0.0); for (i = 0; i < numberM1; i++) - solver_->setColLower(integerVariable_[which[numberIntegers_ - i - 1]], - 1.0); + solver_->setColLower( + integerVariable_[which[numberIntegers_ - i - 1]], 1.0); } else { // fix all +1 at 1, -1 at 0 for (i = 0; i < numberP1; i++) solver_->setColLower(integerVariable_[which[i]], 1.0); for (i = 0; i < numberM1; i++) - solver_->setColUpper(integerVariable_[which[numberIntegers_ - i - 1]], - 0.0); + solver_->setColUpper( + integerVariable_[which[numberIntegers_ - i - 1]], 0.0); } } else { /* - And the final case: we have a clique constraint. If it's within the allowed - size range, make a clique object. + And the final case: we have a clique constraint. If it's + within the allowed size range, make a clique object. */ int length = numberP1 + numberM1; if (length >= atLeastThisMany && length < lessThanThis) { @@ -11345,8 +11552,8 @@ CbcModel::findCliques(bool makeEquality, bool addOne = false; int objectType; /* - Choose equality (type 1) or inequality (type 0). If we're forcing equalities, - add a slack. + Choose equality (type 1) or inequality (type 0). If we're + forcing equalities, add a slack. */ if (iLower == iUpper) { objectType = 1; @@ -11361,11 +11568,11 @@ CbcModel::findCliques(bool makeEquality, } } /* - Record the strong values for the variables. Variables with positive - coefficients force all others when set to 1; variables with negative - coefficients force when set to 0. If the clique is formed against the row - lower bound, convert to the canonical form of a clique against the row - upper bound. + Record the strong values for the variables. Variables with + positive coefficients force all others when set to 1; variables + with negative coefficients force when set to 0. If the clique is + formed against the row lower bound, convert to the canonical form + of a clique against the row upper bound. */ if (state > 0) { totalP1 += numberP1; @@ -11398,9 +11605,9 @@ CbcModel::findCliques(bool makeEquality, } } } - object[numberCliques] = new CbcClique(this, objectType, numberP1, - which, type, - 1000000 + numberCliques, slack); + object[numberCliques] = + new CbcClique(this, objectType, numberP1, which, type, + 1000000 + numberCliques, slack); numberCliques++; } else if (numberP1 + numberM1 >= lessThanThis) { // too big @@ -11419,23 +11626,24 @@ CbcModel::findCliques(bool makeEquality, } else { if (numberCliques) printf("%d cliques of average size %g found, %d P1, %d M1\n", - numberCliques, - (static_cast< double >(totalP1 + totalM1)) / (static_cast< double >(numberCliques)), - totalP1, totalM1); + numberCliques, + (static_cast(totalP1 + totalM1)) / + (static_cast(numberCliques)), + totalP1, totalM1); else printf("No cliques found\n"); if (numberBig) - printf("%d large cliques ( >= %d) found, total %d\n", - numberBig, lessThanThis, totalBig); + printf("%d large cliques ( >= %d) found, total %d\n", numberBig, + lessThanThis, totalBig); if (numberFixed) printf("%d variables fixed\n", numberFixed); } #endif /* - If required, augment the constraint matrix with clique slacks. Seems like we - should be able to add the necessary integer objects without a complete - rebuild of existing integer objects, but I'd need to look further to confirm - that (lh, 071219). Finally, add the clique objects. + If required, augment the constraint matrix with clique slacks. Seems like + we should be able to add the necessary integer objects without a complete + rebuild of existing integer objects, but I'd need to look further to + confirm that (lh, 071219). Finally, add the clique objects. */ if (numberCliques > 0 && numberSlacks && makeEquality) { COIN_DETAIL_PRINT(printf("adding %d integer slacks\n", numberSlacks)); @@ -11467,7 +11675,7 @@ CbcModel::findCliques(bool makeEquality, newModel->numberObjects_ = 0; delete[] newModel->object_; newModel->object_ = NULL; - newModel->findIntegers(true); //Set up all integer objects + newModel->findIntegers(true); // Set up all integer objects for (i = 0; i < numberIntegers_; i++) { newModel->modifiableObject(i)->setPriority(object_[i]->priority()); } @@ -11475,7 +11683,8 @@ CbcModel::findCliques(bool makeEquality, // old model had originalColumns delete[] newModel->originalColumns_; newModel->originalColumns_ = new int[numberColumns + numberSlacks]; - memcpy(newModel->originalColumns_, originalColumns_, numberColumns * sizeof(int)); + memcpy(newModel->originalColumns_, originalColumns_, + numberColumns * sizeof(int)); // mark as not in previous model for (i = numberColumns; i < numberColumns + numberSlacks; i++) newModel->originalColumns_[i] = -1; @@ -11504,16 +11713,16 @@ CbcModel::findCliques(bool makeEquality, } } // Fill in useful estimates -void CbcModel::pseudoShadow(int iActive) -{ +void CbcModel::pseudoShadow(int iActive) { assert(iActive < 2 * 8 * 32 && iActive > -3); if (iActive == -1) { if (numberNodes_) { // zero out for (int i = 0; i < numberObjects_; i++) { - CbcSimpleIntegerDynamicPseudoCost *obj1 = dynamic_cast< CbcSimpleIntegerDynamicPseudoCost * >(object_[i]); + CbcSimpleIntegerDynamicPseudoCost *obj1 = + dynamic_cast(object_[i]); if (obj1) { - //assert (obj1->downShadowPrice()>0.0); + // assert (obj1->downShadowPrice()>0.0); #define P_FACTOR 1.0 #ifndef JJF_ONE obj1->setDownShadowPrice(-P_FACTOR * obj1->downShadowPrice()); @@ -11550,7 +11759,8 @@ void CbcModel::pseudoShadow(int iActive) // Column copy of matrix const double *element = solver_->getMatrixByCol()->getElements(); const int *row = solver_->getMatrixByCol()->getIndices(); - const CoinBigIndex *columnStart = solver_->getMatrixByCol()->getVectorStarts(); + const CoinBigIndex *columnStart = + solver_->getMatrixByCol()->getVectorStarts(); const int *columnLength = solver_->getMatrixByCol()->getVectorLengths(); const double *dual = solver_->getRowPrice(); const double *solution = solver_->getColSolution(); @@ -11589,7 +11799,8 @@ void CbcModel::pseudoShadow(int iActive) // A case 1: for (int iRow = 0; iRow < numberRows; iRow++) { - if (rowActivity[iRow] > rowUpper[iRow] - tolerance || rowActivity[iRow] < rowLower[iRow] + tolerance) { + if (rowActivity[iRow] > rowUpper[iRow] - tolerance || + rowActivity[iRow] < rowLower[iRow] + tolerance) { rowWeight[iRow] = 1.0; } } @@ -11695,8 +11906,8 @@ void CbcModel::pseudoShadow(int iActive) down[iColumn] = downValue; if (solver_->isInteger(iColumn)) { if (!numberNodes_ && handler_->logLevel() > 1) - printf("%d - up %g down %g cost %g\n", - iColumn, upValue, downValue, objective[iColumn]); + printf("%d - up %g down %g cost %g\n", iColumn, upValue, downValue, + objective[iColumn]); upSum += upValue; downSum += downValue; numberIntegers++; @@ -11731,8 +11942,8 @@ void CbcModel::pseudoShadow(int iActive) down[iColumn] = downValue; if (solver_->isInteger(iColumn)) { if (!numberNodes_ && handler_->logLevel() > 1) - printf("%d - up %g down %g cost %g\n", - iColumn, upValue, downValue, objective[iColumn]); + printf("%d - up %g down %g cost %g\n", iColumn, upValue, downValue, + objective[iColumn]); upSum += upValue; downSum += downValue; numberIntegers++; @@ -11781,16 +11992,17 @@ void CbcModel::pseudoShadow(int iActive) down[iColumn] = downValue; if (solver_->isInteger(iColumn)) { if (!numberNodes_ && handler_->logLevel() > 1) - printf("%d - dj %g up %g down %g cost %g\n", - iColumn, djValue, upValue, downValue, objective[iColumn]); + printf("%d - dj %g up %g down %g cost %g\n", iColumn, djValue, + upValue, downValue, objective[iColumn]); upSum += upValue; downSum += downValue; numberIntegers++; } } if (numberIntegers) { - double averagePrice = (0.5 * (upSum + downSum)) / static_cast< double >(numberIntegers); - //averagePrice *= 0.1; + double averagePrice = + (0.5 * (upSum + downSum)) / static_cast(numberIntegers); + // averagePrice *= 0.1; averagePrice *= 100.0; for (int iColumn = 0; iColumn < numberColumns; iColumn++) { double weight = columnWeight[iColumn]; @@ -11802,14 +12014,15 @@ void CbcModel::pseudoShadow(int iActive) delete[] rowWeight; delete[] columnWeight; if (numberIntegers) { - double smallDown = 0.0001 * (downSum / static_cast< double >(numberIntegers)); - double smallUp = 0.0001 * (upSum / static_cast< double >(numberIntegers)); + double smallDown = 0.0001 * (downSum / static_cast(numberIntegers)); + double smallUp = 0.0001 * (upSum / static_cast(numberIntegers)); #define PSEUDO_FACTOR 5.0e-1 double pseudoFactor = PSEUDO_FACTOR; - //if (!numberNodes_) - //pseudoFactor=0.0; + // if (!numberNodes_) + // pseudoFactor=0.0; for (int i = 0; i < numberObjects_; i++) { - CbcSimpleIntegerDynamicPseudoCost *obj1 = dynamic_cast< CbcSimpleIntegerDynamicPseudoCost * >(object_[i]); + CbcSimpleIntegerDynamicPseudoCost *obj1 = + dynamic_cast(object_[i]); if (obj1 && obj1->upShadowPrice() >= 0.0) { int iColumn = obj1->columnNumber(); double upPseudoCost = obj1->upDynamicPseudoCost(); @@ -11819,17 +12032,18 @@ void CbcModel::pseudoShadow(int iActive) upPseudoCost = CoinMax(upPseudoCost, 0.001 * down[iColumn]); obj1->setUpShadowPrice(upPseudoCost); if (upPseudoCost > saveUp && !numberNodes_ && handler_->logLevel() > 1) - printf("For %d up went from %g to %g\n", - iColumn, saveUp, upPseudoCost); + printf("For %d up went from %g to %g\n", iColumn, saveUp, + upPseudoCost); double downPseudoCost = obj1->downDynamicPseudoCost(); double saveDown = downPseudoCost; downPseudoCost = CoinMax(pseudoFactor * downPseudoCost, smallDown); downPseudoCost = CoinMax(downPseudoCost, down[iColumn]); downPseudoCost = CoinMax(downPseudoCost, 0.001 * up[iColumn]); obj1->setDownShadowPrice(downPseudoCost); - if (downPseudoCost > saveDown && !numberNodes_ && handler_->logLevel() > 1) - printf("For %d down went from %g to %g\n", - iColumn, saveDown, downPseudoCost); + if (downPseudoCost > saveDown && !numberNodes_ && + handler_->logLevel() > 1) + printf("For %d down went from %g to %g\n", iColumn, saveDown, + downPseudoCost); } } } @@ -11846,9 +12060,7 @@ void CbcModel::pseudoShadow(int iActive) quietly fail in several directions. */ -void CbcModel::passInPriorities(const int *priorities, - bool ifObject) -{ +void CbcModel::passInPriorities(const int *priorities, bool ifObject) { findIntegers(false); int i; if (priorities) { @@ -11865,15 +12077,13 @@ void CbcModel::passInPriorities(const int *priorities, } i1 = numberIntegers_ - 1; } - messageHandler()->message(CBC_PRIORITY, - messages()) - << i0 << i1 << numberObjects_ << CoinMessageEol; + messageHandler()->message(CBC_PRIORITY, messages()) + << i0 << i1 << numberObjects_ << CoinMessageEol; } } // Delete all object information -void CbcModel::deleteObjects(bool getIntegers) -{ +void CbcModel::deleteObjects(bool getIntegers) { if (ownObjects_) { int i; for (i = 0; i < numberObjects_; i++) @@ -11890,15 +12100,14 @@ void CbcModel::deleteObjects(bool getIntegers) Ensure all attached objects (OsiObjects, heuristics, and cut generators) point to this model. */ -void CbcModel::synchronizeModel() -{ +void CbcModel::synchronizeModel() { if (!numberObjects_) return; int i; for (i = 0; i < numberHeuristics_; i++) heuristic_[i]->setModel(this); for (i = 0; i < numberObjects_; i++) { - CbcObject *obj = dynamic_cast< CbcObject * >(object_[i]); + CbcObject *obj = dynamic_cast(object_[i]); if (obj) { obj->setModel(this); obj->setPosition(i); @@ -11908,14 +12117,16 @@ void CbcModel::synchronizeModel() generator_[i]->refreshModel(this); if (!solverCharacteristics_) { - OsiBabSolver *solverCharacteristics = dynamic_cast< OsiBabSolver * >(solver_->getAuxiliaryInfo()); + OsiBabSolver *solverCharacteristics = + dynamic_cast(solver_->getAuxiliaryInfo()); if (solverCharacteristics) { solverCharacteristics_ = solverCharacteristics; } else { // replace in solver OsiBabSolver defaultC; solver_->setAuxiliaryInfo(&defaultC); - solverCharacteristics_ = dynamic_cast< OsiBabSolver * >(solver_->getAuxiliaryInfo()); + solverCharacteristics_ = + dynamic_cast(solver_->getAuxiliaryInfo()); } } @@ -11943,8 +12154,7 @@ void CbcModel::synchronizeModel() I am going to re-order if necessary */ -void CbcModel::findIntegers(bool startAgain, int type) -{ +void CbcModel::findIntegers(bool startAgain, int type) { assert(solver_); /* No need to do this if we have previous information, unless forced to start @@ -11975,7 +12185,8 @@ void CbcModel::findIntegers(bool startAgain, int type) int iPriority = -100000; for (iObject = 0; iObject < numberObjects_; iObject++) { iPriority = CoinMax(iPriority, object_[iObject]->priority()); - CbcSimpleInteger *obj = dynamic_cast< CbcSimpleInteger * >(oldObject[iObject]); + CbcSimpleInteger *obj = + dynamic_cast(oldObject[iObject]); if (obj) { int iColumn = obj->columnNumber(); if (iColumn >= 0 && iColumn < numberColumns) @@ -11988,8 +12199,8 @@ void CbcModel::findIntegers(bool startAgain, int type) // See if there any SOS #ifdef CBC_HAS_CLP if (!nObjects) { - OsiClpSolverInterface *clpSolver - = dynamic_cast< OsiClpSolverInterface * >(solver_); + OsiClpSolverInterface *clpSolver = + dynamic_cast(solver_); if (clpSolver && (clpSolver->numberSOS() || clpSolver->numberObjects())) { // deal with sos const CoinSet *setInfo = clpSolver->setInfo(); @@ -12013,13 +12224,14 @@ void CbcModel::findIntegers(bool startAgain, int type) oldObject = new OsiObject *[numberObjects]; OsiObject **osiObjects = clpSolver->objects(); for (int i = 0; i < numberObjects; i++) { - OsiSOS *obj = dynamic_cast< OsiSOS * >(osiObjects[i]); + OsiSOS *obj = dynamic_cast(osiObjects[i]); if (obj) { int type = obj->setType(); int n = obj->numberMembers(); const int *which = obj->members(); const double *weights = obj->weights(); - oldObject[nObjects++] = new CbcSOS(this, n, which, weights, i, type); + oldObject[nObjects++] = + new CbcSOS(this, n, which, weights, i, type); } } } @@ -12048,7 +12260,8 @@ void CbcModel::findIntegers(bool startAgain, int type) if (!type) { object_[numberIntegers_] = new CbcSimpleInteger(this, iColumn); } else if (type == 1) { - object_[numberIntegers_] = new CbcSimpleIntegerPseudoCost(this, iColumn, 0.3); + object_[numberIntegers_] = + new CbcSimpleIntegerPseudoCost(this, iColumn, 0.3); } else if (type == 2) { object_[numberIntegers_] = new CbcSimpleInteger(this, iColumn); if (mark[iColumn]) { @@ -12072,15 +12285,16 @@ void CbcModel::findIntegers(bool startAgain, int type) /* If numberBeforeTrust >0 then we are going to use CbcBranchDynamic. Scan and convert CbcSimpleInteger objects */ -void CbcModel::convertToDynamic() -{ +void CbcModel::convertToDynamic() { int iObject; const double *cost = solver_->getObjCoefficients(); bool allDynamic = true; for (iObject = 0; iObject < numberObjects_; iObject++) { - CbcSimpleInteger *obj1 = dynamic_cast< CbcSimpleInteger * >(object_[iObject]); - CbcSimpleIntegerPseudoCost *obj1a = dynamic_cast< CbcSimpleIntegerPseudoCost * >(object_[iObject]); - CbcSimpleIntegerDynamicPseudoCost *obj2 = dynamic_cast< CbcSimpleIntegerDynamicPseudoCost * >(object_[iObject]); + CbcSimpleInteger *obj1 = dynamic_cast(object_[iObject]); + CbcSimpleIntegerPseudoCost *obj1a = + dynamic_cast(object_[iObject]); + CbcSimpleIntegerDynamicPseudoCost *obj2 = + dynamic_cast(object_[iObject]); if (obj1 && !obj2) { // replace int iColumn = obj1->columnNumber(); @@ -12101,23 +12315,26 @@ void CbcModel::convertToDynamic() downCost = obj1a->downPseudoCost(); } delete object_[iObject]; - CbcSimpleIntegerDynamicPseudoCost *newObject = new CbcSimpleIntegerDynamicPseudoCost(this, iColumn, 1.0e0 * downCost, 1.0e0 * upCost); - //newObject->setNumberBeforeTrust(numberBeforeTrust_); + CbcSimpleIntegerDynamicPseudoCost *newObject = + new CbcSimpleIntegerDynamicPseudoCost(this, iColumn, 1.0e0 * downCost, + 1.0e0 * upCost); + // newObject->setNumberBeforeTrust(numberBeforeTrust_); newObject->setPriority(priority); newObject->setPosition(iObject); newObject->setPreferredWay(preferredWay); object_[iObject] = newObject; } else if (!obj2) { - CbcObject *obj3 = dynamic_cast< CbcObject * >(object_[iObject]); + CbcObject *obj3 = dynamic_cast(object_[iObject]); if (!obj3 || !obj3->optionalObject()) allDynamic = false; } else { // synchronize trust - //obj2->setNumberBeforeTrust(numberBeforeTrust_); + // obj2->setNumberBeforeTrust(numberBeforeTrust_); } } if (branchingMethod_) { - if ((branchingMethod_->whichMethod() & 1) == 0 && !branchingMethod_->chooseMethod()) { + if ((branchingMethod_->whichMethod() & 1) == 0 && + !branchingMethod_->chooseMethod()) { // Need a method which can do better delete branchingMethod_; branchingMethod_ = NULL; @@ -12138,8 +12355,7 @@ void CbcModel::convertToDynamic() } #ifdef SWITCH_VARIABLES // Convert Dynamic to Switching -int CbcModel::findSwitching() -{ +int CbcModel::findSwitching() { if ((moreSpecialOptions2_ & 1) == 0) return 0; const CoinPackedMatrix *rowCopy = solver_->getMatrixByRow(); @@ -12151,9 +12367,10 @@ int CbcModel::findSwitching() const double *columnLower = solver_->getColLower(); const double *columnUpper = solver_->getColUpper(); const double *element = rowCopy->getElements(); - //const double * element = solver_->getMatrixByCol()->getElements(); + // const double * element = solver_->getMatrixByCol()->getElements(); const int *row = solver_->getMatrixByCol()->getIndices(); - const CoinBigIndex *columnStart = solver_->getMatrixByCol()->getVectorStarts(); + const CoinBigIndex *columnStart = + solver_->getMatrixByCol()->getVectorStarts(); const int *columnLength = solver_->getMatrixByCol()->getVectorLengths(); int numberRows = solver_->getNumRows(); int numberColumns = solver_->getNumCols(); @@ -12170,7 +12387,7 @@ int CbcModel::findSwitching() int iColumn = integerVariable_[i]; if (columnLower[iColumn] || columnUpper[iColumn] != 1.0) continue; - if (!dynamic_cast< CbcSimpleInteger * >(object_[i])) + if (!dynamic_cast(object_[i])) continue; int nAdd = 0; bool takeThis = false; @@ -12233,16 +12450,18 @@ int CbcModel::findSwitching() marked[last]++; } } - //printf("Column %d has %d other columns\n",iColumn,nAdd); + // printf("Column %d has %d other columns\n",iColumn,nAdd); sort[nAdd] = COIN_INT_MAX; whichRow[nAdd] = COIN_INT_MAX; - CbcSimpleIntegerDynamicPseudoCost *thisOne = dynamic_cast< CbcSimpleIntegerDynamicPseudoCost * >(object_[i]); + CbcSimpleIntegerDynamicPseudoCost *thisOne = + dynamic_cast(object_[i]); if (thisOne) { assert(iColumn == thisOne->columnNumber()); object_[i] = new CbcSwitchingBinary(thisOne, nAdd, sort, whichRow); delete thisOne; } else { - CbcSimpleInteger *thisOne = dynamic_cast< CbcSimpleInteger * >(object_[i]); + CbcSimpleInteger *thisOne = + dynamic_cast(object_[i]); assert(thisOne); assert(iColumn == thisOne->columnNumber()); CbcSimpleIntegerDynamicPseudoCost tempObj(this, iColumn, 0.1); @@ -12290,18 +12509,23 @@ int CbcModel::findSwitching() } } double largestC = CoinMax(fabs(cMin), fabs(cMax)); - if (((cMin > 0.0 && bEl < 0.0 && !rowUpper[iRow]) || (cMin < 0.0 && bEl > 0.0 && !rowLower[iRow])) && cMin * cMax > 0.0 && fabs(bEl) > largeRatio2 * largestC) { + if (((cMin > 0.0 && bEl < 0.0 && !rowUpper[iRow]) || + (cMin < 0.0 && bEl > 0.0 && !rowLower[iRow])) && + cMin * cMax > 0.0 && fabs(bEl) > largeRatio2 * largestC) { // forces to zero - CbcSwitchingBinary *object = dynamic_cast< CbcSwitchingBinary * >(object_[i]); + CbcSwitchingBinary *object = + dynamic_cast(object_[i]); if (!object) { // create empty one - CbcSimpleIntegerDynamicPseudoCost *thisOne = dynamic_cast< CbcSimpleIntegerDynamicPseudoCost * >(object_[i]); + CbcSimpleIntegerDynamicPseudoCost *thisOne = + dynamic_cast(object_[i]); if (thisOne) { assert(iColumn == thisOne->columnNumber()); object = new CbcSwitchingBinary(thisOne, 0, sort, whichRow); delete thisOne; } else { - CbcSimpleInteger *thisOne = dynamic_cast< CbcSimpleInteger * >(object_[i]); + CbcSimpleInteger *thisOne = + dynamic_cast(object_[i]); assert(thisOne); assert(iColumn == thisOne->columnNumber()); CbcSimpleIntegerDynamicPseudoCost tempObj(this, iColumn, 0.1); @@ -12318,8 +12542,8 @@ int CbcModel::findSwitching() } if (n2Switch + nnSwitch) { if (handler_->logLevel() > 2) - printf("%d two switch variables - %d multi (total multi %d)\n", - n2Switch, nnSwitch, nnSwitchTotal); + printf("%d two switch variables - %d multi (total multi %d)\n", n2Switch, + nnSwitch, nnSwitchTotal); memset(whichRow, 0, (numberRows + 1) * sizeof(int)); for (int i = 0; i < numberColumns; i++) { whichRow[marked[i]]++; @@ -12338,15 +12562,15 @@ int CbcModel::findSwitching() return n2Switch + nnSwitch; } // Fix associated variables -int CbcModel::fixAssociated(OsiSolverInterface *solver, int cleanBasis) -{ +int CbcModel::fixAssociated(OsiSolverInterface *solver, int cleanBasis) { int nChanged = 0; if ((moreSpecialOptions2_ & 4) != 0) { int n = -1; while (n) { n = 0; for (int i = 0; i < numberObjects_; i++) { - CbcSwitchingBinary *object = dynamic_cast< CbcSwitchingBinary * >(object_[i]); + CbcSwitchingBinary *object = + dynamic_cast(object_[i]); if (object) { n += object->setAssociatedBounds(solver, cleanBasis); } @@ -12362,8 +12586,7 @@ int CbcModel::fixAssociated(OsiSolverInterface *solver, int cleanBasis) 3 for individuals */ int CbcModel::checkAssociated(const OsiSolverInterface *solver, - const double *solution, int printLevel) -{ + const double *solution, int printLevel) { int nBad = 0; int nBadFixed = 0; if ((moreSpecialOptions2_ & 4) != 0) { @@ -12371,11 +12594,12 @@ int CbcModel::checkAssociated(const OsiSolverInterface *solver, int nAt1 = 0; int nBetween = 0; for (int i = 0; i < numberObjects_; i++) { - CbcSwitchingBinary *object = dynamic_cast< CbcSwitchingBinary * >(object_[i]); + CbcSwitchingBinary *object = + dynamic_cast(object_[i]); if (object) { int state[3]; - nBad += object->checkAssociatedBounds(solver, solution, printLevel, state, - nBadFixed); + nBad += object->checkAssociatedBounds(solver, solution, printLevel, + state, nBadFixed); if (state[0] == 0) nBetween++; else if (state[0] == -1) @@ -12386,8 +12610,9 @@ int CbcModel::checkAssociated(const OsiSolverInterface *solver, } if (handler_->logLevel() > 2) { if (printLevel > 1 || (printLevel == 1 && nBadFixed)) { - printf("%d switches, %d at 0, %d at 1, %d between - %d bad values (%d when fixed)\n", - nBetween + nAt0 + nAt1, nAt0, nAt1, nBetween, nBad, nBadFixed); + printf("%d switches, %d at 0, %d at 1, %d between - %d bad values (%d " + "when fixed)\n", + nBetween + nAt0 + nAt1, nAt0, nAt1, nBetween, nBad, nBadFixed); if (nBadFixed && printLevel != 3) checkAssociated(solver, solution, 3); } @@ -12397,11 +12622,11 @@ int CbcModel::checkAssociated(const OsiSolverInterface *solver, } #endif // Set numberBeforeTrust in all objects -void CbcModel::synchronizeNumberBeforeTrust(int type) -{ +void CbcModel::synchronizeNumberBeforeTrust(int type) { int iObject; for (iObject = 0; iObject < numberObjects_; iObject++) { - CbcSimpleIntegerDynamicPseudoCost *obj2 = dynamic_cast< CbcSimpleIntegerDynamicPseudoCost * >(object_[iObject]); + CbcSimpleIntegerDynamicPseudoCost *obj2 = + dynamic_cast(object_[iObject]); if (obj2) { // synchronize trust if (!type) { @@ -12414,10 +12639,10 @@ void CbcModel::synchronizeNumberBeforeTrust(int type) } else { assert(type == 2); int value = obj2->numberBeforeTrust(); - int n = CoinMax(obj2->numberTimesDown(), - obj2->numberTimesUp()); + int n = CoinMax(obj2->numberTimesDown(), obj2->numberTimesUp()); if (n >= value) { - value = CoinMin(CoinMin(n + 1, 3 * (value + 1) / 2), 5 * numberBeforeTrust_); + value = CoinMin(CoinMin(n + 1, 3 * (value + 1) / 2), + 5 * numberBeforeTrust_); obj2->setNumberBeforeTrust(value); } } @@ -12427,8 +12652,7 @@ void CbcModel::synchronizeNumberBeforeTrust(int type) /* Add in any object information (objects are cloned - owner can delete originals */ -void CbcModel::addObjects(int numberObjects, CbcObject **objects) -{ +void CbcModel::addObjects(int numberObjects, CbcObject **objects) { // If integers but not enough objects fudge if (numberIntegers_ > numberObjects_ || !numberObjects_) findIntegers(true); @@ -12444,7 +12668,7 @@ void CbcModel::addObjects(int numberObjects, CbcObject **objects) int newNumberObjects = numberObjects; int newIntegers = 0; for (i = 0; i < numberObjects; i++) { - CbcSimpleInteger *obj = dynamic_cast< CbcSimpleInteger * >(objects[i]); + CbcSimpleInteger *obj = dynamic_cast(objects[i]); if (obj) { int iColumn = obj->columnNumber(); assert(iColumn >= 0); @@ -12454,7 +12678,7 @@ void CbcModel::addObjects(int numberObjects, CbcObject **objects) } // and existing for (i = 0; i < numberObjects_; i++) { - CbcSimpleInteger *obj = dynamic_cast< CbcSimpleInteger * >(object_[i]); + CbcSimpleInteger *obj = dynamic_cast(object_[i]); if (obj) { int iColumn = obj->columnNumber(); if (mark[iColumn] < 0) { @@ -12471,8 +12695,8 @@ void CbcModel::addObjects(int numberObjects, CbcObject **objects) integerVariable_ = NULL; #if COIN_DEVELOP > 1 if (newIntegers != numberIntegers_) - printf("changing number of integers from %d to %d\n", - numberIntegers_, newIntegers); + printf("changing number of integers from %d to %d\n", numberIntegers_, + newIntegers); #endif numberIntegers_ = newIntegers; integerVariable_ = new int[numberIntegers_]; @@ -12504,7 +12728,7 @@ void CbcModel::addObjects(int numberObjects, CbcObject **objects) // Now rest of old for (i = 0; i < numberObjects_; i++) { if (object_[i]) { - CbcSimpleInteger *obj = dynamic_cast< CbcSimpleInteger * >(object_[i]); + CbcSimpleInteger *obj = dynamic_cast(object_[i]); if (obj) { delete object_[i]; } else { @@ -12514,10 +12738,10 @@ void CbcModel::addObjects(int numberObjects, CbcObject **objects) } // and rest of new for (i = 0; i < numberObjects; i++) { - CbcSimpleInteger *obj = dynamic_cast< CbcSimpleInteger * >(objects[i]); + CbcSimpleInteger *obj = dynamic_cast(objects[i]); if (!obj) { temp[n] = objects[i]->clone(); - CbcObject *obj = dynamic_cast< CbcObject * >(temp[n]); + CbcObject *obj = dynamic_cast(temp[n]); if (obj) obj->setModel(this); n++; @@ -12532,8 +12756,7 @@ void CbcModel::addObjects(int numberObjects, CbcObject **objects) } /* Add in any object information (objects are cloned - owner can delete originals */ -void CbcModel::addObjects(int numberObjects, OsiObject **objects) -{ +void CbcModel::addObjects(int numberObjects, OsiObject **objects) { // If integers but not enough objects fudge if (numberIntegers_ > numberObjects_) findIntegers(true); @@ -12549,13 +12772,13 @@ void CbcModel::addObjects(int numberObjects, OsiObject **objects) int newNumberObjects = numberObjects; int newIntegers = 0; for (i = 0; i < numberObjects; i++) { - CbcSimpleInteger *obj = dynamic_cast< CbcSimpleInteger * >(objects[i]); + CbcSimpleInteger *obj = dynamic_cast(objects[i]); if (obj) { int iColumn = obj->columnNumber(); mark[iColumn] = i + numberColumns; newIntegers++; } else { - OsiSimpleInteger *obj2 = dynamic_cast< OsiSimpleInteger * >(objects[i]); + OsiSimpleInteger *obj2 = dynamic_cast(objects[i]); if (obj2) { // Osi takes precedence int iColumn = obj2->columnNumber(); @@ -12566,7 +12789,7 @@ void CbcModel::addObjects(int numberObjects, OsiObject **objects) } // and existing for (i = 0; i < numberObjects_; i++) { - CbcSimpleInteger *obj = dynamic_cast< CbcSimpleInteger * >(object_[i]); + CbcSimpleInteger *obj = dynamic_cast(object_[i]); if (obj) { int iColumn = obj->columnNumber(); if (mark[iColumn] < 0) { @@ -12582,8 +12805,8 @@ void CbcModel::addObjects(int numberObjects, OsiObject **objects) integerVariable_ = NULL; #if COIN_DEVELOP > 1 if (newIntegers != numberIntegers_) - printf("changing number of integers from %d to %d\n", - numberIntegers_, newIntegers); + printf("changing number of integers from %d to %d\n", numberIntegers_, + newIntegers); #endif numberIntegers_ = newIntegers; integerVariable_ = new int[numberIntegers_]; @@ -12615,7 +12838,7 @@ void CbcModel::addObjects(int numberObjects, OsiObject **objects) // Now rest of old for (i = 0; i < numberObjects_; i++) { if (object_[i]) { - CbcSimpleInteger *obj = dynamic_cast< CbcSimpleInteger * >(object_[i]); + CbcSimpleInteger *obj = dynamic_cast(object_[i]); if (obj) { delete object_[i]; } else { @@ -12625,11 +12848,11 @@ void CbcModel::addObjects(int numberObjects, OsiObject **objects) } // and rest of new for (i = 0; i < numberObjects; i++) { - CbcSimpleInteger *obj = dynamic_cast< CbcSimpleInteger * >(objects[i]); - OsiSimpleInteger *obj2 = dynamic_cast< OsiSimpleInteger * >(objects[i]); + CbcSimpleInteger *obj = dynamic_cast(objects[i]); + OsiSimpleInteger *obj2 = dynamic_cast(objects[i]); if (!obj && !obj2) { temp[n] = objects[i]->clone(); - CbcObject *obj = dynamic_cast< CbcObject * >(temp[n]); + CbcObject *obj = dynamic_cast(temp[n]); if (obj) obj->setModel(this); n++; @@ -12681,7 +12904,7 @@ void CbcModel::setCutoff(double value) double direction = solver_->getObjSense(); #else double direction = 1.0; - if (!dynamic_cast< OsiClpSolverInterface * >(solver_)) + if (!dynamic_cast(solver_)) direction = solver_->getObjSense(); #endif solver_->setDblParam(OsiDualObjectiveLimit, value * direction); @@ -12697,14 +12920,13 @@ void CbcModel::setCutoff(double value) scratch. If the solution is rejected, this will be worse than the cutoff. TODO: There's an issue with getting the correct cutoff value: We update the - cutoff in the regular solver, but not in continuousSolver_. But our only - use for continuousSolver_ is verifying candidate solutions. Would it - make sense to update the cutoff? Then we wouldn't need to step around - isDualObjectiveLimitReached(). + cutoff in the regular solver, but not in continuousSolver_. But our only + use for continuousSolver_ is verifying candidate solutions. Would it + make sense to update the cutoff? Then we wouldn't need to step around + isDualObjectiveLimitReached(). */ -double -CbcModel::checkSolution(double cutoff, double *solution, - int fixVariables, double objectiveValue) +double CbcModel::checkSolution(double cutoff, double *solution, + int fixVariables, double objectiveValue) { int numberContinuousColumns = continuousSolver_->getNumCols(); @@ -12712,11 +12934,11 @@ CbcModel::checkSolution(double cutoff, double *solution, // Can trust solution int numberColumns = solver_->getNumCols(); #ifdef CBC_HAS_CLP - OsiClpSolverInterface *clpContinuousSolver - = dynamic_cast< OsiClpSolverInterface * >(continuousSolver_); + OsiClpSolverInterface *clpContinuousSolver = + dynamic_cast(continuousSolver_); // But not if odd solver - if(dynamic_cast< CbcOsiSolver * >(continuousSolver_)) - clpContinuousSolver = NULL; + if (dynamic_cast(continuousSolver_)) + clpContinuousSolver = NULL; int modifiedTolerances = 0; #ifndef CBC_LEAVE_PERTURBATION_ON_CHECK_SOLUTION int savePerturbation = -1; @@ -12729,7 +12951,7 @@ CbcModel::checkSolution(double cutoff, double *solution, #endif #define CBC_LEAVE_CRUNCH_ON_CHECK_SOLUTION // for now #ifndef CBC_LEAVE_CRUNCH_ON_CHECK_SOLUTION - int saveSpecialOptions=0; + int saveSpecialOptions = 0; #endif if (clpContinuousSolver) { // be more accurate if possible @@ -12765,28 +12987,30 @@ CbcModel::checkSolution(double cutoff, double *solution, #ifndef CBC_LEAVE_CRUNCH_ON_CHECK_SOLUTION modifiedTolerances |= 8; saveSpecialOptions = clpContinuousSolver->specialOptions(); - clpContinuousSolver->setSpecialOptions(saveSpecialOptions&(~1)); // switch off crunch + clpContinuousSolver->setSpecialOptions(saveSpecialOptions & + (~1)); // switch off crunch #endif } #endif /* - Grab the continuous solver (the pristine copy of the problem, made before - starting to work on the root node). Save the bounds on the variables. - Install the solution passed as a parameter, and copy it to the model's - currentSolution_. + Grab the continuous solver (the pristine copy of the problem, made + before starting to work on the root node). Save the bounds on the + variables. Install the solution passed as a parameter, and copy it to the + model's currentSolution_. - TODO: This is a belt-and-suspenders approach. Once the code has settled - a bit, we can cast a critical eye here. + TODO: This is a belt-and-suspenders approach. Once the code has + settled a bit, we can cast a critical eye here. */ OsiSolverInterface *saveSolver = solver_; if (continuousSolver_) solver_ = continuousSolver_; // save basis and solution - CoinWarmStartBasis *basis = dynamic_cast< CoinWarmStartBasis * >(solver_->getWarmStart()); + CoinWarmStartBasis *basis = + dynamic_cast(solver_->getWarmStart()); assert(basis != NULL); - double *saveSolution = CoinCopyOfArray(solver_->getColSolution(), - solver_->getNumCols()); + double *saveSolution = + CoinCopyOfArray(solver_->getColSolution(), solver_->getNumCols()); // move solution to continuous copy solver_->setColSolution(solution); // Put current solution in safe place @@ -12794,9 +13018,9 @@ CbcModel::checkSolution(double cutoff, double *solution, const double *save = testSolution_; // Safe as will be const inside infeasibility() testSolution_ = solver_->getColSolution(); - //memcpy(currentSolution_,solver_->getColSolution(), + // memcpy(currentSolution_,solver_->getColSolution(), // numberColumns*sizeof(double)); - //solver_->messageHandler()->setLogLevel(4); + // solver_->messageHandler()->setLogLevel(4); // save original bounds double *saveUpper = new double[numberColumns]; @@ -12831,7 +13055,8 @@ CbcModel::checkSolution(double cutoff, double *solution, marked[integerVariable_[i]] = -2; if ((moreSpecialOptions2_ & 4) != 0) { for (int i = 0; i < numberObjects_; i++) { - CbcSwitchingBinary *object = dynamic_cast< CbcSwitchingBinary * >(object_[i]); + CbcSwitchingBinary *object = + dynamic_cast(object_[i]); if (object) { int iColumn = object->columnNumber(); const int *other = object->otherVariable(); @@ -12844,7 +13069,8 @@ CbcModel::checkSolution(double cutoff, double *solution, } const double *element = solver_->getMatrixByCol()->getElements(); const int *row = solver_->getMatrixByCol()->getIndices(); - const CoinBigIndex *columnStart = solver_->getMatrixByCol()->getVectorStarts(); + const CoinBigIndex *columnStart = + solver_->getMatrixByCol()->getVectorStarts(); const int *columnLength = solver_->getMatrixByCol()->getVectorLengths(); const CoinPackedMatrix *rowCopy = solver_->getMatrixByRow(); const int *column = rowCopy->getIndices(); @@ -12857,11 +13083,13 @@ CbcModel::checkSolution(double cutoff, double *solution, objValue += value * objective[iColumn]; if (value > columnUpper[iColumn]) { if (value - columnUpper[iColumn] > 1.0e-8) - printf("column %d has value %.12g above %.12g\n", iColumn, value, columnUpper[iColumn]); + printf("column %d has value %.12g above %.12g\n", iColumn, value, + columnUpper[iColumn]); value = columnUpper[iColumn]; } else if (value < columnLower[iColumn]) { if (value - columnLower[iColumn] < -1.0e-8) - printf("column %d has value %.12g below %.12g\n", iColumn, value, columnLower[iColumn]); + printf("column %d has value %.12g below %.12g\n", iColumn, value, + columnLower[iColumn]); value = columnLower[iColumn]; } if (value) { @@ -12875,7 +13103,7 @@ CbcModel::checkSolution(double cutoff, double *solution, } } for (int i = 0; i < numberRows; i++) { -#if 0 //def CLP_INVESTIGATE +#if 0 // def CLP_INVESTIGATE double inf; inf = rowLower[i] - rowActivity[i]; if (inf > primalTolerance) @@ -12886,19 +13114,19 @@ CbcModel::checkSolution(double cutoff, double *solution, printf("Row %d inf %g sum %g %g <= %g <= %g\n", i, inf, rowSum[i], rowLower[i], rowActivity[i], rowUpper[i]); #endif - double infeasibility = CoinMax(rowActivity[i] - rowUpper[i], - rowLower[i] - rowActivity[i]); + double infeasibility = + CoinMax(rowActivity[i] - rowUpper[i], rowLower[i] - rowActivity[i]); // but allow for errors double factor = CoinMax(1.0, rowSum[i] * 1.0e-3); if (infeasibility > largestInfeasibility * factor) { largestInfeasibility = infeasibility / factor; - printf("Ainf of %g on row %d sum %g scaled %g\n", - infeasibility, i, rowSum[i], largestInfeasibility); + printf("Ainf of %g on row %d sum %g scaled %g\n", infeasibility, i, + rowSum[i], largestInfeasibility); if (infeasibility > 1.0e10) { - for (CoinBigIndex j = rowStart[i]; - j < rowStart[i] + rowLength[i]; j++) { - printf("col %d element %g marked %d\n", - column[j], elementByRow[j], marked[column[j]]); + for (CoinBigIndex j = rowStart[i]; j < rowStart[i] + rowLength[i]; + j++) { + printf("col %d element %g marked %d\n", column[j], + elementByRow[j], marked[column[j]]); } } } @@ -12907,7 +13135,8 @@ CbcModel::checkSolution(double cutoff, double *solution, delete[] rowSum; delete[] marked; if (largestInfeasibility > 10.0 * primalTolerance) - printf("Alargest infeasibility is %g - obj %g\n", largestInfeasibility, objValue); + printf("Alargest infeasibility is %g - obj %g\n", largestInfeasibility, + objValue); else printf("Afeasible (%g) - obj %g\n", largestInfeasibility, objValue); } @@ -12916,10 +13145,11 @@ CbcModel::checkSolution(double cutoff, double *solution, OsiBranchingInformation usefulInfo = usefulInformation(); /* - Run through the objects and use feasibleRegion() to set variable bounds - so as to fix the variables specified in the objects at their value in this - solution. Since the object list contains (at least) one object for every - integer variable, this has the effect of fixing all integer variables. + Run through the objects and use feasibleRegion() to set variable + bounds so as to fix the variables specified in the objects at their value + in this solution. Since the object list contains (at least) one object + for every integer variable, this has the effect of fixing all integer + variables. */ int i; for (i = 0; i < numberObjects_; i++) @@ -12937,8 +13167,7 @@ CbcModel::checkSolution(double cutoff, double *solution, if (!looksGood) { // not good messageHandler()->message(CBC_FPUMP2, messages()) - << "On closer inspection - solution discarded" - << CoinMessageEol; + << "On closer inspection - solution discarded" << CoinMessageEol; objectiveValue = 1.0e50; for (int iColumn = 0; iColumn < numberColumns; iColumn++) { solver_->setColLower(iColumn, saveLower[iColumn]); @@ -12952,8 +13181,8 @@ CbcModel::checkSolution(double cutoff, double *solution, solver_->setWarmStart(basis); delete basis; /* - Restore the usual solver. - */ + Restore the usual solver. + */ solver_ = saveSolver; testSolution_ = save; #ifdef CBC_HAS_CLP @@ -12973,8 +13202,8 @@ CbcModel::checkSolution(double cutoff, double *solution, } #endif #ifndef CBC_LEAVE_CRUNCH_ON_CHECK_SOLUTION - // Restore - clpContinuousSolver->setSpecialOptions(saveSpecialOptions); + // Restore + clpContinuousSolver->setSpecialOptions(saveSpecialOptions); #endif } #endif @@ -13008,7 +13237,8 @@ CbcModel::checkSolution(double cutoff, double *solution, marked[integerVariable_[i]] = -2; if ((moreSpecialOptions2_ & 4) != 0) { for (int i = 0; i < numberObjects_; i++) { - CbcSwitchingBinary *object = dynamic_cast< CbcSwitchingBinary * >(object_[i]); + CbcSwitchingBinary *object = + dynamic_cast(object_[i]); if (object) { int iColumn = object->columnNumber(); const int *other = object->otherVariable(); @@ -13021,7 +13251,8 @@ CbcModel::checkSolution(double cutoff, double *solution, } const double *element = solver_->getMatrixByCol()->getElements(); const int *row = solver_->getMatrixByCol()->getIndices(); - const CoinBigIndex *columnStart = solver_->getMatrixByCol()->getVectorStarts(); + const CoinBigIndex *columnStart = + solver_->getMatrixByCol()->getVectorStarts(); const int *columnLength = solver_->getMatrixByCol()->getVectorLengths(); const CoinPackedMatrix *rowCopy = solver_->getMatrixByRow(); const int *column = rowCopy->getIndices(); @@ -13034,11 +13265,13 @@ CbcModel::checkSolution(double cutoff, double *solution, objValue += value * objective[iColumn]; if (value > columnUpper[iColumn]) { if (value - columnUpper[iColumn] > 1.0e-8) - printf("column %d has value %.12g above %.12g\n", iColumn, value, columnUpper[iColumn]); + printf("column %d has value %.12g above %.12g\n", iColumn, value, + columnUpper[iColumn]); value = columnUpper[iColumn]; } else if (value < columnLower[iColumn]) { if (value - columnLower[iColumn] < -1.0e-8) - printf("column %d has value %.12g below %.12g\n", iColumn, value, columnLower[iColumn]); + printf("column %d has value %.12g below %.12g\n", iColumn, value, + columnLower[iColumn]); value = columnLower[iColumn]; } if (value) { @@ -13052,7 +13285,7 @@ CbcModel::checkSolution(double cutoff, double *solution, } } for (int i = 0; i < numberRows; i++) { -#if 0 //def CLP_INVESTIGATE +#if 0 // def CLP_INVESTIGATE double inf; inf = rowLower[i] - rowActivity[i]; if (inf > primalTolerance) @@ -13063,19 +13296,19 @@ CbcModel::checkSolution(double cutoff, double *solution, printf("Row %d inf %g sum %g %g <= %g <= %g\n", i, inf, rowSum[i], rowLower[i], rowActivity[i], rowUpper[i]); #endif - double infeasibility = CoinMax(rowActivity[i] - rowUpper[i], - rowLower[i] - rowActivity[i]); + double infeasibility = + CoinMax(rowActivity[i] - rowUpper[i], rowLower[i] - rowActivity[i]); // but allow for errors double factor = CoinMax(1.0, rowSum[i] * 1.0e-3); if (infeasibility > largestInfeasibility * factor) { largestInfeasibility = infeasibility / factor; - printf("inf of %g on row %d sum %g scaled %g\n", - infeasibility, i, rowSum[i], largestInfeasibility); + printf("inf of %g on row %d sum %g scaled %g\n", infeasibility, i, + rowSum[i], largestInfeasibility); if (infeasibility > 1.0e10) { - for (CoinBigIndex j = rowStart[i]; - j < rowStart[i] + rowLength[i]; j++) { - printf("col %d element %g marked %d\n", - column[j], elementByRow[j], marked[column[j]]); + for (CoinBigIndex j = rowStart[i]; j < rowStart[i] + rowLength[i]; + j++) { + printf("col %d element %g marked %d\n", column[j], + elementByRow[j], marked[column[j]]); } } } @@ -13084,18 +13317,20 @@ CbcModel::checkSolution(double cutoff, double *solution, delete[] rowSum; delete[] marked; if (largestInfeasibility > 10.0 * primalTolerance) - printf("Largest infeasibility is %g - obj %g\n", largestInfeasibility, objValue); + printf("Largest infeasibility is %g - obj %g\n", largestInfeasibility, + objValue); else printf("Feasible (%g) - obj %g\n", largestInfeasibility, objValue); } #endif // If relaxed then leave bounds on basic variables if (fixVariables == -1 && (specialOptions_ & 16) == 0) { - CoinWarmStartBasis *basis = dynamic_cast< CoinWarmStartBasis * >(saveSolver->getWarmStart()); + CoinWarmStartBasis *basis = + dynamic_cast(saveSolver->getWarmStart()); assert(basis != NULL); -#ifdef JJF_ZERO //ndef CBC_OTHER_SOLVER +#ifdef JJF_ZERO // ndef CBC_OTHER_SOLVER for (i = 0; i < numberObjects_; i++) { - CbcSimpleInteger *obj = dynamic_cast< CbcSimpleInteger * >(object_[i]); + CbcSimpleInteger *obj = dynamic_cast(object_[i]); if (obj) { int iColumn = obj->columnNumber(); if (basis->getStructStatus(iColumn) == CoinWarmStartBasis::basic) { @@ -13110,26 +13345,31 @@ CbcModel::checkSolution(double cutoff, double *solution, // We can switch off check if ((specialOptions_ & 4) == 0 && (moreSpecialOptions2_ & 10) != 8) { // Be on safe side - unless very few integers and large - bool allSlack = (specialOptions_ & 2) == 0 && solverCharacteristics_->warmStart(); - if (numberIntegers_ * 4 > solver_->getNumCols() || solver_->getNumCols() < 10000) + bool allSlack = + (specialOptions_ & 2) == 0 && solverCharacteristics_->warmStart(); + if (numberIntegers_ * 4 > solver_->getNumCols() || + solver_->getNumCols() < 10000) allSlack = true; if (allSlack) { /* - Remove any existing warm start information to be sure there is no - residual influence on initialSolve(). + Remove any existing warm start information to be sure there is + no residual influence on initialSolve(). */ - CoinWarmStartBasis *slack = dynamic_cast< CoinWarmStartBasis * >(solver_->getEmptyWarmStart()); + CoinWarmStartBasis *slack = + dynamic_cast(solver_->getEmptyWarmStart()); solver_->setWarmStart(slack); delete slack; } else { - if (bestSolutionBasis_.getNumStructural() == solver_->getNumCols() && bestSolutionBasis_.getNumArtificial() == solver_->getNumRows()) + if (bestSolutionBasis_.getNumStructural() == solver_->getNumCols() && + bestSolutionBasis_.getNumArtificial() == solver_->getNumRows()) solver_->setWarmStart(&bestSolutionBasis_); } // Give a hint to do dual bool saveTakeHint; OsiHintStrength saveStrength; #ifndef NDEBUG - bool gotHint = (solver_->getHintParam(OsiDoDualInInitial, saveTakeHint, saveStrength)); + bool gotHint = (solver_->getHintParam(OsiDoDualInInitial, saveTakeHint, + saveStrength)); assert(gotHint); #else (solver_->getHintParam(OsiDoDualInInitial, saveTakeHint, saveStrength)); @@ -13147,8 +13387,8 @@ CbcModel::checkSolution(double cutoff, double *solution, if (solver_->isProvenOptimal()) { solver_->writeMpsNative("feasible.mps", NULL, NULL, 2); #ifdef CBC_HAS_CLP - OsiClpSolverInterface *clpSolver - = dynamic_cast< OsiClpSolverInterface * >(solver_); + OsiClpSolverInterface *clpSolver = + dynamic_cast(solver_); if (clpSolver) { clpSolver->getModelPtr()->writeBasis("feasible.bas", true); } @@ -13160,29 +13400,33 @@ CbcModel::checkSolution(double cutoff, double *solution, #if CBC_FEASIBILITY_INVESTIGATE printf("checkSolution infeas! Retrying with primal.\n"); #endif - //bool saveTakeHint; - //OsiHintStrength saveStrength; - //bool savePrintHint; - //solver_->writeMpsNative("infeas.mps", NULL, NULL, 2); - //bool gotHint = (solver_->getHintParam(OsiDoReducePrint,savePrintHint,saveStrength)); - //gotHint = (solver_->getHintParam(OsiDoScale,saveTakeHint,saveStrength)); - //solver_->setHintParam(OsiDoScale,false,OsiHintTry); - //solver_->setHintParam(OsiDoReducePrint,false,OsiHintTry) ; + // bool saveTakeHint; + // OsiHintStrength saveStrength; + // bool savePrintHint; + // solver_->writeMpsNative("infeas.mps", NULL, NULL, 2); + // bool gotHint = + // (solver_->getHintParam(OsiDoReducePrint,savePrintHint,saveStrength)); + // gotHint = + // (solver_->getHintParam(OsiDoScale,saveTakeHint,saveStrength)); + // solver_->setHintParam(OsiDoScale,false,OsiHintTry); + // solver_->setHintParam(OsiDoReducePrint,false,OsiHintTry) ; solver_->setHintParam(OsiDoDualInInitial, false, OsiHintTry); solver_->initialSolve(); - //solver_->setHintParam(OsiDoScale,saveTakeHint,saveStrength); - //solver_->setHintParam(OsiDoReducePrint,savePrintHint,OsiHintTry) ; + // solver_->setHintParam(OsiDoScale,saveTakeHint,saveStrength); + // solver_->setHintParam(OsiDoReducePrint,savePrintHint,OsiHintTry) ; // go from all slack now specialOptions_ &= ~2; if (!solver_->isProvenOptimal()) { - CoinWarmStartBasis *slack = dynamic_cast< CoinWarmStartBasis * >(solver_->getEmptyWarmStart()); + CoinWarmStartBasis *slack = + dynamic_cast(solver_->getEmptyWarmStart()); solver_->setWarmStart(slack); delete slack; #if CBC_FEASIBILITY_INVESTIGATE - printf("checkSolution infeas! Retrying wihout basis and with primal.\n"); + printf( + "checkSolution infeas! Retrying wihout basis and with primal.\n"); #endif solver_->initialSolve(); - //solver_->writeMps("bad"); + // solver_->writeMps("bad"); #ifdef CBC_HAS_CLP if (!solver_->isProvenOptimal() && modifiedTolerances) { // Restore @@ -13209,9 +13453,11 @@ CbcModel::checkSolution(double cutoff, double *solution, #endif } } - //assert(solver_->isProvenOptimal()); + // assert(solver_->isProvenOptimal()); solver_->setHintParam(OsiDoDualInInitial, saveTakeHint, saveStrength); - objectiveValue = solver_->isProvenOptimal() ? solver_->getObjValue() * solver_->getObjSense() : 1.0e50; + objectiveValue = solver_->isProvenOptimal() + ? solver_->getObjValue() * solver_->getObjSense() + : 1.0e50; } bestSolutionBasis_ = CoinWarmStartBasis(); @@ -13226,10 +13472,13 @@ CbcModel::checkSolution(double cutoff, double *solution, There really should be no need for the check against original bounds. Perhaps an opportunity for a sanity check? */ - if (objectiveValue > cutoff && objectiveValue < cutoff + 1.0e-8 + 1.0e-8 * fabs(cutoff)) + if (objectiveValue > cutoff && + objectiveValue < cutoff + 1.0e-8 + 1.0e-8 * fabs(cutoff)) cutoff = objectiveValue; // relax - if ((solver_->isProvenOptimal() || (specialOptions_ & 4) != 0) && objectiveValue <= cutoff) { - memcpy(solution, solver_->getColSolution(), numberColumns * sizeof(double)); + if ((solver_->isProvenOptimal() || (specialOptions_ & 4) != 0) && + objectiveValue <= cutoff) { + memcpy(solution, solver_->getColSolution(), + numberColumns * sizeof(double)); int iColumn; #ifndef NDEBUG double integerTolerance = getIntegerTolerance(); @@ -13258,7 +13507,7 @@ CbcModel::checkSolution(double cutoff, double *solution, double value2 = floor(value + 0.5); if (dj[iColumn] < -1.0e-6) { // negative dj - //assert (value2==colUpper[iColumn]); + // assert (value2==colUpper[iColumn]); if (saveUpper[iColumn] == colUpper[iColumn]) { nAtUbNatural++; if (saveLower[iColumn] != colLower[iColumn]) @@ -13267,12 +13516,13 @@ CbcModel::checkSolution(double cutoff, double *solution, nAtLbFixed++; } else { nAtOther++; - if (saveLower[iColumn] != colLower[iColumn] && saveUpper[iColumn] != colUpper[iColumn]) + if (saveLower[iColumn] != colLower[iColumn] && + saveUpper[iColumn] != colUpper[iColumn]) nNotNeeded++; } } else if (dj[iColumn] > 1.0e-6) { // positive dj - //assert (value2==colLower[iColumn]); + // assert (value2==colLower[iColumn]); if (saveLower[iColumn] == colLower[iColumn]) { nAtLbNatural++; if (saveUpper[iColumn] != colUpper[iColumn]) @@ -13281,7 +13531,8 @@ CbcModel::checkSolution(double cutoff, double *solution, nAtUbFixed++; } else { nAtOther++; - if (saveLower[iColumn] != colLower[iColumn] && saveUpper[iColumn] != colUpper[iColumn]) + if (saveLower[iColumn] != colLower[iColumn] && + saveUpper[iColumn] != colUpper[iColumn]) nNotNeeded++; } } else { @@ -13294,7 +13545,8 @@ CbcModel::checkSolution(double cutoff, double *solution, nAtLbNaturalZero++; } else { nAtOtherNatural++; - if (saveLower[iColumn] != colLower[iColumn] && saveUpper[iColumn] != colUpper[iColumn]) + if (saveLower[iColumn] != colLower[iColumn] && + saveUpper[iColumn] != colUpper[iColumn]) nNotNeeded++; } } @@ -13303,19 +13555,15 @@ CbcModel::checkSolution(double cutoff, double *solution, solution[iColumn] = value; } #if CBC_FEASIBILITY_INVESTIGATE - printf("nAtLbNat %d,nAtUbNat %d,nAtLbNatZero %d,nAtUbNatZero %d,nAtLbFixed %d,nAtUbFixed %d,nAtOther %d,nAtOtherNat %d, useless %d\n", - nAtLbNatural, - nAtUbNatural, - nAtLbNaturalZero, - nAtUbNaturalZero, - nAtLbFixed, - nAtUbFixed, - nAtOther, - nAtOtherNatural, nNotNeeded); - //if (currentNode_) - //printf(" SOL at depth %d\n",currentNode_->depth()); - //else - //printf(" SOL at unknown depth\n"); + printf( + "nAtLbNat %d,nAtUbNat %d,nAtLbNatZero %d,nAtUbNatZero %d,nAtLbFixed " + "%d,nAtUbFixed %d,nAtOther %d,nAtOtherNat %d, useless %d\n", + nAtLbNatural, nAtUbNatural, nAtLbNaturalZero, nAtUbNaturalZero, + nAtLbFixed, nAtUbFixed, nAtOther, nAtOtherNatural, nNotNeeded); + // if (currentNode_) + // printf(" SOL at depth %d\n",currentNode_->depth()); + // else + // printf(" SOL at unknown depth\n"); #endif if ((specialOptions_ & 16) == 0) { #ifdef JJF_ZERO @@ -13347,7 +13595,8 @@ CbcModel::checkSolution(double cutoff, double *solution, memset(rowSum, 0, numberRows * sizeof(double)); const double *element = solver_->getMatrixByCol()->getElements(); const int *row = solver_->getMatrixByCol()->getIndices(); - const CoinBigIndex *columnStart = solver_->getMatrixByCol()->getVectorStarts(); + const CoinBigIndex *columnStart = + solver_->getMatrixByCol()->getVectorStarts(); const int *columnLength = solver_->getMatrixByCol()->getVectorLengths(); double offset; solver_->getDblParam(OsiObjOffset, offset); @@ -13371,20 +13620,20 @@ CbcModel::checkSolution(double cutoff, double *solution, double inf; inf = rowLower[i] - rowActivity[i]; if (inf > primalTolerance) - printf("Row %d inf %g sum %g %g <= %g <= %g\n", - i, inf, rowSum[i], rowLower[i], rowActivity[i], rowUpper[i]); + printf("Row %d inf %g sum %g %g <= %g <= %g\n", i, inf, rowSum[i], + rowLower[i], rowActivity[i], rowUpper[i]); inf = rowActivity[i] - rowUpper[i]; if (inf > primalTolerance) - printf("Row %d inf %g sum %g %g <= %g <= %g\n", - i, inf, rowSum[i], rowLower[i], rowActivity[i], rowUpper[i]); + printf("Row %d inf %g sum %g %g <= %g <= %g\n", i, inf, rowSum[i], + rowLower[i], rowActivity[i], rowUpper[i]); #endif double infeasibility = CoinMax(rowActivity[i] - rowUpper[i], - rowLower[i] - rowActivity[i]); + rowLower[i] - rowActivity[i]); // but allow for errors double factor = CoinMax(1.0, rowSum[i] * 1.0e-3); if (infeasibility > largestInfeasibility * factor) { largestInfeasibility = infeasibility / factor; - //printf("inf of %g on row %d sum %g scaled %g\n", + // printf("inf of %g on row %d sum %g scaled %g\n", // infeasibility,i,rowSum[i],largestInfeasibility); } } @@ -13394,16 +13643,18 @@ CbcModel::checkSolution(double cutoff, double *solution, if (handler_->logLevel() > 2) { #endif if (largestInfeasibility > 10.0 * primalTolerance) - printf("BLargest infeasibility is %g - obj %g (%g)\n", largestInfeasibility, objValue, objectiveValue); + printf("BLargest infeasibility is %g - obj %g (%g)\n", + largestInfeasibility, objValue, objectiveValue); else - printf("BFeasible (%g) - obj %g %g\n", largestInfeasibility, objValue, objectiveValue); + printf("BFeasible (%g) - obj %g %g\n", largestInfeasibility, + objValue, objectiveValue); #if CBC_FEASIBILITY_INVESTIGATE == 0 } #else solver_->writeMpsNative("BFeasible.mps", NULL, NULL, 2); #endif - //if (fabs(objValue-objectiveValue)>1.0e-7*fabs(objectiveValue)) { - //printf("Bad obj values\n"); + // if (fabs(objValue-objectiveValue)>1.0e-7*fabs(objectiveValue)) { + // printf("Bad obj values\n"); objectiveValue = objValue; //} #if CBC_FEASIBILITY_INVESTIGATE @@ -13412,7 +13663,7 @@ CbcModel::checkSolution(double cutoff, double *solution, #endif if (largestInfeasibility > 200.0 * primalTolerance) { handler_->message(CBC_NOTFEAS3, messages_) - << largestInfeasibility << CoinMessageEol; + << largestInfeasibility << CoinMessageEol; objectiveValue = 1.0e50; } } @@ -13420,9 +13671,10 @@ CbcModel::checkSolution(double cutoff, double *solution, objectiveValue = 1.0e50; } /* - Regardless of what we think of the solution, we may need to restore the - original bounds of the continuous solver. Unfortunately, const'ness - prevents us from simply reversing the memcpy used to make these snapshots. + Regardless of what we think of the solution, we may need to restore + the original bounds of the continuous solver. Unfortunately, const'ness + prevents us from simply reversing the memcpy used to make these + snapshots. */ if (fixVariables <= 0) { for (int iColumn = 0; iColumn < numberColumns; iColumn++) { @@ -13466,27 +13718,33 @@ CbcModel::checkSolution(double cutoff, double *solution, return objectiveValue; } else { // Outer approximation or similar - //If this is true then the solution comes from the nlp we don't need to resolve the same nlp with ipopt - //solverCharacteristics_->setSolver(solver_); - bool solutionComesFromNlp = solverCharacteristics_->bestObjectiveValue() < cutoff; + // If this is true then the solution comes from the nlp we don't need to + // resolve the same nlp with ipopt + // solverCharacteristics_->setSolver(solver_); + bool solutionComesFromNlp = + solverCharacteristics_->bestObjectiveValue() < cutoff; double objectiveValue; int numberColumns = solver_->getNumCols(); double *saveLower = NULL; double *saveUpper = NULL; - if (!solutionComesFromNlp) { //Otherwise solution already comes from ipopt and cuts are known - if (fixVariables > 0) { //Will temporarily fix all integer valued var + if (!solutionComesFromNlp) { // Otherwise solution already comes from ipopt + // and cuts are known + if (fixVariables > 0) { // Will temporarily fix all integer valued var // save original bounds saveUpper = new double[numberColumns]; saveLower = new double[numberColumns]; - memcpy(saveUpper, solver_->getColUpper(), numberColumns * sizeof(double)); - memcpy(saveLower, solver_->getColLower(), numberColumns * sizeof(double)); - //in any case solution should be already loaded into solver_ + memcpy(saveUpper, solver_->getColUpper(), + numberColumns * sizeof(double)); + memcpy(saveLower, solver_->getColLower(), + numberColumns * sizeof(double)); + // in any case solution should be already loaded into solver_ /* - Run through the objects and use feasibleRegion() to set variable bounds - so as to fix the variables specified in the objects at their value in this - solution. Since the object list contains (at least) one object for every - integer variable, this has the effect of fixing all integer variables. + Run through the objects and use feasibleRegion() to set + variable bounds so as to fix the variables specified in the objects + at their value in this solution. Since the object list contains (at + least) one object for every integer variable, this has the effect of + fixing all integer variables. */ const double *save = testSolution_; testSolution_ = solution; @@ -13499,17 +13757,17 @@ CbcModel::checkSolution(double cutoff, double *solution, } /* - Now step through the cut generators and see if any of them are flagged to - run when a new solution is discovered. Only global cuts are useful. - (The solution being evaluated may not correspond to the current location in the - search tree --- discovered by heuristic, for example.) + Now step through the cut generators and see if any of them are + flagged to run when a new solution is discovered. Only global cuts are + useful. (The solution being evaluated may not correspond to the current + location in the search tree --- discovered by heuristic, for example.) */ OsiCuts theseCuts; int i; int lastNumberCuts = 0; // reset probing info - //if (probingInfo_) - //probingInfo_->initializeFixing(); + // if (probingInfo_) + // probingInfo_->initializeFixing(); for (i = 0; i < numberCutGenerators_; i++) { if (generator_[i]->atSolution()) { generator_[i]->generateCuts(theseCuts, 1, solver_, NULL); @@ -13521,13 +13779,15 @@ CbcModel::checkSolution(double cutoff, double *solution, // { // /* As these are global cuts - // a) Always get debugger object - // b) Not fatal error to cutoff optimal (if we have just got optimal) + // b) Not fatal error to cutoff optimal (if we have just got + // optimal) // */ - // const OsiRowCutDebugger *debugger = solver_->getRowCutDebuggerAlways() ; - // if (debugger) + // const OsiRowCutDebugger *debugger = + // solver_->getRowCutDebuggerAlways() ; if (debugger) // { // if(debugger->invalidCut(*thisCut)) - // printf("ZZZZ Global cut - cuts off optimal solution!\n"); + // printf("ZZZZ Global cut - cuts off optimal + // solution!\n"); // } // } // add to global list @@ -13538,8 +13798,9 @@ CbcModel::checkSolution(double cutoff, double *solution, } else { // obviously wrong if (handler_->logLevel() > 1) - printf("Cut generator %s set to run on new solution but NOT globally valid!!\n", - generator_[i]->cutGeneratorName()); + printf("Cut generator %s set to run on new solution but NOT " + "globally valid!!\n", + generator_[i]->cutGeneratorName()); } } } @@ -13552,12 +13813,11 @@ CbcModel::checkSolution(double cutoff, double *solution, // globalCuts_.insert(*thisCut); // } // } - //have to retrieve the solution and its value from the nlp + // have to retrieve the solution and its value from the nlp } double newObjectiveValue = cutoff; - if (solverCharacteristics_->solution(newObjectiveValue, - const_cast< double * >(solution), - numberColumns)) { + if (solverCharacteristics_->solution( + newObjectiveValue, const_cast(solution), numberColumns)) { objectiveValue = newObjectiveValue; } else { objectiveValue = 2e50; @@ -13571,8 +13831,9 @@ CbcModel::checkSolution(double cutoff, double *solution, delete[] saveUpper; solver_->resolve(); } - //If the variables were fixed the cutting plane procedure may have believed that the node could be fathomed - //re-establish truth.- should do no harm for non nlp + // If the variables were fixed the cutting plane procedure may have believed + // that the node could be fathomed re-establish truth.- should do no harm for + // non nlp if (!solutionComesFromNlp && fixVariables > 0) solverCharacteristics_->setMipBound(-COIN_DBL_MAX); return objectiveValue; @@ -13597,9 +13858,8 @@ CbcModel::checkSolution(double cutoff, double *solution, original bounds (which may well invalidate the solution). */ -void CbcModel::setBestSolution(CBC_Message how, - double &objectiveValue, const double *solutionIn, - int fixVariables) +void CbcModel::setBestSolution(CBC_Message how, double &objectiveValue, + const double *solutionIn, int fixVariables) { @@ -13612,22 +13872,23 @@ void CbcModel::setBestSolution(CBC_Message how, double newTrueSolutionValue = -saveOffset; double newSumInfeas = 0.0; int numberColumns = solver_->getNumCols(); - for (int i = 0; i < numberColumns; i++) { + for (int i = 0; i < numberColumns; i++) { if (solver_->isInteger(i)) { double value = solution[i]; double nearest = floor(value + 0.5); newSumInfeas += fabs(value - nearest); } if (solution[i]) - printf("%d obj %g val %g - total %g true\n", i, obj[i], solution[i], - newTrueSolutionValue); + printf("%d (%c) obj %g val %g - total %g true\n", + i, solver_->isInteger(i) ? 'I':' ',obj[i], solution[i], + newTrueSolutionValue); newTrueSolutionValue += obj[i] * solution[i]; } printf("obj %g\n", newTrueSolutionValue); } #endif - OsiSolverInterface * saveContinuousSolver = NULL; - if ((moreSpecialOptions2_&65536)!=0) { + OsiSolverInterface *saveContinuousSolver = NULL; + if ((moreSpecialOptions2_ & 65536) != 0) { // May need cuts that are there saveContinuousSolver = continuousSolver_; continuousSolver_ = solver_->clone(); @@ -13643,20 +13904,23 @@ void CbcModel::setBestSolution(CBC_Message how, */ double saveObjectiveValue = objectiveValue; // save basis - CoinWarmStartBasis *basis = dynamic_cast< CoinWarmStartBasis * >(solver_->getWarmStart()); + CoinWarmStartBasis *basis = + dynamic_cast(solver_->getWarmStart()); assert(basis != NULL); - objectiveValue = checkSolution(cutoff, solution, fixVariables, objectiveValue); + objectiveValue = + checkSolution(cutoff, solution, fixVariables, objectiveValue); if (cutoff > 1.0e40 && objectiveValue < 1.0e10) saveObjectiveValue = objectiveValue; // take anyway - if (saveObjectiveValue + 1.0e-3 + 1.0e-7 * fabs(saveObjectiveValue) - < objectiveValue) { + if (saveObjectiveValue + 1.0e-3 + 1.0e-7 * fabs(saveObjectiveValue) < + objectiveValue) { #if CBC_FEASIBILITY_INVESTIGATE printf("First try at solution had objective %.16g, rechecked as %.16g\n", - saveObjectiveValue, objectiveValue); + saveObjectiveValue, objectiveValue); #endif // try again with basic variables with original bounds // save basis - CoinWarmStartBasis *basis2 = dynamic_cast< CoinWarmStartBasis * >(solver_->getWarmStart()); + CoinWarmStartBasis *basis2 = + dynamic_cast(solver_->getWarmStart()); assert(basis2 != NULL); solver_->setWarmStart(basis); int numberColumns = solver_->getNumCols(); @@ -13664,8 +13928,7 @@ void CbcModel::setBestSolution(CBC_Message how, double objectiveValue2 = saveObjectiveValue; objectiveValue2 = checkSolution(cutoff, solution2, -1, objectiveValue2); #if CBC_FEASIBILITY_INVESTIGATE - printf("Relaxed second try had objective of %.16g\n", - objectiveValue2); + printf("Relaxed second try had objective of %.16g\n", objectiveValue2); #endif if (objectiveValue2 + 1.0e-7 < objectiveValue) { // Now check tolerances @@ -13696,7 +13959,7 @@ void CbcModel::setBestSolution(CBC_Message how, } } for (i = 0; i < numberObjects_; i++) { - CbcSimpleInteger *obj = dynamic_cast< CbcSimpleInteger * >(object_[i]); + CbcSimpleInteger *obj = dynamic_cast(object_[i]); if (obj) { int iColumn = obj->columnNumber(); double value = solution2[iColumn]; @@ -13710,20 +13973,15 @@ void CbcModel::setBestSolution(CBC_Message how, #if CBC_FEASIBILITY_INVESTIGATE if (iInfeas >= 0) printf("Largest infeasibility of %g on column %d - tolerance %g\n", - largestInfeasibility, iInfeas, tolerance); + largestInfeasibility, iInfeas, tolerance); #endif if (largestAway > integerTolerance) { handler_->message(CBC_RELAXED1, messages_) - << objectiveValue2 - << iAway - << largestAway - << integerTolerance - << CoinMessageEol; + << objectiveValue2 << iAway << largestAway << integerTolerance + << CoinMessageEol; } else { handler_->message(CBC_RELAXED2, messages_) - << objectiveValue2 - << integerTolerance - << CoinMessageEol; + << objectiveValue2 << integerTolerance << CoinMessageEol; // take CoinCopyN(solution2, numberColumns, solution); objectiveValue = objectiveValue2; @@ -13731,34 +13989,34 @@ void CbcModel::setBestSolution(CBC_Message how, } else if (!parentModel_) { // not good messageHandler()->message(CBC_FPUMP2, messages()) - << "On closer inspection - solution discarded" - << CoinMessageEol; + << "On closer inspection - solution discarded" << CoinMessageEol; } delete[] solution2; solver_->setWarmStart(basis2); delete basis2; } delete basis; - if (objectiveValue > cutoff && objectiveValue < cutoff + 1.0e-8 + 1.0e-8 * fabs(cutoff)) + if (objectiveValue > cutoff && + objectiveValue < cutoff + 1.0e-8 + 1.0e-8 * fabs(cutoff)) cutoff = objectiveValue; // relax - CbcEventHandler::CbcAction action = dealWithEventHandler(CbcEventHandler::beforeSolution2, - objectiveValue, solution); + CbcEventHandler::CbcAction action = dealWithEventHandler( + CbcEventHandler::beforeSolution2, objectiveValue, solution); if (action == CbcEventHandler::killSolution) { // Pretend solution never happened objectiveValue = cutoff + 1.0e30; } - if ((moreSpecialOptions2_&65536)!=0) { + if ((moreSpecialOptions2_ & 65536) != 0) { const double *colsol = solver_->getColSolution(); for (int i = 0; i < numberIntegers_; i++) { - int iColumn = integerVariable_[i]; - double value = colsol[iColumn]; - double nearest = floor(value+0.5); - if (fabs(value-nearest)>1.0e-4) { - //printf("bad value of %g at %d\n",value,iColumn); - // Pretend solution never happened - objectiveValue = cutoff + 1.0e30; - break; - } + int iColumn = integerVariable_[i]; + double value = colsol[iColumn]; + double nearest = floor(value + 0.5); + if (fabs(value - nearest) > 1.0e-4) { + // printf("bad value of %g at %d\n",value,iColumn); + // Pretend solution never happened + objectiveValue = cutoff + 1.0e30; + break; + } } } /* @@ -13776,30 +14034,71 @@ void CbcModel::setBestSolution(CBC_Message how, handler_->message(CBC_NOTFEAS1, messages_) << CoinMessageEol; else handler_->message(CBC_NOTFEAS2, messages_) - << objectiveValue << cutoff << CoinMessageEol; + << objectiveValue << cutoff << CoinMessageEol; } else if (objectiveValue < bestObjective_) { /* We have a winner. Install it as the new incumbent. - Bump the objective cutoff value and solution counts. Give the user the - good news. + Bump the objective cutoff value and solution counts. Give the user + the good news. */ specialOptions_ |= 256; // mark as full cut scan should be done saveBestSolution(solution, objectiveValue); - //bestObjective_ = objectiveValue; - //int numberColumns = solver_->getNumCols(); - //if (!bestSolution_) - //bestSolution_ = new double[numberColumns]; - //CoinCopyN(solution,numberColumns,bestSolution_); + //#define SEE_HOW_MANY +#ifdef SEE_HOW_MANY + { + const double *dj = solver_->getReducedCost(); + const double *lower = solver_->getColLower(); + const double *upper = solver_->getColUpper(); + const double *lowerC = continuousSolver_->getColLower(); + const double *upperC = continuousSolver_->getColUpper(); + int nTotallyFixed = 0; + int nTotallyFixedBut = 0; + int nPartiallyFixed = 0; + int nPartiallyFixedBut = 0; + int nUntouched = 0; + for (int i = 0; i < numberIntegers_; i++) { + int iColumn = integerVariable_[i]; + if (lower[iColumn] == lowerC[iColumn] && + upper[iColumn] == upperC[iColumn]) { + nUntouched++; + } else if (lower[iColumn] == upper[iColumn]) { + if ((lower[iColumn] == lowerC[iColumn] && dj[iColumn] > 1.0e-5) || + (upper[iColumn] == upperC[iColumn] && dj[iColumn] < -1.0e-5)) + nTotallyFixedBut++; + else + nTotallyFixed++; + } else { + if ((lower[iColumn] == lowerC[iColumn] && dj[iColumn] > 1.0e-5) || + (upper[iColumn] == upperC[iColumn] && dj[iColumn] < -1.0e-5)) + nPartiallyFixedBut++; + else + nPartiallyFixed++; + } + } + printf("At solution nTotallyFixed %d , nTotallyFixedBut %d ,\ +nPartiallyFixed %d , nPartiallyFixedBut %d , nUntouched %d\n", + nTotallyFixed, nTotallyFixedBut, nPartiallyFixed, + nPartiallyFixedBut, nUntouched); + } +#endif + // bestObjective_ = objectiveValue; + // int numberColumns = solver_->getNumCols(); + // if (!bestSolution_) + // bestSolution_ = new double[numberColumns]; + // CoinCopyN(solution,numberColumns,bestSolution_); cutoff = bestObjective_ - dblParam_[CbcCutoffIncrement]; // But allow for rounding errors if (dblParam_[CbcCutoffIncrement] == 1e-4) { #if CBC_FEASIBILITY_INVESTIGATE if (saveObjectiveValue + 1.0e-7 < bestObjective_) - printf("First try at solution had objective %.16g, rechecked as %.16g\n", - saveObjectiveValue, bestObjective_); + printf( + "First try at solution had objective %.16g, rechecked as %.16g\n", + saveObjectiveValue, bestObjective_); #endif - saveObjectiveValue = CoinMax(saveObjectiveValue, bestObjective_ - 0.0000001 * fabs(bestObjective_)); + saveObjectiveValue = + CoinMax(saveObjectiveValue, + bestObjective_ - 0.0000001 * fabs(bestObjective_)); cutoff = CoinMin(bestObjective_, saveObjectiveValue) - 1.0e-5; if (fabs(cutoff + 1.0e-5 - floor(cutoff + 0.5)) < 1.0e-8) cutoff -= 2.0e-5; @@ -13813,8 +14112,8 @@ void CbcModel::setBestSolution(CBC_Message how, moreSpecialOptions2_ &= ~2; } // This is not correct - that way cutoff can go up if maximization - //double direction = solver_->getObjSense(); - //setCutoff(cutoff*direction); + // double direction = solver_->getObjSense(); + // setCutoff(cutoff*direction); setCutoff(cutoff); // change cutoff as constraint if wanted if (cutoffRowNumber_ >= 0) { @@ -13831,11 +14130,10 @@ void CbcModel::setBestSolution(CBC_Message how, if (how != CBC_ROUNDING) { handler_->message(how, messages_) - << bestObjective_ << numberIterations_ - << numberNodes_ << getCurrentSeconds() - << CoinMessageEol; - dealWithEventHandler(CbcEventHandler::solution, - objectiveValue, solution); + << bestObjective_ << numberIterations_ << numberNodes_ + << getCurrentSeconds() << CoinMessageEol; + dealWithEventHandler(CbcEventHandler::solution, objectiveValue, + solution); } else { const char *name; if (lastHeuristic_) @@ -13843,13 +14141,10 @@ void CbcModel::setBestSolution(CBC_Message how, else name = "Reduced search"; handler_->message(CBC_ROUNDING, messages_) - << bestObjective_ - << name - << numberIterations_ - << numberNodes_ << getCurrentSeconds() - << CoinMessageEol; - dealWithEventHandler(CbcEventHandler::heuristicSolution, - objectiveValue, solution); + << bestObjective_ << name << numberIterations_ << numberNodes_ + << getCurrentSeconds() << CoinMessageEol; + dealWithEventHandler(CbcEventHandler::heuristicSolution, objectiveValue, + solution); } } } else { @@ -13866,32 +14161,35 @@ void CbcModel::setBestSolution(CBC_Message how, CoinWarmStart *saveWs = NULL; // if(how!=CBC_SOLUTION) return; - if (how == CBC_ROUNDING) //We don't want to make any change to solver_ - //take a snapshot of current state + if (how == CBC_ROUNDING) // We don't want to make any change to solver_ + // take a snapshot of current state { - //save solution + // save solution saveColSol = new double[numberColBefore]; CoinCopyN(solver_->getColSolution(), numberColBefore, saveColSol); - //save warm start + // save warm start saveWs = solver_->getWarmStart(); } - //run check solution this will eventually generate cuts - //if in strongBranching or heuristic will do only one cut generation iteration + // run check solution this will eventually generate cuts + // if in strongBranching or heuristic will do only one cut generation + // iteration // by fixing variables. if (!fixVariables && ((how == CBC_ROUNDING) || (how == CBC_STRONGSOL))) fixVariables = 1; double *candidate = new double[numberColBefore]; CoinCopyN(solution, numberColBefore, candidate); - objectiveValue = checkSolution(cutoff, candidate, fixVariables, objectiveValue); + objectiveValue = + checkSolution(cutoff, candidate, fixVariables, objectiveValue); - //If it was an heuristic solution we have to clean up the solver + // If it was an heuristic solution we have to clean up the solver if (how == CBC_ROUNDING) { - //delete the cuts + // delete the cuts int currentNumberRowCuts = solver_->getNumRows() - numberRowBefore; int currentNumberColCuts = solver_->getNumCols() - numberColBefore; if (CoinMax(currentNumberColCuts, currentNumberRowCuts) > 0) { - int *which = new int[CoinMax(currentNumberColCuts, currentNumberRowCuts)]; + int *which = + new int[CoinMax(currentNumberColCuts, currentNumberRowCuts)]; if (currentNumberRowCuts) { for (int i = 0; i < currentNumberRowCuts; i++) which[i] = i + numberRowBefore; @@ -13920,22 +14218,21 @@ void CbcModel::setBestSolution(CBC_Message how, handler_->message(CBC_NOTFEAS1, messages_) << CoinMessageEol; else handler_->message(CBC_NOTFEAS2, messages_) - << objectiveValue << cutoff << CoinMessageEol; + << objectiveValue << cutoff << CoinMessageEol; } } } else { /* We have a winner. Install it as the new incumbent. - Bump the objective cutoff value and solution counts. Give the user the - good news. - NB - Not all of this if from solve with cuts + Bump the objective cutoff value and solution counts. Give the user + the good news. NB - Not all of this if from solve with cuts */ saveBestSolution(candidate, objectiveValue); - //bestObjective_ = objectiveValue; - //int numberColumns = solver_->getNumCols(); - //if (!bestSolution_) - //bestSolution_ = new double[numberColumns]; - //CoinCopyN(candidate,numberColumns,bestSolution_); + // bestObjective_ = objectiveValue; + // int numberColumns = solver_->getNumCols(); + // if (!bestSolution_) + // bestSolution_ = new double[numberColumns]; + // CoinCopyN(candidate,numberColumns,bestSolution_); // don't update if from solveWithCuts if (how != CBC_SOLUTION2) { @@ -13943,8 +14240,8 @@ void CbcModel::setBestSolution(CBC_Message how, numberHeuristicSolutions_++; cutoff = bestObjective_ - dblParam_[CbcCutoffIncrement]; // This is not correct - that way cutoff can go up if maximization - //double direction = solver_->getObjSense(); - //setCutoff(cutoff*direction); + // double direction = solver_->getObjSense(); + // setCutoff(cutoff*direction); setCutoff(cutoff); // change cutoff as constraint if wanted if (cutoffRowNumber_ >= 0) { @@ -13959,18 +14256,14 @@ void CbcModel::setBestSolution(CBC_Message how, if (how != CBC_ROUNDING) { handler_->message(how, messages_) - << bestObjective_ << numberIterations_ - << numberNodes_ << getCurrentSeconds() - << CoinMessageEol; + << bestObjective_ << numberIterations_ << numberNodes_ + << getCurrentSeconds() << CoinMessageEol; } else { assert(lastHeuristic_); const char *name = lastHeuristic_->heuristicName(); handler_->message(CBC_ROUNDING, messages_) - << bestObjective_ - << name - << numberIterations_ - << numberNodes_ << getCurrentSeconds() - << CoinMessageEol; + << bestObjective_ << name << numberIterations_ << numberNodes_ + << getCurrentSeconds() << CoinMessageEol; } } } @@ -13986,10 +14279,8 @@ void CbcModel::setBestSolution(CBC_Message how, } // Deals with event handler and solution CbcEventHandler::CbcAction -CbcModel::dealWithEventHandler(CbcEventHandler::CbcEvent event, - double objValue, - const double *solution) -{ +CbcModel::dealWithEventHandler(CbcEventHandler::CbcEvent event, double objValue, + const double *solution) { CbcEventHandler *eventHandler = getEventHandler(); if (eventHandler) { // Temporarily put in best @@ -14024,17 +14315,16 @@ CbcModel::dealWithEventHandler(CbcEventHandler::CbcEvent event, the comments about `odd ones' infeasibilities. */ bool CbcModel::feasibleSolution(int &numberIntegerInfeasibilities, - int &numberObjectInfeasibilities) const -{ + int &numberObjectInfeasibilities) const { int numberUnsatisfied = 0; - //double sumUnsatisfied=0.0; + // double sumUnsatisfied=0.0; int j; // Point to current solution const double *save = testSolution_; // Safe as will be const inside infeasibility() testSolution_ = solver_->getColSolution(); // Put current solution in safe place - //memcpy(currentSolution_,solver_->getColSolution(), + // memcpy(currentSolution_,solver_->getColSolution(), // solver_->getNumCols()*sizeof(double)); // point to useful information OsiBranchingInformation usefulInfo = usefulInformation(); @@ -14052,7 +14342,7 @@ bool CbcModel::feasibleSolution(int &numberIntegerInfeasibilities, if (infeasibility) { assert(infeasibility > 0); numberUnsatisfied++; - //sumUnsatisfied += infeasibility; + // sumUnsatisfied += infeasibility; } #else int iColumn = integerVariable_[j]; @@ -14072,12 +14362,13 @@ bool CbcModel::feasibleSolution(int &numberIntegerInfeasibilities, if (infeasibility) { assert(infeasibility > 0); numberUnsatisfied++; - //sumUnsatisfied += infeasibility; + // sumUnsatisfied += infeasibility; } } // and restore testSolution_ = save; - numberObjectInfeasibilities = numberUnsatisfied - numberIntegerInfeasibilities; + numberObjectInfeasibilities = + numberUnsatisfied - numberIntegerInfeasibilities; return (!numberUnsatisfied); } @@ -14087,8 +14378,8 @@ bool CbcModel::feasibleSolution(int &numberIntegerInfeasibilities, -1 just vubs where variable away from bound Returns false if not feasible */ -bool CbcModel::tightenVubs(int type, bool allowMultipleBinary, double useCutoff) -{ +bool CbcModel::tightenVubs(int type, bool allowMultipleBinary, + double useCutoff) { CoinPackedMatrix matrixByRow(*solver_->getMatrixByRow()); int numberRows = solver_->getNumRows(); @@ -14097,18 +14388,18 @@ bool CbcModel::tightenVubs(int type, bool allowMultipleBinary, double useCutoff) int iRow, iColumn; // Row copy - //const double * elementByRow = matrixByRow.getElements(); + // const double * elementByRow = matrixByRow.getElements(); const int *column = matrixByRow.getIndices(); const CoinBigIndex *rowStart = matrixByRow.getVectorStarts(); const int *rowLength = matrixByRow.getVectorLengths(); const double *colUpper = solver_->getColUpper(); const double *colLower = solver_->getColLower(); - //const double * rowUpper = solver_->getRowUpper(); - //const double * rowLower = solver_->getRowLower(); + // const double * rowUpper = solver_->getRowUpper(); + // const double * rowLower = solver_->getRowLower(); const double *objective = solver_->getObjCoefficients(); - //double direction = solver_->getObjSense(); + // double direction = solver_->getObjSense(); const double *colsol = solver_->getColSolution(); int numberVub = 0; @@ -14131,7 +14422,8 @@ bool CbcModel::tightenVubs(int type, bool allowMultipleBinary, double useCutoff) x - a * delta <=0 or -x + a * delta >= 0 */ - if (colsol[iColumn] > colLower[iColumn] + 1.0e-6 && colsol[iColumn] < colUpper[iColumn] - 1.0e-6) { + if (colsol[iColumn] > colLower[iColumn] + 1.0e-6 && + colsol[iColumn] < colUpper[iColumn] - 1.0e-6) { numberUnsatisfiedBinary++; weight = CoinMin(weight, fabs(objective[iColumn])); } @@ -14169,8 +14461,7 @@ bool CbcModel::tightenVubs(int type, bool allowMultipleBinary, double useCutoff) } // This version is just handed a list of variables bool CbcModel::tightenVubs(int numberSolves, const int *which, - double useCutoff) -{ + double useCutoff) { int numberColumns = solver_->getNumCols(); @@ -14180,7 +14471,8 @@ bool CbcModel::tightenVubs(int numberSolves, const int *which, double saveCutoff = getCutoff(); double *objective = new double[numberColumns]; - memcpy(objective, solver_->getObjCoefficients(), numberColumns * sizeof(double)); + memcpy(objective, solver_->getObjCoefficients(), + numberColumns * sizeof(double)); double direction = solver_->getObjSense(); // add in objective if there is a cutoff @@ -14213,10 +14505,10 @@ bool CbcModel::tightenVubs(int numberSolves, const int *which, CglProbing *generator = NULL; int iGen; // reset probing info - //if (probingInfo_) - //probingInfo_->initializeFixing(); + // if (probingInfo_) + // probingInfo_->initializeFixing(); for (iGen = 0; iGen < numberCutGenerators_; iGen++) { - generator = dynamic_cast< CglProbing * >(generator_[iGen]->generator()); + generator = dynamic_cast(generator_[iGen]->generator()); if (generator) break; } @@ -14225,7 +14517,7 @@ bool CbcModel::tightenVubs(int numberSolves, const int *which, int numberFixedByProbing = 0; int numberTightenedByProbing = 0; int printFrequency = (numberSolves + 19) / 20; // up to 20 messages - int save[4] = { 0, 0, 0, 0 }; + int save[4] = {0, 0, 0, 0}; if (generator) { // set to cheaper and then restore at end save[0] = generator->getMaxPass(); @@ -14247,7 +14539,8 @@ bool CbcModel::tightenVubs(int numberSolves, const int *which, for (iColumn = 0; iColumn < numberColumns; iColumn++) { double newUpper = tightUpper[iColumn]; double newLower = tightLower[iColumn]; - if (newUpper < upper[iColumn] - 1.0e-8 * (fabs(upper[iColumn]) + 1) || newLower > lower[iColumn] + 1.0e-8 * (fabs(lower[iColumn]) + 1)) { + if (newUpper < upper[iColumn] - 1.0e-8 * (fabs(upper[iColumn]) + 1) || + newLower > lower[iColumn] + 1.0e-8 * (fabs(lower[iColumn]) + 1)) { if (newUpper < newLower) { fprintf(stderr, "Problem is infeasible\n"); return false; @@ -14258,18 +14551,16 @@ bool CbcModel::tightenVubs(int numberSolves, const int *which, solver->setColLower(iColumn, newLower); solver->setColUpper(iColumn, newUpper); COIN_DETAIL_PRINT(printf("Column %d, new bounds %g %g\n", iColumn, - newLower, newUpper)); + newLower, newUpper)); } else if (vub[iColumn]) { numberTightened++; numberTightenedByProbing++; if (!solver->isInteger(iColumn)) { // relax newLower = CoinMax(lower[iColumn], - newLower - - 1.0e-5 * (fabs(lower[iColumn]) + 1)); + newLower - 1.0e-5 * (fabs(lower[iColumn]) + 1)); newUpper = CoinMin(upper[iColumn], - newUpper - + 1.0e-5 * (fabs(upper[iColumn]) + 1)); + newUpper + 1.0e-5 * (fabs(upper[iColumn]) + 1)); } solver->setColLower(iColumn, newLower); solver->setColUpper(iColumn, newUpper); @@ -14282,7 +14573,7 @@ bool CbcModel::tightenVubs(int numberSolves, const int *which, memcpy(solution, solver->getColSolution(), numberColumns * sizeof(double)); for (iColumn = 0; iColumn < numberColumns; iColumn++) solver->setObjCoeff(iColumn, 0.0); - //solver->messageHandler()->setLogLevel(2); + // solver->messageHandler()->setLogLevel(2); for (iVub = 0; iVub < numberSolves; iVub++) { iColumn = which[iVub]; int iTry; @@ -14351,7 +14642,10 @@ bool CbcModel::tightenVubs(int numberSolves, const int *which, for (jColumn = 0; jColumn < numberColumns; jColumn++) { double newUpper = tightUpper[jColumn]; double newLower = tightLower[jColumn]; - if (newUpper < upper[jColumn] - 1.0e-8 * (fabs(upper[jColumn]) + 1) || newLower > lower[jColumn] + 1.0e-8 * (fabs(lower[jColumn]) + 1)) { + if (newUpper < + upper[jColumn] - 1.0e-8 * (fabs(upper[jColumn]) + 1) || + newLower > + lower[jColumn] + 1.0e-8 * (fabs(lower[jColumn]) + 1)) { if (newUpper < newLower) { fprintf(stderr, "Problem is infeasible\n"); delete[] solution; @@ -14367,12 +14661,12 @@ bool CbcModel::tightenVubs(int numberSolves, const int *which, numberTightenedByProbing++; if (!solver->isInteger(jColumn)) { // relax - newLower = CoinMax(lower[jColumn], - newLower - - 1.0e-8 * (fabs(lower[jColumn]) + 1)); - newUpper = CoinMin(upper[jColumn], - newUpper - + 1.0e-8 * (fabs(upper[jColumn]) + 1)); + newLower = + CoinMax(lower[jColumn], + newLower - 1.0e-8 * (fabs(lower[jColumn]) + 1)); + newUpper = + CoinMin(upper[jColumn], + newUpper + 1.0e-8 * (fabs(upper[jColumn]) + 1)); } solver->setColLower(jColumn, newLower); solver->setColUpper(jColumn, newUpper); @@ -14393,13 +14687,13 @@ bool CbcModel::tightenVubs(int numberSolves, const int *which, if (!solver->isProvenOptimal()) { fprintf(stderr, "Problem is infeasible\n"); if (vub) - delete[] vub; + delete[] vub; return false; } delete ws; ws = solver->getWarmStart(); memcpy(solution, solver->getColSolution(), - numberColumns * sizeof(double)); + numberColumns * sizeof(double)); for (jColumn = 0; jColumn < numberColumns; jColumn++) solver->setObjCoeff(jColumn, 0.0); } @@ -14409,12 +14703,10 @@ bool CbcModel::tightenVubs(int numberSolves, const int *which, } if (iVub % printFrequency == 0) handler_->message(CBC_VUB_PASS, messages_) - << iVub + 1 << numberFixed << numberTightened - << CoinMessageEol; + << iVub + 1 << numberFixed << numberTightened << CoinMessageEol; } handler_->message(CBC_VUB_END, messages_) - << numberFixed << numberTightened - << CoinMessageEol; + << numberFixed << numberTightened << CoinMessageEol; delete ws; delete[] solution; // go back to true costs to solve if exists @@ -14428,7 +14720,9 @@ bool CbcModel::tightenVubs(int numberSolves, const int *which, /*printf("Probing fixed %d and tightened %d\n", numberFixedByProbing, numberTightenedByProbing);*/ - if (generator_[iGen]->howOften() == -1 && (numberFixedByProbing + numberTightenedByProbing) * 5 > (numberFixed + numberTightened)) + if (generator_[iGen]->howOften() == -1 && + (numberFixedByProbing + numberTightenedByProbing) * 5 > + (numberFixed + numberTightened)) generator_[iGen]->setHowOften(1000000 + 1); generator->setMaxPass(save[0]); generator->setMaxProbe(save[1]); @@ -14443,8 +14737,10 @@ bool CbcModel::tightenVubs(int numberSolves, const int *which, const double *lowerOrig = solver_->getColLower(); const double *upperOrig = solver_->getColUpper(); for (iColumn = 0; iColumn < numberColumns; iColumn++) { - solver_->setColLower(iColumn, CoinMax(lower[iColumn], lowerOrig[iColumn])); - solver_->setColUpper(iColumn, CoinMin(upper[iColumn], upperOrig[iColumn])); + solver_->setColLower(iColumn, + CoinMax(lower[iColumn], lowerOrig[iColumn])); + solver_->setColUpper(iColumn, + CoinMin(upper[iColumn], upperOrig[iColumn])); } delete solver; } @@ -14452,8 +14748,7 @@ bool CbcModel::tightenVubs(int numberSolves, const int *which, return true; } // Pass in Message handler (not deleted at end) -void CbcModel::passInMessageHandler(CoinMessageHandler *handler) -{ +void CbcModel::passInMessageHandler(CoinMessageHandler *handler) { if (defaultHandler_) { delete handler_; handler_ = NULL; @@ -14469,14 +14764,12 @@ void CbcModel::passInMessageHandler(CoinMessageHandler *handler) if (atSolutionSolver_) atSolutionSolver_->passInMessageHandler(handler); } -void CbcModel::passInTreeHandler(CbcTree &tree) -{ +void CbcModel::passInTreeHandler(CbcTree &tree) { delete tree_; tree_ = tree.clone(); } // Make sure region there -void CbcModel::reserveCurrentSolution(const double *solution) -{ +void CbcModel::reserveCurrentSolution(const double *solution) { int numberColumns = getNumCols(); if (!currentSolution_) currentSolution_ = new double[numberColumns]; @@ -14487,14 +14780,9 @@ void CbcModel::reserveCurrentSolution(const double *solution) /* For passing in an CbcModel to do a sub Tree (with derived tree handlers). Passed in model must exist for duration of branch and bound */ -void CbcModel::passInSubTreeModel(CbcModel &model) -{ - subTreeModel_ = &model; -} +void CbcModel::passInSubTreeModel(CbcModel &model) { subTreeModel_ = &model; } // For retrieving a copy of subtree model with given OsiSolver or NULL -CbcModel * -CbcModel::subTreeModel(OsiSolverInterface *solver) const -{ +CbcModel *CbcModel::subTreeModel(OsiSolverInterface *solver) const { const CbcModel *subModel = subTreeModel_; if (!subModel) subModel = this; @@ -14511,34 +14799,24 @@ CbcModel::subTreeModel(OsiSolverInterface *solver) const // This field is the application to optionally define and use. //############################################################################# -void CbcModel::setApplicationData(void *appData) -{ - appData_ = appData; -} +void CbcModel::setApplicationData(void *appData) { appData_ = appData; } //----------------------------------------------------------------------------- -void *CbcModel::getApplicationData() const -{ - return appData_; -} +void *CbcModel::getApplicationData() const { return appData_; } // Set a pointer to a row cut which will be added instead of normal branching. -void CbcModel::setNextRowCut(const OsiRowCut &cut) -{ +void CbcModel::setNextRowCut(const OsiRowCut &cut) { nextRowCut_ = new OsiRowCut(cut); nextRowCut_->setEffectiveness(COIN_DBL_MAX); // mark so will always stay } // Just update objectiveValue -void CbcModel::setBestObjectiveValue(double objectiveValue) -{ +void CbcModel::setBestObjectiveValue(double objectiveValue) { bestObjective_ = objectiveValue; } -double -CbcModel::getBestPossibleObjValue() const -{ - return CoinMin(bestPossibleObjective_, bestObjective_) * solver_->getObjSense(); +double CbcModel::getBestPossibleObjValue() const { + return CoinMin(bestPossibleObjective_, bestObjective_) * + solver_->getObjSense(); } // Make given rows (L or G) into global cuts and remove from lp -void CbcModel::makeGlobalCuts(int number, const int *which) -{ +void CbcModel::makeGlobalCuts(int number, const int *which) { const double *rowLower = solver_->getRowLower(); const double *rowUpper = solver_->getRowUpper(); @@ -14562,7 +14840,8 @@ void CbcModel::makeGlobalCuts(int number, const int *which) thisCut.setLb(rowLower[iRow]); thisCut.setUb(rowUpper[iRow]); CoinBigIndex start = rowStart[iRow]; - thisCut.setRow(rowLength[iRow], column + start, elementByRow + start, false); + thisCut.setRow(rowLength[iRow], column + start, elementByRow + start, + false); thisCut.setGloballyValid(true); globalCuts_.addCutIfNotDuplicate(thisCut); } @@ -14573,8 +14852,7 @@ void CbcModel::makeGlobalCuts(int number, const int *which) delete[] whichDelete; } // Make given cut into a global cut -int CbcModel::makeGlobalCut(const OsiRowCut *cut) -{ +int CbcModel::makeGlobalCut(const OsiRowCut *cut) { if (cut->row().getNumElements() > 1 - 1) { OsiRowCut newCut(*cut); newCut.setGloballyValidAsInteger(2); @@ -14605,8 +14883,8 @@ int CbcModel::makeGlobalCut(const OsiRowCut *cut) #if PRINT_CONFLICT == 0 if (handler_->logLevel() > 1) { #endif - printf("Conflict cut at depth %d (%d elements)\n", - currentDepth_, cut->row().getNumElements()); + printf("Conflict cut at depth %d (%d elements)\n", currentDepth_, + cut->row().getNumElements()); cut->print(); #if PRINT_CONFLICT == 0 } @@ -14632,16 +14910,14 @@ int CbcModel::makeGlobalCut(const OsiRowCut *cut) } } // Make given cut into a global cut -int CbcModel::makeGlobalCut(const OsiRowCut &cut) -{ +int CbcModel::makeGlobalCut(const OsiRowCut &cut) { OsiRowCut newCut(cut); newCut.setGloballyValid(true); newCut.mutableRow().setTestForDuplicateIndex(false); return globalCuts_.addCutIfNotDuplicate(newCut); } // Make given column cut into a global cut -void CbcModel::makeGlobalCut(const OsiColCut *cut) -{ +void CbcModel::makeGlobalCut(const OsiColCut *cut) { const double *lower; const double *upper; if (topOfTree_) { @@ -14675,8 +14951,7 @@ void CbcModel::makeGlobalCut(const OsiColCut *cut) } } // Make given column cut into a global cut -void CbcModel::makeGlobalCut(const OsiColCut &cut) -{ +void CbcModel::makeGlobalCut(const OsiColCut &cut) { const double *lower; const double *upper; if (topOfTree_) { @@ -14711,8 +14986,7 @@ void CbcModel::makeGlobalCut(const OsiColCut &cut) } // Make partial cut into a global cut and save void CbcModel::makePartialCut(const OsiRowCut *partialCut, - const OsiSolverInterface *solver) -{ + const OsiSolverInterface *solver) { // get greedy cut double bSum = partialCut->lb(); assert(bSum < 0.0); @@ -14758,10 +15032,12 @@ void CbcModel::makePartialCut(const OsiRowCut *partialCut, } newCut.setLb(lo); newCut.setRow(nConflict, column, values); - printf("CUTa has %d (started at %d) - final bSum %g - depth %d\n", nConflict, nC, bSum, currentDepth_); + printf("CUTa has %d (started at %d) - final bSum %g - depth %d\n", nConflict, + nC, bSum, currentDepth_); if (nConflict > 1) { if ((specialOptions_ & 1) != 0) { - const OsiRowCutDebugger *debugger = continuousSolver_->getRowCutDebugger(); + const OsiRowCutDebugger *debugger = + continuousSolver_->getRowCutDebugger(); if (debugger) { if (debugger->invalidCut(newCut)) { continuousSolver_->applyRowCuts(1, &newCut); @@ -14780,15 +15056,15 @@ void CbcModel::makePartialCut(const OsiRowCut *partialCut, // change upper bound double newUpper = -lo; assert(newUpper < originalUpper[iColumn]); - printf("Changing upper bound on %d from %g to %g\n", - iColumn, originalUpper[iColumn], newUpper); + printf("Changing upper bound on %d from %g to %g\n", iColumn, + originalUpper[iColumn], newUpper); originalUpper[iColumn] = newUpper; } else { // change lower bound double newLower = lo; assert(newLower > originalLower[iColumn]); - printf("Changing lower bound on %d from %g to %g\n", - iColumn, originalLower[iColumn], newLower); + printf("Changing lower bound on %d from %g to %g\n", iColumn, + originalLower[iColumn], newLower); originalLower[iColumn] = newLower; } } @@ -14799,38 +15075,30 @@ void CbcModel::makePartialCut(const OsiRowCut *partialCut, delete[] values; } // Make partial cuts into global cuts -void CbcModel::makeGlobalCuts() -{ -} -void CbcModel::setNodeComparison(CbcCompareBase *compare) -{ +void CbcModel::makeGlobalCuts() {} +void CbcModel::setNodeComparison(CbcCompareBase *compare) { delete nodeCompare_; nodeCompare_ = compare->clone(); } -void CbcModel::setNodeComparison(CbcCompareBase &compare) -{ +void CbcModel::setNodeComparison(CbcCompareBase &compare) { delete nodeCompare_; nodeCompare_ = compare.clone(); } -void CbcModel::setProblemFeasibility(CbcFeasibilityBase *feasibility) -{ +void CbcModel::setProblemFeasibility(CbcFeasibilityBase *feasibility) { delete problemFeasibility_; problemFeasibility_ = feasibility->clone(); } -void CbcModel::setProblemFeasibility(CbcFeasibilityBase &feasibility) -{ +void CbcModel::setProblemFeasibility(CbcFeasibilityBase &feasibility) { delete problemFeasibility_; problemFeasibility_ = feasibility.clone(); } // Set the strategy. Clones -void CbcModel::setStrategy(CbcStrategy &strategy) -{ +void CbcModel::setStrategy(CbcStrategy &strategy) { delete strategy_; strategy_ = strategy.clone(); } // Increases usedInSolution for nonzeros -void CbcModel::incrementUsed(const double *solution) -{ +void CbcModel::incrementUsed(const double *solution) { if (usedInSolution_) { // might as well mark all including continuous int numberColumns = solver_->getNumCols(); @@ -14841,8 +15109,7 @@ void CbcModel::incrementUsed(const double *solution) } } // Are there numerical difficulties (for initialSolve) ? -bool CbcModel::isInitialSolveAbandoned() const -{ +bool CbcModel::isInitialSolveAbandoned() const { if (status_ != -1) { return false; } else { @@ -14850,8 +15117,7 @@ bool CbcModel::isInitialSolveAbandoned() const } } // Is optimality proven (for initialSolve) ? -bool CbcModel::isInitialSolveProvenOptimal() const -{ +bool CbcModel::isInitialSolveProvenOptimal() const { if (status_ != -1) { return fabs(originalContinuousObjective_) < 1.0e50; } else { @@ -14859,8 +15125,7 @@ bool CbcModel::isInitialSolveProvenOptimal() const } } // Is primal infeasiblity proven (for initialSolve) ? -bool CbcModel::isInitialSolveProvenPrimalInfeasible() const -{ +bool CbcModel::isInitialSolveProvenPrimalInfeasible() const { if (status_ != -1) { if (status_ == 0 && secondaryStatus_ == 7) return false; @@ -14871,8 +15136,7 @@ bool CbcModel::isInitialSolveProvenPrimalInfeasible() const } } // Is dual infeasiblity proven (for initialSolve) ? -bool CbcModel::isInitialSolveProvenDualInfeasible() const -{ +bool CbcModel::isInitialSolveProvenDualInfeasible() const { if (status_ != -1) { if (status_ == 0 && secondaryStatus_ == 7) return true; @@ -14883,8 +15147,7 @@ bool CbcModel::isInitialSolveProvenDualInfeasible() const } } // Set pointers for speed -void CbcModel::setPointers(const OsiSolverInterface *solver) -{ +void CbcModel::setPointers(const OsiSolverInterface *solver) { /// Pointer to array[getNumCols()] (for speed) of column lower bounds cbcColLower_ = solver_->getColLower(); /// Pointer to array[getNumCols()] (for speed) of column upper bounds @@ -14905,14 +15168,14 @@ void CbcModel::setPointers(const OsiSolverInterface *solver) /// Pointer to array[getNumRows()] (for speed) of row activity levels. cbcRowActivity_ = solver_->getRowActivity(); dblParam_[CbcCurrentObjectiveValue] = solver->getObjValue(); - dblParam_[CbcCurrentMinimizationObjectiveValue] = dblParam_[CbcCurrentObjectiveValue] * dblParam_[CbcOptimizationDirection]; + dblParam_[CbcCurrentMinimizationObjectiveValue] = + dblParam_[CbcCurrentObjectiveValue] * dblParam_[CbcOptimizationDirection]; } /* Delete any existing handler and create a clone of the one supplied. */ -void CbcModel::passInEventHandler(const CbcEventHandler *eventHandler) -{ +void CbcModel::passInEventHandler(const CbcEventHandler *eventHandler) { delete eventHandler_; eventHandler_ = NULL; if (eventHandler) { @@ -14926,12 +15189,11 @@ void CbcModel::passInEventHandler(const CbcEventHandler *eventHandler) */ // Encapsulates solver resolve -int CbcModel::resolve(OsiSolverInterface *solver) -{ +int CbcModel::resolve(OsiSolverInterface *solver) { numberSolves_++; #ifdef CBC_HAS_CLP - OsiClpSolverInterface *clpSolver - = dynamic_cast< OsiClpSolverInterface * >(solver); + OsiClpSolverInterface *clpSolver = + dynamic_cast(solver); #endif #ifdef CLIQUE_ANALYSIS if (probingInfo_ && currentDepth_ > 0) { @@ -14953,19 +15215,20 @@ int CbcModel::resolve(OsiSolverInterface *solver) if (clpSolver) { /*bool takeHint; OsiHintStrength strength; - bool gotHint = (clpSolver->getHintParam(OsiDoDualInResolve,takeHint,strength)); - assert (gotHint); - int algorithm=-1; - if (strength!=OsiHintIgnore) - algorithm = takeHint ? -1 : 1; - assert (algorithm==-1);*/ - //clpSolver->setHintParam(OsiDoDualInResolve,true,OsiHintTry); + bool gotHint = + (clpSolver->getHintParam(OsiDoDualInResolve,takeHint,strength)); assert + (gotHint); int algorithm=-1; if (strength!=OsiHintIgnore) algorithm = + takeHint ? -1 : 1; assert (algorithm==-1);*/ + // clpSolver->setHintParam(OsiDoDualInResolve,true,OsiHintTry); ClpSimplex *clpSimplex = clpSolver->getModelPtr(); int save = clpSimplex->specialOptions(); if ((moreSpecialOptions_ & 8388608) == 0) - clpSimplex->setSpecialOptions(save | 0x11000000); // say is Cbc (and in branch and bound) + clpSimplex->setSpecialOptions( + save | 0x11000000); // say is Cbc (and in branch and bound) else - clpSimplex->setSpecialOptions(save | 0x11200000); // say is Cbc (and in branch and bound - but save ray) + clpSimplex->setSpecialOptions( + save | + 0x11200000); // say is Cbc (and in branch and bound - but save ray) int save2 = clpSolver->specialOptions(); if (false && (save2 & 2048) == 0) { // see if worthwhile crunching @@ -14979,10 +15242,8 @@ int CbcModel::resolve(OsiSolverInterface *solver) } if (nFixed * 20 < clpSimplex->numberColumns()) { double d = nFixed; - printf("%d fixed out of %d - ratio %g\n", - nFixed, - clpSimplex->numberColumns(), - d / clpSimplex->numberColumns()); + printf("%d fixed out of %d - ratio %g\n", nFixed, + clpSimplex->numberColumns(), d / clpSimplex->numberColumns()); clpSolver->setSpecialOptions(save2 | 2048); } } @@ -15002,15 +15263,15 @@ int CbcModel::resolve(OsiSolverInterface *solver) static int nInfSolves = 0; static int nRays = 0; nSolves++; - if (!parentModel_ && clpSolver->getModelPtr()->problemStatus() == 1 - && (clpSolver->getModelPtr()->specialOptions() & 32) != 0) { + if (!parentModel_ && clpSolver->getModelPtr()->problemStatus() == 1 && + (clpSolver->getModelPtr()->specialOptions() & 32) != 0) { nInfSolves++; if (clpSolver->getModelPtr()->infeasibilityRay()) nRays++; } if ((nSolves % 1000) == 0) - printf("ZZ %d solves, %d infeasible %d rays\n", - nSolves, nInfSolves, nRays); + printf("ZZ %d solves, %d infeasible %d rays\n", nSolves, nInfSolves, + nRays); #endif #ifdef CHECK_KNOWN_SOLUTION if ((specialOptions_ & 1) != 0 && onOptimalPath) { @@ -15047,13 +15308,14 @@ int CbcModel::resolve(OsiSolverInterface *solver) } #endif double error = CoinMax(clpSimplex->largestDualError(), - clpSimplex->largestPrimalError()); + clpSimplex->largestPrimalError()); if (error > 1.0e-2 || !clpSolver->isProvenOptimal()) { #if CBC_USEFUL_PRINTING > 1 - printf("Problem was %s largest dual error %g largest primal %g - safer cuts\n", - clpSolver->isProvenOptimal() ? "optimal" : "!infeasible", - clpSimplex->largestDualError(), - clpSimplex->largestPrimalError()); + printf("Problem was %s largest dual error %g largest primal %g - safer " + "cuts\n", + clpSolver->isProvenOptimal() ? "optimal" : "!infeasible", + clpSimplex->largestDualError(), + clpSimplex->largestPrimalError()); #endif if (!clpSolver->isProvenOptimal()) { // check if proven infeasible i.e. bad bounds @@ -15081,13 +15343,14 @@ int CbcModel::resolve(OsiSolverInterface *solver) } } // make cuts safer - for (int iCutGenerator = 0; iCutGenerator < numberCutGenerators_; iCutGenerator++) { + for (int iCutGenerator = 0; iCutGenerator < numberCutGenerators_; + iCutGenerator++) { CglCutGenerator *generator = generator_[iCutGenerator]->generator(); - CglGomory *cgl1 = dynamic_cast< CglGomory * >(generator); + CglGomory *cgl1 = dynamic_cast(generator); if (cgl1) { cgl1->setLimitAtRoot(cgl1->getLimit()); } - CglTwomir *cgl2 = dynamic_cast< CglTwomir * >(generator); + CglTwomir *cgl2 = dynamic_cast(generator); if (cgl2) { generator_[iCutGenerator]->setHowOften(-100); } @@ -15097,7 +15360,8 @@ int CbcModel::resolve(OsiSolverInterface *solver) clpSolver->setSpecialOptions(save2); #if CBC_USEFUL_PRINTING > 1 if (clpSimplex->numberIterations() > 1000) - printf("node %d took %d iterations\n", numberNodes_, clpSimplex->numberIterations()); + printf("node %d took %d iterations\n", numberNodes_, + clpSimplex->numberIterations()); #endif clpSimplex->setSpecialOptions(save); if (clpSimplex->status() == 4) @@ -15119,23 +15383,23 @@ int CbcModel::resolve(OsiSolverInterface *solver) } #ifdef CLP_RESOLVE // Special purpose resolve -int CbcModel::resolveClp(OsiClpSolverInterface *clpSolver, int type) -{ +int CbcModel::resolveClp(OsiClpSolverInterface *clpSolver, int type) { numberSolves_++; ClpSimplex *clpSimplex = clpSolver->getModelPtr(); int save = clpSimplex->specialOptions(); - clpSimplex->setSpecialOptions(save | 0x11000000); // say is Cbc (and in branch and bound) + clpSimplex->setSpecialOptions( + save | 0x11000000); // say is Cbc (and in branch and bound) int save2 = clpSolver->specialOptions(); clpSolver->resolve(); if (!numberNodes_) { double error = CoinMax(clpSimplex->largestDualError(), - clpSimplex->largestPrimalError()); + clpSimplex->largestPrimalError()); if (error > 1.0e-2 || !clpSolver->isProvenOptimal()) { #if CBC_USEFUL_PRINTING > 1 - printf("Problem was %s largest dual error %g largest primal %g - safer cuts\n", - clpSolver->isProvenOptimal() ? "optimal" : "!infeasible", - clpSimplex->largestDualError(), - clpSimplex->largestPrimalError()); + printf("Problem was %s largest dual error %g largest primal %g - safer " + "cuts\n", + clpSolver->isProvenOptimal() ? "optimal" : "!infeasible", + clpSimplex->largestDualError(), clpSimplex->largestPrimalError()); #endif if (!clpSolver->isProvenOptimal()) { clpSolver->setSpecialOptions(save2 | 2048); @@ -15151,13 +15415,14 @@ int CbcModel::resolveClp(OsiClpSolverInterface *clpSolver, int type) } } // make cuts safer - for (int iCutGenerator = 0; iCutGenerator < numberCutGenerators_; iCutGenerator++) { + for (int iCutGenerator = 0; iCutGenerator < numberCutGenerators_; + iCutGenerator++) { CglCutGenerator *generator = generator_[iCutGenerator]->generator(); - CglGomory *cgl1 = dynamic_cast< CglGomory * >(generator); + CglGomory *cgl1 = dynamic_cast(generator); if (cgl1) { cgl1->setLimitAtRoot(cgl1->getLimit()); } - CglTwomir *cgl2 = dynamic_cast< CglTwomir * >(generator); + CglTwomir *cgl2 = dynamic_cast(generator); if (cgl2) { generator_[iCutGenerator]->setHowOften(-100); } @@ -15167,7 +15432,8 @@ int CbcModel::resolveClp(OsiClpSolverInterface *clpSolver, int type) clpSolver->setSpecialOptions(save2); #if CBC_USEFUL_PRINTING > 1 if (clpSimplex->numberIterations() > 1000) - printf("node %d took %d iterations\n", numberNodes_, clpSimplex->numberIterations()); + printf("node %d took %d iterations\n", numberNodes_, + clpSimplex->numberIterations()); #endif if (type == 0 && clpSolver->isProvenOptimal()) { ClpSimplex newModel(*clpSimplex); @@ -15232,7 +15498,7 @@ int CbcModel::resolveClp(OsiClpSolverInterface *clpSolver, int type) } } printf("XX %d inf (sum %g), %d at lb %d at ub %d other integer\n", - numberInf, sumInf, numberLb, numberUb, numberInt); + numberInf, sumInf, numberLb, numberUb, numberInt); if (numberInf) { newModel.primal(1); if (!newModel.isProvenOptimal()) { @@ -15242,8 +15508,8 @@ int CbcModel::resolveClp(OsiClpSolverInterface *clpSolver, int type) clpSimplex->setProblemStatus(1); return clpSolver->isProvenOptimal() ? 1 : 0; } - //newModel.writeMps("bad.mps"); - //assert (newModel.isProvenOptimal()); + // newModel.writeMps("bad.mps"); + // assert (newModel.isProvenOptimal()); printf("%d iterations\n", newModel.numberIterations()); int numberInf2 = 0; int numberLb2 = 0; @@ -15275,22 +15541,19 @@ int CbcModel::resolveClp(OsiClpSolverInterface *clpSolver, int type) } } printf("XXX %d inf (sum %g), %d at lb %d at ub %d other integer\n", - numberInf2, sumInf2, numberLb2, numberUb2, numberInt2); + numberInf2, sumInf2, numberLb2, numberUb2, numberInt2); if (sumInf2 < sumInf * 0.95) { - printf("XXXX suminf reduced from %g (%d) to %g (%d)\n", - sumInf, numberInf, sumInf2, numberInf2); + printf("XXXX suminf reduced from %g (%d) to %g (%d)\n", sumInf, + numberInf, sumInf2, numberInf2); if (numberObj) { newModel.deleteRows(1, &numberRows); } - memcpy(newModel.objective(), - clpSimplex->objective(), - numberColumns * sizeof(double)); - memcpy(newModel.columnLower(), - clpSimplex->columnLower(), - numberColumns * sizeof(double)); - memcpy(newModel.columnUpper(), - clpSimplex->columnUpper(), - numberColumns * sizeof(double)); + memcpy(newModel.objective(), clpSimplex->objective(), + numberColumns * sizeof(double)); + memcpy(newModel.columnLower(), clpSimplex->columnLower(), + numberColumns * sizeof(double)); + memcpy(newModel.columnUpper(), clpSimplex->columnUpper(), + numberColumns * sizeof(double)); newModel.setClpScaledMatrix(NULL); newModel.primal(1); printf("%d iterations\n", newModel.numberIterations()); @@ -15324,23 +15587,19 @@ int CbcModel::resolveClp(OsiClpSolverInterface *clpSolver, int type) } } printf("XXXXX %d inf (sum %g), %d at lb %d at ub %d other integer\n", - numberInf3, sumInf3, numberLb3, numberUb3, numberInt3); + numberInf3, sumInf3, numberLb3, numberUb3, numberInt3); if (sumInf3 < sumInf * 0.95) { memcpy(clpSimplex->primalColumnSolution(), - newModel.primalColumnSolution(), - numberColumns * sizeof(double)); + newModel.primalColumnSolution(), + numberColumns * sizeof(double)); memcpy(clpSimplex->dualColumnSolution(), - newModel.dualColumnSolution(), - numberColumns * sizeof(double)); - memcpy(clpSimplex->primalRowSolution(), - newModel.primalRowSolution(), - numberRows * sizeof(double)); - memcpy(clpSimplex->dualRowSolution(), - newModel.dualRowSolution(), - numberRows * sizeof(double)); - memcpy(clpSimplex->statusArray(), - newModel.statusArray(), - (numberColumns + numberRows) * sizeof(unsigned char)); + newModel.dualColumnSolution(), numberColumns * sizeof(double)); + memcpy(clpSimplex->primalRowSolution(), newModel.primalRowSolution(), + numberRows * sizeof(double)); + memcpy(clpSimplex->dualRowSolution(), newModel.dualRowSolution(), + numberRows * sizeof(double)); + memcpy(clpSimplex->statusArray(), newModel.statusArray(), + (numberColumns + numberRows) * sizeof(unsigned char)); clpSolver->setWarmStart(NULL); } } @@ -15354,17 +15613,16 @@ int CbcModel::resolveClp(OsiClpSolverInterface *clpSolver, int type) #endif /*! \todo It'd be really nice if there were an overload for this method that - allowed a separate value for the underlying solver's log level. The - overload could be coded to allow an increase in the log level of the - underlying solver. + allowed a separate value for the underlying solver's log level. The + overload could be coded to allow an increase in the log level of the + underlying solver. - It's worth contemplating whether OSI should have a setLogLevel method - that's more specific than the hint mechanism. + It's worth contemplating whether OSI should have a setLogLevel method + that's more specific than the hint mechanism. */ // Set log level -void CbcModel::setLogLevel(int value) -{ +void CbcModel::setLogLevel(int value) { handler_->setLogLevel(value); // Reduce print out in Osi if (solver_) { @@ -15372,15 +15630,15 @@ void CbcModel::setLogLevel(int value) if (value < oldLevel) solver_->messageHandler()->setLogLevel(value); #ifdef CBC_HAS_CLP - OsiClpSolverInterface *clpSolver - = dynamic_cast< OsiClpSolverInterface * >(solver_); + OsiClpSolverInterface *clpSolver = + dynamic_cast(solver_); if (clpSolver) { ClpSimplex *clpSimplex = clpSolver->getModelPtr(); oldLevel = clpSimplex->logLevel(); if (value < oldLevel) clpSimplex->setLogLevel(value); } -#else // CBC_HAS_CLP +#else // CBC_HAS_CLP /* For generic OSI solvers, if the new log level is 0, try the DoReducePrint hint for emphasis. @@ -15396,8 +15654,8 @@ void CbcModel::setLogLevel(int value) If priorities then >0 means only branch if incorrect while <0 means branch even if correct. +1 or -1 are highest priority */ -void CbcModel::setHotstartSolution(const double *solution, const int *priorities) -{ +void CbcModel::setHotstartSolution(const double *solution, + const int *priorities) { if (solution == NULL) { delete[] hotstartSolution_; hotstartSolution_ = NULL; @@ -15419,8 +15677,7 @@ void CbcModel::setHotstartSolution(const double *solution, const int *priorities } // Increment strong info void CbcModel::incrementStrongInfo(int numberTimes, int numberIterations, - int numberFixed, bool ifInfeasible) -{ + int numberFixed, bool ifInfeasible) { strongInfo_[0] += numberTimes; numberStrongIterations_ += numberIterations; strongInfo_[1] += numberFixed; @@ -15431,8 +15688,8 @@ void CbcModel::incrementStrongInfo(int numberTimes, int numberIterations, odd solvers can use. It may look at extra information in solverCharacteriscs_ and will also use bound from parent node */ -void CbcModel::setObjectiveValue(CbcNode *thisNode, const CbcNode *parentNode) const -{ +void CbcModel::setObjectiveValue(CbcNode *thisNode, + const CbcNode *parentNode) const { double newObjValue = solver_->getObjSense() * solver_->getObjValue(); // If odd solver take its bound if (solverCharacteristics_) { @@ -15446,9 +15703,7 @@ void CbcModel::setObjectiveValue(CbcNode *thisNode, const CbcNode *parentNode) c thisNode->setObjectiveValue(newObjValue); } // Current time since start of branchAndbound -double -CbcModel::getCurrentSeconds() const -{ +double CbcModel::getCurrentSeconds() const { if (!useElapsedTime()) return CoinCpuTime() - getDblParam(CbcStartSeconds); else @@ -15456,8 +15711,8 @@ CbcModel::getCurrentSeconds() const } /* Encapsulates choosing a variable - anyAction: -2 infeasible - -1 round again - 0 done + -1 round again + 0 done At the point where chooseBranch is called, we've decided that this problem will need to be placed in the live set and we need to choose a branching @@ -15474,11 +15729,10 @@ CbcModel::getCurrentSeconds() const branches: (o) will be filled in with ... ? Null on entry */ int CbcModel::chooseBranch(CbcNode *&newNode, int numberPassesLeft, - CbcNode *oldNode, OsiCuts &cuts, - bool &resolved, CoinWarmStartBasis *lastws, - const double *lowerBefore, const double *upperBefore, - OsiSolverBranch *&branches) -{ + CbcNode *oldNode, OsiCuts &cuts, bool &resolved, + CoinWarmStartBasis *lastws, + const double *lowerBefore, const double *upperBefore, + OsiSolverBranch *&branches) { // Set state of search /* 0 - outside CbcNode @@ -15500,16 +15754,16 @@ int CbcModel::chooseBranch(CbcNode *&newNode, int numberPassesLeft, if (numberNodes_ > 2 * numberObjects_ + 1000) { stateOfSearch_ = 4; } - //stateOfSearch_=3; + // stateOfSearch_=3; if (currentNode_ && currentNode_->depth() >= 8) stateOfSearch_ += 10; int maxNodes = getMaximumNodes(); - if (maxNodes>999999&&maxNodes<1000020) { - stateOfSearch_ = maxNodes-1000000; + if (maxNodes > 999999 && maxNodes < 1000020) { + stateOfSearch_ = maxNodes - 1000000; if (!numberNodes_) - printf("stateOfSearch always %d\n",stateOfSearch_); + printf("stateOfSearch always %d\n", stateOfSearch_); } - //printf("STate %d, %d nodes - parent %c - sol %d %d\n", + // printf("STate %d, %d nodes - parent %c - sol %d %d\n", // stateOfSearch_,numberNodes_,parentModel_ ? 'Y' :'N', // numberSolutions_,numberHeuristicSolutions_); int anyAction = -1; @@ -15522,8 +15776,9 @@ int CbcModel::chooseBranch(CbcNode *&newNode, int numberPassesLeft, // Compute "small" change in branch int nBranches = intParam_[CbcNumberBranches]; if (nBranches) { - double average = dblParam_[CbcSumChange] / static_cast< double >(nBranches); - dblParam_[CbcSmallChange] = CoinMax(average * 1.0e-5, dblParam_[CbcSmallestChange]); + double average = dblParam_[CbcSumChange] / static_cast(nBranches); + dblParam_[CbcSmallChange] = + CoinMax(average * 1.0e-5, dblParam_[CbcSmallestChange]); dblParam_[CbcSmallChange] = CoinMax(dblParam_[CbcSmallChange], 1.0e-8); } else { dblParam_[CbcSmallChange] = 1.0e-8; @@ -15534,9 +15789,9 @@ int CbcModel::chooseBranch(CbcNode *&newNode, int numberPassesLeft, if ((specialOptions_ & 1) != 0) { /* This doesn't work as intended --- getRowCutDebugger will return null - unless the current feasible solution region includes the optimal solution - that RowCutDebugger knows. There's no way to tell inactive from off the - optimal path. + unless the current feasible solution region includes the optimal + solution that RowCutDebugger knows. There's no way to tell inactive from + off the optimal path. */ const OsiRowCutDebugger *debugger = solver_->getRowCutDebugger(); if (debugger) { @@ -15555,23 +15810,23 @@ int CbcModel::chooseBranch(CbcNode *&newNode, int numberPassesLeft, while (anyAction == -1) { // Set objective value (not so obvious if NLP etc) setObjectiveValue(newNode, oldNode); - //if (numberPassesLeft<=0) - //branchingState=1; + // if (numberPassesLeft<=0) + // branchingState=1; /* Is there a CbcBranchDecision object installed? Does it specify a - chooseVariable method? If not, we're using the old (Cbc) side of the branch - decision hierarchy. In quick summary, CbcNode::chooseBranch uses strong - branching on any objects, while CbcNode::chooseDynamicBranch uses dynamic - branching, but only on simple integers (-3 is the code for punt due to - complex objects). Serious bugs remain on the Cbc side, particularly in - chooseDynamicBranch. + chooseVariable method? If not, we're using the old (Cbc) side of the + branch decision hierarchy. In quick summary, CbcNode::chooseBranch uses + strong branching on any objects, while CbcNode::chooseDynamicBranch uses + dynamic branching, but only on simple integers (-3 is the code for punt + due to complex objects). Serious bugs remain on the Cbc side, + particularly in chooseDynamicBranch. */ if (!branchingMethod_ || !branchingMethod_->chooseMethod()) { #ifdef CBC_HAS_CLP bool doClp = oldNode && (oldNode->depth() % 2) == 1; if (!doCutsNow(1)) doClp = true; - //doClp = true; + // doClp = true; int testDepth = 5; // Don't do if many iterations per node int totalNodes = numberNodes_ + numberExtraNodes_; @@ -15582,20 +15837,29 @@ int CbcModel::chooseBranch(CbcNode *&newNode, int numberPassesLeft, if (oldNode && (oldNode->depth() == -2 || oldNode->depth() == 4)) diving = true; } - if (totalNodes * 40 < totalIterations || numberNodes_ < 1000) { + int nodeThreshold = (stateOfSearch_<2) ? 1000 : 250; + if (totalNodes * 40 < totalIterations || numberNodes_ < nodeThreshold) { doClp = false; - //} else if (oldNode&&fastNodeDepth_>=0&&oldNode->depth()>=testDepth&&(specialOptions_&2048)==0) { - //printf("size %d %d - cuts %d - nodes %d its %d %c\n",solver_->getNumRows(), - // solver_->getNumCols(),cuts.sizeRowCuts(), - // totalNodes,totalIterations,doClp ? 'Y' : 'N'); - } - if (oldNode && ((fastNodeDepth_ >= 0 && oldNode->depth() >= testDepth && doClp) || diving) && /*!parentModel_*/ (specialOptions_ & 2048) == 0 - && !cuts.sizeRowCuts()) { - OsiClpSolverInterface *clpSolver - = dynamic_cast< OsiClpSolverInterface * >(solver_); + } +#if 0 + else if (oldNode&&fastNodeDepth_>=0&&oldNode->depth()>=testDepth&&(specialOptions_&2048)==0) { + printf("size %d %d - nodes %d its %d (avgits %d) %c\n", + solver_->getNumRows(), + solver_->getNumCols(), + totalNodes,totalIterations,totalIterations/totalNodes, + doClp ? 'Y' : 'N'); + } +#endif + if (oldNode && + ((fastNodeDepth_ >= 0 && oldNode->depth() >= testDepth && doClp) || + diving) && + /*!parentModel_*/ (specialOptions_ & 2048) == 0 && + !cuts.sizeRowCuts()) { + OsiClpSolverInterface *clpSolver = + dynamic_cast(solver_); if (clpSolver) { anyAction = newNode->chooseClpBranch(this, oldNode); - currentNode_ = NULL; + currentNode_ = NULL; if (anyAction != -1) break; } @@ -15606,12 +15870,14 @@ int CbcModel::chooseBranch(CbcNode *&newNode, int numberPassesLeft, if ((moreSpecialOptions2_ & 32768) != 0) cleanBounds(solver_, NULL); int save = 0; - OsiClpSolverInterface *clpSolver - = dynamic_cast< OsiClpSolverInterface * >(solver_); + OsiClpSolverInterface *clpSolver = + dynamic_cast(solver_); if (clpSolver && (moreSpecialOptions_ & 4194304) != 0) { ClpSimplex *clpSimplex = clpSolver->getModelPtr(); save = clpSimplex->specialOptions(); - clpSimplex->setSpecialOptions(save | 0x11200000); // say is Cbc (and in branch and bound - but save ray) + clpSimplex->setSpecialOptions( + save | + 0x11200000); // say is Cbc (and in branch and bound - but save ray) } #endif #ifdef CBC_HAS_NAUTY @@ -15634,7 +15900,8 @@ int CbcModel::chooseBranch(CbcNode *&newNode, int numberPassesLeft, } else { worthTrying = true; } - if ((moreSpecialOptions2_ & (128 | 256)) == (128 | 256) && currentDepth_ > 5) + if ((moreSpecialOptions2_ & (128 | 256)) == (128 | 256) && + currentDepth_ > 5) worthTrying = false; if (worthTrying) { int n = symmetryInfo_->orbitalFixing(solver_); @@ -15651,30 +15918,32 @@ int CbcModel::chooseBranch(CbcNode *&newNode, int numberPassesLeft, } } } else if (rootSymmetryInfo_) { - int n = rootSymmetryInfo_->orbitalFixing2(solver_); - if (n) { + int n = rootSymmetryInfo_->orbitalFixing2(solver_); + if (n) { #if PRINT_MORE == 0 - if (logLevel() > 1) - printf("%d orbital fixes\n", n); + if (logLevel() > 1) + printf("%d orbital fixes\n", n); #endif - solver_->resolve(); - if (!isProvenOptimal()) { - if (logLevel() > 1) - printf("infeasible after orbital fixing\n"); - } + solver_->resolve(); + if (!isProvenOptimal()) { + if (logLevel() > 1) + printf("infeasible after orbital fixing\n"); + } } } #endif // double check testSolution_ is correct (especially for parallel) - memcpy(currentSolution_,solver_->getColSolution(), - solver_->getNumCols()*sizeof(double)); + memcpy(currentSolution_, solver_->getColSolution(), + solver_->getNumCols() * sizeof(double)); testSolution_ = currentSolution_; if (numberBeforeTrust_ == 0) { anyAction = newNode->chooseBranch(this, oldNode, numberPassesLeft); } else { - anyAction = newNode->chooseDynamicBranch(this, oldNode, branches, numberPassesLeft); + anyAction = newNode->chooseDynamicBranch(this, oldNode, branches, + numberPassesLeft); if (anyAction == -3) - anyAction = newNode->chooseBranch(this, oldNode, numberPassesLeft); // dynamic did nothing + anyAction = newNode->chooseBranch( + this, oldNode, numberPassesLeft); // dynamic did nothing } currentNode_ = NULL; #ifdef CBC_HAS_CLP @@ -15688,17 +15957,18 @@ int CbcModel::chooseBranch(CbcNode *&newNode, int numberPassesLeft, */ } else { OsiBranchingInformation usefulInfo = usefulInformation(); - anyAction = newNode->chooseOsiBranch(this, oldNode, &usefulInfo, branchingState); + anyAction = + newNode->chooseOsiBranch(this, oldNode, &usefulInfo, branchingState); #ifndef SAVE_NODE_INFO currentNode_ = NULL; #endif - //branchingState=0; + // branchingState=0; } if (!oldNode) { if (numberUpdateItems_) { for (int i = 0; i < numberUpdateItems_; i++) { CbcObjectUpdateData *update = updateItems_ + i; - CbcObject *object = dynamic_cast< CbcObject * >(update->object_); + CbcObject *object = dynamic_cast(update->object_); #ifndef NDEBUG bool found = false; for (int j = 0; j < numberObjects_; j++) { @@ -15715,28 +15985,36 @@ int CbcModel::chooseBranch(CbcNode *&newNode, int numberPassesLeft, numberUpdateItems_ = 0; } } - if (solverCharacteristics_ && solverCharacteristics_->solutionAddsCuts() && // we are in some OA based bab - feasible && (newNode->numberUnsatisfied() == 0) //solution has become integer feasible during strong branching + if (solverCharacteristics_ && + solverCharacteristics_ + ->solutionAddsCuts() && // we are in some OA based bab + feasible && + (newNode->numberUnsatisfied() == + 0) // solution has become integer feasible during strong branching ) { - //in the present case we need to check here integer infeasibility if the node is not fathomed we will have to do the loop + // in the present case we need to check here integer infeasibility if the + // node is not fathomed we will have to do the loop // again - //std::cout<normal() && (!generator_[i]->needsOptimalBasis() || solver_->basisIsAvailable())) - generator_[i]->generateCuts(feasCuts, 1 /* = fullscan */, solver_, NULL); + for (int i = 0; i < numberCutGenerators_ && (feasCuts.sizeRowCuts() == 0); + i++) { + if (generator_[i]->normal() && (!generator_[i]->needsOptimalBasis() || + solver_->basisIsAvailable())) + generator_[i]->generateCuts(feasCuts, 1 /* = fullscan */, solver_, + NULL); } solver_->applyCuts(feasCuts); resolve(solver_); double objval = solver_->getObjValue(); lastHeuristic_ = NULL; - setBestSolution(CBC_SOLUTION, objval, - solver_->getColSolution()); + setBestSolution(CBC_SOLUTION, objval, solver_->getColSolution()); int easy = 2; - if (!solverCharacteristics_->mipFeasible()) //did we prove that the node could be pruned? + if (!solverCharacteristics_ + ->mipFeasible()) // did we prove that the node could be pruned? feasible = false; // Reset the bound now solverCharacteristics_->setMipBound(-COIN_DBL_MAX); @@ -15758,14 +16036,14 @@ int CbcModel::chooseBranch(CbcNode *&newNode, int numberPassesLeft, infeasibility from `found a solution and tightened objective target.' if (onOptimalPath) - assert (anyAction!=-2); // can be useful but gives false positives on strong + assert (anyAction!=-2); // can be useful but gives false positives on + strong */ numberPassesLeft--; if (numberPassesLeft <= -1) { if (!numberLongStrong_ && !numberThreads_) - messageHandler()->message(CBC_WARNING_STRONG, - messages()) - << CoinMessageEol; + messageHandler()->message(CBC_WARNING_STRONG, messages()) + << CoinMessageEol; numberLongStrong_++; } if (anyAction == -1) { @@ -15789,7 +16067,7 @@ int CbcModel::chooseBranch(CbcNode *&newNode, int numberPassesLeft, } } } - //A candidate has been found; restore the subproblem. + // A candidate has been found; restore the subproblem. if (saveNumberRows < solver_->getNumRows()) { // delete rows - but leave solution int n = solver_->getNumRows(); @@ -15805,9 +16083,9 @@ int CbcModel::chooseBranch(CbcNode *&newNode, int numberPassesLeft, if (anyAction >= 0) { if (resolved) { /* - Used to be that when the node was not fathomed (branching object present) - the solution was not needed. But that's no longer the case --- heuristics - are applied, and they may want the solution. + Used to be that when the node was not fathomed (branching object + present) the solution was not needed. But that's no longer the case --- + heuristics are applied, and they may want the solution. */ // bool needValidSolution = (newNode->branchingObject() == NULL) ; bool needValidSolution = true; @@ -15816,16 +16094,19 @@ int CbcModel::chooseBranch(CbcNode *&newNode, int numberPassesLeft, { printf("Number of rows after chooseBranch fix (node)" "(active only) %d\n", - numberRowsAtContinuous_ + numberNewCuts_ + numberOldActiveCuts_); - const CoinWarmStartBasis *debugws = dynamic_cast< const CoinWarmStartBasis * >(solver_->getWarmStart()); + numberRowsAtContinuous_ + numberNewCuts_ + numberOldActiveCuts_); + const CoinWarmStartBasis *debugws = + dynamic_cast(solver_->getWarmStart()); debugws->print(); delete debugws; } #endif } { - OsiBranchingObject *branchingObject = newNode->modifiableBranchingObject(); - CbcGeneralBranchingObject *generalBranch = dynamic_cast< CbcGeneralBranchingObject * >(branchingObject); + OsiBranchingObject *branchingObject = + newNode->modifiableBranchingObject(); + CbcGeneralBranchingObject *generalBranch = + dynamic_cast(branchingObject); if (generalBranch && false) { int numberProblems = generalBranch->numberSubProblems(); for (int i = 0; i < numberProblems; i++) { @@ -15833,10 +16114,10 @@ int CbcModel::chooseBranch(CbcNode *&newNode, int numberPassesLeft, double sumInfeasibilities; int numberUnsatisfied; generalBranch->state(objectiveValue, sumInfeasibilities, - numberUnsatisfied, i); - printf("node %d obj %g sumI %g numI %i rel depth %d\n", - i, objectiveValue, sumInfeasibilities, numberUnsatisfied, - generalBranch->subProblem(i)->depth_); + numberUnsatisfied, i); + printf("node %d obj %g sumI %g numI %i rel depth %d\n", i, + objectiveValue, sumInfeasibilities, numberUnsatisfied, + generalBranch->subProblem(i)->depth_); } } if (generalBranch) { @@ -15856,32 +16137,34 @@ int CbcModel::chooseBranch(CbcNode *&newNode, int numberPassesLeft, double sumInfeasibilities; int numberUnsatisfied; generalBranch->state(objectiveValue, sumInfeasibilities, - numberUnsatisfied, i); - //printf("node %d obj %g sumI %g numI %i rel depth %d\n", + numberUnsatisfied, i); + // printf("node %d obj %g sumI %g numI %i rel depth %d\n", // i,objectiveValue,sumInfeasibilities,numberUnsatisfied, // generalBranch->subProblem(i)->depth_); newNode2 = new CbcNode(); - newNode2->setDepth(generalBranch->subProblem(i)->depth_ + currentDepth_); + newNode2->setDepth(generalBranch->subProblem(i)->depth_ + + currentDepth_); generalBranch->subProblem(i)->apply(solver_, 8); // basis newNode2->setNumberUnsatisfied(numberUnsatisfied); newNode2->setSumInfeasibilities(sumInfeasibilities); newNode2->setGuessedObjectiveValue(objectiveValue); newNode2->setObjectiveValue(objectiveValue); - CbcOneGeneralBranchingObject *object = new CbcOneGeneralBranchingObject(this, generalBranch, i); + CbcOneGeneralBranchingObject *object = + new CbcOneGeneralBranchingObject(this, generalBranch, i); newNode2->setBranchingObject(object); assert(lastws->fullBasis()); - newNode2->createInfo(this, oldNode, lastws, - lowerBefore, upperBefore, - numberOldActiveCuts_, numberNewCuts_); + newNode2->createInfo(this, oldNode, lastws, lowerBefore, upperBefore, + numberOldActiveCuts_, numberNewCuts_); newNode2->nodeInfo()->setNumberBranchesLeft(1); - //newNode2->nodeInfo()->unsetParentBasedData(); + // newNode2->nodeInfo()->unsetParentBasedData(); if (i < nProbMinus1) { - //OsiBranchingObject * object = oldNode->modifiableBranchingObject(); + // OsiBranchingObject * object = + // oldNode->modifiableBranchingObject(); CbcNodeInfo *nodeInfo = oldNode->nodeInfo(); - //object->incrementNumberBranchesLeft(); + // object->incrementNumberBranchesLeft(); nodeInfo->incrementNumberPointingToThis(); newNode2->nodeInfo()->setNodeNumber(numberNodes2_); - //newNode2->nodeInfo()->setNumberBranchesLeft(1); + // newNode2->nodeInfo()->setNumberBranchesLeft(1); newNode2->initializeInfo(); numberNodes2_++; tree_->push(newNode2); @@ -15901,7 +16184,7 @@ int CbcModel::chooseBranch(CbcNode *&newNode, int numberPassesLeft, } } newNode->createInfo(this, oldNode, lastws, lowerBefore, upperBefore, - numberOldActiveCuts_, numberNewCuts_); + numberOldActiveCuts_, numberNewCuts_); } } if (newNode->numberUnsatisfied()) { @@ -15912,8 +16195,8 @@ int CbcModel::chooseBranch(CbcNode *&newNode, int numberPassesLeft, int initialNumber = ((threadMode_ & 1) == 0) ? 0 : 1000000000; lockThread(); newNode->nodeInfo()->addCuts(cuts, newNode->numberBranches(), - //whichGenerator_, - initialNumber); + // whichGenerator_, + initialNumber); unlockThread(); } } @@ -15929,7 +16212,7 @@ int CbcModel::chooseBranch(CbcNode *&newNode, int numberPassesLeft, assert(newNode); if (newNode->objectiveValue() >= getCutoff()) { anyAction = -2; // say bad after all - // zap parent nodeInfo + // zap parent nodeInfo #ifdef COIN_DEVELOP printf("zapping3 CbcNodeInfo %x\n", newNode->nodeInfo()->parent()); #endif @@ -15967,27 +16250,25 @@ int CbcModel::chooseBranch(CbcNode *&newNode, int numberPassesLeft, You should do that if solver is odd - if solver is normal simplex then use this */ -void CbcModel::passInSolverCharacteristics(OsiBabSolver *solverCharacteristics) -{ +void CbcModel::passInSolverCharacteristics( + OsiBabSolver *solverCharacteristics) { solverCharacteristics_ = solverCharacteristics; } // Generate an OsiBranchingInformation object -OsiBranchingInformation -CbcModel::usefulInformation() const -{ +OsiBranchingInformation CbcModel::usefulInformation() const { OsiBranchingInformation usefulInfo(solver_, normalSolver(), false); // and modify usefulInfo.solution_ = testSolution_; usefulInfo.integerTolerance_ = dblParam_[CbcIntegerTolerance]; usefulInfo.hotstartSolution_ = hotstartSolution_; usefulInfo.numberSolutions_ = numberSolutions_; - usefulInfo.numberBranchingSolutions_ = numberSolutions_ - numberHeuristicSolutions_; + usefulInfo.numberBranchingSolutions_ = + numberSolutions_ - numberHeuristicSolutions_; usefulInfo.depth_ = -1; return usefulInfo; } void CbcModel::setBestSolution(const double *solution, int numberColumns, - double objectiveValue, bool checkSolution) -{ + double objectiveValue, bool checkSolution) { // May be odd discontinuities - so only check if asked if (checkSolution) { assert(numberColumns == solver_->getNumCols()); @@ -16011,9 +16292,12 @@ void CbcModel::setBestSolution(const double *solution, int numberColumns, solver_->initialSolve(); char printBuffer[200]; if (numberAway) { - sprintf(printBuffer, "Warning %d integer variables were more than 1.0e-4 away from integer", numberAway); + sprintf(printBuffer, + "Warning %d integer variables were more than 1.0e-4 away from " + "integer", + numberAway); messageHandler()->message(CBC_GENERAL, messages()) - << printBuffer << CoinMessageEol; + << printBuffer << CoinMessageEol; } bool looksGood = solver_->isProvenOptimal(); if (looksGood) { @@ -16021,15 +16305,16 @@ void CbcModel::setBestSolution(const double *solution, int numberColumns, double objValue = direction * solver_->getObjValue(); if (objValue > objectiveValue + 1.0e-8 * (1.0 + fabs(objectiveValue))) { sprintf(printBuffer, "Given objective value %g, computed %g", - objectiveValue, objValue); + objectiveValue, objValue); messageHandler()->message(CBC_GENERAL, messages()) - << printBuffer << CoinMessageEol; + << printBuffer << CoinMessageEol; } // Use this as objective value and solution objectiveValue = objValue; solution = solver_->getColSolution(); // Save current basis - CoinWarmStartBasis *ws = dynamic_cast< CoinWarmStartBasis * >(solver_->getWarmStart()); + CoinWarmStartBasis *ws = + dynamic_cast(solver_->getWarmStart()); assert(ws); setBestSolutionBasis(*ws); delete ws; @@ -16045,15 +16330,31 @@ void CbcModel::setBestSolution(const double *solution, int numberColumns, // Return if no good if (!looksGood) { messageHandler()->message(CBC_GENERAL, messages()) - << "Error solution not saved as not feasible" << CoinMessageEol; + << "Error solution not saved as not feasible" << CoinMessageEol; return; } else { // message sprintf(printBuffer, "Solution with objective value %g saved", - objectiveValue); + objectiveValue); messageHandler()->message(CBC_GENERAL, messages()) - << printBuffer << CoinMessageEol; + << printBuffer << CoinMessageEol; + } +#if 0 // breaks unit tests (as objective can be flipped) + } else { + // at least recompute objective value + double saveX = objectiveValue; + double offset; + solver_->getDblParam(OsiObjOffset, offset); + objectiveValue = -offset; + const double *objective = solver_->getObjCoefficients(); + int numberColumns = solver_->getNumCols(); + for (int iColumn = 0; iColumn < numberColumns; iColumn++) { + double value = solution[iColumn]; + objectiveValue += value * objective[iColumn]; } + if (fabs(saveX-objectiveValue)>1.0e-5) + printf("in %g out %g\n",saveX,objectiveValue); +#endif } if (bestSolution_) saveExtraSolution(bestSolution_, bestObjective_); @@ -16070,7 +16371,8 @@ void CbcModel::setBestSolution(const double *solution, int numberColumns, double offset; solver_->getDblParam(OsiObjOffset, offset); solver_->setRowUpper(cutoffRowNumber_, cutoff + offset); - if (continuousSolver_ && solver_->getNumCols() > continuousSolver_->getNumCols()) { + if (continuousSolver_ && + solver_->getNumCols() > continuousSolver_->getNumCols()) { solver_->setRowUpper(cutoffRowNumber_, floor(cutoff) + offset); solver_->setRowLower(cutoffRowNumber_, floor(cutoff) + offset); } @@ -16094,17 +16396,16 @@ void CbcModel::setBestSolution(const double *solution, int numberColumns, The routine is called from branchAndBound to process the root node. But it will also be called when we've recursed into branchAndBound via smallBaB. */ -void CbcModel::doHeuristicsAtRoot(int deleteHeuristicsAfterwards) -{ +void CbcModel::doHeuristicsAtRoot(int deleteHeuristicsAfterwards) { int numberColumns = getNumCols(); double *newSolution = new double[numberColumns]; int i; if (deleteHeuristicsAfterwards != 2) { /* - If mode == 1, we delete and recreate here, then delete at the bottom. The - create/delete part makes sense, but why delete the existing array? Seems like - it should be preserved and restored. + If mode == 1, we delete and recreate here, then delete at the bottom. + The create/delete part makes sense, but why delete the existing array? + Seems like it should be preserved and restored. */ if (deleteHeuristicsAfterwards) { delete[] usedInSolution_; @@ -16117,22 +16418,23 @@ void CbcModel::doHeuristicsAtRoot(int deleteHeuristicsAfterwards) if (eventHandler) eventHandler->setModel(this); /* - currentPassNumber_ is described as `cut pass number'. Again, seems a bit - cavalier to just change it. - - Whether this has any effect is determined by individual heuristics. Typically - there will be a check at the front of the solution() routine that determines - whether it will run or simply return. Root heuristics are characterised by - node count of 0. In addition, currentPassNumber_ can be checked to to limit - execution in terms of passes through cut generation / heuristic execution in - solveWithCuts. + currentPassNumber_ is described as `cut pass number'. Again, seems a + bit cavalier to just change it. + + Whether this has any effect is determined by individual heuristics. + Typically there will be a check at the front of the solution() routine + that determines whether it will run or simply return. Root heuristics are + characterised by node count of 0. In addition, currentPassNumber_ can be + checked to to limit execution in terms of passes through cut generation / + heuristic execution in solveWithCuts. */ currentPassNumber_ = 1; // so root heuristics will run /* A loop to run the heuristics. incrementUsed will mark entries in - usedInSolution corresponding to variables that are nonzero in the solution. - CBC_ROUNDING just identifies a message template, not the heuristic. + usedInSolution corresponding to variables that are nonzero in the + solution. CBC_ROUNDING just identifies a message template, not the + heuristic. */ // Modify based on size etc adjustHeuristics(); @@ -16169,7 +16471,8 @@ void CbcModel::doHeuristicsAtRoot(int deleteHeuristicsAfterwards) // skip if can't run here if (!heuristic_[i]->shouldHeurRun(0)) continue; - if (lastSolutionCount > 0 && (heuristic_[i]->switches() & 16) == 0) + if (lastSolutionCount > 0 && + (heuristic_[i]->switches() & 16) == 0) continue; // no point parameters[i - iChunk].solutionValue = heuristicValue; // Don't want a strategy object @@ -16186,28 +16489,26 @@ void CbcModel::doHeuristicsAtRoot(int deleteHeuristicsAfterwards) parameters[i - iChunk].solution = new double[numberColumns]; ; parameters[i - iChunk].foundSol = 0; - //newModel->gutsOfCopy(*this,-1); + // newModel->gutsOfCopy(*this,-1); for (int j = 0; j < numberHeuristics_; j++) delete newModel->heuristic_[j]; - //newModel->heuristic_ = new CbcHeuristic * [1]; + // newModel->heuristic_ = new CbcHeuristic * [1]; newModel->heuristic_[0] = heuristic_[i]->clone(); newModel->heuristic_[0]->setModel(newModel); newModel->heuristic_[0]->resetModel(newModel); newModel->numberHeuristics_ = 1; } - void - parallelHeuristics(int numberThreads, - int sizeOfData, - void *argBundle); - parallelHeuristics(nThisTime, - static_cast< int >(sizeof(argBundle)), - parameters); + void parallelHeuristics(int numberThreads, int sizeOfData, + void *argBundle); + parallelHeuristics(nThisTime, static_cast(sizeof(argBundle)), + parameters); double cutoff = heuristicValue; for (int i = 0; i < chunk; i++) { if (parameters[i].model) { - if (parameters[i].foundSol > 0 && parameters[i].solutionValue < heuristicValue) { + if (parameters[i].foundSol > 0 && + parameters[i].solutionValue < heuristicValue) { memcpy(newSolution, parameters[i].solution, - numberColumns * sizeof(double)); + numberColumns * sizeof(double)); lastHeuristic_ = heuristic_[i + iChunk]; double value = parameters[i].solutionValue; setBestSolution(CBC_ROUNDING, value, newSolution); @@ -16217,13 +16518,16 @@ void CbcModel::doHeuristicsAtRoot(int deleteHeuristicsAfterwards) heuristicValue = value; heuristic_[i + iChunk]->incrementNumberSolutionsFound(); incrementUsed(newSolution); - // increment number of solutions so other heuristics can test + // increment number of solutions so other heuristics can + // test thisSolutionCount++; numberHeuristicSolutions_++; found = i + iChunk; } } - if (heuristic_[i + iChunk]->exitNow(bestObjective_) || (parameters[i].model->heuristic(0)->switches() & (1024 + 2048)) == (1024 + 2048)) + if (heuristic_[i + iChunk]->exitNow(bestObjective_) || + (parameters[i].model->heuristic(0)->switches() & + (1024 + 2048)) == (1024 + 2048)) exitNow = true; delete[] parameters[i].solution; delete parameters[i].model; @@ -16249,15 +16553,14 @@ void CbcModel::doHeuristicsAtRoot(int deleteHeuristicsAfterwards) // see if heuristic will do anything double saveValue = heuristicValue; double before = getCurrentSeconds(); - int ifSol = heuristic_[i]->solution(heuristicValue, - newSolution); + int ifSol = heuristic_[i]->solution(heuristicValue, newSolution); if (handler_->logLevel() > 1) { char line[100]; sprintf(line, "Heuristic %s took %g seconds (%s)", - heuristic_[i]->heuristicName(), - getCurrentSeconds() - before, - ifSol ? "good" : "no good"); - handler_->message(CBC_GENERAL, messages_) << line << CoinMessageEol; + heuristic_[i]->heuristicName(), + getCurrentSeconds() - before, ifSol ? "good" : "no good"); + handler_->message(CBC_GENERAL, messages_) + << line << CoinMessageEol; } //#define DEBUG_BEST #ifdef DEBUG_BEST @@ -16271,7 +16574,8 @@ void CbcModel::doHeuristicsAtRoot(int deleteHeuristicsAfterwards) assert(numberWritten == 1); numberWritten = fwrite(&heuristicValue, sizeof(double), 1, fp); assert(numberWritten == 1); - numberWritten = fwrite(newSolution, sizeof(double), numberColumns, fp); + numberWritten = + fwrite(newSolution, sizeof(double), numberColumns, fp); assert(numberWritten == numberColumns); fclose(fp); } else if (fp) { @@ -16283,7 +16587,8 @@ void CbcModel::doHeuristicsAtRoot(int deleteHeuristicsAfterwards) if (numberColumns == numberColumnsX) { numberRead = fread(&heuristicValue, sizeof(double), 1, fp); assert(numberRead == 1); - numberRead = fread(newSolution, sizeof(double), numberColumns, fp); + numberRead = + fread(newSolution, sizeof(double), numberColumns, fp); assert(numberRead == numberColumns); ifSol = 1; } @@ -16305,29 +16610,34 @@ void CbcModel::doHeuristicsAtRoot(int deleteHeuristicsAfterwards) // numberSolutions_++; numberHeuristicSolutions_++; #ifdef HEURISTIC_INFORM - printf("HEUR %s where %d C\n", - lastHeuristic_->heuristicName(), whereFrom); + printf("HEUR %s where %d C\n", lastHeuristic_->heuristicName(), + whereFrom); #endif whereFrom |= 8; // say solution found - if (heuristic_[i]->exitNow(bestObjective_) - || numberSolutions_ >= getMaximumSolutions()) { + if (heuristic_[i]->exitNow(bestObjective_) || + numberSolutions_ >= getMaximumSolutions()) { thisSolutionCount = -1000000; break; } if (eventHandler) { - if (!eventHandler->event(CbcEventHandler::heuristicSolution)) { + if (!eventHandler->event( + CbcEventHandler::heuristicSolution)) { eventHappened_ = true; // exit thisSolutionCount = -1000000; break; } } - double testGap = CoinMax(dblParam_[CbcAllowableGap], - CoinMax(fabs(bestObjective_), fabs(bestPossibleObjective_)) - * dblParam_[CbcAllowableFractionGap]); - if (bestObjective_ - bestPossibleObjective_ < testGap && getCutoffIncrement() >= 0.0 && bestPossibleObjective_ < 1.0e30) { + double testGap = + CoinMax(dblParam_[CbcAllowableGap], + CoinMax(fabs(bestObjective_), + fabs(bestPossibleObjective_)) * + dblParam_[CbcAllowableFractionGap]); + if (bestObjective_ - bestPossibleObjective_ < testGap && + getCutoffIncrement() >= 0.0 && + bestPossibleObjective_ < 1.0e30) { if (bestPossibleObjective_ < getCutoff()) stoppedOnGap_ = true; - //eventHappened_=true; // stop as fast as possible + // eventHappened_=true; // stop as fast as possible thisSolutionCount = -1000000; break; } @@ -16336,7 +16646,7 @@ void CbcModel::doHeuristicsAtRoot(int deleteHeuristicsAfterwards) // NOT better solution #if CBC_USEFUL_PRINTING > 1 printf("HEUR %s where %d REJECTED i==%d\n", - heuristic_[i]->heuristicName(), whereFrom, i); + heuristic_[i]->heuristicName(), whereFrom, i); #endif lastHeuristic_ = saveHeuristic; heuristicValue = saveValue; @@ -16362,15 +16672,14 @@ void CbcModel::doHeuristicsAtRoot(int deleteHeuristicsAfterwards) } currentPassNumber_ = 0; /* - Did any of the heuristics turn up a new solution? Record it before we free - the vector. tree_ will not necessarily be a CbcTreeLocal; the main model gets - a CbcTree by default. CbcTreeLocal actually implements a k-neighbourhood - search heuristic. This initialises it with a solution and creates the - k-neighbourhood cut. + Did any of the heuristics turn up a new solution? Record it before we + free the vector. tree_ will not necessarily be a CbcTreeLocal; the main + model gets a CbcTree by default. CbcTreeLocal actually implements a + k-neighbourhood search heuristic. This initialises it with a solution and + creates the k-neighbourhood cut. */ if (found >= 0) { - CbcTreeLocal *tree - = dynamic_cast< CbcTreeLocal * >(tree_); + CbcTreeLocal *tree = dynamic_cast(tree_); if (tree) tree->passInSolution(bestSolution_, heuristicValue); if (eventHandler) { @@ -16389,10 +16698,10 @@ void CbcModel::doHeuristicsAtRoot(int deleteHeuristicsAfterwards) if (!deleteHeuristicsAfterwards) { for (i = 0; i < numberHeuristics_; i++) { // delete FPump - CbcHeuristicFPump *pump - = dynamic_cast< CbcHeuristicFPump * >(heuristic_[i]); - if (pump && pump->feasibilityPumpOptions() < 1000000 - && (specialOptions_ & 33554432) == 0) { + CbcHeuristicFPump *pump = + dynamic_cast(heuristic_[i]); + if (pump && pump->feasibilityPumpOptions() < 1000000 && + (specialOptions_ & 33554432) == 0) { delete pump; numberHeuristics_--; for (int j = i; j < numberHeuristics_; j++) @@ -16412,8 +16721,7 @@ void CbcModel::doHeuristicsAtRoot(int deleteHeuristicsAfterwards) delete[] newSolution; } // Zap integer information in problem (may leave object info) -void CbcModel::zapIntegerInformation(bool leaveObjects) -{ +void CbcModel::zapIntegerInformation(bool leaveObjects) { numberIntegers_ = 0; delete[] integerVariable_; integerVariable_ = NULL; @@ -16427,8 +16735,7 @@ void CbcModel::zapIntegerInformation(bool leaveObjects) } } // Create C++ lines to get to current state -void CbcModel::generateCpp(FILE *fp, int /*options*/) -{ +void CbcModel::generateCpp(FILE *fp, int /*options*/) { // Do cut generators int i; for (i = 0; i < numberCutGenerators_; i++) { @@ -16442,17 +16749,15 @@ void CbcModel::generateCpp(FILE *fp, int /*options*/) bool atSolution = generator_[i]->atSolution(); bool whenInfeasible = generator_[i]->whenInfeasible(); bool timing = generator_[i]->timing(); - fprintf(fp, "3 cbcModel->addCutGenerator(&%s,%d,", - name.c_str(), howOften); + fprintf(fp, "3 cbcModel->addCutGenerator(&%s,%d,", name.c_str(), howOften); // change name - name[0] = static_cast< char >(toupper(name[0])); - fprintf(fp, "\"%s\",%s,%s,%s,%d,%d,%d);\n", - name.c_str(), normal ? "true" : "false", - atSolution ? "true" : "false", - whenInfeasible ? "true" : "false", - howOftenInSub, whatDepth, whatDepthInSub); - fprintf(fp, "3 cbcModel->cutGenerator(%d)->setTiming(%s);\n", - i, timing ? "true" : "false"); + name[0] = static_cast(toupper(name[0])); + fprintf(fp, "\"%s\",%s,%s,%s,%d,%d,%d);\n", name.c_str(), + normal ? "true" : "false", atSolution ? "true" : "false", + whenInfeasible ? "true" : "false", howOftenInSub, whatDepth, + whatDepthInSub); + fprintf(fp, "3 cbcModel->cutGenerator(%d)->setTiming(%s);\n", i, + timing ? "true" : "false"); fprintf(fp, "3 \n"); } for (i = 0; i < numberHeuristics_; i++) { @@ -16469,121 +16774,215 @@ void CbcModel::generateCpp(FILE *fp, int /*options*/) double dValue1, dValue2; iValue1 = this->getMaximumNodes(); iValue2 = other->getMaximumNodes(); - fprintf(fp, "%d int save_getMaximumNodes = cbcModel->getMaximumNodes();\n", iValue1 == iValue2 ? 2 : 1); - fprintf(fp, "%d cbcModel->setMaximumNodes(%d);\n", iValue1 == iValue2 ? 4 : 3, iValue1); - fprintf(fp, "%d cbcModel->setMaximumNodes(save_getMaximumNodes);\n", iValue1 == iValue2 ? 7 : 6); + fprintf(fp, "%d int save_getMaximumNodes = cbcModel->getMaximumNodes();\n", + iValue1 == iValue2 ? 2 : 1); + fprintf(fp, "%d cbcModel->setMaximumNodes(%d);\n", + iValue1 == iValue2 ? 4 : 3, iValue1); + fprintf(fp, "%d cbcModel->setMaximumNodes(save_getMaximumNodes);\n", + iValue1 == iValue2 ? 7 : 6); iValue1 = this->getMaximumSolutions(); iValue2 = other->getMaximumSolutions(); - fprintf(fp, "%d int save_getMaximumSolutions = cbcModel->getMaximumSolutions();\n", iValue1 == iValue2 ? 2 : 1); - fprintf(fp, "%d cbcModel->setMaximumSolutions(%d);\n", iValue1 == iValue2 ? 4 : 3, iValue1); - fprintf(fp, "%d cbcModel->setMaximumSolutions(save_getMaximumSolutions);\n", iValue1 == iValue2 ? 7 : 6); + fprintf( + fp, + "%d int save_getMaximumSolutions = cbcModel->getMaximumSolutions();\n", + iValue1 == iValue2 ? 2 : 1); + fprintf(fp, "%d cbcModel->setMaximumSolutions(%d);\n", + iValue1 == iValue2 ? 4 : 3, iValue1); + fprintf(fp, "%d cbcModel->setMaximumSolutions(save_getMaximumSolutions);\n", + iValue1 == iValue2 ? 7 : 6); iValue1 = this->numberStrong(); iValue2 = other->numberStrong(); - fprintf(fp, "%d int save_numberStrong = cbcModel->numberStrong();\n", iValue1 == iValue2 ? 2 : 1); - fprintf(fp, "%d cbcModel->setNumberStrong(%d);\n", iValue1 == iValue2 ? 4 : 3, iValue1); - fprintf(fp, "%d cbcModel->setNumberStrong(save_numberStrong);\n", iValue1 == iValue2 ? 7 : 6); + fprintf(fp, "%d int save_numberStrong = cbcModel->numberStrong();\n", + iValue1 == iValue2 ? 2 : 1); + fprintf(fp, "%d cbcModel->setNumberStrong(%d);\n", + iValue1 == iValue2 ? 4 : 3, iValue1); + fprintf(fp, "%d cbcModel->setNumberStrong(save_numberStrong);\n", + iValue1 == iValue2 ? 7 : 6); iValue1 = this->numberBeforeTrust(); iValue2 = other->numberBeforeTrust(); - fprintf(fp, "%d int save_numberBeforeTrust = cbcModel->numberBeforeTrust();\n", iValue1 == iValue2 ? 2 : 1); - fprintf(fp, "%d cbcModel->setNumberBeforeTrust(%d);\n", iValue1 == iValue2 ? 4 : 3, iValue1); - fprintf(fp, "%d cbcModel->setNumberBeforeTrust(save_numberBeforeTrust);\n", iValue1 == iValue2 ? 7 : 6); + fprintf(fp, + "%d int save_numberBeforeTrust = cbcModel->numberBeforeTrust();\n", + iValue1 == iValue2 ? 2 : 1); + fprintf(fp, "%d cbcModel->setNumberBeforeTrust(%d);\n", + iValue1 == iValue2 ? 4 : 3, iValue1); + fprintf(fp, "%d cbcModel->setNumberBeforeTrust(save_numberBeforeTrust);\n", + iValue1 == iValue2 ? 7 : 6); iValue1 = this->numberPenalties(); iValue2 = other->numberPenalties(); - fprintf(fp, "%d int save_numberPenalties = cbcModel->numberPenalties();\n", iValue1 == iValue2 ? 2 : 1); - fprintf(fp, "%d cbcModel->setNumberPenalties(%d);\n", iValue1 == iValue2 ? 4 : 3, iValue1); - fprintf(fp, "%d cbcModel->setNumberPenalties(save_numberPenalties);\n", iValue1 == iValue2 ? 7 : 6); + fprintf(fp, "%d int save_numberPenalties = cbcModel->numberPenalties();\n", + iValue1 == iValue2 ? 2 : 1); + fprintf(fp, "%d cbcModel->setNumberPenalties(%d);\n", + iValue1 == iValue2 ? 4 : 3, iValue1); + fprintf(fp, "%d cbcModel->setNumberPenalties(save_numberPenalties);\n", + iValue1 == iValue2 ? 7 : 6); iValue1 = this->howOftenGlobalScan(); iValue2 = other->howOftenGlobalScan(); - fprintf(fp, "%d int save_howOftenGlobalScan = cbcModel->howOftenGlobalScan();\n", iValue1 == iValue2 ? 2 : 1); - fprintf(fp, "%d cbcModel->setHowOftenGlobalScan(%d);\n", iValue1 == iValue2 ? 4 : 3, iValue1); - fprintf(fp, "%d cbcModel->setHowOftenGlobalScan(save_howOftenGlobalScan);\n", iValue1 == iValue2 ? 7 : 6); + fprintf(fp, + "%d int save_howOftenGlobalScan = cbcModel->howOftenGlobalScan();\n", + iValue1 == iValue2 ? 2 : 1); + fprintf(fp, "%d cbcModel->setHowOftenGlobalScan(%d);\n", + iValue1 == iValue2 ? 4 : 3, iValue1); + fprintf(fp, "%d cbcModel->setHowOftenGlobalScan(save_howOftenGlobalScan);\n", + iValue1 == iValue2 ? 7 : 6); iValue1 = this->printFrequency(); iValue2 = other->printFrequency(); - fprintf(fp, "%d int save_printFrequency = cbcModel->printFrequency();\n", iValue1 == iValue2 ? 2 : 1); - fprintf(fp, "%d cbcModel->setPrintFrequency(%d);\n", iValue1 == iValue2 ? 4 : 3, iValue1); - fprintf(fp, "%d cbcModel->setPrintFrequency(save_printFrequency);\n", iValue1 == iValue2 ? 7 : 6); + fprintf(fp, "%d int save_printFrequency = cbcModel->printFrequency();\n", + iValue1 == iValue2 ? 2 : 1); + fprintf(fp, "%d cbcModel->setPrintFrequency(%d);\n", + iValue1 == iValue2 ? 4 : 3, iValue1); + fprintf(fp, "%d cbcModel->setPrintFrequency(save_printFrequency);\n", + iValue1 == iValue2 ? 7 : 6); iValue1 = this->getPrintingMode(); iValue2 = other->getPrintingMode(); - fprintf(fp, "%d int save_printingMode = cbcModel->getPrintingMode();\n", iValue1 == iValue2 ? 2 : 1); - fprintf(fp, "%d cbcModel->setPrintingMode(%d);\n", iValue1 == iValue2 ? 4 : 3, iValue1); - fprintf(fp, "%d cbcModel->setPrintingMode(save_printingMode);\n", iValue1 == iValue2 ? 7 : 6); + fprintf(fp, "%d int save_printingMode = cbcModel->getPrintingMode();\n", + iValue1 == iValue2 ? 2 : 1); + fprintf(fp, "%d cbcModel->setPrintingMode(%d);\n", + iValue1 == iValue2 ? 4 : 3, iValue1); + fprintf(fp, "%d cbcModel->setPrintingMode(save_printingMode);\n", + iValue1 == iValue2 ? 7 : 6); iValue1 = this->searchStrategy(); iValue2 = other->searchStrategy(); - fprintf(fp, "%d int save_searchStrategy = cbcModel->searchStrategy();\n", iValue1 == iValue2 ? 2 : 1); - fprintf(fp, "%d cbcModel->setSearchStrategy(%d);\n", iValue1 == iValue2 ? 4 : 3, iValue1); - fprintf(fp, "%d cbcModel->setSearchStrategy(save_searchStrategy);\n", iValue1 == iValue2 ? 7 : 6); + fprintf(fp, "%d int save_searchStrategy = cbcModel->searchStrategy();\n", + iValue1 == iValue2 ? 2 : 1); + fprintf(fp, "%d cbcModel->setSearchStrategy(%d);\n", + iValue1 == iValue2 ? 4 : 3, iValue1); + fprintf(fp, "%d cbcModel->setSearchStrategy(save_searchStrategy);\n", + iValue1 == iValue2 ? 7 : 6); iValue1 = this->specialOptions(); iValue2 = other->specialOptions(); - fprintf(fp, "%d int save_cbcSpecialOptions = cbcModel->specialOptions();\n", iValue1 == iValue2 ? 2 : 1); - fprintf(fp, "%d cbcModel->setSpecialOptions(%d);\n", iValue1 == iValue2 ? 4 : 3, iValue1); - fprintf(fp, "%d cbcModel->setSpecialOptions(save_cbcSpecialOptions);\n", iValue1 == iValue2 ? 7 : 6); + fprintf(fp, "%d int save_cbcSpecialOptions = cbcModel->specialOptions();\n", + iValue1 == iValue2 ? 2 : 1); + fprintf(fp, "%d cbcModel->setSpecialOptions(%d);\n", + iValue1 == iValue2 ? 4 : 3, iValue1); + fprintf(fp, "%d cbcModel->setSpecialOptions(save_cbcSpecialOptions);\n", + iValue1 == iValue2 ? 7 : 6); iValue1 = this->messageHandler()->logLevel(); iValue2 = other->messageHandler()->logLevel(); - fprintf(fp, "%d int save_cbcMessageLevel = cbcModel->messageHandler()->logLevel();\n", iValue1 == iValue2 ? 2 : 1); - fprintf(fp, "%d cbcModel->messageHandler()->setLogLevel(%d);\n", iValue1 == iValue2 ? 4 : 3, iValue1); - fprintf(fp, "%d cbcModel->messageHandler()->setLogLevel(save_cbcMessageLevel);\n", iValue1 == iValue2 ? 7 : 6); + fprintf(fp, + "%d int save_cbcMessageLevel = " + "cbcModel->messageHandler()->logLevel();\n", + iValue1 == iValue2 ? 2 : 1); + fprintf(fp, "%d cbcModel->messageHandler()->setLogLevel(%d);\n", + iValue1 == iValue2 ? 4 : 3, iValue1); + fprintf( + fp, + "%d cbcModel->messageHandler()->setLogLevel(save_cbcMessageLevel);\n", + iValue1 == iValue2 ? 7 : 6); iValue1 = this->getMaximumCutPassesAtRoot(); iValue2 = other->getMaximumCutPassesAtRoot(); - fprintf(fp, "%d int save_getMaximumCutPassesAtRoot = cbcModel->getMaximumCutPassesAtRoot();\n", iValue1 == iValue2 ? 2 : 1); - fprintf(fp, "%d cbcModel->setMaximumCutPassesAtRoot(%d);\n", iValue1 == iValue2 ? 4 : 3, iValue1); - fprintf(fp, "%d cbcModel->setMaximumCutPassesAtRoot(save_getMaximumCutPassesAtRoot);\n", iValue1 == iValue2 ? 7 : 6); + fprintf(fp, + "%d int save_getMaximumCutPassesAtRoot = " + "cbcModel->getMaximumCutPassesAtRoot();\n", + iValue1 == iValue2 ? 2 : 1); + fprintf(fp, "%d cbcModel->setMaximumCutPassesAtRoot(%d);\n", + iValue1 == iValue2 ? 4 : 3, iValue1); + fprintf( + fp, + "%d " + "cbcModel->setMaximumCutPassesAtRoot(save_getMaximumCutPassesAtRoot);\n", + iValue1 == iValue2 ? 7 : 6); iValue1 = this->getMaximumCutPasses(); iValue2 = other->getMaximumCutPasses(); - fprintf(fp, "%d int save_getMaximumCutPasses = cbcModel->getMaximumCutPasses();\n", iValue1 == iValue2 ? 2 : 1); - fprintf(fp, "%d cbcModel->setMaximumCutPasses(%d);\n", iValue1 == iValue2 ? 4 : 3, iValue1); - fprintf(fp, "%d cbcModel->setMaximumCutPasses(save_getMaximumCutPasses);\n", iValue1 == iValue2 ? 7 : 6); + fprintf( + fp, + "%d int save_getMaximumCutPasses = cbcModel->getMaximumCutPasses();\n", + iValue1 == iValue2 ? 2 : 1); + fprintf(fp, "%d cbcModel->setMaximumCutPasses(%d);\n", + iValue1 == iValue2 ? 4 : 3, iValue1); + fprintf(fp, "%d cbcModel->setMaximumCutPasses(save_getMaximumCutPasses);\n", + iValue1 == iValue2 ? 7 : 6); iValue1 = this->getPreferredWay(); iValue2 = other->getPreferredWay(); - fprintf(fp, "%d int save_getPreferredWay = cbcModel->getPreferredWay();\n", iValue1 == iValue2 ? 2 : 1); - fprintf(fp, "%d cbcModel->setPreferredWay(%d);\n", iValue1 == iValue2 ? 4 : 3, iValue1); - fprintf(fp, "%d cbcModel->setPreferredWay(save_getPreferredWay);\n", iValue1 == iValue2 ? 7 : 6); + fprintf(fp, "%d int save_getPreferredWay = cbcModel->getPreferredWay();\n", + iValue1 == iValue2 ? 2 : 1); + fprintf(fp, "%d cbcModel->setPreferredWay(%d);\n", + iValue1 == iValue2 ? 4 : 3, iValue1); + fprintf(fp, "%d cbcModel->setPreferredWay(save_getPreferredWay);\n", + iValue1 == iValue2 ? 7 : 6); dValue1 = this->getMinimumDrop(); dValue2 = other->getMinimumDrop(); - fprintf(fp, "%d double save_getMinimumDrop = cbcModel->getMinimumDrop();\n", dValue1 == dValue2 ? 2 : 1); - fprintf(fp, "%d cbcModel->setMinimumDrop(%g);\n", dValue1 == dValue2 ? 4 : 3, dValue1); - fprintf(fp, "%d cbcModel->setMinimumDrop(save_getMinimumDrop);\n", dValue1 == dValue2 ? 7 : 6); + fprintf(fp, "%d double save_getMinimumDrop = cbcModel->getMinimumDrop();\n", + dValue1 == dValue2 ? 2 : 1); + fprintf(fp, "%d cbcModel->setMinimumDrop(%g);\n", dValue1 == dValue2 ? 4 : 3, + dValue1); + fprintf(fp, "%d cbcModel->setMinimumDrop(save_getMinimumDrop);\n", + dValue1 == dValue2 ? 7 : 6); dValue1 = this->getIntegerTolerance(); dValue2 = other->getIntegerTolerance(); - fprintf(fp, "%d double save_getIntegerTolerance = cbcModel->getIntegerTolerance();\n", dValue1 == dValue2 ? 2 : 1); - fprintf(fp, "%d cbcModel->setIntegerTolerance(%g);\n", dValue1 == dValue2 ? 4 : 3, dValue1); - fprintf(fp, "%d cbcModel->setIntegerTolerance(save_getIntegerTolerance);\n", dValue1 == dValue2 ? 7 : 6); + fprintf(fp, + "%d double save_getIntegerTolerance = " + "cbcModel->getIntegerTolerance();\n", + dValue1 == dValue2 ? 2 : 1); + fprintf(fp, "%d cbcModel->setIntegerTolerance(%g);\n", + dValue1 == dValue2 ? 4 : 3, dValue1); + fprintf(fp, "%d cbcModel->setIntegerTolerance(save_getIntegerTolerance);\n", + dValue1 == dValue2 ? 7 : 6); dValue1 = this->getInfeasibilityWeight(); dValue2 = other->getInfeasibilityWeight(); - fprintf(fp, "%d double save_getInfeasibilityWeight = cbcModel->getInfeasibilityWeight();\n", dValue1 == dValue2 ? 2 : 1); - fprintf(fp, "%d cbcModel->setInfeasibilityWeight(%g);\n", dValue1 == dValue2 ? 4 : 3, dValue1); - fprintf(fp, "%d cbcModel->setInfeasibilityWeight(save_getInfeasibilityWeight);\n", dValue1 == dValue2 ? 7 : 6); + fprintf(fp, + "%d double save_getInfeasibilityWeight = " + "cbcModel->getInfeasibilityWeight();\n", + dValue1 == dValue2 ? 2 : 1); + fprintf(fp, "%d cbcModel->setInfeasibilityWeight(%g);\n", + dValue1 == dValue2 ? 4 : 3, dValue1); + fprintf( + fp, + "%d cbcModel->setInfeasibilityWeight(save_getInfeasibilityWeight);\n", + dValue1 == dValue2 ? 7 : 6); dValue1 = this->getCutoffIncrement(); dValue2 = other->getCutoffIncrement(); - fprintf(fp, "%d double save_getCutoffIncrement = cbcModel->getCutoffIncrement();\n", dValue1 == dValue2 ? 2 : 1); - fprintf(fp, "%d cbcModel->setCutoffIncrement(%g);\n", dValue1 == dValue2 ? 4 : 3, dValue1); - fprintf(fp, "%d cbcModel->setCutoffIncrement(save_getCutoffIncrement);\n", dValue1 == dValue2 ? 7 : 6); + fprintf( + fp, + "%d double save_getCutoffIncrement = cbcModel->getCutoffIncrement();\n", + dValue1 == dValue2 ? 2 : 1); + fprintf(fp, "%d cbcModel->setCutoffIncrement(%g);\n", + dValue1 == dValue2 ? 4 : 3, dValue1); + fprintf(fp, "%d cbcModel->setCutoffIncrement(save_getCutoffIncrement);\n", + dValue1 == dValue2 ? 7 : 6); dValue1 = this->getAllowableGap(); dValue2 = other->getAllowableGap(); - fprintf(fp, "%d double save_getAllowableGap = cbcModel->getAllowableGap();\n", dValue1 == dValue2 ? 2 : 1); - fprintf(fp, "%d cbcModel->setAllowableGap(%g);\n", dValue1 == dValue2 ? 4 : 3, dValue1); - fprintf(fp, "%d cbcModel->setAllowableGap(save_getAllowableGap);\n", dValue1 == dValue2 ? 7 : 6); + fprintf(fp, + "%d double save_getAllowableGap = cbcModel->getAllowableGap();\n", + dValue1 == dValue2 ? 2 : 1); + fprintf(fp, "%d cbcModel->setAllowableGap(%g);\n", + dValue1 == dValue2 ? 4 : 3, dValue1); + fprintf(fp, "%d cbcModel->setAllowableGap(save_getAllowableGap);\n", + dValue1 == dValue2 ? 7 : 6); dValue1 = this->getAllowableFractionGap(); dValue2 = other->getAllowableFractionGap(); - fprintf(fp, "%d double save_getAllowableFractionGap = cbcModel->getAllowableFractionGap();\n", dValue1 == dValue2 ? 2 : 1); - fprintf(fp, "%d cbcModel->setAllowableFractionGap(%g);\n", dValue1 == dValue2 ? 4 : 3, dValue1); - fprintf(fp, "%d cbcModel->setAllowableFractionGap(save_getAllowableFractionGap);\n", dValue1 == dValue2 ? 7 : 6); + fprintf(fp, + "%d double save_getAllowableFractionGap = " + "cbcModel->getAllowableFractionGap();\n", + dValue1 == dValue2 ? 2 : 1); + fprintf(fp, "%d cbcModel->setAllowableFractionGap(%g);\n", + dValue1 == dValue2 ? 4 : 3, dValue1); + fprintf( + fp, + "%d cbcModel->setAllowableFractionGap(save_getAllowableFractionGap);\n", + dValue1 == dValue2 ? 7 : 6); dValue1 = this->getMaximumSeconds(); dValue2 = other->getMaximumSeconds(); - fprintf(fp, "%d double save_cbcMaximumSeconds = cbcModel->getMaximumSeconds();\n", dValue1 == dValue2 ? 2 : 1); - fprintf(fp, "%d cbcModel->setMaximumSeconds(%g);\n", dValue1 == dValue2 ? 4 : 3, dValue1); - fprintf(fp, "%d cbcModel->setMaximumSeconds(save_cbcMaximumSeconds);\n", dValue1 == dValue2 ? 7 : 6); + fprintf( + fp, + "%d double save_cbcMaximumSeconds = cbcModel->getMaximumSeconds();\n", + dValue1 == dValue2 ? 2 : 1); + fprintf(fp, "%d cbcModel->setMaximumSeconds(%g);\n", + dValue1 == dValue2 ? 4 : 3, dValue1); + fprintf(fp, "%d cbcModel->setMaximumSeconds(save_cbcMaximumSeconds);\n", + dValue1 == dValue2 ? 7 : 6); } // So we can use osiObject or CbcObject during transition void getIntegerInformation(const OsiObject *object, double &originalLower, - double &originalUpper) -{ - const CbcSimpleInteger *integerObject = dynamic_cast< const CbcSimpleInteger * >(object); + double &originalUpper) { + const CbcSimpleInteger *integerObject = + dynamic_cast(object); if (integerObject) { // get original bounds originalLower = integerObject->originalLowerBound(); originalUpper = integerObject->originalUpperBound(); } else { - const OsiSimpleInteger *integerObject = dynamic_cast< const OsiSimpleInteger * >(object); + const OsiSimpleInteger *integerObject = + dynamic_cast(object); assert(integerObject); // get original bounds originalLower = integerObject->originalLowerBound(); @@ -16591,8 +16990,7 @@ void getIntegerInformation(const OsiObject *object, double &originalLower, } } // Set original columns as created by preprocessing -void CbcModel::setOriginalColumns(const int *originalColumns, int numberGood) -{ +void CbcModel::setOriginalColumns(const int *originalColumns, int numberGood) { int numberColumns = getNumCols(); delete[] originalColumns_; originalColumns_ = new int[numberColumns]; @@ -16602,15 +17000,13 @@ void CbcModel::setOriginalColumns(const int *originalColumns, int numberGood) originalColumns_[i] = -1; } // Set the cut modifier method -void CbcModel::setCutModifier(CbcCutModifier *modifier) -{ +void CbcModel::setCutModifier(CbcCutModifier *modifier) { delete cutModifier_; cutModifier_ = modifier->clone(); } /* Set the cut modifier method */ -void CbcModel::setCutModifier(CbcCutModifier &modifier) -{ +void CbcModel::setCutModifier(CbcCutModifier &modifier) { delete cutModifier_; cutModifier_ = modifier.clone(); } @@ -16620,8 +17016,8 @@ void CbcModel::setCutModifier(CbcCutModifier &modifier) node NULL on return if no branches left newNode NULL if no new node created */ -int CbcModel::doOneNode(CbcModel *baseModel, CbcNode *&node, CbcNode *&newNode) -{ +int CbcModel::doOneNode(CbcModel *baseModel, CbcNode *&node, + CbcNode *&newNode) { int foundSolution = 0; int saveNumberCutGenerators = numberCutGenerators_; #ifdef SAVE_NODE_INFO @@ -16639,24 +17035,22 @@ int CbcModel::doOneNode(CbcModel *baseModel, CbcNode *&node, CbcNode *&newNode) bool onOptimalPath = false; #ifdef CHECK_NODE printf("Node %x popped from tree - %d left, %d count\n", node, - node->nodeInfo()->numberBranchesLeft(), - node->nodeInfo()->numberPointingToThis()); - printf("\tdepth = %d, z = %g, unsat = %d\n", //var = %d.\n", - node->depth(), node->objectiveValue(), - node->numberUnsatisfied()); - //node->columnNumber()) ; + node->nodeInfo()->numberBranchesLeft(), + node->nodeInfo()->numberPointingToThis()); + printf("\tdepth = %d, z = %g, unsat = %d\n", // var = %d.\n", + node->depth(), node->objectiveValue(), node->numberUnsatisfied()); + // node->columnNumber()) ; #endif /* - Rebuild the subproblem for this node: Call addCuts() to adjust the model - to recreate the subproblem for this node (set proper variable bounds, add - cuts, create a basis). This may result in the problem being fathomed by - bound or infeasibility. Returns 1 if node is fathomed. - Execute the current arm of the branch: If the problem survives, save the - resulting variable bounds and call branch() to modify variable bounds - according to the current arm of the branching object. If we're processing - the final arm of the branching object, flag the node for removal from the - live set. + Rebuild the subproblem for this node: Call addCuts() to adjust the + model to recreate the subproblem for this node (set proper variable bounds, + add cuts, create a basis). This may result in the problem being fathomed + by bound or infeasibility. Returns 1 if node is fathomed. Execute the + current arm of the branch: If the problem survives, save the resulting + variable bounds and call branch() to modify variable bounds according to + the current arm of the branching object. If we're processing the final arm + of the branching object, flag the node for removal from the live set. */ /* Used to generate bound edits for CbcPartialNodeInfo. @@ -16672,9 +17066,9 @@ int CbcModel::doOneNode(CbcModel *baseModel, CbcNode *&node, CbcNode *&newNode) CoinWarmStartBasis *lastws = new CoinWarmStartBasis(); lockThread(); // point to genuine ones - //int save1 = maximumNumberCuts_; - //maximumNumberCuts_ = baseModel->maximumNumberCuts_; - //addedCuts_ = baseModel->addedCuts_; + // int save1 = maximumNumberCuts_; + // maximumNumberCuts_ = baseModel->maximumNumberCuts_; + // addedCuts_ = baseModel->addedCuts_; if (parallelMode() >= 0) { maximumDepth_ = baseModel->maximumDepth_; walkback_ = baseModel->walkback_; @@ -16688,10 +17082,10 @@ int CbcModel::doOneNode(CbcModel *baseModel, CbcNode *&node, CbcNode *&newNode) #ifdef SWITCH_VARIABLES fixAssociated(solver_, 0); #endif - //if (save1maximumNumberCuts_ = maximumNumberCuts_; - //baseModel->addedCuts_ = addedCuts_; + // baseModel->maximumNumberCuts_ = maximumNumberCuts_; + // baseModel->addedCuts_ = addedCuts_; //} if (parallelMode() >= 0 && save2 < maximumDepth_) { // increased @@ -16726,10 +17120,10 @@ int CbcModel::doOneNode(CbcModel *baseModel, CbcNode *&node, CbcNode *&newNode) // old way so need to cheat OsiBranchingObject *branch2 = node->modifiableBranchingObject(); #ifndef NDEBUG - CbcBranchingObject *branch = dynamic_cast< CbcBranchingObject * >(branch2); + CbcBranchingObject *branch = dynamic_cast(branch2); assert(branch); #else - CbcBranchingObject *branch = static_cast< CbcBranchingObject * >(branch2); + CbcBranchingObject *branch = static_cast(branch2); #endif #if 1 branch->setModel(this); @@ -16750,9 +17144,9 @@ int CbcModel::doOneNode(CbcModel *baseModel, CbcNode *&node, CbcNode *&newNode) if ((specialOptions_ & 1) != 0) { /* This doesn't work as intended --- getRowCutDebugger will return null - unless the current feasible solution region includes the optimal solution - that RowCutDebugger knows. There's no way to tell inactive from off the - optimal path. + unless the current feasible solution region includes the optimal + solution that RowCutDebugger knows. There's no way to tell inactive + from off the optimal path. */ const OsiRowCutDebugger *debugger = solver_->getRowCutDebugger(); if (debugger) { @@ -16763,8 +17157,8 @@ int CbcModel::doOneNode(CbcModel *baseModel, CbcNode *&node, CbcNode *&newNode) /* Reoptimize, possibly generating cuts and/or using heuristics to find - solutions. Cut reference counts are unaffected unless we lose feasibility, - in which case solveWithCuts() will make the adjustment. + solutions. Cut reference counts are unaffected unless we lose + feasibility, in which case solveWithCuts() will make the adjustment. */ phase_ = 2; OsiCuts cuts; @@ -16776,12 +17170,13 @@ int CbcModel::doOneNode(CbcModel *baseModel, CbcNode *&node, CbcNode *&newNode) int iObject; int numberUnsatisfied = 0; memcpy(currentSolution_, solver_->getColSolution(), - numberColumns * sizeof(double)); + numberColumns * sizeof(double)); // point to useful information OsiBranchingInformation usefulInfo = usefulInformation(); for (iObject = 0; iObject < numberObjects_; iObject++) { - double infeasibility = object_[iObject]->checkInfeasibility(&usefulInfo); + double infeasibility = + object_[iObject]->checkInfeasibility(&usefulInfo); if (infeasibility) numberUnsatisfied++; } @@ -16790,9 +17185,8 @@ int CbcModel::doOneNode(CbcModel *baseModel, CbcNode *&node, CbcNode *&newNode) feasible = solveWithCuts(cuts, maximumCutPasses_, node); } else { // may generate cuts and turn the solution - //to an infeasible one - feasible = solveWithCuts(cuts, 1, - node); + // to an infeasible one + feasible = solveWithCuts(cuts, 1, node); } } // check extra info on feasibility @@ -16812,10 +17206,10 @@ int CbcModel::doOneNode(CbcModel *baseModel, CbcNode *&node, CbcNode *&newNode) printf("%d fixed to %g\n", i, lower[i]); } #ifdef CBC_HAS_CLP - OsiClpSolverInterface *clpSolver - = dynamic_cast< OsiClpSolverInterface * >(solver_); - if ((clpSolver || (specialOptions_ & 16384) != 0) && fastNodeDepth_ < -1 - && (specialOptions_ & 2048) == 0) { + OsiClpSolverInterface *clpSolver = + dynamic_cast(solver_); + if ((clpSolver || (specialOptions_ & 16384) != 0) && + fastNodeDepth_ < -1 && (specialOptions_ & 2048) == 0) { #define FATHOM_BIAS -2 if (numberNodes_ == 1) { int numberNodesBeforeFathom = 500; @@ -16826,7 +17220,7 @@ int CbcModel::doOneNode(CbcModel *baseModel, CbcNode *&node, CbcNode *&newNode) #ifdef COIN_DEVELOP int fastNodeDepth1 = -fastNodeDepth_ % 1000000; printf("initial depth %d after %d nodes\n", - FATHOM_BIAS + fastNodeDepth1, numberNodesBeforeFathom); + FATHOM_BIAS + fastNodeDepth1, numberNodesBeforeFathom); #endif } //#endif @@ -16835,8 +17229,8 @@ int CbcModel::doOneNode(CbcModel *baseModel, CbcNode *&node, CbcNode *&newNode) /* Used to generate bound edits for CbcPartialNodeInfo. */ - //double * lowerBefore = NULL; - //double * upperBefore = NULL; + // double * lowerBefore = NULL; + // double * upperBefore = NULL; int fastNodeDepth1 = -fastNodeDepth_ % 1000000; int numberNodesBeforeFathom = 500; if (fastNodeDepth_ < -1000001) { @@ -16846,9 +17240,10 @@ int CbcModel::doOneNode(CbcModel *baseModel, CbcNode *&node, CbcNode *&newNode) int go_fathom = FATHOM_BIAS + fastNodeDepth1; if ((specialOptions_ & 16384) != 0) numberNodesBeforeFathom = 0; - if (node->depth() >= go_fathom && (specialOptions_ & 2048) == 0 - //if (node->depth()>=FATHOM_BIAS-fastNodeDepth_&&!parentModel_ - && numberNodes_ >= numberNodesBeforeFathom && !hotstartSolution_) { + if (node->depth() >= go_fathom && + (specialOptions_ & 2048) == 0 + // if (node->depth()>=FATHOM_BIAS-fastNodeDepth_&&!parentModel_ + && numberNodes_ >= numberNodesBeforeFathom && !hotstartSolution_) { #ifndef CBC_HAS_OSICPX specialOptions_ &= ~16384; #endif @@ -16863,13 +17258,15 @@ int CbcModel::doOneNode(CbcModel *baseModel, CbcNode *&node, CbcNode *&newNode) if (numberNodes_ > 2 * numberObjects_ + 1000) { info->stateOfSearch_ = 4; } - // try this - info->stateOfSearch_ = stateOfSearch_; + // try this + info->stateOfSearch_ = stateOfSearch_; // Compute "small" change in branch int nBranches = intParam_[CbcNumberBranches]; if (nBranches) { - double average = dblParam_[CbcSumChange] / static_cast< double >(nBranches); - info->smallChange_ = CoinMax(average * 1.0e-5, dblParam_[CbcSmallestChange]); + double average = + dblParam_[CbcSumChange] / static_cast(nBranches); + info->smallChange_ = + CoinMax(average * 1.0e-5, dblParam_[CbcSmallestChange]); info->smallChange_ = CoinMax(info->smallChange_, 1.0e-8); } else { info->smallChange_ = 1.0e-8; @@ -16882,7 +17279,7 @@ int CbcModel::doOneNode(CbcModel *baseModel, CbcNode *&node, CbcNode *&newNode) int *numberDownInfeasible = new int[numberIntegers_]; int *numberUpInfeasible = new int[numberIntegers_]; fillPseudoCosts(down, up, priority, numberDown, numberUp, - numberDownInfeasible, numberUpInfeasible); + numberDownInfeasible, numberUpInfeasible); // See if all priorities same bool allSame = true; int kPriority = priority[0]; @@ -16893,8 +17290,10 @@ int CbcModel::doOneNode(CbcModel *baseModel, CbcNode *&node, CbcNode *&newNode) } } ClpSimplex *simplex = clpSolver->getModelPtr(); - double *saveLower = CoinCopyOfArray(solver_->getColLower(), numberColumns); - double *saveUpper = CoinCopyOfArray(solver_->getColUpper(), numberColumns); + double *saveLower = + CoinCopyOfArray(solver_->getColLower(), numberColumns); + double *saveUpper = + CoinCopyOfArray(solver_->getColUpper(), numberColumns); if (allSame && false) { // change priorities on general const double *lower = simplex->columnLower(); @@ -16906,8 +17305,8 @@ int CbcModel::doOneNode(CbcModel *baseModel, CbcNode *&node, CbcNode *&newNode) } } info->fillPseudoCosts(down, up, priority, numberDown, numberUp, - numberDownInfeasible, - numberUpInfeasible, numberIntegers_); + numberDownInfeasible, numberUpInfeasible, + numberIntegers_); info->presolveType_ = 1; // for reduced costs and duals info->solverOptions_ |= 7; @@ -16921,7 +17320,7 @@ int CbcModel::doOneNode(CbcModel *baseModel, CbcNode *&node, CbcNode *&newNode) bool takeHint; OsiHintStrength strength; solver_->getHintParam(OsiDoReducePrint, takeHint, strength); - //printf("mod cutoff %g solver %g offset %g\n", + // printf("mod cutoff %g solver %g offset %g\n", // getCutoff(),simplex->dualObjectiveLimit(),simplex->objectiveOffset()); int saveLevel = simplex->logLevel(); if (strength != OsiHintIgnore && takeHint && saveLevel == 1) @@ -16929,7 +17328,7 @@ int CbcModel::doOneNode(CbcModel *baseModel, CbcNode *&node, CbcNode *&newNode) clpSolver->setBasis(); int perturbation = simplex->perturbation(); if ((specialOptions_ & 131072) != 0) { - //assert (perturbation == 100); + // assert (perturbation == 100); simplex->setPerturbation(50); } int saveMoreOptions = simplex->moreSpecialOptions(); @@ -16943,15 +17342,15 @@ int CbcModel::doOneNode(CbcModel *baseModel, CbcNode *&node, CbcNode *&newNode) feasible = simplex->fathom(info) != 0; simplex->setMoreSpecialOptions(saveMoreOptions); simplex->setPerturbation(perturbation); - incrementExtra(info->numberNodesExplored_, - info->numberIterations_); + incrementExtra(info->numberNodesExplored_, info->numberIterations_); if (feasible && false) { // can mess up cuts double objValue = simplex->objectiveValue(); feasible = solveWithCuts(cuts, 1, node); if (!feasible) { if ((specialOptions_ & 1) != 0) - printf("small was feasible %g now infeasible! - depths %d %d\n", - objValue, node->depth(), fastNodeDepth_); + printf( + "small was feasible %g now infeasible! - depths %d %d\n", + objValue, node->depth(), fastNodeDepth_); // switch off info->nNodes_ = -99; solver_->setColLower(saveLower); @@ -16963,55 +17362,59 @@ int CbcModel::doOneNode(CbcModel *baseModel, CbcNode *&node, CbcNode *&newNode) if (feasible) fathomStatus = 1; sprintf(general, "fathom took %d nodes, %d iterations - status %d", - info->numberNodesExplored_, - info->numberIterations_, fathomStatus); - messageHandler()->message(CBC_FPUMP2, - messages()) - << general << CoinMessageEol; - if (info->numberNodesExplored_ > 10000 /* && !feasible */ - && (moreSpecialOptions_ & 524288) == 0 && info->nNodes_ >= 0) { + info->numberNodesExplored_, info->numberIterations_, + fathomStatus); + messageHandler()->message(CBC_FPUMP2, messages()) + << general << CoinMessageEol; + if ((info->numberNodesExplored_ > 50000 || + info->numberNodesExplored_ > 10000 && + (moreSpecialOptions_&2048) == 0) + && (moreSpecialOptions_ & 524288) == 0 && info->nNodes_ >= 0) { fastNodeDepth_--; #ifndef NO_FATHOM_PRINT if ((moreSpecialOptions_ & 262144) != 0) - handler_->message(CBC_FATHOM_CHANGE, messages_) << FATHOM_BIAS - fastNodeDepth_ << CoinMessageEol; + handler_->message(CBC_FATHOM_CHANGE, messages_) + << FATHOM_BIAS - fastNodeDepth_ << CoinMessageEol; #endif #if CBC_USEFUL_PRINTING > 0 printf(">10000 - depth now %d so at depth >= %d\n", - fastNodeDepth_, FATHOM_BIAS - fastNodeDepth_); + fastNodeDepth_, FATHOM_BIAS - fastNodeDepth_); #endif } if (info->nNodes_ < 0) { // we gave up - //abort(); - fastNodeDepth_ -= (info->nNodes_ == -10) ? 5 : 2; + // abort(); + fastNodeDepth_ -= 2; if (info->nNodes_ == -99) fastNodeDepth_ = -1; // switch off #ifndef NO_FATHOM_PRINT if ((moreSpecialOptions_ & 262144) != 0) - handler_->message(CBC_FATHOM_CHANGE, messages_) << FATHOM_BIAS - fastNodeDepth_ << CoinMessageEol; + handler_->message(CBC_FATHOM_CHANGE, messages_) + << FATHOM_BIAS - fastNodeDepth_ << CoinMessageEol; #endif #if CBC_USEFUL_PRINTING > 0 printf("gave up fastNodeDepth now %d - so at depth >= %d\n", - fastNodeDepth_, FATHOM_BIAS - fastNodeDepth_); + fastNodeDepth_, FATHOM_BIAS - fastNodeDepth_); #endif if (feasible) { // Save bounds round bestSolution - //double * saveLower = CoinCopyOfArray(solver_->getColLower(), + // double * saveLower = CoinCopyOfArray(solver_->getColLower(), // numberColumns); - //double * saveUpper = CoinCopyOfArray(solver_->getColUpper(), + // double * saveUpper = CoinCopyOfArray(solver_->getColUpper(), // numberColumns); clpSolver->setWarmStart(NULL); // try and do solution double value = simplex->objectiveValue(); - double *newSolution = CoinCopyOfArray(simplex->primalColumnSolution(), - numberColumns); + double *newSolution = CoinCopyOfArray( + simplex->primalColumnSolution(), numberColumns); double saveBest = bestObjective_; setBestSolution(CBC_STRONGSOL, value, newSolution); delete[] newSolution; if (bestObjective_ == saveBest) { if ((specialOptions_ & 1) != 0) - printf("small was feasible now just infeasible! - depths %d %d\n", - node->depth(), fastNodeDepth_); + printf("small was feasible now just infeasible! - depths " + "%d %d\n", + node->depth(), fastNodeDepth_); fastNodeDepth_ = -1; // switch off solver_->setColLower(saveLower); solver_->setColUpper(saveUpper); @@ -17024,28 +17427,39 @@ int CbcModel::doOneNode(CbcModel *baseModel, CbcNode *&node, CbcNode *&newNode) clpSolver->setWarmStart(NULL); // try and do solution double value = simplex->objectiveValue(); - double *newSolution = CoinCopyOfArray(simplex->primalColumnSolution(), - numberColumns); + double *newSolution = CoinCopyOfArray( + simplex->primalColumnSolution(), numberColumns); double saveBest = bestObjective_; setBestSolution(CBC_STRONGSOL, value, newSolution); // in case of inaccuracy - simplex->setObjectiveValue(CoinMax(bestObjective_, - simplex->objectiveValue())); + simplex->setObjectiveValue( + CoinMax(bestObjective_, simplex->objectiveValue())); delete[] newSolution; if (bestObjective_ == saveBest) { - if ((specialOptions_ & 1) != 0) - printf("small was feasible now just infeasible! - depths %d %d\n", - node->depth(), fastNodeDepth_); - fastNodeDepth_ = -1; // switch off - solver_->setColLower(saveLower); - solver_->setColUpper(saveUpper); + if (value > saveBest) { + if ((specialOptions_ & 1) != 0) + printf("small was feasible now just infeasible! - depths " + "%d %d\n", + node->depth(), fastNodeDepth_); + fastNodeDepth_ = -1; // switch off + solver_->setColLower(saveLower); + solver_->setColUpper(saveUpper); + } else { + // due to scaling etc got back to equal best solution + if ((specialOptions_ & 1) != 0) + printf("small was feasible == previous! - depths " + "%d %d\n", + node->depth(), fastNodeDepth_); + } } } // update pseudo costs double smallest = 1.0e50; double largest = -1.0; for (int i = 0; i < numberIntegers_; i++) { - CbcSimpleIntegerDynamicPseudoCost *obj = dynamic_cast< CbcSimpleIntegerDynamicPseudoCost * >(object_[i]); + CbcSimpleIntegerDynamicPseudoCost *obj = + dynamic_cast( + object_[i]); if (!obj) continue; assert(obj->columnNumber() == integerVariable_[i]); @@ -17058,15 +17472,13 @@ int CbcModel::doOneNode(CbcModel *baseModel, CbcNode *&node, CbcNode *&newNode) largest = info->upPseudo_[i]; if (info->upPseudo_[i] < smallest) smallest = info->upPseudo_[i]; - obj->updateAfterMini(info->numberDown_[i], - info->numberDownInfeasible_[i], - info->downPseudo_[i], - info->numberUp_[i], - info->numberUpInfeasible_[i], - info->upPseudo_[i]); + obj->updateAfterMini( + info->numberDown_[i], info->numberDownInfeasible_[i], + info->downPseudo_[i], info->numberUp_[i], + info->numberUpInfeasible_[i], info->upPseudo_[i]); } } - //printf("range of costs %g to %g\n",smallest,largest); + // printf("range of costs %g to %g\n",smallest,largest); } delete[] saveLower; delete[] saveUpper; @@ -17084,8 +17496,8 @@ int CbcModel::doOneNode(CbcModel *baseModel, CbcNode *&node, CbcNode *&newNode) const double *columnLower = clpSolver->getColLower(); const double *columnUpper = clpSolver->getColUpper(); const double *objective = clpSolver->getObjCoefficients(); - cpxSolver.loadProblem(*matrix, columnLower, columnUpper, - objective, rowLower, rowUpper); + cpxSolver.loadProblem(*matrix, columnLower, columnUpper, objective, + rowLower, rowUpper); double *setSol = new double[numberIntegers_]; int *setVar = new int[numberIntegers_]; // cplex doesn't know about objective offset @@ -17099,35 +17511,40 @@ int CbcModel::doOneNode(CbcModel *baseModel, CbcNode *&node, CbcNode *&newNode) } } CPXENVptr env = cpxSolver.getEnvironmentPtr(); - CPXLPptr lpPtr = cpxSolver.getLpPtr(OsiCpxSolverInterface::KEEPCACHED_ALL); + CPXLPptr lpPtr = + cpxSolver.getLpPtr(OsiCpxSolverInterface::KEEPCACHED_ALL); cpxSolver.switchToMIP(); if (bestSolution_) { #if 0 CPXcopymipstart(env, lpPtr, numberIntegers_, setVar, setSol); #else int zero = 0; - CPXaddmipstarts(env, lpPtr, 1, numberIntegers_, &zero, setVar, setSol, NULL, NULL); + CPXaddmipstarts(env, lpPtr, 1, numberIntegers_, &zero, setVar, + setSol, NULL, NULL); #endif } if (getCutoff() < 1.0e50) { double useCutoff = getCutoff() + offset; if (bestObjective_ < 1.0e50) useCutoff = bestObjective_ + offset + 1.0e-7; - cpxSolver.setDblParam(OsiDualObjectiveLimit, useCutoff * direction); + cpxSolver.setDblParam(OsiDualObjectiveLimit, + useCutoff * direction); if (direction > 0.0) CPXsetdblparam(env, CPX_PARAM_CUTUP, useCutoff); // min else CPXsetdblparam(env, CPX_PARAM_CUTLO, useCutoff); // max } - CPXsetdblparam(env, CPX_PARAM_EPGAP, dblParam_[CbcAllowableFractionGap]); + CPXsetdblparam(env, CPX_PARAM_EPGAP, + dblParam_[CbcAllowableFractionGap]); delete[] setSol; delete[] setVar; if (offset) { char printBuffer[200]; - sprintf(printBuffer, "Add %g to all Cplex messages for true objective", - -offset); + sprintf(printBuffer, + "Add %g to all Cplex messages for true objective", + -offset); messageHandler()->message(CBC_GENERAL, messages()) - << printBuffer << CoinMessageEol; + << printBuffer << CoinMessageEol; cpxSolver.setDblParam(OsiObjOffset, offset); } cpxSolver.branchAndBound(); @@ -17138,8 +17555,8 @@ int CbcModel::doOneNode(CbcModel *baseModel, CbcNode *&node, CbcNode *&newNode) feasible = true; clpSolver->setWarmStart(NULL); // try and do solution - double *newSolution = CoinCopyOfArray(cpxSolver.getColSolution(), - getNumCols()); + double *newSolution = + CoinCopyOfArray(cpxSolver.getColSolution(), getNumCols()); setBestSolution(CBC_STRONGSOL, value, newSolution); delete[] newSolution; } @@ -17148,7 +17565,7 @@ int CbcModel::doOneNode(CbcModel *baseModel, CbcNode *&node, CbcNode *&newNode) } } if (feasible) { - //int numberPasses = doCutsNow(1) ? maximumCutPasses_ : 0; + // int numberPasses = doCutsNow(1) ? maximumCutPasses_ : 0; int numberPasses = /*doCutsNow(1) ?*/ maximumCutPasses_ /*: 0*/; feasible = solveWithCuts(cuts, numberPasses, node); } @@ -17191,17 +17608,17 @@ int CbcModel::doOneNode(CbcModel *baseModel, CbcNode *&node, CbcNode *&newNode) assert(numberNodes2_); assert(statistics_[numberNodes2_ - 1]); assert(statistics_[numberNodes2_ - 1]->node() == numberNodes2_ - 1); - statistics_[numberNodes2_ - 1]->endOfBranch(numberIterations_ - saveNumber, - feasible ? solver_->getObjValue() - : COIN_DBL_MAX); + statistics_[numberNodes2_ - 1]->endOfBranch( + numberIterations_ - saveNumber, + feasible ? solver_->getObjValue() : COIN_DBL_MAX); } /* - Are we still feasible? If so, create a node and do the work to attach a - branching object, reoptimising as needed if chooseBranch() identifies + Are we still feasible? If so, create a node and do the work to attach + a branching object, reoptimising as needed if chooseBranch() identifies monotone objects. - Finally, attach a partial nodeInfo object and store away any cuts that we - created back in solveWithCuts. addCuts() will initialise the reference + Finally, attach a partial nodeInfo object and store away any cuts that + we created back in solveWithCuts. addCuts() will initialise the reference counts for these new cuts. This next test can be problematic if we've discovered an @@ -17215,7 +17632,8 @@ int CbcModel::doOneNode(CbcModel *baseModel, CbcNode *&node, CbcNode *&newNode) printf("infeas2\n"); solver_->getRowCutDebuggerAlways()->printOptimalSolution(*solver_); solver_->writeMpsNative("infeas.mps", NULL, NULL, 2); - CoinWarmStartBasis *slack = dynamic_cast< CoinWarmStartBasis * >(solver_->getEmptyWarmStart()); + CoinWarmStartBasis *slack = + dynamic_cast(solver_->getEmptyWarmStart()); solver_->setWarmStart(slack); delete slack; solver_->setHintParam(OsiDoReducePrint, false, OsiHintDo, 0); @@ -17246,13 +17664,15 @@ int CbcModel::doOneNode(CbcModel *baseModel, CbcNode *&node, CbcNode *&newNode) memset(touched, 0, numberColumns); double direction = solver_->getObjSense(); bool canDelete = nodeInfo->numberBranchesLeft() > 0; - //int numberBounds = nodeInfo->numberChangedBounds(); - //const int * which = nodeInfo->variables(); - //const double * bounds = nodeInfo->newBounds(); + // int numberBounds = nodeInfo->numberChangedBounds(); + // const int * which = nodeInfo->variables(); + // const double * bounds = nodeInfo->newBounds(); const OsiBranchingObject *obj = node->branchingObject(); - const CbcIntegerBranchingObject *objectI = dynamic_cast< const CbcIntegerBranchingObject * >(obj); + const CbcIntegerBranchingObject *objectI = + dynamic_cast(obj); if (objectI) { - const CbcSimpleInteger *object1 = dynamic_cast< const CbcSimpleInteger * >(objectI->object()); + const CbcSimpleInteger *object1 = + dynamic_cast(objectI->object()); int iColumn1 = -1; int way1 = 0; const double *bounds1 = NULL; @@ -17262,7 +17682,8 @@ int CbcModel::doOneNode(CbcModel *baseModel, CbcNode *&node, CbcNode *&newNode) double originalLower1 = object1->originalLowerBound(); double originalUpper1 = object1->originalUpperBound(); // Unset all bounds from parents - CbcPartialNodeInfo *partial = dynamic_cast< CbcPartialNodeInfo * >(nodeInfo); + CbcPartialNodeInfo *partial = + dynamic_cast(nodeInfo); touched[iColumn1] = 1; if (partial) { /* maybe don't do if obj hasn't changed @@ -17294,9 +17715,10 @@ int CbcModel::doOneNode(CbcModel *baseModel, CbcNode *&node, CbcNode *&newNode) way1 = objectI->way(); assert(way1 == -1 || way1 == 1); int kWay = way1; - //way1 = -way1; // what last branch did + // way1 = -way1; // what last branch did // work out using bounds - if (objectI->downBounds()[1] >= upper[iColumn1] && objectI->downBounds()[0] <= lower[iColumn1]) + if (objectI->downBounds()[1] >= upper[iColumn1] && + objectI->downBounds()[0] <= lower[iColumn1]) way1 = -1; else way1 = 1; @@ -17309,15 +17731,18 @@ int CbcModel::doOneNode(CbcModel *baseModel, CbcNode *&node, CbcNode *&newNode) bounds1 = objectI->upBounds(); } // double check bounds - assert(bounds1[0] <= lower[iColumn1] && bounds1[1] >= upper[iColumn1]); + assert(bounds1[0] <= lower[iColumn1] && + bounds1[1] >= upper[iColumn1]); } bool inBetween = false; #ifdef CBC_PRINT2 - printf("%d (way %d) with down bounds %g, %g and up bounds %g, %g current bounds %g, %g solution %g dj %g (bleft %d)\n", - iColumn1, way1, objectI->downBounds()[0], objectI->downBounds()[1], - objectI->upBounds()[0], objectI->upBounds()[1], - lower[iColumn1], upper[iColumn1], solution[iColumn1], - dj[iColumn1], nodeInfo->numberBranchesLeft()); + printf("%d (way %d) with down bounds %g, %g and up bounds %g, %g " + "current bounds %g, %g solution %g dj %g (bleft %d)\n", + iColumn1, way1, objectI->downBounds()[0], + objectI->downBounds()[1], objectI->upBounds()[0], + objectI->upBounds()[1], lower[iColumn1], upper[iColumn1], + solution[iColumn1], dj[iColumn1], + nodeInfo->numberBranchesLeft()); #endif while (nodeInfo->parent()) { nodeInfo = nodeInfo->parent(); @@ -17325,10 +17750,12 @@ int CbcModel::doOneNode(CbcModel *baseModel, CbcNode *&node, CbcNode *&newNode) if (!nodeLook || nodeLook->objectiveValue() == 0.5 * COIN_DBL_MAX) continue; OsiBranchingObject *obj = nodeLook->modifiableBranchingObject(); - CbcIntegerBranchingObject *objectI = dynamic_cast< CbcIntegerBranchingObject * >(obj); - //const OsiObject * object2a = obj->originalObject(); - //assert (object2a); - const CbcSimpleInteger *object2 = dynamic_cast< const CbcSimpleInteger * >(objectI->object()); + CbcIntegerBranchingObject *objectI = + dynamic_cast(obj); + // const OsiObject * object2a = obj->originalObject(); + // assert (object2a); + const CbcSimpleInteger *object2 = + dynamic_cast(objectI->object()); if (nodeInfo->numberBranchesLeft() && object2) { int iColumn2 = object2->columnNumber(); double originalLower = object2->originalLowerBound(); @@ -17337,17 +17764,20 @@ int CbcModel::doOneNode(CbcModel *baseModel, CbcNode *&node, CbcNode *&newNode) zeroOne1 = true; // temp double newUpper = originalUpper; double newLower = originalLower; - //double value = solution[iColumn2]; + // double value = solution[iColumn2]; double djValue = dj[iColumn2] * direction; int way = objectI->way(); assert(way == -1 || way == 1); way = -way; // what last branch did #ifdef CBC_PRINT2 - printf("%d (way %d) with down bounds %g, %g and up bounds %g, %g current bounds %g, %g solution %g dj %g (bleft %d)\n", - iColumn2, way, objectI->downBounds()[0], objectI->downBounds()[1], - objectI->upBounds()[0], objectI->upBounds()[1], - lower[iColumn2], upper[iColumn2], solution[iColumn2], - djValue, nodeInfo->numberBranchesLeft()); + printf( + "%d (way %d) with down bounds %g, %g and up bounds %g, %g " + "current bounds %g, %g solution %g dj %g (bleft %d)\n", + iColumn2, way, objectI->downBounds()[0], + objectI->downBounds()[1], objectI->upBounds()[0], + objectI->upBounds()[1], lower[iColumn2], upper[iColumn2], + solution[iColumn2], djValue, + nodeInfo->numberBranchesLeft()); #endif /*if (objectI->downBounds()[0]==0&&objectI->downBounds()[1]==1&& objectI->upBounds()[0]==0&&objectI->upBounds()[1]==1) @@ -17355,34 +17785,45 @@ int CbcModel::doOneNode(CbcModel *baseModel, CbcNode *&node, CbcNode *&newNode) if (way < 0) { // must have been down branch const double *bounds = objectI->downBounds(); - if (djValue > 1.0e-3 || solution[iColumn2] < upper[iColumn2] - 1.0e-5) { + if (djValue > 1.0e-3 || + solution[iColumn2] < upper[iColumn2] - 1.0e-5) { if (canDelete) { - //nRedundantDown++; + // nRedundantDown++; #ifndef JJF_ONE - COIN_DETAIL_PRINT(printf("%d redundant branch down with bounds %g, %g current upper %g solution %g dj %g\n", - iColumn2, bounds[0], bounds[1], upper[iColumn2], solution[iColumn2], djValue)); -#endif - if (bounds[0] == bounds[1] || zeroOne2 || (bounds[0] == lower[iColumn2] && false)) { + COIN_DETAIL_PRINT( + printf("%d redundant branch down with bounds %g, %g " + "current upper %g solution %g dj %g\n", + iColumn2, bounds[0], bounds[1], + upper[iColumn2], solution[iColumn2], djValue)); +#endif + if (bounds[0] == bounds[1] || zeroOne2 || + (bounds[0] == lower[iColumn2] && false)) { { // get rid of node as far as branching nodeLook->setObjectiveValue(0.5 * COIN_DBL_MAX); objectI->deactivate(); } - previousBounds(node, nodeInfo, iColumn2, newLower, newUpper, 2); + previousBounds(node, nodeInfo, iColumn2, newLower, + newUpper, 2); solver_->setColUpper(iColumn2, newUpper); assert(newLower == lower[iColumn2]); } else { COIN_DETAIL_PRINT(printf("SKipping\n")); } - } else if (iColumn1 >= 0 && iColumn1 != iColumn2 && (!inBetween || true) && zeroOne1 && zeroOne2 && false) { + } else if (iColumn1 >= 0 && iColumn1 != iColumn2 && + (!inBetween || true) && zeroOne1 && zeroOne2 && + false) { #ifndef JJF_ONE if (true) { // add in bounds newLower = bounds1[0]; newUpper = bounds1[1]; - COIN_DETAIL_PRINT(printf("setting bounds of %g and %g (column %d) on other branch for column %d\n", - newLower, newUpper, iColumn1, iColumn2)); - int infeasible = objectI->applyExtraBounds(iColumn1, newLower, newUpper, objectI->way()); + COIN_DETAIL_PRINT( + printf("setting bounds of %g and %g (column %d) on " + "other branch for column %d\n", + newLower, newUpper, iColumn1, iColumn2)); + int infeasible = objectI->applyExtraBounds( + iColumn1, newLower, newUpper, objectI->way()); if (infeasible) { COIN_DETAIL_PRINT(printf("infeasa!\n")); // get rid of node as far as branching @@ -17391,40 +17832,51 @@ int CbcModel::doOneNode(CbcModel *baseModel, CbcNode *&node, CbcNode *&newNode) } #endif } - //break; + // break; } else { inBetween = true; } } else { // must have been up branch const double *bounds = objectI->upBounds(); - if (djValue < -1.0e-3 || solution[iColumn2] > lower[iColumn2] + 1.0e-5) { + if (djValue < -1.0e-3 || + solution[iColumn2] > lower[iColumn2] + 1.0e-5) { if (canDelete) { - //nRedundantUp++; + // nRedundantUp++; #ifndef JJF_ONE - COIN_DETAIL_PRINT(printf("%d redundant branch up with bounds %g, %g current lower %g solution %g dj %g\n", - iColumn2, bounds[0], bounds[1], lower[iColumn2], solution[iColumn2], djValue)); -#endif - if (bounds[0] == bounds[1] || zeroOne2 || (bounds[1] == upper[iColumn2] && false)) { + COIN_DETAIL_PRINT( + printf("%d redundant branch up with bounds %g, %g " + "current lower %g solution %g dj %g\n", + iColumn2, bounds[0], bounds[1], + lower[iColumn2], solution[iColumn2], djValue)); +#endif + if (bounds[0] == bounds[1] || zeroOne2 || + (bounds[1] == upper[iColumn2] && false)) { { // get rid of node as far as branching nodeLook->setObjectiveValue(0.5 * COIN_DBL_MAX); objectI->deactivate(); } - previousBounds(node, nodeInfo, iColumn2, newLower, newUpper, 1); + previousBounds(node, nodeInfo, iColumn2, newLower, + newUpper, 1); solver_->setColLower(iColumn2, newLower); assert(newUpper == upper[iColumn2]); } else { COIN_DETAIL_PRINT(printf("SKipping\n")); } - } else if (iColumn1 >= 0 && iColumn1 != iColumn2 && (!inBetween || true) && zeroOne1 && zeroOne2 && false) { + } else if (iColumn1 >= 0 && iColumn1 != iColumn2 && + (!inBetween || true) && zeroOne1 && zeroOne2 && + false) { #ifndef JJF_ONE // add in bounds newLower = bounds1[0]; newUpper = bounds1[1]; - COIN_DETAIL_PRINT(printf("setting bounds of %g and %g (column %d) on other branch for column %d\n", - newLower, newUpper, iColumn1, iColumn2)); - int infeasible = objectI->applyExtraBounds(iColumn1, newLower, newUpper, objectI->way()); + COIN_DETAIL_PRINT( + printf("setting bounds of %g and %g (column %d) on " + "other branch for column %d\n", + newLower, newUpper, iColumn1, iColumn2)); + int infeasible = objectI->applyExtraBounds( + iColumn1, newLower, newUpper, objectI->way()); if (infeasible) { COIN_DETAIL_PRINT(printf("infeasb!\n")); // get rid of node as far as branching @@ -17500,14 +17952,16 @@ int CbcModel::doOneNode(CbcModel *baseModel, CbcNode *&node, CbcNode *&newNode) checkingNode = true; OsiSolverBranch *branches = NULL; // point to useful information - anyAction = chooseBranch(newNode, numberPassesLeft, node, cuts, resolved, - lastws, lowerBefore, upperBefore, branches); + anyAction = + chooseBranch(newNode, numberPassesLeft, node, cuts, resolved, + lastws, lowerBefore, upperBefore, branches); } /* - If we end up infeasible, we can delete the new node immediately. Since this - node won't be needing the cuts we collected, decrement the reference counts. - If we are feasible, then we'll be placing this node into the live set, so - increment the reference count in the current (parent) nodeInfo. + If we end up infeasible, we can delete the new node immediately. + Since this node won't be needing the cuts we collected, decrement the + reference counts. If we are feasible, then we'll be placing this node + into the live set, so increment the reference count in the current + (parent) nodeInfo. */ lockThread(); if (anyAction == -2) { @@ -17523,7 +17977,7 @@ int CbcModel::doOneNode(CbcModel *baseModel, CbcNode *&node, CbcNode *&newNode) delete newNode; newNode = NULL; } else { - //assert (newNode->active()); + // assert (newNode->active()); newNode->setActive(false); } // say strong doing well @@ -17576,7 +18030,8 @@ int CbcModel::doOneNode(CbcModel *baseModel, CbcNode *&node, CbcNode *&newNode) assert(statistics_[numberNodes2_ - 1]); assert(statistics_[numberNodes2_ - 1]->node() == numberNodes2_ - 1); if (newNode && newNode->active()) - statistics_[numberNodes2_ - 1]->updateInfeasibility(newNode->numberUnsatisfied()); + statistics_[numberNodes2_ - 1]->updateInfeasibility( + newNode->numberUnsatisfied()); else statistics_[numberNodes2_ - 1]->sayInfeasible(); } @@ -17586,7 +18041,7 @@ int CbcModel::doOneNode(CbcModel *baseModel, CbcNode *&node, CbcNode *&newNode) if (numberUpdateItems_) { for (i = 0; i < numberUpdateItems_; i++) { CbcObjectUpdateData *update = updateItems_ + i; - CbcObject *object = dynamic_cast< CbcObject * >(update->object_); + CbcObject *object = dynamic_cast(update->object_); #ifndef NDEBUG bool found = false; for (int j = 0; j < numberObjects_; j++) { @@ -17607,18 +18062,21 @@ int CbcModel::doOneNode(CbcModel *baseModel, CbcNode *&node, CbcNode *&newNode) if (newNode && newNode->active()) { if (newNode->branchingObject() == NULL) { const double *solution = solver_->getColSolution(); - CbcEventHandler::CbcAction action = dealWithEventHandler(CbcEventHandler::beforeSolution1, - getSolverObjValue(), solution); - if (action == CbcEventHandler::addCuts || solverCharacteristics_->solverType() == 4) { + CbcEventHandler::CbcAction action = dealWithEventHandler( + CbcEventHandler::beforeSolution1, getSolverObjValue(), solution); + if (action == CbcEventHandler::addCuts || + solverCharacteristics_->solverType() == 4) { // need to check if any cuts would do anything OsiCuts theseCuts; // reset probing info - //if (probingInfo_) - //probingInfo_->initializeFixing(solver_); + // if (probingInfo_) + // probingInfo_->initializeFixing(solver_); for (int i = 0; i < numberCutGenerators_; i++) { bool generate = generator_[i]->normal(); - // skip if not optimal and should be (maybe a cut generator has fixed variables) - if (generator_[i]->needsOptimalBasis() && !solver_->basisIsAvailable()) + // skip if not optimal and should be (maybe a cut generator has + // fixed variables) + if (generator_[i]->needsOptimalBasis() && + !solver_->basisIsAvailable()) generate = false; if (!generator_[i]->mustCallAgain()) generate = false; // only special cuts @@ -17639,16 +18097,16 @@ int CbcModel::doOneNode(CbcModel *baseModel, CbcNode *&node, CbcNode *&newNode) } if (newNode->branchingObject()) { handler_->message(CBC_BRANCH, messages_) - << numberNodes_ << newNode->objectiveValue() - << newNode->numberUnsatisfied() << newNode->depth() - << CoinMessageEol; + << numberNodes_ << newNode->objectiveValue() + << newNode->numberUnsatisfied() << newNode->depth() + << CoinMessageEol; // Increment cut counts (taking off current) int numberLeft = newNode->numberBranches(); for (i = 0; i < currentNumberCuts_; i++) { if (addedCuts_[i]) { #ifdef CHECK_CUT_COUNTS printf("Count on cut %x increased by %d\n", addedCuts_[i], - numberLeft - 1); + numberLeft - 1); #endif addedCuts_[i]->increment(numberLeft - 1); } @@ -17680,23 +18138,23 @@ int CbcModel::doOneNode(CbcModel *baseModel, CbcNode *&node, CbcNode *&newNode) } else { lastHeuristic_ = heuristic_[found]; #ifdef HEURISTIC_INFORM - printf("HEUR %s where %d D\n", - lastHeuristic_->heuristicName(), whereFrom); + printf("HEUR %s where %d D\n", lastHeuristic_->heuristicName(), + whereFrom); #endif setBestSolution(CBC_ROUNDING, heurValue, newSolution); foundSolution = 1; whereFrom |= 8; // say solution found } } else if (ifSol < 0) { // just returning an estimate - estValue = heurValue; //CoinMin(heurValue, estValue) ; + estValue = heurValue; // CoinMin(heurValue, estValue) ; heurValue = saveValue; } } if (found >= 0 && parallelMode() > 0) { lastHeuristic_ = heuristic_[found]; #if CBC_USEFUL_PRINTING > 1 - printf("HEUR %s where %d D\n", - lastHeuristic_->heuristicName(), whereFrom); + printf("HEUR %s where %d D\n", lastHeuristic_->heuristicName(), + whereFrom); #endif setBestSolution(CBC_ROUNDING, heurValue, newSolution); foundSolution = 1; @@ -17712,7 +18170,8 @@ int CbcModel::doOneNode(CbcModel *baseModel, CbcNode *&node, CbcNode *&newNode) maximumStatistics_ = 2 * maximumStatistics_; CbcStatistics **temp = new CbcStatistics *[maximumStatistics_]; memset(temp, 0, maximumStatistics_ * sizeof(CbcStatistics *)); - memcpy(temp, statistics_, numberNodes2_ * sizeof(CbcStatistics *)); + memcpy(temp, statistics_, + numberNodes2_ * sizeof(CbcStatistics *)); delete[] statistics_; statistics_ = temp; } @@ -17724,13 +18183,15 @@ int CbcModel::doOneNode(CbcModel *baseModel, CbcNode *&node, CbcNode *&newNode) printf("Node %x pushed on tree c\n", newNode); #endif } else { - if (solverCharacteristics_ && //we may be in a non standard bab - solverCharacteristics_->solutionAddsCuts() // we are in some kind of OA based bab. + if (solverCharacteristics_ && // we may be in a non standard bab + solverCharacteristics_ + ->solutionAddsCuts() // we are in some kind of OA based bab. ) { std::cerr << "You should never get here" << std::endl; - throw CoinError("Nodes should not be fathomed on integer infeasibility in this setting", - "branchAndBound", "CbcModel"); + throw CoinError("Nodes should not be fathomed on integer " + "infeasibility in this setting", + "branchAndBound", "CbcModel"); } for (i = 0; i < currentNumberCuts_; i++) { if (addedCuts_[i]) { @@ -17742,16 +18203,17 @@ int CbcModel::doOneNode(CbcModel *baseModel, CbcNode *&node, CbcNode *&newNode) } double objectiveValue = newNode->objectiveValue(); lastHeuristic_ = NULL; - // Just possible solver did not know about a solution from another thread! + // Just possible solver did not know about a solution from another + // thread! if (objectiveValue < getCutoff()) { incrementUsed(solver_->getColSolution()); setBestSolution(CBC_SOLUTION, objectiveValue, - solver_->getColSolution()); + solver_->getColSolution()); // Check if was found if (bestObjective_ < getCutoff()) foundSolution = 1; } - //assert(nodeInfo->numberPointingToThis() <= 2) ; + // assert(nodeInfo->numberPointingToThis() <= 2) ; if (parallelMode() >= 0) { // avoid accidental pruning, if newNode was final branch arm node->nodeInfo()->increment(); @@ -17784,12 +18246,12 @@ int CbcModel::doOneNode(CbcModel *baseModel, CbcNode *&node, CbcNode *&newNode) statistics_[numberNodes2_] = new CbcStatistics(node, this); } numberNodes2_++; - //nodeOnTree=true; // back on tree - //deleteNode = false ; + // nodeOnTree=true; // back on tree + // deleteNode = false ; #ifdef CHECK_NODE printf("Node %x pushed back on tree - %d left, %d count\n", node, - node->nodeInfo()->numberBranchesLeft(), - node->nodeInfo()->numberPointingToThis()); + node->nodeInfo()->numberBranchesLeft(), + node->nodeInfo()->numberPointingToThis()); #endif if (parallelMode() > 0) { assert(node->nodeInfo()); @@ -17797,8 +18259,8 @@ int CbcModel::doOneNode(CbcModel *baseModel, CbcNode *&node, CbcNode *&newNode) } } else { /* - This node has been completely expanded and can be removed from the live - set. + This node has been completely expanded and can be removed from the + live set. */ if (parallelMode() > 0) { assert(masterThread_); @@ -17819,12 +18281,13 @@ int CbcModel::doOneNode(CbcModel *baseModel, CbcNode *&node, CbcNode *&newNode) unlockThread(); } else { // add cuts found to be infeasible (on bound)! - COIN_DETAIL_PRINT(printf("found to be infeas! - branches left %d - cutoff %g\n", node->nodeInfo()->numberBranchesLeft(), - getCutoff())); + COIN_DETAIL_PRINT( + printf("found to be infeas! - branches left %d - cutoff %g\n", + node->nodeInfo()->numberBranchesLeft(), getCutoff())); #ifdef COIN_DETAIL node->print(); #endif - //abort(); + // abort(); assert(node->nodeInfo()); if (parallelMode() >= 0) { if (!node->nodeInfo()->numberBranchesLeft()) @@ -17838,11 +18301,11 @@ int CbcModel::doOneNode(CbcModel *baseModel, CbcNode *&node, CbcNode *&newNode) /* Delete cuts to get back to the original system. - I'm thinking this is redundant --- the call to addCuts that conditions entry - to this code block also performs this action. + I'm thinking this is redundant --- the call to addCuts that conditions + entry to this code block also performs this action. */ #ifndef JJF_ONE - //if (numberThreads_) + // if (numberThreads_) { int numberToDelete = getNumRows() - numberRowsAtContinuous_; if (numberToDelete) { @@ -17869,7 +18332,8 @@ int CbcModel::doOneNode(CbcModel *baseModel, CbcNode *&node, CbcNode *&newNode) baseModel->usedInSolution_[i] += usedInSolution_[i]; usedInSolution_[i] = 0; } - if (bestObjective_ < baseModel->bestObjective_ && bestObjective_ < baseModel->getCutoff()) { + if (bestObjective_ < baseModel->bestObjective_ && + bestObjective_ < baseModel->getCutoff()) { baseModel->bestObjective_ = bestObjective_; int numberColumns = solver_->getNumCols(); if (!baseModel->bestSolution_) @@ -17877,11 +18341,8 @@ int CbcModel::doOneNode(CbcModel *baseModel, CbcNode *&node, CbcNode *&newNode) CoinCopyN(bestSolution_, numberColumns, baseModel->bestSolution_); baseModel->setCutoff(getCutoff()); baseModel->handler_->message(CBC_ROUNDING, messages_) - << bestObjective_ - << "heuristic" - << baseModel->numberIterations_ - << baseModel->numberNodes_ << getCurrentSeconds() - << CoinMessageEol; + << bestObjective_ << "heuristic" << baseModel->numberIterations_ + << baseModel->numberNodes_ << getCurrentSeconds() << CoinMessageEol; } baseModel->numberSolutions_++; unlockThread(); @@ -17890,11 +18351,11 @@ int CbcModel::doOneNode(CbcModel *baseModel, CbcNode *&node, CbcNode *&newNode) return foundSolution; } // Adds an update information object -void CbcModel::addUpdateInformation(const CbcObjectUpdateData &data) -{ +void CbcModel::addUpdateInformation(const CbcObjectUpdateData &data) { if (numberUpdateItems_ == maximumNumberUpdateItems_) { maximumNumberUpdateItems_ += 10; - CbcObjectUpdateData *temp = new CbcObjectUpdateData[maximumNumberUpdateItems_]; + CbcObjectUpdateData *temp = + new CbcObjectUpdateData[maximumNumberUpdateItems_]; for (int i = 0; i < maximumNumberUpdateItems_ - 10; i++) temp[i] = updateItems_[i]; delete[] updateItems_; @@ -17902,10 +18363,10 @@ void CbcModel::addUpdateInformation(const CbcObjectUpdateData &data) } updateItems_[numberUpdateItems_++] = data; } -// Returns bounds just before where - initially original bounds - also sets bounds +// Returns bounds just before where - initially original bounds - also sets +// bounds void CbcModel::previousBounds(CbcNode *node, CbcNodeInfo *where, int iColumn, - double &lower, double &upper, int force) -{ + double &lower, double &upper, int force) { int i; int nNode = 0; CbcNodeInfo *nodeInfo = node->nodeInfo(); @@ -17915,7 +18376,7 @@ void CbcModel::previousBounds(CbcNode *node, CbcNodeInfo *where, int iColumn, Accumulate the path from node to the root in walkback_ */ while (nodeInfo) { - //printf("nNode = %d, nodeInfo = %x\n",nNode,nodeInfo); + // printf("nNode = %d, nodeInfo = %x\n",nNode,nodeInfo); walkback_[nNode++] = nodeInfo; nodeInfo = nodeInfo->parent(); if (nNode == maximumDepth_) { @@ -17935,10 +18396,12 @@ void CbcModel::previousBounds(CbcNode *node, CbcNodeInfo *where, int iColumn, CbcNode *nodeLook = walkback_[nNode]->mutableOwner(); if (nodeLook) { OsiBranchingObject *obj = nodeLook->modifiableBranchingObject(); - CbcIntegerBranchingObject *objectI = dynamic_cast< CbcIntegerBranchingObject * >(obj); - //const OsiObject * object2 = obj->orig + CbcIntegerBranchingObject *objectI = + dynamic_cast(obj); + // const OsiObject * object2 = obj->orig #ifndef NDEBUG - const CbcSimpleInteger *object2 = dynamic_cast< const CbcSimpleInteger * >(objectI->object()); + const CbcSimpleInteger *object2 = + dynamic_cast(objectI->object()); assert(object2); assert(iColumn == object2->columnNumber()); #endif @@ -17955,9 +18418,11 @@ void CbcModel::previousBounds(CbcNode *node, CbcNodeInfo *where, int iColumn, CbcNode *nodeLook = walkback_[nNode]->mutableOwner(); if (nodeLook) { const OsiBranchingObject *obj = nodeLook->branchingObject(); - const CbcIntegerBranchingObject *objectI = dynamic_cast< const CbcIntegerBranchingObject * >(obj); - //const OsiObject * object2 = obj->orig - const CbcSimpleInteger *object2 = dynamic_cast< const CbcSimpleInteger * >(objectI->object()); + const CbcIntegerBranchingObject *objectI = + dynamic_cast(obj); + // const OsiObject * object2 = obj->orig + const CbcSimpleInteger *object2 = + dynamic_cast(objectI->object()); assert(object2); int iColumn2 = object2->columnNumber(); assert(iColumn != iColumn2); @@ -17972,11 +18437,9 @@ void CbcModel::previousBounds(CbcNode *node, CbcNodeInfo *where, int iColumn, User must allocate arrays before call */ void CbcModel::fillPseudoCosts(double *downCosts, double *upCosts, - int *priority, - int *numberDown, int *numberUp, - int *numberDownInfeasible, - int *numberUpInfeasible) const -{ + int *priority, int *numberDown, int *numberUp, + int *numberDownInfeasible, + int *numberUpInfeasible) const { CoinFillN(downCosts, numberIntegers_, 1.0); CoinFillN(upCosts, numberIntegers_, 1.0); if (priority) { @@ -18001,11 +18464,13 @@ void CbcModel::fillPseudoCosts(double *downCosts, double *upCosts, int numberNot = 0; #endif for (i = 0; i < numberObjects_; i++) { - CbcSimpleIntegerDynamicPseudoCost *obj = dynamic_cast< CbcSimpleIntegerDynamicPseudoCost * >(object_[i]); + CbcSimpleIntegerDynamicPseudoCost *obj = + dynamic_cast(object_[i]); if (!obj) continue; #if CBC_USEFUL_PRINTING > 1 - if (obj->numberTimesDown() < numberBeforeTrust_ || obj->numberTimesUp() < numberBeforeTrust_) + if (obj->numberTimesDown() < numberBeforeTrust_ || + obj->numberTimesUp() < numberBeforeTrust_) numberNot++; #endif int iColumn = obj->columnNumber(); @@ -18026,21 +18491,20 @@ void CbcModel::fillPseudoCosts(double *downCosts, double *upCosts, } #if CBC_USEFUL_PRINTING > 5 if (priority) - printf("Before fathom %d not trusted out of %d\n", - numberNot, numberIntegers_); + printf("Before fathom %d not trusted out of %d\n", numberNot, + numberIntegers_); #endif delete[] back; } // Redo walkback arrays -void CbcModel::redoWalkBack() -{ +void CbcModel::redoWalkBack() { int nNode = maximumDepth_; maximumDepth_ *= 2; CbcNodeInfo **temp = new CbcNodeInfo *[maximumDepth_]; CbcNodeInfo **temp2 = new CbcNodeInfo *[maximumDepth_]; - memset(temp2,0,maximumDepth_*sizeof(CbcNodeInfo*)); + memset(temp2, 0, maximumDepth_ * sizeof(CbcNodeInfo *)); int *temp3 = new int[maximumDepth_]; - memset(temp3,0,maximumDepth_*sizeof(int)); + memset(temp3, 0, maximumDepth_ * sizeof(int)); for (int i = 0; i < nNode; i++) { temp[i] = walkback_[i]; temp2[i] = lastNodeInfo_[i]; @@ -18059,8 +18523,7 @@ void CbcModel::redoWalkBack() if 2 then says if cuts allowed anywhere apart from root if 3 then gives smallest valid depth >shallow */ -bool CbcModel::doCutsNow(int allowForTopOfTree) const -{ +bool CbcModel::doCutsNow(int allowForTopOfTree) const { int whenCutsUse = whenCuts_; int alwaysReturnAt10 = whenCutsUse % 100000; if (whenCutsUse > 0 && alwaysReturnAt10) { @@ -18068,26 +18531,27 @@ bool CbcModel::doCutsNow(int allowForTopOfTree) const if (currentDepth_ > 10) return false; } - //if (currentDepth_>10) - //return false; + // if (currentDepth_>10) + // return false; #define TRY_IDEA1 2 int size = continuousSolver_->getNumRows() + continuousSolver_->getNumCols(); - if (true && (whenCutsUse < 0 || (size <= 500 - 500 * TRY_IDEA1 && allowForTopOfTree != 3))) { + if (true && (whenCutsUse < 0 || + (size <= 500 - 500 * TRY_IDEA1 && allowForTopOfTree != 3))) { int whenCuts = (size <= 500) ? -1 : 1; - //whenCuts = (size<=500) ? 1 :1; + // whenCuts = (size<=500) ? 1 :1; if (parentModel_) whenCuts = 1; - //int nodeDepth = currentDepth_-1; + // int nodeDepth = currentDepth_-1; bool doCuts2 = !(currentDepth_ > 11 && (currentDepth_ & 1) == whenCuts); if (fastNodeDepth_ > 0 && currentDepth_ > 10) doCuts2 = false; - //printf("when %d node %d depth %d size %d doing cuts %s\n",whenCutsUse, + // printf("when %d node %d depth %d size %d doing cuts %s\n",whenCutsUse, // numberNodes_,currentDepth_,size,doCuts2 ? "yes" : "no"); return doCuts2; } - //if (!parentModel_&¤tDepth_==7) - //printf("q\n"); + // if (!parentModel_&¤tDepth_==7) + // printf("q\n"); int top = whenCutsUse / 1000000; int shallow = top ? (top - 1) : 9; int when = whenCutsUse - 1000000 * top; @@ -18113,19 +18577,20 @@ bool CbcModel::doCutsNow(int allowForTopOfTree) const doCuts = (currentDepth_ == 10); #endif } - //if (!doCuts&¤tDepth_&&!parentModel_) - //printf("zzz\n"); + // if (!doCuts&¤tDepth_&&!parentModel_) + // printf("zzz\n"); return doCuts; } // See if can stop on gap -bool CbcModel::canStopOnGap() const -{ +bool CbcModel::canStopOnGap() const { bool returnCode = false; if (bestObjective_ < 1.0e50) { - double testGap = CoinMax(dblParam_[CbcAllowableGap], - CoinMax(fabs(bestObjective_), fabs(bestPossibleObjective_)) - * dblParam_[CbcAllowableFractionGap]); - returnCode = (bestObjective_ - bestPossibleObjective_ < testGap && getCutoffIncrement() >= 0.0); + double testGap = + CoinMax(dblParam_[CbcAllowableGap], + CoinMax(fabs(bestObjective_), fabs(bestPossibleObjective_)) * + dblParam_[CbcAllowableFractionGap]); + returnCode = (bestObjective_ - bestPossibleObjective_ < testGap && + getCutoffIncrement() >= 0.0); } #if 0 if (returnCode) { @@ -18140,14 +18605,14 @@ bool CbcModel::canStopOnGap() const return returnCode; } // Adjust heuristics based on model -void CbcModel::adjustHeuristics() -{ +void CbcModel::adjustHeuristics() { int numberRows = solver_->getNumRows(); int numberColumns = solver_->getNumCols(); int nTree = CoinMax(10000, 2 * numberRows + numberColumns); int nRoot = CoinMax(40000, 8 * numberRows + 4 * numberColumns); for (int i = 0; i < numberHeuristics_; i++) { - CbcHeuristicDive *heuristic = dynamic_cast< CbcHeuristicDive * >(heuristic_[i]); + CbcHeuristicDive *heuristic = + dynamic_cast(heuristic_[i]); if (heuristic && heuristic->maxSimplexIterations() != COIN_INT_MAX) { heuristic->setMaxSimplexIterations(nTree); heuristic->setMaxSimplexIterationsAtRoot(nRoot); @@ -18155,22 +18620,20 @@ void CbcModel::adjustHeuristics() } } // Number of saved solutions (including best) -int CbcModel::numberSavedSolutions() const -{ +int CbcModel::numberSavedSolutions() const { if (!bestSolution_) return 0; else return numberSavedSolutions_ + 1; } // Set maximum number of extra saved solutions -void CbcModel::setMaximumSavedSolutions(int value) -{ +void CbcModel::setMaximumSavedSolutions(int value) { if (value < maximumSavedSolutions_) { for (int i = value; i < maximumSavedSolutions_; i++) delete[] savedSolutions_[i]; maximumSavedSolutions_ = value; - numberSavedSolutions_ = CoinMin(numberSavedSolutions_, - maximumSavedSolutions_); + numberSavedSolutions_ = + CoinMin(numberSavedSolutions_, maximumSavedSolutions_); if (!maximumSavedSolutions_) delete[] savedSolutions_; } else if (value > maximumSavedSolutions_) { @@ -18186,36 +18649,32 @@ void CbcModel::setMaximumSavedSolutions(int value) } } // Return a saved solution objective (0==best) - COIN_DBL_MAX if off end -double -CbcModel::savedSolutionObjective(int which) const -{ +double CbcModel::savedSolutionObjective(int which) const { if (which == 0) { return bestObjective_; } else if (which <= numberSavedSolutions_) { double *sol = savedSolutions_[which - 1]; - assert(static_cast< int >(sol[0]) == solver_->getNumCols()); + assert(static_cast(sol[0]) == solver_->getNumCols()); return sol[1]; } else { return COIN_DBL_MAX; } } // Return a saved solution (0==best) - NULL if off end -const double * -CbcModel::savedSolution(int which) const -{ +const double *CbcModel::savedSolution(int which) const { if (which == 0) { return bestSolution_; } else if (which <= numberSavedSolutions_) { double *sol = savedSolutions_[which - 1]; - assert(static_cast< int >(sol[0]) == solver_->getNumCols()); + assert(static_cast(sol[0]) == solver_->getNumCols()); return sol + 2; } else { return NULL; } } // Save a solution -void CbcModel::saveExtraSolution(const double *solution, double objectiveValue) -{ +void CbcModel::saveExtraSolution(const double *solution, + double objectiveValue) { double *save = NULL; if (maximumSavedSolutions_) { if (!savedSolutions_) { @@ -18227,7 +18686,7 @@ void CbcModel::saveExtraSolution(const double *solution, double objectiveValue) int k; for (k = numberSavedSolutions_ - 1; k >= 0; k--) { double *sol = savedSolutions_[k]; - assert(static_cast< int >(sol[0]) == n); + assert(static_cast(sol[0]) == n); if (objectiveValue > sol[1]) break; } @@ -18249,7 +18708,7 @@ void CbcModel::saveExtraSolution(const double *solution, double objectiveValue) bool allInt = (solver_->getNumIntegers() == solver_->getNumCols()); double *x = save + 2; if (roundIntVars_ || allInt) { - for ( int i=0 ; (iisInteger(i)) x[i] = floor(x[i] + 0.5); } @@ -18257,8 +18716,7 @@ void CbcModel::saveExtraSolution(const double *solution, double objectiveValue) } } // Save a solution to best and move current to saved -void CbcModel::saveBestSolution(const double *solution, double objectiveValue) -{ +void CbcModel::saveBestSolution(const double *solution, double objectiveValue) { int n = solver_->getNumCols(); if (bestSolution_) saveExtraSolution(bestSolution_, bestObjective_); @@ -18268,11 +18726,11 @@ void CbcModel::saveBestSolution(const double *solution, double objectiveValue) memcpy(bestSolution_, solution, n * sizeof(double)); bool allInt = (solver_->getNumIntegers() == solver_->getNumCols()); if (roundIntVars_ || allInt) { - for ( int i=0 ; (iisInteger(i)) bestSolution_[i] = floor(bestSolution_[i] + 0.5); } - if ((moreSpecialOptions2_&65536)!=0) { + if ((moreSpecialOptions2_ & 65536) != 0) { // save a copy of solver with constraints delete atSolutionSolver_; atSolutionSolver_ = solver_->clone(); @@ -18284,8 +18742,7 @@ void CbcModel::saveBestSolution(const double *solution, double objectiveValue) } } // Delete best and saved solutions -void CbcModel::deleteSolutions() -{ +void CbcModel::deleteSolutions() { delete[] bestSolution_; bestSolution_ = NULL; for (int i = 0; i < maximumSavedSolutions_; i++) { @@ -18295,8 +18752,7 @@ void CbcModel::deleteSolutions() numberSavedSolutions_ = 0; } // Delete a saved solution and move others up -void CbcModel::deleteSavedSolution(int which) -{ +void CbcModel::deleteSavedSolution(int which) { if (which > 0 && which <= numberSavedSolutions_) { delete[] savedSolutions_[which - 1]; // move up @@ -18308,25 +18764,28 @@ void CbcModel::deleteSavedSolution(int which) } } #ifdef CBC_HAS_CLP -void CbcModel::goToDantzig(int numberNodes, ClpDualRowPivot *&savePivotMethod) -{ +void CbcModel::goToDantzig(int numberNodes, ClpDualRowPivot *&savePivotMethod) { // Possible change of pivot method if (!savePivotMethod && !parentModel_) { - OsiClpSolverInterface *clpSolver - = dynamic_cast< OsiClpSolverInterface * >(solver_); - if (clpSolver && numberNodes_ >= numberNodes && numberNodes_ < 2 * numberNodes && clpSolver->getNumRows() < 10000) { + OsiClpSolverInterface *clpSolver = + dynamic_cast(solver_); + if (clpSolver && numberNodes_ >= numberNodes && + numberNodes_ < 2 * numberNodes && clpSolver->getNumRows() < 10000) { if (numberIterations_ < (numberSolves_ + numberNodes_) * 10) { - //if (numberIterations_getModelPtr(); ClpDualRowPivot *pivotMethod = simplex->dualRowPivot(); - ClpDualRowDantzig *pivot = dynamic_cast< ClpDualRowDantzig * >(pivotMethod); + ClpDualRowDantzig *pivot = + dynamic_cast(pivotMethod); if (!pivot) { + if ((simplex->moreSpecialOptions()&2048)!=0) + return; savePivotMethod = pivotMethod->clone(true); ClpDualRowDantzig dantzig; simplex->setDualRowPivotAlgorithm(dantzig); #ifdef COIN_DEVELOP printf("%d node, %d iterations ->Dantzig\n", numberNodes_, - numberIterations_); + numberIterations_); #endif #ifdef CBC_THREAD if (master_) @@ -18338,8 +18797,7 @@ void CbcModel::goToDantzig(int numberNodes, ClpDualRowPivot *&savePivotMethod) } } #else -CbcModel::goToDantzig(int numberNodes, ClpDualRowPivot *&savePivotMethod) -{ +CbcModel::goToDantzig(int numberNodes, ClpDualRowPivot *&savePivotMethod) { printf("Need Clp to go to Dantzig\n"); abort(); } @@ -18350,12 +18808,10 @@ CbcModel::goToDantzig(int numberNodes, ClpDualRowPivot *&savePivotMethod) I have to work out cleanest way of getting solution to original problem at end. So this is very preliminary. */ -CbcModel * -CbcModel::integerPresolve(bool weak) -{ +CbcModel *CbcModel::integerPresolve(bool weak) { status_ = 0; // solve LP - //solver_->writeMps("bad"); + // solver_->writeMps("bad"); bool feasible = (resolve(NULL, 3) != 0); CbcModel *newModel = NULL; @@ -18368,14 +18824,14 @@ CbcModel::integerPresolve(bool weak) feasible = newModel->integerPresolveThisModel(solver_, weak); } if (!feasible) { - handler_->message(CBC_INFEAS, messages_) - << CoinMessageEol; + handler_->message(CBC_INFEAS, messages_) << CoinMessageEol; status_ = 0; secondaryStatus_ = 1; delete newModel; return NULL; } else { - newModel->synchronizeModel(); // make sure everything that needs solver has it + newModel + ->synchronizeModel(); // make sure everything that needs solver has it return newModel; } } @@ -18383,8 +18839,7 @@ CbcModel::integerPresolve(bool weak) Do Integer Presolve - destroying current model */ bool CbcModel::integerPresolveThisModel(OsiSolverInterface *originalSolver, - bool weak) -{ + bool weak) { printf("DEPRECATED\n"); status_ = 0; // solve LP @@ -18396,9 +18851,8 @@ bool CbcModel::integerPresolveThisModel(OsiSolverInterface *originalSolver, double cutoff = getCutoff(); double direction = solver_->getObjSense(); if (cutoff < 1.0e20 && direction < 0.0) - messageHandler()->message(CBC_CUTOFF_WARNING1, - messages()) - << cutoff << -cutoff << CoinMessageEol; + messageHandler()->message(CBC_CUTOFF_WARNING1, messages()) + << cutoff << -cutoff << CoinMessageEol; if (cutoff > bestObjective_) cutoff = bestObjective_; setCutoff(cutoff); @@ -18408,14 +18862,16 @@ bool CbcModel::integerPresolveThisModel(OsiSolverInterface *originalSolver, currentPassNumber_ = 0; synchronizeModel(); // make sure everything that needs solver has it if (!solverCharacteristics_) { - OsiBabSolver *solverCharacteristics = dynamic_cast< OsiBabSolver * >(solver_->getAuxiliaryInfo()); + OsiBabSolver *solverCharacteristics = + dynamic_cast(solver_->getAuxiliaryInfo()); if (solverCharacteristics) { solverCharacteristics_ = solverCharacteristics; } else { // replace in solver OsiBabSolver defaultC; solver_->setAuxiliaryInfo(&defaultC); - solverCharacteristics_ = dynamic_cast< OsiBabSolver * >(solver_->getAuxiliaryInfo()); + solverCharacteristics_ = + dynamic_cast(solver_->getAuxiliaryInfo()); } } solverCharacteristics_->setSolver(solver_); @@ -18482,16 +18938,16 @@ bool CbcModel::integerPresolveThisModel(OsiSolverInterface *originalSolver, } if (originalUpper[iColumn] < upper[iColumn]) { #ifdef CBC_DEBUG - printf("Changing upper bound on %d from %g to %g\n", - iColumn, upper[iColumn], originalUpper[iColumn]); + printf("Changing upper bound on %d from %g to %g\n", iColumn, + upper[iColumn], originalUpper[iColumn]); #endif cleanModel->setColUpper(iColumn, originalUpper[iColumn]); numberChanged++; } if (originalLower[iColumn] > lower[iColumn]) { #ifdef CBC_DEBUG - printf("Changing lower bound on %d from %g to %g\n", - iColumn, lower[iColumn], originalLower[iColumn]); + printf("Changing lower bound on %d from %g to %g\n", iColumn, + lower[iColumn], originalLower[iColumn]); #endif cleanModel->setColLower(iColumn, originalLower[iColumn]); numberChanged++; @@ -18510,7 +18966,7 @@ bool CbcModel::integerPresolveThisModel(OsiSolverInterface *originalSolver, if (originalUpper[iColumn] > originalLower[iColumn]) { if (objective[iColumn]) { double value = fabs(objective[iColumn]) * multiplier; - int nearest = static_cast< int >(floor(value + 0.5)); + int nearest = static_cast(floor(value + 0.5)); if (fabs(value - floor(value + 0.5)) > 1.0e-8 || value > 2.1e9) { increment = 0; break; // no good @@ -18528,8 +18984,7 @@ bool CbcModel::integerPresolveThisModel(OsiSolverInterface *originalSolver, value /= multiplier; if (value * 0.999 > dblParam_[CbcCutoffIncrement]) { messageHandler()->message(CBC_INTEGERINCREMENT, messages()) - << value - << CoinMessageEol; + << value << CoinMessageEol; dblParam_[CbcCutoffIncrement] = value * 0.999; } } @@ -18544,14 +18999,15 @@ bool CbcModel::integerPresolveThisModel(OsiSolverInterface *originalSolver, #endif #ifdef CBC_HAS_CLP // do presolve - for now just clp but easy to get osi interface - OsiClpSolverInterface *clpSolver - = dynamic_cast< OsiClpSolverInterface * >(cleanModel); + OsiClpSolverInterface *clpSolver = + dynamic_cast(cleanModel); if (clpSolver) { ClpSimplex *clp = clpSolver->getModelPtr(); - clp->messageHandler()->setLogLevel(cleanModel->messageHandler()->logLevel()); + clp->messageHandler()->setLogLevel( + cleanModel->messageHandler()->logLevel()); ClpPresolve pinfo; - //printf("integerPresolve - temp switch off doubletons\n"); - //pinfo.setPresolveActions(4); + // printf("integerPresolve - temp switch off doubletons\n"); + // pinfo.setPresolveActions(4); ClpSimplex *model2 = pinfo.presolvedModel(*clp, 1.0e-8); if (!model2) { // presolve found to be infeasible @@ -18597,8 +19053,8 @@ bool CbcModel::integerPresolveThisModel(OsiSolverInterface *originalSolver, if (!heuristic_[iHeuristic]->shouldHeurRun(whereFrom)) continue; double saveValue = heuristicValue; - int ifSol = heuristic_[iHeuristic]->solution(heuristicValue, - newSolution); + int ifSol = + heuristic_[iHeuristic]->solution(heuristicValue, newSolution); if (ifSol > 0) { // better solution found heuristic_[iHeuristic]->incrementNumberSolutionsFound(); @@ -18618,11 +19074,10 @@ bool CbcModel::integerPresolveThisModel(OsiSolverInterface *originalSolver, // better solution save lastHeuristic_ = heuristic_[found]; #ifdef HEURISTIC_INFORM - printf("HEUR %s where %d oddE\n", - lastHeuristic_->heuristicName(), whereFrom); + printf("HEUR %s where %d oddE\n", lastHeuristic_->heuristicName(), + whereFrom); #endif - setBestSolution(CBC_ROUNDING, heuristicValue, - newSolution); + setBestSolution(CBC_ROUNDING, heuristicValue, newSolution); // update cutoff cutoff = getCutoff(); } @@ -18645,10 +19100,10 @@ bool CbcModel::integerPresolveThisModel(OsiSolverInterface *originalSolver, lastDepth_ = 0; delete[] lastNodeInfo_; lastNodeInfo_ = new CbcNodeInfo *[maximumDepth_]; - memset(lastNodeInfo_,0,maximumDepth_*sizeof(CbcNodeInfo*)); + memset(lastNodeInfo_, 0, maximumDepth_ * sizeof(CbcNodeInfo *)); delete[] lastNumberCuts_; lastNumberCuts_ = new int[maximumDepth_]; - memset(lastNumberCuts_,0,maximumDepth_*sizeof(int)); + memset(lastNumberCuts_, 0, maximumDepth_ * sizeof(int)); maximumCuts_ = 100; delete[] lastCut_; lastCut_ = new const OsiRowCut *[maximumCuts_]; @@ -18688,7 +19143,7 @@ bool CbcModel::integerPresolveThisModel(OsiSolverInterface *originalSolver, break; } } - //solver_->writeMps("xx"); + // solver_->writeMps("xx"); delete cleanModel; delete[] originalIntegers; numberColumns = getNumCols(); @@ -18711,8 +19166,7 @@ bool CbcModel::integerPresolveThisModel(OsiSolverInterface *originalSolver, return feasible; } // Put back information into original model - after integerpresolve -void CbcModel::originalModel(CbcModel *presolvedModel, bool weak) -{ +void CbcModel::originalModel(CbcModel *presolvedModel, bool weak) { solver_->copyParameters(*(presolvedModel->solver_)); bestObjective_ = presolvedModel->bestObjective_; delete[] bestSolution_; @@ -18720,7 +19174,7 @@ void CbcModel::originalModel(CbcModel *presolvedModel, bool weak) if (presolvedModel->bestSolution_) { int numberColumns = getNumCols(); int numberOtherColumns = presolvedModel->getNumCols(); - //bestSolution_ = new double[numberColumns]; + // bestSolution_ = new double[numberColumns]; // set up map int *back = new int[numberColumns]; int i; @@ -18731,24 +19185,24 @@ void CbcModel::originalModel(CbcModel *presolvedModel, bool weak) int iColumn; // set ones in presolved model to values double *otherSolution = presolvedModel->bestSolution_; - //const double * lower = getColLower(); + // const double * lower = getColLower(); for (i = 0; i < numberIntegers_; i++) { iColumn = integerVariable_[i]; int jColumn = back[iColumn]; - //bestSolution_[iColumn]=lower[iColumn]; + // bestSolution_[iColumn]=lower[iColumn]; if (jColumn >= 0) { double value = floor(otherSolution[jColumn] + 0.5); solver_->setColLower(iColumn, value); solver_->setColUpper(iColumn, value); - //bestSolution_[iColumn]=value; + // bestSolution_[iColumn]=value; } } delete[] back; #ifdef JJF_ZERO // ** looks as if presolve needs more intelligence // do presolve - for now just clp but easy to get osi interface - OsiClpSolverInterface *clpSolver - = dynamic_cast< OsiClpSolverInterface * >(solver_); + OsiClpSolverInterface *clpSolver = + dynamic_cast(solver_); assert(clpSolver); ClpSimplex *clp = clpSolver->getModelPtr(); Presolve pinfo; @@ -18783,7 +19237,7 @@ void CbcModel::originalModel(CbcModel *presolvedModel, bool weak) int numberIntegerInfeasibilities; int numberObjectInfeasibilities; assert(feasibleSolution(numberIntegerInfeasibilities, - numberObjectInfeasibilities)); + numberObjectInfeasibilities)); #endif } } else { @@ -18797,11 +19251,10 @@ void CbcModel::originalModel(CbcModel *presolvedModel, bool weak) secondaryStatus_ = presolvedModel->secondaryStatus_; synchronizeModel(); } -void CbcModel::setOptionalInteger(int index) -{ +void CbcModel::setOptionalInteger(int index) { #ifdef CBC_HAS_CLP - OsiClpSolverInterface *clpSolver - = dynamic_cast< OsiClpSolverInterface * >(solver_); + OsiClpSolverInterface *clpSolver = + dynamic_cast(solver_); if (clpSolver) clpSolver->setOptionalInteger(index); else @@ -18810,28 +19263,26 @@ void CbcModel::setOptionalInteger(int index) } bool CbcModel::stoppingCriterionReached() const { - return ( - numberNodes_ >= intParam_[CbcMaxNumNode] || - numberSolutions_ >= intParam_[CbcMaxNumSol] || - stoppedOnGap_ || - eventHappened_ || - maximumSecondsReached() || - (numberSolutions_ && (numberNodes_ - lastNodeImprovingFeasSol_ >= intParam_[CbcMaxNodesNotImprovingFeasSol])) || - (!(maximumNumberIterations_ < 0 || numberIterations_ < maximumNumberIterations_)) - ); + return (numberNodes_ >= intParam_[CbcMaxNumNode] || + numberSolutions_ >= intParam_[CbcMaxNumSol] || stoppedOnGap_ || + eventHappened_ || maximumSecondsReached() || + (numberSolutions_ && (numberNodes_ - lastNodeImprovingFeasSol_ >= + intParam_[CbcMaxNodesNotImproving])) || + (!(maximumNumberIterations_ < 0 || + numberIterations_ < maximumNumberIterations_))); } // Return true if maximum time reached -bool CbcModel::maximumSecondsReached() const -{ +bool CbcModel::maximumSecondsReached() const { double maxSeconds = getMaximumSeconds(); if (maxSeconds>1.0e10 && - dblParam_[CbcMaximumSecondsNotImprovingFeasSol]>1.0e10) + dblParam_[CbcMaxSecondsNotImproving]>1.0e10) return false; double totalTime = getCurrentSeconds(); bool hitMaxTime = (totalTime >= maxSeconds); if (numberSolutions_ && (!hitMaxTime)) { - hitMaxTime = totalTime - lastTimeImprovingFeasSol_ >= dblParam_[CbcMaximumSecondsNotImprovingFeasSol]; + hitMaxTime = totalTime - lastTimeImprovingFeasSol_ >= + dblParam_[CbcMaxSecondsNotImproving]; } if (parentModel_ && !hitMaxTime) { // In a sub tree @@ -18839,10 +19290,9 @@ bool CbcModel::maximumSecondsReached() const maxSeconds = parentModel_->getMaximumSeconds(); hitMaxTime = (totalTime >= maxSeconds); if (numberSolutions_ && (!hitMaxTime)) { - double maxSecondsNotImprFS = parentModel_->getDblParam(CbcMaximumSecondsNotImprovingFeasSol); - double lastSolutionTime = - CoinMax(lastTimeImprovingFeasSol_,parentModel_->lastTimeImprovingFeasSol()); - hitMaxTime = totalTime - lastSolutionTime >= maxSecondsNotImprFS; + double maxSecondsNotImprFS = + parentModel_->getDblParam(CbcMaxSecondsNotImproving); + hitMaxTime = totalTime - lastTimeImprovingFeasSol_ >= maxSecondsNotImprFS; } } if (hitMaxTime) { @@ -18858,8 +19308,7 @@ bool CbcModel::maximumSecondsReached() const return hitMaxTime; } // Check original model before it gets messed up -void CbcModel::checkModel() -{ +void CbcModel::checkModel() { int iColumn; int numberColumns = getNumCols(); const double *lower = getColLower(); @@ -18882,8 +19331,7 @@ void CbcModel::checkModel() } specialOptions_ |= setFlag; } -static void flipSolver(OsiSolverInterface *solver, double newCutoff) -{ +static void flipSolver(OsiSolverInterface *solver, double newCutoff) { if (solver) { double objValue = solver->getObjValue(); double objectiveOffset; @@ -18891,15 +19339,16 @@ static void flipSolver(OsiSolverInterface *solver, double newCutoff) solver->getDblParam(OsiObjOffset, objectiveOffset); solver->setDblParam(OsiObjOffset, -objectiveOffset); int numberColumns = solver->getNumCols(); - double *array = CoinCopyOfArray(solver->getObjCoefficients(), numberColumns); + double *array = + CoinCopyOfArray(solver->getObjCoefficients(), numberColumns); for (int i = 0; i < numberColumns; i++) array[i] = -array[i]; solver->setObjective(array); delete[] array; solver->setDblParam(OsiDualObjectiveLimit, newCutoff); #ifdef CBC_HAS_CLP - OsiClpSolverInterface *clpSolver - = dynamic_cast< OsiClpSolverInterface * >(solver); + OsiClpSolverInterface *clpSolver = + dynamic_cast(solver); if (clpSolver) { double *dj = clpSolver->getModelPtr()->dualColumnSolution(); for (int i = 0; i < numberColumns; i++) @@ -18921,8 +19370,7 @@ static void flipSolver(OsiSolverInterface *solver, double newCutoff) /* Flip direction of optimization on all models */ -void CbcModel::flipModel() -{ +void CbcModel::flipModel() { if (parentModel_) return; // I think cutoff is always minimization @@ -18942,9 +19390,8 @@ void CbcModel::flipModel() If makeEquality is 1 add slacks to get cliques, if 2 add slacks to get sos (but only if looks plausible) and keep sos info */ -CglPreProcess * -CbcModel::preProcess(int makeEquality, int numberPasses, int tuning) -{ +CglPreProcess *CbcModel::preProcess(int makeEquality, int numberPasses, + int tuning) { CglPreProcess *process = new CglPreProcess(); // Default set of cut generators CglProbing generator1; @@ -18967,7 +19414,7 @@ CbcModel::preProcess(int makeEquality, int numberPasses, int tuning) int i; int numberSOS2 = 0; for (i = 0; i < numberObjects_; i++) { - CbcSOS *objSOS = dynamic_cast< CbcSOS * >(object_[i]); + CbcSOS *objSOS = dynamic_cast(object_[i]); if (objSOS) { int type = objSOS->sosType(); if (type == 2) @@ -18980,7 +19427,7 @@ CbcModel::preProcess(int makeEquality, int numberPasses, int tuning) char *prohibited = new char[numberColumns]; memset(prohibited, 0, numberColumns); for (i = 0; i < numberObjects_; i++) { - CbcSOS *objSOS = dynamic_cast< CbcSOS * >(object_[i]); + CbcSOS *objSOS = dynamic_cast(object_[i]); if (objSOS) { int type = objSOS->sosType(); if (type == 2) { @@ -18998,14 +19445,14 @@ CbcModel::preProcess(int makeEquality, int numberPasses, int tuning) } // Tell solver we are in Branch and Cut solver_->setHintParam(OsiDoInBranchAndCut, true, OsiHintDo); - setPreProcessingMode(solver_,1); - OsiSolverInterface *newSolver = process->preProcessNonDefault(*solver_, makeEquality, - numberPasses, tuning); + setPreProcessingMode(solver_, 1); + OsiSolverInterface *newSolver = process->preProcessNonDefault( + *solver_, makeEquality, numberPasses, tuning); // Tell solver we are not in Branch and Cut solver_->setHintParam(OsiDoInBranchAndCut, false, OsiHintDo); - setPreProcessingMode(solver_,0); + setPreProcessingMode(solver_, 0); if (newSolver) { - setPreProcessingMode(newSolver,0); + setPreProcessingMode(newSolver, 0); int numberOriginalObjects = numberObjects_; OsiSolverInterface *originalSolver = solver_; solver_ = newSolver->clone(); // clone as process owns solver @@ -19040,7 +19487,8 @@ CbcModel::preProcess(int makeEquality, int numberPasses, int tuning) int jColumn = originalColumns[iColumn]; if (temp[jColumn] >= 0) { int iObject = temp[jColumn]; - CbcSimpleInteger *obj = dynamic_cast< CbcSimpleInteger * >(originalObject[iObject]); + CbcSimpleInteger *obj = + dynamic_cast(originalObject[iObject]); if (obj) numberOldIntegers++; else @@ -19053,14 +19501,15 @@ CbcModel::preProcess(int makeEquality, int numberPasses, int tuning) Allocate an array to hold the indices of the integer variables. Make a large enough array for all objects */ - numberObjects_ = numberNewIntegers + numberOldIntegers + numberOldOther + nNonInt; + numberObjects_ = + numberNewIntegers + numberOldIntegers + numberOldOther + nNonInt; object_ = new OsiObject *[numberObjects_]; delete[] integerVariable_; integerVariable_ = new int[numberNewIntegers + numberOldIntegers]; /* - Walk the variables again, filling in the indices and creating objects for - the integer variables. Initially, the objects hold the index and upper & - lower bounds. + Walk the variables again, filling in the indices and creating objects + for the integer variables. Initially, the objects hold the index and + upper & lower bounds. */ numberIntegers_ = 0; int n = originalColumns[numberColumns - 1] + 1; @@ -19074,11 +19523,12 @@ CbcModel::preProcess(int makeEquality, int numberPasses, int tuning) int jColumn = originalColumns[iColumn]; if (temp[jColumn] >= 0) { int iObject = temp[jColumn]; - CbcSimpleInteger *obj = dynamic_cast< CbcSimpleInteger * >(originalObject[iObject]); + CbcSimpleInteger *obj = + dynamic_cast(originalObject[iObject]); if (obj) { object_[numberIntegers_] = originalObject[iObject]->clone(); // redo ids etc - //object_[numberIntegers_]->resetSequenceEtc(numberColumns,originalColumns); + // object_[numberIntegers_]->resetSequenceEtc(numberColumns,originalColumns); object_[numberIntegers_]->resetSequenceEtc(numberColumns, backward); integerVariable_[numberIntegers_++] = iColumn; } @@ -19094,11 +19544,12 @@ CbcModel::preProcess(int makeEquality, int numberPasses, int tuning) int jColumn = originalColumns[iColumn]; if (temp[jColumn] >= 0) { int iObject = temp[jColumn]; - CbcSimpleInteger *obj = dynamic_cast< CbcSimpleInteger * >(originalObject[iObject]); + CbcSimpleInteger *obj = + dynamic_cast(originalObject[iObject]); if (!obj) { object_[numberObjects_] = originalObject[iObject]->clone(); // redo ids etc - CbcObject *obj = dynamic_cast< CbcObject * >(object_[numberObjects_]); + CbcObject *obj = dynamic_cast(object_[numberObjects_]); assert(obj); obj->redoSequenceEtc(this, numberColumns, originalColumns); numberObjects_++; @@ -19111,7 +19562,7 @@ CbcModel::preProcess(int makeEquality, int numberPasses, int tuning) if (iColumn < 0) { object_[numberObjects_] = originalObject[iObject]->clone(); // redo ids etc - CbcObject *obj = static_cast< CbcObject * >(object_[numberObjects_]); + CbcObject *obj = static_cast(object_[numberObjects_]); assert(obj); obj->redoSequenceEtc(this, numberColumns, originalColumns); numberObjects_++; @@ -19131,12 +19582,10 @@ CbcModel::preProcess(int makeEquality, int numberPasses, int tuning) } /* Does postprocessing - original solver back. User has to delete process */ -void CbcModel::postProcess(CglPreProcess *process) -{ +void CbcModel::postProcess(CglPreProcess *process) { process->postProcess(*solver_); delete solver_; solver_ = process->originalModel(); - } /* Process root node and return a strengthened model @@ -19145,9 +19594,7 @@ The method assumes that initialSolve() has been called to solve the LP relaxation. It processes the root node and then returns a pointer to the strengthened model (or NULL if infeasible) */ -OsiSolverInterface * -CbcModel::strengthenedModel() -{ +OsiSolverInterface *CbcModel::strengthenedModel() { /* Switch off heuristics */ @@ -19169,14 +19616,14 @@ CbcModel::strengthenedModel() /* Solve the relaxation. - Apparently there are circumstances where this will be non-trivial --- i.e., - we've done something since initialSolve that's trashed the solution to the - continuous relaxation. + Apparently there are circumstances where this will be non-trivial --- + i.e., we've done something since initialSolve that's trashed the solution + to the continuous relaxation. */ bool feasible = resolve(NULL, 0) != 0; /* - If the linear relaxation of the root is infeasible, bail out now. Otherwise, - continue with processing the root node. + If the linear relaxation of the root is infeasible, bail out now. + Otherwise, continue with processing the root node. */ if (!feasible) { handler_->message(CBC_INFEAS, messages_) << CoinMessageEol; @@ -19195,9 +19642,8 @@ CbcModel::strengthenedModel() double cutoff = getCutoff(); double direction = solver_->getObjSense(); if (cutoff < 1.0e20 && direction < 0.0) - messageHandler()->message(CBC_CUTOFF_WARNING1, - messages()) - << cutoff << -cutoff << CoinMessageEol; + messageHandler()->message(CBC_CUTOFF_WARNING1, messages()) + << cutoff << -cutoff << CoinMessageEol; if (cutoff > bestObjective_) cutoff = bestObjective_; setCutoff(cutoff); @@ -19221,9 +19667,9 @@ CbcModel::strengthenedModel() */ analyzeObjective(); /* - Set up for cut generation. addedCuts_ holds the cuts which are relevant for - the active subproblem. whichGenerator will be used to record the generator - that produced a given cut. + Set up for cut generation. addedCuts_ holds the cuts which are relevant + for the active subproblem. whichGenerator will be used to record the + generator that produced a given cut. */ maximumWhich_ = INITIAL_MAXIMUM_WHICH; delete[] whichGenerator_; @@ -19247,7 +19693,8 @@ CbcModel::strengthenedModel() */ int iCutGenerator; - for (iCutGenerator = 0; iCutGenerator < numberCutGenerators_; iCutGenerator++) { + for (iCutGenerator = 0; iCutGenerator < numberCutGenerators_; + iCutGenerator++) { CglCutGenerator *generator = generator_[iCutGenerator]->generator(); generator->setAggressiveness(generator->getAggressiveness() + 100); } @@ -19258,7 +19705,7 @@ CbcModel::strengthenedModel() int iObject; int numberUnsatisfied = 0; memcpy(currentSolution_, solver_->getColSolution(), - numberColumns * sizeof(double)); + numberColumns * sizeof(double)); // point to useful information OsiBranchingInformation usefulInfo = usefulInformation(); @@ -19268,8 +19715,7 @@ CbcModel::strengthenedModel() numberUnsatisfied++; } if (numberUnsatisfied) { - feasible = solveWithCuts(cuts, maximumCutPassesAtRoot_, - NULL); + feasible = solveWithCuts(cuts, maximumCutPassesAtRoot_, NULL); } } /* @@ -19314,9 +19760,7 @@ CbcModel::strengthenedModel() The method creates a new clean model with given bounds. */ -CbcModel * -CbcModel::cleanModel(const double *lower, const double *upper) -{ +CbcModel *CbcModel::cleanModel(const double *lower, const double *upper) { OsiSolverInterface *solver = continuousSolver_->clone(); int numberIntegers = numberIntegers_; @@ -19327,10 +19771,12 @@ CbcModel::cleanModel(const double *lower, const double *upper) int iColumn = integerVariable[i]; const OsiObject *object = object_[i]; #ifndef NDEBUG - const CbcSimpleInteger *integerObject = dynamic_cast< const CbcSimpleInteger * >(object); + const CbcSimpleInteger *integerObject = + dynamic_cast(object); assert(integerObject); #else - const CbcSimpleInteger *integerObject = static_cast< const CbcSimpleInteger * >(object); + const CbcSimpleInteger *integerObject = + static_cast(object); #endif // get original bounds double originalLower = integerObject->originalLowerBound(); @@ -19355,12 +19801,10 @@ CbcModel::cleanModel(const double *lower, const double *upper) if (howOften > -100) { CbcCutGenerator *generator = virginGenerator_[i]; CglCutGenerator *cglGenerator = generator->generator(); - model->addCutGenerator(cglGenerator, howOften, - generator->cutGeneratorName(), - generator->normal(), - generator->atSolution(), - generator->whenInfeasible(), - -100, generator->whatDepthInSub(), -1); + model->addCutGenerator( + cglGenerator, howOften, generator->cutGeneratorName(), + generator->normal(), generator->atSolution(), + generator->whenInfeasible(), -100, generator->whatDepthInSub(), -1); } } double cutoff = getCutoff(); @@ -19385,10 +19829,8 @@ CbcModel::cleanModel(const double *lower, const double *upper) */ -int CbcModel::subBranchAndBound(CbcModel *model, - CbcModel *presolvedModel, - int maximumNodes) -{ +int CbcModel::subBranchAndBound(CbcModel *model, CbcModel *presolvedModel, + int maximumNodes) { int i; double cutoff = model->getCutoff(); CbcModel *model2; @@ -19404,9 +19846,9 @@ int CbcModel::subBranchAndBound(CbcModel *model, } // Definition of node choice model2->setNodeComparison(nodeCompare_->clone()); - //model2->solver()->setHintParam(OsiDoReducePrint,true,OsiHintTry); + // model2->solver()->setHintParam(OsiDoReducePrint,true,OsiHintTry); model2->messageHandler()->setLogLevel(CoinMax(0, handler_->logLevel() - 1)); - //model2->solver()->messageHandler()->setLogLevel(2); + // model2->solver()->messageHandler()->setLogLevel(2); model2->setMaximumCutPassesAtRoot(maximumCutPassesAtRoot_); model2->setPrintFrequency(50); model2->setIntParam(CbcModel::CbcMaxNumNode, maximumNodes); @@ -19447,8 +19889,7 @@ Returns 0 if search completed and solution, 1 if not completed and solution, 2 if completed and no solution, 3 if not completed and no solution. */ int CbcModel::subBranchAndBound(const double *lower, const double *upper, - int maximumNodes) -{ + int maximumNodes) { OsiSolverInterface *solver = continuousSolver_->clone(); int numberIntegers = numberIntegers_; @@ -19459,10 +19900,12 @@ int CbcModel::subBranchAndBound(const double *lower, const double *upper, int iColumn = integerVariable[i]; const OsiObject *object = object_[i]; #ifndef NDEBUG - const CbcSimpleInteger *integerObject = dynamic_cast< const CbcSimpleInteger * >(object); + const CbcSimpleInteger *integerObject = + dynamic_cast(object); assert(integerObject); #else - const CbcSimpleInteger *integerObject = static_cast< const CbcSimpleInteger * >(object); + const CbcSimpleInteger *integerObject = + static_cast(object); #endif // get original bounds double originalLower = integerObject->originalLowerBound(); @@ -19489,8 +19932,8 @@ int CbcModel::subBranchAndBound(const double *lower, const double *upper, return 2; } if (handler_->logLevel() > 1) - printf("Reduced model has %d rows and %d columns\n", - model2->getNumRows(), model2->getNumCols()); + printf("Reduced model has %d rows and %d columns\n", model2->getNumRows(), + model2->getNumCols()); // Do complete search // Cuts @@ -19499,12 +19942,10 @@ int CbcModel::subBranchAndBound(const double *lower, const double *upper, if (howOften > -100) { CbcCutGenerator *generator = virginGenerator_[i]; CglCutGenerator *cglGenerator = generator->generator(); - model2->addCutGenerator(cglGenerator, howOften, - generator->cutGeneratorName(), - generator->normal(), - generator->atSolution(), - generator->whenInfeasible(), - -100, generator->whatDepthInSub(), -1); + model2->addCutGenerator( + cglGenerator, howOften, generator->cutGeneratorName(), + generator->normal(), generator->atSolution(), + generator->whenInfeasible(), -100, generator->whatDepthInSub(), -1); } } for (i = 0; i < numberHeuristics_; i++) { @@ -19513,9 +19954,9 @@ int CbcModel::subBranchAndBound(const double *lower, const double *upper, } // Definition of node choice model2->setNodeComparison(nodeCompare_->clone()); - //model2->solver()->setHintParam(OsiDoReducePrint,true,OsiHintTry); + // model2->solver()->setHintParam(OsiDoReducePrint,true,OsiHintTry); model2->messageHandler()->setLogLevel(CoinMax(0, handler_->logLevel() - 1)); - //model2->solver()->messageHandler()->setLogLevel(2); + // model2->solver()->messageHandler()->setLogLevel(2); model2->setMaximumCutPassesAtRoot(maximumCutPassesAtRoot_); model2->setPrintFrequency(50); model2->setIntParam(CbcModel::CbcMaxNumNode, maximumNodes); @@ -19550,8 +19991,8 @@ static void *doRootCbcThread(void *voidInfo) rootBundle * bundle = reinterpret_cast< rootBundle *>(voidInfo); CbcModel *model = bundle->model; #ifdef CBC_HAS_CLP - OsiClpSolverInterface *clpSolver - = dynamic_cast< OsiClpSolverInterface * >(model->solver()); + OsiClpSolverInterface *clpSolver = + dynamic_cast(model->solver()); char general[200]; if (clpSolver) { sprintf(general, "Starting multiple root solver %d",bundle->iModel+1); @@ -19569,17 +20010,16 @@ static void *doRootCbcThread(void *voidInfo) } else { model->initialSolve(); sprintf(general, "Solver did %d iterations in initialSolve\n", - model->solver()->getIterationCount()); - model->messageHandler()->message(CBC_GENERAL, - model->messages()) - << general << CoinMessageEol; + model->solver()->getIterationCount()); + model->messageHandler()->message(CBC_GENERAL, model->messages()) + << general << CoinMessageEol; } #endif - // switch off nauty + // switch off nauty #ifdef CBC_HAS_NAUTY - int newOptions = model->moreSpecialOptions2(); - newOptions &= ~(128|256); - model->setMoreSpecialOptions2(newOptions); + int newOptions = model->moreSpecialOptions2(); + newOptions &= ~(128 | 256); + model->setMoreSpecialOptions2(newOptions); #endif model->branchAndBound(); sprintf(general, "Ending multiple root solver %d",bundle->iModel+1); @@ -19588,14 +20028,13 @@ static void *doRootCbcThread(void *voidInfo) << general << CoinMessageEol; return NULL; } -OsiRowCut * -CbcModel::conflictCut(const OsiSolverInterface *solver, bool &localCuts) -{ +OsiRowCut *CbcModel::conflictCut(const OsiSolverInterface *solver, + bool &localCuts) { OsiRowCut *cut = NULL; localCuts = false; #ifdef CBC_HAS_CLP - const OsiClpSolverInterface *clpSolver - = dynamic_cast< const OsiClpSolverInterface * >(solver); + const OsiClpSolverInterface *clpSolver = + dynamic_cast(solver); if (clpSolver && topOfTree_) { int debugMode = 0; const double *originalLower = topOfTree_->lower(); @@ -19624,8 +20063,8 @@ CbcModel::conflictCut(const OsiSolverInterface *solver, bool &localCuts) for (int i = 0; i < numberRows; i++) { if (fabs(ray[i] - saveRay[i]) > 1.0e-3) { if (debugMode) - printf("row %d true %g bad %g - diff %g\n", - i, ray[i], saveRay[i], ray[i] - saveRay[i]); + printf("row %d true %g bad %g - diff %g\n", i, ray[i], + saveRay[i], ray[i] - saveRay[i]); nBad++; } } @@ -19637,7 +20076,7 @@ CbcModel::conflictCut(const OsiSolverInterface *solver, bool &localCuts) // make sure we use non-scaled versions ClpPackedMatrix *saveMatrix = simplex->swapScaledMatrix(NULL); double *saveScale = simplex->swapRowScale(NULL); - //printf("Could do normal cut\n"); + // printf("Could do normal cut\n"); // could use existing arrays int numberRows = simplex->numberRows(); int numberColumns = simplex->numberColumns(); @@ -19669,8 +20108,8 @@ CbcModel::conflictCut(const OsiSolverInterface *solver, bool &localCuts) // get farkas row memset(farkas, 0, (2 * numberColumns + numberRows) * sizeof(double)); simplex->transposeTimes(-1.0, ray, farkas); - //const char * integerInformation = simplex->integerType_; - //assert (integerInformation); + // const char * integerInformation = simplex->integerType_; + // assert (integerInformation); int sequenceOut = simplex->sequenceOut(); // Put nonzero bounds in bound @@ -19687,7 +20126,7 @@ CbcModel::conflictCut(const OsiSolverInterface *solver, bool &localCuts) farkas[i] = 0.0; } if (value) { - //printf("basic %d direction %d farkas %g\n", + // printf("basic %d direction %d farkas %g\n", // i,simplex->directionOut(),value); if (value < 0.0) boundValue = columnLower[i]; @@ -19706,8 +20145,8 @@ CbcModel::conflictCut(const OsiSolverInterface *solver, bool &localCuts) } const double *rowLower = simplex->rowLower(); const double *rowUpper = simplex->rowUpper(); - //int pivotRow = simplex->spareIntArray_[3]; - //bool badPivot=pivotRow<0; + // int pivotRow = simplex->spareIntArray_[3]; + // bool badPivot=pivotRow<0; for (int i = 0; i < numberRows; i++) { double value = ray[i]; double rhsValue = 0.0; @@ -19718,7 +20157,7 @@ CbcModel::conflictCut(const OsiSolverInterface *solver, bool &localCuts) ray[i] = 0.0; } if (value) { - //printf("row basic %d direction %d ray %g\n", + // printf("row basic %d direction %d ray %g\n", // i,simplex->directionOut(),value); if (value < 0.0) rhsValue = rowLower[i]; @@ -19742,8 +20181,7 @@ CbcModel::conflictCut(const OsiSolverInterface *solver, bool &localCuts) } if (numberBad || bSum > -1.0e-4) { #ifndef NDEBUG - printf("bad BOUND bSum %g - %d bad\n", - bSum, numberBad); + printf("bad BOUND bSum %g - %d bad\n", bSum, numberBad); #endif } else { const char *integerInformation = simplex->integerInformation(); @@ -19758,10 +20196,10 @@ CbcModel::conflictCut(const OsiSolverInterface *solver, bool &localCuts) if (integerInformation[iColumn]) { if ((debugMode & 1) != 0) printf("%d status %d %g <= %g <=%g (orig %g, %g) farkas %g\n", - iColumn, simplex->getStatus(iColumn), columnLower[iColumn], - simplex->primalColumnSolution()[iColumn], columnUpper[iColumn], - originalLower[iColumn], originalUpper[iColumn], - farkas[iColumn]); + iColumn, simplex->getStatus(iColumn), columnLower[iColumn], + simplex->primalColumnSolution()[iColumn], + columnUpper[iColumn], originalLower[iColumn], + originalUpper[iColumn], farkas[iColumn]); double gap = originalUpper[iColumn] - originalLower[iColumn]; if (!gap) continue; @@ -19779,44 +20217,54 @@ CbcModel::conflictCut(const OsiSolverInterface *solver, bool &localCuts) if (farkas[iColumn] < 0.0) { assert(originalLower[iColumn] - columnLower[iColumn] <= 0.0); // farkas is negative - relax lower bound all way - relax += farkas[iColumn] * (originalLower[iColumn] - columnLower[iColumn]); + relax += farkas[iColumn] * + (originalLower[iColumn] - columnLower[iColumn]); } else { assert(originalUpper[iColumn] - columnUpper[iColumn] >= 0.0); // farkas is positive - relax upper bound all way - relax += farkas[iColumn] * (originalUpper[iColumn] - columnUpper[iColumn]); + relax += farkas[iColumn] * + (originalUpper[iColumn] - columnUpper[iColumn]); } continue; } if (originalLower[iColumn] == columnLower[iColumn]) { - if (farkas[iColumn] > 0.0 && (simplex->getStatus(iColumn) == ClpSimplex::atUpperBound || simplex->getStatus(iColumn) == ClpSimplex::isFixed || iColumn == sequenceOut)) { + if (farkas[iColumn] > 0.0 && + (simplex->getStatus(iColumn) == ClpSimplex::atUpperBound || + simplex->getStatus(iColumn) == ClpSimplex::isFixed || + iColumn == sequenceOut)) { // farkas is positive - add to list gap = originalUpper[iColumn] - columnUpper[iColumn]; if (gap) { sort[nConflict] = -farkas[iColumn] * gap; conflict[nConflict++] = iColumn; } - //assert (gap>columnUpper[iColumn]-columnLower[iColumn]); + // assert (gap>columnUpper[iColumn]-columnLower[iColumn]); } } else if (originalUpper[iColumn] == columnUpper[iColumn]) { - if (farkas[iColumn] < 0.0 && (simplex->getStatus(iColumn) == ClpSimplex::atLowerBound || simplex->getStatus(iColumn) == ClpSimplex::isFixed || iColumn == sequenceOut)) { + if (farkas[iColumn] < 0.0 && + (simplex->getStatus(iColumn) == ClpSimplex::atLowerBound || + simplex->getStatus(iColumn) == ClpSimplex::isFixed || + iColumn == sequenceOut)) { // farkas is negative - add to list gap = columnLower[iColumn] - originalLower[iColumn]; if (gap) { sort[nConflict] = farkas[iColumn] * gap; conflict[nConflict++] = iColumn; } - //assert (gap>columnUpper[iColumn]-columnLower[iColumn]); + // assert (gap>columnUpper[iColumn]-columnLower[iColumn]); } } else { // can't use if (farkas[iColumn] < 0.0) { assert(originalLower[iColumn] - columnLower[iColumn] <= 0.0); // farkas is negative - relax lower bound all way - relax += farkas[iColumn] * (originalLower[iColumn] - columnLower[iColumn]); + relax += farkas[iColumn] * + (originalLower[iColumn] - columnLower[iColumn]); } else { assert(originalUpper[iColumn] - columnUpper[iColumn] >= 0.0); // farkas is positive - relax upper bound all way - relax += farkas[iColumn] * (originalUpper[iColumn] - columnUpper[iColumn]); + relax += farkas[iColumn] * + (originalUpper[iColumn] - columnUpper[iColumn]); } } assert(relax >= 0.0); @@ -19828,11 +20276,13 @@ CbcModel::conflictCut(const OsiSolverInterface *solver, bool &localCuts) if (farkas[iColumn] < 0.0) { assert(originalLower[iColumn] - columnLower[iColumn] <= 0.0); // farkas is negative - relax lower bound all way - relax += farkas[iColumn] * (originalLower[iColumn] - columnLower[iColumn]); + relax += farkas[iColumn] * + (originalLower[iColumn] - columnLower[iColumn]); } else { assert(originalUpper[iColumn] - columnUpper[iColumn] >= 0.0); // farkas is positive - relax upper bound all way - relax += farkas[iColumn] * (originalUpper[iColumn] - columnUpper[iColumn]); + relax += farkas[iColumn] * + (originalUpper[iColumn] - columnUpper[iColumn]); } } } @@ -19843,7 +20293,8 @@ CbcModel::conflictCut(const OsiSolverInterface *solver, bool &localCuts) printf("General integers relax bSum to %g\n", relax + bSum); #endif } else { - printf("All variables relaxed and still infeasible - what does this mean?\n"); + printf("All variables relaxed and still infeasible - what does " + "this mean?\n"); int nR = 0; for (int i = 0; i < numberRows; i++) { if (fabs(ray[i]) > 1.0e-10) @@ -19863,14 +20314,15 @@ CbcModel::conflictCut(const OsiSolverInterface *solver, bool &localCuts) } } } else { - printf("BOUNDS violation bSum %g (relaxed %g) - %d at original bounds, %d fixed - %d in conflict\n", bSum, - relax + bSum, nOriginal, nFixed, nConflict); + printf("BOUNDS violation bSum %g (relaxed %g) - %d at original " + "bounds, %d fixed - %d in conflict\n", + bSum, relax + bSum, nOriginal, nFixed, nConflict); CoinSort_2(sort, sort + nConflict, conflict); int nC = nConflict; bSum += relax; double saveBsum = bSum; while (nConflict) { - //int iColumn=conflict[nConflict-1]; + // int iColumn=conflict[nConflict-1]; double change = -sort[nConflict - 1]; if (bSum + change > -1.0e-4) break; @@ -19916,13 +20368,14 @@ CbcModel::conflictCut(const OsiSolverInterface *solver, bool &localCuts) } cut->setLb(lo); cut->setRow(nConflict, conflict, sort); - printf("CUT has %d (started at %d) - final bSum %g\n", nConflict, nC, bSum); + printf("CUT has %d (started at %d) - final bSum %g\n", nConflict, + nC, bSum); } else { // just save for use later // first take off small int nC2 = nC; while (nC2) { - //int iColumn=conflict[nConflict-1]; + // int iColumn=conflict[nConflict-1]; double change = -sort[nC2 - 1]; if (saveBsum + change > -1.0e-4 || change > 1.0e-4) break; @@ -19935,8 +20388,9 @@ CbcModel::conflictCut(const OsiSolverInterface *solver, bool &localCuts) sort[i] = farkas[iColumn]; } cut->setRow(nC2, conflict, sort); - printf("Stem CUT has %d (greedy %d - with small %d) - saved bSum %g final greedy bSum %g\n", - nC2, nConflict, nC, saveBsum, bSum); + printf("Stem CUT has %d (greedy %d - with small %d) - saved bSum " + "%g final greedy bSum %g\n", + nC2, nConflict, nC, saveBsum, bSum); } } } @@ -19952,30 +20406,29 @@ CbcModel::conflictCut(const OsiSolverInterface *solver, bool &localCuts) return cut; } -void CbcModel::setMIPStart(int count, const char **colNames, const double colValues[]) -{ +void CbcModel::setMIPStart(int count, const char **colNames, + const double colValues[]) { mipStart_.clear(); for (int i = 0; (i < count); ++i) - mipStart_.push_back(std::pair< std::string, double >(std::string(colNames[i]), colValues[i])); + mipStart_.push_back( + std::pair(std::string(colNames[i]), colValues[i])); } #ifdef CBC_HAS_NAUTY // get rid of all -void CbcModel::zapSymmetry() -{ +void CbcModel::zapSymmetry() { delete symmetryInfo_; symmetryInfo_ = NULL; } #endif /* Add SOS info to solver - Overwrites SOS information in solver with information - in CbcModel. Has no effect with some solvers. + in CbcModel. Has no effect with some solvers. Also updates integer info. */ -void CbcModel::addSOSEtcToSolver() -{ +void CbcModel::addSOSEtcToSolver() { // at present just for OsiClp #ifdef CBC_HAS_CLP - OsiClpSolverInterface *clpSolver - = dynamic_cast< OsiClpSolverInterface * >(solver_); + OsiClpSolverInterface *clpSolver = + dynamic_cast(solver_); if (clpSolver) { int numberColumns = clpSolver->getNumCols(); for (int i = 0; i < numberColumns; i++) @@ -19983,10 +20436,10 @@ void CbcModel::addSOSEtcToSolver() int nOdd = 0; int numberSOS = 0; for (int i = 0; i < numberObjects_; i++) { - CbcObject *obj = dynamic_cast< CbcObject * >(object_[i]); - CbcSimpleInteger *thisInt = dynamic_cast< CbcSimpleInteger * >(obj); - OsiSOS *objSOS1 = dynamic_cast< OsiSOS * >(obj); - CbcSOS *objSOS2 = dynamic_cast< CbcSOS * >(obj); + CbcObject *obj = dynamic_cast(object_[i]); + CbcSimpleInteger *thisInt = dynamic_cast(obj); + OsiSOS *objSOS1 = dynamic_cast(obj); + CbcSOS *objSOS2 = dynamic_cast(obj); if (thisInt) { clpSolver->setInteger(thisInt->columnNumber()); } else if (objSOS1) { @@ -20000,18 +20453,17 @@ void CbcModel::addSOSEtcToSolver() if (nOdd) { char general[200]; sprintf(general, "%d objects not SOS or Integer - can't move to Osi", - nOdd); - messageHandler()->message(CBC_GENERAL, - messages()) - << general << CoinMessageEol; + nOdd); + messageHandler()->message(CBC_GENERAL, messages()) + << general << CoinMessageEol; } if (numberSOS) { CoinSet *setInfo = new CoinSet[numberSOS]; numberSOS = 0; for (int i = 0; i < numberObjects_; i++) { - CbcObject *obj = dynamic_cast< CbcObject * >(object_[i]); - OsiSOS *objSOS1 = dynamic_cast< OsiSOS * >(obj); - CbcSOS *objSOS2 = dynamic_cast< CbcSOS * >(obj); + CbcObject *obj = dynamic_cast(object_[i]); + OsiSOS *objSOS1 = dynamic_cast(obj); + CbcSOS *objSOS2 = dynamic_cast(obj); if (objSOS1 || objSOS2) { int numberMembers; const int *members; @@ -20028,10 +20480,9 @@ void CbcModel::addSOSEtcToSolver() type = objSOS2->sosType(); weights = objSOS2->weights(); } - CoinSosSet info(numberMembers, members, - weights, type); - //info.setSetType(type); - //memcpy(info.modifiableWeights(),weights, + CoinSosSet info(numberMembers, members, weights, type); + // info.setSetType(type); + // memcpy(info.modifiableWeights(),weights, // numberMembers*sizeof(double)); setInfo[numberSOS++] = info; } @@ -20042,10 +20493,9 @@ void CbcModel::addSOSEtcToSolver() #endif } - void CbcModel::roundIntVars() { if (bestSolution_) { - for ( int i=0 ; igetNumCols() ; ++i ) { + for (int i = 0; i < solver_->getNumCols(); ++i) { if (solver_->isInteger(i)) { bestSolution_[i] = floor(bestSolution_[i] + 0.5); } @@ -20058,14 +20508,13 @@ void CbcModel::roundIntVars() { Returns number of variables forced out cleanVariables array will be used if exists */ -int CbcModel::cleanBounds(OsiSolverInterface *solver, char *cleanIn) -{ +int CbcModel::cleanBounds(OsiSolverInterface *solver, char *cleanIn) { int numberBad = 0; #ifdef CBC_HAS_CLP #ifndef ZERO_ODD_TOLERANCE #define ZERO_ODD_TOLERANCE 1.0e-14 #endif - OsiClpSolverInterface *osiclp = dynamic_cast< OsiClpSolverInterface * >(solver); + OsiClpSolverInterface *osiclp = dynamic_cast(solver); if (osiclp && osiclp->isProvenOptimal()) { int numberColumns = osiclp->getNumCols(); char *cleanVariables; @@ -20105,7 +20554,8 @@ int CbcModel::cleanBounds(OsiSolverInterface *solver, char *cleanIn) } if (numberBad) { #ifdef SHOW_BAD - printf("%d small variables low (%g max %g), high (%g max %g)\n", numberBad, sumBadLow, maxBadLow, sumBadHigh, maxBadHigh); + printf("%d small variables low (%g max %g), high (%g max %g)\n", + numberBad, sumBadLow, maxBadLow, sumBadHigh, maxBadHigh); #endif for (int i = 0; i < numberColumns; i++) { if (cleanVariables[i]) { @@ -20130,18 +20580,18 @@ int CbcModel::cleanBounds(OsiSolverInterface *solver, char *cleanIn) return numberBad; } // Sets up cleanVariables array (i.e. ones to be careful about) -char * -CbcModel::setupCleanVariables() -{ - OsiClpSolverInterface *osiclp = dynamic_cast< OsiClpSolverInterface * >(solver_); +char *CbcModel::setupCleanVariables() { + OsiClpSolverInterface *osiclp = + dynamic_cast(solver_); int numberColumns = osiclp->getNumCols(); char *cleanVariables = NULL; if (osiclp) { cleanVariables = new char[numberColumns]; memset(cleanVariables, 0, numberColumns); for (int i = 0; i < numberObjects_; i++) { - const CbcSimpleInteger *intvar = dynamic_cast< const CbcSimpleInteger * >(object_[i]); - const CbcSOS *sos = dynamic_cast< const CbcSOS * >(object_[i]); + const CbcSimpleInteger *intvar = + dynamic_cast(object_[i]); + const CbcSOS *sos = dynamic_cast(object_[i]); if (intvar) { #ifdef CLEAN_INTEGER_VARIABLES cleanVariables[intvar->columnNumber()] = 1; @@ -20158,33 +20608,35 @@ CbcModel::setupCleanVariables() } /* Returns postProcessed solution in solver(called from event handler) Normally used for integer solution (not really tested otherwise) - solutionType 1 is best integer so far, 0 is current solution + solutionType 1 is best integer so far, 0 is current solution (may not be integer) */ -const OsiSolverInterface * -CbcModel::postProcessedSolver(int solutionType) -{ +const OsiSolverInterface *CbcModel::postProcessedSolver(int solutionType) { CbcModel *model = this; CglPreProcess *processPointer = model->preProcess(); OsiSolverInterface *originalModel = NULL; const double *solution = bestSolution(); while (processPointer) { int numberSolvers = processPointer->numberSolvers(); - OsiSolverInterface *solver = processPointer->presolve(numberSolvers - 1)->presolvedModel(); + OsiSolverInterface *solver = + processPointer->presolve(numberSolvers - 1)->presolvedModel(); if (solutionType) { // massage solution int numberColumns = solver->getNumCols(); - double *saveLower = CoinCopyOfArray(model->solver()->getColLower(), numberColumns); - double *saveUpper = CoinCopyOfArray(model->solver()->getColUpper(), numberColumns); + double *saveLower = + CoinCopyOfArray(model->solver()->getColLower(), numberColumns); + double *saveUpper = + CoinCopyOfArray(model->solver()->getColUpper(), numberColumns); const double *saveSolution = testSolution_; setTestSolution(solution); model->solver()->setColLower(solution); model->solver()->setColUpper(solution); OsiBranchingInformation usefulInfo = model->usefulInformation(); /* - Run through the objects and use feasibleRegion() to set variable bounds - so as to fix the variables specified in the objects at their value in this - solution. Since the object list contains (at least) one object for every - integer variable, this has the effect of fixing all integer variables. + Run through the objects and use feasibleRegion() to set variable bounds + so as to fix the variables specified in the objects at their value in + this solution. Since the object list contains (at least) one object for + every integer variable, this has the effect of fixing all integer + variables. */ for (int i = 0; i < model->numberObjects(); i++) model->object(i)->feasibleRegion(solver, &usefulInfo); @@ -20205,19 +20657,15 @@ CbcModel::postProcessedSolver(int solutionType) return originalModel; } // Delete a node and possibly null out currentNode_ -void -CbcModel::deleteNode(CbcNode * node) -{ +void CbcModel::deleteNode(CbcNode *node) { delete node; - if (node==currentNode_) + if (node == currentNode_) currentNode_ = NULL; } // Check if a solution is really valid e.g. lazy constraints // Returns true if ok or normal cuts (i.e. no atSolution ones) -bool -CbcModel::reallyValid(OsiCuts * existingCuts) -{ - if ((moreSpecialOptions2_&65536)==0) +bool CbcModel::reallyValid(OsiCuts *existingCuts) { + if ((moreSpecialOptions2_ & 65536) == 0) return true; /* Now step through the cut generators and see if any of them are flagged to @@ -20229,41 +20677,44 @@ CbcModel::reallyValid(OsiCuts * existingCuts) int lastNumberCuts = 0; for (int i = 0; i < numberCutGenerators_; i++) { bool generate = generator_[i]->atSolution(); - // skip if not optimal and should be (maybe a cut generator has fixed variables) + // skip if not optimal and should be (maybe a cut generator has fixed + // variables) if (generator_[i]->needsOptimalBasis() && !solver_->basisIsAvailable()) generate = false; if (generate) { generator_[i]->generateCuts(theseCuts, 1, solver_, NULL); int numberCuts = theseCuts.sizeRowCuts(); - const double * solution = solver_->getColSolution(); + const double *solution = solver_->getColSolution(); double integerTolerance = getDblParam(CbcIntegerTolerance); for (int j = lastNumberCuts; j < numberCuts; j++) { - const OsiRowCut *thisCut = theseCuts.rowCutPtr(j); - // Check if cut generator is stupid - if (thisCut->violated(solution) > integerTolerance) { - if (thisCut->globallyValid()) { - if ((specialOptions_ & 1) != 0) { - /* As these are global cuts - - a) Always get debugger object - b) Not fatal error to cutoff optimal (if we have just got optimal) - */ - const OsiRowCutDebugger *debugger = solver_->getRowCutDebuggerAlways(); - if (debugger) { - if (debugger->invalidCut(*thisCut)) - printf("ZZZZ Global cut - cuts off optimal solution!\n"); - } - } - // add to global list - OsiRowCut newCut(*thisCut); - newCut.setGloballyValid(true); - newCut.mutableRow().setTestForDuplicateIndex(false); - globalCuts_.addCutIfNotDuplicate(newCut); - generator_[i]->incrementNumberCutsInTotal(); - // and to existing cuts - if (existingCuts) - existingCuts->insertIfNotDuplicate(newCut); - } - } + const OsiRowCut *thisCut = theseCuts.rowCutPtr(j); + // Check if cut generator is stupid + if (thisCut->violated(solution) > integerTolerance) { + if (thisCut->globallyValid()) { + if ((specialOptions_ & 1) != 0) { + /* As these are global cuts - + a) Always get debugger object + b) Not fatal error to cutoff optimal (if we have just got + optimal) + */ + const OsiRowCutDebugger *debugger = + solver_->getRowCutDebuggerAlways(); + if (debugger) { + if (debugger->invalidCut(*thisCut)) + printf("ZZZZ Global cut - cuts off optimal solution!\n"); + } + } + // add to global list + OsiRowCut newCut(*thisCut); + newCut.setGloballyValid(true); + newCut.mutableRow().setTestForDuplicateIndex(false); + globalCuts_.addCutIfNotDuplicate(newCut); + generator_[i]->incrementNumberCutsInTotal(); + // and to existing cuts + if (existingCuts) + existingCuts->insertIfNotDuplicate(newCut); + } + } } } } @@ -20278,6 +20729,6 @@ CbcModel::reallyValid(OsiCuts * existingCuts) return (theseCuts.sizeRowCuts() == 0 && theseCuts.sizeColCuts() == 0); } -void CbcModel::setRoundIntegerVariables( bool round_ ) { +void CbcModel::setRoundIntegerVariables(bool round_) { this->roundIntVars_ = round_; } diff --git a/src/CbcModel.hpp b/src/CbcModel.hpp index f1ba1ed63..53a8ee8a2 100644 --- a/src/CbcModel.hpp +++ b/src/CbcModel.hpp @@ -128,7 +128,7 @@ class CBCLIB_EXPORT CbcModel { /** Maximum number of nodes without improving the best feasible * solution (just checked if a feasible solution was already found ) */ - CbcMaxNodesNotImprovingFeasSol, + CbcMaxNodesNotImproving, /** Just a marker, so that a static sized array can store parameters. */ CbcLastIntParam }; @@ -197,7 +197,7 @@ class CBCLIB_EXPORT CbcModel { CbcSmallChange, /** \brief Maximum time without improving the best solution found, checked only if a * feasible solution is already available */ - CbcMaximumSecondsNotImprovingFeasSol, + CbcMaxSecondsNotImproving, /** Just a marker, so that a static sized array can store parameters. */ CbcLastDblParam }; @@ -260,6 +260,8 @@ class CBCLIB_EXPORT CbcModel { int &numberNodesOutput, int &status); /// Update size of whichGenerator void resizeWhichGenerator(int numberNow, int numberAfter); + /// One last go at cuts + int oneLastGoAtCuts(OsiCuts &cuts, int typeGo); public: #ifdef CBC_KEEP_DEPRECATED @@ -641,6 +643,34 @@ class CBCLIB_EXPORT CbcModel { return getIntParam(CbcMaxNumNode); } + /// Set the \link CbcModel::CbcMaxNodesNotImproving limit \endlink + inline bool setMaxNodesNotImproving(int value) { + return setIntParam(CbcMaxNodesNotImproving, value); + } + + /// Get the \link CbcModel::CbcMaxNodesNotImproving limit \endlink + inline int getMaxNodesNotImproving() const { + return getIntParam(CbcMaxNodesNotImproving); + } + + /// Set the \link CbcModel::CbcMaxSecondsNotImproving limit \endlink + inline bool setMaxSecondsNotImproving(double value) { + return setDblParam(CbcMaxSecondsNotImproving, value); + } + + /// Get the \link CbcModel::CbcMaxSecondsNotImproving limit \endlink + inline double getMaxSecondsNotImproving() const { + return getDblParam(CbcMaxSecondsNotImproving); + } + + /// Set the \link CbcModel::CbcMaxSolutions limit \endlink + inline bool setMaxSolutions(int value) { + return setIntParam(CbcMaxNumSol, value); + } + + /// Get the \link CbcModel::CbcMaxSolutions limit \endlink + inline int getMaxSolution() const { return getIntParam(CbcMaxNumSol); } + /// If integer variables should be rounded before saving a solution. // For some problems with integer and continuous variables, rounding can // increase the infeasibilities, but it can make sense if all variables @@ -1863,6 +1893,10 @@ class CBCLIB_EXPORT CbcModel { { parentModel_ = &parentModel; } + /// See if in sub tree + inline bool inSmallBranchAndBound() const { + return (specialOptions_ & 2048) != 0 && parentModel_; + } //@} /** \name Heuristics and priorities */ @@ -2155,6 +2189,9 @@ class CBCLIB_EXPORT CbcModel { 21 bit 2097152 - analyze changed priorities but were equal before 22 bit 4194304 - ignore cutoff increment in multiple root solvers 23 bit (8388608) - no crunch + 25 bit 33554432 - also 26,27 lagrangean cuts + 28 bit 268435456 - alternative lagrangean cuts + 29 bit 536870912 - one shot of less useful cuts */ inline void setMoreSpecialOptions2(int value) { diff --git a/src/CbcNode.cpp b/src/CbcNode.cpp index f86f24b7a..48aa18a3f 100644 --- a/src/CbcNode.cpp +++ b/src/CbcNode.cpp @@ -2645,7 +2645,8 @@ int CbcNode::chooseDynamicBranch(CbcModel *model, CbcNode *lastNode, bestChoice = iBestGot; else bestChoice = iBestNot; - assert(bestChoice >= 0); + if(bestChoice < 0) + bestChoice = 0; // If we have hit max time don't do strong branching bool hitMaxTime = (model->getCurrentSeconds() > model->getDblParam(CbcModel::CbcMaximumSeconds)); // also give up if we are looping round too much @@ -3007,6 +3008,10 @@ int CbcNode::chooseDynamicBranch(CbcModel *model, CbcNode *lastNode, solver->setIntParam(OsiMaxNumIterationHotStart, 100000); //printf("Strong branching type %d\n",strongType); } + } else { + if (!depth_&&(model->specialOptions()&2048)==0) { + strongType = 2; + } } #endif #ifdef CBC_HAS_NAUTY diff --git a/src/CbcParam.cpp b/src/CbcParam.cpp index 5f843e175..713affaf5 100644 --- a/src/CbcParam.cpp +++ b/src/CbcParam.cpp @@ -1,510 +1,141 @@ -// Copyright (C) 2002, International Business Machines -// Corporation and others. All Rights Reserved. -// This code is licensed under the terms of the Eclipse Public License (EPL). +/* + Copyright (C) 2007, Lou Hafer, International Business Machines Corporation + and others. All Rights Reserved. + + This code is licensed under the terms of the Eclipse Public License (EPL). + +*/ #if defined(_MSC_VER) // Turn off compiler warning about long names #pragma warning(disable : 4786) #endif -#include -#include #include +#include +#include + +#include "CoinUtilsConfig.h" + +#include "CoinFileIO.hpp" +#include "CoinFinite.hpp" + +#include "CbcModel.hpp" #include "CbcParam.hpp" +#include "CbcParameters.hpp" -//############################################################################# -// Constructors / Destructor / Assignment -//############################################################################# +/* + Constructors and destructors -//------------------------------------------------------------------- -// Default Constructor -//------------------------------------------------------------------- + There's a generic constructor and one for integer, double, keyword, string, + and action parameters. +*/ + +//########################################################################### +//########################################################################### + +/* + Default constructor. +*/ CbcParam::CbcParam() - : type_(CBC_PARAM_NOTUSED_INVALID) - , lowerDoubleValue_(0.0) - , upperDoubleValue_(0.0) - , lowerIntValue_(0) - , upperIntValue_(0) - , lengthName_(0) - , lengthMatch_(0) - , definedKeyWords_() - , name_() - , shortHelp_() - , longHelp_() - , action_(CBC_PARAM_NOTUSED_INVALID) - , display_(false) - , intValue_(0) - , doubleValue_(0) - , currentKeyWord_(-1) - , indexNumber_(0) -{ + : CoinParam(), paramCode_(CbcParamCode(0)), parameters_(0), model_(0) { + /* Nothing to be done here */ } -// Other constructors -CbcParam::CbcParam(std::string name, std::string help, - double lower, double upper, CbcParameterType type, - bool display) - : type_(type) - , lowerIntValue_(0) - , upperIntValue_(0) - , definedKeyWords_() - , name_(name) - , shortHelp_(help) - , longHelp_() - , action_(type) - , currentKeyWord_(-1) - , display_(false) - , intValue_(0) - , doubleValue_(0) - , indexNumber_(0) -{ - lowerDoubleValue_ = lower; - upperDoubleValue_ = upper; - gutsOfConstructor(); -} -CbcParam::CbcParam(std::string name, std::string help, - int lower, int upper, CbcParameterType type, - bool display) - : type_(type) - , lowerDoubleValue_(0.0) - , upperDoubleValue_(0.0) - , definedKeyWords_() - , name_(name) - , shortHelp_(help) - , longHelp_() - , action_(type) - , currentKeyWord_(-1) - , display_(false) - , intValue_(0) - , doubleValue_(0) - , indexNumber_(0) -{ - gutsOfConstructor(); - lowerIntValue_ = lower; - upperIntValue_ = upper; -} -// Other strings will be added by append -CbcParam::CbcParam(std::string name, std::string help, - std::string firstValue, - CbcParameterType type, int defaultIndex, - bool display) - : type_(type) - , lowerDoubleValue_(0.0) - , upperDoubleValue_(0.0) - , lowerIntValue_(0) - , upperIntValue_(0) - , definedKeyWords_() - , name_(name) - , shortHelp_(help) - , longHelp_() - , action_(type) - , currentKeyWord_(0) - , display_(false) - , intValue_(0) - , doubleValue_(0) - , indexNumber_(0) -{ - gutsOfConstructor(); - definedKeyWords_.push_back(firstValue); + +//########################################################################### +//########################################################################### + +/* + Constructor for double parameter +*/ +CbcParam::CbcParam(int code, std::string name, + std::string help, double lower, double upper, + std::string longHelp, CoinDisplayPriority displayPriority) + : CoinParam(name, help, lower, upper, longHelp, displayPriority), + paramCode_(code), parameters_(0), model_(0) { + /* Nothing to be done here */ } -// Action -CbcParam::CbcParam(std::string name, std::string help, - CbcParameterType type, int indexNumber, - bool display) - : type_(type) - , lowerDoubleValue_(0.0) - , upperDoubleValue_(0.0) - , lowerIntValue_(0) - , upperIntValue_(0) - , definedKeyWords_() - , name_(name) - , shortHelp_(help) - , longHelp_() - , action_(type) - , currentKeyWord_(-1) - , display_(false) - , intValue_(0) - , doubleValue_(0) - , indexNumber_(0) -{ - gutsOfConstructor(); + +//########################################################################### +//########################################################################### + +/* + Constructor for integer parameter +*/ +CbcParam::CbcParam(int code, std::string name, + std::string help, int lower, int upper, + std::string longHelp, CoinDisplayPriority displayPriority) + : CoinParam(name, help, lower, upper, longHelp, displayPriority), + paramCode_(code), parameters_(0), model_(0) { + /* Nothing to be done here */ } -//------------------------------------------------------------------- -// Copy constructor -//------------------------------------------------------------------- -CbcParam::CbcParam(const CbcParam &rhs) -{ - type_ = rhs.type_; - lowerDoubleValue_ = rhs.lowerDoubleValue_; - upperDoubleValue_ = rhs.upperDoubleValue_; - lowerIntValue_ = rhs.lowerIntValue_; - upperIntValue_ = rhs.upperIntValue_; - lengthName_ = rhs.lengthName_; - lengthMatch_ = rhs.lengthMatch_; - definedKeyWords_ = rhs.definedKeyWords_; - name_ = rhs.name_; - shortHelp_ = rhs.shortHelp_; - longHelp_ = rhs.longHelp_; - action_ = rhs.action_; - currentKeyWord_ = rhs.currentKeyWord_; - display_ = rhs.display_; - intValue_ = rhs.intValue_; - doubleValue_ = rhs.doubleValue_; - indexNumber_ = rhs.indexNumber_; +//########################################################################### +//########################################################################### + +/* + Constructor for parameters with a string (or no) value (all others). + Type is not optional to resolve ambiguity. + + The default value is "" for all such parameter types +*/ +CbcParam::CbcParam(int code, std::string name, + CoinParam::CoinParamType type, + std::string help, std::string longHelp, + CoinDisplayPriority displayPriority) + : CoinParam(name, type, help, longHelp, displayPriority), + paramCode_(code), parameters_(0) { + /* Nothing to be done here */ } -//------------------------------------------------------------------- -// Destructor -//------------------------------------------------------------------- -CbcParam::~CbcParam() -{ +//########################################################################### +//########################################################################### + +/* + Copy constructor. +*/ +CbcParam::CbcParam(const CbcParam &orig) + : CoinParam(orig), paramCode_(orig.paramCode_), parameters_(orig.parameters_), + model_(orig.model_) { + /* Nothing to be done here */ } -//---------------------------------------------------------------- -// Assignment operator -//------------------------------------------------------------------- -CbcParam & -CbcParam::operator=(const CbcParam &rhs) -{ +//########################################################################### +//########################################################################### + +/* + Clone +*/ + +CbcParam *CbcParam::clone() { return (new CbcParam(*this)); } + +CbcParam &CbcParam::operator=(const CbcParam &rhs) { if (this != &rhs) { - type_ = rhs.type_; - lowerDoubleValue_ = rhs.lowerDoubleValue_; - upperDoubleValue_ = rhs.upperDoubleValue_; - lowerIntValue_ = rhs.lowerIntValue_; - upperIntValue_ = rhs.upperIntValue_; - lengthName_ = rhs.lengthName_; - lengthMatch_ = rhs.lengthMatch_; - definedKeyWords_ = rhs.definedKeyWords_; - name_ = rhs.name_; - shortHelp_ = rhs.shortHelp_; - longHelp_ = rhs.longHelp_; - action_ = rhs.action_; - currentKeyWord_ = rhs.currentKeyWord_; - display_ = rhs.display_; - intValue_ = rhs.intValue_; - doubleValue_ = rhs.doubleValue_; - indexNumber_ = rhs.indexNumber_; + CoinParam::operator=(rhs); + + paramCode_ = rhs.paramCode_; + model_ = rhs.model_; + parameters_ = rhs.parameters_; } + return *this; } -void CbcParam::gutsOfConstructor() -{ - std::string::size_type shriekPos = name_.find('!'); - lengthName_ = name_.length(); - if (shriekPos == std::string::npos) { - //does not contain '!' - lengthMatch_ = lengthName_; - } else { - lengthMatch_ = shriekPos; - name_ = name_.substr(0, shriekPos) + name_.substr(shriekPos + 1); - lengthName_--; - } -} -// Insert string (only valid for keywords) -void CbcParam::append(std::string keyWord) -{ - definedKeyWords_.push_back(keyWord); -} -int CbcParam::matches(std::string input) const -{ - // look up strings to do more elegantly - if (input.length() > lengthName_) { - return 0; - } else { - unsigned int i; - for (i = 0; i < input.length(); i++) { - if (tolower(name_[i]) != tolower(input[i])) - break; - } - if (i < input.length()) { - return 0; - } else if (i >= lengthMatch_) { - return 1; - } else { - // matched but too short - return 2; - } - } -} -// Returns name which could match -std::string -CbcParam::matchName() const -{ - if (lengthMatch_ == lengthName_) - return name_; - else - return name_.substr(0, lengthMatch_) + "(" + name_.substr(lengthMatch_) + ")"; -} +//########################################################################### +//########################################################################### -// Returns parameter option which matches (-1 if none) -int CbcParam::parameterOption(std::string check) const -{ - int numberItems = definedKeyWords_.size(); - if (!numberItems) { - return -1; - } else { - int whichItem = 0; - unsigned int it; - for (it = 0; it < definedKeyWords_.size(); it++) { - std::string thisOne = definedKeyWords_[it]; - std::string::size_type shriekPos = thisOne.find('!'); - unsigned int length1 = thisOne.length(); - unsigned int length2 = length1; - if (shriekPos != std::string::npos) { - //contains '!' - length2 = shriekPos; - thisOne = thisOne.substr(0, shriekPos) + thisOne.substr(shriekPos + 1); - length1 = thisOne.length(); - } - if (check.length() <= length1) { - unsigned int i; - for (i = 0; i < check.length(); i++) { - if (tolower(thisOne[i]) != tolower(check[i])) - break; - } - if (i < check.length()) { - whichItem++; - } else if (i >= length2) { - break; - } - } else { - whichItem++; - } - } - if (whichItem < numberItems) - return whichItem; - else - return -1; - } -} -// Prints parameter options -void CbcParam::printOptions() const -{ - std::cout << "Possible options for " << name_ << " are:" << std::endl; - unsigned int it; - for (it = 0; it < definedKeyWords_.size(); it++) { - std::string thisOne = definedKeyWords_[it]; - std::string::size_type shriekPos = thisOne.find('!'); - if (shriekPos != std::string::npos) { - //contains '!' - thisOne = thisOne.substr(0, shriekPos) + "(" + thisOne.substr(shriekPos + 1) + ")"; - } - std::cout << thisOne << std::endl; - } -} -int CbcParam::setDoubleParameter(OsiSolverInterface *model, double value) const -{ - if (value < lowerDoubleValue_ || value > upperDoubleValue_) { - std::cout << value << " was provided for " << name_ << " - valid range is " << lowerDoubleValue_ << " to " << upperDoubleValue_ << std::endl; - return 1; - } else { - double oldValue; - switch (type_) { - case CLP_PARAM_DBL_DUALTOLERANCE: - model->getDblParam(OsiDualTolerance, oldValue); - model->setDblParam(OsiDualTolerance, value); - break; - case CLP_PARAM_DBL_PRIMALTOLERANCE: - model->getDblParam(OsiPrimalTolerance, oldValue); - model->setDblParam(OsiPrimalTolerance, value); - break; - default: - oldValue = 0.0; // to avoid compiler message - abort(); - } - std::cout << name_ << " was changed from " << oldValue << " to " - << value << std::endl; - return 0; - } -} -int CbcParam::checkDoubleParameter(double value) const -{ - if (value < lowerDoubleValue_ || value > upperDoubleValue_) { - std::cout << value << " was provided for " << name_ << " - valid range is " << lowerDoubleValue_ << " to " << upperDoubleValue_ << std::endl; - return 1; - } else { - return 0; - } -} -double -CbcParam::doubleParameter(OsiSolverInterface *model) const -{ - double value; - bool getDblParamRetValue; - switch (type_) { - case CLP_PARAM_DBL_DUALTOLERANCE: - getDblParamRetValue = model->getDblParam(OsiDualTolerance, value); - assert(getDblParamRetValue); - break; - case CLP_PARAM_DBL_PRIMALTOLERANCE: - getDblParamRetValue = model->getDblParam(OsiPrimalTolerance, value); - assert(getDblParamRetValue); - break; - default: - abort(); - } - return value; -} -int CbcParam::setIntParameter(OsiSolverInterface *model, int value) const -{ - if (value < lowerIntValue_ || value > upperIntValue_) { - std::cout << value << " was provided for " << name_ << " - valid range is " << lowerIntValue_ << " to " << upperIntValue_ << std::endl; - return 1; - } else { - int oldValue; - switch (type_) { - case CLP_PARAM_INT_LOGLEVEL: - oldValue = model->messageHandler()->logLevel(); - model->messageHandler()->setLogLevel(value); - break; - default: - oldValue = 0; // to avoid compiler message - abort(); - } - std::cout << name_ << " was changed from " << oldValue << " to " - << value << std::endl; - return 0; - } -} -int CbcParam::intParameter(OsiSolverInterface *model) const -{ - int value = 0; - switch (type_) { - case CLP_PARAM_INT_LOGLEVEL: - //value=model->logLevel(); - break; - default: - abort(); - } - return value; -} -int CbcParam::setDoubleParameter(CbcModel &model, double value) const -{ - if (value < lowerDoubleValue_ || value > upperDoubleValue_) { - std::cout << value << " was provided for " << name_ << " - valid range is " << lowerDoubleValue_ << " to " << upperDoubleValue_ << std::endl; - return 1; - } else { - double oldValue; - switch (type_) { - case CBC_PARAM_DBL_INFEASIBILITYWEIGHT: - oldValue = model.getDblParam(CbcModel::CbcInfeasibilityWeight); - model.setDblParam(CbcModel::CbcInfeasibilityWeight, value); - break; - case CBC_PARAM_DBL_INTEGERTOLERANCE: - oldValue = model.getDblParam(CbcModel::CbcIntegerTolerance); - model.setDblParam(CbcModel::CbcIntegerTolerance, value); - break; - case CBC_PARAM_DBL_INCREMENT: - oldValue = model.getDblParam(CbcModel::CbcCutoffIncrement); - model.setDblParam(CbcModel::CbcCutoffIncrement, value); - break; - case CBC_PARAM_DBL_ALLOWABLEGAP: - oldValue = model.getDblParam(CbcModel::CbcAllowableGap); - model.setDblParam(CbcModel::CbcAllowableGap, value); - break; - case CLP_PARAM_DBL_TIMELIMIT: { - oldValue = model.getDblParam(CbcModel::CbcMaximumSeconds); - model.setDblParam(CbcModel::CbcMaximumSeconds, value); - break; - } - case CLP_PARAM_DBL_DUALTOLERANCE: - case CLP_PARAM_DBL_PRIMALTOLERANCE: - setDoubleParameter(model.solver(), value); - return 0; // to avoid message - default: - oldValue = 0.0; // to avoid compiler message - abort(); - } - std::cout << name_ << " was changed from " << oldValue << " to " - << value << std::endl; - return 0; - } -} -double -CbcParam::doubleParameter(CbcModel &model) const -{ - double value; - switch (type_) { - case CBC_PARAM_DBL_INFEASIBILITYWEIGHT: - value = model.getDblParam(CbcModel::CbcInfeasibilityWeight); - break; - case CBC_PARAM_DBL_INTEGERTOLERANCE: - value = model.getDblParam(CbcModel::CbcIntegerTolerance); - break; - case CBC_PARAM_DBL_INCREMENT: - value = model.getDblParam(CbcModel::CbcCutoffIncrement); - case CBC_PARAM_DBL_ALLOWABLEGAP: - value = model.getDblParam(CbcModel::CbcAllowableGap); - break; - case CLP_PARAM_DBL_TIMELIMIT: { - value = model.getDblParam(CbcModel::CbcMaximumSeconds); - break; - } - case CLP_PARAM_DBL_DUALTOLERANCE: - case CLP_PARAM_DBL_PRIMALTOLERANCE: - value = doubleParameter(model.solver()); - break; - default: - abort(); - } - return value; -} -int CbcParam::setIntParameter(CbcModel &model, int value) const -{ - if (value < lowerIntValue_ || value > upperIntValue_) { - std::cout << value << " was provided for " << name_ << " - valid range is " << lowerIntValue_ << " to " << upperIntValue_ << std::endl; - return 1; - } else { - int oldValue; - switch (type_) { - case CLP_PARAM_INT_LOGLEVEL: - oldValue = model.messageHandler()->logLevel(); - model.messageHandler()->setLogLevel(value); - break; - case CLP_PARAM_INT_SOLVERLOGLEVEL: - oldValue = model.solver()->messageHandler()->logLevel(); - model.solver()->messageHandler()->setLogLevel(value); - break; - case CBC_PARAM_INT_MAXNODES: - oldValue = model.getIntParam(CbcModel::CbcMaxNumNode); - model.setIntParam(CbcModel::CbcMaxNumNode, value); - break; - case CBC_PARAM_INT_STRONGBRANCHING: - oldValue = model.numberStrong(); - model.setNumberStrong(value); - break; - default: - oldValue = 0; // to avoid compiler message - abort(); - } - std::cout << name_ << " was changed from " << oldValue << " to " - << value << std::endl; - return 0; - } -} -int CbcParam::intParameter(CbcModel &model) const -{ - int value; - switch (type_) { - case CLP_PARAM_INT_LOGLEVEL: - value = model.messageHandler()->logLevel(); - break; - case CLP_PARAM_INT_SOLVERLOGLEVEL: - value = model.solver()->messageHandler()->logLevel(); - break; - case CBC_PARAM_INT_MAXNODES: - value = model.getIntParam(CbcModel::CbcMaxNumNode); - break; - case CBC_PARAM_INT_STRONGBRANCHING: - value = model.numberStrong(); - break; - default: - abort(); - } - return value; +/* + Destructor +*/ +CbcParam::~CbcParam() { /* Nothing more to do */ } -/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +/* + Utility routine to save the current solution to a file. No formatting, and + not intended to be portable in any way, shape, or form. */ + + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 + */ diff --git a/src/CbcParam.hpp b/src/CbcParam.hpp index 2a16aa6e5..e24e11c7a 100644 --- a/src/CbcParam.hpp +++ b/src/CbcParam.hpp @@ -1,337 +1,385 @@ -// Copyright (C) 2002, International Business Machines -// Corporation and others. All Rights Reserved. -// This code is licensed under the terms of the Eclipse Public License (EPL). +/* + Copyright (C) 2007, Lou Hafer, International Business Machines Corporation + and others. All Rights Reserved. + + This code is licensed under the terms of the Eclipse Public License (EPL). + +*/ #ifndef CbcParam_H #define CbcParam_H -#include "OsiSolverInterface.hpp" -#include "CbcModel.hpp" -class ClpSimplex; -/*! \brief Parameter codes - - Parameter type ranges are allocated as follows -
    -
  • 1 -- 100 double parameters -
  • 101 -- 200 integer parameters -
  • 201 -- 250 string parameters -
  • 251 -- 300 cuts etc(string but broken out for clarity) -
  • 301 -- 400 `actions' -
- - `Actions' do not necessarily invoke an immediate action; it's just that they - don't fit neatly into the parameters array. - - This coding scheme is in flux. - CBC_PARAM_STR_NODESTRATEGY, - CBC_PARAM_STR_BRANCHSTRATEGY, - CBC_PARAM_NOTUSED_ADDCUTSSTRATEGY, - CLP_PARAM_ACTION_CLEARCUTS, - CBC_PARAM_NOTUSED_OSLSTUFF, - CBC_PARAM_NOTUSED_CBCSTUFF are not used at present (03.10.24). +#include "CoinParam.hpp" + +/* \file CbcParam.hpp + \brief Declarations for parameters that control the cbc-generic main + program. */ -enum CbcParameterType - -{ CBC_PARAM_GENERALQUERY = -100, - CBC_PARAM_FULLGENERALQUERY, - - CLP_PARAM_DBL_PRIMALTOLERANCE = 1, - CLP_PARAM_DBL_DUALTOLERANCE, - CBC_PARAM_DBL_CUTOFF, - CLP_PARAM_DBL_TIMELIMIT, - CLP_PARAM_DBL_DUALBOUND, - CLP_PARAM_DBL_PRIMALWEIGHT, - CLP_PARAM_DBL_OBJSCALE, - CLP_PARAM_DBL_RHSSCALE, - - CBC_PARAM_DBL_INFEASIBILITYWEIGHT = 51, - CBC_PARAM_DBL_INTEGERTOLERANCE, - CBC_PARAM_DBL_INCREMENT, - CBC_PARAM_DBL_ALLOWABLEGAP, - - CBC_PARAM_DBL_DJFIX = 81, - CBC_PARAM_DBL_GAPRATIO, - CBC_PARAM_DBL_TIGHTENFACTOR, - - CLP_PARAM_INT_LOGLEVEL = 101, - CLP_PARAM_INT_SOLVERLOGLEVEL, - CBC_PARAM_INT_MAXNODES, - CBC_PARAM_INT_STRONGBRANCHING, - CLP_PARAM_INT_MAXFACTOR, - CLP_PARAM_INT_PERTVALUE, - CLP_PARAM_INT_MAXITERATION, - CLP_PARAM_INT_PRESOLVEPASS, - CLP_PARAM_INT_IDIOT, - CLP_PARAM_INT_SPRINT, - CLP_PARAM_INT_OUTPUTFORMAT, - CLP_PARAM_INT_SLPVALUE, - CLP_PARAM_INT_PRESOLVEOPTIONS, - CLP_PARAM_INT_PRINTOPTIONS, - CLP_PARAM_INT_SPECIALOPTIONS, - - CLP_PARAM_STR_DIRECTION = 201, - CLP_PARAM_STR_DUALPIVOT, - CLP_PARAM_STR_SCALING, - CLP_PARAM_STR_ERRORSALLOWED, - CLP_PARAM_STR_KEEPNAMES, - CLP_PARAM_STR_SPARSEFACTOR, - CLP_PARAM_STR_PRIMALPIVOT, - CLP_PARAM_STR_PRESOLVE, - CLP_PARAM_STR_CRASH, - CLP_PARAM_STR_BIASLU, - CLP_PARAM_STR_PERTURBATION, - CLP_PARAM_STR_MESSAGES, - CLP_PARAM_STR_AUTOSCALE, - CLP_PARAM_STR_CHOLESKY, - CLP_PARAM_STR_KKT, - CLP_PARAM_STR_BARRIERSCALE, - CLP_PARAM_STR_GAMMA, - CLP_PARAM_STR_CROSSOVER, - CLP_PARAM_STR_PFI, - CLP_PARAM_NOTUSED_ALGORITHM, - - CBC_PARAM_STR_NODESTRATEGY = 251, - CBC_PARAM_STR_BRANCHSTRATEGY, - CBC_PARAM_NOTUSED_ADDCUTSSTRATEGY, - CBC_PARAM_STR_GOMORYCUTS, - CBC_PARAM_STR_PROBINGCUTS, - CBC_PARAM_STR_KNAPSACKCUTS, - CBC_PARAM_NOTUSED_ODDHOLECUTS, - CBC_PARAM_STR_ROUNDING, - CBC_PARAM_STR_SOLVER, - CBC_PARAM_STR_CLIQUECUTS, - CBC_PARAM_STR_COSTSTRATEGY, - CBC_PARAM_STR_FLOWCUTS, - CBC_PARAM_STR_MIXEDCUTS, - CBC_PARAM_STR_TWOMIRCUTS, - CBC_PARAM_STR_PREPROCESS, - - CLP_PARAM_ACTION_DIRECTORY = 301, - CLP_PARAM_ACTION_IMPORT, - CLP_PARAM_ACTION_EXPORT, - CLP_PARAM_ACTION_RESTORE, - CLP_PARAM_ACTION_SAVE, - CLP_PARAM_ACTION_DUALSIMPLEX, - CLP_PARAM_ACTION_PRIMALSIMPLEX, - CLP_PARAM_ACTION_MAXIMIZE, - CLP_PARAM_ACTION_MINIMIZE, - CLP_PARAM_ACTION_EXIT, - CLP_PARAM_ACTION_STDIN, - CLP_PARAM_ACTION_UNITTEST, - CLP_PARAM_ACTION_NETLIB_DUAL, - CLP_PARAM_ACTION_NETLIB_PRIMAL, - CLP_PARAM_ACTION_SOLUTION, - CLP_PARAM_ACTION_TIGHTEN, - CLP_PARAM_ACTION_FAKEBOUND, - CLP_PARAM_ACTION_HELP, - CLP_PARAM_ACTION_PLUSMINUS, - CLP_PARAM_ACTION_NETWORK, - CLP_PARAM_ACTION_ALLSLACK, - CLP_PARAM_ACTION_REVERSE, - CLP_PARAM_ACTION_BARRIER, - CLP_PARAM_ACTION_NETLIB_BARRIER, - CLP_PARAM_ACTION_REALLY_SCALE, - CLP_PARAM_ACTION_BASISIN, - CLP_PARAM_ACTION_BASISOUT, - CLP_PARAM_ACTION_SOLVECONTINUOUS, - CBC_PARAM_ACTION_BAB, - CBC_PARAM_ACTION_MIPLIB, - CLP_PARAM_ACTION_CLEARCUTS, - CLP_VERSION_NOTUSED_PRINTVERSION, - - CBC_PARAM_NOTUSED_OSLSTUFF = 401, - CBC_PARAM_NOTUSED_CBCSTUFF, - - CBC_PARAM_NOTUSED_INVALID = 1000 -}; +/* + */ + +class CbcModel; +class CbcParameters; -/// Very simple class for setting parameters +/*! \class CbcParam + \brief Class for cbc-generic control parameters -class CBCLIB_EXPORT CbcParam { + Adds parameter type codes and push/pull functions to the generic parameter + object. +*/ + +class CbcParam : public CoinParam { public: - /**@name Constructor and destructor */ + + /*! \name Enumeration types used to index parameters */ + //@{ + + /*! \brief Codes to specify psramters */ + + enum CbcParamCode { + FIRSTPARAM = 0, + + // Unused paramters that we may delete + FIRSTUNUSEDPARAM, + BRANCHSTRATEGY, + CLEARCUTS, + SOLVER, + LASTUNUSEDPARAM, + + // Help and Information Parameters + FIRSTHELPPARAM, + GENERALQUERY, + FULLGENERALQUERY, + HELP, + LASTHELPPARAM, + + // Action Parameters + FIRSTACTIONPARAM, + BAB, + DEBUG, + ENVIRONMENT, + END, + EXIT, + QUIT, + STOP, + EXPORT, + IMPORT, + MIPLIB, + OUTDUPROWS, + PRINTSOL, + PRINTVERSION, + READMIPSTART, + READPRIORITIES, + READSOL, + READMODEL, + READMODEL_OLD, // For backward compatibility + SHOWUNIMP, + SOLVECONTINUOUS, + STATISTICS, + STDIN, + STRENGTHEN, + UNITTEST, + WRITEGMPLSOL, + WRITEGMPLSOL_OLD, // For backward compatibility + WRITEMODEL, + WRITEMODEL_OLD, // For backward compatibility + WRITENEXTSOL, + WRITESOL, + WRITESOL_OLD, // For backward compatibility + WRITESOLBINARY, + WRITESOLBINARY_OLD, // For backward compatibility + WRITESTATS, + LASTACTIONPARAM, + + // File Parameters + FIRSTFILEPARAM, + CSVSTATSFILE, + DEBUGFILE, + EXPORTFILE, + IMPORTFILE, + GMPLSOLFILE, + MIPSTARTFILE, + MODELFILE, + NEXTSOLFILE, + PRIORITYFILE, + SOLUTIONFILE, + SOLUTIONBINARYFILE, + LASTFILEPARAM, + + // Directory Paramaters + FIRSTDIRECTORYPARAM, + DIRECTORY, + DIRSAMPLE, + DIRNETLIB, + DIRMIPLIB, + LASTDIRECTORYPARAM, + + // String Parameters + FIRSTSTRINGPARAM, + PRINTMASK, + LASTSTRINGPARAM, + + // Cut Parameters + FIRSTCUTPARAM, + CLIQUECUTS, + CUTSTRATEGY, + FLOWCUTS, + GMICUTS, + GOMORYCUTS, + KNAPSACKCUTS, + LAGOMORYCUTS, + LANDPCUTS, + LATWOMIRCUTS, + MIRCUTS, + //ODDHOLECUTS, // Not used + ODDWHEELCUTS, + PROBINGCUTS, + REDSPLITCUTS, + REDSPLIT2CUTS, + RESIDCAPCUTS, + TWOMIRCUTS, + ZEROHALFCUTS, + LASTCUTPARAM, + + // Heuristic Parameters + FIRSTHEURPARAM, + COMBINE, + CROSSOVER, + DINS, + DIVINGC, + DIVINGF, + DIVINGG, + DIVINGL, + DIVINGP, + DIVINGS, + DIVINGV, + DW, + FPUMP, + GREEDY, + HEURISTICSTRATEGY, + LOCALTREE, + NAIVE, + PIVOTANDFIX, + PIVOTANDCOMPLEMENT, + PROXIMITY, + RANDROUND, + RENS, + RINS, + ROUNDING, + VND, + LASTHEURPARAM, + + // On/Off Parameters + FIRSTBOOLPARAM, + CPX, + DOHEURISTIC, + ERRORSALLOWED, + MESSAGES, + PREPROCNAMES, + SOS, + USESOLUTION, + LASTBOOLPARAM, + + // Keyword Parameters + FIRSTKWDPARAM, + COMMANDPRINTLEVEL, + CLQSTRENGTHENING, + BRANCHPRIORITY, + CUTOFFCONSTRAINT, + INTPRINT, + NODESTRATEGY, + ORBITAL, + PREPROCESS, + SOSPRIORITIZE, + STRATEGY, + TIMEMODE, + USECGRAPH, + LASTKWDPARAM, + + // Integer Parameters + FIRSTINTPARAM, + BKPIVOTINGSTRATEGY, + BKMAXCALLS, + BKCLQEXTMETHOD, + CPP, + CUTDEPTH, + CUTLENGTH, + CUTPASSINTREE, + DEPTHMINIBAB, + DIVEOPT, + DIVEOPTSOLVES, + DUMMY, + EXPERIMENT, + EXTRA1, + EXTRA2, + EXTRA3, + EXTRA4, + EXTRAVARIABLES, + FPUMPITS, + FPUMPTUNE, + FPUMPTUNE2, + HEUROPTIONS, + LOGLEVEL, + LPLOGLEVEL, + MAXHOTITS, + MAXSAVEDSOLS, + MAXSLOWCUTS, + MOREMOREMIPOPTIONS, + MULTIPLEROOTS, + ODDWEXTMETHOD, + OUTPUTFORMAT, + PRINTOPTIONS, + PROCESSTUNE, + RANDOMSEED, + STRONGSTRATEGY, + TESTOSI, + THREADS, + USERCBC, + VERBOSE, + VUBTRY, + LASTINTPARAM, + + // Double Parameters + FIRSTDBLPARAM, + ARTIFICIALCOST, + DEXTRA3, + DEXTRA4, + DEXTRA5, + DJFIX, + FAKECUTOFF, + FAKEINCREMENT, + SMALLBAB, + TIGHTENFACTOR, + LASTDBLPARAM, + + FIRSTMODELPARAM, + ALLOWABLEGAP, + COSTSTRATEGY, + //CUTDEPTH, + CUTOFF, + CUTPASS, + DIRECTION, + GAPRATIO, + INCREMENT, + INFEASIBILITYWEIGHT, + INTEGERTOLERANCE, + //LOGLEVEL, + MAXIMIZE, + MAXNODES, + MAXNODESNOTIMPROVING, // Added + MAXSECONDSNOTIMPROVING, // Added + MAXSOLS, // Added + MINIMIZE, + MIPOPTIONS, + MOREMIPOPTIONS, + NUMBERANALYZE, + NUMBERBEFORE, + REVERSE, + STRONGBRANCHING, + TIMELIMIT, + LASTMODELPARAM, + + INVALID, + + LASTPARAM + }; + + //@} + + /*! \name Constructors and Destructors + + Be careful how you specify parameters for the constructors! There's great + potential for confusion. + */ //@{ - /// Constructors + /*! \brief Default constructor */ + CbcParam(); - CbcParam(std::string name, std::string help, - double lower, double upper, CbcParameterType type, bool display = true); - CbcParam(std::string name, std::string help, - int lower, int upper, CbcParameterType type, bool display = true); - // Other strings will be added by insert - CbcParam(std::string name, std::string help, std::string firstValue, - CbcParameterType type, int defaultIndex = 0, bool display = true); - // Action - CbcParam(std::string name, std::string help, - CbcParameterType type, int indexNumber = -1, bool display = true); - /// Copy constructor. - CbcParam(const CbcParam &); - /// Assignment operator. This copies the data + + /*! \brief Constructor for a parameter with a double value + + The default value is 0.0. Be careful to clearly indicate that \p lower and + \p upper are real (double) values to distinguish this constructor from the + constructor for an integer parameter. + */ + CbcParam(int code, std::string name, std::string help, + double lower = -COIN_DBL_MAX, double upper = COIN_DBL_MAX, + std::string longHelp = "", + CoinDisplayPriority display = displayPriorityHigh); + + /*! \brief Constructor for a parameter with an integer value + + The default value is 0. + */ + CbcParam(int code, std::string name, std::string help, + int lower = -COIN_INT_MAX, int upper = COIN_INT_MAX, + std::string longHelp = "", + CoinDisplayPriority display = displayPriorityHigh); + + /*! \brief Constructor for a parameter with string values (or no value) + Type is not optional to resolve ambiguity. + + The default value is "" for all such parameter types + */ + CbcParam(int code, std::string name, CoinParam::CoinParamType type, + std::string help, std::string longHelp = "", + CoinDisplayPriority displayPriority = CoinParam::displayPriorityHigh); + /*! \brief Copy constructor */ + CbcParam(const CbcParam &orig); + + /*! \brief Clone */ + CbcParam *clone(); + + /*! \brief Assignment */ CbcParam &operator=(const CbcParam &rhs); - /// Destructor + + /*! \brief Destructor */ ~CbcParam(); + //@} - /**@name stuff */ + /*! \name Methods to query and manipulate a parameter object */ //@{ - /// Insert string (only valid for keywords) - void append(std::string keyWord); - /// Adds one help line - void addHelp(std::string keyWord); - /// Returns name - inline std::string name() const - { - return name_; - }; - /// Returns short help - inline std::string shortHelp() const - { - return shortHelp_; - }; - /// Sets a double parameter (nonzero code if error) - int setDoubleParameter(CbcModel &model, double value) const; - /// Gets a double parameter - double doubleParameter(CbcModel &model) const; - /// Sets a int parameter (nonzero code if error) - int setIntParameter(CbcModel &model, int value) const; - /// Gets a int parameter - int intParameter(CbcModel &model) const; - /// Sets a double parameter (nonzero code if error) - int setDoubleParameter(ClpSimplex *model, double value) const; - /// Gets a double parameter - double doubleParameter(ClpSimplex *model) const; - /// Sets a int parameter (nonzero code if error) - int setIntParameter(ClpSimplex *model, int value) const; - /// Gets a int parameter - int intParameter(ClpSimplex *model) const; - /// Sets a double parameter (nonzero code if error) - int setDoubleParameter(OsiSolverInterface *model, double value) const; - /// Gets a double parameter - double doubleParameter(OsiSolverInterface *model) const; - /// Sets a int parameter (nonzero code if error) - int setIntParameter(OsiSolverInterface *model, int value) const; - /// Gets a int parameter - int intParameter(OsiSolverInterface *model) const; - /// Checks a double parameter (nonzero code if error) - int checkDoubleParameter(double value) const; - /// Returns name which could match - std::string matchName() const; - /// Returns parameter option which matches (-1 if none) - int parameterOption(std::string check) const; - /// Prints parameter options - void printOptions() const; - /// Returns current parameter option - inline std::string currentOption() const - { - return definedKeyWords_[currentKeyWord_]; - } - /// Sets current parameter option - inline void setCurrentOption(int value) - { - currentKeyWord_ = value; - } - /// Sets int value - inline void setIntValue(int value) - { - intValue_ = value; - } - inline int intValue() const - { - return intValue_; - } - /// Sets double value - inline void setDoubleValue(double value) - { - doubleValue_ = value; - } - inline double doubleValue() const - { - return doubleValue_; - } - /// Sets string value - inline void setStringValue(std::string value) - { - stringValue_ = value; - } - inline std::string stringValue() const - { - return stringValue_; - } - /// Returns 1 if matches minimum, 2 if matches less, 0 if not matched - int matches(std::string input) const; - /// type - inline CbcParameterType type() const - { - return type_; - } - /// whether to display - inline bool displayThis() const - { - return display_; - } - /// Set Long help - inline void setLonghelp(const std::string help) - { - longHelp_ = help; - } - /// Print Long help - void printLongHelp() const; - /// Print action and string - void printString() const; - /// type for classification - inline int indexNumber() const - { - return indexNumber_; - } + + /*! \brief Get the parameter code */ + inline int paramCode() const { return (paramCode_); } + + /*! \brief Set the parameter code */ + inline void setParamCode(int code) { paramCode_ = code; } + + /*! \brief Get the associated Cbc parameters object */ + inline CbcParameters *parameters() const { return (parameters_); } + + /*! \brief Set the associated Cbc parameters object */ + inline void setParameters(CbcParameters *s) { parameters_ = s; } + + /*! \brief Get the associated model */ + inline CbcModel *model() const { return (model_); } + + /*! \brief Set the associated Cbc model object */ + inline void setModel(CbcModel *m) { model_ = m; } + +//@} private: - /// gutsOfConstructor - void gutsOfConstructor(); - //@} - ////////////////// data ////////////////// -private: - /**@name data - We might as well throw all type data in - could derive? - */ + /*! \name Data */ //@{ - // Type see CbcParameterType - CbcParameterType type_; - /// If double == okay - double lowerDoubleValue_; - double upperDoubleValue_; - /// If int == okay - int lowerIntValue_; - int upperIntValue_; - // Length of name - unsigned int lengthName_; - // Minimum match - unsigned int lengthMatch_; - /// set of valid strings - std::vector< std::string > definedKeyWords_; - /// Name - std::string name_; - /// Short help - std::string shortHelp_; - /// Long help - std::string longHelp_; - /// Action - CbcParameterType action_; - /// Current keyWord (if a keyword parameter) - int currentKeyWord_; - /// Display on ? - bool display_; - /// Integer parameter - current value - int intValue_; - /// Double parameter - current value - double doubleValue_; - /// String parameter - current value - std::string stringValue_; - /// index number to use for display purposes - int indexNumber_; + + /// Parameter code + int paramCode_; + + /// Pointer to enclosing parameters object + CbcParameters *parameters_; + + /// Pointer to model object + CbcModel * model_; + //@} }; -#endif /* CbcParam_H */ + +#endif /* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 -*/ + */ diff --git a/src/CbcParamUtils.cpp b/src/CbcParamUtils.cpp new file mode 100644 index 000000000..2a1872727 --- /dev/null +++ b/src/CbcParamUtils.cpp @@ -0,0 +1,1312 @@ +/* + Copyright (C) 2007, Lou Hafer, International Business Machines Corporation + and others. All Rights Reserved. + + This code is licensed under the terms of the Eclipse Public License (EPL). + +*/ + +#if defined(_MSC_VER) +// Turn off compiler warning about long names +#pragma warning(disable : 4786) +#endif + +#include +#include +#include + +#include "CoinUtilsConfig.h" + +#include "CoinParam.hpp" +#include "CoinFileIO.hpp" +#include "CoinFinite.hpp" + +#include "CbcModel.hpp" + +#include "CbcParam.hpp" +#include "CbcParamUtils.hpp" +#include "CbcParameters.hpp" + +namespace CbcParamUtils { + +//########################################################################### +//########################################################################### + +/* Functions to perform actions related to setting parameters */ + +/* + Maintainer's utility, scan the parameters and report the ones that are + unimplemented (i.e., have no pushFunc). +*/ + +int doUnimplementedParam(CoinParam ¶m) + +{ + CbcParam &cbcParam = dynamic_cast(param); + CbcParameters parameters = *cbcParam.parameters(); + + int unimpCnt = 0; + int maxAcross = 5; + for (int code = CbcParam::FIRSTPARAM + 1; + code < CbcParam::LASTPARAM; code++) { + if (parameters[code]->pushFunc() == 0) { + if (unimpCnt % maxAcross == 0) { + std::cout << std::endl; + } else { + std::cout << " "; + } + std::cout << parameters[code]->name(); + unimpCnt++; + } + } + if (unimpCnt % maxAcross != 1) { + std::cout << std::endl; + } + std::cout << unimpCnt << " unimplemented parameters." << std::endl; + + return (0); +} + +//########################################################################### +//########################################################################### + +/* + Noop function. Mainly to eliminate commands from the list returned by + doUnimplmentedParam. +*/ + +int doNothingParam(CoinParam ¶m) { return (0); } + +/* + Function to terminate command parsing by returning -1. +*/ + +int doExitParam(CoinParam ¶m) + +{ + return (-1); +} + +//########################################################################### +//########################################################################### + +/* + Function to print the current version. +*/ + +int doVersionParam(CoinParam ¶m) + +{ + CbcParam &cbcParam = dynamic_cast(param); + CbcParameters *parameters = cbcParam.parameters(); + assert(parameters != 0); + + std::cout << "Cbc version " << parameters->getVersion() << std::endl; + + return (0); +} + +//########################################################################### +//########################################################################### + +/* + Function to handle help (HELP), `?' (GENERALQUERY), and `???' + (FULLGENERALQUERY). +*/ + +int doHelpParam(CoinParam ¶m) + +{ + CbcParam &cbcParam = dynamic_cast(param); + CbcParameters *parameters = cbcParam.parameters(); + assert(parameters != 0); + + int cbcParamCode = cbcParam.paramCode(); + + int verbose = parameters->getVerbose(); + bool shortHelp = ((verbose & 0x01) ? true : false); + bool longHelp = ((verbose & 0x02) ? true : false); + bool hidden = ((verbose & 0x08) ? true : false); + + CoinParamVec ¶mVec = parameters->paramVec(); + /* + Tune up the initial parameters. FULLGENERALQUERY will print normally + hidden params, and a request for long help overrules a request for short + help. + */ + if (cbcParamCode == CbcParam::FULLGENERALQUERY) { + hidden = true; + } + if (longHelp) { + shortHelp = false; + } + + CoinParamUtils::printGenericHelp(); + + std::cout << "\nAvailable commands are:"; + std::string pfx(" "); + CoinParamUtils::printHelp(paramVec, 0, paramVec.size() - 1, + pfx, shortHelp, longHelp, hidden); + + return (0); +} + +//########################################################################### +//########################################################################### + +/* + Function to push a double-valued parameter. +*/ + +int pushCbcSolverDblParam(CoinParam ¶m) + +{ + CbcParam &cbcParam = dynamic_cast(param); + CbcParameters *parameters = cbcParam.parameters(); + assert(parameters != 0); + + double val = cbcParam.dblVal(); + int cbcParamCode = cbcParam.paramCode(); + + int retval = 0; + /* + Figure out what we're doing and set the relevant field. + */ + switch (cbcParamCode) { + case CbcParam::ARTIFICIALCOST: { + parameters->setArtVarMode(CbcParameters::ParamOn, val); + break; + } + case CbcParam::DEXTRA3: { + parameters->setExtraDbl3(val); + break; + } + case CbcParam::DEXTRA4: { + parameters->setExtraDbl4(val); + break; + } + case CbcParam::DEXTRA5: { + parameters->setExtraDbl5(val); + break; + } + case CbcParam::DJFIX: { + parameters->setDjFixMode(CbcParameters::ParamOn, val); + break; + } + case CbcParam::FAKECUTOFF: { + parameters->setFeasPumpFakeCutoff(val); + break; + } + case CbcParam::FAKEINCREMENT: { + parameters->setFeasPumpFakeIncrement(val); + break; + } + case CbcParam::SMALLBAB: { + parameters->setSmallBab(val); + break; + } + case CbcParam::TIGHTENFACTOR: { + parameters->setTightenFactor(val); + break; + } + + default: { + std::cerr << "pushCbcSolverDbl: no equivalent CbcParameters field for " + << "parameter code `" << cbcParamCode << "'." << std::endl; + retval = -1; + break; + } + } + + return (retval); +} + +//########################################################################### +//########################################################################### + +/* + Function to push an integer-valued parameter. +*/ + +int pushCbcSolverIntParam(CoinParam ¶m) +{ + CbcParam &cbcParam = dynamic_cast(param); + CbcParameters *parameters = cbcParam.parameters(); + assert(parameters != 0); + + int val = cbcParam.intVal(); + int cbcParamCode = cbcParam.paramCode(); + + int retval = 0; + /* + Figure out what we're doing and set the relevant field. + */ + switch (cbcParamCode) { + case CbcParam::BKPIVOTINGSTRATEGY: { + parameters->setBkPivotStrategy(val); + break; + } + case CbcParam::BKMAXCALLS: { + parameters->setBkMaxCalls(val); + break; + } + case CbcParam::BKCLQEXTMETHOD: { + parameters->setBkClqExtMethod(val); + break; + } + case CbcParam::CPP: { + parameters->setCppMode(val); + break; + } + case CbcParam::CUTDEPTH: { + parameters->setCutDepth(val); + break; + } + case CbcParam::CUTLENGTH: { + parameters->setCutLength(val); + break; + } + case CbcParam::CUTPASSINTREE: { + parameters->setCutPassInTree(val); + break; + } + case CbcParam::DEPTHMINIBAB: { + parameters->setDepthMiniBaB(val); + break; + } + case CbcParam::DIVEOPT: { + parameters->setDiveOpt(val); + break; + } + case CbcParam::DIVEOPTSOLVES: { + parameters->setDiveOptSolves(val); + break; + } + case CbcParam::EXPERIMENT: { + parameters->setExperimentMode(val); + break; + } + case CbcParam::EXTRA1: { + parameters->setExtraIntParam1(val); + break; + } + case CbcParam::EXTRA2: { + parameters->setExtraIntParam2(val); + break; + } + case CbcParam::EXTRA3: { + parameters->setExtraIntParam3(val); + break; + } + case CbcParam::EXTRA4: { + parameters->setExtraIntParam4(val); + break; + } + case CbcParam::FPUMPITS: { + parameters->setFeasPumpIters(val); + break; + } + case CbcParam::FPUMPTUNE: { + parameters->setFeasPumpTune(val); + break; + } + case CbcParam::FPUMPTUNE2: { + parameters->setFeasPumpTune2(val); + break; + } + case CbcParam::HEUROPTIONS: { + parameters->setHeurOptions(val); + break; + } + case CbcParam::LOGLEVEL: { + parameters->setLogLevel(val); + break; + } + case CbcParam::LPLOGLEVEL: { + parameters->setLpLogLevel(val); + break; + } + case CbcParam::MAXSAVEDSOLS: { + parameters->setMaxSavedSols(val); + break; + } + case CbcParam::MAXSLOWCUTS: { + parameters->setMaxSlowCuts(val); + break; + } + case CbcParam::MOREMOREMIPOPTIONS: { + parameters->setMoreMoreOptions(val); + break; + } + case CbcParam::MULTIPLEROOTS: { + parameters->setMultipleRoots(val); + break; + } + case CbcParam::ODDWEXTMETHOD: { + parameters->setOddWextMethod(val); + break; + } + case CbcParam::OUTPUTFORMAT: { + parameters->setOutputFormat(val); + break; + } + case CbcParam::PRINTOPTIONS: { + parameters->setPrintOptions(val); + break; + } + case CbcParam::PROCESSTUNE: { + parameters->setProcessTune(val); + break; + } + case CbcParam::RANDOMSEED: { + parameters->setRandomSeed(val); + break; + } + case CbcParam::STRONGSTRATEGY: { + parameters->setStrongStrategy(val); + break; + } + case CbcParam::TESTOSI: { + parameters->setTestOsi(val); + break; + } +#ifdef CBC_THREADS + case CbcParam::THREADS: { + parameters->setThreads(val); + break; + } +#endif + case CbcParam::USERCBC: { + parameters->setUserCbc(val); + break; + } + case CbcParam::VERBOSE: { + parameters->setVerbose(val); + break; + } + case CbcParam::VUBTRY: { + parameters->setVubTry(val); + break; + } + default: { + std::cerr << "pushCbcSolverInt: no method for storing " + << "parameter code `" << cbcParamCode << "'." << std::endl; + retval = -1; + break; + } + } + + return (retval); +} + +//########################################################################### +//########################################################################### + +/* + Function to push a keyword-valued parameter. This is the catch-all function + for keyword parameters that don't belong to any other useful grouping. +*/ + +int pushCbcSolverKwdParam(CoinParam ¶m) { + CbcParam &cbcParam = dynamic_cast(param); + CbcParameters *parameters = cbcParam.parameters(); + assert(parameters != 0); + + int mode = cbcParam.modeVal(); + int cbcParamCode = cbcParam.paramCode(); + + int retval = 0; + /* + Figure out what we're doing and set the relevant field. + */ + + switch (cbcParamCode) { + case CbcParam::COMMANDPRINTLEVEL: { + parameters->setCommandDisplayMode( + static_cast(mode)); + break; + } + case CbcParam::CLQSTRENGTHENING: { + parameters->setClqStrMode(static_cast(mode)); + break; + } + case CbcParam::BRANCHPRIORITY: { + parameters->setBranchingPriorityMode(CbcParameters::BPOff); + break; + } + case CbcParam::CUTOFFCONSTRAINT: { + parameters->setCutoffMode(static_cast(mode)); + break; + } + case CbcParam::INTPRINT: { + parameters->setIntPrintMode( + static_cast(mode)); + break; + } + case CbcParam::NODESTRATEGY: { + parameters->setNodeStrategy( + static_cast(mode)); + break; + } + case CbcParam::ORBITAL: { + parameters->setOrbitalStrategy( + static_cast(mode)); + break; + } + case CbcParam::PREPROCESS: { + parameters->setIPPMode(static_cast(mode)); + break; + } + case CbcParam::SOSPRIORITIZE: { + parameters->setSOSStrategy(static_cast(mode)); + break; + } + case CbcParam::STRATEGY: { + parameters->setStrategyMode( + static_cast(mode)); + break; + } + case CbcParam::TIMEMODE: { + parameters->setClockType(static_cast(mode)); + break; + } + case CbcParam::USECGRAPH: { + parameters->setCGraphMode(static_cast(mode)); + break; + } + default: + break; + } + + return (retval); +} + +//########################################################################### +//########################################################################### + +/* + Function to push a bool-valued parameter. These are really just keyword + parameters that take values "on" and "off" + +*/ + +int pushCbcSolverBoolParam(CoinParam ¶m) { + CbcParam &cbcParam = dynamic_cast(param); + CbcParameters *parameters = cbcParam.parameters(); + assert(parameters != 0); + + // This is ugly, get keyword and set parameter with it instead. + CbcParameters::OnOffMode mode = + static_cast(cbcParam.modeVal()); + int cbcParamCode = cbcParam.paramCode(); + + int retval = 0; + + switch (cbcParamCode) { + case CbcParam::CPX: { + parameters->setCPXMode(mode); + break; + } + case CbcParam::DOHEURISTIC: { + parameters->setDoHeuristicMode(mode); + break; + } + case CbcParam::ERRORSALLOWED: { + parameters->setImportErrorsMode(mode); + break; + } + case CbcParam::MESSAGES: { + parameters->setMessagePrefixMode(mode); + break; + } + case CbcParam::PREPROCNAMES: { + parameters->setPreProcNamesMode(mode); + break; + } + case CbcParam::SOS: { + parameters->setSOSMode(mode); + break; + } + case CbcParam::USESOLUTION: { + parameters->setUseSolutionMode(mode); + break; + } + default: + break; + } + + return (retval); +} + +//########################################################################### +//########################################################################### + +/* + Function to push a keyword-valued parameter related to heuristics. +*/ + +int pushCbcSolverHeurParam(CoinParam ¶m) { + CbcParam &cbcParam = dynamic_cast(param); + CbcParameters *parameters = cbcParam.parameters(); + assert(parameters != 0); + + // This is ugly, get keyword and set parameter with it instead. + CbcParameters::HeurMode mode = + static_cast(cbcParam.modeVal()); + int cbcParamCode = cbcParam.paramCode(); + + int retval = 0; + + /* + We've done the basic checks; go ahead and set the relevant field in the + control block. We shouldn't need the default case, but some compilers will + complain if it's missing. + */ + switch (cbcParamCode) { + case CbcParam::HEURISTICSTRATEGY: { + parameters->setGreedyCoverMode(mode); + parameters->setGreedyEqualityMode(mode); + parameters->setCrossoverMode(mode); + parameters->setDinsMode(mode); + parameters->setDiveCoefficientMode(mode); + parameters->setDiveFractionalMode(mode); + parameters->setDiveGuidedMode(mode); + parameters->setDiveLineSearchMode(mode); + parameters->setDivePseudocostMode(mode); + parameters->setDiveVectorLengthMode(mode); + parameters->setDWMode(mode); + parameters->setNaiveHeurMode(mode); + parameters->setPivotAndFixMode(mode); +#if 0 + parameters->setPivotAndComplementMode(mode); +#endif + parameters->setProximityMode(mode); + parameters->setRandRoundMode(mode); + parameters->setRensMode(mode); + parameters->setRinsMode(mode); + parameters->setRoundingMode(mode); + parameters->setVndMode(mode); + break; + } + case CbcParam::COMBINE: { + parameters->setCombineMode(mode); + break; + } + case CbcParam::CROSSOVER: { + parameters->setCrossoverMode(mode); + break; + } + case CbcParam::DINS: { + parameters->setDinsMode(mode); + break; + } + case CbcParam::DIVINGC: { + parameters->setDiveCoefficientMode(mode); + break; + } + case CbcParam::DIVINGF: { + parameters->setDiveFractionalMode(mode); + break; + } + case CbcParam::DIVINGG: { + parameters->setDiveGuidedMode(mode); + break; + } + case CbcParam::DIVINGL: { + parameters->setDiveLineSearchMode(mode); + break; + } + case CbcParam::DIVINGP: { + parameters->setDivePseudocostMode(mode); + break; + } + case CbcParam::DIVINGS: { + parameters->setDiveRandomMode(mode); + break; + } + case CbcParam::DIVINGV: { + parameters->setDiveVectorLengthMode(mode); + break; + } + case CbcParam::DW: { + parameters->setDWMode(mode); + break; + } + case CbcParam::FPUMP: { + parameters->setFeasPumpMode(mode); + break; + } + case CbcParam::GREEDY: { + parameters->setGreedyCoverMode(mode); + parameters->setGreedyEqualityMode(mode); + break; + } + case CbcParam::NAIVE: { + parameters->setNaiveHeurMode(mode); + break; + } + case CbcParam::PIVOTANDFIX: { + parameters->setPivotAndFixMode(mode); + break; + } +#if 0 + case CbcParam::PIVOTANDCOMPLEMENT: { + parameters->setPivotAndComplementMode(mode); + break; + } +#endif + case CbcParam::PROXIMITY: { + parameters->setProximityMode(mode); + break; + } + case CbcParam::RANDROUND: { + parameters->setRandRoundMode(mode); + break; + } + case CbcParam::RENS: { + parameters->setRensMode(mode); + break; + } + case CbcParam::RINS: { + parameters->setRinsMode(mode); + break; + } + case CbcParam::ROUNDING: { + parameters->setRoundingMode(mode); + break; + } + case CbcParam::VND: { + parameters->setVndMode(mode); + break; + } + default: + break; + } + + return (retval); +} + +//########################################################################### +//########################################################################### + +/* + Function to push a string-valued parameter +*/ + +int pushCbcSolverStrParam(CoinParam ¶m) + +{ + CbcParam &cbcParam = dynamic_cast(param); + CbcParameters *parameters = cbcParam.parameters(); + assert(parameters != 0); + + std::string str = cbcParam.strVal(); + int cbcParamCode = cbcParam.paramCode(); + + int retval = 0; + /* + Figure out what we're doing and set the relevant field. + */ + switch (cbcParamCode) { + case CbcParam::DIRECTORY: { + char dirSep = CoinFindDirSeparator(); + if (str[str.length() - 1] != dirSep) { + str += dirSep; + } + parameters->setDefaultDirectory(str); + break; + } + default: { + std::cerr << "pushCbcSolverStr: no equivalent CbcParameters field for " + << "parameter code `" << cbcParamCode << "'." << std::endl; + retval = -1; + break; + } + } + + return (retval); +} + +//########################################################################### +//########################################################################### + +/* + The various parameters to control cut generators can be + grouped, as they all use the same set of keywords. +*/ +int pushCbcSolverCutParam(CoinParam ¶m) + +{ + CbcParam &cbcParam = dynamic_cast(param); + CbcParameters *parameters = cbcParam.parameters(); + assert(parameters != 0); + + CbcParameters::CGMode mode = + static_cast(cbcParam.modeVal()); + int cbcParamCode = cbcParam.paramCode(); + /* + Setup to return nonfatal/fatal error (1/-1) by default, so that all we + need to do is correct to 0 (no error) if we're successful. + */ + int retval; + + //if (CoinParamUtils::isInteractive()) { + // retval = 1; + //} else { + retval = -1; + //} + + /* + We've done the basic checks; go ahead and set the relevant field in the + control block. We shouldn't need the default case, but some compilers will + complain if it's missing. + */ + switch (cbcParamCode) { + case CbcParam::CLIQUECUTS: { + parameters->setCliqueMode(mode); + break; + } + case CbcParam::FLOWCUTS: { + parameters->setFlowMode(mode); + break; + } + case CbcParam::GMICUTS: { + parameters->setGMIMode(mode); + break; + } + case CbcParam::GOMORYCUTS: { + parameters->setGomoryMode(mode); + break; + } + case CbcParam::KNAPSACKCUTS: { + parameters->setKnapsackMode(mode); + break; + } + case CbcParam::LAGOMORYCUTS: { + parameters->setLaGomoryMode(mode); + break; + } + case CbcParam::LANDPCUTS: { + parameters->setLandPMode(mode); + break; + } + case CbcParam::LATWOMIRCUTS: { + parameters->setLaTwomirMode(mode); + break; + } + case CbcParam::MIRCUTS: { + parameters->setMirMode(mode); + break; + } + case CbcParam::ODDWHEELCUTS: { + parameters->setOddWheelMode(mode); + break; + } + case CbcParam::PROBINGCUTS: { + parameters->setProbingMode(mode); + break; + } + case CbcParam::REDSPLITCUTS: { + parameters->setRedSplitMode(mode); + break; + } + case CbcParam::REDSPLIT2CUTS: { + parameters->setRedSplit2Mode(mode); + break; + } + case CbcParam::RESIDCAPCUTS: { + parameters->setResidCapMode(mode); + break; + } + case CbcParam::TWOMIRCUTS: { + parameters->setTwomirMode(mode); + break; + } + case CbcParam::ZEROHALFCUTS: { + parameters->setZeroHalfMode(mode); + break; + } + case CbcParam::CUTSTRATEGY: { + parameters->setCliqueMode(mode); + parameters->setFlowMode(mode); + parameters->setGMIMode(mode); + parameters->setGomoryMode(mode); + parameters->setKnapsackMode(mode); + parameters->setLaGomoryMode(mode); + parameters->setLandPMode(mode); + parameters->setLaTwomirMode(mode); + parameters->setMirMode(mode); + parameters->setOddWheelMode(mode); + parameters->setProbingMode(mode); + parameters->setRedSplitMode(mode); + parameters->setRedSplit2Mode(mode); + parameters->setRedSplit2Mode(mode); + parameters->setTwomirMode(mode); + parameters->setZeroHalfMode(mode); + break; + } + default: + break; + } + + return (0); +} + +//########################################################################### +//########################################################################### + +/* + This routine imports a new constraint system into the solver. +*/ + +int doImportParam(CoinParam ¶m) + +{ + CbcParam &cbcParam = dynamic_cast(param); + CbcParameters *parameters = cbcParam.parameters(); + assert(parameters != 0); + /* + Setup to return nonfatal/fatal error (1/-1) by default, so that all we + need to do is correct to 0 (no error) if we're successful. + */ + int retval; + //if (CoinParamUtils::isInteractive()) { + // retval = 1; + //} else { + retval = -1; + //} + /* + Figure out where we're going to acquire this new model. As special cases, + `$' says `use the previous input source' and `-' says `use stdin'. + */ + std::string field = cbcParam.strVal(); + std::string fileName; + if (field == "$") { + fileName = parameters->getLastMpsIn(); + field = fileName; + } else if (field == "-") { + fileName = "stdin"; + field = fileName; + } else { + fileName = field; + } + /* + See if we can open a file. fileCoinReadable understands a fair bit about + platforms and compressed files and will try variations of the file name + (see the doxygen doc'n for details). The file name returned in field wil + be the one that actually worked. + */ + bool canOpen = fileCoinReadable(fileName, parameters->getDefaultDirectory()); + if (canOpen == false) { + std::cout << "Unable to open file `" << fileName << "', original name '" + << cbcParam.strVal() << "'." << std::endl; + return (retval); + } + /* + We can find the file. Record the name. This requires a little finesse: + what we want is the base file name (and extension(s), if present) but not + the prefix, unless it's an absolute path. + */ + if (!fileAbsPath(fileName)) { + std::string::size_type pos = fileName.rfind(field); + parameters->setLastMpsIn(fileName.substr(pos)); + } else { + parameters->setLastMpsIn(fileName); + } + /* + Try to read the file. Standard OSI doesn't support the Clp extensions for + keepImportNames and allowImportErrors. It should at least support + keepImportNames. Status will be zero for a successful read. + */ + OsiSolverInterface *lpSolver = parameters->getModel()->solver(); + int status = lpSolver->readMps(fileName.c_str(), ""); + if (status) { + std::cout << "There were " << status << " errors on input." << std::endl; + return (retval); + } + /* + We have a model! Return success. + */ + parameters->setGoodModel(true); + + return (0); +} + +//########################################################################### +//########################################################################### + +/* + This routine imports a debug file into the solver, or arranges for its + creation. Import works in the standard way, using the file name provided + with the command. + + As special cases, if the file name is `create' or `createAfterPre', the + action here sets up to cause a debug file containing the solution to be + dumped after branch-and-cut is completed. `createAfterPre' will dump the + solution before undoing the presolve transforms. `create' will dump the + solution after integer presolve is backed out. +*/ + +int doDebugParam(CoinParam ¶m) + +{ + CbcParam &cbcParam = dynamic_cast(param); + CbcParameters *parameters = cbcParam.parameters(); + assert(parameters != 0); + /* + Setup to return nonfatal/fatal error (1/-1) by default, so that all we + need to do is correct to 0 (no error) if we're successful. + */ + int retval; + //if (CoinParamUtils::isInteractive()) { + // retval = 1; + //} else { + retval = -1; + //} + /* + If the file name is `create' or `createAfterPre', we're just setting up + to make a debug file the next time we do branch-and-cut. + */ + std::string field = cbcParam.strVal(); + if (field == "create" || field == "createAfterPre") { + parameters->setDebugCreate(field); + return (0); + } + /* + Figure out where we're going to acquire the debug file. As special cases, + `$' says `use the previous input source' and `-' says `use stdin'. + */ + std::string fileName; + if (field == "$") { + fileName = parameters->getDebugFile(); + field = fileName; + } else if (field == "-") { + fileName = "stdin"; + field = fileName; + } else { + fileName = field; + } + /* + See if we can open a file. fileCoinReadable understands a fair bit about + platforms and compressed files and will try variations of the file name + (see the doxygen doc'n for details). The file name returned in field wil + be the one that actually worked. No default prefix --- a debug file is + assumed to always be in the current directory. + */ + bool canOpen = fileCoinReadable(fileName, parameters->getDefaultDirectory()); + if (canOpen == false) { + std::cout << "Unable to open file `" << fileName << "', original name '" + << cbcParam.strVal() << "'." << std::endl; + return (retval); + } + /* + We can find the file. Record the name. This requires a little finesse: + what we want is the base file name (and extension(s), if present) but not + the prefix, unless it's an absolute path. + */ + if (!fileAbsPath(fileName)) { + std::string::size_type pos = fileName.rfind(field); + parameters->setLastMpsIn(fileName.substr(pos)); + } else { + parameters->setLastMpsIn(fileName); + } + /* + Load the primal variable values into the debug solution vector. + */ + int intUnused, numCols; + double dblUnused; + double *primals; + + bool readOK = readSolution(fileName, intUnused, numCols, + dblUnused, 0, 0, &primals, 0); + + if (readOK) { + parameters->setDebugSol(numCols, primals); + } else { + if (primals) { + delete[] primals; + } + } + + return (retval); +} + +//########################################################################### +//########################################################################### + +void saveSolution(const OsiSolverInterface *osi, std::string fileName) + +{ + FILE *fp = fopen(fileName.c_str(), "wb"); + + if (fp) { + int numberRows = osi->getNumRows(); + int numberColumns = osi->getNumCols(); + double objectiveValue = osi->getObjValue(); + + fwrite(&numberRows, sizeof(int), 1, fp); + fwrite(&numberColumns, sizeof(int), 1, fp); + fwrite(&objectiveValue, sizeof(double), 1, fp); + + const double *primalRowSolution = osi->getRowActivity(); + const double *dualRowSolution = osi->getRowPrice(); + const double *primalColumnSolution = osi->getColSolution(); + const double *dualColumnSolution = osi->getReducedCost(); + + fwrite(primalRowSolution, sizeof(double), numberRows, fp); + fwrite(dualRowSolution, sizeof(double), numberRows, fp); + fwrite(primalColumnSolution, sizeof(double), numberColumns, fp); + fwrite(dualColumnSolution, sizeof(double), numberColumns, fp); + + fclose(fp); + } else { + std::cout << "saveSolution: Unable to open file `" << fileName << "'." + << std::endl; + } + + return; +} + +//########################################################################### +//########################################################################### + +/* + Utility routine to read in a solution dump created by saveSolution. Generally + we don't need all the info in this file, so the routine accepts a bunch of + reference/pointer paramaters and fills in any that are non-null. It's the + client's responsibility to dispose of space allocated for solution vectors. + The parameters fileName, numRows, numCols, and objVal are mandatory. The rest + can be null. +*/ +bool readSolution(std::string fileName, int &numRows, int &numCols, + double &objVal, double **rowActivity, double **dualVars, + double **primalVars, double **reducedCosts) + +{ + FILE *fp = fopen(fileName.c_str(), "rb"); + bool retval = true; + + numRows = -1; + numCols = -1; + objVal = 0; + *rowActivity = 0; + *dualVars = 0; + *primalVars = 0; + *reducedCosts = 0; + + if (fp) { + fread(&numRows, sizeof(int), 1, fp); + fread(&numCols, sizeof(int), 1, fp); + fread(&objVal, sizeof(double), 1, fp); + + if (rowActivity != NULL) { + *rowActivity = new double[numRows]; + fread(*rowActivity, sizeof(double), numRows, fp); + } else { + fseek(fp, numRows * sizeof(double), SEEK_CUR); + } + + if (dualVars != NULL) { + *dualVars = new double[numRows]; + fread(*dualVars, sizeof(double), numRows, fp); + } else { + fseek(fp, numRows * sizeof(double), SEEK_CUR); + } + + if (primalVars != NULL) { + *primalVars = new double[numCols]; + fread(*primalVars, sizeof(double), numCols, fp); + } else { + fseek(fp, numCols * sizeof(double), SEEK_CUR); + } + + if (reducedCosts != NULL) { + *reducedCosts = new double[numCols]; + fread(*reducedCosts, sizeof(double), numCols, fp); + } else { + fseek(fp, numCols * sizeof(double), SEEK_CUR); + } + + fclose(fp); + } else { + std::cout << "readSolution: Unable to open file `" << fileName << "'." + << std::endl; + retval = false; + } + + return (retval); +} + +//########################################################################### +//########################################################################### + +/* + Function to push a double parameter. +*/ + +int pushCbcModelDblParam(CoinParam ¶m) + +{ + CbcParam &cbcParam = dynamic_cast(param); + CbcModel *model = cbcParam.model(); + double val = cbcParam.dblVal(); + int cbcParamCode = cbcParam.paramCode(); + + assert(model != 0); + + int retval = 0; + /* + Translate the parameter code from CbcParamCode into the correct key + for CbcDblParam. + */ + CbcModel::CbcDblParam key; + switch (cbcParamCode) { + case CbcParam::INTEGERTOLERANCE: { + key = CbcModel::CbcIntegerTolerance; + break; + } + case CbcParam::INFEASIBILITYWEIGHT: { + key = CbcModel::CbcInfeasibilityWeight; + break; + } + case CbcParam::INCREMENT: { + key = CbcModel::CbcCutoffIncrement; + break; + } + case CbcParam::ALLOWABLEGAP: { + key = CbcModel::CbcAllowableGap; + break; + } + case CbcParam::GAPRATIO: { + key = CbcModel::CbcAllowableFractionGap; + break; + } + case CbcParam::MAXSECONDSNOTIMPROVING: { + model->setMaxSecondsNotImproving(val); + break; + } + case CbcParam::TIMELIMIT: { + key = CbcModel::CbcMaximumSeconds; + break; + } + case CbcParam::CUTOFF: { + key = CbcModel::CbcCurrentCutoff; + break; + } + default: { + std::cerr << "pushCbcModelDblParam: no equivalent CbcDblParam for " + << "parameter code `" << cbcParamCode << "'." << std::endl; + retval = -1; + break; + } + } + + bool result = model->setDblParam(key, val); + if (result == false) { + retval = -1; + } + + return (retval); +} + +//########################################################################### +//########################################################################### + +/* + Function to push an integer parameter. +*/ + +int pushCbcModelIntParam(CoinParam ¶m) + +{ + CbcParam &cbcParam = dynamic_cast(param); + CbcModel *model = cbcParam.model(); + int val = cbcParam.intVal(); + int cbcParamCode = cbcParam.paramCode(); + + assert(model != 0); + + int retval = 0; + /* + Translate the parameter code from CbcParamCode into the correct key + for CbcIntParam, or call the appropriate method directly. + */ + CbcModel::CbcIntParam key = CbcModel::CbcLastIntParam; + switch (cbcParamCode) { + case CbcParam::CUTPASS: { + model->setMaximumCutPassesAtRoot(val); + break; + } + case CbcParam::LOGLEVEL: { + CoinMessageHandler *hndl = model->messageHandler(); + assert(hndl != 0); + hndl->setLogLevel(val); + break; + } + case CbcParam::MAXNODESNOTIMPROVING: { + model->setMaxNodesNotImproving(val); + break; + } + case CbcParam::MAXSOLS: { + model->setMaxSolutions(val); + break; + } + case CbcParam::NUMBERBEFORE: { + model->setNumberBeforeTrust(val); + break; + } + default: { + std::cerr << "pushCbcModelIntParam: no equivalent CbcIntParam for " + << "parameter code `" << cbcParamCode << "'." << std::endl; + retval = -1; + break; + } + } + + if (key != CbcModel::CbcLastIntParam) { + bool result = model->setIntParam(key, val); + if (result == false) { + retval = -1; + } + } + + return (retval); +} + +//########################################################################### +//########################################################################### + +/* + Set CbcModel defaults appropriate for cbc-generic. +*/ + +void setCbcModelDefaults(CbcModel *model) +{ + model->setIntParam(CbcModel::CbcMaxNumNode, (COIN_INT_MAX / 2)); + model->setIntParam(CbcModel::CbcMaxNumSol, 999999); + model->setIntParam(CbcModel::CbcFathomDiscipline, 0); + + model->setDblParam(CbcModel::CbcIntegerTolerance, 1.0e-6); + model->setDblParam(CbcModel::CbcInfeasibilityWeight, 0.0); + model->setDblParam(CbcModel::CbcCutoffIncrement, 1.0e-5); + model->setDblParam(CbcModel::CbcAllowableGap, 1.0e-10); + model->setDblParam(CbcModel::CbcAllowableFractionGap, 0.0); + // One year is 60x60x24x365 = 31,536,000 seconds. + model->setDblParam(CbcModel::CbcMaximumSeconds, 3.0e7); + model->setDblParam(CbcModel::CbcCurrentCutoff, 1.0e100); + model->setDblParam(CbcModel::CbcOptimizationDirection, 1.0); + model->setDblParam(CbcModel::CbcCurrentObjectiveValue, 1.0e100); + model->setDblParam(CbcModel::CbcCurrentMinimizationObjectiveValue, 1.0e100); + model->setDblParam(CbcModel::CbcStartSeconds, 0.0); + + model->setNumberBeforeTrust(5); + model->setNumberStrong(5); + + return; +} + +} // end namespace CbcParamUtils + + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 + */ diff --git a/src/CbcParamUtils.hpp b/src/CbcParamUtils.hpp new file mode 100644 index 000000000..37513b7d7 --- /dev/null +++ b/src/CbcParamUtils.hpp @@ -0,0 +1,54 @@ +/* + Copyright (C) 2007, Lou Hafer, International Business Machines Corporation + and others. All Rights Reserved. + + This code is licensed under the terms of the Eclipse Public License (EPL). + +*/ + +#ifndef CbcParamUtils_H +#define CbcParamUtils_H + +#include "CoinParam.hpp" + +#include "OsiSolverInterface.hpp" + +/* + Declare the utility functions. +*/ + +namespace CbcParamUtils { + +void saveSolution(const OsiSolverInterface *osi, std::string fileName); +bool readSolution(std::string fileName, int &numRows, int &numCols, + double &objVal, double **rowActivity, double **dualVars, + double **primalVars, double **reducedCosts); + +int doBaCParam(CoinParam ¶m); +int doDebugParam(CoinParam ¶m); +int doExitParam(CoinParam ¶m); +int doHelpParam(CoinParam ¶m); +int doImportParam(CoinParam ¶m); +int doPrintMaskParam(CoinParam ¶m); +int doNothingParam(CoinParam ¶m); +int doSolutionParam(CoinParam ¶m); +int doUnimplementedParam(CoinParam ¶m); +int doVersionParam(CoinParam ¶m); + +int pushCbcSolverDblParam(CoinParam ¶m); +int pushCbcSolverIntParam(CoinParam ¶m); +int pushCbcSolverKwdParam(CoinParam ¶m); +int pushCbcSolverStrParam(CoinParam ¶m); +int pushCbcSolverBoolParam(CoinParam ¶m); + +int pushCbcSolverHeurParam(CoinParam ¶m); +int pushCbcSolverCutParam(CoinParam ¶m); + +int pushCbcModelDblParam(CoinParam ¶m); +int pushCbcModelIntParam(CoinParam ¶m); + +void setCbcModelDefaults(CbcModel *model); + +} // namespace CbcParamUtils + +#endif diff --git a/src/CbcParameters.cpp b/src/CbcParameters.cpp new file mode 100644 index 000000000..3af359079 --- /dev/null +++ b/src/CbcParameters.cpp @@ -0,0 +1,2811 @@ +/* + Copyright (C) 2007, Lou Hafer, International Business Machines Corporation + and others. All Rights Reserved. + + This code is licensed under the terms of the Eclipse Public License (EPL). + +*/ + +#include "CoinPragma.hpp" + +#include + +#include "CbcParameters.hpp" +#include "CbcParamUtils.hpp" + +/* + Constructor for parameters class. + + Set up defaults. Note that prototypes for + cut generators and heuristics will be created on demand; see the access + functions. + + Once this structure settles down, simple intialisation should move up to + the standard `:' block. In the meantime, this avoids complaints about + ordering. +*/ + +CbcParameters::CbcParameters() : parameters_(CbcParam::LASTPARAM), model_(0), + clpParameters_(ClpParameters(true)) +{ + + init(DefaultStrategy); + +} + +//########################################################################### +//########################################################################### + +CbcParameters::CbcParameters(int strategy) : + parameters_(CbcParam::LASTPARAM), model_(0) +{ + init(strategy); +} + +//########################################################################### +//########################################################################### + +void CbcParameters::init(int strategy){ + + // First, initialize Clp parameters + switch (strategy) { + case DefaultStrategy: + default: + // already done clpParameters_.init(ClpParameters::DefaultStrategy); + break; + } + + for (int i = 0; i < parameters_.size(); i++){ + parameters_[i] = new CbcParam(); + } + + dfltDirectory_ = ""; + lastMpsIn_ = ""; + allowImportErrors_ = false; + lastSolnOut_ = "stdout"; + printMode_ = 0; + printMask_ = ""; + noPrinting_ = false; + printWelcome_ = true; + useSignalHandler_ = false; + + verbose_ = 0; + paramsProcessed_ = 0; + defaultSettings_ = true; + + debugCreate_ = ""; + debugFile_ = ""; + debugSol_.numCols_ = -1; + debugSol_.values_ = 0; + + printOpt_ = 0; + + /* + Assigning us_en to cur_lang_ is entirely bogus, but CoinMessages::Language + does not provide an `unspecified' code. + */ + msgHandler_ = new CoinMessageHandler(); + ourMsgHandler_ = true; + cur_lang_ = CoinMessages::us_en; + msgs_ = 0; + logLvl_ = 0; + lpLogLvl_ = 0; + + totalTime_ = 0.0; + + model_ = 0; + dfltSolver_ = 0; + goodModel_ = false; + bab_.majorStatus_ = CbcParameters::BACInvalid; + bab_.minorStatus_ = CbcParameters::BACmInvalid; + bab_.where_ = CbcParameters::BACwInvalid; + bab_.haveAnswer_ = false; + bab_.answerSolver_ = 0; + + preProcess_ = CbcParameters::IPPSOS; + cutDepth_ = -1; + + probing_.mode_ = CbcParameters::CGIfMove; + probing_.proto_ = 0; + probing_.usingObjective_ = true; + probing_.maxPass_ = 3; + probing_.maxPassRoot_ = 3; + probing_.maxProbe_ = 10; + probing_.maxProbeRoot_ = 50; + probing_.maxLook_ = 10; + probing_.maxLookRoot_ = 50; + probing_.maxElements_ = 200; + probing_.rowCuts_ = 3; + + clique_.mode_ = CbcParameters::CGIfMove; + clique_.proto_ = 0; + clique_.starCliqueReport_ = false; + clique_.rowCliqueReport_ = false; + clique_.minViolation_ = 0.1; + + flow_.mode_ = CbcParameters::CGIfMove; + flow_.proto_ = 0; + + gomory_.mode_ = CbcParameters::CGIfMove; + gomory_.proto_ = 0; + gomory_.limit_ = 50; + gomory_.limitAtRoot_ = 512; + + knapsack_.mode_ = CbcParameters::CGIfMove; + knapsack_.proto_ = 0; + + // landp_mode_ = CbcParameters::CGOff ; + // landp_.proto_ = 0 ; + + mir_.mode_ = CbcParameters::CGIfMove; + mir_.proto_ = 0; + +#if 0 + oddHole_.mode_ = CbcParameters::CGOff; + oddHole_.proto_ = 0; +#endif + + redSplit_.mode_ = CbcParameters::CGRoot; + redSplit_.proto_ = 0; + + twomir_.mode_ = CbcParameters::CGRoot; + twomir_.proto_ = 0; + twomir_.maxElements_ = 250; + + fpump_.mode_ = CbcParameters::HeurOn; + fpump_.proto_ = 0; + fpump_.initialTune_ = -1; + fpump_.iters_ = 0; + + combine_.mode_ = CbcParameters::HeurOn; + combine_.proto_ = 0; + combine_.trySwap_ = 1; + + greedyCover_.mode_ = CbcParameters::HeurOn; + greedyCover_.proto_ = 0; + greedyEquality_.mode_ = CbcParameters::HeurOn; + greedyEquality_.proto_ = 0; + + localTree_.mode_ = CbcParameters::HeurOff; + localTree_.proto_ = 0; + localTree_.soln_ = 0; + localTree_.range_ = 10; + localTree_.typeCuts_ = 0; + localTree_.maxDiverge_ = 0; + localTree_.timeLimit_ = 10000; + localTree_.nodeLimit_ = 2000; + localTree_.refine_ = true; + + rounding_.mode_ = CbcParameters::HeurOn; + rounding_.proto_ = 0; + + djFix_.mode_ = CbcParameters::ParamOff; + djFix_.threshold_ = 1.0e100; + + artVar_.mode_ = CbcParameters::ParamOff; + artVar_.threshold_ = 0.0; + + priorityMode_ = CbcParameters::BPOff; + /* + The value for numBeforeTrust is as recommended by Achterberg. Cbc's + implementation doesn't really have a parameter equivalent to Achterberg's + dynamic limit on number of strong branching evaluations, so go with a + fairly large default. As of 06.12.16, the magic number for shadow price + mode meant `use shadow prices (penalties, I think) if there's no strong + branching info'. + */ + chooseStrong_.numBeforeTrust_ = 8; + chooseStrong_.numStrong_ = 100; + chooseStrong_.shadowPriceMode_ = 1; + + addCbcParams(); + addCbcModelParams(); + setDefaults(strategy); + + return; +} + +//########################################################################### +//########################################################################### + +/* + Note that we don't want to delete dfltSolver_ here because it's just a + copy of the pointer held in the solvers map over in CbcGenSolvers.cpp. +*/ +CbcParameters::~CbcParameters() { + // TODO Do we own pointer here? + for (int i = 0; i < parameters_.size(); i++){ + delete parameters_[i]; + } + +#ifndef CBC_CLUMSY_CODING + if (model_) + delete model_; +#endif + if (bab_.answerSolver_) + delete bab_.answerSolver_; + + if (probing_.proto_) + delete probing_.proto_; + if (clique_.proto_) + delete clique_.proto_; + if (flow_.proto_) + delete flow_.proto_; + if (gomory_.proto_) + delete gomory_.proto_; + if (knapsack_.proto_) + delete knapsack_.proto_; + if (mir_.proto_) + delete mir_.proto_; +#if 0 + if (oddHole_.proto_) + delete oddHole_.proto_; +#endif + if (redSplit_.proto_) + delete redSplit_.proto_; + if (twomir_.proto_) + delete twomir_.proto_; + + if (fpump_.proto_) + delete fpump_.proto_; + if (combine_.proto_) + delete combine_.proto_; + if (greedyCover_.proto_) + delete greedyCover_.proto_; + if (greedyEquality_.proto_) + delete greedyEquality_.proto_; + if (rounding_.proto_) + delete rounding_.proto_; + + if (msgHandler_ && ourMsgHandler_) + delete msgHandler_; + if (msgs_) + delete msgs_; + + return; +} + +//########################################################################### +//########################################################################### + +int CbcParameters::matches(std::string field, int &numberMatches){ + int firstMatch = -1; + for (int iParam = 0; iParam < (int)parameters_.size(); iParam++) { + int match = parameters_[iParam]->matches(field); + if (match == 1) { + numberMatches = 1; + return iParam; + } else { + if (match){ + if (firstMatch < 0){ + firstMatch = iParam; + } + numberMatches++; + } + } + } + return firstMatch < 0 ? CbcParam::INVALID : firstMatch; +} + +//########################################################################### +//########################################################################### + +// some help strings that repeat for many options +#define CUTS_LONGHELP \ + "Value 'on' enables the cut generator and CBC will try it in the branch " \ + "and cut tree (see cutDepth on how to fine tune the behavior). Value " \ + "'root' lets CBC run the cut generator generate only at the root node. " \ + "Value 'ifmove' lets CBC use the cut generator in the tree if it looks as " \ + "if it is doing some good and moves the objective value. Value 'forceon' " \ + "turns on the cut generator and forces CBC to use it at every node.\n" + +#define HEURISTICS_LONGHELP \ + "Value 'on' means to use the heuristic in each node of the tree, i.e. " \ + "after preprocessing. Value 'before' means use the heuristic only if " \ + "option doHeuristics is used. Value 'both' means to use the heuristic if " \ + "option doHeuristics is used and during solve." + +//########################################################################### +//########################################################################### + +/* + Function to add Cbc parameters to the Cbc parameter + vector. Where needed, defaults are drawn from CbcParameters. + This function is a friend of CbcParameters. +*/ + +void CbcParameters::addCbcParams() { + + addCbcSolverStrParams(); + addCbcSolverDirParams(); + addCbcSolverFileParams(); + addCbcSolverHelpParams(); + addCbcSolverActionParams(); + addCbcSolverKwdParams(); + addCbcSolverDblParams(); + addCbcSolverIntParams(); + addCbcSolverBoolParams(); + addCbcSolverCutParams(); + addCbcSolverHeurParams(); + addCbcModelParams(); + + for (int code = CbcParam::FIRSTPARAM + 1; code < CbcParam::LASTPARAM; + code++) { + getParam(code)->setParameters(this); + getParam(code)->setModel(model_); + getParam(code)->setParamCode(code); + } + + return; +} + +//########################################################################### +//########################################################################### + +void CbcParameters::setDefaults(int strategy) { + + for (int code = CbcParam::FIRSTSTRINGPARAM + 1; + code < CbcParam::LASTSTRINGPARAM; code++) { + getParam(code)->setDefault(dfltDirectory_); + } + + parameters_[CbcParam::DEBUGFILE]->setDefault(""); + parameters_[CbcParam::CSVSTATSFILE]->setDefault(std::string("stats.csv")); + parameters_[CbcParam::EXPORTFILE]->setDefault(std::string("export.mps")); + parameters_[CbcParam::IMPORTFILE]->setDefault(std::string("import.mps")); + parameters_[CbcParam::GMPLSOLFILE]->setDefault(std::string("gmpl.sol")); + parameters_[CbcParam::MIPSTARTFILE]->setDefault(std::string("mipstart.sol")); + parameters_[CbcParam::MODELFILE]->setDefault(std::string("prob.mod")); + parameters_[CbcParam::NEXTSOLFILE]->setDefault(std::string("next.sol")); + parameters_[CbcParam::PRINTMASK]->setDefault(""); + parameters_[CbcParam::PRIORITYFILE]->setDefault(std::string("priorities.txt")); + parameters_[CbcParam::SOLUTIONFILE]->setDefault(std::string("opt.sol")); + parameters_[CbcParam::SOLUTIONBINARYFILE]->setDefault(std::string("solution.file")); + parameters_[CbcParam::COMMANDPRINTLEVEL]->setDefault("more"); + + // Now set up parameters according to overall strategies + switch (strategy) { + case CbcParameters::DefaultStrategy: + parameters_[CbcParam::CLQSTRENGTHENING]->setDefault("after"); + parameters_[CbcParam::BRANCHPRIORITY]->setDefault("off"); + parameters_[CbcParam::CUTOFFCONSTRAINT]->setDefault("off"); + parameters_[CbcParam::INTPRINT]->setDefault("normal"); + parameters_[CbcParam::NODESTRATEGY]->setDefault("hybrid"); + parameters_[CbcParam::ORBITAL]->setDefault("off"); + parameters_[CbcParam::PREPROCESS]->setDefault("off"); + parameters_[CbcParam::SOSPRIORITIZE]->setDefault("off"); + parameters_[CbcParam::STRATEGY]->setDefault("default"); + parameters_[CbcParam::TIMEMODE]->setDefault("cpu"); + parameters_[CbcParam::USECGRAPH]->setDefault("on"); + parameters_[CbcParam::ARTIFICIALCOST]->setDefault(getArtVarThreshold()); + parameters_[CbcParam::DEXTRA3]->setDefault(0.0); + parameters_[CbcParam::DEXTRA4]->setDefault(0.0); + parameters_[CbcParam::DEXTRA5]->setDefault(0.0); + parameters_[CbcParam::DJFIX]->setDefault(getDjFixThreshold()); + parameters_[CbcParam::FAKECUTOFF]->setDefault(0.0); + parameters_[CbcParam::FAKEINCREMENT]->setDefault(0.0); + parameters_[CbcParam::SMALLBAB]->setDefault(0.5); + parameters_[CbcParam::TIGHTENFACTOR]->setDefault(0.0); + parameters_[CbcParam::BKPIVOTINGSTRATEGY]->setDefault(3); + parameters_[CbcParam::BKMAXCALLS]->setDefault(1000); + parameters_[CbcParam::BKCLQEXTMETHOD]->setDefault(4); + parameters_[CbcParam::CPP]->setDefault(0); + parameters_[CbcParam::CUTDEPTH]->setDefault(getCutDepth()); + parameters_[CbcParam::CUTLENGTH]->setDefault(-1); + parameters_[CbcParam::CUTPASSINTREE]->setDefault(1); + parameters_[CbcParam::DEPTHMINIBAB]->setDefault(-1); + parameters_[CbcParam::DIVEOPT]->setDefault(-1); + parameters_[CbcParam::DIVEOPTSOLVES]->setDefault(100); + parameters_[CbcParam::DUMMY]->setDefault(0); + parameters_[CbcParam::EXPERIMENT]->setDefault(0); + parameters_[CbcParam::EXTRA1]->setDefault(-1); + parameters_[CbcParam::EXTRA2]->setDefault(-1); + parameters_[CbcParam::EXTRA3]->setDefault(-1); + parameters_[CbcParam::EXTRA4]->setDefault(-1); + parameters_[CbcParam::EXTRAVARIABLES]->setDefault(0); + parameters_[CbcParam::FPUMPITS]->setDefault(getFeasPumpIters()); + parameters_[CbcParam::FPUMPTUNE]->setDefault(0); + parameters_[CbcParam::FPUMPTUNE2]->setDefault(0); + parameters_[CbcParam::HEUROPTIONS]->setDefault(0); + parameters_[CbcParam::LOGLEVEL]->setDefault(getLogLevel()); + parameters_[CbcParam::LPLOGLEVEL]->setDefault(getLpLogLevel()); + parameters_[CbcParam::MAXHOTITS]->setDefault(0); + parameters_[CbcParam::MAXSAVEDSOLS]->setDefault(1); + parameters_[CbcParam::MAXSLOWCUTS]->setDefault(10); + parameters_[CbcParam::MOREMOREMIPOPTIONS]->setDefault(0); + parameters_[CbcParam::MULTIPLEROOTS]->setDefault(0); + parameters_[CbcParam::ODDWEXTMETHOD]->setDefault(2); + parameters_[CbcParam::OUTPUTFORMAT]->setDefault(2); + parameters_[CbcParam::PRINTOPTIONS]->setDefault(0); + parameters_[CbcParam::PROCESSTUNE]->setDefault(0); + parameters_[CbcParam::RANDOMSEED]->setDefault(-1); + parameters_[CbcParam::STRONGSTRATEGY]->setDefault(0); + parameters_[CbcParam::TESTOSI]->setDefault(-1); +#ifdef CBC_THREAD + parameters_[CbcParam::THREADS]->setDefault(0); +#endif + parameters_[CbcParam::USERCBC]->setDefault(0); + parameters_[CbcParam::VERBOSE]->setDefault(verbose_); + parameters_[CbcParam::VUBTRY]->setDefault(-1); + parameters_[CbcParam::CPX]->setDefault("off"); + parameters_[CbcParam::DOHEURISTIC]->setDefault("off"); + parameters_[CbcParam::ERRORSALLOWED]->setDefault("off"); + parameters_[CbcParam::MESSAGES]->setDefault("off"); + parameters_[CbcParam::PREPROCNAMES]->setDefault("off"); + parameters_[CbcParam::SOS]->setDefault("off"); + parameters_[CbcParam::USESOLUTION]->setDefault("off"); + parameters_[CbcParam::CUTSTRATEGY]->setDefault("off"); + parameters_[CbcParam::FLOWCUTS]->setDefault("ifmove"); + parameters_[CbcParam::GMICUTS]->setDefault("off"); + parameters_[CbcParam::GOMORYCUTS]->setDefault("ifmove"); + parameters_[CbcParam::KNAPSACKCUTS]->setDefault("ifmove"); + parameters_[CbcParam::LAGOMORYCUTS]->setDefault("off"); + parameters_[CbcParam::LANDPCUTS]->setDefault("off"); + parameters_[CbcParam::LATWOMIRCUTS]->setDefault("off"); + parameters_[CbcParam::MIRCUTS]->setDefault("ifmove"); + parameters_[CbcParam::ODDWHEELCUTS]->setDefault("ifmove"); + parameters_[CbcParam::PROBINGCUTS]->setDefault("ifmove"); + parameters_[CbcParam::REDSPLITCUTS]->setDefault("off"); + parameters_[CbcParam::REDSPLIT2CUTS]->setDefault("ifmove"); + parameters_[CbcParam::RESIDCAPCUTS]->setDefault("off"); + parameters_[CbcParam::TWOMIRCUTS]->setDefault("ifmove"); + parameters_[CbcParam::ZEROHALFCUTS]->setDefault("ifmove"); + parameters_[CbcParam::COMBINE]->setDefault("off"); + parameters_[CbcParam::CROSSOVER]->setDefault("off"); + parameters_[CbcParam::DINS]->setDefault("off"); + parameters_[CbcParam::DIVINGC]->setDefault("off"); + parameters_[CbcParam::DIVINGF]->setDefault("off"); + parameters_[CbcParam::DIVINGG]->setDefault("off"); + parameters_[CbcParam::DIVINGL]->setDefault("off"); + parameters_[CbcParam::DIVINGP]->setDefault("off"); + parameters_[CbcParam::DIVINGS]->setDefault("off"); + parameters_[CbcParam::DIVINGV]->setDefault("off"); + parameters_[CbcParam::DW]->setDefault("off"); + parameters_[CbcParam::FPUMP]->setDefault("off"); + parameters_[CbcParam::GREEDY]->setDefault("off"); + parameters_[CbcParam::HEURISTICSTRATEGY]->setDefault("off"); + parameters_[CbcParam::LOCALTREE]->setDefault("off"); + parameters_[CbcParam::NAIVE]->setDefault("off"); + parameters_[CbcParam::PIVOTANDFIX]->setDefault("off"); +#if 0 + parameters_[CbcParam::PIVOTANDCOMPLEMENT]->setDefault("off"); +#endif + parameters_[CbcParam::PROXIMITY]->setDefault("off"); + parameters_[CbcParam::RANDROUND]->setDefault("off"); + parameters_[CbcParam::RENS]->setDefault("off"); + parameters_[CbcParam::RINS]->setDefault("off"); + parameters_[CbcParam::ROUNDING]->setDefault("off"); + parameters_[CbcParam::VND]->setDefault("off"); + parameters_[CbcParam::ALLOWABLEGAP]->setDefault(1.0e-12); + parameters_[CbcParam::CUTOFF]->setDefault(1.0e50); + parameters_[CbcParam::DIRECTION]->setDefault("min!imize"); + parameters_[CbcParam::INCREMENT]->setDefault(1.0e-4); + parameters_[CbcParam::INFEASIBILITYWEIGHT]->setDefault(0.0); + parameters_[CbcParam::INTEGERTOLERANCE]->setDefault(1.0e-6); + parameters_[CbcParam::LOGLEVEL]->setDefault(1); + parameters_[CbcParam::MAXIMIZE]->setType(CoinParam::paramAct); + parameters_[CbcParam::MAXNODES]->setDefault(COIN_INT_MAX); + parameters_[CbcParam::MAXNODESNOTIMPROVING]->setDefault(COIN_INT_MAX); + parameters_[CbcParam::MAXSECONDSNOTIMPROVING]->setDefault(COIN_DBL_MAX); + parameters_[CbcParam::MAXSOLS]->setDefault(COIN_INT_MAX/2); + parameters_[CbcParam::MINIMIZE]->setType(CoinParam::paramAct); + parameters_[CbcParam::MIPOPTIONS]->setDefault(0); + parameters_[CbcParam::MOREMIPOPTIONS]->setDefault(0); +#if 0 + parameters_[CbcParam::NUMBERMINI]->setDefault(0); +#endif + parameters_[CbcParam::NUMBERANALYZE]->setDefault(0); + parameters_[CbcParam::REVERSE]->setType(CoinParam::paramAct); + parameters_[CbcParam::CUTPASS]->setDefault(100); + parameters_[CbcParam::GAPRATIO]->setDefault(0.0); + parameters_[CbcParam::TIMELIMIT]->setDefault( 1.0e11); + parameters_[CbcParam::STRONGBRANCHING]->setDefault(0); + parameters_[CbcParam::NUMBERBEFORE]->setDefault(10); + break; + default: + std::cout << "Unknown strategy!" << std::endl; + break; + } + +} + +//########################################################################### +//########################################################################### + +#ifdef CBC_CLUMSY_CODING +// Synchronize Cbc (and Clp) model - Int and Dbl +void CbcParameters::synchronizeModel() { + if (goodModel_) { + assert (model_); + // Integer parameters + int intValue; + int modelIntValue; + parameters_[CbcParam::MAXNODES]->getVal(intValue); + //#define PRINT_CBC_CHANGES +#ifdef PRINT_CBC_CHANGES + modelIntValue = model_->getIntParam(CbcModel::CbcMaxNumNode); + if (intValue!=modelIntValue) + printf("changing MAXNODES from %d to %d at line %d\n",modelIntValue,intValue,__LINE__+1); +#endif + model_->setIntParam(CbcModel::CbcMaxNumNode, intValue); + parameters_[CbcParam::MAXNODESNOTIMPROVING]->getVal(intValue); +#ifdef PRINT_CBC_CHANGES + modelIntValue = model_->getIntParam(CbcModel::CbcMaxNodesNotImproving); + if (intValue!=modelIntValue) + printf("changing MAXNODESNOTIMPROVING from %d to %d at line %d\n",modelIntValue,intValue,__LINE__+1); +#endif + model_->setIntParam(CbcModel::CbcMaxNodesNotImproving, intValue); + parameters_[CbcParam::MAXSOLS]->getVal(intValue); +#ifdef PRINT_CBC_CHANGES + modelIntValue = model_->getIntParam(CbcModel::CbcMaxNumSol); + if (intValue!=modelIntValue) + printf("changing MAXSOLS from %d to %d at line %d\n",modelIntValue,intValue,__LINE__+1); +#endif + model_->setIntParam(CbcModel::CbcMaxNumSol, intValue); + // ?case CBC_PARAM_INT_MAXSAVEDSOLS: + parameters_[CbcParam::STRONGBRANCHING]->getVal(intValue); +#ifdef PRINT_CBC_CHANGES + modelIntValue = model_->numberStrong(); + if (intValue!=modelIntValue) + printf("changing STRONGBRANCHING from %d to %d at line %d\n",modelIntValue,intValue,__LINE__+1); +#endif + model_->setNumberStrong(intValue); + parameters_[CbcParam::NUMBERBEFORE]->getVal(intValue); +#ifdef PRINT_CBC_CHANGES + modelIntValue = model_->numberBeforeTrust(); + if (intValue!=modelIntValue) + printf("changing NUMBERBEFORE from %d to %d at line %d\n",modelIntValue,intValue,__LINE__+1); +#endif + model_->setNumberBeforeTrust(intValue); + parameters_[CbcParam::NUMBERANALYZE]->getVal(intValue); + modelIntValue = model_->numberAnalyzeIterations(); +#ifdef PRINT_CBC_CHANGES + if (intValue!=modelIntValue) + printf("changing NUMBERANALYZE from %d to %d at line %d\n",modelIntValue,intValue,__LINE__+1); +#endif + model_->setNumberAnalyzeIterations(intValue); + parameters_[CbcParam::CUTPASSINTREE]->getVal(intValue); +#ifdef PRINT_CBC_CHANGES + modelIntValue = model_->getMaximumCutPasses(); + if (intValue!=modelIntValue) + printf("changing CUTPASSINTREE from %d to %d at line %d\n",modelIntValue,intValue,__LINE__+1); +#endif + model_->setMaximumCutPasses(intValue); + parameters_[CbcParam::CUTPASS]->getVal(intValue); +#ifdef PRINT_CBC_CHANGES + modelIntValue = model_->getMaximumCutPassesAtRoot(); + if (intValue!=modelIntValue) + printf("changing CUTPASS from %d to %d at line %d\n",modelIntValue,intValue,__LINE__+1); +#endif + model_->setMaximumCutPassesAtRoot(intValue); +#ifdef CBC_THREAD + parameters_[CbcParam::THREADS]->getVal(intValue); +#ifdef PRINT_CBC_CHANGES + modelIntValue = model_->getNumberThreads(); + if (intValue!=modelIntValue) + printf("changing THREADS from %d to %d at line %d\n",modelIntValue,intValue,__LINE__+1); +#endif + model_->setNumberThreads(intValue); +#endif + parameters_[CbcParam::RANDOMSEED]->getVal(intValue); +#ifdef PRINT_CBC_CHANGES + modelIntValue = model_->getRandomSeed(); + if (intValue!=modelIntValue) + printf("changing RANDOMSEED from %d to %d at line %d\n",modelIntValue,intValue,__LINE__+1); +#endif + model_->setRandomSeed(intValue); + // Double parameters + double doubleValue; + double modelDoubleValue; + parameters_[CbcParam::INFEASIBILITYWEIGHT]->getVal(doubleValue); +#ifdef PRINT_CBC_CHANGES + modelDoubleValue = model_->getDblParam(CbcModel::CbcInfeasibilityWeight); + if (doubleValue!=modelDoubleValue) + printf("changing INFEASIBILITYWEIGHT from %g to %g at line %d\n",modelDoubleValue,doubleValue,__LINE__+1); +#endif + model_->setDblParam(CbcModel::CbcInfeasibilityWeight, intValue); + parameters_[CbcParam::INTEGERTOLERANCE]->getVal(doubleValue); +#ifdef PRINT_CBC_CHANGES + modelDoubleValue = model_->getDblParam(CbcModel::CbcIntegerTolerance); + if (doubleValue!=modelDoubleValue) + printf("changing INTEGERTOLERANCE from %g to %g at line %d\n",modelDoubleValue,doubleValue,__LINE__+1); +#endif + model_->setDblParam(CbcModel::CbcIntegerTolerance, doubleValue); + parameters_[CbcParam::INCREMENT]->getVal(doubleValue); +#ifdef PRINT_CBC_CHANGES + modelDoubleValue = model_->getDblParam(CbcModel::CbcCutoffIncrement); + if (doubleValue!=modelDoubleValue) + printf("changing INCREMENT from %g to %g at line %d\n",modelDoubleValue,doubleValue,__LINE__+1); +#endif + model_->setDblParam(CbcModel::CbcCutoffIncrement, doubleValue); + parameters_[CbcParam::ALLOWABLEGAP]->getVal(doubleValue); +#ifdef PRINT_CBC_CHANGES + modelDoubleValue = model_->getDblParam(CbcModel::CbcAllowableGap); + if (doubleValue!=modelDoubleValue) + printf("changing ALLOWABLEGAP from %g to %g at line %d\n",modelDoubleValue,doubleValue,__LINE__+1); +#endif + model_->setDblParam(CbcModel::CbcAllowableGap, doubleValue); + parameters_[CbcParam::GAPRATIO]->getVal(doubleValue); +#ifdef PRINT_CBC_CHANGES + if (doubleValue!=modelDoubleValue) + modelDoubleValue = model_->getDblParam(CbcModel::CbcAllowableFractionGap); + printf("changing GAPRATIO from %g to %g at line %d\n",modelDoubleValue,doubleValue,__LINE__+1); +#endif + model_->setDblParam(CbcModel::CbcAllowableFractionGap, doubleValue); + parameters_[CbcParam::CUTOFF]->getVal(doubleValue); +#ifdef PRINT_CBC_CHANGES + modelDoubleValue = model_->getCutoff(); + if (doubleValue!=modelDoubleValue) + printf("changing CUTOFF from %g to %g at line %d\n",modelDoubleValue,doubleValue,__LINE__+1); +#endif + if (fabs(doubleValue)<1.0e40) + model_->setCutoff(doubleValue); + parameters_[CbcParam::TIMELIMIT]->getVal(doubleValue); +#ifdef PRINT_CBC_CHANGES + modelDoubleValue = model_->getDblParam(CbcModel::CbcMaximumSeconds); + if (doubleValue!=modelDoubleValue) + printf("changing TIMELIMIT from %g to %g at line %d\n",modelDoubleValue,doubleValue,__LINE__+1); +#endif + model_->setDblParam(CbcModel::CbcMaximumSeconds, doubleValue); + parameters_[CbcParam::MAXSECONDSNOTIMPROVING]->getVal(doubleValue); +#ifdef PRINT_CBC_CHANGES + modelDoubleValue = model_->getDblParam(CbcModel::CbcMaxSecondsNotImproving); + if (doubleValue!=modelDoubleValue) + printf("changing MAXSECONDSNOTIMPROVING from %g to %g at line %d\n",modelDoubleValue,doubleValue,__LINE__+1); +#endif + model_->setDblParam(CbcModel::CbcMaxSecondsNotImproving, doubleValue); + if (clpParameters_.getModel()) + clpParameters_.synchronizeModel(); + } +} +#endif + +//########################################################################### +//########################################################################### + +void CbcParameters::addCbcSolverHelpParams() { + for (int code = CbcParam::FIRSTHELPPARAM + 1; + code < CbcParam::LASTHELPPARAM; code++) { + getParam(code)->setPushFunc(CbcParamUtils::doHelpParam); + getParam(code)->setType(CoinParam::paramAct); + } + // Duplicate help to get correct call + parameters_[CbcParam::GENERALQUERY]->setup( + "?", "Print a list of commands","Print a list of commands", + CoinParam::displayPriorityNone); + + parameters_[CbcParam::FULLGENERALQUERY]->setup( + "???", "Print a list of commands with short explanation", + "Print a list of commands with short explanation", + CoinParam::displayPriorityNone); + + // Need display parameter to resolve ambiguity + parameters_[CbcParam::HELP]->setup( + "help", "Print out version, non-standard options and some help", + "This prints out some help to get a user started. If you're seeing this " + "message, you should be past that stage.", + CoinParam::displayPriorityHigh); +} + +//########################################################################### +//########################################################################### + +void CbcParameters::addCbcSolverActionParams() { + + for (int code = CbcParam::FIRSTACTIONPARAM + 1; + code < CbcParam::LASTACTIONPARAM; code++) { + getParam(code)->setType(CoinParam::paramAct); + } + + parameters_[CbcParam::BAB]->setup( + "solv!e", "invoke branch and cut to solve the current problem", + "This does branch and cut. There are many parameters which can affect " + "the performance. First just try with default cbcSettings and look " + "carefully at the log file. Did cuts help? Did they take too long? " + "Look at output to see which cuts were effective and then do some " + "tuning. You will see that the options for cuts are off, on, root and " + "ifmove. Off is obvious, on means that this cut generator will be tried " + "in the branch and cut tree (you can fine tune using 'depth'). Root " + "means just at the root node while 'ifmove' means that cuts will be used " + "in the tree if they look as if they are doing some good and moving the " + "objective value. If pre-processing reduced the size of the problem or " + "strengthened many coefficients then it is probably wise to leave it on. " + " Switch off heuristics which did not provide solutions. The other " + "major area to look at is the search. Hopefully good solutions were " + "obtained fairly early in the search so the important point is to select " + "the best variable to branch on. See whether strong branching did a " + "good job - or did it just take a lot of iterations. Adjust the " + "strongBranching and trustPseudoCosts parameters.", + CoinParam::displayPriorityHigh); + parameters_[CbcParam::BAB]->setPushFunc(CbcParamUtils::doBaCParam); + + parameters_[CbcParam::DEBUG]->setup( + "debug!In", "Read/write valid solution from/to file", + "This will read a solution file from the given file name. It will use " + "the default directory given by 'directory'. If no name is supplied, " + "the previous value will be used. This is initialized to '', i.e. it " + " must be set.\n\nIf set to create it will create a file called " + "debug.file after B&C search; if set to createAfterPre it will create " + "the file before undoing preprocessing.\n\nThe idea is that if you " + "suspect a bad cut generator and you did not use preprocessing you can " + "do a good run with debug set to 'create' and then switch on the cuts " + "you suspect and re-run with debug set to 'debug.file' Similarly if " + "you do use preprocessing, but use 'createAfterPre'. The 'create' case" + "has the same effect as 'saveSolution'.", + CoinParam::displayPriorityNone); + parameters_[CbcParam::DEBUG]->setPushFunc(CbcParamUtils::doDebugParam); + + parameters_[CbcParam::END]->setup( + "end", "Stops execution", + "This stops execution; end, exit, quit and stop are synonyms.", + CoinParam::displayPriorityHigh); + parameters_[CbcParam::END]->setPushFunc(CbcParamUtils::doExitParam); + +#if 1 + parameters_[CbcParam::QUIT]->setup("quit", "Stops cbc execution", + "This stops the execution of Cbc, end, exit, quit and stop are synonyms", + CoinParam::displayPriorityHigh); + parameters_[CbcParam::END]->setPushFunc(CbcParamUtils::doExitParam); + + parameters_[CbcParam::EXIT]->setup("exit", "Stops cbc execution", + "This stops the execution of Cbc, end, exit, quit and stop are synonyms", + CoinParam::displayPriorityHigh); + parameters_[CbcParam::END]->setPushFunc(CbcParamUtils::doExitParam); + + parameters_[CbcParam::STOP]->setup("stop", "Stops cbc execution", + "This stops the execution of Cbc, end, exit, quit and stop are synonyms", + CoinParam::displayPriorityHigh); + parameters_[CbcParam::END]->setPushFunc(CbcParamUtils::doExitParam); +#endif + + parameters_[CbcParam::ENVIRONMENT]->setup( + "environ!ment", "Read commands from environment", + "This starts reading from environment variable COIN_ENVIRONMENT.", + CoinParam::displayPriorityNone); + parameters_[CbcParam::ENVIRONMENT]->setPushFunc(CbcParamUtils::doNothingParam); + + parameters_[CbcParam::EXPORT]->setup( + "export", "Export model as mps file", + "This will write an MPS format file to the given file name. It will use " + "the default directory given by 'directory'. A name of '$' will use the " + "previous value for the name. This is initialized to 'default.mps'. It " + "can be useful to get rid of the original names and go over to using " + "Rnnnnnnn and Cnnnnnnn. This can be done by setting 'keepnames' off " + "before importing mps file.", + CoinParam::displayPriorityHigh); + + parameters_[CbcParam::IMPORT]->setup( + "import", "Import model from file", + "This will read an MPS format file from the given file name. It will " + "use the default directory given by 'directory'. A name of '$' will use " + "the previous value for the name. This is initialized to '', i.e., it " + "must be set. If you have libgz then it can read compressed files " + "'xxxxxxxx.gz'.", + CoinParam::displayPriorityHigh); + parameters_[CbcParam::IMPORT]->setPushFunc(CbcParamUtils::doImportParam); + + parameters_[CbcParam::MIPLIB]->setup("miplib", "Do some of miplib test set", "", + CoinParam::displayPriorityHigh); + + parameters_[CbcParam::OUTDUPROWS]->setup( + "outDup!licates", "Takes duplicate rows, etc., out of the integer model", + "", CoinParam::displayPriorityNone); + + parameters_[CbcParam::PRINTSOL]->setup( + "printS!olution", "writes solution to file (or stdout)", + "This will write a binary solution file to the file set by solFile.", + CoinParam::displayPriorityHigh); + + parameters_[CbcParam::PRINTVERSION]->setup( + "version", "Print version", "", CoinParam::displayPriorityHigh); + parameters_[CbcParam::PRINTVERSION]->setPushFunc(CbcParamUtils::doVersionParam); + + parameters_[CbcParam::READMIPSTART]->setup( + "mipS!tart", "reads an initial feasible solution from file", + "The MIPStart allows one to enter an initial integer feasible solution " + "to CBC. Values of the main decision variables which are active (have " + "non-zero values) in this solution are specified in a text file. The " + "text file format used is the same of the solutions saved by CBC, but " + "not all fields are required to be filled. First line may contain the " + "solution status and will be ignored, remaining lines contain column " + "indexes, names and values as in this example:\n\n Stopped on iterations " + "- objective value 57597.00000000\n 0 x(1,1,2,2) 1 " + "\n 1 x(3,1,3,2) 1 \n 5 v(5,1) " + " 2 \n 33 x(8,1,5,2) 1 \n ...\n\n Column " + "indexes are also ignored since pre-processing can change them. There is " + "no need to include values for continuous or integer auxiliary " + "variables, since they can be computed based on main decision variables. " + "Starting CBC with an integer feasible solution can dramatically improve " + "its performance: several MIP heuristics (e.g. RINS) rely on having at " + "least one feasible solution available and can start immediately if the " + "user provides one. Feasibility Pump (FP) is a heuristic which tries to " + "overcome the problem of taking too long to find feasible solution (or " + "not finding at all), but it not always succeeds. If you provide one " + "starting solution you will probably save some time by disabling FP. " + "\n\n Knowledge specific to your problem can be considered to write an " + "external module to quickly produce an initial feasible solution - some " + "alternatives are the implementation of simple greedy heuristics or the " + "solution (by CBC for example) of a simpler model created just to find a " + "feasible solution. \n\n Silly options added. If filename ends .low " + "then integers not mentioned are set low - also .high, .lowcheap, " + ".highcheap, .lowexpensive, .highexpensive where .lowexpensive sets " + "costed ones to make expensive others low. Also if filename starts " + "empty. then no file is read at all - just actions done. \n\n Question " + "and suggestions regarding MIPStart can be directed to\n " + "haroldo.santos@gmail.com. "); + + parameters_[CbcParam::READMODEL]->setup( + "readM!odel", "Reads problem from a binary save file", + "This will read the problem saved by 'writeModel' from the file name " + "set by 'modelFile'.", + CoinParam::displayPriorityHigh); + + // For backward compatibility + parameters_[CbcParam::READMODEL_OLD]->setup( + "restoreM!odel", "Reads problem from a file", + "This will read the problem saved by 'writeModel' from the file name " + "set by 'modelFile'.", + CoinParam::displayPriorityNone); + + parameters_[CbcParam::READPRIORITIES]->setup( + "readP!riorities", "reads priorities from file", + "Read priorities from the file name designated by PRIORITYFILE. " + "File is in csv format with allowed headings - name, number, priority, " + "direction, up, down, solution. Exactly one of name and number must be " + "given.", CoinParam::displayPriorityHigh); + + parameters_[CbcParam::SHOWUNIMP]->setup( + "unimp!lemented", "Report unimplemented commands.", "", + CoinParam::displayPriorityNone); + parameters_[CbcParam::SHOWUNIMP]->setPushFunc(CbcParamUtils::doUnimplementedParam); + + parameters_[CbcParam::SOLVECONTINUOUS]->setup( + "initialS!olve", "Solve to continuous optimum", + "This just solves the problem to the continuous optimum, without adding " + "any cuts.", + CoinParam::displayPriorityHigh); + + parameters_[CbcParam::STATISTICS]->setup( + "stat!istics", "Print some statistics", + "This command prints some statistics for the current model. If log level " + ">1 then more is printed. These are for presolved model if presolve on " + "(and unscaled).", + CoinParam::displayPriorityHigh); + +#if 0 + // Need to figure out what to do here. Same parameter can't have two names... + parameters_[CbcParam::STDIN]->setup( "-", "Switch to interactive command line mode", "" + CoinParam::displayPriorityNone); + parameters_[CbcParam::STDIN]->setPushFunc(CbcParamUtils::doNothingParam); +#endif + + parameters_[CbcParam::STDIN]->setup( + "stdin", "Switch to interactive command line mode", "", + CoinParam::displayPriorityNone); + + parameters_[CbcParam::STRENGTHEN]->setup( + "strengthen", "Create strengthened problem", + "This creates a new problem by applying the root node cuts. All tight " + "constraints will be in resulting problem.", + CoinParam::displayPriorityHigh); + + parameters_[CbcParam::UNITTEST]->setup( + "unitTest", "Do unit test", "This exercises the unit test.", + CoinParam::displayPriorityHigh); + + parameters_[CbcParam::WRITEGMPLSOL]->setup( + "writeGSolu!tion", "Puts glpk solution to file", + "Will write a glpk solution file to the given file name. It will use " + "the default directory given by 'directory'. A name of '$' will use the " + "previous value for the name. This is initialized to 'stdout' (this " + "defaults to ordinary solution if stdout). If problem created from gmpl " + "model - will do any reports.", + CoinParam::displayPriorityHigh); + + // For backward compatibility + parameters_[CbcParam::WRITEGMPLSOL_OLD]->setup( + "gsolu!tion", "Puts glpk solution to file (synonym for writeGSolu!tion)", + "Will write a glpk solution file to the given file name. It will use " + "the default directory given by 'directory'. A name of '$' will use the " + "previous value for the name. This is initialized to 'stdout' (this " + "defaults to ordinary solution if stdout). If problem created from gmpl " + "model - will do any reports.", + CoinParam::displayPriorityNone); + + parameters_[CbcParam::WRITEMODEL]->setup( + "writeM!odel", "save model to binary file", + "This will write the problem in binary foramt to the file name set by " + "'modelFile' for future use by readModel.", + CoinParam::displayPriorityHigh); + + // For backward compatibility + parameters_[CbcParam::WRITEMODEL_OLD]->setup( + "saveM!odel", "save model to binary file (synonym for writeModel)", + "This will write the problem in binary foramt to the file name set by " + "'modelFile' for future use by readModel.", + CoinParam::displayPriorityNone); + + parameters_[CbcParam::WRITENEXTSOL]->setup( + "nextB!estSolution", "Prints next best saved solution to file", + "To write best solution, just use writeSolution. This prints next best " + "(if exists) and then deletes it. This will write a primitive solution " + "file to the file name set by 'nextBestSolutionFile'. The amount of " + "output can be varied using 'printingOptions' or 'printMask'."); + + parameters_[CbcParam::WRITESOL]->setup( + "writeS!olution", "writes solution to file (or stdout)", + "This will write a primitive solution file to the file set by " + "'solFile'. The amount of output can be varied using " + "'printingOptions' or 'printMask'.", + CoinParam::displayPriorityHigh); + + // For backward compatibility + parameters_[CbcParam::WRITESOL_OLD]->setup( + "solu!tion", "writes solution to file (or stdout) (synonym for " + "writeSolution).", + "This will write a primitive solution file to the file set by " + "'solFile'. The amount of output can be varied using " + "'printingOptions' or 'printMask'.", + CoinParam::displayPriorityHigh); + + parameters_[CbcParam::WRITESOLBINARY]->setup( + "writeSolB!inary", "writes solution to file in binary format", + "This will write a binary solution file to the file set by " + "'solBinaryFile'. To read the file use fread(int) twice to pick up " + "number of rows and columns, then fread(double) to pick up objective " + "value, then pick up row activities, row duals, column activities and " + "reduced costs - see bottom of ClpParamUtils.cpp for code that reads or " + "writes file. If name contains '_fix_read_', then does not write but " + "reads and will fix all variables", + CoinParam::displayPriorityHigh); + + // For backward compatibility + parameters_[CbcParam::WRITESOLBINARY_OLD]->setup( + "saveS!olution", "writes solution to file in binary format (synonym for " + "writeSolBinary", + "This will write a binary solution file to the file set by " + "'solBinaryFile'. To read the file use fread(int) twice to pick up " + "number of rows and columns, then fread(double) to pick up objective " + "value, then pick up row activities, row duals, column activities and " + "reduced costs - see bottom of ClpParamUtils.cpp for code that reads or " + "writes file. If name contains '_fix_read_', then does not write but " + "reads and will fix all variables", + CoinParam::displayPriorityNone); +} + +//########################################################################### +//########################################################################### + +void CbcParameters::addCbcSolverDirParams() { + + for (int code = CbcParam::FIRSTDIRECTORYPARAM + 1; + code < CbcParam::LASTDIRECTORYPARAM; code++) { + getParam(code)->setType(CoinParam::paramDir); + } + + parameters_[CbcParam::DIRECTORY]->setup( + "directory", "Set Default directory for import etc.", + "This sets the directory which import, export, saveModel, restoreModel " + "etc. will use. It is initialized to the current directory."); + parameters_[CbcParam::DIRECTORY]->setPushFunc(CbcParamUtils::pushCbcSolverStrParam); + + parameters_[CbcParam::DIRSAMPLE]->setup( + "dirSample", "Set directory where the COIN-OR sample problems are.", + "This sets the directory where the COIN-OR sample problems reside. It is " + "used only when -unitTest is passed to cbc. cbc will pick up the test " + "problems from this directory.", CoinParam::displayPriorityLow); + parameters_[CbcParam::DIRSAMPLE]->setPushFunc(CbcParamUtils::pushCbcSolverStrParam); + + parameters_[CbcParam::DIRNETLIB]->setup( + "dirNetlib", "Set directory where the netlib problems are.", + "This sets the directory where the netlib problems reside. One can get " + "the netlib problems from COIN-OR or from the main netlib site. This " + "parameter is used only when -netlib is passed to cbc. cbc will pick up " + "the netlib problems from this directory. If cbc is built without zlib " + "support then the problems must be uncompressed.", + CoinParam::displayPriorityLow); + parameters_[CbcParam::DIRNETLIB]->setPushFunc(CbcParamUtils::pushCbcSolverStrParam); + + parameters_[CbcParam::DIRMIPLIB]->setup( + "dirMiplib", "Set directory where the miplib 2003 problems are.", + "This sets the directory where the miplib 2003 problems reside. One can " + "get the miplib problems from COIN-OR or from the main miplib site. This " + "parameter is used only when -miplib is passed to cbc. cbc will pick up " + "the miplib problems from this directory. If cbc is built without zlib " + "support then the problems must be uncompressed.", + CoinParam::displayPriorityLow); + parameters_[CbcParam::DIRMIPLIB]->setPushFunc(CbcParamUtils::pushCbcSolverStrParam); + +} + +//########################################################################### +//########################################################################### + +void CbcParameters::addCbcSolverFileParams() { + + for (int code = CbcParam::FIRSTFILEPARAM + 1; + code < CbcParam::LASTFILEPARAM; code++) { + getParam(code)->setType(CoinParam::paramFile); + } + + parameters_[CbcParam::CSVSTATSFILE]->setup( + "csv!Statistics", "sets file name for writing out statistics", + "This appends statistics to given file name. If name is not " + "specified, the previous value will be used. " + "This is initialized to '', i.e. it must be set. " + "Adds header if file empty or does not exist.", + CoinParam::displayPriorityLow); + + parameters_[CbcParam::DEBUGFILE]->setup( + "debugF!ile", "sets name of file to read/write valid solution from/to", + "This will read a solution file from the given file name. It will use " + "the default directory given by 'directory'. If no name is specified, " + "previous value will be used. This is initialized to '', i.e. it must " + "be set.\n\nIf set to 'create' it will create a file called debug.file " + "after B&C search; if set to 'createAfterPre' it will create the file " + "before undoing preprocessing.\n\nThe idea is that if you suspect a bad " + "cut generator and you did not use preprocessing you can do a good run " + "with debug set to 'create' and then switch on the cuts you suspect and " + "re-run with debug set to 'debug.file' Similarly if you do use " + "preprocessing, but use 'createAfterPre'. The 'create' case has the " + "same effect as saveSolution.", + CoinParam::displayPriorityNone); + + parameters_[CbcParam::EXPORTFILE]->setup( + "exportF!ile", "sets name for file to export model to", + "This will set the name of the model will be written to and read from. " + "This is initialized to 'export.mps'. ", + CoinParam::displayPriorityHigh); + + parameters_[CbcParam::IMPORTFILE]->setup( + "importF!ile", "sets name for file to import model from", + "This will set the name of the model to be read in with the import " + "command. This is initialized to 'import.mps'", + CoinParam::displayPriorityHigh); + + parameters_[CbcParam::GMPLSOLFILE]->setup( + "gmplSolutionF!ile", "sets name for file to store GMPL solution in", + "This will set the name the GMPL solution will be written to and read from. " + "This is initialized to 'gmpl.sol'. ", + CoinParam::displayPriorityHigh); + + parameters_[CbcParam::MIPSTARTFILE]->setup( + "mipStartF!ile", "sets name for file to read mip start from", + "This will set the name the model will be written to and read from. " + "This is initialized to 'prob.mod'. ", + CoinParam::displayPriorityHigh); + + parameters_[CbcParam::MODELFILE]->setup( + "modelF!ile", "sets name for file to store model in", + "This will set the name the model will be written to and read from. " + "This is initialized to 'prob.mod'. ", + CoinParam::displayPriorityHigh); + + parameters_[CbcParam::NEXTSOLFILE]->setup( + "nextSolutionF!ile", "sets name for file to store suboptimal solutions " + "in", "This will set the name solutions will be written to and read " + "from. This is initialized to 'next.sol'. ", + CoinParam::displayPriorityHigh); + + parameters_[CbcParam::PRIORITYFILE]->setup( + "priorityF!ile", "Name of file to import priorities from", + "Priorities will be read from the given file name. It " + "will use the default directory given by 'directory'. " + "The default name is priorities.txt and it cannot be a compressed file." + "File is in csv format with allowed headings - name, number, priority, " + "direction, up, down, solution. Exactly one of name and number must be " + "given."); + + parameters_[CbcParam::SOLUTIONBINARYFILE]->setup( + "solBinaryF!ile", + "sets name for file to store solution in binary format", + "This will set the name the solution will be saved to and read from. " + "By default, binary solutions are written to 'solution.file'." + "use printSolution.", CoinParam::displayPriorityHigh); + + parameters_[CbcParam::SOLUTIONFILE]->setup( + "solF!ile", "sets name for file to store solution in", + "This will set the name the solution will be saved to and read from. " + "By default, solutions are written to 'opt.sol'. To print to stdout, " + "use printSolution.", CoinParam::displayPriorityHigh); + +} + +//########################################################################### +//########################################################################### + +void CbcParameters::addCbcSolverStrParams() { + + for (int code = CbcParam::FIRSTSTRINGPARAM + 1; + code < CbcParam::LASTSTRINGPARAM; code++) { + getParam(code)->setType(CoinParam::paramStr); + } + + parameters_[CbcParam::PRINTMASK]->setup( + "printM!ask", "Control printing of solution with a regular expression", + "If set then only those names which match mask are printed in a " + "solution. '?' matches any character and '*' matches any set of " + "characters. The default is '' (unset) so all variables are printed. " + "This is only active if model has names."); + parameters_[CbcParam::PRINTMASK]->setPushFunc(CbcParamUtils::doPrintMaskParam); + +} + +//########################################################################### +//########################################################################### + +void CbcParameters::addCbcSolverKwdParams() { + for (int code = CbcParam::FIRSTKWDPARAM + 1; + code < CbcParam::LASTKWDPARAM; code++) { + getParam(code)->setPushFunc(CbcParamUtils::pushCbcSolverKwdParam); + getParam(code)->setType(CoinParam::paramKwd); + } + + parameters_[CbcParam::COMMANDPRINTLEVEL]->setup( + "allC!ommands", "What priority level of commands to print", + "For the sake of your sanity, only the more useful and simple commands " + "are printed out on ?.", + CoinParam::displayPriorityNone); + parameters_[CbcParam::COMMANDPRINTLEVEL]->appendKwd("all", CbcParameters::displayHigh); + parameters_[CbcParam::COMMANDPRINTLEVEL]->appendKwd("more", CbcParameters::displayAll); + parameters_[CbcParam::COMMANDPRINTLEVEL]->appendKwd("important", CbcParameters::displayLowHigh); + + parameters_[CbcParam::CLQSTRENGTHENING]->setup( + "clqstr!engthen", + "Whether and when to perform Clique Strengthening preprocessing routine", ""); + parameters_[CbcParam::CLQSTRENGTHENING]->appendKwd("after", CbcParameters::ClqStrAfter); + parameters_[CbcParam::CLQSTRENGTHENING]->appendKwd("off", CbcParameters::ClqStrOff); + parameters_[CbcParam::CLQSTRENGTHENING]->appendKwd("before", CbcParameters::ClqStrBefore); + + parameters_[CbcParam::BRANCHPRIORITY]->setup( + "branch!Priorities", "What rule (if any) to use in prioritizing variables for branching", + "What rule (if any) to use in prioritizing variables for branching\n" + " - 'priorities' assigns highest priority to variables with largest absolute cost.\n" + " This primitive strategy can be surprisingly effective. \n" + " - 'columnorder' assigns the priorities with respect to the column ordering.\n" + " - '01first' ('01last') gives highest priority to binary variables.\n" + " - 'length' assigns high priority to variables that occur in many constraints.\n"); + parameters_[CbcParam::BRANCHPRIORITY]->appendKwd("off", CbcParameters::BPOff); + parameters_[CbcParam::BRANCHPRIORITY]->appendKwd("pri!orities", CbcParameters::BPCost); + parameters_[CbcParam::BRANCHPRIORITY]->appendKwd("column!Order", CbcParameters::BPOrder); + parameters_[CbcParam::BRANCHPRIORITY]->appendKwd("01f!irst?", CbcParameters::BPBinaryFirst); + parameters_[CbcParam::BRANCHPRIORITY]->appendKwd("01l!ast?", CbcParameters::BPBinaryLast); + parameters_[CbcParam::BRANCHPRIORITY]->appendKwd("length!?", CbcParameters::BPLength); + parameters_[CbcParam::BRANCHPRIORITY]->appendKwd("singletons", CbcParameters::BPSingleton); + parameters_[CbcParam::BRANCHPRIORITY]->appendKwd("nonzero", CbcParameters::BPNonzero); + parameters_[CbcParam::BRANCHPRIORITY]->appendKwd("general!Force?", CbcParameters::BPGeneral); + + parameters_[CbcParam::CUTOFFCONSTRAINT]->setup( + "constraint!fromCutoff", "Whether to use cutoff as constraint", + "For some problems, cut generators and general branching work better if " + "the problem would be infeasible if the cost is too high. " + "If this option is enabled, the objective function is added as a " + "constraint which right hand side is set to the current cutoff value " + "(objective value of best known solution)"); + parameters_[CbcParam::CUTOFFCONSTRAINT]->appendKwd("off", CbcParameters::COOff); + parameters_[CbcParam::CUTOFFCONSTRAINT]->appendKwd("on", CbcParameters::COOn); + parameters_[CbcParam::CUTOFFCONSTRAINT]->appendKwd("variable", CbcParameters::COVariable); + parameters_[CbcParam::CUTOFFCONSTRAINT]->appendKwd("forcevariable", CbcParameters::COForceVariable); + parameters_[CbcParam::CUTOFFCONSTRAINT]->appendKwd("conflict", CbcParameters::COConflict); + + parameters_[CbcParam::INTPRINT]->setup( + "printi!ngOptions", "Print options", + "This changes the amount and format of printing a solution:\n normal - " + "nonzero column variables \ninteger - nonzero integer column variables\n " + "special - in format suitable for OsiRowCutDebugger\n rows - nonzero " + "column variables and row activities\n all - all column variables and " + "row activities.\n\n For non-integer problems 'integer' and 'special' " + "act like 'normal'. Also see printMask for controlling output."); + parameters_[CbcParam::INTPRINT]->appendKwd("normal", CbcParameters::PMNormal); + parameters_[CbcParam::INTPRINT]->appendKwd("integer", CbcParameters::PMInteger); + parameters_[CbcParam::INTPRINT]->appendKwd("special", CbcParameters::PMSpecial); + parameters_[CbcParam::INTPRINT]->appendKwd("rows", CbcParameters::PMRows); + parameters_[CbcParam::INTPRINT]->appendKwd("all", CbcParameters::PMAll); + parameters_[CbcParam::INTPRINT]->appendKwd("csv", CbcParameters::PMCsv); + parameters_[CbcParam::INTPRINT]->appendKwd("bound!ranging", CbcParameters::PMBoundRanging); + parameters_[CbcParam::INTPRINT]->appendKwd("rhs!ranging", CbcParameters::PMRhsRanging); + parameters_[CbcParam::INTPRINT]->appendKwd("objective!ranging", + CbcParameters::PMObjectiveRanging); + parameters_[CbcParam::INTPRINT]->appendKwd("stats", CbcParameters::PMStats); + parameters_[CbcParam::INTPRINT]->appendKwd("boundsint", CbcParameters::PMBoundsInt); + parameters_[CbcParam::INTPRINT]->appendKwd("boundsall", CbcParameters::PMBoundsAll); + parameters_[CbcParam::INTPRINT]->appendKwd("fixint", CbcParameters::PMFixInt); + parameters_[CbcParam::INTPRINT]->appendKwd("fixall", CbcParameters::PMFixAll); + + parameters_[CbcParam::NODESTRATEGY]->setup( + "node!Strategy", + "What strategy to use to select the next node from the branch and cut " + "tree", + "Normally before a feasible solution is found, CBC will choose a node " + "with fewest infeasibilities. Alternatively, one may choose tree-depth " + "as the criterion. This requires the minimal amount of memory, but may " + "take a long time to find the best solution. Additionally, one may " + "specify whether up or down branches must be selected first (the up-down " + "choice will carry on after a first solution has been bound). The choice " + "'hybrid' does breadth first on small depth nodes and then switches to " + "'fewest'."); + parameters_[CbcParam::NODESTRATEGY]->appendKwd("hybrid", CbcParameters::NSHybrid); + parameters_[CbcParam::NODESTRATEGY]->appendKwd("fewest", CbcParameters::NSFewest); + parameters_[CbcParam::NODESTRATEGY]->appendKwd("depth", CbcParameters::NSDepth); + parameters_[CbcParam::NODESTRATEGY]->appendKwd("upfewest", CbcParameters::NSUpFewest); + parameters_[CbcParam::NODESTRATEGY]->appendKwd("updepth", CbcParameters::NSUpDepth); + parameters_[CbcParam::NODESTRATEGY]->appendKwd("downfewest", CbcParameters::NSDownFewest); + parameters_[CbcParam::NODESTRATEGY]->appendKwd("downdepth", CbcParameters::NSDownDepth); + + parameters_[CbcParam::ORBITAL]->setup( + "Orbit!alBranching", "Whether to try orbital branching", + "This switches on Orbital branching. Value 'on' just adds orbital, " + "'strong' tries extra fixing in strong branching."); + parameters_[CbcParam::ORBITAL]->appendKwd("off", CbcParameters::OBOff); + parameters_[CbcParam::ORBITAL]->appendKwd("slowish", CbcParameters::OBSlowish); + parameters_[CbcParam::ORBITAL]->appendKwd("strong", CbcParameters::OBStrong); + parameters_[CbcParam::ORBITAL]->appendKwd("force", CbcParameters::OBForce); + parameters_[CbcParam::ORBITAL]->appendKwd("simple", CbcParameters::OBSimple); + parameters_[CbcParam::ORBITAL]->appendKwd("on", CbcParameters::OBOn); + parameters_[CbcParam::ORBITAL]->appendKwd("moreprinting", CbcParameters::OBMorePrinting); + + parameters_[CbcParam::PREPROCESS]->setup( + "preprocess", "Whether to use integer preprocessing", + "This tries to reduce size of the model in a similar way to presolve and " + "it also tries to strengthen the model. This can be very useful and is " + "worth trying. save option saves on file presolved.mps. equal will " + "turn <= cliques into ==. sos will create sos sets if all 0-1 in sets " + "(well one extra is allowed) and no overlaps. trysos is same but allows " + "any number extra. equalall will turn all valid inequalities into " + "equalities with integer slacks. strategy is as on but uses " + "CbcStrategy."); + parameters_[CbcParam::PREPROCESS]->appendKwd("off", CbcParameters::IPPOff); + parameters_[CbcParam::PREPROCESS]->appendKwd("on", CbcParameters::IPPOn); + parameters_[CbcParam::PREPROCESS]->appendKwd("save", CbcParameters::IPPSave); + parameters_[CbcParam::PREPROCESS]->appendKwd("equal", CbcParameters::IPPEqual); + parameters_[CbcParam::PREPROCESS]->appendKwd("sos", CbcParameters::IPPSOS); + parameters_[CbcParam::PREPROCESS]->appendKwd("trysos", CbcParameters::IPPTrySOS); + parameters_[CbcParam::PREPROCESS]->appendKwd("equalall", CbcParameters::IPPEqualAll); + parameters_[CbcParam::PREPROCESS]->appendKwd("strategy", CbcParameters::IPPStrategy); + parameters_[CbcParam::PREPROCESS]->appendKwd("aggregate", CbcParameters::IPPAggregate); + parameters_[CbcParam::PREPROCESS]->appendKwd("forcesos", CbcParameters::IPPForceSOS); + parameters_[CbcParam::PREPROCESS]->appendKwd("stop!aftersaving", CbcParameters::IPPStopAfterSaving); + parameters_[CbcParam::PREPROCESS]->appendKwd("equalallstop", CbcParameters::IPPEqualAllStop); + + parameters_[CbcParam::SOSPRIORITIZE]->setup( + "sosP!rioritize", "How to deal with SOS priorities", + "This sets priorities for SOS. Values 'high' and 'low' just set a " + "priority relative to the for integer variables. Value 'orderhigh' " + "gives first highest priority to the first SOS and integer variables a " + "low priority. Value 'orderlow' gives integer variables a high priority " + "then SOS in order."); + parameters_[CbcParam::SOSPRIORITIZE]->appendKwd("off", CbcParameters::SOSOff); + parameters_[CbcParam::SOSPRIORITIZE]->appendKwd("high", CbcParameters::SOSHigh); + parameters_[CbcParam::SOSPRIORITIZE]->appendKwd("low", CbcParameters::SOSLow); + parameters_[CbcParam::SOSPRIORITIZE]->appendKwd("orderhigh", CbcParameters::SOSOrderHigh); + parameters_[CbcParam::SOSPRIORITIZE]->appendKwd("orderlow", CbcParameters::SOSOrderLow); + + parameters_[CbcParam::STRATEGY]->setup( + "strat!egy", "Switches on groups of features", + "This turns on newer features. " + "Default uses Gomory cuts with a tolerance of 0.01 at the root " + "node, does a possible restart after 100 nodes if many variables could " + "be fixed, activates a diving and RINS heuristic, and makes the " + "feasibility pump more aggressive."); // This does not apply to unit tests + // (where 'experiment' may have + // similar effects) + parameters_[CbcParam::STRATEGY]->appendKwd("easy", CbcParameters::StrategyEasy); + parameters_[CbcParam::STRATEGY]->appendKwd("default", CbcParameters::StrategyDefault); + parameters_[CbcParam::STRATEGY]->appendKwd("aggressive", CbcParameters::StrategyAggressive); + + parameters_[CbcParam::TIMEMODE]->setup( + "timeM!ode", "Whether to use CPU or elapsed time", + "cpu uses CPU time for stopping, while elapsed uses elapsed time. (On " + "Windows, elapsed time is always used)."); + parameters_[CbcParam::TIMEMODE]->appendKwd( "cpu", CbcParameters::ClockCpu); + parameters_[CbcParam::TIMEMODE]->appendKwd("elapsed", CbcParameters::ClockElapsed); + + parameters_[CbcParam::USECGRAPH]->setup( + "cgraph", + "Whether to use the conflict graph-based preprocessing and cut " + "separation routines.", + "This switches the conflict graph-based preprocessing and cut separation " + "routines (CglBKClique, CglOddWheel and CliqueStrengthening) on or off. " + "Values: \n\t off: turns these routines off;\n\t on: turns these " + "routines on; \n\t clq: turns these routines off and enables the cut " + "separator of CglClique."); + parameters_[CbcParam::USECGRAPH]->appendKwd("on", CbcParameters::CGraphOn); + parameters_[CbcParam::USECGRAPH]->appendKwd("off", CbcParameters::CGraphOff); + parameters_[CbcParam::USECGRAPH]->appendKwd("clq", CbcParameters::CGraphClique); +} + +//########################################################################### +//########################################################################### + +void CbcParameters::addCbcSolverDblParams() { + for (int code = CbcParam::FIRSTDBLPARAM + 1; + code < CbcParam::LASTDBLPARAM; code++) { + getParam(code)->setPushFunc(CbcParamUtils::pushCbcSolverDblParam); + } + + parameters_[CbcParam::ARTIFICIALCOST]->setup( + "artif!icialCost", + "Costs >= this treated as artificials in feasibility pump", 0.0, + COIN_DBL_MAX, "", CoinParam::displayPriorityLow); + + parameters_[CbcParam::DEXTRA3]->setup( + "dextra3", "Extra double parameter 3", -COIN_DBL_MAX, COIN_DBL_MAX, + "", CoinParam::displayPriorityNone); + + parameters_[CbcParam::DEXTRA4]->setup( + "dextra4", "Extra double parameter 4", -COIN_DBL_MAX, COIN_DBL_MAX, + "", CoinParam::displayPriorityNone); + + parameters_[CbcParam::DEXTRA5]->setup( + "dextra5", "Extra double parameter 5", -COIN_DBL_MAX, COIN_DBL_MAX, + "", CoinParam::displayPriorityNone); + + parameters_[CbcParam::DJFIX]->setup( + "fix!OnDj", "Try heuristic that fixes variables based on reduced costs", + -1.0e20, 1.0e20, + "If set, integer variables with reduced costs greater than the specified " + "value will be fixed before branch and bound - use with extreme " + "caution!"); + + parameters_[CbcParam::FAKECUTOFF]->setup( + "pumpC!utoff", "Fake cutoff for use in feasibility pump", -COIN_DBL_MAX, + COIN_DBL_MAX, + "A value of 0.0 means off. Otherwise, add a constraint forcing objective " + "below this value in feasibility pump", + CoinParam::displayPriorityLow); + + parameters_[CbcParam::FAKEINCREMENT]->setup( + "pumpI!ncrement", "Fake increment for use in feasibility pump", + -COIN_DBL_MAX, COIN_DBL_MAX, + "A value of 0.0 means off. Otherwise, add a constraint forcing objective " + "below this value in feasibility pump", + CoinParam::displayPriorityLow); + + parameters_[CbcParam::SMALLBAB]->setup( + "fraction!forBAB", "Fraction in feasibility pump", 1.0e-5, 1.1, + "After a pass in the feasibility pump, variables which have not moved " + "about are fixed and if the preprocessed model is smaller than this " + "fraction of the original problem, a few nodes of branch and bound are " + "done on the reduced problem.", + CoinParam::displayPriorityLow); + + parameters_[CbcParam::TIGHTENFACTOR]->setup( + "tighten!Factor", + "Tighten bounds using value times largest activity at continuous " + "solution", + 0.0, COIN_DBL_MAX, "This sleazy trick can help on some problems."); +} + +//########################################################################### +//########################################################################### + +void CbcParameters::addCbcSolverIntParams() { + + for (int code = CbcParam::FIRSTINTPARAM + 1; + code < CbcParam::LASTINTPARAM; code++) { + getParam(code)->setPushFunc(CbcParamUtils::pushCbcSolverIntParam); + } + + parameters_[CbcParam::BKPIVOTINGSTRATEGY]->setup( + "bkpivot!ing", "Pivoting strategy used in Bron-Kerbosch algorithm", 0, 6); + + parameters_[CbcParam::BKMAXCALLS]->setup( + "bkmaxcalls", + "Maximum number of recursive calls made by Bron-Kerbosch algorithm", 1, + COIN_INT_MAX); + + parameters_[CbcParam::BKCLQEXTMETHOD]->setup( + "bkclqext!method", + "Strategy used to extend violated cliques found by BK Clique Cut " + "Separation routine", + 0, 5, + "Sets the method used in the extension module of BK Clique Cut " + "Separation routine: 0=no extension; 1=random; 2=degree; 3=modified " + "degree; 4=reduced cost(inversely proportional); 5=reduced " + "cost(inversely proportional) + modified degree"); + + parameters_[CbcParam::CPP]->setup( + "cpp!Generate", "Generates C++ code", 0, 4, + "Once you like what the stand-alone solver does then this allows you to " + "generate user_driver.cpp which approximates the code. 0 gives simplest " + "driver, 1 generates saves and restores, 2 generates saves and restores " + "even for variables at default value. 4 bit in cbc generates size " + "dependent code rather than computed values."); + + parameters_[CbcParam::CUTDEPTH]->setup( + "cutD!epth", "Depth in tree at which to do cuts", -1, COIN_INT_MAX, + "Cut generators may be off, on only at the root, on if they look useful, " + "and on at some interval. If they are done every node then that is " + "that, but it may be worth doing them every so often. The original " + "method was every so many nodes but it is more logical to do it whenever " + "depth in tree is a multiple of K. This option does that and defaults " + "to -1 (off)."); + + parameters_[CbcParam::CUTLENGTH]->setup( + "cutL!ength", "Length of a cut", -1, COIN_INT_MAX, + "At present this only applies to Gomory cuts. -1 (default) leaves as is. " + "Any value >0 says that all cuts <= this length can be generated both at " + "root node and in tree. 0 says to use some dynamic lengths. If value " + ">=10,000,000 then the length in tree is value%10000000 - so 10000100 " + "means unlimited length at root and 100 in tree."); + + parameters_[CbcParam::CUTPASSINTREE]->setup( + "passT!reeCuts", + "Number of rounds that cut generators are applied in the tree", + -COIN_INT_MAX, COIN_INT_MAX, "The default is to do one pass. " + "A negative value -n means that n passes are also applied if " + "the objective does not drop."); + + parameters_[CbcParam::DEPTHMINIBAB]->setup( + "depth!MiniBab", "Depth at which to try mini branch-and-bound", + -COIN_INT_MAX, COIN_INT_MAX, + "Rather a complicated parameter but can be useful. -1 means off for " + "large problems but on as if -12 for problems where rows+columns<500, -2 " + "means use Cplex if it is linked in. Otherwise if negative then go into " + "depth first complete search fast branch and bound when depth>= -value-2 " + "(so -3 will use this at depth>=1). This mode is only switched on after " + "500 nodes. If you really want to switch it off for small problems then " + "set this to -999. If >=0 the value doesn't matter very much. The code " + "will do approximately 100 nodes of fast branch and bound every now and " + "then at depth>=5. The actual logic is too twisted to describe here."); + + parameters_[CbcParam::DIVEOPT]->setup( + "diveO!pt", "Diving options", -1, 20, + "If >2 && <20 then modify diving options - \n\t3 only at root " + "and if no solution, \n\t4 only at root and if this heuristic has " + "not got solution, \n\t5 decay only if no solution, \n\t6 " + "if depth <3 or decay, \n\t7 run up to 2 times if solution found 4 " + "otherwise, \n\t>10 All only at root (DivingC normal as " + "value-10), \n\t>20 All with value-20).", + CoinParam::displayPriorityLow); + + parameters_[CbcParam::DIVEOPTSOLVES]->setup( + "diveS!olves", "Diving solve option", -1, 200000, + "If >0 then do up to this many solves. However, the last digit is " + "ignored and used for extra options: 1-3 enables fixing of satisfied " + "integer variables (but not at bound), where 1 switches this off for " + "that dive if the dive goes infeasible, and 2 switches it off " + "permanently if the dive goes infeasible.", + CoinParam::displayPriorityLow); + + parameters_[CbcParam::DUMMY]->setup( + "sleep", "for debug", 0, 9999, + "If passed to solver from ampl, then ampl will wait so that you can copy " + ".nl file for debug.", + CoinParam::displayPriorityNone); + + parameters_[CbcParam::EXPERIMENT]->setup( + "exper!iment", "Whether to use testing features", -1, 200000, + "Defines how adventurous you want to be in using new ideas. 0 then no " + "new ideas, 1 fairly sensible, 2 a bit dubious, 3 you are on your own!", + CoinParam::displayPriorityLow); + + parameters_[CbcParam::EXTRA1]->setup( + "extra1", "Extra integer parameter 1", -COIN_INT_MAX, COIN_INT_MAX, + "", CoinParam::displayPriorityLow); + + parameters_[CbcParam::EXTRA2]->setup( + "extra2", "Extra integer parameter 2", -COIN_INT_MAX, COIN_INT_MAX, + "", CoinParam::displayPriorityLow); + + parameters_[CbcParam::EXTRA3]->setup( + "extra3", "Extra integer parameter 3", -COIN_INT_MAX, COIN_INT_MAX, + "", CoinParam::displayPriorityLow); + + parameters_[CbcParam::EXTRA4]->setup( + "extra4", "Extra integer parameter 4", -COIN_INT_MAX, COIN_INT_MAX, + "", CoinParam::displayPriorityLow); + + parameters_[CbcParam::EXTRAVARIABLES]->setup( + "extraV!ariables", "Allow creation of extra integer variables", + -COIN_INT_MAX, COIN_INT_MAX, + "Switches on a trivial re-formulation that introduces extra integer " + "variables to group together variables with same cost.", + CoinParam::displayPriorityLow); + + parameters_[CbcParam::FPUMPITS]->setup( + "passF!easibilityPump", "How many passes in feasibility pump", 0, 10000, + "This fine tunes the Feasibility Pump heuristic by doing more or fewer " + "passes."); + + parameters_[CbcParam::FPUMPTUNE]->setup( + "pumpT!une", "Dubious ideas for feasibility pump", 0, 100000000, + "This fine tunes Feasibility Pump \n\t>=10000000 use as objective " + "weight switch \n\t>=1000000 use as accumulate switch \n\t>=1000 " + "use index+1 as number of large loops \n\t==100 use objvalue " + "+0.05*fabs(objvalue) as cutoff OR fakeCutoff if set \n\t%100 == " + "10,20 affects how each solve is done \n\t1 == fix ints at bounds, 2 " + "fix all integral ints, 3 and continuous at bounds. If accumulate is on " + "then after a major pass, variables which have not moved are fixed and a " + "small branch and bound is tried."); + + parameters_[CbcParam::FPUMPTUNE2]->setup( + "moreT!une", "Yet more dubious ideas for feasibility pump", 0, 100000000, + "Yet more ideas for Feasibility Pump \n\t/100000 == 1 use box " + "constraints and original obj in cleanup \n\t/1000 == 1 Pump will " + "run twice if no solution found \n\t/1000 == 2 Pump will only run " + "after root cuts if no solution found \n\t/1000 >10 as above but " + "even if solution found \n\t/100 == 1,3.. exact 1.0 for objective " + "values \n\t/100 == 2,3.. allow more iterations per pass \n\t n " + "fix if value of variable same for last n iterations.", + CoinParam::displayPriorityNone); + + parameters_[CbcParam::HEUROPTIONS]->setup( + "hOp!tions", "Heuristic options", -COIN_INT_MAX, COIN_INT_MAX, + "Value 1 stops heuristics immediately if the allowable gap has been " + "reached. Other values are for the feasibility pump - 2 says do exact " + "number of passes given, 4 only applies if an initial cutoff has been " + "given and says relax after 50 passes, while 8 will adapt the cutoff rhs " + "after the first solution if it looks as if the code is stalling.", + CoinParam::displayPriorityLow); + + parameters_[CbcParam::LOGLEVEL]->setup( + "log!Level", "Level of detail in CBC output.", -1, 999999, + "If set to 0 then there should be no output in normal circumstances. A " + "value of 1 is probably the best value for most uses, while 2 and 3 give " + "more information."); + + parameters_[CbcParam::LPLOGLEVEL]->setup( + "lplog!Level", "Level of detail in LP solver output.", -1, 999999, + "If set to 0 then there should be no output in normal circumstances. A " + "value of 1 is probably the best value for most uses, while 2 and 3 give " + "more information."); + + parameters_[CbcParam::MAXHOTITS]->setup( + "hot!StartMaxIts", "Maximum iterations on hot start", + 0, COIN_INT_MAX); + + parameters_[CbcParam::MAXSAVEDSOLS]->setup( + "maxSaved!Solutions", "Maximum number of solutions to save", 0, + COIN_INT_MAX, "Number of solutions to save."); + + parameters_[CbcParam::MAXSLOWCUTS]->setup( + "slow!cutpasses", "Maximum number of rounds for slower cut generators", + -1, COIN_INT_MAX, + "Some cut generators are fairly slow - this limits the number of times " + "they are tried. The cut generators identified as 'may be slow' at " + "present are Lift and project cuts and both versions of Reduce and Split " + "cuts."); + + parameters_[CbcParam::MOREMOREMIPOPTIONS]->setup( + "more2!MipOptions", "More more dubious options for mip", -1, COIN_INT_MAX, + "", CoinParam::displayPriorityNone); + parameters_[CbcParam::MOREMOREMIPOPTIONS]->appendKwd("nodezero1#More strong branching at root node",8192); + parameters_[CbcParam::MOREMOREMIPOPTIONS]->appendKwd("nodezero2#More strong branching at root node - more",16384); + parameters_[CbcParam::MOREMOREMIPOPTIONS]->appendKwd("nodezero3#More strong branching at root node - yet more",24578); + parameters_[CbcParam::MOREMOREMIPOPTIONS]->appendKwd("lagrangean1#lagrangean cuts at end of root cuts",234881024); + parameters_[CbcParam::MOREMOREMIPOPTIONS]->appendKwd("lagrangean2#lagrangean cuts at end of root cuts",268435456); + parameters_[CbcParam::MOREMOREMIPOPTIONS]->appendKwd("lessused#less used cuts at beginning of root cuts",536870912); + parameters_[CbcParam::MULTIPLEROOTS]->setup( + "multiple!RootPasses", + "Do multiple root passes to collect cuts and solutions", 0, COIN_INT_MAX, + "Solve (in parallel, if enabled) the root phase this number of times, " + "each with its own different seed, and collect all solutions and cuts " + "generated. The actual format is aabbcc where aa is the number of extra " + "passes; if bb is non zero, then it is number of threads to use " + "(otherwise uses threads setting); and cc is the number of times to do " + "root phase. The solvers do not interact with each other. However if " + "extra passes are specified then cuts are collected and used in later " + "passes - so there is interaction there. Some parts of this " + "implementation have their origin in idea of Andrea Lodi, Matteo " + "Fischetti, Michele Monaci, Domenico Salvagnin, and Andrea Tramontani.", + CoinParam::displayPriorityHigh); + + parameters_[CbcParam::ODDWEXTMETHOD]->setup( + "oddwext!method", + "Strategy used to search for wheel centers for the cuts found by Odd " + "Wheel Cut Separation routine", + 0, 2, + "Sets the method used in the extension module of Odd Wheel Cut " + "Separation routine: 0=no extension; 1=one variable; 2=clique"); + + parameters_[CbcParam::OUTPUTFORMAT]->setup( + "output!Format", "Which output format to use", 1, 6, + "Normally export will be done using normal representation for numbers " + "and two values per line. You may want to do just one per line (for " + "grep or suchlike) and you may wish to save with absolute accuracy using " + "a coded version of the IEEE value. A value of 2 is normal. Otherwise, " + "odd values give one value per line, even values two. Values of 1 and 2 " + "give normal format, 3 and 4 give greater precision, 5 and 6 give IEEE " + "values. When exporting a basis, 1 does not save values, 2 saves " + "values, 3 saves with greater accuracy and 4 saves in IEEE format."); + + parameters_[CbcParam::PRINTOPTIONS]->setup( + "pO!ptions", "Dubious print options", 0, COIN_INT_MAX, + "If this is greater than 0 then presolve will give more information and " + "branch and cut will give statistics"); + + parameters_[CbcParam::PROCESSTUNE]->setup( + "tune!PreProcess", "Dubious tuning parameters for preprocessing", 0, + COIN_INT_MAX, + "Format aabbcccc - \n If aa then this is number of major passes (i.e. " + "with presolve) \n If bb and bb>0 then this is number of minor passes " + "(if unset or 0 then 10) \n cccc is bit set \n 0 - 1 Heavy probing \n 1 " + "- 2 Make variables integer if possible (if obj value)\n 2 - 4 As above " + "but even if zero objective value\n 7 - 128 Try and create cliques\n 8 - " + "256 If all +1 try hard for dominated rows\n 9 - 512 Even heavier " + "probing \n 10 - 1024 Use a larger feasibility tolerance in presolve\n " + "11 - 2048 Try probing before creating cliques\n 12 - 4096 Switch off " + "duplicate column checking for integers \n 13 - 8192 Allow scaled " + "duplicate column checking \n \n Now aa 99 has special meaning i.e. " + "just one simple presolve.", + CoinParam::displayPriorityLow); + parameters_[CbcParam::PROCESSTUNE]->appendKwd("heavy!Probing#Do more probing",7); + parameters_[CbcParam::PROCESSTUNE]->appendKwd("heavier!Probing#Do yet more probing",519); + + parameters_[CbcParam::RANDOMSEED]->setup( + "randomC!bcSeed", "Random seed for Cbc", -1, COIN_INT_MAX, + "Allows initialization of the random seed for pseudo-random numbers used " + "in heuristics such as the Feasibility Pump to decide whether to round " + "up or down. The special value of 0 lets Cbc use the time of the day for " + "the initial seed."); + + parameters_[CbcParam::STRONGSTRATEGY]->setup( + "expensive!Strong", "Whether to do even more strong branching", 0, + COIN_INT_MAX, + "Strategy for extra strong branching. 0 is normal strong branching. 1, " + "2, 4, and 6 does strong branching on all fractional variables if at the " + "root node (1), at depth less than modifier (2), objective equals best " + "possible (4), or at depth less than modifier and objective equals best " + "possible (6). 11, 12, 14, and 16 are like 1, 2, 4, and 6, " + "respecitively, but do strong branching on all integer (incl. " + "non-fractional) variables. Values >= 100 are used to specify a depth " + "limit (value/100), otherwise 5 is used. If the values >= 100, then " + "above rules are applied to value%100.", + CoinParam::displayPriorityNone); + + parameters_[CbcParam::TESTOSI]->setup("testO!si", "Test OsiObject stuff", + -1, COIN_INT_MAX, "", + CoinParam::displayPriorityNone); + +#ifdef CBC_THREAD + parameters_[CbcParam::THREADS]->setup( + "thread!s", "Number of threads to try and use", -100, 100000, + "To use multiple threads, set threads to number wanted. It may be " + "better to use one or two more than number of cpus available. If 100+n " + "then n threads and search is repeatable (maybe be somewhat slower), if " + "200+n use threads for root cuts, 400+n threads used in sub-trees.", + CoinParam::displayPriorityLow); +#endif + + parameters_[CbcParam::USERCBC]->setup( + "userCbc", "Hand coded Cbc stuff", 0, COIN_INT_MAX, + "There are times (e.g., when using AMPL interface) when you may wish to " + "do something unusual. Look for USERCBC in main driver and modify " + "sample code.", + CoinParam::displayPriorityNone); + + parameters_[CbcParam::VERBOSE]->setup( + "verbose", "Switches on longer help on single ?", 0, 15, + "Set to 1 to get short help with ? list, 2 to get long help.", + CoinParam::displayPriorityNone); + + parameters_[CbcParam::VUBTRY]->setup( + "vub!heuristic", "Type of VUB heuristic", -2, 20, + "This heuristic tries to fix some integer variables.", + CoinParam::displayPriorityNone); +} + +//########################################################################### +//########################################################################### + +void CbcParameters::addCbcSolverBoolParams() { + for (int code = CbcParam::FIRSTBOOLPARAM + 1; + code < CbcParam::LASTBOOLPARAM; code++) { + getParam(code)->setType(CoinParam::paramKwd); + getParam(code)->appendKwd("off", CbcParameters::ParamOff); + getParam(code)->appendKwd("on", CbcParameters::ParamOn); + getParam(code)->setPushFunc(CbcParamUtils::pushCbcSolverKwdParam); + } + + parameters_[CbcParam::CPX]->setup( + "cplex!Use", "Whether to use Cplex!", + "If the user has Cplex, but wants to use some of Cbc's heuristics then " + "you can! If this is on, then Cbc will get to the root node and then " + "hand over to Cplex. If heuristics find a solution this can be " + "significantly quicker. You will probably want to switch off Cbc's cuts " + "as Cplex thinks they are genuine constraints. It is also probable that " + "you want to switch off preprocessing, although for difficult problems " + "it is worth trying both."); + + parameters_[CbcParam::DOHEURISTIC]->setup( + "doH!euristic", "Do heuristics before any preprocessing", + "Normally heuristics are done in branch and bound. It may be useful to " + "do them outside. Only those heuristics with 'both' or 'before' set will " + "run. Doing this may also set cutoff, which can help with " + "preprocessing."); + + parameters_[CbcParam::ERRORSALLOWED]->setup( + "error!sAllowed", "Whether to allow import errors", + "The default is not to use any model which had errors when reading the " + "mps file. Setting this to 'on' will allow all errors from which the " + "code can recover simply by ignoring the error. There are some errors " + "from which the code can not recover, e.g., no ENDATA. This has to be " + "set before import, i.e., -errorsAllowed on -import xxxxxx.mps."); + + parameters_[CbcParam::MESSAGES]->setup( + "mess!ages", "Controls whether standardised message prefix is printed", + "By default, messages have a standard prefix, such as:\n Cbc0005 2261 " + "Objective 109.024 Primal infeas 944413 (758)\nbut this program turns " + "this off to make it look more friendly. It can be useful to turn them " + "back on if you want to be able to 'grep' for particular messages or if " + "you intend to override the behavior of a particular message."); + + parameters_[CbcParam::PREPROCNAMES]->setup( + "PrepN!ames", "If column names will be kept in pre-processed model", + "Normally the preprocessed model has column names replaced by new names " + "C0000... Setting this option to on keeps original names in variables " + "which still exist in the preprocessed problem"); + + parameters_[CbcParam::SOS]->setup( + "sos!Options", "Whether to use SOS from AMPL", + "Normally if AMPL says there are SOS variables they should be used, but " + "sometimes they should be turned off - this does so."); + + parameters_[CbcParam::USESOLUTION]->setup( + "force!Solution", "Whether to use given solution as crash for BAB", + "If on then tries to branch to solution given by AMPL or priorities " + "file."); +} + +//########################################################################### +//########################################################################### + +void CbcParameters::addCbcSolverCutParams() { + for (int code = CbcParam::FIRSTCUTPARAM + 1; + code < CbcParam::LASTCUTPARAM; code++) { + getParam(code)->setType(CoinParam::paramKwd); + getParam(code)->setPushFunc(CbcParamUtils::pushCbcSolverKwdParam); + } + + parameters_[CbcParam::CLIQUECUTS]->setup( + "clique!Cuts", "Whether to use clique cuts", + "This switches on clique cuts (either at root or in entire tree). " + "An improved version of the Bron-Kerbosch algorithm is used to separate cliques."); + + parameters_[CbcParam::CUTSTRATEGY]->setup( + "cuts!OnOff", "Switches all cuts on or off", + "This can be used to switch on or off all cuts (apart from Reduce and " + "Split). Then you can set individual ones off or on. See branchAndCut " + "for information on options."); + + parameters_[CbcParam::FLOWCUTS]->setup( + "flow!CoverCuts", "Whether to use Flow Cover cuts", + CUTS_LONGHELP + " Reference: https://github.com/coin-or/Cgl/wiki/CglFlowCover"); + + parameters_[CbcParam::GMICUTS]->setup( + "GMI!Cuts", "Whether to use alternative Gomory cuts", + CUTS_LONGHELP " This version is by Giacomo Nannicini and may be more " + "robust than gomoryCuts."); + + parameters_[CbcParam::GOMORYCUTS]->setup( + "gomory!Cuts", "Whether to use Gomory cuts", + "The original cuts - beware of imitations! Having gone out of favor, " + "they are now more fashionable as LP solvers are more robust and they " + "interact well with other cuts. They will almost always give cuts " + "(although in this executable they are limited as to number of variables " + "in cut). However the cuts may be dense so it is worth experimenting " + "(Long allows any length). " CUTS_LONGHELP + " Reference: https://github.com/coin-or/Cgl/wiki/CglGomory"); + + parameters_[CbcParam::KNAPSACKCUTS]->setup( + "knapsack!Cuts", "Whether to use Knapsack cuts", + CUTS_LONGHELP + " Reference: https://github.com/coin-or/Cgl/wiki/CglKnapsackCover"); + + parameters_[CbcParam::LAGOMORYCUTS]->setup( + "lagomory!Cuts", "Whether to use Lagrangean Gomory cuts", + "This is a gross simplification of 'A Relax-and-Cut Framework for " + "Gomory's Mixed-Integer Cuts' by Matteo Fischetti & Domenico Salvagnin. " + "This simplification just uses original constraints while modifying " + "objective using other cuts. So you don't use messy constraints " + "generated by Gomory etc. A variant is to allow non messy cuts e.g. " + "clique cuts. So 'only' does this while 'clean' also allows integral " + "valued cuts. 'End' is recommended and waits until other cuts have " + "finished before it does a few passes. The length options for gomory " + "cuts are used."); + + parameters_[CbcParam::LANDPCUTS]->setup( + "lift!AndProjectCuts", "Whether to use lift-and-project cuts", + "These cuts may be expensive to compute. " + CUTS_LONGHELP + " Reference: https://github.com/coin-or/Cgl/wiki/CglLandP"); + + parameters_[CbcParam::LATWOMIRCUTS]->setup( + "latwomir!Cuts", "Whether to use Lagrangean Twomir cuts", + "This is a Lagrangean relaxation for Twomir cuts. See lagomoryCuts for " + "description of options."); + + parameters_[CbcParam::MIRCUTS]->setup( + "mixed!IntegerRoundingCuts", "Whether to use Mixed Integer Rounding cuts", + CUTS_LONGHELP + " Reference: https://github.com/coin-or/Cgl/wiki/CglMixedIntegerRounding2"); + + parameters_[CbcParam::ODDWHEELCUTS]->setup( + "oddwheel!Cuts", "Whether to use odd wheel cuts", + "This switches on odd-wheel inequalities (either at root or in entire " + "tree)."); + + parameters_[CbcParam::PROBINGCUTS]->setup( + "probing!Cuts", "Whether to use Probing cuts", + "Value 'forceOnBut' turns on probing and forces CBC to do probing at every node, but " + "does only probing, not strengthening etc. Value 'strong' forces CBC to strongly do " + "probing at every node, that is, also when CBC would usually turn it off because it " + "hasn't found something. Value 'forceonbutstrong' is like 'forceonstrong', but does " + "only probing (column fixing) and turns off row strengthening, so the matrix will " + "not change inside the branch and bound." + "Reference: https://github.com/coin-or/Cgl/wiki/CglProbing"); + + parameters_[CbcParam::REDSPLITCUTS]->setup( + "reduce!AndSplitCuts", "Whether to use Reduce-and-Split cuts", + "These cuts may be expensive to generate. " CUTS_LONGHELP + " Reference: https://github.com/coin-or/Cgl/wiki/CglRedSplit"); + + parameters_[CbcParam::REDSPLIT2CUTS]->setup( + "reduce2!AndSplitCuts", "Whether to use Reduce-and-Split cuts - style 2", + "This switches on reduce and split cuts (either at root or in entire " + "tree). This version is by Giacomo Nannicini based on Francois Margot's version. " + "Standard setting only uses rows in tableau <= 256, long uses all. " + "These cuts may be expensive to generate. " + "See option cuts for more information on the possible values."); + + parameters_[CbcParam::RESIDCAPCUTS]->setup( + "residual!CapacityCuts", "Whether to use Residual Capacity cuts", + CUTS_LONGHELP + " Reference: https://github.com/coin-or/Cgl/wiki/CglResidualCapacity"); + + parameters_[CbcParam::TWOMIRCUTS]->setup( + "two!MirCuts", "Whether to use Two phase Mixed Integer Rounding cuts", + CUTS_LONGHELP + " Reference: https://github.com/coin-or/Cgl/wiki/CglTwomir"); + + parameters_[CbcParam::ZEROHALFCUTS]->setup( + "zero!HalfCuts", "Whether to use zero half cuts", + CUTS_LONGHELP " This implementation was written by Alberto Caprara."); + + // Populate the keyword lists + for (int code = CbcParam::FIRSTCUTPARAM + 1; + code < CbcParam::LASTCUTPARAM; code++) { + // First the common keywords + switch (code) { + case CbcParam::CUTSTRATEGY: + case CbcParam::CLIQUECUTS: + case CbcParam::FLOWCUTS: + case CbcParam::GMICUTS: + case CbcParam::GOMORYCUTS: + case CbcParam::KNAPSACKCUTS: + case CbcParam::LANDPCUTS: + case CbcParam::MIRCUTS: + case CbcParam::ODDWHEELCUTS: + case CbcParam::PROBINGCUTS: + case CbcParam::REDSPLITCUTS: + case CbcParam::RESIDCAPCUTS: + case CbcParam::TWOMIRCUTS: + case CbcParam::ZEROHALFCUTS: + parameters_[code]->appendKwd("off", CbcParameters::CGOff); + parameters_[code]->appendKwd("on", CbcParameters::CGOn); + parameters_[code]->appendKwd("root", CbcParameters::CGRoot); + parameters_[code]->appendKwd("ifmove", CbcParameters::CGIfMove); + parameters_[code]->appendKwd("forceon", CbcParameters::CGForceOn); + break; + default: + break; + } + + // Now, add some additional keywords for different classes + switch (code) { + case CbcParam::GOMORYCUTS: + parameters_[code]->appendKwd("onglobal", CbcParameters::CGOnGlobal); + parameters_[code]->appendKwd("forceandglobal", CbcParameters::CGForceAndGlobal); + parameters_[code]->appendKwd("forcelongon", CbcParameters::CGForceLongOn); + parameters_[code]->appendKwd("longer", CbcParameters::CGLonger); + parameters_[code]->appendKwd("shorter", CbcParameters::CGShorter); + break; + case CbcParam::GMICUTS: + parameters_[code]->appendKwd("endonly", CbcParameters::CGEndOnly); + parameters_[code]->appendKwd("long", CbcParameters::CGLong); + parameters_[code]->appendKwd("longroot", CbcParameters::CGLongRoot); + parameters_[code]->appendKwd("longifmove", CbcParameters::CGLongIfMove); + parameters_[code]->appendKwd("forcelongon", CbcParameters::CGForceLongOn); + parameters_[code]->appendKwd("longendonly", CbcParameters::CGLongEndOnly); + break; + case CbcParam::KNAPSACKCUTS: + parameters_[code]->appendKwd("onglobal", CbcParameters::CGOnGlobal); + parameters_[code]->appendKwd("forceandglobal", CbcParameters::CGForceAndGlobal); + break; + case CbcParam::LAGOMORYCUTS: + parameters_[code]->appendKwd("root", CbcParameters::CGRoot); + parameters_[code]->appendKwd("onlyaswellroot", CbcParameters::CGOnlyAsWellRoot); + parameters_[code]->appendKwd("cleanaswellroot", CbcParameters::CGCleanAsWellRoot); + parameters_[code]->appendKwd("bothaswellroot", CbcParameters::CGCleanBothAsWellRoot); + // Here, we intentionally drop through to the next set + case CbcParam::LATWOMIRCUTS: + parameters_[code]->appendKwd("off", CbcParameters::CGOff); + parameters_[code]->appendKwd("endonlyroot", CbcParameters::CGEndOnlyRoot); + parameters_[code]->appendKwd("endcleanroot", CbcParameters::CGEndCleanRoot); + parameters_[code]->appendKwd("endonly", CbcParameters::CGEndOnly); + parameters_[code]->appendKwd("endclean", CbcParameters::CGEndClean); + parameters_[code]->appendKwd("endboth", CbcParameters::CGEndBoth); + parameters_[code]->appendKwd("onlyaswell", CbcParameters::CGOnlyAsWell); + parameters_[code]->appendKwd("cleanaswell", CbcParameters::CGCleanAsWell); + parameters_[code]->appendKwd("bothaswell", CbcParameters::CGBothAsWell); + parameters_[code]->appendKwd("onlyinstead", CbcParameters::CGOnlyInstead); + parameters_[code]->appendKwd("cleaninstead", CbcParameters::CGCleanInstead); + parameters_[code]->appendKwd("bothinstead", CbcParameters::CGBothInstead); + break; + case CbcParam::CLIQUECUTS: + case CbcParam::FLOWCUTS: + case CbcParam::MIRCUTS: + case CbcParam::ODDWHEELCUTS: + case CbcParam::ZEROHALFCUTS: + parameters_[code]->appendKwd("onglobal", CbcParameters::CGOnGlobal); + break; + case CbcParam::LANDPCUTS: + parameters_[code]->appendKwd("iflongon", CbcParameters::CGIfLongOn); + break; + case CbcParam::PROBINGCUTS: + parameters_[code]->appendKwd("onglobal", CbcParameters::CGOnGlobal); + parameters_[code]->appendKwd("forceonglobal", CbcParameters::CGForceOnGlobal); + parameters_[code]->appendKwd("forceonbut", CbcParameters::CGForceOnBut); + parameters_[code]->appendKwd("forceonstrong", CbcParameters::CGForceOnStrong); + parameters_[code]->appendKwd("forceonbutstrong", CbcParameters::CGForceOnButStrong); + parameters_[code]->appendKwd("strongroot", CbcParameters::CGStrongRoot); + break; + case CbcParam::REDSPLIT2CUTS: + parameters_[code]->appendKwd("off", CbcParameters::CGOff); + parameters_[code]->appendKwd("on", CbcParameters::CGOn); + parameters_[code]->appendKwd("root", CbcParameters::CGRoot); + parameters_[code]->appendKwd("longon", CbcParameters::CGLongOn); + parameters_[code]->appendKwd("longroot", CbcParameters::CGLongRoot); + break; + case CbcParam::TWOMIRCUTS: + parameters_[code]->appendKwd("onglobal", CbcParameters::CGOnGlobal); + parameters_[code]->appendKwd("forceandglobal", CbcParameters::CGForceAndGlobal); + parameters_[code]->appendKwd("forcelongon", CbcParameters::CGForceLongOn); + break; + default: + break; + } + } +} + +//########################################################################### +//########################################################################### + +void CbcParameters::addCbcSolverHeurParams() { + for (int code = CbcParam::FIRSTHEURPARAM + 1; + code < CbcParam::LASTHEURPARAM; code++) { + getParam(code)->setType(CoinParam::paramKwd); + getParam(code)->setPushFunc(CbcParamUtils::pushCbcSolverKwdParam); + } + + parameters_[CbcParam::COMBINE]->setup( + "combine!Solutions", "Whether to use combine solution heuristic", + "This switches on a heuristic which does branch and cut on the problem " + "given by just using variables which have appeared in one or more " + "solutions. It is obviously only tried after two or more solutions." + HEURISTICS_LONGHELP); + + parameters_[CbcParam::CROSSOVER]->setup( + "combine2!Solutions", "Whether to use crossover solution heuristic", + "This heuristic does branch and cut on the problem given by " + "fixing variables which have the same value in two or more solutions. " + "It obviously only tries after two or more solutions. " + HEURISTICS_LONGHELP); + + parameters_[CbcParam::DINS]->setup( + "Dins", "Whether to try Distance Induced Neighborhood Search", HEURISTICS_LONGHELP); + + parameters_[CbcParam::DIVINGC]->setup( + "DivingC!oefficient", "Whether to try Coefficient diving heuristic", + HEURISTICS_LONGHELP); + + parameters_[CbcParam::DIVINGF]->setup( + "DivingF!ractional", "Whether to try Fractional diving heuristic", HEURISTICS_LONGHELP); + + parameters_[CbcParam::DIVINGG]->setup( + "DivingG!uided", "Whether to try Guided diving heuristic", HEURISTICS_LONGHELP); + + parameters_[CbcParam::DIVINGL]->setup( + "DivingL!ineSearch", "Whether to try Linesearch diving heuristic", HEURISTICS_LONGHELP); + + parameters_[CbcParam::DIVINGP]->setup( + "DivingP!seudocost", "Whether to try Pseudocost diving heuristic", HEURISTICS_LONGHELP); + + parameters_[CbcParam::DIVINGS]->setup( + "DivingS!ome", "Whether to try Diving heuristics", + "This switches on a random diving heuristic at various times. One may " + "prefer to individually turn diving heuristics on or off. " + HEURISTICS_LONGHELP); + + parameters_[CbcParam::DIVINGV]->setup( + "DivingV!ectorLength", "Whether to try Vectorlength diving heuristic", + HEURISTICS_LONGHELP); + + parameters_[CbcParam::DW]->setup( + "dw!Heuristic", "Whether to try Dantzig Wolfe heuristic", + "This heuristic is very very compute intensive. It tries to find a " + "Dantzig Wolfe structure and use that. " HEURISTICS_LONGHELP); + + parameters_[CbcParam::FPUMP]->setup( + "feas!ibilityPump", "Whether to try Feasibility Pump", + "This switches on feasibility pump heuristic at root. This is due to " + "Fischetti and Lodi and uses a sequence of LPs to try and get an integer " + "feasible solution. Some fine tuning is available by " + "passFeasibilityPump." HEURISTICS_LONGHELP); + + parameters_[CbcParam::GREEDY]->setup( + "greedy!Heuristic", "Whether to use a greedy heuristic", + "Switches on a pair of greedy heuristic which will try and obtain a " + "solution. It may just fix a percentage of variables and then try a " + "small branch and cut run." HEURISTICS_LONGHELP); + + parameters_[CbcParam::HEURISTICSTRATEGY]->setup( + "heur!isticsOnOff", "Switches most heuristics on or off", + "This can be used to switch on or off all heuristics. Then you can set " + "individual ones off or on. CbcTreeLocal is not included as it " + "dramatically alters search."); + + parameters_[CbcParam::LOCALTREE]->setup( + "local!TreeSearch", "Whether to use local tree search", + "This switches on a local search algorithm when a solution is found. " + "This is from Fischetti and Lodi and is not really a heuristic although " + "it can be used as one. When used from this program it has limited " + "functionality."); + + parameters_[CbcParam::NAIVE]->setup( + "naive!Heuristics", "Whether to try some stupid heuristic", + "This is naive heuristics which, e.g., fix all integers with costs to " + "zero!. " HEURISTICS_LONGHELP, + CoinParam::displayPriorityLow); + + parameters_[CbcParam::PIVOTANDFIX]->setup( + "pivotAndF!ix", "Whether to try Pivot and Fix heuristic", HEURISTICS_LONGHELP); + +#if 0 + parameters_[CbcParam::PIVOTANDCOMPLEMENT]->setup( + "pivotAndC!omplement", "Whether to try Pivot and Complement heuristic", + HEURISTICS_LONGHELP); +#endif + + parameters_[CbcParam::PROXIMITY]->setup( + "proximity!Search", "Whether to do proximity search heuristic", + "This heuristic looks for a solution close to the incumbent solution " + "(Fischetti and Monaci, 2012). The idea is to define a sub-MIP without " + "additional constraints but with a modified objective function intended " + "to attract the search in the proximity of the incumbent. The approach " + "works well for 0-1 MIPs whose solution landscape is not too irregular " + "(meaning the there is reasonable probability of finding an improved " + "solution by flipping a small number of binary variables), in particular " + "when it is applied to the first heuristic solutions found at the root " + "node. " HEURISTICS_LONGHELP); // Can also set different maxNode + // cbcSettings by plusnnnn (and are + // 'on'(on==30)). + + parameters_[CbcParam::RANDROUND]->setup( + "randomi!zedRounding", "Whether to try randomized rounding heuristic", + HEURISTICS_LONGHELP); + + parameters_[CbcParam::RENS]->setup( + "Rens", "Whether to try Relaxation Enforced Neighborhood Search", + HEURISTICS_LONGHELP " Value 'on' just does 50 nodes. 200, 1000, and " + "10000 does that many nodes."); + + parameters_[CbcParam::RINS]->setup( + "Rins", "Whether to try Relaxed Induced Neighborhood Search", + HEURISTICS_LONGHELP); + + parameters_[CbcParam::ROUNDING]->setup( + "round!ingHeuristic", "Whether to use Rounding heuristic", + "This switches on a simple (but effective) rounding heuristic at each " + "node of tree."); + + parameters_[CbcParam::VND]->setup( + "Vnd!VariableNeighborhoodSearch", + "Whether to try Variable Neighborhood Search", HEURISTICS_LONGHELP); + + // Populate the keyword lists + for (int code = CbcParam::FIRSTHEURPARAM + 1; + code < CbcParam::LASTHEURPARAM; code++) { + // First the common keywords + switch (code) { + case CbcParam::HEURISTICSTRATEGY: + case CbcParam::COMBINE: + case CbcParam::CROSSOVER: + case CbcParam::DINS: + case CbcParam::DIVINGC: + case CbcParam::DIVINGF: + case CbcParam::DIVINGG: + case CbcParam::DIVINGL: + case CbcParam::DIVINGP: + case CbcParam::DIVINGS: + case CbcParam::DIVINGV: + case CbcParam::DW: + case CbcParam::FPUMP: + case CbcParam::GREEDY: + case CbcParam::NAIVE: + case CbcParam::PIVOTANDFIX: + case CbcParam::PIVOTANDCOMPLEMENT: + case CbcParam::PROXIMITY: + case CbcParam::RANDROUND: + case CbcParam::RENS: + case CbcParam::RINS: + case CbcParam::ROUNDING: + case CbcParam::VND: + parameters_[code]->appendKwd("off", CbcParameters::CGOff); + parameters_[code]->appendKwd("on", CbcParameters::CGOn); + parameters_[code]->appendKwd("both", CbcParameters::CGRoot); + parameters_[code]->appendKwd("before", CbcParameters::CGIfMove); + break; + default: + break; + } + // Check the unique keywords + switch (code) { + case CbcParam::COMBINE: + parameters_[code]->appendKwd("onequick", CbcParameters::HeurOneQuick); + parameters_[code]->appendKwd("bothquick", CbcParameters::HeurBothQuick); + parameters_[code]->appendKwd("beforequick", CbcParameters::HeurBeforeQuick); + break; + case CbcParam::DINS: + parameters_[code]->appendKwd("often", CbcParameters::HeurOften); + break; + case CbcParam::LOCALTREE: + parameters_[code]->appendKwd("off", CbcParameters::HeurOff); + parameters_[code]->appendKwd("on", CbcParameters::HeurOn); + case CbcParam::PROXIMITY: + parameters_[code]->appendKwd("10", CbcParameters::HeurTen); + parameters_[code]->appendKwd("100", CbcParameters::HeurOneHundred); + parameters_[code]->appendKwd("300", CbcParameters::HeurThreeHundred); + break; + case CbcParam::RENS: + parameters_[code]->appendKwd("200", CbcParameters::HeurTwoHundred); + parameters_[code]->appendKwd("1000", CbcParameters::HeurOneThousand); + parameters_[code]->appendKwd("10000", CbcParameters::HeurTenThousand); + parameters_[code]->appendKwd("dj", CbcParameters::HeurDj); + parameters_[code]->appendKwd("djbefore", CbcParameters::HeurDjBefore); + parameters_[code]->appendKwd("usesolution", CbcParameters::HeurUseSolution); + break; + case CbcParam::RINS: + parameters_[code]->appendKwd("often", CbcParameters::HeurOften); + break; + case CbcParam::VND: + parameters_[code]->appendKwd("intree", CbcParameters::HeurInTree); + break; + default: + break; + } + } +} + +//########################################################################### +//########################################################################### + +/* Function to set up cbc (CbcModel) parameters. */ + +void CbcParameters::addCbcModelParams() +{ + + parameters_[CbcParam::ALLOWABLEGAP]->setup( + "allow!ableGap", + "Stop when gap between best possible and incumbent is less than this", + 0.0, 1.0e20, + "If the gap between best solution and best possible solution is less " + "than this then the search will be terminated. Also see ratioGap."); + + parameters_[CbcParam::CUTOFF]->setup( + "cuto!ff", "All solutions must be better than this", -1.0e60, 1.0e60, + "All solutions must be better than this value (in a minimization sense). " + " This is also set by cbc whenever it obtains a solution and is set to " + "the value of the objective for the solution minus the cutoff " + "increment."); + + parameters_[CbcParam::DIRECTION]->setup( + "direction", "Minimize or maximize", + "The default is minimize - use 'direction maximize' for " + "maximization.\nYou can also use the parameters_ 'maximize' or " + "'minimize'."); + parameters_[CbcParam::DIRECTION]->setType(CoinParam::paramKwd); + parameters_[CbcParam::DIRECTION]->appendKwd("min!imize", CbcParameters::OptDirMinimize); + parameters_[CbcParam::DIRECTION]->appendKwd("max!imize", CbcParameters::OptDirMaximize); + parameters_[CbcParam::DIRECTION]->appendKwd("zero", CbcParameters::OptDirZero); + + parameters_[CbcParam::INCREMENT]->setup( + "inc!rement", + "A new solution must be at least this much better than the incumbent", + -1.0e20, 1.0e20, + "Whenever a solution is found the bound on future solutions is set to " + "the objective of the solution (in a minimization sense) plus the " + "specified increment. If this option is not specified, the code will " + "try and work out an increment. E.g., if all objective coefficients are " + "multiples of 0.01 and only integer variables have entries in objective " + "then the increment can be set to 0.01. Be careful if you set this " + "negative!"); + + parameters_[CbcParam::INFEASIBILITYWEIGHT]->setup( + "inf!easibilityWeight", + "Each integer infeasibility is expected to cost this much", 0.0, 1.0e20, + "A primitive way of deciding which node to explore next. Satisfying " + "each integer infeasibility is expected to cost this much."); + + parameters_[CbcParam::INTEGERTOLERANCE]->setup( + "integerT!olerance", + "For an optimal solution, no integer variable may be farther than this " + "from an integer value", + 1.0e-20, 0.5, + "When checking a solution for feasibility, if the difference between the " + "value of a variable and the nearest integer is less than the integer " + "tolerance, the value is considered to be integral. Beware of setting " + "this smaller than the primal tolerance."); + + parameters_[CbcParam::MAXIMIZE]->setup( + "max!imize", "Set optimization direction to maximize", + "The default is minimize - use 'maximize' for maximization.\n A synonym " + "for 'direction maximize'.", + CoinParam::displayPriorityHigh); + parameters_[CbcParam::MAXIMIZE]->setType(CoinParam::paramAct); + + parameters_[CbcParam::MAXNODES]->setup( + "maxN!odes", "Maximum number of nodes to evaluate", 1, COIN_INT_MAX, + "This is a repeatable way to limit search. Normally using time is " + "easier but then the results may not be repeatable."); + + parameters_[CbcParam::MAXNODESNOTIMPROVING]->setup( + "maxNNI!FS", + "Maximum number of nodes to be processed without improving the incumbent " + "solution.", + -1, COIN_INT_MAX, + "This criterion specifies that when a feasible solution is available, " + "the search should continue only if better feasible solutions were " + "produced in the last nodes."); + + parameters_[CbcParam::MAXSECONDSNOTIMPROVING]->setup( + "secni!fs", "maximum seconds without improving the incumbent solution", + -1.0, COIN_DBL_MAX, + "With this stopping criterion, after a feasible solution is found, the " + "search should continue only if the incumbent solution was updated " + "recently, the tolerance is specified here. A discussion on why this " + "criterion can be useful is included here: " + "https://yetanothermathprogrammingconsultant.blogspot.com/2019/11/" + "mip-solver-stopping-criteria.html ."); + + parameters_[CbcParam::MAXSOLS]->setup( + "maxSo!lutions", "Maximum number of feasible solutions to get", 1, + COIN_INT_MAX/2, + "You may want to stop after (say) two solutions or an hour. This is " + "checked every node in tree, so it is possible to get more solutions " + "from heuristics."); + + parameters_[CbcParam::MINIMIZE]->setup( + "min!imize", "Set optimization direction to minimize", + "The default is minimize - use 'maximize' for maximization.\nThis should " + "only be necessary if you have previously set maximization. A synonym " + "for 'direction minimize'."); + parameters_[CbcParam::MINIMIZE]->setType(CoinParam::paramAct); + + parameters_[CbcParam::MIPOPTIONS]->setup( + "mipO!ptions", "Dubious options for mip", 0, COIN_INT_MAX, "", + CoinParam::displayPriorityNone); + + parameters_[CbcParam::MOREMIPOPTIONS]->setup( + "more!MipOptions", "More dubious options for mip", -1, COIN_INT_MAX, + "", CoinParam::displayPriorityNone); + +#if 0 + parameters_[CbcParam::NUMBERMINI]->setup("miniT!ree", + "Size of fast mini tree", 0, COIN_INT_MAX, + "The idea is that I can do a small tree fast. This is a first try and will" + "hopefully become more sophisticated.", CoinParam::displayPriorityNone); +#endif + + parameters_[CbcParam::NUMBERANALYZE]->setup( + "numberA!nalyze", "Number of analysis iterations", -COIN_INT_MAX, + COIN_INT_MAX, + "This says how many iterations to spend at the root node analyzing the " + "problem. This is a first try and will hopefully become more " + "sophisticated.", + CoinParam::displayPriorityNone); + + parameters_[CbcParam::REVERSE]->setup( + "reverse", "Reverses sign of objective", + "Useful for testing if maximization works correctly", + CoinParam::displayPriorityNone); + parameters_[CbcParam::REVERSE]->setType(CoinParam::paramAct); + + parameters_[CbcParam::CUTPASS]->setup( + "passC!uts", "Number of cut passes at root node", -COIN_INT_MAX, COIN_INT_MAX, + "The default is 100 passes if less than 500 columns, 100 passes (but " + "stop if the drop is small) if less than 5000 columns, 20 otherwise."); + + parameters_[CbcParam::GAPRATIO]->setup( + "ratio!Gap", + "Stop when the gap between the best possible solution and the incumbent " + "is less than this fraction of the larger of the two", + 0.0, 1.0e20, + "If the gap between the best solution and the best possible solution is " + "less than this fraction of the objective value at the root node then " + "the search will terminate. See 'allowableGap' for a way of using " + "absolute value rather than fraction."); + + parameters_[CbcParam::TIMELIMIT]->setup( + "sec!onds", "Maximum seconds for branch and cut", -1.0, 1.0e12, + "After this many seconds the program will act as if maximum nodes had " + "been reached."); + + parameters_[CbcParam::STRONGBRANCHING]->setup( + "strong!Branching", "Number of variables to look at in strong branching", + 0, 999999, + "In order to decide which variable to branch on, the code will choose up " + "to this number of unsatisfied variables and try mini up and down " + "branches. The most effective one is chosen. If a variable is branched " + "on many times then the previous average up and down costs may be used - " + "see number before trust."); + + parameters_[CbcParam::NUMBERBEFORE]->setup( + "trust!Pseudocosts", "Number of branches before we trust pseudocosts", -3, + COIN_INT_MAX, + "Using strong branching computes pseudo-costs. After this many times " + "for a variable we just trust the pseudo costs and do not do any more " + "strong branching."); + + for (int code = CbcParam::FIRSTMODELPARAM + 1; + code < CbcParam::LASTMODELPARAM; code++) { + if (getParam(code)->type() == CoinParam::paramInt){ + getParam(code)->setPushFunc(CbcParamUtils::pushCbcModelIntParam); + }else{ + getParam(code)->setPushFunc(CbcParamUtils::pushCbcModelDblParam); + } + } +} + +//########################################################################### +//########################################################################### + +/* + Access functions for cut generators. These support lazy + creation --- if mode_ is other than CGOff, an object is created if + necessary and a pointer is stored in proto_. The pointer is returned as + a generic CglCutGenerator or CbcHeuristic. The return value of the function + is the value of mode_. + + Because the model may have changed, the default for heuristics is to delete + any existing object and create a new one. This can be suppressed if desired. +*/ + +CbcParameters::CGMode CbcParameters::getClique(CglCutGenerator *&gen) { + if (clique_.mode_ != CbcParameters::CGOff && clique_.proto_ == 0) { + clique_.proto_ = new CglClique(); + clique_.proto_->setStarCliqueReport(clique_.starCliqueReport_); + clique_.proto_->setRowCliqueReport(clique_.rowCliqueReport_); + clique_.proto_->setMinViolation(clique_.minViolation_); + } + gen = dynamic_cast(clique_.proto_); + + return (clique_.mode_); +} + +CbcParameters::CGMode CbcParameters::getFlow(CglCutGenerator *&gen) + +{ + if (flow_.mode_ != CbcParameters::CGOff && flow_.proto_ == 0) { + flow_.proto_ = new CglFlowCover(); + } + gen = dynamic_cast(flow_.proto_); + + return (flow_.mode_); +} + +CbcParameters::CGMode CbcParameters::getGomory(CglCutGenerator *&gen) { + if (gomory_.mode_ != CbcParameters::CGOff && gomory_.proto_ == 0) { + gomory_.proto_ = new CglGomory(); + gomory_.proto_->setLimitAtRoot(gomory_.limitAtRoot_); + gomory_.proto_->setLimit(gomory_.limit_); + } + gen = dynamic_cast(gomory_.proto_); + + return (gomory_.mode_); +} + +CbcParameters::CGMode CbcParameters::getKnapsack(CglCutGenerator *&gen) { + if (knapsack_.mode_ != CbcParameters::CGOff && knapsack_.proto_ == 0) { + knapsack_.proto_ = new CglKnapsackCover(); + } + gen = dynamic_cast(knapsack_.proto_); + + return (knapsack_.mode_); +} + +CbcParameters::CGMode CbcParameters::getMir(CglCutGenerator *&gen) { + if (mir_.mode_ != CbcParameters::CGOff && mir_.proto_ == 0) { + mir_.proto_ = new CglMixedIntegerRounding2(); + } + gen = dynamic_cast(mir_.proto_); + + return (mir_.mode_); +} + +CbcParameters::CGMode CbcParameters::getProbing(CglCutGenerator *&gen) { + if (probing_.mode_ != CbcParameters::CGOff && probing_.proto_ == 0) { + probing_.proto_ = new CglProbing(); + probing_.proto_->setUsingObjective(probing_.usingObjective_); + probing_.proto_->setMaxPass(probing_.maxPass_); + probing_.proto_->setMaxPassRoot(probing_.maxPassRoot_); + probing_.proto_->setMaxProbe(probing_.maxProbe_); + probing_.proto_->setMaxProbeRoot(probing_.maxProbeRoot_); + probing_.proto_->setMaxLook(probing_.maxLook_); + probing_.proto_->setMaxLookRoot(probing_.maxLookRoot_); + probing_.proto_->setMaxElements(probing_.maxElements_); + probing_.proto_->setRowCuts(probing_.rowCuts_); + } + gen = dynamic_cast(probing_.proto_); + + return (probing_.mode_); +} + +CbcParameters::CGMode CbcParameters::getRedSplit(CglCutGenerator *&gen) + +{ + if (redSplit_.mode_ != CbcParameters::CGOff && redSplit_.proto_ == 0) { + redSplit_.proto_ = new CglRedSplit(); + } + gen = dynamic_cast(redSplit_.proto_); + + return (redSplit_.mode_); +} + +CbcParameters::CGMode CbcParameters::getTwomir(CglCutGenerator *&gen) { + if (twomir_.mode_ != CbcParameters::CGOff && twomir_.proto_ == 0) { + twomir_.proto_ = new CglTwomir(); + twomir_.proto_->setMaxElements(twomir_.maxElements_); + } + gen = dynamic_cast(twomir_.proto_); + + return (twomir_.mode_); +} + +CbcParameters::HeurMode CbcParameters::getFeasPump(CbcHeuristic *&gen, + bool alwaysCreate) + +{ + if (fpump_.mode_ != CbcParameters::HeurOff && + (fpump_.proto_ == 0 || alwaysCreate)) { + if (fpump_.proto_) { + delete fpump_.proto_; + } + fpump_.proto_ = new CbcHeuristicFPump(*model_); + fpump_.proto_->setMaximumPasses(fpump_.iters_); + } + gen = dynamic_cast(fpump_.proto_); + + return (fpump_.mode_); +} + +/* + Access functions for heuristics. These support lazy + creation --- if mode_ is other than HeurOff, an object is created if + necessary and a pointer is stored in proto_. The pointer is returned as + a generic CbcHeuristic. The return value of the function + is the value of mode_. + + Because the model may have changed, the default for heuristics is to delete + any existing object and create a new one. This can be suppressed if desired. +*/ + +CbcParameters::HeurMode CbcParameters::getCombine(CbcHeuristic *&gen, + bool alwaysCreate) + +{ + if (combine_.mode_ != CbcParameters::HeurOff && + (combine_.proto_ == 0 || alwaysCreate)) { + if (combine_.proto_) { + delete combine_.proto_; + } + //TODO Should we be passing a pointer here? Otherwise, making a copy + combine_.proto_ = new CbcHeuristicLocal(*model_); + combine_.proto_->setSearchType(combine_.trySwap_); + } + gen = dynamic_cast(combine_.proto_); + + return (combine_.mode_); +} + +CbcParameters::HeurMode CbcParameters::getGreedyCover(CbcHeuristic *&gen, + bool alwaysCreate) + +{ + if (greedyCover_.mode_ != CbcParameters::HeurOff && + (greedyCover_.proto_ == 0 || alwaysCreate)) { + if (greedyCover_.proto_) { + delete greedyCover_.proto_; + } + greedyCover_.proto_ = new CbcHeuristicGreedyCover(*model_); + } + gen = dynamic_cast(greedyCover_.proto_); + + return (greedyCover_.mode_); +} + +CbcParameters::HeurMode +CbcParameters::getGreedyEquality(CbcHeuristic *&gen, + bool alwaysCreate) + +{ + if (greedyEquality_.mode_ != CbcParameters::HeurOff && + (greedyEquality_.proto_ == 0 || alwaysCreate)) { + if (greedyEquality_.proto_) { + delete greedyEquality_.proto_; + } + greedyEquality_.proto_ = new CbcHeuristicGreedyEquality(*model_); + } + gen = dynamic_cast(greedyEquality_.proto_); + + return (greedyEquality_.mode_); +} + +CbcParameters::HeurMode CbcParameters::getRounding(CbcHeuristic *&gen, + bool alwaysCreate) + +{ + if (rounding_.mode_ != CbcParameters::HeurOff && + (rounding_.proto_ == 0 || alwaysCreate)) { + if (rounding_.proto_) { + delete rounding_.proto_; + } + rounding_.proto_ = new CbcRounding(*model_); + } + gen = dynamic_cast(rounding_.proto_); + + return (rounding_.mode_); +} + +CbcParameters::HeurMode +CbcParameters::getLocalTree(CbcTreeLocal *&localTree, + bool alwaysCreate) + +{ + if (localTree_.mode_ != CbcParameters::HeurOff && + (localTree_.proto_ == 0 || alwaysCreate)) { + if (localTree_.proto_) { + delete localTree_.proto_; + } + localTree_.proto_ = new CbcTreeLocal( + model_, localTree_.soln_, localTree_.range_, localTree_.typeCuts_, + localTree_.maxDiverge_, localTree_.timeLimit_, localTree_.nodeLimit_, + localTree_.refine_); + } + localTree = localTree_.proto_; + + return (localTree_.mode_); +} + +/* + A bunch of little translation helper routines leading up to a version of + setBaBStatus that figures it all out given a CbcModel and BACWhere code. + This translation needs to be centralised to avoid sprinkling magic numbers + all through the code. + + Be a bit careful with the translation routines --- they aren't sensitive to + where the search stopped. +*/ + +CbcParameters::BACMajorStatus CbcParameters::translateMajor(int status) + +{ + switch (status) { + case -1: { + return (CbcParameters::BACNotRun); + } + case 0: { + return (CbcParameters::BACFinish); + } + case 1: { + return (CbcParameters::BACStop); + } + case 2: { + return (CbcParameters::BACAbandon); + } + case 5: { + return (CbcParameters::BACUser); + } + default: { return (CbcParameters::BACInvalid); } + } +} + +CbcParameters::BACMinorStatus CbcParameters::translateMinor(int status) + +{ + switch (status) { + case -1: { + return (CbcParameters::BACmInvalid); + } + case 0: { + return (CbcParameters::BACmFinish); + } + case 1: { + return (CbcParameters::BACmInfeas); + } + case 2: { + return (CbcParameters::BACmGap); + } + case 3: { + return (CbcParameters::BACmNodeLimit); + } + case 4: { + return (CbcParameters::BACmTimeLimit); + } + case 5: { + return (CbcParameters::BACmUser); + } + case 6: { + return (CbcParameters::BACmSolnLimit); + } + case 7: { + return (CbcParameters::BACmUbnd); + } + default: { return (CbcParameters::BACmOther); } + } +} + +/* + A bit different --- given an OSI, use its interrogation functions to choose + an appropriate BACMinorStatus code. Not everything matches up, eh? +*/ +CbcParameters::BACMinorStatus +CbcParameters::translateMinor(const OsiSolverInterface *osi) + +{ + if (osi->isProvenOptimal()) { + return (CbcParameters::BACmFinish); + } else if (osi->isProvenPrimalInfeasible()) { + return (CbcParameters::BACmInfeas); + } else if (osi->isProvenDualInfeasible()) { + return (CbcParameters::BACmUbnd); + } else { + return (CbcParameters::BACmOther); + } +} + +/* + A routine to set the bab_ status block given a CbcModel and an indication + of where we're at in the search. Really, this is just a big mapping from + CbcModel codes to CbcGeneric codes. +*/ + +void CbcParameters::setBaBStatus(CbcParameters::BACWhere where, + bool haveAnswer, + OsiSolverInterface *answerSolver) + +{ + CbcParameters::BACMajorStatus major; + CbcParameters::BACMinorStatus minor; + + major = translateMajor(model_->status()); + + if (where == CbcParameters::BACwBareRoot || + where == CbcParameters::BACwIPPRelax) { + minor = translateMinor(model_->solver()); + } else { + minor = translateMinor(model_->secondaryStatus()); + } + + setBaBStatus(major, minor, where, haveAnswer, answerSolver); + + return; +} + +/* + Last, but not least, a routine to print the result. +*/ + +void CbcParameters::printBaBStatus() + +{ + std::cout << "BAC result: stopped "; + + switch (bab_.where_) { + case CbcParameters::BACwNotStarted: { + std::cout << "before root relaxation"; + break; + } + case CbcParameters::BACwBareRoot: { + std::cout << "after root relaxation"; + break; + } + case CbcParameters::BACwIPP: { + std::cout << "after integer preprocessing"; + break; + } + case CbcParameters::BACwIPPRelax: { + std::cout << "after solving preprocessed relaxation"; + break; + } + case CbcParameters::BACwBAC: { + std::cout << "after branch-and-cut"; + break; + } + default: { + std::cout << "!!invalid phase code!!"; + break; + } + } + + std::cout << std::endl << " Branch-and-cut "; + + switch (bab_.majorStatus_) { + case CbcParameters::BACNotRun: { + std::cout << "never got started"; + break; + } + case CbcParameters::BACFinish: { + std::cout << "finished"; + break; + } + case CbcParameters::BACStop: { + std::cout << "stopped on a limit"; + break; + } + case CbcParameters::BACAbandon: { + std::cout << "was abandoned"; + break; + } + case CbcParameters::BACUser: { + std::cout << "stopped due to a user event"; + break; + } + default: { + std::cout << "!!invalid major status code!!"; + break; + } + } + + std::cout << "; minor status is "; + + switch (bab_.minorStatus_) { + case CbcParameters::BACmFinish: { + std::cout << "optimal"; + break; + } + case CbcParameters::BACmInfeas: { + std::cout << "infeasible"; + break; + } + case CbcParameters::BACmUbnd: { + std::cout << "unbounded"; + break; + } + case CbcParameters::BACmGap: { + std::cout << "reached specified integrality gap."; + break; + } + case CbcParameters::BACmNodeLimit: { + std::cout << "reached node limit"; + break; + } + case CbcParameters::BACmTimeLimit: { + std::cout << "reached time limit"; + break; + } + case CbcParameters::BACmSolnLimit: { + std::cout << "reached limit on number of solutions"; + break; + } + case CbcParameters::BACmUser: { + std::cout << "stopped due to a user event"; + break; + } + case CbcParameters::BACmOther: { + std::cout << "other"; + break; + } + default: { + std::cout << "!!invalid minor status code!!"; + break; + } + } + + std::cout << "." << std::endl; +} + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 + */ diff --git a/src/CbcParameters.hpp b/src/CbcParameters.hpp new file mode 100644 index 000000000..de675043d --- /dev/null +++ b/src/CbcParameters.hpp @@ -0,0 +1,2503 @@ +/* + Copyright (C) 2007, Lou Hafer, International Business Machines Corporation + and others. All Rights Reserved. + + This code is licensed under the terms of the Eclipse Public License (EPL). + +*/ + +#ifndef CbcParameters_H +#define CbcParameters_H + +/* \file CbcParameters.hpp + \brief Declarations for parameters of Cbc. +*/ + +#include "CbcConfig.h" + +#include "CoinMessageHandler.hpp" +#include "CoinParam.hpp" + +#include "ClpParam.hpp" +#include "ClpParameters.hpp" + +#include "CglClique.hpp" +#include "CglCutGenerator.hpp" +#include "CglFlowCover.hpp" +#include "CglGMI.hpp" +#include "CglGomory.hpp" +#include "CglKnapsackCover.hpp" +#include "CglLandP.hpp" +#include "CglMixedIntegerRounding2.hpp" +#include "CglOddWheel.hpp" +#include "CglProbing.hpp" +#include "CglRedSplit.hpp" +#include "CglRedSplit2.hpp" +#include "CglResidualCapacity.hpp" +#include "CglTwomir.hpp" +#include "CglZeroHalf.hpp" + +#include "CbcModel.hpp" +#include "CbcHeuristic.hpp" +#include "CbcHeuristicDINS.hpp" +#include "CbcHeuristicDW.hpp" +#include "CbcHeuristicDive.hpp" +#include "CbcHeuristicDiveCoefficient.hpp" +#include "CbcHeuristicDiveFractional.hpp" +#include "CbcHeuristicDiveGuided.hpp" +#include "CbcHeuristicDiveLineSearch.hpp" +#include "CbcHeuristicDivePseudoCost.hpp" +#include "CbcHeuristicDiveVectorLength.hpp" +#include "CbcHeuristicFPump.hpp" +#include "CbcHeuristicGreedy.hpp" +#include "CbcHeuristicLocal.hpp" +#include "CbcHeuristicPivotAndFix.hpp" +#include "CbcHeuristicRENS.hpp" +#include "CbcHeuristicRINS.hpp" +#include "CbcHeuristicRandRound.hpp" +#include "CbcHeuristicVND.hpp" +#include "CbcParam.hpp" +#include "CbcTreeLocal.hpp" + +#include "CbcGenMessages.hpp" + +/* + It turns out that doxygen is not good with anonymous structures. Hence the + `struct name_struct' style used for structured fields in CbcParameters. +*/ + +/* + */ + +/* \brief Cbc algorithm parameters class + + This class defines and stores the parameters used to control the operation + of Cbc. +*/ + +class CBCLIB_EXPORT CbcParameters { + +public: + /*! \name Constructors and destructors */ + //@{ + + /*! \brief Constructors */ + CbcParameters(); + + CbcParameters(int strategy); + + void init(int strategy); + + /*! \brief Destructor */ + ~CbcParameters(); + + //@} + + /*! \name Enumeration types used for Cbc keyword parameters */ + //@{ + + /*! \brief Codes to specify overall strategies */ + + enum CbcStrategy { DefaultStrategy = 0 }; + + /*! \brief Codes to control integer preprocessing + + - IPPOff: Integer preprocessing is off. + - IPPOn: Integer preprocessing is on. + - IPPSave: IPPOn, plus preprocessed system will be saved to presolved.mps. + - IPPEqual: IPPOn, plus `<=' cliques are converted to `=' cliques. + - IPPSOS: IPPOn, plus will create SOS sets (see below). + - IPPTrySOS: IPPOn, plus will create SOS sets (see below). + - IPPEqualAll: IPPOn, plus turns all valid inequalities into equalities + with integer slacks. + - IPPStrategy: look to CbcStrategy object for instructions. + - IPPAggregate: ?. + - IPPForceSOS try even harder/ + - IPPStopAfterSaving :. + - IPPEqualAllStop:. + + IPPSOS will create SOS sets if all binary variables (except perhaps one) + can be covered by SOS sets with no overlap between sets. IPPTrySOS will + allow any number of binary variables to be uncovered. + */ + + enum IPPMode { + IPPOff = 0, + IPPOn, + IPPSave, + IPPEqual, + IPPSOS, + IPPTrySOS, + IPPEqualAll, + IPPStrategy, + IPPAggregate, + IPPForceSOS, + IPPStopAfterSaving, + IPPEqualAllStop, + IPPEndMarker + }; + + /*! \brief What parameters to print + + - displayAll: + - displayLowHigh: + - displayHigh: + - displayEndMarker + + */ + + enum CommandDisplayMode { + displayAll = 0, + displayLowHigh, + displayHigh, + displayEndMarker }; + + /*! \brief When to do clique strengthening + + - ClqOff: + - ClqAfter: + - ClqBefore: + - ClqEndMarker: + + */ + + enum ClqStrMode { ClqStrOff = 0, ClqStrBefore, ClqStrAfter, ClqStrEndMarker }; + + /*! \brief What node strategy to use + + - NSHybrid: + - NSFewest: + - NSDepth: + - NSUpFewest: + - NSUpDepth: + - NSDownDepth + + */ + + enum NodeStrategy { + NSHybrid = 0, + NSFewest, + NSDepth, + NSUpFewest, + NSDownFewest, + NSUpDepth, + NSDownDepth + }; + + /*! \brief What orbital branching strategy to use + + - OBOff: + - OBSlowish: + - OBStrong: + - OBForce: + - OBSimple: + - OBOn: + - OBMorePrinting: + - OBEndMarker + */ + + enum OrbitalStrategy { + OBOff = 0, + OBSlowish, + OBStrong, + OBForce, + OBSimple, + OBOn, + OBMorePrinting, + OBEndMarker + }; + + /*! \brief What SOS prioritization strategy to use + + - SOSOff: + - SOSHigh: + - SOSLow: + - SOSOrderHigh: + - SOSOrderLow: + - SOSEndMarker + */ + + enum SOSStrategy { + SOSOff = 0, + SOSHigh, + SOSLow, + SOSOrderHigh, + SOSOrderLow, + SOSEndMarker + }; + + /*! \brief What overall strategy to use + + - StrategyDefaulty = 0, + - StrategyEasy, + - StrategyAggressive, + - StrategyEndMarker + + */ + + enum StrategyMode { + StrategyEasy = 0, + StrategyDefault, + StrategyAggressive, + StrategyEndMarker + }; + + /*! \brief What clock type to use + + - Clock Cpu: Use CPU time + - ClockElapsed: Use elapsed time + + */ + + enum ClockType { ClockCpu = 0, ClockElapsed, ClockEndMarker }; + + /*! \brief What clock type to use + + - CGraphOff: + - CGraphOn: + - CGraphClique: + - CGraphEndMarker + + */ + + enum CGraphMode { CGraphOff = 0, CGraphOn, CGraphClique, CGraphEndMarker }; + + /* + In order for initialisation to work properly, the order of declaration of + the enum constants here must match the order of keyword declaration for + the various cut and heuristic control parameters in + CbcGenParamUtils::addCbcGenParams + */ + /*! \brief Codes to control the use of cut generators and heuristics + + - CGOff: the cut generator will not be installed + - CGOn: the cut generator will be installed; exactly how often it's + activated depends on the settings at installation + - CGRoot: the cut generator will be installed with settings that restrict + it to activation at the root node only. + - CGIfMove: the cut generator will be installed with settings that allow + it to remain active only so long as it's generating cuts that + tighten the relaxation. + - CGForceOn: the cut generator will be installed with settings that force + it to be called at every node + - CGForceOnBut: the cut generator will be installed with settings that + force it to be called at every node, but more active at root (probing only) + - CGEndOnly: + - CGEndClean: + - CGEndBoth: + - CGLlong: + - CGLongRoot: + - CGLongIfMove: + - CGForceLongOn: + - CGLongEndOnly: + - CGOnlyAsWell: + - CGOnlyAsWellRoot: + - CGCleanAsWell: + - CGCleanAsWellRoot: + - CGBothAsWell: + - CGBothAsWellRoot: + - CGOnlyInstead: + - CGCleanInstead: + - CGBothInstead: + - CGOnGlobal: + - CGForceAndGlobal: + - CGShorter: + - CGEndMarker: a convenience to mark the end of the codes. + + */ + + enum CGMode { + CGOff = 0, + CGOn, + CGRoot, + CGIfMove, + CGForceOn, + CGForceOnBut, + CGForceOnButStrong, + CGEndOnly, + CGEndOnlyRoot, + CGEndClean, + CGEndCleanRoot, + CGEndBoth, + CGEndBothRoot, + CGLong, + CGLongOn, + CGLongRoot, + CGLongIfMove, + CGForceAndGlobal, + CGForceLongOn, + CGForceOnGlobal, + CGForceOnStrong, + CGLongEndOnly, + CGOnlyAsWell, + CGOnlyAsWellRoot, + CGCleanAsWell, + CGCleanAsWellRoot, + CGBothAsWell, + CGBothAsWellRoot, + CGCleanBothAsWellRoot, + CGOnlyInstead, + CGCleanInstead, + CGBothInstead, + CGOnGlobal, + CGLonger, + CGShorter, + CGStrongRoot, + CGIfLongOn, + CGEndMarker + }; + + /*! \brief Codes to specify whether to use a cutoff constraint + */ + + enum CutoffMode { + COOff = 0, + COOn, + COVariable, + COForceVariable, + COConflict, + COEndMarker + }; + + /*! \brief Codes to specify the assignment of branching priorities + + - HeurOff: + - HeurOn: + - HeurBoth, + - HeurBefore, + - HuerOften, + - HeurTen, + - HeurOneHundred, + - HeurTwoHundred, + - HeurThreeHundred, + - HeurOneThousand, + - HeurTenThousand, + - HeurDj, + - HeurDjBefore, + - HeurUseSolution, + - HeurInTree, + */ + + enum HeurMode { + HeurOff = 0, + HeurOn, + HeurRoot, + HeurBoth, + HeurBefore, + HeurOften, + HeurOneQuick, + HeurBothQuick, + HeurBeforeQuick, + HeurTen, + HeurOneHundred, + HeurTwoHundred, + HeurThreeHundred, + HeurOneThousand, + HeurTenThousand, + HeurDj, + HeurDjBefore, + HeurUseSolution, + HeurInTree, + HeurEndMarker + }; + + /*! \brief Codes to specify one or off for boolean parameters + + - ParamOff: Capability is switched off + - ParamOn: Capability is switched on + */ + + enum OnOffMode { ParamOff = 0, ParamOn, ParamEndMarker }; + + /*! \brief Codes to specify the assignment of branching priorities + + - BPOff: no priorities are passed to cbc + - BPCost: a priority vector is constructed based on objective coefficients + - BPOrder: a priority vector is constructed based on column order + - BPExt: the user has provided a priority vector + */ + + enum BPMode { + BPOff = 0, + BPCost, + BPOrder, + BPBinaryFirst, + BPBinaryLast, + BPLength, + BPSingleton, + BPNonzero, + BPGeneral, + BPEndMarker }; + + /*! \brief Codes tos pecify mode for printing integers + + - PMNormal = 0, + - PMInteger, + - PMSpecial, + - PMRows, + - PMAll, + - PMEndMarker + + */ + + enum IntPrintMode { + PMNormal = 0, + PMInteger, + PMSpecial, + PMRows, + PMAll, + PMCsv, + PMBoundRanging, + PMRhsRanging, + PMObjectiveRanging, + PMStats, + PMBoundsInt, + PMBoundsAll, + PMFixInt, + PMFixAll, + PMEndMarker + }; + + /*! \brief Major status codes for branch-and-cut + + - BACInvalid: status not yet set + - BACNotRun: branch-and-cut has not yet run for the current problem + - BACFinish: branch-and-cut has finished normally + - BACStop: branch-and-cut has stopped on a limit + - BACAbandon: branch-and-cut abandoned the problem + - BACUser: branch-and-cut stopped on user signal + + Consult minorStatus_ for details. + + These codes are (mostly) set to match the codes used by CbcModel. + Additions to CbcModel codes should be reflected here and in translateMajor. + */ + + enum BACMajorStatus { + BACInvalid = -1, + BACFinish = 0, + BACStop = 1, + BACAbandon = 2, + BACNotRun, + BACUser = 5, + BacEndMarker + }; + + /*! \brief Minor status codes + + - BACmInvalid status not yet set + - BACmFinish search exhausted the tree; optimal solution + found + - BACmInfeas problem is infeasible + - BACmUbnd problem is unbounded + - BACmGap stopped on integrality gap + - BACmNodeLimit stopped on node limit + - BACmTimeLimit stopped on time limit + - BACmSolnLimit stopped on number of solutions limit + - BACmUser stopped due to user event + - BACmOther nothing else is appropriate + + It's not possible to make these codes agree with CbcModel. The meaning + varies according to context: if the BACWhere code specifies a relaxation, + then the minor status reflects the underlying OSI solver. Otherwise, it + reflects the integer problem. + */ + + enum BACMinorStatus { + BACmInvalid = -1, + BACmFinish = 0, + BACmInfeas, + BACmUbnd, + BACmGap, + BACmNodeLimit, + BACmTimeLimit, + BACmSolnLimit, + BACmUser, + BACmOther, + BACmEndMarker + }; + + /*! \brief Codes to specify where branch-and-cut stopped + + - BACwNotStarted stopped before we ever got going + - BACwBareRoot stopped after initial solve of root relaxation + - BACwIPP stopped after integer preprocessing + - BACwIPPRelax stopped after initial solve of preprocessed problem + - BACwBAC stopped at some point in branch-and-cut + */ + + enum BACWhere { + BACwInvalid = -1, + BACwNotStarted = 0, + BACwBareRoot, + BACwIPP, + BACwIPPRelax, + BACwBAC, + BACwEndMarker + }; + + enum OptimizationDirection { + OptDirMaximize = 0, + OptDirMinimize, + OptDirZero, + OptDireEndMarker + }; + + //@} + + /*! \name Operators + \brief Functions that define operators to allow access by []. + */ + + //@{ + + CbcParam *operator[](std::size_t idx){ + return getParam(idx); + } + + //@} + + /*! \name Functions for Setting Up Parameters + \brief Functions that populate the parameters objects. + */ + + //@{ + + /*! set up the solver parameter vector */ + void addCbcParams(); + void addCbcSolverStrParams(); + void addCbcSolverDirParams(); + void addCbcSolverFileParams(); + void addCbcSolverHelpParams(); + void addCbcSolverActionParams(); + void addCbcSolverKwdParams(); + void addCbcSolverDblParams(); + void addCbcSolverIntParams(); + void addCbcSolverBoolParams(); + void addCbcSolverCutParams(); + void addCbcSolverHeurParams(); + void addCbcModelParams(); + + /*! set up the default */ + void setDefaults(int strategy); + + //@} + + /*! \name Access and Control Functions for Cut Generators + \brief Control functions, plus lazy creation functions for cut + generators + + Cbc avoids creating objects for cut generators and heuristics + unless they're actually used. For cut generators, a prototype is created + and reused. For heuristics, the default is to create a new object with + each call, because the model may have changed. The object is returned + through the reference parameter. The return value of the function is the + current mode. + + Cut generator and heuristic objects created by these calls will be + deleted with the destruction of the CbcParameters object. + */ + //@{ + + /*! \brief Get cut depth setting + + The name is a bit of a misnomer. Essentially, this overrides the + `every so many nodes' control with `execute when (depth in tree) + mod (cut depth) == 0'. + */ + inline int getCutDepth() { return cutDepth_; } + + /*! \brief Get cut length setting */ + inline int getCutLength() { return cutLength_; } + + /*! \brief Get cut length setting */ + inline int getCutPassInTree() { return cutPassInTree_; } + + /*! \brief Set cut depth setting. + + See comments for getCutDepth(). + */ + inline void setCutDepth(int cutDepth) { cutDepth_ = cutDepth; } + + /*! \brief Set cut length setting. */ + inline void setCutLength(int cutLength) { cutLength_ = cutLength; } + + /*! \brief Set cut pass in tree setting. */ + inline void setCutPassInTree(int cutPassInTree) { + cutPassInTree_ = cutPassInTree; + } + + /*! \brief Obtain a prototype for a clique cut generator. */ + CbcParameters::CGMode getClique(CglCutGenerator *&gen); + + /*! \brief Set mode for use of clique cut generator. */ + inline void setCliqueMode(CbcParameters::CGMode mode) { + clique_.mode_ = mode; + } + + /*! \brief Get mode for use of clique cut generator. */ + inline CbcParameters::CGMode getCliqueMode() { return (clique_.mode_); } + + /*! \brief Obtain a prototype for a flow cover cut generator. */ + CbcParameters::CGMode getFlow(CglCutGenerator *&gen); + + /*! \brief Set mode for use of flow cover cut generator. */ + inline void setFlowMode(CbcParameters::CGMode mode) { flow_.mode_ = mode; } + + /*! \brief Get mode for use of flow cover cut generator. */ + inline CbcParameters::CGMode getFlowMode() { return (flow_.mode_); } + + /*! \brief Obtain a prototype for a GMI cut generator. */ + CbcParameters::CGMode getGMI(CglCutGenerator *&gen); + + /*! \brief Set mode for use of GMI cut generator. */ + inline void setGMIMode(CbcParameters::CGMode mode) { gmi_.mode_ = mode; } + + /*! \brief Get mode for use of GMI cut generator. */ + inline CbcParameters::CGMode getGMIMode() { return (gmi_.mode_); } + + /*! \brief Obtain a prototype for a Gomory cut generator. */ + CbcParameters::CGMode getGomory(CglCutGenerator *&gen); + + /*! \brief Set mode for use of Gomory cut generator. */ + inline void setGomoryMode(CbcParameters::CGMode mode) { + gomory_.mode_ = mode; + } + + /*! \brief Get mode for use of Gomory cut generator. */ + inline CbcParameters::CGMode getGomoryMode() { return (gomory_.mode_); } + + /*! \brief Obtain a prototype for a knapsack cover cut generator. */ + CbcParameters::CGMode getKnapsack(CglCutGenerator *&gen); + + /*! \brief Set mode for use of knapsack cut generator. */ + inline void setKnapsackMode(CbcParameters::CGMode mode) { + knapsack_.mode_ = mode; + } + + /*! \brief Get mode for use of knapsack cut generator. */ + inline CbcParameters::CGMode getKnapsackMode() { return (knapsack_.mode_); } + + /*! \brief Obtain a prototype for a LaGomory cut generator. */ + CbcParameters::CGMode getLaGomory(CglCutGenerator *&gen); + + /*! \brief Set mode for use of LaGomory cut generator. */ + inline void setLaGomoryMode(CbcParameters::CGMode mode) { + laGomory_.mode_ = mode; + } + + /*! \brief Get mode for use of LaGomory cut generator. */ + inline CbcParameters::CGMode getLaGomoryMode() { return (laGomory_.mode_); } + + /* \brief Obtain a prototype for a lift-and-project cut generator. */ + CbcParameters::CGMode getLandP(CglCutGenerator *&gen); + + /* \brief Set mode for use of lift-and-project cut generator. */ + inline void setLandPMode(CbcParameters::CGMode mode) { landP_.mode_ = mode; } + + /*! \brief Get mode for use of lift-and-project cut generator. */ + inline CbcParameters::CGMode getLandPMode() { return (landP_.mode_); } + + /*! \brief Obtain a prototype for a LaTwomir cut generator. */ + CbcParameters::CGMode getLaTwomir(CglCutGenerator *&gen); + + /*! \brief Set mode for use of LaTwomir cut generator. */ + inline void setLaTwomirMode(CbcParameters::CGMode mode) { + laTwomir_.mode_ = mode; + } + + /*! \brief Get mode for use of LaTwomir cut generator. */ + inline CbcParameters::CGMode getLaTwomirMode() { return (laTwomir_.mode_); } + + /*! \brief Obtain a prototype for a mixed integer rounding (MIR) + cut generator. + */ + CbcParameters::CGMode getMir(CglCutGenerator *&gen); + + /*! \brief Set mode for use of MIR cut generator. */ + inline void setMirMode(CbcParameters::CGMode mode) { mir_.mode_ = mode; } + + /*! \brief Get mode for use of MIR cut generator. */ + inline CbcParameters::CGMode getMirMode() { return (mir_.mode_); } + + /*! \brief Obtain a prototype for an odd wheel cut generator. */ + CbcParameters::CGMode getOddWheel(CglCutGenerator *&gen); + + /*! \brief Set mode for use of odd wheel cut generator. */ + inline void setOddWheelMode(CbcParameters::CGMode mode) { + oddWheel_.mode_ = mode; + } + + /*! \brief Get mode for use of odd wheel cut generator. */ + inline CbcParameters::CGMode getOddWheelMode() { return (oddWheel_.mode_); } + + /*! \brief Obtain a prototype for a probing cut generator. */ + CbcParameters::CGMode getProbing(CglCutGenerator *&gen); + + /*! \brief Set mode for use of probing cut generator. */ + inline void setProbingMode(CbcParameters::CGMode mode) { + probing_.mode_ = mode; + } + + /*! \brief Get mode for use of probing cut generator. */ + inline CbcParameters::CGMode getProbingMode() { return (probing_.mode_); } + + /*! \brief Obtain a prototype for a reduce and split cut generator. */ + CbcParameters::CGMode getRedSplit(CglCutGenerator *&gen); + + /*! \brief Set mode for use of reduce and split cut generator. */ + inline void setRedSplitMode(CbcParameters::CGMode mode) { + redSplit_.mode_ = mode; + } + + /*! \brief Get mode for use of reduce and split cut generator. */ + inline CbcParameters::CGMode getRedSplitMode() { return (redSplit_.mode_); } + + /*! \brief Obtain a prototype for a reduce and split 2 cut generator. */ + CbcParameters::CGMode getRedSplit2(CglCutGenerator *&gen); + + /*! \brief Set mode for use of reduce and split 2 cut generator. */ + inline void setRedSplit2Mode(CbcParameters::CGMode mode) { + redSplit2_.mode_ = mode; + } + + /*! \brief Get mode for use of reduce and split 2 cut generator. */ + inline CbcParameters::CGMode getRedSplit2Mode() { + return (redSplit2_.mode_); + } + + /*! \brief Obtain a prototype for a residual capacity cut generator. */ + CbcParameters::CGMode getResidCap(CglCutGenerator *&gen); + + /*! \brief Set mode for use of residual capacity cut generator. */ + inline void setResidCapMode(CbcParameters::CGMode mode) { + residCap_.mode_ = mode; + } + + /*! \brief Get mode for use of residual capacity cut generator. */ + inline CbcParameters::CGMode getResidCapMode() { return (residCap_.mode_); } + + /*! \brief Obtain a prototype for a 2-MIR cut generator. */ + CbcParameters::CGMode getTwomir(CglCutGenerator *&gen); + + /*! \brief Set mode for use of 2-MIR cut generator. */ + inline void setTwomirMode(CbcParameters::CGMode mode) { + twomir_.mode_ = mode; + } + + /*! \brief Get mode for use of Twomir cut generator. */ + inline CbcParameters::CGMode getTwomirMode() { return (twomir_.mode_); } + + /*! \brief Obtain a prototype for a zero-half cut generator. */ + CbcParameters::CGMode getZeroHalf(CglCutGenerator *&gen); + + /*! \brief Set mode for use of zero-half cut generator. */ + inline void setZeroHalfMode(CbcParameters::CGMode mode) { + zeroHalf_.mode_ = mode; + } + + /*! \brief Get mode for use of reduce and split cut generator. */ + inline CbcParameters::CGMode getZeroHalfMode() { return (zeroHalf_.mode_); } + + //@} + + /*! \name Access and Control Functions for Heuristics + \brief Control functions, plus lazy creation functions for cut + generators + + CBC avoids creating objects for heuristics + unless they're actually used. For cut generators, a prototype is created + and reused. For heuristics, the default is to create a new object with + each call, because the model may have changed. The object is returned + through the reference parameter. The return value of the function is the + current mode. + + Heuristic objects created by these calls will be deleted + with the destruction of the CbcParameters object. + */ + //@{ + + /*! \brief Set mode for overall control of heuristics. */ + inline CbcParameters::OnOffMode getDoHeuristicMode() { + return (doHeuristicMode_); + } + + /*! \brief Get mode for overall control of heuristics. */ + inline void + setDoHeuristicMode(CbcParameters::OnOffMode mode) { + doHeuristicMode_ = mode; + } + + /*! \brief Obtain a local search/combine heuristic. + + By default, any existing object is deleted and a new object is created and + loaded with \c model. Set alwaysCreate = false to return an existing + object if one exists. + */ + CbcParameters::HeurMode getCombine(CbcHeuristic *&gen, + bool alwaysCreate = true); + + /*! \brief Set mode for use of local search/combine heuristic. */ + inline void setCombineMode(CbcParameters::HeurMode mode) { + combine_.mode_ = mode; + } + + /*! \brief Get mode for use of local search/combine heuristic. */ + CbcParameters::HeurMode getCombineMode() { return (combine_.mode_); } + + /*! \brief Obtain a crossover heuristic. + + By default, any existing object is deleted and a new object is created and + loaded with \c model. Set alwaysCreate = false to return an existing + object if one exists. + */ + CbcParameters::HeurMode getCrossover(CbcHeuristic *&gen, + bool alwaysCreate = true); + + /*! \brief Set mode for use of crossover heuristic. */ + inline void setCrossoverMode(CbcParameters::HeurMode mode) { + crossover_.mode_ = mode; + } + + /*! \brief Get mode for use of crossover heuristic. */ + CbcParameters::HeurMode getCrossoverMode() { return (crossover_.mode_); } + + /*! \brief Obtain a DINS heuristic. + + By default, any existing object is deleted and a new object is created and + loaded with \c model. Set alwaysCreate = false to return an existing + object if one exists. + */ + CbcParameters::HeurMode getDins(CbcHeuristic *&gen, + bool alwaysCreate = true); + + /*! \brief Set mode for use of DINS heuristic. */ + inline void setDinsMode(CbcParameters::HeurMode mode) { dins_.mode_ = mode; } + + /*! \brief Get mode for use of DINS heuristic. */ + CbcParameters::HeurMode getDinsMode() { return (dins_.mode_); } + + /*! \brief Obtain a Diving Coefficient heuristic. + + By default, any existing object is deleted and a new object is created and + loaded with \c model. Set alwaysCreate = false to return an existing + object if one exists. + */ + CbcParameters::HeurMode getDiveCofficient(CbcHeuristic *&gen, + bool alwaysCreate = true); + + /*! \brief Set mode for use of Diving Coefficient heuristic. */ + inline void setDiveCoefficientMode(CbcParameters::HeurMode mode) { + divingc_.mode_ = mode; + } + + /*! \brief Get mode for use of Diving Coefficient heuristic. */ + CbcParameters::HeurMode getDiveCoefficientMode() { return (divingc_.mode_); } + + /*! \brief Obtain a Diving Fractional heuristic. + + By default, any existing object is deleted and a new object is created and + loaded with \c model. Set alwaysCreate = false to return an existing + object if one exists. + */ + CbcParameters::HeurMode getDiveFractional(CbcHeuristic *&gen, + bool alwaysCreate = true); + + /*! \brief Set mode for use of Diving Coefficient heuristic. */ + inline void setDiveFractionalMode(CbcParameters::HeurMode mode) { + divingf_.mode_ = mode; + } + + /*! \brief Get mode for use of Diving Fractional heuristic. */ + CbcParameters::HeurMode getDiveFractionalMode() { return (divingf_.mode_); } + + /*! \brief Obtain a Diving Guided heuristic. + + By default, any existing object is deleted and a new object is created and + loaded with \c model. Set alwaysCreate = false to return an existing + object if one exists. + */ + CbcParameters::HeurMode getDiveGuided(CbcHeuristic *&gen, + bool alwaysCreate = true); + + /*! \brief Set mode for use of Diving Guided heuristic. */ + inline void setDiveGuidedMode(CbcParameters::HeurMode mode) { + divingg_.mode_ = mode; + } + + /*! \brief Get mode for use of Diving Guided heuristic. */ + CbcParameters::HeurMode getDiveGuidedMode() { return (divingg_.mode_); } + + /*! \brief Obtain a Diving Line Search heuristic. + + By default, any existing object is deleted and a new object is created and + loaded with \c model. Set alwaysCreate = false to return an existing + object if one exists. + */ + CbcParameters::HeurMode getDiveLineSearch(CbcHeuristic *&gen, + bool alwaysCreate = true); + + /*! \brief Set mode for use of Diving Line Search heuristic. */ + inline void setDiveLineSearchMode(CbcParameters::HeurMode mode) { + divingl_.mode_ = mode; + } + + /*! \brief Get mode for use of Diving LineSearch heuristic. */ + CbcParameters::HeurMode getDiveLineSearchMode() { return (divingl_.mode_); } + + /*! \brief Obtain a Diving Pseudocost heuristic. + + By default, any existing object is deleted and a new object is created and + loaded with \c model. Set alwaysCreate = false to return an existing + object if one exists. + */ + CbcParameters::HeurMode getDivePseudocost(CbcHeuristic *&gen, + bool alwaysCreate = true); + + /*! \brief Set mode for use of Diving Pseudocost heuristic. */ + inline void setDivePseudocostMode(CbcParameters::HeurMode mode) { + divingp_.mode_ = mode; + } + + /*! \brief Get mode for use of Diving Pseudocost heuristic. */ + CbcParameters::HeurMode getDivePseudocostMode() { return (divingp_.mode_); } + + /*! \brief Set mode for use of rand. */ + inline void setDiveRandomMode(CbcParameters::HeurMode mode) { + randomDivingMode_ = mode; + } + + /*! \brief Get mode for use of Diving Pseudocost heuristic. */ + CbcParameters::HeurMode getDiveRandomMode() { return (randomDivingMode_); } + + /*! \brief Obtain a Diving Vector Length heuristic. + + By default, any existing object is deleted and a new object is created and + loaded with \c model. Set alwaysCreate = false to return an existing + object if one exists. + */ + CbcParameters::HeurMode getDiveVectorLength(CbcHeuristic *&gen, + bool alwaysCreate = true); + + /*! \brief Set mode for use of Diving Vector Length heuristic. */ + inline void setDiveVectorLengthMode(CbcParameters::HeurMode mode) { + divingv_.mode_ = mode; + } + + /*! \brief Get mode for use of Diving Vector Length heuristic. */ + CbcParameters::HeurMode getDiveVectorLengthMode() { + return (divingv_.mode_); + } + + /*! \brief Obtain a DW heuristic. + + By default, any existing object is deleted and a new object is created and + loaded with \c model. Set alwaysCreate = false to return an existing + object if one exists. + */ + CbcParameters::HeurMode getDW(CbcHeuristic *&gen, + bool alwaysCreate = true); + + /*! \brief Set mode for use of DW heuristic. */ + inline void setDWMode(CbcParameters::HeurMode mode) { dw_.mode_ = mode; } + + /*! \brief Get mode for use of DW heuristic. */ + CbcParameters::HeurMode getDWMode() { return (dw_.mode_); } + + /*! \brief Obtain a feasibility pump heuristic. + + By default, any existing object is deleted and a new object is created and + loaded with \c model. Set alwaysCreate = false to return an existing + object if one exists. + */ + CbcParameters::HeurMode getFeasPump(CbcHeuristic *&gen, + bool alwaysCreate = true); + + /*! \brief Set mode for use of feasibility pump heuristic. */ + inline void setFeasPumpMode(CbcParameters::HeurMode mode) { + fpump_.mode_ = mode; + } + + /*! \brief Get mode for use of feasibility pump heuristic. */ + CbcParameters::HeurMode getFeasPumpMode() { return (fpump_.mode_); } + + /*! \brief Set iterations for use of feasibility pump heuristic. */ + inline void setFeasPumpIters(int iters) { fpump_.iters_ = iters; } + + /*! \brief Get iterations for use of feasibility pump heuristic. */ + inline int getFeasPumpIters() { return (fpump_.iters_); } + + /*! \brief Set tune mode for use of feasibility pump heuristic. */ + inline void setFeasPumpTune(int tune) { fpump_.tune_ = tune; } + + /*! \brief Get tune mode for use of feasibility pump heuristic. */ + inline int getFeasPumpTune() { return (fpump_.tune_); } + + /*! \brief Set second tune mode for use of feasibility pump heuristic. */ + inline void setFeasPumpTune2(int tune2) { fpump_.tune2_ = tune2; } + + /*! \brief Get second tune mode for use of feasibility pump heuristic. */ + inline int getFeasPumpTune2(int tune2) { return (fpump_.tune2_); } + + /*! \brief Set fake cutoff for use of feasibility pump heuristic. */ + inline void setFeasPumpFakeCutoff(double cutoff) { fpump_.cutoff_ = cutoff; } + + /*! \brief Get fake cutoff for use of feasibility pump heuristic. */ + inline double getFeasPumpFakeCutoff() { return (fpump_.cutoff_); } + + /*! \brief Set fake increment for use of feasibility pump heuristic. */ + inline void setFeasPumpFakeIncrement(double increment) { + fpump_.increment_ = increment; + } + + /*! \brief Get fake increment for use of feasibility pump heuristic. */ + inline double getFeasPumpFakeIncrement() { return (fpump_.increment_); } + + /*! \brief Obtain a greedy cover heuristic. + + By default, any existing object is deleted and a new object is created and + loaded with \c model. Set alwaysCreate = false to return an existing + object if one exists. + */ + CbcParameters::HeurMode getGreedyCover(CbcHeuristic *&gen, + bool alwaysCreate = true); + + /*! \brief Set mode for use of greedy cover heuristic. */ + inline void setGreedyCoverMode(CbcParameters::HeurMode mode) { + greedyCover_.mode_ = mode; + } + + /*! \brief Get mode for use of greedy cover heuristic. */ + CbcParameters::HeurMode getGreedyCoverMode() { return (greedyCover_.mode_); } + + /*! \brief Obtain a greedy equality heuristic. + + By default, any existing object is deleted and a new object is created and + loaded with \c model. Set alwaysCreate = false to return an existing + object if one exists. + */ + CbcParameters::HeurMode getGreedyEquality(CbcHeuristic *&gen, + bool alwaysCreate = true); + + /*! \brief Set mode for use of greedy equality heuristic. */ + inline void setGreedyEqualityMode(CbcParameters::HeurMode mode) { + greedyEquality_.mode_ = mode; + } + + /*! \brief Get mode for use of greedy equality heuristic. */ + CbcParameters::HeurMode getGreedyEqualityMode() { + return (greedyEquality_.mode_); + } + + /*! \brief Obtain a Naive heuristic. + + By default, any existing object is deleted and a new object is created and + loaded with \c model. Set alwaysCreate = false to return an existing + object if one exists. + */ + CbcParameters::HeurMode getNaiveHeur(CbcHeuristic *&gen, + bool alwaysCreate = true); + + /*! \brief Set mode for use of Naive heuristic. */ + inline void setNaiveHeurMode(CbcParameters::HeurMode mode) { + naive_.mode_ = mode; + } + + /*! \brief Get mode for use of Naive heuristic. */ + CbcParameters::HeurMode getNaiveHeurMode() { return (divingc_.mode_); } + + /*! \brief Obtain a Pivot And Fix heuristic. + + By default, any existing object is deleted and a new object is created and + loaded with \c model. Set alwaysCreate = false to return an existing + object if one exists. + */ + CbcParameters::HeurMode getPivotAndFix(CbcHeuristic *&gen, + bool alwaysCreate = true); + + /*! \brief Set mode for use of Pivot and Fix heuristic. */ + + inline void setPivotAndFixMode(CbcParameters::HeurMode mode) { + pivotAndFix_.mode_ = mode; + } + + /*! \brief Get mode for use of pivot and fix heuristic. */ + CbcParameters::HeurMode getPivotAndFixMode() { return (pivotAndFix_.mode_); } + +#if 0 + /*! \brief Obtain a Pivot and Complement heuristic. + + By default, any existing object is deleted and a new object is created and + loaded with \c model. Set alwaysCreate = false to return an existing object + if one exists. + */ + CbcParameters::HeurMode getPivotAndComplement(CbcHeuristic *&gen, + bool alwaysCreate = true); + + /*! \brief Set mode for use of Pivot and Complement heuristic. */ + inline void setPivotAndComplementMode(CbcParameters::HeurMode mode) + { + pivotandcomplement_.mode_ = mode; + } + + /*! \brief Get mode for use of pivot and complement heuristic. */ + CbcParameters::HeurMode getPivotAndComplementMode() + { + return(pivotAndComplement_.mode_); + } +#endif + + /*! \brief Obtain a Proximity heuristic. + + By default, any existing object is deleted and a new object is created and + loaded with \c model. Set alwaysCreate = false to return an existing + object if one exists. + */ + CbcParameters::HeurMode getProximity(CbcHeuristic *&gen, + bool alwaysCreate = true); + + /*! \brief Set mode for use of Proximity heuristic. */ + inline void setProximityMode(CbcParameters::HeurMode mode) { + proximity_.mode_ = mode; + } + + /*! \brief Get mode for use of proximity heuristic. */ + CbcParameters::HeurMode getProximityMode() { return (proximity_.mode_); } + + /*! \brief Obtain a Randomized Rounding heuristic. + + By default, any existing object is deleted and a new object is created and + loaded with \c model. Set alwaysCreate = false to return an existing + object if one exists. + */ + CbcParameters::HeurMode getRandRound(CbcHeuristic *&gen, + bool alwaysCreate = true); + + /*! \brief Set mode for use of Randomized Rounding heuristic. */ + inline void setRandRoundMode(CbcParameters::HeurMode mode) { + randRound_.mode_ = mode; + } + + /*! \brief Get mode for use of randomized rounding heuristic. */ + CbcParameters::HeurMode getRandRoundMode() { return (randRound_.mode_); } + + /*! \brief Obtain a RENS heuristic. + + By default, any existing object is deleted and a new object is created and + loaded with \c model. Set alwaysCreate = false to return an existing + object if one exists. + */ + CbcParameters::HeurMode getRens(CbcHeuristic *&gen, + bool alwaysCreate = true); + + /*! \brief Set mode for use of RENS heuristic. */ + inline void setRensMode(CbcParameters::HeurMode mode) { rens_.mode_ = mode; } + + /*! \brief Get mode for use of RENS heuristic. */ + CbcParameters::HeurMode getRensMode() { return (rens_.mode_); } + + /*! \brief Obtain a RINS heuristic. + + By default, any existing object is deleted and a new object is created and + loaded with \c model. Set alwaysCreate = false to return an existing + object if one exists. + */ + CbcParameters::HeurMode getRins(CbcHeuristic *&gen, + bool alwaysCreate = true); + + /*! \brief Set mode for use of RINS heuristic. */ + inline void setRinsMode(CbcParameters::HeurMode mode) { rins_.mode_ = mode; } + + /*! \brief Get mode for use of RINS heuristic. */ + CbcParameters::HeurMode getRinsMode() { return (rins_.mode_); } + + /*! \brief Obtain a simple rounding heuristic. + + By default, any existing object is deleted and a new object is created and + loaded with \c model. Set alwaysCreate = false to return an existing + object if one exists. + */ + CbcParameters::HeurMode getRounding(CbcHeuristic *&gen, + bool alwaysCreate = true); + + /*! \brief Set mode for use of simple rounding heuristic. */ + inline void setRoundingMode(CbcParameters::HeurMode mode) { + rounding_.mode_ = mode; + } + + /*! \brief Get mode for use of rounding heuristic. */ + CbcParameters::HeurMode getRoundingMode() { return (rounding_.mode_); } + + /*! \brief Obtain a variable neighborhood heuristic. + + By default, any existing object is deleted and a new object is created and + loaded with \c model. Set alwaysCreate = false to return an existing + object if one exists. + */ + CbcParameters::HeurMode getVnd(CbcHeuristic *&gen, + bool alwaysCreate = true); + + /*! \brief Set mode for use of variable neighborhood heuristic. */ + inline void setVndMode(CbcParameters::HeurMode mode) { vnd_.mode_ = mode; } + + /*! \brief Get mode for use of variable neighborhood heuristic. */ + CbcParameters::HeurMode getVndMode() { return (vnd_.mode_); } + + /*! \brief Obtain a local search tree object + + By default, any existing object is deleted and a new object is created and + loaded with \c model. Set alwaysCreate = false to return an existing + object if one exists. + */ + CbcParameters::HeurMode getLocalTree(CbcTreeLocal *&localTree, + bool alwaysCreate = true); + + /*! \brief Set mode for use of local tree. */ + inline void setLocalTreeMode(CbcParameters::HeurMode mode) { + localTree_.mode_ = mode; + } + + /*! \brief Get mode for use of Diving Coefficient heuristic. */ + CbcParameters::HeurMode getLocalTreeMode() { return (localTree_.mode_); } + + //@} + + /*! \name Miscellaneous Integer Parameters + + */ + + //@{ + + /*! \brief Get BkPivotStrategy setting */ + inline int getBkPivotStrategy() { return bkPivotStrategy_; } + + /*! \brief Set BkPivotStrategy setting */ + inline void setBkPivotStrategy(int bkPivotStrategy) { + bkPivotStrategy_ = bkPivotStrategy; + } + + /*! \brief Get BkMaxCalls setting */ + inline int getBkMaxCalls() { return bkMaxCalls_; } + + /*! \brief Set BkMaxCalls setting */ + inline void setBkMaxCalls(int bkMaxCalls) { bkMaxCalls_ = bkMaxCalls; } + + /*! \brief Get BkClqExtMethod setting */ + inline int getBkClqExtMethod() { return bkClqExtMethod_; } + + /*! \brief Set BkClqExtMethod setting */ + inline void setBkClqExtMethod(int bkClqExtMethod) { + bkClqExtMethod_ = bkClqExtMethod; + } + + /*! \brief Get CppMode setting */ + inline int getCppMode() { return cppMode_; } + + /*! \brief Set CppMode setting */ + inline void setCppMode(int cppMode) { cppMode_ = cppMode; } + + /*! \brief Get DepthMiniBaB setting */ + inline int getDepthMiniBaB() { return depthMiniBaB_; } + + /*! \brief Set DepthMiniBaB setting */ + inline void setDepthMiniBaB(int depthMiniBaB) { + depthMiniBaB_ = depthMiniBaB; + } + + /*! \brief Get DiveOpt setting */ + inline int getDiveOpt() { return diveOpt_; } + + /*! \brief Set DiveOpt setting */ + inline void setDiveOpt(int diveOpt) { diveOpt_ = diveOpt; } + + /*! \brief Get DiveOptSolves setting */ + inline int getDiveOptSolves() { return diveOptSolves_; } + + /*! \brief Set DiveOptSolves setting */ + inline void setDiveOptSolves(int diveOptSolves) { + diveOptSolves_ = diveOptSolves; + } + + /*! \brief Get ExperimentMode setting */ + inline int getExperimentMode() { return experiment_; } + + /*! \brief Set ExperimentMode setting */ + inline void setExperimentMode(int experimentMode) { + experiment_ = experimentMode; + } + + /*! \brief Get ExtraIntParam1 setting */ + inline int getExtraIntParam1() { return extraInt1_; } + + /*! \brief Set ExtraIntParam1 setting */ + inline void setExtraIntParam1(int extraInt1) { extraInt1_ = extraInt1; } + + /*! \brief Get ExtraIntParam2 setting */ + inline int getExtraIntParam2() { return extraInt2_; } + + /*! \brief Set ExtraIntParam2 setting */ + inline void setExtraIntParam2(int extraInt2) { extraInt2_ = extraInt2; } + + /*! \brief Get ExtraIntParam3 setting */ + inline int getExtraIntParam3() { return extraInt3_; } + + /*! \brief Set ExtraIntParam3 setting */ + inline void setExtraIntParam3(int extraInt3) { extraInt3_ = extraInt3; } + + /*! \brief Get ExtraIntParam4 setting */ + inline int getExtraIntParam4() { return extraInt4_; } + + /*! \brief Set ExtraIntParam4 setting */ + inline void setExtraIntParam4(int extraInt4) { extraInt4_ = extraInt4; } + + /*! \brief Get HeurOptions setting */ + inline int getHeurOptions() { return heurOptions_; } + + /*! \brief Set HeurOptions setting */ + inline void setHeurOptions(int heurOptions) { heurOptions_ = heurOptions; } + + /*! \brief Get MaxSavedSols setting */ + inline int getMaxSavedSols() { return maxSavedSols_; } + + /*! \brief Set MaxSavedSols setting */ + inline void setMaxSavedSols(int maxSavedSols) { + maxSavedSols_ = maxSavedSols; + } + + /*! \brief Get MaxSlowCuts setting */ + inline int getMaxSlowCuts() { return maxSlowCuts_; } + + /*! \brief Set MaxSlowCuts setting */ + inline void setMaxSlowCuts(int maxSlowCuts) { maxSlowCuts_ = maxSlowCuts; } + + /*! \brief Get MoreMoreOptions setting */ + inline int getMoreMoreOptions() { return moreMoreOptions_; } + + /*! \brief Set MoreMoreOptions setting */ + inline void setMoreMoreOptions(int moreMoreOptions) { + moreMoreOptions_ = moreMoreOptions; + } + + /*! \brief Get MultipleRoots setting */ + inline int getMultipleRoots() { return multipleRoots_; } + + /*! \brief Set MultipleRoots setting */ + inline void setMultipleRoots(int multipleRoots) { + multipleRoots_ = multipleRoots; + } + + /*! \brief Get OddWextMethod setting */ + inline int getOddWextMethod() { return oddWextMethod_; } + + /*! \brief Set OddWextMethod setting */ + inline void setOddWextMethod(int oddWextMethod) { + oddWextMethod_ = oddWextMethod; + } + + /*! \brief Get OutputFormat setting */ + inline int getOutputFormat() { return outputFormat_; } + + /*! \brief Set OutputFormat setting */ + inline void setOutputFormat(int outputFormat) { + outputFormat_ = outputFormat; + } + + /*! \brief Get PrintOptions setting */ + inline int getPrintOptions() { return printOpt_; } + + /*! \brief Set PrintOptions setting */ + inline void setPrintOptions(int printOpt) { printOpt_ = printOpt; } + + /*! \brief Enable printing */ + inline void enablePrinting() { noPrinting_ = false; } + + /*! \brief Disable printing */ + inline void disablePrinting() { noPrinting_ = true; } + + /*! \brief Get printing status*/ + inline bool noPrinting() { return noPrinting_; } + + /*! \brief Enable welcome printing */ + inline void enableWelcomePrinting() { printWelcome_ = true; } + + /*! \brief Disable welcome printing */ + inline void disableWelcomePrinting() { printWelcome_ = false; } + + /*! \brief Get welcome printing status */ + inline bool printWelcome() { return printWelcome_; } + + /*! \brief Enable signal handler */ + inline void enableSignalHandler() { useSignalHandler_ = true; } + + /*! \brief Disable signal handler */ + inline void disableSignalHandler() { useSignalHandler_ = false; } + + /*! \brief Get signal handler status*/ + inline bool useSignalHandler() { return useSignalHandler_; } + + /*! \brief Get ProcessTune setting */ + inline int getProcessTune() { return processTune_; } + + /*! \brief Set ProcessTune setting */ + inline void setProcessTune(int processTune) { processTune_ = processTune; } + + /*! \brief Get RandomSeed setting */ + inline int getRandomSeed() { return randomSeed_; } + + /*! \brief Set RandomSeed setting */ + inline void setRandomSeed(int randomSeed) { randomSeed_ = randomSeed; } + + /*! \brief Get StrongStrategy setting */ + inline int getStrongStrategy() { return strongStrategy_; } + + /*! \brief Set StrongStrategy setting */ + inline void setStrongStrategy(int strongStrategy) { + strongStrategy_ = strongStrategy; + } + + /*! \brief Get TestOsi setting */ + inline int getTestOsi() { return testOsi_; } + + /*! \brief Set TestOsi setting */ + inline void setTestOsi(int testOsi) { testOsi_ = testOsi; } + + /*! \brief Get Threads setting */ + inline int getThreads() { return threads_; } + + /*! \brief Set Threads setting */ + inline void setThreads(int threads) { threads_ = threads; } + + /*! \brief Get UserCbc setting */ + inline int getUserCbc() { return userCbc_; } + + /*! \brief Set UserCbc setting */ + inline void setUserCbc(int userCbc) { userCbc_ = userCbc; } + + /*! \brief Get Verbose setting */ + inline int getVerbose() { return verbose_; } + + /*! \brief Set Verbose setting */ + inline void setVerbose(int verbose) { verbose_ = verbose; } + + /*! \brief Get VubTry setting */ + inline int getVubTry() { return vubTry_; } + + /*! \brief Set VubTry setting */ + inline void setVubTry(int vubTry) { vubTry_ = vubTry; } + + //@} + + /*! \name Miscellaneous Double Parameters + + */ + + //@{ + + /*! \brief Get extra double 3 setting */ + inline double getExtraDbl3() { return extraDbl3_; } + + /*! \brief Set extra double 3 setting */ + inline void setExtraDbl3(double extraDbl3) { extraDbl3_ = extraDbl3; } + + /*! \brief Get extra double 4 setting */ + inline double getExtraDbl4() { return extraDbl4_; } + + /*! \brief Set extra double 4 setting */ + inline void setExtraDbl4(double extraDbl4) { extraDbl4_ = extraDbl4; } + + /*! \brief Get extra double 3 setting */ + inline double getExtraDbl5() { return extraDbl5_; } + + /*! \brief Set extra double 5 setting */ + inline void setExtraDbl5(double extraDbl5) { extraDbl5_ = extraDbl5; } + + /*! \brief Get small branch and bound setting */ + inline double getSmallBaB() { return smallBaB_; } + + /*! \brief Set small branch and bound setting */ + inline void setSmallBab(double smallBaB) { smallBaB_ = smallBaB; } + + /*! \brief Get tighten factor */ + inline double getTightenFactor() { return tightenFactor_; } + + /*! \brief Set tighten factor + + */ + + inline void setTightenFactor(double tightenFactor) { + tightenFactor_ = tightenFactor; + } + + //@} + + /*! \name Miscellaneous Keyword Parameters + + */ + + //@{ + + /*! \brief Get command mode */ + inline CbcParameters::CommandDisplayMode getCommandDisplayMode() { + return (commandDisplayMode_); + } + + /*! \brief Set command mode */ + inline void setCommandDisplayMode(int mode) { + commandDisplayMode_ = static_cast(mode); + } + + /*! \brief Get mode for clique strengthening */ + inline CbcParameters::ClqStrMode getClqStrMode() { return (clqStrMode_); } + + /*! \brief Set mode for use of integer preprocessing */ + inline void setClqStrMode(CbcParameters::ClqStrMode mode) { clqStrMode_ = mode; + } + + /*! \brief Get mode for branching priorities */ + inline CbcParameters::BPMode getBranchPriority() { return (branchPriority_); + } + + /*! \brief Set mode for branching priorities */ + inline void setBranchPriority(CbcParameters::BPMode mode) { branchPriority_ = mode; + } + + /*! \brief Get mode for use of cutoff constraint */ + inline CbcParameters::CutoffMode getCutoffMode() { return (cutoffMode_); } + + /*! \brief Set mode for use of cutoff constraint */ + inline void setCutoffMode(CbcParameters::CutoffMode mode) { cutoffMode_ = mode; + } + + /*! \brief Get mode for printing integers */ + inline CbcParameters::IntPrintMode getIntPrintMode() { return (intPrintMode_); + } + + /*! \brief Set mode for printing integers */ + inline void setIntPrintMode(CbcParameters::IntPrintMode mode) { intPrintMode_ = mode; + } + + /*! \brief Get print mode */ + inline int getPrintMode() { return (printMode_); } + + /*! \brief Set print mode */ + inline void setIntPrintMode(int mode) { printMode_ = mode; } + + /*! \brief Get print mask */ + inline std::string getPrintMask() { return (printMask_); + } + + /*! \brief Set print mask */ + inline void setPrintMask(std::string mask) { printMask_ = mask; } + + /*! \brief Get node search strategy */ + inline CbcParameters::NodeStrategy getNodeStrategy() { return (nodeStrategy_); + } + + /*! \brief Set node search strategy */ + inline void setNodeStrategy(CbcParameters::NodeStrategy mode) { nodeStrategy_ = mode; + } + + /*! \brief Get strategy for orbital branching */ + inline CbcParameters::OrbitalStrategy getOrbitalStrategy() { return (orbitalStrategy_); + } + + /*! \brief Set strategy for orbital branching */ + inline void setOrbitalStrategy(CbcParameters::OrbitalStrategy mode) { + orbitalStrategy_ = mode; + } + + /*! \brief Get mode for use of integer preprocessing */ + inline CbcParameters::IPPMode getIPPMode() { return (preProcess_); } + + /*! \brief Set mode for use of integer preprocessing */ + inline void setIPPMode(CbcParameters::IPPMode mode) { preProcess_ = mode; } + + /*! \brief Get priority mode for SOS */ + inline CbcParameters::SOSStrategy getSOSStrategy() { return (sosStrategy_); } + + /*! \brief Set mode state for use of integer preprocessing */ + inline void setSOSStrategy(CbcParameters::SOSStrategy mode) { + sosStrategy_ = mode; + } + + /*! \brief Get overall strategy mode */ + inline CbcParameters::StrategyMode getStrategyMode() { return (strategyMode_); } + + /*! \brief Set overall strategy mode */ + inline void setStrategyMode(CbcParameters::StrategyMode mode) { strategyMode_ = mode; + } + + /*! \brief Get clock type */ + inline CbcParameters::ClockType getClockType() { return (clockType_); } + + /*! \brief Set clock type */ + inline void setClockType(CbcParameters::ClockType type) { clockType_ = type; + } + + /*! \brief Get mode for CGraph */ + inline CbcParameters::CGraphMode getCGraphMode() { return (cgraphMode_); } + + /*! \brief Set mode for CGraph */ + inline void setCGraphMode(CbcParameters::CGraphMode mode) { cgraphMode_ = mode; + } + + /*! \brief Get threshold for artificial costs */ + inline double getArtVarThreshold() { return (artVar_.threshold_); } + + /*! \brief Get mode for artificial costs */ + inline double getArtVarMode() { return (artVar_.mode_); } + + /*! \brief Set mode for artificial costs */ + inline void setArtVarMode(CbcParameters::OnOffMode mode, double threshold) { + artVar_.threshold_ = threshold; + artVar_.mode_ = mode; + } + + /*! \brief Get threshold for reduced costs fixing */ + inline double getDjFixThreshold() { return (djFix_.threshold_); } + + /*! \brief Get mode for reduced cost fixing */ + inline double getDjFixMode() { return (djFix_.mode_); } + + /*! \brief Set mode for reduced cost fixing */ + inline void setDjFixMode(CbcParameters::OnOffMode mode, double threshold) { + djFix_.threshold_ = threshold; + djFix_.mode_ = mode; + } + + /*! \brief Get mode for branching priorities */ + inline CbcParameters::BPMode getBranchingPriorityMode() { + return (priorityMode_); + } + + /*! \brief Set mode for reduced cost fixing */ + inline void setBranchingPriorityMode(CbcParameters::BPMode mode) { + priorityMode_ = mode; + } + + //@} + + /*! \name Miscellaneous Bool Parameters + + */ + + //@{ + + /*! \brief Get CPX mode */ + inline CbcParameters::OnOffMode getCpxMode() { return (CPXMode_); } + + /*! \brief Set CPX mode */ + inline void setCPXMode(CbcParameters::OnOffMode mode) { CPXMode_ = mode; } + + /*! \brief Get import errors mode */ + inline CbcParameters::OnOffMode getImportErrorsMode() { + return (importErrorsMode_); + } + + /*! \brief Set import errors mode */ + inline void setImportErrorsMode(CbcParameters::OnOffMode mode) { + importErrorsMode_ = mode; + } + + /*! \brief Get message prefix mode */ + inline CbcParameters::OnOffMode getMessagePrefixMode() { + return (messagePrefixMode_); + } + + /*! \brief Set message prefix mode */ + inline void setMessagePrefixMode(CbcParameters::OnOffMode mode) { + messagePrefixMode_ = mode; + } + + /*! \brief Get preprocess names mode */ + inline CbcParameters::OnOffMode getPreProcNamesMode() { + return (preProcNamesMode_); + } + + /*! \brief Set preprocess names mode */ + inline void setPreProcNamesMode(CbcParameters::OnOffMode mode) { + preProcNamesMode_ = mode; + } + + /*! \brief Get SOS mode */ + inline CbcParameters::OnOffMode getSOSMode() { return (SOSMode_); } + + /*! \brief Set SOS mode */ + inline void setSOSMode(CbcParameters::OnOffMode mode) { SOSMode_ = mode; } + + /*! \brief Get use solution mode */ + inline CbcParameters::OnOffMode getUseSolutionMode() { + return (useSolutionMode_); + } + + /*! \brief Set use solution mode */ + inline void setUseSolutionMode(CbcParameters::OnOffMode mode) { + useSolutionMode_ = mode; + } + + //@} + + /*! \name Status Functions + \brief Convenience routines for status codes. + */ + //@{ + + /*! \brief Set the result of branch-and-cut search */ + inline void setBaBStatus(CbcParameters::BACMajorStatus majorStatus, + CbcParameters::BACMinorStatus minorStatus, + CbcParameters::BACWhere where, bool haveAnswer, + OsiSolverInterface *answerSolver) { + bab_.majorStatus_ = majorStatus; + bab_.minorStatus_ = minorStatus; + bab_.where_ = where; + bab_.haveAnswer_ = haveAnswer; + bab_.answerSolver_ = answerSolver; + } + + /*! \brief Set the result of branch-and-cut search + + This version will extract the necessary information from the CbcModel + object and set appropriate status based on the value passed for where. + */ + void setBaBStatus(CbcParameters::BACWhere where, + bool haveAnswer = false, + OsiSolverInterface *answerSolver = 0); + + /*! \brief Get status of branch-and-cut search */ + inline bool haveAnswer() { return bab_.haveAnswer_; } + inline OsiSolverInterface *answerSolver() { return bab_.answerSolver_; } + + /*! \brief Translate CbcModel major status to #BACMajorStatus + + See the #BACMajorStatus enum for details. + */ + CbcParameters::BACMajorStatus translateMajor(int status); + + /*!\brief Translate CbcModel minor status to #BACMinorStatus + + See the #BACMinorStatus enum for details. + */ + CbcParameters::BACMinorStatus translateMinor(int status); + + /*!\brief Translate OsiSolverInterface status to #BACMinorStatus + + See the #BACMinorStatus enum for details. Optimal, infeasible, and + unbounded get their own codes; everything else maps to BACmOther. + */ + CbcParameters::BACMinorStatus translateMinor(const OsiSolverInterface *osi); + + /*! \brief Print the status block */ + + void printBaBStatus(); + + //@} + + /*! \name Messages and statistics */ + //@{ + + /*! \brief Print a message + Uses the current message handler and messages. + */ + CoinMessageHandler &message(CbcGenMsgCode inID); + + /*! \brief Supply a new message handler. + + Replaces the current message handler. The current handler is destroyed + if ourMsgHandler_ is true, and the call will set ourMsgHandler_ = true. + */ + void passInMessageHandler(CoinMessageHandler *handler); + + /*! \brief Return a pointer to the message handler */ + inline CoinMessageHandler *messageHandler() const { return msgHandler_; } + + /*! \brief Set up messages in the specified language. + + Building a set of messages in a given language implies rebuilding the + whole set of messages, for reasons explained in the body of the code. + Hence there's no separate setLanguage routine. Use this routine for the + initial setup of messages and any subsequent change in language. Note + that the constructor gives you a message handler by default, but \e not + messages. You need to call setMessages explicitly. + + The default value specified here for lang effectively sets the default + language. + */ + void setMessages(CoinMessages::Language lang = CoinMessages::us_en); + + /*! \brief Set log level */ + inline void setLogLevel(int lvl) { + logLvl_ = lvl; + if (msgHandler_) + msgHandler_->setLogLevel(lvl); + } + + /*! \brief Get log level */ + inline int getLogLevel() const { return (logLvl_); } + + /*! \brief Set LP log level */ + inline void setLpLogLevel(int lvl) { lpLogLvl_ = lvl; } + + /*! \brief Get LP log level */ + inline int getLpLogLevel() const { return (lpLogLvl_); } + + /*! \brief Set LP log level */ + inline void setModel(CbcModel *model) { model_ = model; } + + /*! \brief Get LP log level */ + inline CbcModel *getModel() const { return (model_); } + +#ifdef CBC_CLUMSY_CODING + /*! \brief Synchronize Cbc (and Clp) model - Int and Dbl */ + void synchronizeModel(); +#endif + + /*! \brief Get total time */ + inline double getTotalTime() const { return totalTime_; } + + /*! \brief Set total time */ + inline void setTotalTime(double t) { totalTime_ = t; } + + /* \brief Get Clp parameters */ + inline ClpParameters &clpParameters() { + return clpParameters_; + } + + /* \brief Get Clp solver parameter vector */ + inline CoinParamVec &clpParamVec() { + return clpParameters_.paramVec(); + } + + /* \brief Get Cbc solver parameter vector */ + inline CoinParamVec ¶mVec() { return parameters_; } + + /* \brief Get specific Cbc solver parameter object */ + inline CbcParam *getParam(int code) { + return static_cast(parameters_[code]); + } + + /* \brief Get value of parameter */ + void getParamVal(int code, std::string &value) { + value = parameters_[code]->getVal(value); + } + void getParamVal(int code, double &value) { + value = parameters_[code]->getVal(value); + } + void getParamVal(int code, int &value) { + value = parameters_[code]->getVal(value); + } + + /* \brief Set value of parameter */ + void setParamVal(int code, std::string value, + std::string *message = NULL, + CoinParam::ParamPushMode pMode = CoinParam::pushDefault) { + parameters_[code]->setVal(value, message, pMode); + } + void setParamVal(int code, double value, + std::string *message = NULL, + CoinParam::ParamPushMode pMode = CoinParam::pushDefault) { + parameters_[code]->setVal(value, message, pMode); + } + void setParamVal(int code, int value, + std::string *message = NULL, + CoinParam::ParamPushMode pMode = CoinParam::pushDefault) { + parameters_[code]->setVal(value, message, pMode); + } + + /* \brief Get version */ + inline std::string getVersion() { return CBC_VERSION; } + + /* \brief Get default directory */ + inline std::string getDefaultDirectory() { return dfltDirectory_; } + + /* \brief Set default directory */ + inline void setDefaultDirectory(std::string dir) { dfltDirectory_ = dir; } + + /* \brief Get model status */ + inline bool goodModel() { return goodModel_; } + + /* \brief Set model status */ + inline void setGoodModel(bool gm) { goodModel_ = gm; } + + /* \brief Get debug file */ + inline std::string getDebugFile() { return debugFile_; } + + /* \brief Set debug file */ + inline void setDebugFile(std::string f) { debugFile_ = f; } + + /* \brief Get debug creation file */ + inline std::string getDebugCreate() { return debugCreate_; } + + /* \brief Set debug creation file */ + inline void setDebugCreate(std::string d) { debugCreate_ = d; } + + /* \brief Get last MPS file */ + inline std::string getLastMpsIn() { return lastMpsIn_; } + + /* \brief Set last MPS file */ + inline void setLastMpsIn(std::string f) { lastMpsIn_ = f; } + + /* \brief Get last solution file */ + inline std::string getLastSolnOut() { return lastSolnOut_; } + + /* \brief Set last solution file */ + inline void setLastSolnOut(std::string f) { lastSolnOut_ = f; } + + /* \brief Toggle set by user for given parameter */ + inline void toggleSetByUser(int code) { setByUser_[code] = true; } + + /* \brief Toggle set by user for given parameter */ + inline bool setByUser(int code) { return setByUser_[code]; } + + /* \brief Set debug solution */ + void setDebugSol(int numCols, double* values) { + if (debugSol_.values_){ + delete[] debugSol_.values_; + } + debugSol_.numCols_ = numCols; + debugSol_.values_ = values; + } + + /* \brief Get debug solution */ + inline int getDebugSolNumCols() const { return debugSol_.numCols_; } + inline double *getDebugSolValues() const { return debugSol_.values_; } + + /* \brief getShadowPriceMode */ + inline int getShadowPriceMode() { return chooseStrong_.shadowPriceMode_; } + + //@} + + /*! \brief Returns index of first parameter that matches and number of + matches overall. Returns CLP_INVALID if no match */ + int matches(std::string field, int &numberMatches); + +private: + + friend class CbcParam; + + template + struct HeuristicSettings { + CbcParameters::HeurMode mode_ = CbcParameters::HeurOff; + T *proto_ = NULL; + }; + + template + struct CGSettings + { + CbcParameters::CGMode mode_ = CbcParameters::CGOff; + T *proto_ = NULL; + }; + + template + struct CGLimitSettings : CGSettings { + int limit_ = 0; + int limitAtRoot_ = 0; + }; + + /*! \name Parameter parsing and input/output. */ + //@{ + + /*! \brief Default directory prefix */ + std::string dfltDirectory_; + + /*! \brief Last MPS input file */ + std::string lastMpsIn_; + + /*! \brief Allow/disallow errors when importing a model */ + bool allowImportErrors_; + + /*! \brief The Cbc parameter vector (parameters stored by their index) */ + CoinParamVec parameters_; + + /*! \brief The Clp parameter vector */ + ClpParameters clpParameters_; + + /*! \brief Last solution output file */ + std::string lastSolnOut_; + + /*! \brief Solution printing mode + Controls the amount of information printed when printing a solution. + Coding is set by the keyword declarations for the printingOptions + command. + */ + int printMode_; + + /*! \brief When greater than 0, integer presolve gives more information and + branch-and-cut provides statistics. + */ + int printOpt_; + + /*! \brief Print mask + + Used to specify row/column names to be printed. Not implemented as of + 060920. + */ + std::string printMask_; + + /*! \brief Disable printing altogether */ + bool noPrinting_; + + /*! \brief Disable printing of welcome message */ + bool printWelcome_; + + /*! \brief Whether to use ginal handler */ + bool useSignalHandler_; + + /*! \brief Verbosity level for help messages. + + Interpretation is bitwise: + - (0): short help + - (1): long help + - (2): unused (for compatibility with cbc; indicates AMPL) + - (3): show parameters with display = false. + */ + int verbose_; + + /*! \brief Number of parameters processed */ + int paramsProcessed_; + + /*! \brief Record of parameters changed by user command */ + std::vector setByUser_; + + /*! \brief False if the user has made nontrivial modifications to the + default control settings. + + Initially true. Specifying DJFIX, TIGHTENFACTOR, or any cut or heuristic + parameter will set this to false. + */ + bool defaultSettings_; + + /*! \brief Control debug file creation + + At the conclusion of branch-and-cut, dump the full solution in a binary + format to debug.file in the current directory. When set to + "createAfterPre", the solution is dumped before integer presolve + transforms are removed. When set to "create", the solution is dumped + after integer presolve transforms are backed out. + */ + std::string debugCreate_; + + /*! \brief Last debug input file + + The file is expected to be in a binary format understood by + activateRowCutDebugger. + */ + std::string debugFile_; + + /*! \brief Array of primal variable values for debugging + + Used to provide a known optimal solution to activateRowCutDebugger(). + */ + struct debugSolInfo_struct { + int numCols_; + double *values_; + } debugSol_; + //@} + + /* \name Timing */ + //@{ + + /*! \brief Total elapsed time for this run. */ + double totalTime_; + + //@} + + /*! \name Models of various flavours */ + //@{ + + /*! \brief The reference CbcModel object. + + This is the CbcModel created when cbc-generic boots up. It holds the + default solver with the current constraint system. CbcCbcParam parameters + are applied here, and CbcOsiParam parameters are applied to the solver. + Major modifications for branch-and-cut (integer preprocessing, + installation of heuristics and cut generators) are performed on a clone. + The solution is transferred back into this object. + */ + CbcModel *model_; + + /*! \brief The current default LP solver + + This is a pointer to a reference copy. If you want the solver associated + with #model_, ask for it directly. + */ + OsiSolverInterface *dfltSolver_; + + /*! \brief True if we have a valid model loaded, false otherwise. */ + bool goodModel_; + + /*! \brief State of branch-and-cut + + Major and minor status codes, and a solver holding the answer, assuming + we have a valid answer. See the documentation with the BACMajorStatus, + BACMinorStatus, and BACWhere enums for the meaning of the codes. + */ + struct babState_struct { + CbcParameters::BACMajorStatus majorStatus_; + CbcParameters::BACMinorStatus minorStatus_; + CbcParameters::BACWhere where_; + bool haveAnswer_; + OsiSolverInterface *answerSolver_; + } bab_; + + //@} + + /*! \name Various algorithm control variables and settings */ + //@{ + + /*! \brief Control use of reduced cost fixing prior to B&C + + This heuristic fixes variables whose reduced cost for the root + relaxtion exceeds the specified threshold. This is purely a heuristic, + performed before there's any incumbent solution. It may well fix variables + at the wrong bound! + */ + struct djFix_struct { + CbcParameters::OnOffMode mode_; + double threshold_; + } djFix_; + + /*! \brief Treat some variables as artificial in feasibility pump + + */ + struct artVar_struct { + CbcParameters::OnOffMode mode_; + double threshold_; + } artVar_; + + /*! \brief Control the assignment of branching priorities to integer + variables. + */ + CbcParameters::BPMode priorityMode_; + + //@} + + /*! \name Branching Method Control + \brief Usage control and prototypes for branching methods. + + Looking to the future, this covers only OsiChoose methods. + */ + //@{ + + /*! \brief Control variables for a strong branching method. + + Consult OsiChooseVariable and CbcModel for details. An artifact of the + changeover from CbcObjects to OsiObjects is that the number of uses before + pseudo costs are trusted (numBeforeTrust_) and the number of variables + evaluated with strong branching (numStrong_) are parameters of CbcModel. + */ + struct chooseStrong_struct { + int numBeforeTrust_; + int numStrong_; + int shadowPriceMode_; + } chooseStrong_; + //@} + + /*! \name Cut Generator Control + \brief Usage control and prototypes for cut generators. + */ + //@{ + + /*! \brief Control integer preprocessing. */ + CbcParameters::IPPMode preProcess_; + + /*! \brief Control cut generator activity + + Generators that are active in the tree will be activated when + (depth) mod (cutDepth) == 0. + */ + int cutDepth_; + int cutLength_; + int cutPassInTree_; + + /*! \brief Control variable and prototype for clique cut generator */ + struct clique_struct : CGSettings { + bool starCliqueReport_; + bool rowCliqueReport_; + double minViolation_; + } clique_; + + /*! \brief Control variable and prototype for flow cover cut generator */ + CGSettings flow_; + + /*! \brief Control variable and prototype for Gomory cut generator */ + CGLimitSettings gmi_; + + /*! \brief Control variable and prototype for Gomory cut generator */ + CGLimitSettings gomory_; + + /*! \brief Control variable and prototype for knapsack cover cut generator */ + CGSettings knapsack_; + + /* \brief Control variable and prototype for LaGomory cut generator */ + CGSettings laGomory_; + + /* \brief Control variable and prototype for lift-and-project cut generator */ + CGSettings landP_; + + /* \brief Control variable and prototype for lift-and-project cut generator */ + CGSettings laTwomir_; + + /*! \brief Control variable and prototype for MIR cut generator */ + CGSettings mir_; + + /*! \brief Control variable and prototype for odd hole cut generator */ + CGSettings oddWheel_; + + /*! \brief Control variable and prototype for probing cut generator */ + struct probing_struct : CGSettings { + bool usingObjective_; + int maxPass_; + int maxPassRoot_; + int maxProbe_; + int maxProbeRoot_; + int maxLook_; + int maxLookRoot_; + int maxElements_; + int rowCuts_; + } probing_; + + /*! \brief Control variable and prototype for reduce-and-split cut generator */ + CGSettings redSplit_; + + /*! \brief Control variable and prototype for reduce-and-split 2 cut generator */ + CGSettings redSplit2_; + + /*! \brief Control variable and prototype for residual capacity cut generator */ + CGSettings residCap_; + + /*! \brief Control variable and prototype for Two-MIR cut generator */ + struct twomir_struct : CGSettings { + int maxElements_; + } twomir_; + + /*! \brief Control variable and prototype for residual capacity cut generator */ + CGSettings zeroHalf_; + + //@} + + /*! \name Heuristic Control + \brief Usage control and prototypes for heuristics. + */ + //@{ + + /*! \brief Overall control variable for heuristics */ + CbcParameters::OnOffMode doHeuristicMode_; + + /*! \brief Control variable and prototype for combine heuristic */ + struct combine_struct : HeuristicSettings { + int trySwap_; + } combine_; + + /*! \brief Control variable and prototype for crossover heuristic */ + HeuristicSettings crossover_; + + /*! \brief Control variable and prototype for heuristic */ + HeuristicSettings dins_; + + /*! \brief Control variable and prototype for Dive Coefficient heuristic */ + HeuristicSettings divingc_; + + /*! \brief Control variable and prototype for Dive Fractional heuristic */ + HeuristicSettings divingf_; + + /*! \brief Control variable and prototype for Dive Guided heuristic */ + HeuristicSettings divingg_; + + /*! \brief Control variable and prototype for Dive Line Search heuristic */ + HeuristicSettings divingl_; + + /*! \brief Control variable and prototype for Dive Pseudocost heuristic */ + HeuristicSettings divingp_; + + /*! \brief Control variable and prototype for Dive Vector Lengthheuristic */ + HeuristicSettings divingv_; + + /*! \brief Control variable and prototype for DW heuristic */ + HeuristicSettings dw_; + + /*! \brief Control variable and prototype for feasibility pump heuristic */ + struct fpump_struct : HeuristicSettings { + int iters_; + int initialTune_; + int tune_; + int tune2_; + double cutoff_; + double increment_; + } fpump_; + + /*! \brief Control variable and prototype for greedy cover heuristic */ + HeuristicSettings greedyCover_; + + /*! \brief Control variable and prototype for greedy equality heuristic */ + HeuristicSettings greedyEquality_; + + /*! \brief Control variable and prototype for Naive heuristic */ + HeuristicSettings naive_; + + /*! \brief Control variable and prototype for Pivot and Fix heuristic */ + HeuristicSettings pivotAndFix_; + +#if 0 + /*! \brief Control variable and prototype for Pivot and Complement heuristic */ + struct pivotAndComp_struct { + CbcParameters::HeurMode mode_; + CbcHeuristicPivotAndComplement *proto_; + } pivotAndComplement_; +#endif + + /*! \brief Control variable and prototype for Proximity heuristic */ + HeuristicSettings proximity_; + + /*! \brief Control variable and prototype for Randomized Rounding heuristic */ + HeuristicSettings randRound_; + + /*! \brief Control variable and prototype for RENS heuristic */ + HeuristicSettings rens_; + + /*! \brief Control variable and prototype for RINS heuristic */ + HeuristicSettings rins_; + + /*! \brief Control variable and prototype for simple rounding heuristic */ + HeuristicSettings rounding_; + + /*! \brief Control variable and prototype for Variable Neighborhood + heuristic + */ + HeuristicSettings vnd_; + + CbcParameters::HeurMode randomDivingMode_ = CbcParameters::HeurOff; + + /*! \brief Control variables for local tree + + This is a bit different --- getTreeLocal() takes a CbcModel as a parameter + and installs a local tree object. But we can keep the parameters here and + hide the details. Consult CbcTreeLocal.hpp for details. + */ + struct localTree_struct : HeuristicSettings { + double *soln_; + int range_; + int typeCuts_; + int maxDiverge_; + int timeLimit_; + int nodeLimit_; + bool refine_; + } localTree_; + + //@} + + /*! \name Miscellaneous double paramters + + */ + //@{ + + double extraDbl3_; + double extraDbl4_; + double extraDbl5_; + double smallBaB_; + double tightenFactor_; + + //@} + + /*! \name Miscellaneous integer paramters + + */ + //@{ + + int bkPivotStrategy_; + int bkMaxCalls_; + int bkClqExtMethod_; + int cppMode_; + int depthMiniBaB_; + int diveOpt_; + int diveOptSolves_; + int experiment_; + int extraInt1_; + int extraInt2_; + int extraInt3_; + int extraInt4_; + int heurOptions_; + int maxSavedSols_; + int maxSlowCuts_; + int moreMoreOptions_; + int multipleRoots_; + int oddWextMethod_; + int outputFormat_; + int processTune_; + int randomSeed_; + int strongStrategy_; + int testOsi_; + int threads_; + int userCbc_; + int vubTry_; + + //@} + + /*! \name Miscellaneous keyword paramters + + */ + //@{ + + CbcParameters::CommandDisplayMode commandDisplayMode_; + CbcParameters::ClqStrMode clqStrMode_; + CbcParameters::BPMode branchPriority_; + CbcParameters::CutoffMode cutoffMode_; + CbcParameters::IntPrintMode intPrintMode_; + CbcParameters::NodeStrategy nodeStrategy_; + CbcParameters::OrbitalStrategy orbitalStrategy_; + CbcParameters::SOSStrategy sosStrategy_; + CbcParameters::StrategyMode strategyMode_; + CbcParameters::ClockType clockType_; + CbcParameters::CGraphMode cgraphMode_; + + //@} + + /*! \name Miscellaneous bool paramters + + */ + //@{ + + CbcParameters::OnOffMode CPXMode_; + CbcParameters::OnOffMode importErrorsMode_; + CbcParameters::OnOffMode messagePrefixMode_; + CbcParameters::OnOffMode preProcNamesMode_; + CbcParameters::OnOffMode SOSMode_; + CbcParameters::OnOffMode useSolutionMode_; + + //@} + + /*! \name Messages and statistics (private) + \brief Data and objects related to messages and statistics that should + be protected from direct manipulation. + */ + //@{ + + /*! \brief Message handler. */ + CoinMessageHandler *msgHandler_; + + /*! \brief Ownership of message handler. + + If true, the control block owns the message handler and it will be + destroyed with the control block. If false, the client is responsible for + the message handler. + */ + bool ourMsgHandler_; + + /*! \brief The current language */ + CoinMessages::Language cur_lang_; + + /*! \brief The current set of messages. */ + CoinMessages *msgs_; + + /*! \brief The current log level */ + int logLvl_; + + /*! \brief The current LP log level */ + int lpLogLvl_; + + //@} +}; + +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 + */ diff --git a/src/CbcGenSolution.cpp b/src/CbcSolution.cpp similarity index 81% rename from src/CbcGenSolution.cpp rename to src/CbcSolution.cpp index c13a3d4a6..468627de6 100644 --- a/src/CbcGenSolution.cpp +++ b/src/CbcSolution.cpp @@ -9,21 +9,19 @@ This file is part of cbc-generic. */ -#include -#include #include +#include +#include +#include "CoinFileIO.hpp" #include "CoinHelperFunctions.hpp" #include "CoinSort.hpp" -#include "CoinFileIO.hpp" -#include "CbcGenCtlBlk.hpp" -#include "CbcGenParam.hpp" - -namespace { +#include "CbcParam.hpp" +#include "CbcParamUtils.hpp" +#include "CbcParameters.hpp" - -} +namespace {} namespace { @@ -37,8 +35,8 @@ namespace { Returns the number of generated masks, -1 on error. */ -int generateMasks(std::string proto, int longestName, - int *&maskStarts, char **&finalMasks) +int generateMasks(std::string proto, int longestName, int *&maskStarts, + char **&finalMasks) { int nAst = 0; @@ -201,45 +199,43 @@ bool maskMatches(const int *starts, char **masks, const char *checkC) all (4) all primal variables and row activities */ -int CbcGenParamUtils::doSolutionParam(CoinParam *param) +int CbcParamUtils::doSolutionParam(CoinParam ¶m) { - assert(param != 0); - CbcGenParam *genParam = dynamic_cast< CbcGenParam * >(param); - assert(genParam != 0); - CbcGenCtlBlk *ctlBlk = genParam->obj(); - assert(ctlBlk != 0); - CbcModel *model = ctlBlk->model_; + CbcParam &cbcParam = dynamic_cast(param); + CbcParameters *parameters = cbcParam.parameters(); + assert(parameters != 0); + CbcModel *model = parameters->getModel(); assert(model != 0); /* Setup to return nonfatal/fatal error (1/-1) by default. */ int retval; - if (CoinParamUtils::isInteractive()) { - retval = 1; - } else { + //if (CoinParamUtils::isInteractive()) { + // retval = 1; + //} else { retval = -1; - } + //} /* It's hard to print a solution we don't have. */ - if (ctlBlk->bab_.haveAnswer_ == false) { + if (!parameters->haveAnswer()) { std::cout << "There is no solution available to print." << std::endl; return (retval); } - OsiSolverInterface *osi = ctlBlk->bab_.answerSolver_; + OsiSolverInterface *osi = parameters->answerSolver(); assert(osi != 0); /* Figure out where we're going to write the solution. As special cases, `$' says `use the previous output file' and `-' says `use stdout'. - cbc will also accept `no string value' as stdout, but that'd be a real pain - in this architecture. + cbc will also accept `no string value' as stdout, but that'd be a real + pain in this architecture. */ - std::string field = genParam->strVal(); + std::string field = cbcParam.strVal(); std::string fileName; if (field == "$") { - fileName = ctlBlk->lastSolnOut_; + fileName = parameters->getLastSolnOut(); field = fileName; } if (field == "-") { @@ -260,7 +256,7 @@ int CbcGenParamUtils::doSolutionParam(CoinParam *param) } } if (!(fileAbsPath(fileName) || fileName.substr(0, 2) == "./")) { - fileName = ctlBlk->dfltDirectory_ + fileName; + fileName = parameters->getDefaultDirectory() + fileName; } } /* @@ -276,13 +272,11 @@ int CbcGenParamUtils::doSolutionParam(CoinParam *param) fp = fopen(fileName.c_str(), "w"); } if (!fp) { - std::cout - << "Unable to open file `" << fileName - << "', original name '" << genParam->strVal() << "'." << std::endl; + std::cout << "Unable to open file `" << fileName << "', original name '" + << cbcParam.strVal() << "'." << std::endl; return (retval); } else { - std::cout - << "Writing solution to `" << fileName << "'." << std::endl; + std::cout << "Writing solution to `" << fileName << "'." << std::endl; } int m = osi->getNumRows(); @@ -294,7 +288,7 @@ int CbcGenParamUtils::doSolutionParam(CoinParam *param) row cut debugger. For the row cut debugger, we want to produce C++ code that can be pasted into the debugger's set of known problems. */ - if (ctlBlk->printMode_ == 2) { + if (parameters->getPrintMode() == 2) { int k = 0; bool newLine = true; bool comma = false; @@ -332,7 +326,7 @@ int CbcGenParamUtils::doSolutionParam(CoinParam *param) } else { value = ceil(value - .5); } - int ivalue = static_cast< int >(value); + int ivalue = static_cast(value); fprintf(fp, "%d.0", ivalue); if (++k == 10) { k = 0; @@ -345,15 +339,15 @@ int CbcGenParamUtils::doSolutionParam(CoinParam *param) } /* Begin the code to generate output meant for a human. What's our longest - name? Scan the names we're going to print. printMode_ of 3 or 4 requires we - scan the row names too. Force between 8 and 20 characters in any event. + name? Scan the names we're going to print. printMode_ of 3 or 4 requires + we scan the row names too. Force between 8 and 20 characters in any event. */ int longestName = 0; for (int j = 0; j < n; j++) { int len = osi->getColName(j).length(); longestName = CoinMax(longestName, len); } - if (ctlBlk->printMode_ >= 3) { + if (parameters->getPrintMode() >= 3) { for (int i = 0; i < m; i++) { int len = osi->getRowName(i).length(); longestName = CoinMax(longestName, len); @@ -362,12 +356,14 @@ int CbcGenParamUtils::doSolutionParam(CoinParam *param) /* Generate masks if we need to do so. */ - bool doMask = ctlBlk->printMask_ != ""; + bool doMask = parameters->getPrintMask() != ""; int *maskStarts = NULL; int maxMasks = 0; char **masks = NULL; if (doMask) { - maxMasks = generateMasks(ctlBlk->printMask_, longestName, maskStarts, masks); + maxMasks = + generateMasks(parameters->getPrintMask(), longestName, maskStarts, + masks); if (maxMasks < 0) { return (retval); } @@ -386,7 +382,7 @@ int CbcGenParamUtils::doSolutionParam(CoinParam *param) the row activity and the value of the associated dual. Which to print? Violated constraints will always be flagged to print. - Otherwise, if m < 50 or all rows are requested, print all rows. Otherwise, + Otherwise, if m < 50 or all rows are requested, print all rows. Otherwise, print tight constraints (non-zero dual). All of this is filtered through printMask, if specified. @@ -395,23 +391,24 @@ int CbcGenParamUtils::doSolutionParam(CoinParam *param) osi->getDblParam(OsiPrimalTolerance, primalTolerance); int iRow; - if (ctlBlk->printMode_ >= 3) { + if (parameters->getPrintMode() >= 3) { const double *dualRowSolution = osi->getRowPrice(); const double *primalRowSolution = osi->getRowActivity(); const double *rowLower = osi->getRowLower(); const double *rowUpper = osi->getRowUpper(); - fprintf(fp, "\n %7s %-*s%15s%15s\n\n", - "Index", longestName, "Row", "Activity", "Dual"); + fprintf(fp, "\n %7s %-*s%15s%15s\n\n", "Index", longestName, "Row", + "Activity", "Dual"); for (iRow = 0; iRow < m; iRow++) { bool violated = false; bool print = false; - if (primalRowSolution[iRow] > rowUpper[iRow] + primalTolerance || primalRowSolution[iRow] < rowLower[iRow] - primalTolerance) { + if (primalRowSolution[iRow] > rowUpper[iRow] + primalTolerance || + primalRowSolution[iRow] < rowLower[iRow] - primalTolerance) { violated = true; print = true; } else { - if (m < 50 || ctlBlk->printMode_ >= 4) { + if (m < 50 || parameters->getPrintMode() >= 4) { print = true; } else if (fabs(dualRowSolution[iRow]) > 1.0e-8) { print = true; @@ -428,7 +425,7 @@ int CbcGenParamUtils::doSolutionParam(CoinParam *param) fprintf(fp, "%3s", " "); } fprintf(fp, "%7d %-*s%15.8g%15.8g\n", iRow, longestName, name, - primalRowSolution[iRow], dualRowSolution[iRow]); + primalRowSolution[iRow], dualRowSolution[iRow]); } } fprintf(fp, "\n"); @@ -439,25 +436,26 @@ int CbcGenParamUtils::doSolutionParam(CoinParam *param) variables, all are printed. All of this is filtered through `integer only' and can be further filtered using printMask. */ - if (ctlBlk->printMode_ != 2) { + if (parameters->getPrintMode() != 2) { const double *columnLower = osi->getColLower(); const double *columnUpper = osi->getColUpper(); const double *dualColSolution = osi->getReducedCost(); - fprintf(fp, "\n %7s %-*s%15s%15s\n\n", - "Index", longestName, "Column", "Value", "Reduced Cost"); + fprintf(fp, "\n %7s %-*s%15s%15s\n\n", "Index", longestName, "Column", + "Value", "Reduced Cost"); for (iColumn = 0; iColumn < n; iColumn++) { bool violated = false; bool print = false; - if (primalColSolution[iColumn] > columnUpper[iColumn] + primalTolerance || primalColSolution[iColumn] < columnLower[iColumn] - primalTolerance) { + if (primalColSolution[iColumn] > columnUpper[iColumn] + primalTolerance || + primalColSolution[iColumn] < columnLower[iColumn] - primalTolerance) { violated = true; print = true; } else { - if (n < 50 || ctlBlk->printMode_ == 4) { + if (n < 50 || parameters->getPrintMode() == 4) { print = true; } else if (fabs(primalColSolution[iColumn]) > 1.0e-8) { - if (ctlBlk->printMode_ == 1) { + if (parameters->getPrintMode() == 1) { print = osi->isInteger(iColumn); } else { print = true; @@ -475,7 +473,7 @@ int CbcGenParamUtils::doSolutionParam(CoinParam *param) fprintf(fp, "%3s", " "); } fprintf(fp, "%7d %-*s%15.8g%15.8g\n", iColumn, longestName, name, - primalColSolution[iColumn], dualColSolution[iColumn]); + primalColSolution[iColumn], dualColSolution[iColumn]); } } } @@ -502,36 +500,33 @@ int CbcGenParamUtils::doSolutionParam(CoinParam *param) it's valid. */ -int CbcGenParamUtils::doPrintMaskParam(CoinParam *param) +int CbcParamUtils::doPrintMaskParam(CoinParam ¶m) { - assert(param != 0); - CbcGenParam *genParam = dynamic_cast< CbcGenParam * >(param); - assert(genParam != 0); - CbcGenCtlBlk *ctlBlk = genParam->obj(); - assert(ctlBlk != 0); + CbcParam &cbcParam = dynamic_cast(param); + CbcParameters *parameters = cbcParam.parameters(); + assert(parameters != 0); /* Setup to return nonfatal/fatal error (1/-1) by default. */ int retval; - if (CoinParamUtils::isInteractive()) { - retval = 1; - } else { + //if (CoinParamUtils::isInteractive()) { + // retval = 1; + //} else { retval = -1; - } + //} /* Now do a bit of verification of the mask. It should be non-null and, if quoted, the quotes should be matched. Aribtrarily put the absolute maximum - length at 50 characters. If we have a model loaded, that'll be tightened to - the length of the longest name. + length at 50 characters. If we have a model loaded, that'll be tightened + to the length of the longest name. */ - std::string maskProto = param->strVal(); + std::string maskProto = cbcParam.strVal(); int maskLen = maskProto.length(); if (maskLen <= 0 || maskLen > 50) { - std::cerr - << "Mask |" << maskProto - << "| is " << maskLen << " characters; should be between " - << 0 << " and " << 50 << "." << std::endl; + std::cerr << "Mask |" << maskProto << "| is " << maskLen + << " characters; should be between " << 0 << " and " << 50 << "." + << std::endl; return (retval); } /* @@ -540,9 +535,8 @@ int CbcGenParamUtils::doPrintMaskParam(CoinParam *param) if (maskProto[0] == '"' || maskProto[0] == '\'') { char quoteChar = maskProto[0]; if (maskProto[maskLen - 1] != quoteChar) { - std::cerr - << "Mismatched quotes around mask |" << maskProto - << "|." << std::endl; + std::cerr << "Mismatched quotes around mask |" << maskProto << "|." + << std::endl; return (retval); } else { maskProto = maskProto.substr(1, maskLen - 2); @@ -552,8 +546,8 @@ int CbcGenParamUtils::doPrintMaskParam(CoinParam *param) Mask should not be longer than longest name. Of course, if we don't have a model, we can't do this check. */ - if (ctlBlk->goodModel_) { - CbcModel *model = ctlBlk->model_; + if (parameters->goodModel()) { + CbcModel *model = parameters->getModel(); assert(model != 0); OsiSolverInterface *osi = model->solver(); assert(osi != 0); @@ -569,18 +563,18 @@ int CbcGenParamUtils::doPrintMaskParam(CoinParam *param) longestName = CoinMax(longestName, len); } if (maskLen > longestName) { - std::cerr - << "Mask |" << maskProto << "| has " << maskLen << " chars; this" - << " is longer than the longest name (" << longestName - << " chars)." << std::endl; + std::cerr << "Mask |" << maskProto << "| has " << maskLen + << " chars; this" + << " is longer than the longest name (" << longestName + << " chars)." << std::endl; return (retval); } } - ctlBlk->printMask_ = maskProto; + parameters->setPrintMask(maskProto); return (0); } /* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 -*/ + */ diff --git a/src/CbcSolver.cpp b/src/CbcSolver.cpp index f37e049b9..94ddfecae 100644 --- a/src/CbcSolver.cpp +++ b/src/CbcSolver.cpp @@ -6,76 +6,183 @@ \brief Second level routines for the cbc stand-alone solver. */ -#include "CbcSolverConfig.h" -#include "CoinPragma.hpp" +// Need these up front to define symbols for other imports +#include "CoinUtilsConfig.h" +#include "CbcConfig.h" #include +#include +#include #include #include -#include -#include #include +#include +#include #include -#ifdef HAVE_SIGNAL_H -#ifdef HAVE_EXECINFO_H + +#if defined(NEW_DEBUG_AND_FILL) || defined(CLP_MALLOC_STATISTICS) +#include +#include +#include +#endif +#if defined(HAVE_SIGNAL_H) && defined(HAVE_EXECINFO_H) #include #include -void CbcCrashHandler( int sig ); +void CbcCrashHandler(int sig); +#endif + +#ifdef COINUTILS_HAS_GLPK +#include "glpk.h" #endif +#ifdef DMALLOC +#include "dmalloc.h" #endif -#include "CoinPragma.hpp" -#include "CoinHelperFunctions.hpp" +//########################################################################### +// COIN-OR headers (do we really need all these?) +// Should some be in CbcSolver.hpp? +//########################################################################### -#include "CoinMpsIO.hpp" +#include "CoinHelperFunctions.hpp" #include "CoinModel.hpp" +#include "CoinMpsIO.hpp" +#include "CoinParam.hpp" +#include "CoinPragma.hpp" +#include "CoinSignal.hpp" +#include "CoinWarmStartBasis.hpp" +#include "ClpDualRowDantzig.hpp" +#include "ClpDualRowSteepest.hpp" #include "ClpFactorization.hpp" -#include "ClpQuadraticObjective.hpp" -#include "CoinTime.hpp" -#include "ClpSimplex.hpp" -#include "ClpSimplexOther.hpp" -#include "ClpSolve.hpp" -#include "ClpMessage.hpp" -#include "ClpPackedMatrix.hpp" -#include "ClpPlusMinusOneMatrix.hpp" +#include "ClpLinearObjective.hpp" #include "ClpNetworkMatrix.hpp" -#include "ClpDualRowSteepest.hpp" -#include "ClpDualRowDantzig.hpp" -#include "ClpPEDualRowSteepest.hpp" #include "ClpPEDualRowDantzig.hpp" -#include "ClpPEPrimalColumnSteepest.hpp" +#include "ClpPEDualRowSteepest.hpp" #include "ClpPEPrimalColumnDantzig.hpp" -#include "ClpLinearObjective.hpp" -#include "ClpPrimalColumnSteepest.hpp" +#include "ClpPEPrimalColumnSteepest.hpp" +#include "ClpPackedMatrix.hpp" +#include "ClpParamUtils.hpp" +#include "ClpPlusMinusOneMatrix.hpp" +#include "ClpPresolve.hpp" #include "ClpPrimalColumnDantzig.hpp" +#include "ClpPrimalColumnSteepest.hpp" +#include "ClpQuadraticObjective.hpp" +#include "ClpSimplex.hpp" +#include "ClpSimplexOther.hpp" +#include "ClpSolve.hpp" +#include "CoinTime.hpp" -#include "ClpPresolve.hpp" -#ifndef COIN_HAS_CBC -#define COIN_HAS_CBC +#include "OsiAuxInfo.hpp" +#include "OsiChooseVariable.hpp" +#include "OsiClpSolverInterface.hpp" +#include "OsiColCut.hpp" +#include "OsiCuts.hpp" +#include "OsiRowCut.hpp" +#include "OsiRowCutDebugger.hpp" +#include "OsiSolverInterface.hpp" +/* CBC_OTHER_SOLVER == 1 is cplex. */ +#if CBC_OTHER_SOLVER == 1 +#ifndef CBC_HAS_OSICPX +#error "Configuration did not detect OsiCpx installation." +#else +#include "OsiCpxSolverInterface.hpp" #endif -#ifndef COIN_HAS_CLP -#define COIN_HAS_CLP #endif -#include "CbcOrClpParam.hpp" -#include "OsiRowCutDebugger.hpp" -#include "OsiChooseVariable.hpp" -#include "OsiAuxInfo.hpp" -#include "CbcMipStartIO.hpp" + +#include "CglBKClique.hpp" +#include "CglClique.hpp" +#include "CglCliqueStrengthening.hpp" +#include "CglCutGenerator.hpp" +#include "CglDuplicateRow.hpp" +#include "CglFlowCover.hpp" +#include "CglGMI.hpp" +#include "CglGomory.hpp" +#include "CglKnapsackCover.hpp" +#include "CglLandP.hpp" +#include "CglMessage.hpp" +#include "CglMixedIntegerRounding2.hpp" +#include "CglOddWheel.hpp" +#include "CglPreProcess.hpp" +#include "CglProbing.hpp" +#include "CglRedSplit.hpp" +#include "CglRedSplit2.hpp" +#include "CglResidualCapacity.hpp" +#include "CglStored.hpp" +#include "CglTwomir.hpp" +#include "CglZeroHalf.hpp" + +#include "CbcBranchActual.hpp" +#include "CbcBranchCut.hpp" +#include "CbcBranchLotsize.hpp" +#include "CbcCompareActual.hpp" +#include "CbcCompareObjective.hpp" +#include "CbcCutGenerator.hpp" +#include "CbcHeuristic.hpp" +#include "CbcHeuristicDiveCoefficient.hpp" +#include "CbcHeuristicDiveFractional.hpp" +#include "CbcHeuristicDiveGuided.hpp" +#include "CbcHeuristicDiveLineSearch.hpp" +#include "CbcHeuristicDivePseudoCost.hpp" +#include "CbcHeuristicDiveVectorLength.hpp" +#include "CbcHeuristicFPump.hpp" +#include "CbcHeuristicGreedy.hpp" +#include "CbcHeuristicLocal.hpp" +#include "CbcHeuristicPivotAndFix.hpp" +#include "CbcHeuristicRINS.hpp" +#include "CbcHeuristicRandRound.hpp" #include "CbcMessage.hpp" -// for printing +#include "CbcMipStartIO.hpp" +#include "CbcModel.hpp" +#include "CbcParam.hpp" +#include "CbcParamUtils.hpp" +#include "CbcSolver.hpp" +#include "CbcSolverAnalyze.hpp" +#include "CbcSolverExpandKnapsack.hpp" +#include "CbcSolverHeuristics.hpp" +#include "CbcStrategy.hpp" +#include "CbcTreeLocal.hpp" + +//############################################################################# +//############################################################################# + +void printGeneralMessage(CbcModel &model, std::string message, int type) +{ + if (message.length()) { + model.messageHandler()->message(type, model.messages()) + << message << CoinMessageEol; + } +} + +//############################################################################# +//############################################################################# + +void printGeneralWarning(CbcModel &model, std::string message, int type) +{ + if (message.length()) { + model.messageHandler()->message(type, model.messages()) + << message << CoinMessageEol; + } +} + +//########################################################################### +// Define symbols +//########################################################################### + +#ifndef COIN_HAS_LINK +#define COIN_HAS_LINK +#endif +#ifdef COIN_HAS_LINK +#include "CbcLinked.hpp" +#endif + #ifndef CLP_OUTPUT_FORMAT #define CLP_OUTPUT_FORMAT % 15.8g #endif + #define CLP_QUOTE(s) CLP_STRING(s) #define CLP_STRING(s) #s -#include "CbcSolverHeuristics.hpp" -#ifdef CBC_HAS_GLPK -#include "glpk.h" -extern COINUTILSLIB_EXPORT glp_tran *cbc_glp_tran; -extern COINUTILSLIB_EXPORT glp_prob *cbc_glp_prob; -#else +#ifndef COINUTILS_HAS_GLPK #define GLP_UNDEF 1 #define GLP_FEAS 2 #define GLP_INFEAS 3 @@ -87,41 +194,96 @@ extern COINUTILSLIB_EXPORT glp_prob *cbc_glp_prob; #define CBC_QUIET 0 #endif -//#define USER_HAS_FAKE_CLP -//#define USER_HAS_FAKE_CBC -//#define NEW_DEBUG_AND_FILL // use this to make it easier to trap unset +#if defined(WSSMP_BARRIER) || defined(UFL_BARRIER) || defined(TAUCS_BARRIER) +#define FOREIGN_BARRIER +#endif + +//#define IN_BRANCH_AND_BOUND (0x01000000|262144) +#define IN_BRANCH_AND_BOUND (0x01000000 | 262144 | 128 | 1024 | 2048) +//#define IN_BRANCH_AND_BOUND (0x01000000|262144|128) + +//########################################################################### +// Global variables (can we get rid of these?) +//########################################################################### + +static int initialPumpTune = -1; + +#ifdef CGL_WRITEMPS +extern double *debugSolution; +extern int debugNumberColumns; +#endif + +static CbcModel *currentBranchModel = NULL; + +CglPreProcess *cbcPreProcessPointer = NULL; + +static char cbcCrashAnnounced = 0; + +#ifdef CLP_MALLOC_STATISTICS +static double malloc_times = 0.0; +static double malloc_total = 0.0; +static int malloc_amount[] = {0, 32, 128, 256, 1024, + 4096, 16384, 65536, 262144, INT_MAX}; +static int malloc_n = 10; +double malloc_counts[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +bool malloc_counts_on = true; +#endif + +//########################################################################### +// Forward declarations (move to header?) +//########################################################################### + +static void statistics(ClpSimplex *originalModel, ClpSimplex *model); +static bool maskMatches(const int *starts, char **masks, std::string &check); +static void generateCode(CbcModel *model, const char *fileName, int type, + int preProcess); +#ifdef CBC_HAS_NAUTY +// returns number of constraints added +static int nautiedConstraints(CbcModel &model, int maxPass); +#endif + +// dummy fake main programs for UserClp and UserCbc +void fakeMain(ClpSimplex &model, OsiSolverInterface &osiSolver, + CbcModel &babSolver); +void fakeMain2(ClpSimplex &model, OsiClpSolverInterface &osiSolver, + int options); + +int CbcClpUnitTest(const CbcModel &saveModel, const std::string &dirMiplib, + int testSwitch, const double *stuff, std::deque, + int callBack(CbcModel *currentSolver, int whereFrom), + CbcParameters ¶meters); + +//########################################################################### +// Some debugging routines +//########################################################################### + +//########################################################################### +//########################################################################### #ifdef NEW_DEBUG_AND_FILL -#include -#include -#include -void *operator new(size_t size) -{ + +void *operator new(size_t size) { void *p = malloc(size); char *xx = (char *)p; memset(xx, 0x20, size); return p; } -void operator delete(void *p) throw() -{ - free(p); -} -#endif // end NEW_DEBUG -//#define CLP_MALLOC_STATISTICS + +//########################################################################### +//########################################################################### + +void operator delete(void *p) throw() { free(p); } + +#endif // end NEW_DEBUG_AND_FILL + +//########################################################################### +//########################################################################### #ifdef CLP_MALLOC_STATISTICS -#include -#include -#include + #include "stolen_from_ekk_malloc.cpp" -static double malloc_times = 0.0; -static double malloc_total = 0.0; -static int malloc_amount[] = { 0, 32, 128, 256, 1024, 4096, 16384, 65536, 262144, INT_MAX }; -static int malloc_n = 10; -double malloc_counts[10] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; -bool malloc_counts_on = true; -void *operator new(size_t size) throw(std::bad_alloc) -{ + +void *operator new(size_t size) throw(std::bad_alloc) { malloc_times++; malloc_total += size; int i; @@ -140,14 +302,17 @@ void *operator new(size_t size) throw(std::bad_alloc) #else void *p = malloc(size); #endif - //char * xx = (char *) p; - //memset(xx,0,size); + // char * xx = (char *) p; + // memset(xx,0,size); // Initialize random seed - //CoinSeedRandom(987654321); + // CoinSeedRandom(987654321); return p; } -void operator delete(void *p) throw() -{ + +//########################################################################### +//########################################################################### + +void operator delete(void *p) throw() { #ifdef DEBUG_MALLOC if (malloc_counts_on) stolen_from_ekk_freeBase(p); @@ -157,215 +322,250 @@ void operator delete(void *p) throw() free(p); #endif } -static void malloc_stats2() -{ + +//########################################################################### +//########################################################################### + +static void malloc_stats2() { double average = malloc_total / malloc_times; - printf("count %g bytes %g - average %g\n", malloc_times, malloc_total, average); - for (int i = 0; i < malloc_n; i++) + printf("count %g bytes %g - average %g\n", malloc_times, malloc_total, + average); + for (int i = 0; i < malloc_n; i++) { printf("%g ", malloc_counts[i]); + } printf("\n"); malloc_times = 0.0; malloc_total = 0.0; memset(malloc_counts, 0, sizeof(malloc_counts)); // print results } -#else //CLP_MALLOC_STATISTICS -//void stolen_from_ekk_memory(void * dummy,int type) -//{ -//} -//bool malloc_counts_on=false; -#endif //CLP_MALLOC_STATISTICS - -//#define DMALLOC -#ifdef DMALLOC -#include "dmalloc.h" -#endif - -#ifdef WSSMP_BARRIER -#define FOREIGN_BARRIER -#endif - -#ifdef UFL_BARRIER -#define FOREIGN_BARRIER -#endif - -#ifdef TAUCS_BARRIER -#define FOREIGN_BARRIER -#endif +#endif // CLP_MALLOC_STATISTICS -static int initialPumpTune = -1; -#include "CoinWarmStartBasis.hpp" +//########################################################################### +// Debug checks on special ordered sets. -#include "OsiSolverInterface.hpp" -#include "OsiCuts.hpp" -#include "OsiRowCut.hpp" -#include "OsiColCut.hpp" +// This is active only for debugging. The entire body of the routine becomes +// a noop when COIN_DEVELOP is not defined. To avoid compiler warnings, the +// formal parameters also need to go away. +//########################################################################### -#ifndef COIN_HAS_LINK -#define COIN_HAS_LINK +#ifdef COIN_DEVELOP +void checkSOS(CbcModel *babModel, const OsiSolverInterface *solver) +#else +void checkSOS(CbcModel * /*babModel*/, const OsiSolverInterface * /*solver*/) #endif -#ifdef COIN_HAS_LINK -#include "CbcLinked.hpp" +{ +#ifdef COIN_DEVELOP + if (!babModel->ownObjects()) + return; +#if COIN_DEVELOP > 2 + // const double *objective = solver->getObjCoefficients() ; + const double *columnLower = solver->getColLower(); + const double *columnUpper = solver->getColUpper(); + const double *solution = solver->getColSolution(); + // int numberRows = solver->getNumRows(); + // double direction = solver->getObjSense(); + // int iRow,iColumn; #endif -#include "CglCliqueStrengthening.hpp" -#include "CglBKClique.hpp" -#include "CglOddWheel.hpp" -#include "CglMessage.hpp" + // Row copy + CoinPackedMatrix matrixByRow(*solver->getMatrixByRow()); + // const double * elementByRow = matrixByRow.getElements(); + // const int * column = matrixByRow.getIndices(); + // const CoinBigIndex * rowStart = matrixByRow.getVectorStarts(); + const int *rowLength = matrixByRow.getVectorLengths(); -#include "CglPreProcess.hpp" -#include "CglCutGenerator.hpp" -#include "CglGomory.hpp" -#include "CglProbing.hpp" -#include "CglKnapsackCover.hpp" -#include "CglRedSplit.hpp" -#include "CglRedSplit2.hpp" -#include "CglGMI.hpp" -#include "CglClique.hpp" -#include "CglFlowCover.hpp" -#include "CglMixedIntegerRounding2.hpp" -#include "CglTwomir.hpp" -#include "CglDuplicateRow.hpp" -#include "CglStored.hpp" -#include "CglLandP.hpp" -#include "CglResidualCapacity.hpp" -#include "CglZeroHalf.hpp" -#if DEBUG_PREPROCESS >1 -extern double *debugSolution; -extern int debugNumberColumns; + // Column copy + CoinPackedMatrix matrixByCol(*solver->getMatrixByCol()); + const double *element = matrixByCol.getElements(); + const int *row = matrixByCol.getIndices(); + const CoinBigIndex *columnStart = matrixByCol.getVectorStarts(); + const int *columnLength = matrixByCol.getVectorLengths(); + + const double *rowLower = solver->getRowLower(); + const double *rowUpper = solver->getRowUpper(); + OsiObject **objects = babModel->objects(); + int numberObjects = babModel->numberObjects(); + int numberColumns = solver->getNumCols(); + for (int iObj = 0; iObj < numberObjects; iObj++) { + CbcSOS *objSOS = dynamic_cast(objects[iObj]); + if (objSOS) { + int n = objSOS->numberMembers(); + const int *which = objSOS->members(); +#if COIN_DEVELOP > 2 + const double *weight = objSOS->weights(); #endif -#include "CbcModel.hpp" -#include "CbcHeuristic.hpp" -#include "CbcHeuristicLocal.hpp" -#include "CbcHeuristicPivotAndFix.hpp" -//#include "CbcHeuristicPivotAndComplement.hpp" -#include "CbcHeuristicRandRound.hpp" -#include "CbcHeuristicGreedy.hpp" -#include "CbcHeuristicFPump.hpp" -#include "CbcHeuristicRINS.hpp" -#include "CbcHeuristicDiveCoefficient.hpp" -#include "CbcHeuristicDiveFractional.hpp" -#include "CbcHeuristicDiveGuided.hpp" -#include "CbcHeuristicDiveVectorLength.hpp" -#include "CbcHeuristicDivePseudoCost.hpp" -#include "CbcHeuristicDiveLineSearch.hpp" -#include "CbcTreeLocal.hpp" -#include "CbcCompareActual.hpp" -#include "CbcCompareObjective.hpp" -#include "CbcBranchActual.hpp" -#include "CbcBranchLotsize.hpp" -#include "CbcOrClpParam.hpp" -#include "CbcCutGenerator.hpp" -#include "CbcStrategy.hpp" -#include "CbcBranchCut.hpp" + int type = objSOS->sosType(); + // convexity row? + int iColumn; + iColumn = which[0]; + int j; + int convex = -1; + for (j = columnStart[iColumn]; + j < columnStart[iColumn] + columnLength[iColumn]; j++) { + int iRow = row[j]; + double value = element[j]; + if (rowLower[iRow] == 1.0 && rowUpper[iRow] == 1.0 && value == 1.0) { + // possible + if (rowLength[iRow] == n) { + if (convex == -1) + convex = iRow; + else + convex = -2; + } + } + } + printf("set %d of type %d has %d members - possible convexity row %d\n", + iObj, type, n, convex); + for (int i = 0; i < n; i++) { + iColumn = which[i]; + // Column may have been added + if (iColumn < numberColumns) { + int convex2 = -1; + for (j = columnStart[iColumn]; + j < columnStart[iColumn] + columnLength[iColumn]; j++) { + int iRow = row[j]; + if (iRow == convex) { + double value = element[j]; + if (value == 1.0) { + convex2 = iRow; + } + } + } + if (convex2 < 0 && convex >= 0) { + printf("odd convexity row\n"); + convex = -2; + } +#if COIN_DEVELOP > 2 + printf("col %d has weight %g and value %g, bounds %g %g\n", iColumn, + weight[i], solution[iColumn], columnLower[iColumn], + columnUpper[iColumn]); +#endif + } + } + } + } +#endif // COIN_DEVELOP +} -#include "OsiClpSolverInterface.hpp" +//########################################################################### +// Signal handling +//########################################################################### -#include "CbcSolverAnalyze.hpp" -#include "CbcSolverExpandKnapsack.hpp" +//########################################################################### +// Allow for interrupts +// But is this threadsafe? (so switched off by option) +//########################################################################### -#include "CbcSolver.hpp" +extern "C" { +static void signal_handler(int whichSignal) { + if (currentBranchModel != NULL) { + currentBranchModel->sayEventHappened(); // say why stopped + if (currentBranchModel->heuristicModel()) + currentBranchModel->heuristicModel()->sayEventHappened(); + } + return; +} +} -//#define IN_BRANCH_AND_BOUND (0x01000000|262144) -#define IN_BRANCH_AND_BOUND (0x01000000 | 262144 | 128 | 1024 | 2048) -//#define IN_BRANCH_AND_BOUND (0x01000000|262144|128) +//########################################################################### +// Handle crashes +//########################################################################### -/* - CbcStopNow class definitions. -*/ +#if defined(HAVE_SIGNAL_H) && defined(HAVE_EXECINFO_H) +void CbcCrashHandler(int sig) { + char signame[256] = ""; + switch (sig) { + case SIGILL: + strcpy(signame, "SIGILL"); + break; + case SIGSEGV: + strcpy(signame, "SIGSEGV"); + break; + case SIGABRT: + strcpy(signame, "SIGABRT"); + break; + } -CbcStopNow::CbcStopNow() -{ -} -CbcStopNow::~CbcStopNow() -{ -} -// Copy constructor -CbcStopNow::CbcStopNow(const CbcStopNow &) -{ -} -// Assignment operator -CbcStopNow & -CbcStopNow::operator=(const CbcStopNow &rhs) -{ - if (this != &rhs) { + fflush(stderr); + fflush(stdout); + fprintf( + stderr, + "\n\nERROR while running Cbc. Signal %s caught. Getting stack trace.\n", + signame); + fflush(stderr); + { + char *st = getenv("RUNNING_TEST"); + if (st) { + fprintf(stderr, "Error happened while running the \"%s\" test\n", st); + fflush(stderr); + } } - return *this; -} -// Clone -CbcStopNow * -CbcStopNow::clone() const -{ - return new CbcStopNow(*this); -} -/* - CbcUser class definitions. -*/ +#define MAX_FRAMES 50 + void *array[MAX_FRAMES]; + size_t size; + char **strings; + size_t i; -// User stuff (base class) -CbcUser::CbcUser() - : coinModel_(NULL) - , userName_("null") -{ -} -CbcUser::~CbcUser() -{ - delete coinModel_; -} -// Copy constructor -CbcUser::CbcUser(const CbcUser &rhs) -{ - if (rhs.coinModel_) - coinModel_ = new CoinModel(*rhs.coinModel_); - else - coinModel_ = NULL; - userName_ = rhs.userName_; -} -// Assignment operator -CbcUser & -CbcUser::operator=(const CbcUser &rhs) -{ - if (this != &rhs) { - if (rhs.coinModel_) - coinModel_ = new CoinModel(*rhs.coinModel_); - else - coinModel_ = NULL; - userName_ = rhs.userName_; + size = backtrace(array, MAX_FRAMES); + strings = backtrace_symbols(array, size); + + for (i = 0; i < size; i++) { + fprintf(stderr, "%s\n", strings[i]); + fflush(stderr); } - return *this; + fprintf(stderr, "\n\n"); + fflush(stderr); + + free(strings); + + if (!cbcCrashAnnounced) { + cbcCrashAnnounced = 1; + abort(); + } +#undef MAX_FRAMES } +#endif + +//########################################################################### +// Some additional helper functions +//########################################################################### static void putBackOtherSolutions(CbcModel *presolvedModel, CbcModel *model, - CglPreProcess *preProcess) -{ + CglPreProcess *preProcess) { int numberSolutions = presolvedModel->numberSavedSolutions(); int numberColumns = presolvedModel->getNumCols(); if (numberSolutions > 1) { model->deleteSolutions(); - double *bestSolution = CoinCopyOfArray(presolvedModel->bestSolution(), numberColumns); - //double cutoff = presolvedModel->getCutoff(); + double *bestSolution = + CoinCopyOfArray(presolvedModel->bestSolution(), numberColumns); + // double cutoff = presolvedModel->getCutoff(); double objectiveValue = presolvedModel->getObjValue(); - //model->createSpaceForSavedSolutions(numberSolutions-1); + // model->createSpaceForSavedSolutions(numberSolutions-1); for (int iSolution = numberSolutions - 1; iSolution >= 0; iSolution--) { presolvedModel->setCutoff(COIN_DBL_MAX); - presolvedModel->solver()->setColSolution(presolvedModel->savedSolution(iSolution)); - //presolvedModel->savedSolutionObjective(iSolution)); + presolvedModel->solver()->setColSolution( + presolvedModel->savedSolution(iSolution)); + // presolvedModel->savedSolutionObjective(iSolution)); preProcess->postProcess(*presolvedModel->solver(), false); - model->setBestSolution(preProcess->originalModel()->getColSolution(), model->solver()->getNumCols(), - presolvedModel->savedSolutionObjective(iSolution)); + model->setBestSolution(preProcess->originalModel()->getColSolution(), + model->solver()->getNumCols(), + presolvedModel->savedSolutionObjective(iSolution)); } presolvedModel->setBestObjectiveValue(objectiveValue); presolvedModel->solver()->setColSolution(bestSolution); - //presolvedModel->setBestSolution(bestSolution,numberColumns,objectiveValue); + // presolvedModel->setBestSolution(bestSolution,numberColumns,objectiveValue); } } +//########################################################################### +//########################################################################### + // For when number of column is messed up e.g. BiLinear -static int numberPrintingColumns(const OsiSolverInterface *solver) -{ +static int numberPrintingColumns(const OsiSolverInterface *solver) { #ifdef COIN_HAS_LINK - const OsiSolverLink *linkSolver = dynamic_cast< const OsiSolverLink * >(solver); + const OsiSolverLink *linkSolver = dynamic_cast(solver); if (!linkSolver) return solver->getNumCols(); return linkSolver->coinModel()->numberColumns(); @@ -374,65 +574,139 @@ static int numberPrintingColumns(const OsiSolverInterface *solver) #endif } -/* - CbcSolver class definitions -*/ +//########################################################################### +//########################################################################### + +//########################################################################### +// CbcUser definitions +//########################################################################### + +//########################################################################### +//########################################################################### + +// User stuff (base class) +CbcUser::CbcUser() : coinModel_(NULL), userName_("null") {} + +//########################################################################### +//########################################################################### + +CbcUser::~CbcUser() { delete coinModel_; } + +//########################################################################### +//########################################################################### + +// Copy constructor +CbcUser::CbcUser(const CbcUser &rhs) { + if (rhs.coinModel_) + coinModel_ = new CoinModel(*rhs.coinModel_); + else + coinModel_ = NULL; + userName_ = rhs.userName_; +} + +//########################################################################### +//########################################################################### + +// Assignment operator +CbcUser &CbcUser::operator=(const CbcUser &rhs) { + if (this != &rhs) { + if (rhs.coinModel_) + coinModel_ = new CoinModel(*rhs.coinModel_); + else + coinModel_ = NULL; + userName_ = rhs.userName_; + } + return *this; +} + +//########################################################################### +//########################################################################### + +//########################################################################### +// CbcStopNow definitions +//########################################################################### + +//########################################################################### +//########################################################################### + +CbcStopNow::CbcStopNow() {} + +//########################################################################### +//########################################################################### + +CbcStopNow::~CbcStopNow() {} + +//########################################################################### +//########################################################################### + +// Copy constructor +CbcStopNow::CbcStopNow(const CbcStopNow &) {} + +//########################################################################### +//########################################################################### + +// Assignment operator +CbcStopNow &CbcStopNow::operator=(const CbcStopNow &rhs) { + if (this != &rhs) { + } + return *this; +} + +//########################################################################### +//########################################################################### + +// Clone +CbcStopNow *CbcStopNow::clone() const { return new CbcStopNow(*this); } + +//########################################################################### +//########################################################################### + +//########################################################################### +// CbcSsolver definitions +//########################################################################### CbcSolver::CbcSolver() - : babModel_(NULL) - , userFunction_(NULL) - , statusUserFunction_(NULL) - , originalSolver_(NULL) - , originalCoinModel_(NULL) - , cutGenerator_(NULL) - , numberUserFunctions_(0) - , numberCutGenerators_(0) - , startTime_(CoinCpuTime()) - , doMiplib_(false) - , noPrinting_(false) - , readMode_(1) -{ + : babModel_(NULL), userFunction_(NULL), statusUserFunction_(NULL), + originalSolver_(NULL), originalCoinModel_(NULL), cutGenerator_(NULL), + numberUserFunctions_(0), numberCutGenerators_(0), + startTime_(CoinCpuTime()), doMiplib_(false), noPrinting_(false), + readMode_(1) { callBack_ = new CbcStopNow(); - fillParameters(); + //fillParameters(); } + +//########################################################################### +//########################################################################### + CbcSolver::CbcSolver(const OsiClpSolverInterface &solver) - : babModel_(NULL) - , userFunction_(NULL) - , statusUserFunction_(NULL) - , originalSolver_(NULL) - , originalCoinModel_(NULL) - , cutGenerator_(NULL) - , numberUserFunctions_(0) - , numberCutGenerators_(0) - , startTime_(CoinCpuTime()) - , doMiplib_(false) - , noPrinting_(false) - , readMode_(1) -{ + : babModel_(NULL), userFunction_(NULL), statusUserFunction_(NULL), + originalSolver_(NULL), originalCoinModel_(NULL), cutGenerator_(NULL), + numberUserFunctions_(0), numberCutGenerators_(0), + startTime_(CoinCpuTime()), doMiplib_(false), noPrinting_(false), + readMode_(1) { callBack_ = new CbcStopNow(); model_ = CbcModel(solver); - fillParameters(); + //fillParameters(); } + +//########################################################################### +//########################################################################### + CbcSolver::CbcSolver(const CbcModel &solver) - : babModel_(NULL) - , userFunction_(NULL) - , statusUserFunction_(NULL) - , originalSolver_(NULL) - , originalCoinModel_(NULL) - , cutGenerator_(NULL) - , numberUserFunctions_(0) - , numberCutGenerators_(0) - , startTime_(CoinCpuTime()) - , doMiplib_(false) - , noPrinting_(false) - , readMode_(1) -{ + : babModel_(NULL), userFunction_(NULL), statusUserFunction_(NULL), + originalSolver_(NULL), originalCoinModel_(NULL), cutGenerator_(NULL), + numberUserFunctions_(0), numberCutGenerators_(0), + startTime_(CoinCpuTime()), doMiplib_(false), noPrinting_(false), + readMode_(1) { callBack_ = new CbcStopNow(); model_ = solver; - fillParameters(); + //fillParameters(); } -CbcSolver::~CbcSolver() -{ + +//########################################################################### +//########################################################################### + +CbcSolver::~CbcSolver() { int i; for (i = 0; i < numberUserFunctions_; i++) delete userFunction_[i]; @@ -446,21 +720,20 @@ CbcSolver::~CbcSolver() delete babModel_; delete callBack_; } + +//########################################################################### +//########################################################################### + // Copy constructor CbcSolver::CbcSolver(const CbcSolver &rhs) - : model_(rhs.model_) - , babModel_(NULL) - , userFunction_(NULL) - , statusUserFunction_(NULL) - , cutGenerator_(new CglCutGenerator *[rhs.numberCutGenerators()]) - , numberUserFunctions_(rhs.numberUserFunctions_) - , numberCutGenerators_(rhs.numberCutGenerators()) - , startTime_(CoinCpuTime()) - , doMiplib_(rhs.doMiplib_) - , noPrinting_(rhs.noPrinting_) - , readMode_(rhs.readMode_) -{ - fillParameters(); + : model_(rhs.model_), babModel_(NULL), userFunction_(NULL), + statusUserFunction_(NULL), + cutGenerator_(new CglCutGenerator *[rhs.numberCutGenerators()]), + numberUserFunctions_(rhs.numberUserFunctions_), + numberCutGenerators_(rhs.numberCutGenerators()), + startTime_(CoinCpuTime()), doMiplib_(rhs.doMiplib_), + noPrinting_(rhs.noPrinting_), readMode_(rhs.readMode_) { + //fillParameters(); if (rhs.babModel_) babModel_ = new CbcModel(*rhs.babModel_); userFunction_ = new CbcUser *[numberUserFunctions_]; @@ -468,23 +741,26 @@ CbcSolver::CbcSolver(const CbcSolver &rhs) for (i = 0; i < numberUserFunctions_; i++) userFunction_[i] = rhs.userFunction_[i]->clone(); this->parameters_ = rhs.parameters_; + this->clpParameters_ = rhs.clpParameters_; for (i = 0; i < numberCutGenerators_; i++) cutGenerator_[i] = rhs.cutGenerator_[i]->clone(); callBack_ = rhs.callBack_->clone(); originalSolver_ = NULL; if (rhs.originalSolver_) { OsiSolverInterface *temp = rhs.originalSolver_->clone(); - originalSolver_ = dynamic_cast< OsiClpSolverInterface * >(temp); + originalSolver_ = dynamic_cast(temp); assert(originalSolver_); } originalCoinModel_ = NULL; if (rhs.originalCoinModel_) originalCoinModel_ = new CoinModel(*rhs.originalCoinModel_); } + +//########################################################################### +//########################################################################### + // Assignment operator -CbcSolver & -CbcSolver::operator=(const CbcSolver &rhs) -{ +CbcSolver &CbcSolver::operator=(const CbcSolver &rhs) { if (this != &rhs) { int i; for (i = 0; i < numberUserFunctions_; i++) @@ -501,6 +777,7 @@ CbcSolver::operator=(const CbcSolver &rhs) numberUserFunctions_ = rhs.numberUserFunctions_; startTime_ = rhs.startTime_; this->parameters_ = rhs.parameters_; + this->clpParameters_ = rhs.clpParameters_; for (i = 0; i < numberCutGenerators_; i++) cutGenerator_[i] = rhs.cutGenerator_[i]->clone(); noPrinting_ = rhs.noPrinting_; @@ -518,7 +795,7 @@ CbcSolver::operator=(const CbcSolver &rhs) originalSolver_ = NULL; if (rhs.originalSolver_) { OsiSolverInterface *temp = rhs.originalSolver_->clone(); - originalSolver_ = dynamic_cast< OsiClpSolverInterface * >(temp); + originalSolver_ = dynamic_cast(temp); assert(originalSolver_); } originalCoinModel_ = NULL; @@ -527,29 +804,44 @@ CbcSolver::operator=(const CbcSolver &rhs) } return *this; } + +//########################################################################### +//########################################################################### + // Get int value -int CbcSolver::intValue(CbcOrClpParameterType type) const -{ - return parameters_[whichParam(type, parameters_)].intValue(); +int CbcSolver::intValue(int code) { + return parameters_[code]->intVal(); } + +//########################################################################### +//########################################################################### + // Set int value -void CbcSolver::setIntValue(CbcOrClpParameterType type, int value) -{ - parameters_[whichParam(type, parameters_)].setIntValue(value); +void CbcSolver::setIntValue(int code, int value) { + parameters_[code]->setVal(value); } -// Get double value -double CbcSolver::doubleValue(CbcOrClpParameterType type) const -{ - return parameters_[whichParam(type, parameters_)].doubleValue(); + +//########################################################################### +//########################################################################### + +// Get double value +double CbcSolver::doubleValue(int code) { + return parameters_[code]->dblVal(); } + +//########################################################################### +//########################################################################### + // Set double value -void CbcSolver::setDoubleValue(CbcOrClpParameterType type, double value) -{ - parameters_[whichParam(type, parameters_)].setDoubleValue(value); +void CbcSolver::setDoubleValue(int code, double value) { + parameters_[code]->setVal(value); } + +//########################################################################### +//########################################################################### + // User function (NULL if no match) -CbcUser *CbcSolver::userFunction(const char *name) const -{ +CbcUser *CbcSolver::userFunction(const char *name) const { int i; for (i = 0; i < numberUserFunctions_; i++) { if (!strcmp(name, userFunction_[i]->name().c_str())) @@ -560,776 +852,244 @@ CbcUser *CbcSolver::userFunction(const char *name) const else return NULL; } -void CbcSolver::fillParameters() -{ - establishParams(parameters_); - const char dirsep = CoinFindDirSeparator(); - std::string directory; - std::string dirSample; - std::string dirNetlib; - std::string dirMiplib; - if (dirsep == '/') { - directory = "./"; - dirSample = "../../Data/Sample/"; - dirNetlib = "../../Data/Netlib/"; - dirMiplib = "../../Data/miplib3/"; - } else { - directory = ".\\"; - dirSample = "..\\..\\..\\..\\Data\\Sample\\"; - dirNetlib = "..\\..\\..\\..\\Data\\Netlib\\"; - dirMiplib = "..\\..\\..\\..\\Data\\miplib3\\"; - } - std::string defaultDirectory = directory; - std::string importFile = ""; - std::string exportFile = "default.mps"; - std::string importBasisFile = ""; - std::string importPriorityFile = ""; - std::string mipStartFile = ""; - std::string debugFile = ""; - std::string printMask = ""; - std::string exportBasisFile = "default.bas"; - std::string saveFile = "default.prob"; - std::string restoreFile = "default.prob"; - std::string solutionFile = "stdout"; - std::string solutionSaveFile = "solution.file"; - int doIdiot = -1; - int outputFormat = 2; - int substitution = 3; - int dualize = 3; - int preSolve = 5; - int doSprint = -1; - int testOsiParameters = -1; - int createSolver = 0; - ClpSimplex *lpSolver; - OsiClpSolverInterface *clpSolver; - if (model_.solver()) { - clpSolver = dynamic_cast< OsiClpSolverInterface * >(model_.solver()); - assert(clpSolver); - lpSolver = clpSolver->getModelPtr(); - assert(lpSolver); - } else { - lpSolver = new ClpSimplex(); - clpSolver = new OsiClpSolverInterface(lpSolver, true); - createSolver = 1; - } - parameters_[whichParam(CLP_PARAM_ACTION_BASISIN, parameters_)].setStringValue(importBasisFile); - parameters_[whichParam(CBC_PARAM_ACTION_PRIORITYIN, parameters_)].setStringValue(importPriorityFile); - parameters_[whichParam(CBC_PARAM_ACTION_MIPSTART, parameters_)].setStringValue(mipStartFile); - parameters_[whichParam(CLP_PARAM_ACTION_BASISOUT, parameters_)].setStringValue(exportBasisFile); - parameters_[whichParam(CLP_PARAM_ACTION_DEBUG, parameters_)].setStringValue(debugFile); - parameters_[whichParam(CLP_PARAM_ACTION_PRINTMASK, parameters_)].setStringValue(printMask); - parameters_[whichParam(CLP_PARAM_ACTION_DIRECTORY, parameters_)].setStringValue(directory); - parameters_[whichParam(CLP_PARAM_ACTION_DIRSAMPLE, parameters_)].setStringValue(dirSample); - parameters_[whichParam(CLP_PARAM_ACTION_DIRNETLIB, parameters_)].setStringValue(dirNetlib); - parameters_[whichParam(CBC_PARAM_ACTION_DIRMIPLIB, parameters_)].setStringValue(dirMiplib); - parameters_[whichParam(CLP_PARAM_DBL_DUALBOUND, parameters_)].setDoubleValue(lpSolver->dualBound()); - parameters_[whichParam(CLP_PARAM_DBL_DUALTOLERANCE, parameters_)].setDoubleValue(lpSolver->dualTolerance()); - parameters_[whichParam(CLP_PARAM_ACTION_EXPORT, parameters_)].setStringValue(exportFile); - parameters_[whichParam(CLP_PARAM_INT_IDIOT, parameters_)].setIntValue(doIdiot); - parameters_[whichParam(CLP_PARAM_ACTION_IMPORT, parameters_)].setStringValue(importFile); - parameters_[whichParam(CLP_PARAM_DBL_PRESOLVETOLERANCE, parameters_)].setDoubleValue(1.0e-8); - int iParam = whichParam(CLP_PARAM_INT_SOLVERLOGLEVEL, parameters_); - int value = 1; - clpSolver->messageHandler()->setLogLevel(1); - lpSolver->setLogLevel(1); - parameters_[iParam].setIntValue(value); - iParam = whichParam(CLP_PARAM_INT_LOGLEVEL, parameters_); - model_.messageHandler()->setLogLevel(value); - parameters_[iParam].setIntValue(value); - parameters_[whichParam(CLP_PARAM_INT_MAXFACTOR, parameters_)].setIntValue(lpSolver->factorizationFrequency()); - parameters_[whichParam(CLP_PARAM_INT_MAXITERATION, parameters_)].setIntValue(lpSolver->maximumIterations()); - parameters_[whichParam(CLP_PARAM_INT_OUTPUTFORMAT, parameters_)].setIntValue(outputFormat); - parameters_[whichParam(CLP_PARAM_INT_PRESOLVEPASS, parameters_)].setIntValue(preSolve); - parameters_[whichParam(CLP_PARAM_INT_PERTVALUE, parameters_)].setIntValue(lpSolver->perturbation()); - parameters_[whichParam(CLP_PARAM_DBL_PRIMALTOLERANCE, parameters_)].setDoubleValue(lpSolver->primalTolerance()); - parameters_[whichParam(CLP_PARAM_DBL_PRIMALWEIGHT, parameters_)].setDoubleValue(lpSolver->infeasibilityCost()); - parameters_[whichParam(CLP_PARAM_ACTION_RESTORE, parameters_)].setStringValue(restoreFile); - parameters_[whichParam(CLP_PARAM_ACTION_SAVE, parameters_)].setStringValue(saveFile); - //parameters_[whichParam(CLP_PARAM_DBL_TIMELIMIT,numberParameters_,parameters_)].setDoubleValue(1.0e8); - parameters_[whichParam(CBC_PARAM_DBL_TIMELIMIT_BAB, parameters_)].setDoubleValue(1.0e8); - parameters_[whichParam(CLP_PARAM_ACTION_SOLUTION, parameters_)].setStringValue(solutionFile); - parameters_[whichParam(CLP_PARAM_ACTION_NEXTBESTSOLUTION, parameters_)].setStringValue(solutionFile); - parameters_[whichParam(CLP_PARAM_ACTION_SAVESOL, parameters_)].setStringValue(solutionSaveFile); - parameters_[whichParam(CLP_PARAM_INT_SPRINT, parameters_)].setIntValue(doSprint); - parameters_[whichParam(CLP_PARAM_INT_SUBSTITUTION, parameters_)].setIntValue(substitution); - parameters_[whichParam(CLP_PARAM_INT_DUALIZE, parameters_)].setIntValue(dualize); - parameters_[whichParam(CBC_PARAM_INT_NUMBERBEFORE, parameters_)].setIntValue(model_.numberBeforeTrust()); - parameters_[whichParam(CBC_PARAM_INT_MAXNODES, parameters_)].setIntValue(model_.getMaximumNodes()); - parameters_[whichParam(CBC_PARAM_INT_STRONGBRANCHING, parameters_)].setIntValue(model_.numberStrong()); - parameters_[whichParam(CBC_PARAM_DBL_INFEASIBILITYWEIGHT, parameters_)].setDoubleValue(model_.getDblParam(CbcModel::CbcInfeasibilityWeight)); - parameters_[whichParam(CBC_PARAM_DBL_INTEGERTOLERANCE, parameters_)].setDoubleValue(model_.getDblParam(CbcModel::CbcIntegerTolerance)); - parameters_[whichParam(CBC_PARAM_DBL_INCREMENT, parameters_)].setDoubleValue(model_.getDblParam(CbcModel::CbcCutoffIncrement)); - parameters_[whichParam(CBC_PARAM_INT_TESTOSI, parameters_)].setIntValue(testOsiParameters); - parameters_[whichParam(CBC_PARAM_INT_FPUMPTUNE, parameters_)].setIntValue(1003); - initialPumpTune = 1003; -#ifdef CBC_THREAD - parameters_[whichParam(CBC_PARAM_INT_THREADS, parameters_)].setIntValue(0); -#endif - // Set up likely cut generators and defaults - parameters_[whichParam(CBC_PARAM_STR_PREPROCESS, parameters_)].setCurrentOption("sos"); - parameters_[whichParam(CBC_PARAM_INT_MIPOPTIONS, parameters_)].setIntValue(1057); - parameters_[whichParam(CBC_PARAM_INT_CUTPASSINTREE, parameters_)].setIntValue(1); - parameters_[whichParam(CBC_PARAM_INT_MOREMIPOPTIONS, parameters_)].setIntValue(-1); - parameters_[whichParam(CBC_PARAM_INT_MAXHOTITS, parameters_)].setIntValue(100); - parameters_[whichParam(CBC_PARAM_STR_CUTSSTRATEGY, parameters_)].setCurrentOption("on"); - parameters_[whichParam(CBC_PARAM_STR_HEURISTICSTRATEGY, parameters_)].setCurrentOption("on"); - parameters_[whichParam(CBC_PARAM_STR_NODESTRATEGY, parameters_)].setCurrentOption("fewest"); - parameters_[whichParam(CBC_PARAM_STR_GOMORYCUTS, parameters_)].setCurrentOption("ifmove"); - parameters_[whichParam(CBC_PARAM_STR_PROBINGCUTS, parameters_)].setCurrentOption("ifmove"); - parameters_[whichParam(CBC_PARAM_STR_KNAPSACKCUTS, parameters_)].setCurrentOption("ifmove"); - parameters_[whichParam(CBC_PARAM_STR_ZEROHALFCUTS, parameters_)].setCurrentOption("ifmove"); - parameters_[whichParam(CBC_PARAM_STR_REDSPLITCUTS, parameters_)].setCurrentOption("off"); - parameters_[whichParam(CBC_PARAM_STR_REDSPLIT2CUTS, parameters_)].setCurrentOption("off"); - parameters_[whichParam(CBC_PARAM_STR_GMICUTS, parameters_)].setCurrentOption("off"); - parameters_[whichParam(CBC_PARAM_STR_MIXEDCUTS, parameters_)].setCurrentOption("ifmove"); - parameters_[whichParam(CBC_PARAM_STR_FLOWCUTS, parameters_)].setCurrentOption("ifmove"); - parameters_[whichParam(CBC_PARAM_STR_TWOMIRCUTS, parameters_)].setCurrentOption("ifmove"); - parameters_[whichParam(CBC_PARAM_STR_LANDPCUTS, parameters_)].setCurrentOption("off"); - parameters_[whichParam(CBC_PARAM_STR_RESIDCUTS, parameters_)].setCurrentOption("off"); - parameters_[whichParam(CBC_PARAM_STR_ROUNDING, parameters_)].setCurrentOption("on"); - parameters_[whichParam(CBC_PARAM_STR_FPUMP, parameters_)].setCurrentOption("on"); - parameters_[whichParam(CBC_PARAM_STR_GREEDY, parameters_)].setCurrentOption("on"); - parameters_[whichParam(CBC_PARAM_STR_COMBINE, parameters_)].setCurrentOption("on"); - parameters_[whichParam(CBC_PARAM_STR_CROSSOVER2, parameters_)].setCurrentOption("off"); - parameters_[whichParam(CBC_PARAM_STR_PIVOTANDCOMPLEMENT, parameters_)].setCurrentOption("off"); - parameters_[whichParam(CBC_PARAM_STR_PIVOTANDFIX, parameters_)].setCurrentOption("off"); - parameters_[whichParam(CBC_PARAM_STR_RANDROUND, parameters_)].setCurrentOption("off"); - parameters_[whichParam(CBC_PARAM_STR_NAIVE, parameters_)].setCurrentOption("off"); - parameters_[whichParam(CBC_PARAM_STR_RINS, parameters_)].setCurrentOption("off"); - parameters_[whichParam(CBC_PARAM_STR_DINS, parameters_)].setCurrentOption("off"); - parameters_[whichParam(CBC_PARAM_STR_RENS, parameters_)].setCurrentOption("off"); - parameters_[whichParam(CBC_PARAM_STR_LOCALTREE, parameters_)].setCurrentOption("off"); - parameters_[whichParam(CBC_PARAM_STR_COSTSTRATEGY, parameters_)].setCurrentOption("off"); - parameters_[whichParam(CBC_PARAM_STR_CLIQUECUTS, parameters_)].setCurrentOption("ifmove"); - parameters_[whichParam(CBC_PARAM_STR_ODDWHEELCUTS, parameters_)].setCurrentOption("ifmove"); - parameters_[whichParam(CBC_PARAM_STR_CLQSTRENGTHENING, parameters_)].setCurrentOption("after"); - parameters_[whichParam(CBC_PARAM_STR_USECGRAPH, parameters_)].setCurrentOption("on"); - parameters_[whichParam(CBC_PARAM_INT_BKPIVOTINGSTRATEGY, parameters_)].setIntValue(3); - parameters_[whichParam(CBC_PARAM_INT_BKMAXCALLS, parameters_)].setIntValue(1000); - parameters_[whichParam(CBC_PARAM_INT_BKCLQEXTMETHOD, parameters_)].setIntValue(4); - parameters_[whichParam(CBC_PARAM_INT_ODDWEXTMETHOD, parameters_)].setIntValue(2); - if (createSolver) - delete clpSolver; -} -/* - Initialise a subset of the parameters prior to processing any input from - the user. +//########################################################################### +//########################################################################### - Why this choice of subset? -*/ -/*! - \todo Guard/replace clp-specific code -*/ -void CbcSolver::fillValuesInSolver() -{ - OsiSolverInterface *solver = model_.solver(); - OsiClpSolverInterface *clpSolver = dynamic_cast< OsiClpSolverInterface * >(solver); - assert(clpSolver); - ClpSimplex *lpSolver = clpSolver->getModelPtr(); - - /* - Why are we reaching into the underlying solver(s) for these settings? - Shouldn't CbcSolver have its own defaults, which are then imposed on the - underlying solver? - - Coming at if from the other side, if CbcSolver had the capability to use - multiple solvers then it definitely makes sense to acquire the defaults from - the solver (on the assumption that we haven't processed command line - parameters yet, which can then override the defaults). But then it's more of - a challenge to avoid solver-specific coding here. - */ - noPrinting_ = (lpSolver->logLevel() == 0); - CoinMessageHandler *generalMessageHandler = clpSolver->messageHandler(); - generalMessageHandler->setPrefix(true); - - lpSolver->setPerturbation(50); - lpSolver->messageHandler()->setPrefix(false); - - parameters_[whichParam(CLP_PARAM_DBL_DUALBOUND, parameters_)].setDoubleValue(lpSolver->dualBound()); - parameters_[whichParam(CLP_PARAM_DBL_DUALTOLERANCE, parameters_)].setDoubleValue(lpSolver->dualTolerance()); - /* - Why are we doing this? We read the log level from parameters_, set it into - the message handlers for cbc and the underlying solver. Then we read the - log level back from the handlers and use it to set the values in - parameters_! - */ - int iParam = whichParam(CLP_PARAM_INT_SOLVERLOGLEVEL, parameters_); - int value = parameters_[iParam].intValue(); - clpSolver->messageHandler()->setLogLevel(value); - lpSolver->setLogLevel(value); - iParam = whichParam(CLP_PARAM_INT_LOGLEVEL, parameters_); - value = parameters_[iParam].intValue(); - model_.messageHandler()->setLogLevel(value); - parameters_[whichParam(CLP_PARAM_INT_LOGLEVEL, parameters_)].setIntValue(model_.logLevel()); - parameters_[whichParam(CLP_PARAM_INT_SOLVERLOGLEVEL, parameters_)].setIntValue(lpSolver->logLevel()); - parameters_[whichParam(CLP_PARAM_INT_MAXFACTOR, parameters_)].setIntValue(lpSolver->factorizationFrequency()); - parameters_[whichParam(CLP_PARAM_INT_MAXITERATION, parameters_)].setIntValue(lpSolver->maximumIterations()); - parameters_[whichParam(CLP_PARAM_INT_PERTVALUE, parameters_)].setIntValue(lpSolver->perturbation()); - parameters_[whichParam(CLP_PARAM_DBL_PRIMALTOLERANCE, parameters_)].setDoubleValue(lpSolver->primalTolerance()); - parameters_[whichParam(CLP_PARAM_DBL_PRIMALWEIGHT, parameters_)].setDoubleValue(lpSolver->infeasibilityCost()); - parameters_[whichParam(CBC_PARAM_INT_NUMBERBEFORE, parameters_)].setIntValue(model_.numberBeforeTrust()); - parameters_[whichParam(CBC_PARAM_INT_MAXNODES, parameters_)].setIntValue(model_.getMaximumNodes()); - parameters_[whichParam(CBC_PARAM_INT_STRONGBRANCHING, parameters_)].setIntValue(model_.numberStrong()); - parameters_[whichParam(CBC_PARAM_DBL_INFEASIBILITYWEIGHT, parameters_)].setDoubleValue(model_.getDblParam(CbcModel::CbcInfeasibilityWeight)); - parameters_[whichParam(CBC_PARAM_DBL_INTEGERTOLERANCE, parameters_)].setDoubleValue(model_.getDblParam(CbcModel::CbcIntegerTolerance)); - parameters_[whichParam(CBC_PARAM_DBL_INCREMENT, parameters_)].setDoubleValue(model_.getDblParam(CbcModel::CbcCutoffIncrement)); -} // Add user function -void CbcSolver::addUserFunction(CbcUser *function) -{ +void CbcSolver::addUserFunction(CbcUser *function) { CbcUser **temp = new CbcUser *[numberUserFunctions_ + 1]; int i; - for (i = 0; i < numberUserFunctions_; i++) - temp[i] = userFunction_[i]; - delete[] userFunction_; - userFunction_ = temp; - userFunction_[numberUserFunctions_++] = function->clone(); - delete[] statusUserFunction_; - statusUserFunction_ = NULL; -} -// Set user call back -void CbcSolver::setUserCallBack(CbcStopNow *function) -{ - delete callBack_; - callBack_ = function->clone(); -} -// Copy of model on initial load (will contain output solutions) -void CbcSolver::setOriginalSolver(OsiClpSolverInterface *originalSolver) -{ - delete originalSolver_; - OsiSolverInterface *temp = originalSolver->clone(); - originalSolver_ = dynamic_cast< OsiClpSolverInterface * >(temp); - assert(originalSolver_); -} -// Copy of model on initial load -void CbcSolver::setOriginalCoinModel(CoinModel *originalCoinModel) -{ - delete originalCoinModel_; - originalCoinModel_ = new CoinModel(*originalCoinModel); -} -// Add cut generator -void CbcSolver::addCutGenerator(CglCutGenerator *generator) -{ - CglCutGenerator **temp = new CglCutGenerator *[numberCutGenerators_ + 1]; - int i; - for (i = 0; i < numberCutGenerators_; i++) - temp[i] = cutGenerator_[i]; - delete[] cutGenerator_; - cutGenerator_ = temp; - cutGenerator_[numberCutGenerators_++] = generator->clone(); -} - -/* - The only other solver that's ever been used is cplex, and the use is - limited -- do the root with clp and all the cbc smarts, then give the - problem over to cplex to finish. Although the defines can be read in some - places to allow other options, nothing's been tested and success is - unlikely. - - CBC_OTHER_SOLVER == 1 is cplex. -*/ - -#if CBC_OTHER_SOLVER == 1 -#ifndef CBC_HAS_OSICPX -#error "Configuration did not detect OsiCpx installation." -#else -#include "OsiCpxSolverInterface.hpp" -#endif -#endif - -static void statistics(ClpSimplex *originalModel, ClpSimplex *model); -static bool maskMatches(const int *starts, char **masks, - std::string &check); -static void generateCode(CbcModel *model, const char *fileName, int type, int preProcess); -#ifdef CBC_HAS_NAUTY -// returns number of constraints added -static int nautiedConstraints(CbcModel &model, int maxPass); -#endif - -// dummy fake main programs for UserClp and UserCbc -void fakeMain(ClpSimplex &model, OsiSolverInterface &osiSolver, CbcModel &babSolver); -void fakeMain2(ClpSimplex &model, OsiClpSolverInterface &osiSolver, int options); - -// Allow for interrupts -// But is this threadsafe? (so switched off by option) - -#include "CoinSignal.hpp" -static CbcModel *currentBranchModel = NULL; - -extern "C" { -static void signal_handler(int whichSignal) -{ - if (currentBranchModel != NULL) { - currentBranchModel->sayEventHappened(); // say why stopped - if (currentBranchModel->heuristicModel()) - currentBranchModel->heuristicModel()->sayEventHappened(); - } - return; -} -} - -/* - Debug checks on special ordered sets. - - This is active only for debugging. The entire body of the routine becomes - a noop when COIN_DEVELOP is not defined. To avoid compiler warnings, the - formal parameters also need to go away. -*/ -#ifdef COIN_DEVELOP -void checkSOS(CbcModel *babModel, const OsiSolverInterface *solver) -#else -void checkSOS(CbcModel * /*babModel*/, const OsiSolverInterface * /*solver*/) -#endif -{ -#ifdef COIN_DEVELOP - if (!babModel->ownObjects()) - return; -#if COIN_DEVELOP > 2 - //const double *objective = solver->getObjCoefficients() ; - const double *columnLower = solver->getColLower(); - const double *columnUpper = solver->getColUpper(); - const double *solution = solver->getColSolution(); - //int numberRows = solver->getNumRows(); - //double direction = solver->getObjSense(); - //int iRow,iColumn; -#endif - - // Row copy - CoinPackedMatrix matrixByRow(*solver->getMatrixByRow()); - //const double * elementByRow = matrixByRow.getElements(); - //const int * column = matrixByRow.getIndices(); - //const CoinBigIndex * rowStart = matrixByRow.getVectorStarts(); - const int *rowLength = matrixByRow.getVectorLengths(); - - // Column copy - CoinPackedMatrix matrixByCol(*solver->getMatrixByCol()); - const double *element = matrixByCol.getElements(); - const int *row = matrixByCol.getIndices(); - const CoinBigIndex *columnStart = matrixByCol.getVectorStarts(); - const int *columnLength = matrixByCol.getVectorLengths(); - - const double *rowLower = solver->getRowLower(); - const double *rowUpper = solver->getRowUpper(); - OsiObject **objects = babModel->objects(); - int numberObjects = babModel->numberObjects(); - int numberColumns = solver->getNumCols(); - for (int iObj = 0; iObj < numberObjects; iObj++) { - CbcSOS *objSOS = dynamic_cast< CbcSOS * >(objects[iObj]); - if (objSOS) { - int n = objSOS->numberMembers(); - const int *which = objSOS->members(); -#if COIN_DEVELOP > 2 - const double *weight = objSOS->weights(); -#endif - int type = objSOS->sosType(); - // convexity row? - int iColumn; - iColumn = which[0]; - int j; - int convex = -1; - for (j = columnStart[iColumn]; j < columnStart[iColumn] + columnLength[iColumn]; j++) { - int iRow = row[j]; - double value = element[j]; - if (rowLower[iRow] == 1.0 && rowUpper[iRow] == 1.0 && value == 1.0) { - // possible - if (rowLength[iRow] == n) { - if (convex == -1) - convex = iRow; - else - convex = -2; - } - } - } - printf("set %d of type %d has %d members - possible convexity row %d\n", - iObj, type, n, convex); - for (int i = 0; i < n; i++) { - iColumn = which[i]; - // Column may have been added - if (iColumn < numberColumns) { - int convex2 = -1; - for (j = columnStart[iColumn]; j < columnStart[iColumn] + columnLength[iColumn]; j++) { - int iRow = row[j]; - if (iRow == convex) { - double value = element[j]; - if (value == 1.0) { - convex2 = iRow; - } - } - } - if (convex2 < 0 && convex >= 0) { - printf("odd convexity row\n"); - convex = -2; - } -#if COIN_DEVELOP > 2 - printf("col %d has weight %g and value %g, bounds %g %g\n", - iColumn, weight[i], solution[iColumn], columnLower[iColumn], - columnUpper[iColumn]); -#endif - } - } - } - } -#endif // COIN_DEVELOP -} - -static int dummyCallBack(CbcModel * /*model*/, int /*whereFrom*/) -{ - return 0; -} - -/* - Global parameters for command processing. - - These will need to be moved into an object of some sort in order to make - this set of calls thread-safe. -*/ - -// Alternative to environment -extern char *alternativeEnvironment; -extern int CbcOrClpEnvironmentIndex; - -int callCbc1(const char *input2, CbcModel &model, - int callBack(CbcModel *currentSolver, int whereFrom), - CbcSolverUsefulData ¶meterData); - -/* - Wrappers for CbcMain0, CbcMain1. The various forms of callCbc will eventually - resolve to a call to CbcMain0 followed by a call to callCbc1. -*/ -/* - Simplest calling form: supply just a string with the command options. The - wrapper creates an OsiClpSolverInterface and calls the next wrapper. -*/ -int callCbc(const std::string input2) -{ - char *input3 = CoinStrdup(input2.c_str()); - OsiClpSolverInterface solver1; - int returnCode = callCbc(input3, solver1); - free(input3); - return returnCode; -} - -int callCbc(const char *input2) -{ - { - OsiClpSolverInterface solver1; - return callCbc(input2, solver1); - } -} - -/* - Second calling form: supply the command line and an OsiClpSolverInterface. - the wrapper will create a CbcModel and call the next wrapper. -*/ - -int callCbc(const std::string input2, OsiClpSolverInterface &solver1) -{ - char *input3 = CoinStrdup(input2.c_str()); - int returnCode = callCbc(input3, solver1); - free(input3); - return returnCode; -} - -int callCbc(const char *input2, OsiClpSolverInterface &solver1) -{ - CbcModel model(solver1); - return callCbc(input2, model); -} - -/* - Third calling form: supply the command line and a CbcModel. This wrapper will - actually call CbcMain0 and then call the next set of wrappers (callCbc1) to - handle the call to CbcMain1. -*/ -int callCbc(const char *input2, CbcModel &babSolver) -{ - CbcSolverUsefulData data; -#ifndef CBC_NO_INTERRUPT - data.useSignalHandler_ = true; -#endif -#ifndef CBC_NO_PRINTING - data.noPrinting_ = false; -#endif - CbcMain0(babSolver, data); - return callCbc1(input2, babSolver, dummyCallBack, data); -} - -int callCbc(const std::string input2, CbcModel &babSolver) -{ - CbcSolverUsefulData cbcData; - cbcData.noPrinting_ = false; - char *input3 = CoinStrdup(input2.c_str()); - CbcMain0(babSolver, cbcData); - int returnCode = callCbc1(input3, babSolver, dummyCallBack, cbcData); - free(input3); - return returnCode; -} - -/* - Various overloads of callCbc1. The first pair accepts just a CbcModel and - supplements it with a dummy callback routine. The second pair allows the - user to supply a callback. See CbcMain1 for further explanation of the - callback. The various overloads of callCbc1 resolve to the final version, - which breaks the string into individual parameter strings (i.e., creates - something that looks like a standard argv vector). -*/ - -// Disabling non thread safe overloads -/* - int callCbc1(const std::string input2, CbcModel & babSolver) - { - char * input3 = CoinStrdup(input2.c_str()); - int returnCode = callCbc1(input3, babSolver); - free(input3); - return returnCode; - } - - int callCbc1(const char * input2, CbcModel & model) - { - return callCbc1(input2, model, dummyCallBack); - } - - int callCbc1(const std::string input2, CbcModel & babSolver, - int callBack(CbcModel * currentSolver, int whereFrom)) - { - char * input3 = CoinStrdup(input2.c_str()); - int returnCode = callCbc1(input3, babSolver, callBack); - free(input3); - return returnCode; - } - */ -int callCbc1(const char *input2, CbcModel &model, - int callBack(CbcModel *currentSolver, int whereFrom), - CbcSolverUsefulData ¶meterData) -{ - char *input = CoinStrdup(input2 ? input2 : ""); - size_t length = strlen(input); - bool blank = input[0] == ' '; - int n = blank ? 0 : 1; - for (size_t i = 0; i < length; i++) { - if (blank) { - // look for next non blank - if (input[i] == ' ') { - continue; - } else { - n++; - blank = false; - } - } else { - // look for next blank - if (input[i] != ' ') { - continue; - } else { - blank = true; - } - } - } - char **argv = new char *[n + 2]; - argv[0] = CoinStrdup("cbc"); - size_t i = 0; - while (input[i] == ' ') - i++; - for (int j = 0; j < n; j++) { - size_t saveI = i; - for (; i < length; i++) { - // look for next blank - if (input[i] != ' ') { - continue; - } else { - break; - } - } - input[i++] = '\0'; - argv[j + 1] = CoinStrdup(input + saveI); - while (input[i] == ' ') - i++; - } - argv[n + 1] = CoinStrdup("-quit"); - free(input); - currentBranchModel = NULL; - setCbcOrClpReadMode(1); - setCbcOrClpReadCommand(stdin); - int returnCode = CbcMain1(n + 2, const_cast< const char ** >(argv), - model, callBack, parameterData); - for (int k = 0; k < n + 2; k++) - free(argv[k]); - delete[] argv; - return returnCode; + for (i = 0; i < numberUserFunctions_; i++) + temp[i] = userFunction_[i]; + delete[] userFunction_; + userFunction_ = temp; + userFunction_[numberUserFunctions_++] = function->clone(); + delete[] statusUserFunction_; + statusUserFunction_ = NULL; } -int callCbc1(const char *input2, CbcModel &model, - int callBack(CbcModel *currentSolver, int whereFrom)) -{ - CbcSolverUsefulData data; - // allow interrupts and printing -#ifndef CBC_NO_INTERRUPT - data.useSignalHandler_ = true; -#endif -#ifndef CBC_NO_PRINTING - data.noPrinting_ = false; -#endif - return callCbc1(input2, model, callBack, data); +//########################################################################### +//########################################################################### + +// Set user call back +void CbcSolver::setUserCallBack(CbcStopNow *function) { + delete callBack_; + callBack_ = function->clone(); } -CglPreProcess *cbcPreProcessPointer = NULL; +//########################################################################### +//########################################################################### -int CbcClpUnitTest(const CbcModel &saveModel, - const std::string &dirMiplib, int testSwitch, - const double *stuff, int argc, const char ** argv, - int callBack(CbcModel *currentSolver, int whereFrom), - CbcSolverUsefulData ¶meterData); +// Copy of model on initial load (will contain output solutions) +void CbcSolver::setOriginalSolver(OsiClpSolverInterface *originalSolver) { + delete originalSolver_; + OsiSolverInterface *temp = originalSolver->clone(); + originalSolver_ = dynamic_cast(temp); + assert(originalSolver_); +} -//#define CBC_THREAD_SAFE -#ifdef CBC_THREAD_SAFE -// Copies of some input decoding +//########################################################################### +//########################################################################### -static std::string -CoinReadGetCommand(int &whichArgument, int argc, const char *argv[]) -{ - std::string field; - if (whichArgument < argc) - field = argv[whichArgument++]; - else - field = "quit"; - if (field[0] == '-') - field = field.substr(1); - return field; -} -static std::string -CoinReadGetString(int &whichArgument, int argc, const char *argv[]) -{ - std::string field; - if (whichArgument < argc) - field = argv[whichArgument++]; - else - field = ""; - return field; -} -// valid 0 - okay, 1 bad, 2 not there -static int -CoinReadGetIntField(int &whichArgument, int argc, const char *argv[], int *valid) -{ - std::string field; - if (whichArgument < argc) - field = argv[whichArgument++]; - else - field = "0"; - long int value = 0; - const char *start = field.c_str(); - char *endPointer = NULL; - // check valid - value = strtol(start, &endPointer, 10); - if (*endPointer == '\0') { - *valid = 0; - } else { - *valid = 1; - std::cout << "String of " << field; - } - return static_cast< int >(value); -} -static double -CoinReadGetDoubleField(int &whichArgument, int argc, const char *argv[], int *valid) -{ - std::string field; - if (whichArgument < argc) - field = argv[whichArgument++]; - else - field = "0.0"; - double value = 0.0; - const char *start = field.c_str(); - char *endPointer = NULL; - // check valid - value = strtod(start, &endPointer); - if (*endPointer == '\0') { - *valid = 0; - } else { - *valid = 1; - std::cout << "String of " << field; - } - return value; -} -// Redefine all -#define CoinReadGetCommand(x, y) CoinReadGetCommand(whichArgument, x, y) -#define CoinReadGetString(x, y) CoinReadGetString(whichArgument, x, y) -#define CoinReadGetIntField(x, y, z) CoinReadGetIntField(whichArgument, x, y, z) -#define CoinReadGetDoubleField(x, y, z) CoinReadGetDoubleField(whichArgument, x, y, z) -#endif -// Default Constructor -CbcSolverUsefulData::CbcSolverUsefulData() -{ - totalTime_ = 0.0; - noPrinting_ = true; - printWelcome_ = true; - useSignalHandler_ = false; - establishParams(parameters_); +// Copy of model on initial load +void CbcSolver::setOriginalCoinModel(CoinModel *originalCoinModel) { + delete originalCoinModel_; + originalCoinModel_ = new CoinModel(*originalCoinModel); } -/* Copy constructor . - */ -CbcSolverUsefulData::CbcSolverUsefulData(const CbcSolverUsefulData &rhs) -{ - totalTime_ = rhs.totalTime_; - noPrinting_ = rhs.noPrinting_; - useSignalHandler_ = rhs.useSignalHandler_; - this->parameters_ = rhs.parameters_; -} +//########################################################################### +//########################################################################### -// Assignment operator -CbcSolverUsefulData &CbcSolverUsefulData::operator=(const CbcSolverUsefulData &rhs) -{ - if (this != &rhs) { - totalTime_ = rhs.totalTime_; - noPrinting_ = rhs.noPrinting_; - useSignalHandler_ = rhs.useSignalHandler_; - this->parameters_ = rhs.parameters_; - } - return *this; +// Add cut generator +void CbcSolver::addCutGenerator(CglCutGenerator *generator) { + CglCutGenerator **temp = new CglCutGenerator *[numberCutGenerators_ + 1]; + int i; + for (i = 0; i < numberCutGenerators_; i++) + temp[i] = cutGenerator_[i]; + delete[] cutGenerator_; + cutGenerator_ = temp; + cutGenerator_[numberCutGenerators_++] = generator->clone(); } -// Destructor -CbcSolverUsefulData::~CbcSolverUsefulData() -{ -} +//########################################################################### +//########################################################################### -static bool ends_with(std::string const &value, std::string const &ending) -{ +//TODO Should we replace with the STL version +static bool ends_with(std::string const &value, std::string const &ending) { if (ending.size() > value.size()) return false; return std::equal(ending.rbegin(), ending.rend(), value.rbegin()); } -static void printGeneralMessage(CbcModel &model, const char *message); -// Version of CbcMain1 without callBack -int CbcMain1(int argc, const char *argv[], - CbcModel &model, - CbcSolverUsefulData ¶meterData) -{ - return CbcMain1(argc,argv,model,dummyCallBack,parameterData); + +//########################################################################### +// Wrappers for CbcMain0, CbcMain1. The various forms of callCbc will +// eventually resolve to a call to CbcMain0 followed by a call to callCbc1. +//########################################################################### + +//########################################################################### +// This is the function for setting things up, default parameters, etc. +//########################################################################### + +void CbcMain0(CbcModel &model, CbcParameters ¶meters) { +#if defined(HAVE_SIGNAL_H) && defined(HAVE_EXECINFO_H) + signal(SIGSEGV, CbcCrashHandler); + signal(SIGABRT, CbcCrashHandler); + signal(SIGFPE, CbcCrashHandler); + +#endif + + ClpParameters &clpParameters = parameters.clpParameters(); + +#ifndef CBC_OTHER_SOLVER + OsiClpSolverInterface *originalSolver = + dynamic_cast(model.solver()); +#elif CBC_OTHER_SOLVER == 1 + OsiCpxSolverInterface *originalSolver = + dynamic_cast(model.solver()); + // Dummy solvers + OsiClpSolverInterface dummySolver; + ClpSimplex *lpSolver = dummySolver.getModelPtr(); + OsiCpxSolverInterface *clpSolver = originalSolver; +#endif + assert(originalSolver); + CoinMessageHandler *generalMessageHandler = originalSolver->messageHandler(); + generalMessageHandler->setPrefix(true); +#ifndef CBC_OTHER_SOLVER + OsiSolverInterface *solver = model.solver(); + OsiClpSolverInterface *clpSolver = + dynamic_cast(solver); + ClpSimplex *lpSolver = clpSolver->getModelPtr(); + lpSolver->setPerturbation(50); + lpSolver->messageHandler()->setPrefix(false); + clpParameters.setModel(lpSolver); +#endif + // establishParams(numberParameters, parameters) ; + int doIdiot = -1; + int outputFormat = 2; + int substitution = 3; + int dualize = 3; + int preSolve = 5; + int doSprint = -1; + int testOsiParameters = -1; + clpParameters[ClpParam::DUALBOUND]->setVal(lpSolver->dualBound()); + clpParameters[ClpParam::DUALTOLERANCE]->setVal(lpSolver->dualTolerance()); + clpParameters[ClpParam::IDIOT]->setVal(doIdiot); + clpParameters[ClpParam::PRESOLVETOLERANCE]->setVal(1.0e-8); + clpParameters[ClpParam::MAXFACTOR]->setVal(lpSolver->factorizationFrequency()); + clpParameters[ClpParam::MAXITERATION]->setVal(lpSolver->maximumIterations()); + clpParameters[ClpParam::PRESOLVEPASS]->setVal(preSolve); + clpParameters[ClpParam::PERTVALUE]->setVal(lpSolver->perturbation()); + clpParameters[ClpParam::PRIMALTOLERANCE]->setVal(lpSolver->primalTolerance()); + clpParameters[ClpParam::PRIMALWEIGHT]->setVal(lpSolver->infeasibilityCost()); + clpParameters[ClpParam::SPRINT]->setVal(doSprint); + clpParameters[ClpParam::SUBSTITUTION]->setVal(substitution); + clpParameters[ClpParam::DUALIZE]->setVal(dualize); + parameters[CbcParam::OUTPUTFORMAT]->setVal(outputFormat); + parameters[CbcParam::LOGLEVEL]->setVal(1); + parameters[CbcParam::LPLOGLEVEL]->setVal(1); + clpParameters[ClpParam::LOGLEVEL]->setType(CoinParam::paramInt); // as can be set + clpSolver->messageHandler()->setLogLevel(1); + lpSolver->setLogLevel(1); + parameters[CbcParam::TIMELIMIT]->setVal(1.0e8); + parameters[CbcParam::TESTOSI]->setVal(testOsiParameters); + parameters[CbcParam::FPUMPTUNE]->setVal(1003); + initialPumpTune = 1003; +#ifdef CBC_THREAD + parameters[CbcParam::THREADS]->setVal(0); +#endif + // Set up likely cut generators and defaults + parameters[CbcParam::CLIQUECUTS]->setVal("ifmove"); + parameters[CbcParam::ODDWHEELCUTS]->setVal("ifmove"); + parameters[CbcParam::CLQSTRENGTHENING]->setVal("after"); + parameters[CbcParam::USECGRAPH]->setVal("on"); + parameters[CbcParam::BKPIVOTINGSTRATEGY]->setVal(3); + parameters[CbcParam::BKMAXCALLS]->setVal(1000); + parameters[CbcParam::BKCLQEXTMETHOD]->setVal(4); + parameters[CbcParam::ODDWEXTMETHOD]->setVal(2); + parameters[CbcParam::PREPROCESS]->setVal("sos"); + parameters[CbcParam::MIPOPTIONS]->setVal(1057); + parameters[CbcParam::CUTPASSINTREE]->setVal(10); + parameters[CbcParam::MOREMIPOPTIONS]->setVal(-1); + parameters[CbcParam::MAXHOTITS]->setVal(100); + parameters[CbcParam::CUTSTRATEGY]->setVal("on"); + parameters[CbcParam::HEURISTICSTRATEGY]->setVal("on"); + parameters[CbcParam::NODESTRATEGY]->setVal("fewest"); + parameters[CbcParam::GOMORYCUTS]->setVal("ifmove"); + parameters[CbcParam::PROBINGCUTS]->setVal("ifmove"); + parameters[CbcParam::KNAPSACKCUTS]->setVal("ifmove"); + parameters[CbcParam::ZEROHALFCUTS]->setVal("ifmove"); + parameters[CbcParam::REDSPLITCUTS]->setVal("off"); + parameters[CbcParam::REDSPLIT2CUTS]->setVal("off"); + parameters[CbcParam::GMICUTS]->setVal("off"); + parameters[CbcParam::MIRCUTS]->setVal("ifmove"); + parameters[CbcParam::FLOWCUTS]->setVal("ifmove"); + parameters[CbcParam::TWOMIRCUTS]->setVal("ifmove"); + parameters[CbcParam::LANDPCUTS]->setVal("off"); + parameters[CbcParam::RESIDCAPCUTS]->setVal("off"); + parameters[CbcParam::ROUNDING]->setVal("on"); + parameters[CbcParam::FPUMP]->setVal("on"); + parameters[CbcParam::GREEDY]->setVal("on"); + parameters[CbcParam::COMBINE]->setVal("off"); + parameters[CbcParam::CROSSOVER]->setVal("off"); +#ifdef CBC_HAS_NAUTY + parameters[CbcParam::ORBITAL]->setVal("on"); +#endif + //parameters[CbcParam::PIVOTANDCOMPLEMENT]->setVal("off"); + parameters[CbcParam::PIVOTANDFIX]->setVal("off"); + parameters[CbcParam::RANDROUND]->setVal("off"); + parameters[CbcParam::NAIVE]->setVal("off"); + parameters[CbcParam::RINS]->setVal("off"); + parameters[CbcParam::DINS]->setVal("off"); + parameters[CbcParam::RENS]->setVal("off"); + parameters[CbcParam::LOCALTREE]->setVal("off"); + parameters[CbcParam::BRANCHPRIORITY]->setVal("off"); + + model.messageHandler()->setLogLevel(1); + model.setNumberBeforeTrust(10); + parameters[CbcParam::NUMBERBEFORE]->setVal(10); + parameters[CbcParam::MAXNODES]->setVal(model.getMaximumNodes()); + model.setNumberStrong(5); + parameters[CbcParam::STRONGBRANCHING]->setVal(model.numberStrong()); + parameters[CbcParam::INFEASIBILITYWEIGHT]->setVal(model.getDblParam(CbcModel::CbcInfeasibilityWeight)); + parameters[CbcParam::INTEGERTOLERANCE]->setVal(model.getDblParam(CbcModel::CbcIntegerTolerance)); + parameters[CbcParam::INCREMENT]->setVal(model.getDblParam(CbcModel::CbcCutoffIncrement)); } -/* - Meaning of whereFrom: - 1 after initial solve by dualsimplex etc - 2 after preprocessing - 3 just before branchAndBound (so user can override) - 4 just after branchAndBound (before postprocessing) - 5 after postprocessing - 6 after a user called heuristic phase -*/ -int CbcMain1(int argc, const char *argv[], - CbcModel &model, - int callBack(CbcModel *currentSolver, int whereFrom), - CbcSolverUsefulData ¶meterData) -{ - std::vector< CbcOrClpParam > parameters_(parameterData.parameters_); - double totalTime = parameterData.totalTime_; - bool noPrinting = parameterData.noPrinting_; - bool useSignalHandler = parameterData.useSignalHandler_; + +//########################################################################### +//########################################################################### + +//########################################################################### +// CbcMain 1 +// Meaning of whereFrom: +// 1 after initial solve by dualsimplex etc +// 2 after preprocessing +// 3 just before branchAndBound (so user can override) +// 4 just after branchAndBound (before postprocessing) +// 5 after postprocessing +// 6 after a user called heuristic phase +//########################################################################### + +int CbcMain1(std::deque inputQueue, CbcModel &model, + CbcParameters ¶meters, + int callBack(CbcModel *currentSolver, int whereFrom), + ampl_info *info) { + + ClpParameters &clpParameters = parameters.clpParameters(); + + std::ostringstream buffer; + std::string field, message, fileName; + FILE *fp; + + double totalTime = parameters.getTotalTime(); + bool useSignalHandler = parameters.useSignalHandler(); CbcModel &model_ = model; CglPreProcess *preProcessPointer = NULL; -#ifdef CBC_THREAD_SAFE - // Initialize argument - int whichArgument = 1; -#endif + OsiSolverInterface *saveSolver = NULL; + CglPreProcess process; + // Save a copy of input for unit testing + // Could also be used for friendly error messages? + std::deque saveInputQueue = inputQueue; // Meaning 0 - start at very beginning // 1 start at beginning of preprocessing // 2 start at beginning of branch and bound @@ -1343,8 +1103,11 @@ int CbcMain1(int argc, const char *argv[], model_.setDblParam(CbcModel::CbcStartSeconds, CoinCpuTime()); #endif CbcModel *babModel_ = NULL; +#ifdef COINUTILS_HAS_GLPK + glp_tran *coin_glp_tran = NULL; + glp_prob *coin_glp_prob = NULL; +#endif int returnMode = 1; - setCbcOrClpReadMode(1); int statusUserFunction_[1]; int numberUserFunctions_ = 1; // to allow for ampl // Statistics @@ -1363,8 +1126,8 @@ int CbcMain1(int argc, const char *argv[], int currentBestSolution = 0; memset(statusUserFunction_, 0, numberUserFunctions_ * sizeof(int)); /* Note - This is meant as a stand-alone executable to do as much of coin as possible. - It should only have one solver known to it. + This is meant as a stand-alone executable to do as much of coin as + possible. It should only have one solver known to it. */ CoinMessageHandler *generalMessageHandler = model_.messageHandler(); generalMessageHandler->setPrefix(false); @@ -1378,48 +1141,39 @@ int CbcMain1(int argc, const char *argv[], typedef struct {lotStruct * lotsize;int numberLotSizing;} lotStruct2; lotStruct2 passSCtopreprocess; #ifndef CBC_OTHER_SOLVER - OsiClpSolverInterface *originalSolver = dynamic_cast< OsiClpSolverInterface * >(model_.solver()); + OsiClpSolverInterface *originalSolver = + dynamic_cast(model_.solver()); assert(originalSolver); // Move handler across if not default - if (!originalSolver->defaultHandler() && originalSolver->getModelPtr()->defaultHandler()) - originalSolver->getModelPtr()->passInMessageHandler(originalSolver->messageHandler()); + if (!originalSolver->defaultHandler() && + originalSolver->getModelPtr()->defaultHandler()) + originalSolver->getModelPtr()->passInMessageHandler( + originalSolver->messageHandler()); CoinMessages generalMessages = originalSolver->getModelPtr()->messages(); - char generalPrint[10000]; if (originalSolver->getModelPtr()->logLevel() == 0) { - noPrinting = true; - parameterData.printWelcome_ = false; + generalMessageHandler->setLogLevel(0); + parameters.disableWelcomePrinting(); } #elif CBC_OTHER_SOLVER == 1 - OsiCpxSolverInterface *originalSolver = dynamic_cast< OsiCpxSolverInterface * >(model_.solver()); + /* + The only other solver that's ever been used is cplex, and the use is + limited -- do the root with clp and all the cbc smarts, then give the + problem over to cplex to finish. Although the defines can be read in some + places to allow other options, nothing's been tested and success is + unlikely. + */ + OsiCpxSolverInterface *originalSolver = + dynamic_cast(model_.solver()); assert(originalSolver); OsiClpSolverInterface dummySolver; OsiCpxSolverInterface *clpSolver = originalSolver; CoinMessages generalMessages = dummySolver.getModelPtr()->messages(); - char generalPrint[10000]; - noPrinting = true; + parameters.enablePrinting(); #endif - bool noPrinting_ = noPrinting; // Say not in integer int integerStatus = -1; // Say no resolve after cuts model_.setResolveAfterTakeOffCuts(false); - // see if log in list - for (int i = 1; i < argc; i++) { - if (!strncmp(argv[i], "log", 3)) { - const char *equals = strchr(argv[i], '='); - if (equals && atoi(equals + 1) != 0) - noPrinting_ = false; - else - noPrinting_ = true; - break; - } else if (!strncmp(argv[i], "-log", 4) && i < argc - 1) { - if (atoi(argv[i + 1]) != 0) - noPrinting_ = false; - else - noPrinting_ = true; - break; - } - } double time0; double time0Elapsed = CoinGetTimeOfDay(); { @@ -1429,7 +1183,7 @@ int CbcMain1(int argc, const char *argv[], bool goodModel = (originalSolver->getNumCols()) ? true : false; // register signal handler - //CoinSighandler_t saveSignal=signal(SIGINT,signal_handler); + // CoinSighandler_t saveSignal=signal(SIGINT,signal_handler); #if CBC_QUIET < 2 if (useSignalHandler) signal(SIGINT, signal_handler); @@ -1442,12 +1196,11 @@ int CbcMain1(int argc, const char *argv[], // 0 normal, 1 from ampl or MIQP etc (2 allows cuts) int complicatedInteger = 0; OsiSolverInterface *solver = model_.solver(); - if (noPrinting_) - setCbcOrClpPrinting(false); #ifndef CBC_OTHER_SOLVER - OsiClpSolverInterface *clpSolver = dynamic_cast< OsiClpSolverInterface * >(solver); + OsiClpSolverInterface *clpSolver = + dynamic_cast(solver); ClpSimplex *lpSolver = clpSolver->getModelPtr(); - if (noPrinting_) { + if (parameters.noPrinting()) { lpSolver->setLogLevel(0); } #else @@ -1460,8 +1213,8 @@ int CbcMain1(int argc, const char *argv[], double *pseudoUp = NULL; double *solutionIn = NULL; int *prioritiesIn = NULL; - std::vector< std::pair< std::string, double > > mipStart; - std::vector< std::pair< std::string, double > > mipStartBefore; + std::vector > mipStart; + std::vector > mipStartBefore; std::string mipStartFile = ""; int numberSOS = 0; int *sosStart = NULL; @@ -1478,200 +1231,6 @@ int CbcMain1(int argc, const char *argv[], int *knapsackStart = NULL; int *knapsackRow = NULL; int numberKnapsack = 0; - ampl_info info; - { - memset(&info, 0, sizeof(info)); - if (argc > 2 && !strcmp(argv[2], "-AMPL")) { - statusUserFunction_[0] = 1; - // see if log in list - noPrinting_ = true; - for (int i = 1; i < argc; i++) { - if (!strncmp(argv[i], "log", 3)) { - const char *equals = strchr(argv[i], '='); - if (equals && atoi(equals + 1) > 0) { - noPrinting_ = false; - info.logLevel = atoi(equals + 1); - int log = whichParam(CLP_PARAM_INT_LOGLEVEL, parameters_); - parameters_[log].setIntValue(info.logLevel); - // mark so won't be overWritten - info.numberRows = -1234567; - break; - } - } - } - - union { - void *voidModel; - CoinModel *model; - } coinModelStart; - coinModelStart.model = NULL; - int returnCode = readAmpl(&info, argc, const_cast< char ** >(argv), &coinModelStart.voidModel, "cbc"); - coinModel = coinModelStart.model; - if (returnCode) - return returnCode; - if (info.numberSos) { - numberSOS = info.numberSos; - sosStart = info.sosStart; - sosIndices = info.sosIndices; - sosType = info.sosType; - sosReference = info.sosReference; - sosPriority = info.sosPriority; - } - setCbcOrClpReadMode(2); // so will start with parameters - // see if log in list (including environment) - for (int i = 1; i < info.numberArguments; i++) { - if (!strcmp(info.arguments[i], "log")) { - if (i < info.numberArguments - 1 && atoi(info.arguments[i + 1]) > 0) - noPrinting_ = false; - break; - } - } - if (noPrinting_) { - model_.messageHandler()->setLogLevel(0); - setCbcOrClpPrinting(false); - } - if (!noPrinting_) - printf("%d rows, %d columns and %d elements\n", - info.numberRows, info.numberColumns, info.numberElements); -#ifdef COIN_HAS_LINK - if (!coinModel) { -#endif - solver->loadProblem(info.numberColumns, info.numberRows, - reinterpret_cast< const CoinBigIndex * >(info.starts), - info.rows, info.elements, - info.columnLower, info.columnUpper, info.objective, - info.rowLower, info.rowUpper); - // take off cuts if ampl wants that - if (info.cut && 0) { - printf("AMPL CUTS OFF until global cuts fixed\n"); - info.cut = NULL; - } - if (info.cut) { - int numberRows = info.numberRows; - int *whichRow = new int[numberRows]; - // Row copy - const CoinPackedMatrix *matrixByRow = solver->getMatrixByRow(); - const double *elementByRow = matrixByRow->getElements(); - const int *column = matrixByRow->getIndices(); - const CoinBigIndex *rowStart = matrixByRow->getVectorStarts(); - const int *rowLength = matrixByRow->getVectorLengths(); - - const double *rowLower = solver->getRowLower(); - const double *rowUpper = solver->getRowUpper(); - int nDelete = 0; - for (int iRow = 0; iRow < numberRows; iRow++) { - if (info.cut[iRow]) { - whichRow[nDelete++] = iRow; - int start = rowStart[iRow]; - storedAmpl.addCut(rowLower[iRow], rowUpper[iRow], - rowLength[iRow], column + start, elementByRow + start); - } - } - solver->deleteRows(nDelete, whichRow); - delete[] whichRow; - } -#ifdef COIN_HAS_LINK - } else { -#ifndef CBC_OTHER_SOLVER - // save - saveCoinModel = *coinModel; - // load from coin model - OsiSolverLink solver1; - OsiSolverInterface *solver2 = solver1.clone(); - model_.assignSolver(solver2, false); - OsiSolverLink *si = dynamic_cast< OsiSolverLink * >(model_.solver()); - assert(si != NULL); - si->setDefaultMeshSize(0.001); - // need some relative granularity - si->setDefaultBound(100.0); - double dextra3 = parameters_[whichParam(CBC_PARAM_DBL_DEXTRA3, parameters_)].doubleValue(); - if (dextra3) - si->setDefaultMeshSize(dextra3); - si->setDefaultBound(100000.0); - si->setIntegerPriority(1000); - si->setBiLinearPriority(10000); - CoinModel *model2 = reinterpret_cast< CoinModel * >(coinModel); - int logLevel = parameters_[whichParam(CLP_PARAM_INT_LOGLEVEL, parameters_)].intValue(); - si->load(*model2, true, logLevel); - // redo - solver = model_.solver(); - clpSolver = dynamic_cast< OsiClpSolverInterface * >(solver); - lpSolver = clpSolver->getModelPtr(); - clpSolver->messageHandler()->setLogLevel(0); - testOsiParameters = 0; - parameters_[whichParam(CBC_PARAM_INT_TESTOSI, parameters_)].setIntValue(0); - complicatedInteger = 1; - if (info.cut) { - printf("Sorry - can't do cuts with LOS as ruins delicate row order\n"); - abort(); - int numberRows = info.numberRows; - int *whichRow = new int[numberRows]; - // Row copy - const CoinPackedMatrix *matrixByRow = solver->getMatrixByRow(); - const double *elementByRow = matrixByRow->getElements(); - const int *column = matrixByRow->getIndices(); - const CoinBigIndex *rowStart = matrixByRow->getVectorStarts(); - const int *rowLength = matrixByRow->getVectorLengths(); - - const double *rowLower = solver->getRowLower(); - const double *rowUpper = solver->getRowUpper(); - int nDelete = 0; - for (int iRow = 0; iRow < numberRows; iRow++) { - if (info.cut[iRow]) { - whichRow[nDelete++] = iRow; - int start = rowStart[iRow]; - storedAmpl.addCut(rowLower[iRow], rowUpper[iRow], - rowLength[iRow], column + start, elementByRow + start); - } - } - solver->deleteRows(nDelete, whichRow); - // and special matrix - si->cleanMatrix()->deleteRows(nDelete, whichRow); - delete[] whichRow; - } -#endif - } -#endif - // If we had a solution use it - if (info.primalSolution) { - solver->setColSolution(info.primalSolution); - } - // status - if (info.rowStatus) { - unsigned char *statusArray = lpSolver->statusArray(); - int i; - for (i = 0; i < info.numberColumns; i++) - statusArray[i] = static_cast< unsigned char >(info.columnStatus[i]); - statusArray += info.numberColumns; - for (i = 0; i < info.numberRows; i++) - statusArray[i] = static_cast< unsigned char >(info.rowStatus[i]); - CoinWarmStartBasis *basis = lpSolver->getBasis(); - solver->setWarmStart(basis); - delete basis; - } - freeArrays1(&info); - // modify objective if necessary - solver->setObjSense(info.direction); - solver->setDblParam(OsiObjOffset, -info.offset); - if (info.offset) { - sprintf(generalPrint, "Ampl objective offset is %g", - info.offset); - generalMessageHandler->message(CLP_GENERAL, generalMessages) - << generalPrint - << CoinMessageEol; - } - // Set integer variables (unless nonlinear when set) - if (!info.nonLinear) { - for (int i = info.numberColumns - info.numberIntegers; - i < info.numberColumns; i++) - solver->setInteger(i); - } - goodModel = true; - // change argc etc - argc = info.numberArguments; - argv = const_cast< const char ** >(info.arguments); - } - } // default action on import int allowImportErrors = 0; int keepImportNames = 1; @@ -1688,6 +1247,93 @@ int CbcMain1(int argc, const char *argv[], int doVector = 0; int doSprint = -1; int doScaling = 4; + + if (info) { + parameters[ClpParam::LOGLEVEL]->setVal(info->logLevel); + goodModel = true; + // FIXME Do we really need this? Seems to just mean that AMPL is being used + statusUserFunction_[0] = 1; + if (info->numberSos) { + numberSOS = info->numberSos; + sosStart = info->sosStart; + sosIndices = info->sosIndices; + sosType = info->sosType; + sosReference = info->sosReference; + sosPriority = info->sosPriority; + } + if (info->cut) { + int numberRows = info->numberRows; + int *whichRow = new int[numberRows]; + // Row copy + const CoinPackedMatrix *matrixByRow = solver->getMatrixByRow(); + const double *elementByRow = matrixByRow->getElements(); + const int *column = matrixByRow->getIndices(); + const CoinBigIndex *rowStart = matrixByRow->getVectorStarts(); + const int *rowLength = matrixByRow->getVectorLengths(); + + const double *rowLower = solver->getRowLower(); + const double *rowUpper = solver->getRowUpper(); + int nDelete = 0; + for (int iRow = 0; iRow < numberRows; iRow++) { + if (info->cut[iRow]) { + whichRow[nDelete++] = iRow; + int start = rowStart[iRow]; + storedAmpl.addCut(rowLower[iRow], rowUpper[iRow], + rowLength[iRow], column + start, + elementByRow + start); + } + } + solver->deleteRows(nDelete, whichRow); + delete[] whichRow; + } + solver->loadProblem( + info->numberColumns, info->numberRows, + reinterpret_cast(info->starts), info->rows, + info->elements, info->columnLower, info->columnUpper, info->objective, + info->rowLower, info->rowUpper); + // take off cuts if ampl wants that + if (info->cut && 0) { + printf("AMPL CUTS OFF until global cuts fixed\n"); + info->cut = NULL; + } + + //FIXME A big block was deleted which seemed as though it should never be entered. + // Check that. + + // If we had a solution use it + if (info->primalSolution) { + solver->setColSolution(info->primalSolution); + } + // status + if (info->rowStatus) { + unsigned char *statusArray = lpSolver->statusArray(); + int i; + for (i = 0; i < info->numberColumns; i++) + statusArray[i] = static_cast(info->columnStatus[i]); + statusArray += info->numberColumns; + for (i = 0; i < info->numberRows; i++) + statusArray[i] = static_cast(info->rowStatus[i]); + CoinWarmStartBasis *basis = lpSolver->getBasis(); + solver->setWarmStart(basis); + delete basis; + } + freeArrays1(info); + // modify objective if necessary + solver->setObjSense(info->direction); + solver->setDblParam(OsiObjOffset, -info->offset); + if (info->offset) { + buffer.str(""); + buffer << "Ampl objective offset is " << info->offset; + printGeneralMessage(model, buffer.str()); + } + // Set integer variables (unless nonlinear when set) + if (!info->nonLinear) { + for (int i = info->numberColumns - info->numberIntegers; + i < info->numberColumns; i++) + solver->setInteger(i); + } + } + // set reasonable defaults int preSolve = 5; int preProcess = 4; @@ -1699,38 +1345,9 @@ int CbcMain1(int argc, const char *argv[], double djFix = 1.0e100; double tightenFactor = 0.0; const char dirsep = CoinFindDirSeparator(); - std::string directory; - std::string dirSample; - std::string dirNetlib; - std::string dirMiplib; - if (dirsep == '/') { - directory = "./"; - dirSample = "../../Data/Sample/"; - dirNetlib = "../../Data/Netlib/"; - dirMiplib = "../../Data/miplib3/"; - } else { - directory = ".\\"; - dirSample = "..\\..\\..\\..\\Data\\Sample\\"; - dirNetlib = "..\\..\\..\\..\\Data\\Netlib\\"; - dirMiplib = "..\\..\\..\\..\\Data\\miplib3\\"; - } - std::string defaultDirectory = directory; - std::string importFile = ""; - std::string exportFile = "default.mps"; - std::string importBasisFile = ""; - std::string importPriorityFile = ""; - std::string debugFile = ""; - std::string printMask = ""; double *debugValues = NULL; int numberDebugValues = -1; int basisHasValues = 0; - std::string exportBasisFile = "default.bas"; - std::string saveFile = "default.prob"; - std::string restoreFile = "default.prob"; - std::string solutionFile = "stdout"; - std::string solutionSaveFile = "solution.file"; - int slog = whichParam(CLP_PARAM_INT_SOLVERLOGLEVEL, parameters_); - int log = whichParam(CLP_PARAM_INT_LOGLEVEL, parameters_); #ifndef CBC_OTHER_SOLVER double normalIncrement = model_.getCutoffIncrement(); ; @@ -1748,8 +1365,9 @@ int CbcMain1(int argc, const char *argv[], // try larger limit gomoryGen.setLimitAtRoot(1000); gomoryGen.setLimit(50); - // set default action (0=off,1=on,2=root) - int gomoryAction = 3; + // set default action (0=off,1=on,2=root,3=ifmove) + int gomoryMode = CbcParameters::CGIfMove; + assert (parameters[CbcParam::GOMORYCUTS]->modeVal()==gomoryMode); CglProbing probingGen; probingGen.setUsingObjective(1); @@ -1766,73 +1384,82 @@ int CbcMain1(int argc, const char *argv[], probingGen.setMaxElements(200); probingGen.setMaxElementsRoot(300); probingGen.setRowCuts(3); - // set default action (0=off,1=on,2=root) - int probingAction = 1; + // set default action (0=off,1=on,2=root,3=ifmove) + int probingMode = CbcParameters::CGIfMove; + assert (parameters[CbcParam::PROBINGCUTS]->modeVal()==probingMode); CglKnapsackCover knapsackGen; - //knapsackGen.switchOnExpensive(); - //knapsackGen.setMaxInKnapsack(100); - // set default action (0=off,1=on,2=root) - int knapsackAction = 3; + // knapsackGen.switchOnExpensive(); + // knapsackGen.setMaxInKnapsack(100); + // set default action (0=off,1=on,2=root,3=ifmove) + int knapsackMode = CbcParameters::CGIfMove; + assert (parameters[CbcParam::KNAPSACKCUTS]->modeVal()==knapsackMode); CglRedSplit redsplitGen; - //redsplitGen.setLimit(100); - // set default action (0=off,1=on,2=root) + // set default action (0=off,1=on,2=root,3=ifmove) // Off as seems to give some bad cuts - int redsplitAction = 0; + int redsplitMode = CbcParameters::CGOff; + assert (parameters[CbcParam::REDSPLITCUTS]->modeVal()==redsplitMode); CglRedSplit2 redsplit2Gen; - //redsplit2Gen.setLimit(100); - // set default action (0=off,1=on,2=root) + // redsplit2Gen.setLimit(100); + // set default action (0=off,1=on,2=root,3=ifmove) // Off - int redsplit2Action = 0; + int redsplit2Mode = CbcParameters::CGOff; + assert (parameters[CbcParam::REDSPLIT2CUTS]->modeVal()==redsplit2Mode); CglGMI GMIGen; - //GMIGen.setLimit(100); - // set default action (0=off,1=on,2=root) - // Off - int GMIAction = 0; + int GMIMode = parameters[CbcParam::GMICUTS]->modeVal(); - std::string cgraphAction = "on"; - std::string clqstrAction = "after"; + std::string cgraphMode = "on"; + std::string clqstrMode = "after"; CglBKClique bkCliqueGen; - int cliqueAction = 3, bkPivotingStrategy = 3, maxCallsBK = 1000, bkClqExtMethod = 4; + int bkPivotingStrategy = 3, maxCallsBK = 1000, bkClqExtMethod = 4; + int cliqueMode = parameters[CbcParam::CLIQUECUTS]->modeVal(); + int oldCliqueMode = cliqueMode; CglOddWheel oddWheelGen; - int oddWheelAction = 3, oddWExtMethod = 2; + int oddWheelMode = CbcParameters::CGIfMove, oddWExtMethod = 2; + assert (parameters[CbcParam::ODDWHEELCUTS]->modeVal()==oddWheelMode); // maxaggr,multiply,criterion(1-3) CglMixedIntegerRounding2 mixedGen(1, true, 1); - // set default action (0=off,1=on,2=root) - int mixedAction = 3; + // set default action (0=off,1=on,2=root,3=ifmove) + int mixedMode = CbcParameters::CGIfMove; + assert (parameters[CbcParam::MIRCUTS]->modeVal()==mixedMode); mixedGen.setDoPreproc(1); // safer (and better) CglFlowCover flowGen; - // set default action (0=off,1=on,2=root) - int flowAction = 3; + // set default action (0=off,1=on,2=root,3=ifmove) + int flowMode = CbcParameters::CGIfMove; + assert (parameters[CbcParam::FLOWCUTS]->modeVal()==flowMode); CglTwomir twomirGen; twomirGen.setMaxElements(250); - // set default action (0=off,1=on,2=root) - int twomirAction = 3; + // set default action (0=off,1=on,2=root,3=ifmove) + int twomirMode = CbcParameters::CGIfMove; + assert (parameters[CbcParam::TWOMIRCUTS]->modeVal()==twomirMode); #ifndef DEBUG_MALLOC CglLandP landpGen; landpGen.parameter().maximumCutLength = 2000; landpGen.validator().setMinViolation(1.0e-4); #endif - // set default action (0=off,1=on,2=root) - int landpAction = 0; + // set default action (0=off,1=on,2=root,3=ifmove) + int landpMode = CbcParameters::CGOff; + assert (parameters[CbcParam::LANDPCUTS]->modeVal()==landpMode); CglResidualCapacity residualCapacityGen; residualCapacityGen.setDoPreproc(1); // always preprocess - // set default action (0=off,1=on,2=root) - int residualCapacityAction = 0; + // set default action (0=off,1=on,2=root,3=ifmove) + int residualCapacityMode = CbcParameters::CGOff; + assert (parameters[CbcParam::RESIDCAPCUTS]->modeVal()==residualCapacityMode); CglZeroHalf zerohalfGen; - //zerohalfGen.switchOnExpensive(); - // set default action (0=off,1=on,2=root) - int zerohalfAction = 3; + // zerohalfGen.switchOnExpensive(); + // set default action (0=off,1=on,2=root,3=ifmove) + int zerohalfMode = CbcParameters::CGIfMove; + assert (parameters[CbcParam::ZEROHALFCUTS]->modeVal()==zerohalfMode); // Stored cuts - //bool storedCuts = false; + // bool storedCuts = false; int useCosts = 0; // don't use input solution @@ -1852,8 +1479,8 @@ int CbcMain1(int argc, const char *argv[], bool biLinearProblem = false; // For names int lengthName = 0; - std::vector< std::string > rowNames; - std::vector< std::string > columnNames; + std::vector rowNames; + std::vector columnNames; // Default strategy stuff { // try changing tolerance at root @@ -1862,169 +1489,273 @@ int CbcMain1(int argc, const char *argv[], gomoryGen.setAwayAtRoot(0.005); twomirGen.setAwayAtRoot(0.005); twomirGen.setAway(0.01); - //twomirGen.setMirScale(1,1); - //twomirGen.setTwomirScale(1,1); - //twomirGen.setAMax(2); + // twomirGen.setMirScale(1,1); + // twomirGen.setTwomirScale(1,1); + // twomirGen.setAMax(2); #else gomoryGen.setAwayAtRoot(0.01); twomirGen.setAwayAtRoot(0.01); twomirGen.setAway(0.01); #endif - int iParam; - iParam = whichParam(CBC_PARAM_INT_DIVEOPT, parameters_); - parameters_[iParam].setIntValue(2); - iParam = whichParam(CBC_PARAM_INT_FPUMPITS, parameters_); - parameters_[iParam].setIntValue(30); - iParam = whichParam(CBC_PARAM_INT_FPUMPTUNE, parameters_); - parameters_[iParam].setIntValue(1005043); + // TODO: See what's going on with these free-standing parameters initialPumpTune = 1005043; - iParam = whichParam(CLP_PARAM_INT_PROCESSTUNE, parameters_); - parameters_[iParam].setIntValue(6); tunePreProcess = 6; - iParam = whichParam(CBC_PARAM_STR_DIVINGC, parameters_); - parameters_[iParam].setCurrentOption("on"); - iParam = whichParam(CBC_PARAM_STR_RINS, parameters_); - parameters_[iParam].setCurrentOption("on"); - iParam = whichParam(CBC_PARAM_STR_PROBINGCUTS, parameters_); - parameters_[iParam].setCurrentOption("on"); - probingAction = 3; - //parameters_[iParam].setCurrentOption("forceOnStrong"); - //probingAction = 8; + probingMode = CbcParameters::CGIfMove; + parameters[CbcParam::DIVEOPT]->setVal(2); + parameters[CbcParam::FPUMPITS]->setVal(30); + parameters[CbcParam::FPUMPTUNE]->setVal(1005043); + parameters[CbcParam::PROCESSTUNE]->setVal(7); + parameters[CbcParam::DIVINGC]->setVal("on"); + parameters[CbcParam::RINS]->setVal("on"); + parameters[CbcParam::PROBINGCUTS]->setVal("ifmove"); + // parameters[iParam]->setVal("forceOnStrong"); + // probingMode = 8; } - std::string field; + + bool interactiveMode = false, canOpen; + + int status, iValue; + double dValue; + std::string prompt = "Cbc: "; + #if CBC_QUIET == 0 - if ((!noPrinting_) && (parameterData.printWelcome_)) { - sprintf(generalPrint, - "Welcome to the CBC MILP Solver \n"); - if (strcmp(CBC_VERSION, "trunk")) { - sprintf(generalPrint + strlen(generalPrint), - "Version: %s \n", CBC_VERSION); + if (parameters.printWelcome()) { + buffer.str(""); + buffer << "Welcome to the CBC MILP Solver" << std::endl; + if (strcmp(CBC_VERSION, "devel")) { + buffer << "Version: " << CBC_VERSION << std::endl; } else { - sprintf(generalPrint + strlen(generalPrint), - "Version: Trunk (unstable) \n"); + buffer << "Version: Devel (unstable)" << std::endl; } - sprintf(generalPrint + strlen(generalPrint), - "Build Date: %s \n", __DATE__); -#ifdef CBC_SVN_REV - sprintf(generalPrint + strlen(generalPrint), - "Revision Number: %d \n", CBC_SVN_REV); -#endif - generalMessageHandler->message(CLP_GENERAL, generalMessages) - << generalPrint - << CoinMessageEol; + buffer << "Build Date: " << __DATE__ << std::endl; + printGeneralMessage(model_, buffer.str()); // Print command line - if (argc > 1) { + if (!inputQueue.empty()) { bool foundStrategy = false; - sprintf(generalPrint, "command line - "); - for (int i = 0; i < argc; i++) { - if (!argv[i]) - break; - if (strstr(argv[i], "strat")) - foundStrategy = true; - sprintf(generalPrint + strlen(generalPrint), "%s ", argv[i]); + buffer.str(""); + buffer << "command line -"; + for (int i = 0; i < inputQueue.size(); i++) { + size_t found = inputQueue[i].find("strat"); + if (found != std::string::npos){ + foundStrategy = true; + } + buffer << " " << inputQueue[i]; } - if (!foundStrategy) - sprintf(generalPrint + strlen(generalPrint), "(default strategy 1)"); - generalMessageHandler->message(CLP_GENERAL, generalMessages) - << generalPrint - << CoinMessageEol; + if (!foundStrategy){ + buffer << " (default strategy 1)"; + } + printGeneralMessage(model_, buffer.str()); } } #endif + + // If no arguments, just go into interactive mode + if (!inputQueue.size()){ + interactiveMode = true; + // let's give the sucker a hint + std::cout + << "Cbc takes input from arguments ( - switches to stdin)" + << std::endl + << "Enter ? for list of commands or help" << std::endl; + } + while (1) { - // next command - field = CoinReadGetCommand(argc, argv); // Reset time time1 = CoinCpuTime(); time1Elapsed = CoinGetTimeOfDay(); - // adjust field if has odd trailing characters - char temp[200]; - strcpy(temp, field.c_str()); - int length = static_cast< int >(strlen(temp)); - for (int k = length - 1; k >= 0; k--) { - if (temp[k] < ' ') - length--; - else - break; - } - temp[length] = '\0'; - field = temp; + + field = CoinParamUtils::getNextField(inputQueue, interactiveMode, prompt); + // exit if null or similar if (!field.length()) { - if (numberGoodCommands == 1 && goodModel) { - // we just had file name - do branch and bound - field = "branch"; - } else if (!numberGoodCommands) { - // let's give the sucker a hint - std::cout - << "CoinSolver takes input from arguments ( - switches to stdin)" - << std::endl - << "Enter ? for list of commands or help" << std::endl; - field = "-"; - } else { - break; - } + if (numberGoodCommands == 1 && goodModel) { + // we just had file name - do branch and bound + field = "-solve"; + } else { + break; + } } - // see if ? at end - size_t numberQuery = 0; - if (field != "?" && field != "???") { - size_t length = field.length(); - size_t i; - for (i = length - 1; i > 0; i--) { - if (field[i] == '?') - numberQuery++; - else - break; - } - field = field.substr(0, length - numberQuery); + // These are some special case we deal with separately + // (only in non-interactive mode) + if (!interactiveMode){ + if (field == "-") { + std::cout << "Switching to line mode" << std::endl; + interactiveMode = true; + while (!inputQueue.empty()) + inputQueue.pop_front(); + field = CoinParamUtils::getNextField(inputQueue, interactiveMode, prompt); + } else if (field[0] != '-') { + // special dispensation - taken as -import name, put name back on queue + inputQueue.push_front(field); + field = "import"; + } else { + if (field != "--") { + // take off - + field = field.substr(1); + } else { + // special dispensation - taken as -import -- + field = "import"; + } + } } + // find out if valid command - int iParam; - int numberMatches = 0; - int firstMatch = -1; - for (iParam = 0; iParam < (int)parameters_.size(); iParam++) { - int match = parameters_[iParam].matches(field); - if (match == 1) { - numberMatches = 1; - firstMatch = iParam; - break; + // ? would it be better to do Cbc first ? + int numberClpMatches(0), numberClpShortMatches(0), numberClpQuery(999); + int clpParamCode = CoinParamUtils::lookupParam(field, + clpParameters.paramVec(), + &numberClpMatches, + &numberClpShortMatches, + &numberClpQuery); + + int numberCbcMatches(0), numberCbcShortMatches(0), numberCbcQuery(0); + if (numberClpQuery>0) + numberCbcQuery = 999; // so won't complain if no matches + int cbcParamCode = CoinParamUtils::lookupParam(field, + parameters.paramVec(), + &numberCbcMatches, + &numberCbcShortMatches, + &numberCbcQuery); + + int numberMatches(numberClpMatches + numberCbcMatches); + int numberShortMatches(numberClpShortMatches + numberCbcShortMatches); + int numberQuery(numberClpQuery + numberCbcQuery); + + if (numberQuery > 0 || (numberShortMatches > 0 && !numberMatches)){ + continue; + } + if (!numberMatches) { + if (!interactiveMode){ + std::cout << "Unrecognized parameter - " << field + << ", exiting..." + << std::endl; + cbcParamCode = CbcParam::EXIT; + } else { + std::cout << "Unrecognized parameter - " << field + << " - enter valid command or end to exit" + << std::endl; + continue; + } + } + + // Do some translation for backwards compatibility + switch (cbcParamCode){ + case CbcParam::READMODEL_OLD: + cbcParamCode = CbcParam::READMODEL; + break; + case CbcParam::WRITEGMPLSOL_OLD: + cbcParamCode = CbcParam::WRITEGMPLSOL; + break; + case CbcParam::WRITEMODEL_OLD: + cbcParamCode = CbcParam::WRITEMODEL; + break; + case CbcParam::WRITESOL_OLD: + cbcParamCode = CbcParam::WRITESOL; + break; + case CbcParam::WRITESOLBINARY_OLD: + cbcParamCode = CbcParam::WRITESOLBINARY; + break; + default: + break; + } + + CbcParam *cbcParam = parameters[CbcParam::INVALID]; + ClpParam *clpParam = clpParameters[ClpParam::INVALID]; + + if (cbcParamCode >= 0){ + cbcParam = parameters[cbcParamCode]; + clpParamCode = ClpParam::INVALID; + }else{ + clpParam = clpParameters[clpParamCode]; + } + +#if 0 + // This logic is all captured in lookupParam + if ((cbcParam->type() == CoinParam::paramInvalid && + clpParam->type() == CoinParam::paramInvalid) || + numberQuery) { + if (!numberMatches) { + std::cout << "No match for " << field << " - ? for list of commands" + << std::endl; + } else if (numberMatches == 1) { + if (!numberQuery) { + std::cout << "Short match for " << field << " - completion: "; + if (cbcParam->type() != CoinParam::paramInvalid) { + std::cout << cbcParam->matchName() << std::endl; + } else { + std::cout << clpParam->matchName() << std::endl; + } + } else if (numberQuery) { + if (cbcParam->type() != CoinParam::paramInvalid) { + std::cout << cbcParam->matchName() << " : "; + std::cout << cbcParam->shortHelp() << std::endl; + if (numberQuery >= 2){ + cbcParam->printLongHelp(); + } + } else { + std::cout << clpParam->matchName() << " : "; + std::cout << clpParam->shortHelp() << std::endl; + if (numberQuery >= 2){ + clpParam->printLongHelp(); + } + } + } } else { - if (match && firstMatch < 0) - firstMatch = iParam; - numberMatches += match >> 1; + if (!numberQuery) + std::cout << "Multiple matches for " << field + << " - possible completions:" << std::endl; + else + std::cout << "Completions of " << field << ":" << std::endl; + for (int iParam = CbcParam::FIRSTPARAM + 1; + iParam < CbcParam::LASTPARAM; iParam++) { + int match = parameters[iParam]->matches(field); + if (match && parameters[iParam]->getDisplayPriority()) { + std::cout << parameters[iParam]->matchName(); + if (numberQuery >= 2) + std::cout << " : " << parameters[iParam]->shortHelp(); + std::cout << std::endl; + } + } + for (int iParam = ClpParam::FIRSTPARAM + 1; + iParam < ClpParam::LASTPARAM; iParam++) { + int match = clpParameters[iParam]->matches(field); + if (match && clpParameters[iParam]->getDisplayPriority()) { + std::cout << clpParameters[iParam]->matchName(); + if (numberQuery >= 2) + std::cout << " : " << clpParameters[iParam]->shortHelp(); + std::cout << std::endl; + } + } } - } - if (iParam < (int)parameters_.size() && !numberQuery) { + } else { +#endif // found - CbcOrClpParam found = parameters_[iParam]; - CbcOrClpParameterType type = found.type(); - int valid; + int status; numberGoodCommands++; - if (type == CBC_PARAM_ACTION_BAB && goodModel) { - if (clqstrAction == "before") { //performing clique strengthening before initial solve - CglCliqueStrengthening clqStr(model_.solver(), model_.messageHandler()); + if (cbcParamCode == CbcParam::BAB && goodModel) { + if (clqstrMode == "before") { // performing clique strengthening + // before initial solve + CglCliqueStrengthening clqStr(model_.solver(), + model_.messageHandler()); clqStr.strengthenCliques(2); - if (clqStr.constraintsExtended() + clqStr.constraintsDominated() > 0) { + if (clqStr.constraintsExtended() + clqStr.constraintsDominated() > + 0) { model_.solver()->initialSolve(); - if ((!noPrinting_) && (model_.messageHandler()->logLevel())) { - if (model_.solver()->isProvenPrimalInfeasible()) { - sprintf(generalPrint, "Clique Strengthening says infeasible!"); - generalMessageHandler->message(CLP_GENERAL, generalMessages) - << generalPrint - << CoinMessageEol; - } else { - sprintf(generalPrint, "After applying Clique Strengthening continuous objective value is %.2lf", model_.solver()->getObjValue()); - generalMessageHandler->message(CLP_GENERAL, generalMessages) - << generalPrint - << CoinMessageEol; - } + if (model_.solver()->isProvenPrimalInfeasible()) { + printGeneralMessage(model_, + "Clique Strengthening says infeasible!"); + } else { + buffer.str(""); + buffer << "After applying Clique Strengthening continuous " + << "objective value is " << model_.solver()->getObjValue(); + printGeneralMessage(model_, buffer.str()); } } } -#if CBC_USE_INITIAL_TIME==1 +#if CBC_USE_INITIAL_TIME == 1 if (model_.useElapsedTime()) model_.setDblParam(CbcModel::CbcStartSeconds, CoinGetTimeOfDay()); else @@ -2033,13 +1764,17 @@ int CbcMain1(int argc, const char *argv[], biLinearProblem = false; // check if any integers #ifndef CBC_OTHER_SOLVER - if (info.numberSos && doSOS && statusUserFunction_[0]) { + if (info && info->numberSos && doSOS && statusUserFunction_[0]) { // SOS - numberSOS = info.numberSos; + numberSOS = info->numberSos; } lpSolver = clpSolver->getModelPtr(); - if (!lpSolver->integerInformation() && !numberSOS && !clpSolver->numberSOS() && !model_.numberObjects() && !clpSolver->numberObjects()) { - type = CLP_PARAM_ACTION_DUALSIMPLEX; + if (!lpSolver->integerInformation() && !numberSOS && + !clpSolver->numberSOS() && !model_.numberObjects() && + !clpSolver->numberObjects()) { + clpParamCode = ClpParam::DUALSIMPLEX; + cbcParamCode = CbcParam::LASTACTIONPARAM; // acts like dummy + clpParam = clpParameters[clpParamCode]; #ifdef CBC_MAXIMUM_BOUND } else { double *lower = lpSolver->columnLower(); @@ -2053,932 +1788,1023 @@ int CbcMain1(int argc, const char *argv[], } #endif } - if (type == CBC_PARAM_GENERALQUERY) { - bool evenHidden = false; - int printLevel = parameters_[whichParam(CLP_PARAM_STR_ALLCOMMANDS, - parameters_)] - .currentOptionAsInteger(); - int convertP[] = { 2, 1, 0 }; - printLevel = convertP[printLevel]; + if (cbcParamCode == CbcParam::GENERALQUERY || + cbcParamCode == CbcParam::FULLGENERALQUERY) { + //TODO This should be made more transparent + //bool evenHidden = false; + int commandPrintLevel = + parameters[CbcParam::COMMANDPRINTLEVEL]->modeVal(); + if (cbcParamCode == CbcParam::FULLGENERALQUERY) { + verbose = 1; + commandPrintLevel = 1; + } +#if 0 if ((verbose & 8) != 0) { // even hidden - evenHidden = true; + // evenHidden = true; verbose &= ~8; } if (verbose < 4 && statusUserFunction_[0]) - verbose += 4; - if (verbose < 4) { - std::cout << "In argument list keywords have leading - " - ", -stdin or just - switches to stdin" - << std::endl; - std::cout << "One command per line (and no -)" << std::endl; - std::cout << "abcd? gives list of possibilities, if only one + explanation" << std::endl; - std::cout << "abcd?? adds explanation, if only one fuller help" << std::endl; - std::cout << "abcd without value (where expected) gives current value" << std::endl; - std::cout << "abcd value sets value" << std::endl; - std::cout << "Commands are:" << std::endl; - } else { - std::cout << "Cbc options are set within AMPL with commands like:" << std::endl - << std::endl; - std::cout << " option cbc_options \"cuts=root log=2 feas=on slog=1\"" << std::endl - << std::endl; - std::cout << "only maximize, dual, primal, help and quit are recognized without =" << std::endl; - } - int maxAcross = 10; - if ((verbose % 4) != 0) - maxAcross = 1; - int limits[] = { 1, 51, 101, 151, 201, 301, 401, 501, 601 }; - std::vector< std::string > types; - types.push_back("Double parameters:"); - types.push_back("Branch and Cut double parameters:"); - types.push_back("Integer parameters:"); - types.push_back("Branch and Cut integer parameters:"); - types.push_back("Keyword parameters:"); - types.push_back("Branch and Cut keyword parameters:"); - types.push_back("Actions or string parameters:"); - types.push_back("Branch and Cut actions:"); - int iType; - for (iType = 0; iType < 8; iType++) { - int across = 0; - int lengthLine = 0; - if ((verbose % 4) != 0) - std::cout << std::endl; - std::cout << types[iType] << std::endl; - if ((verbose & 2) != 0) - std::cout << std::endl; - for (iParam = 0; iParam < (int)parameters_.size(); iParam++) { - int type = parameters_[iParam].type(); - //printf("%d type %d limits %d %d display %d\n",iParam, - // type,limits[iType],limits[iType+1],parameters_[iParam].displayThis()); - if ((parameters_[iParam].displayThis() >= printLevel || evenHidden) && type >= limits[iType] - && type < limits[iType + 1]) { - // but skip if not useful for ampl (and in ampl mode) - if (verbose >= 4 && (parameters_[iParam].whereUsed() & 4) == 0) - continue; - if (!across) { - if ((verbose & 2) != 0) - std::cout << "Command "; - } - int length = parameters_[iParam].lengthMatchName() + 1; - if (lengthLine + length > 80) { - std::cout << std::endl; - across = 0; - lengthLine = 0; - } - std::cout << " " << parameters_[iParam].matchName(); - lengthLine += length; - across++; - if (across == maxAcross) { - across = 0; - if ((verbose % 4) != 0) { - // put out description as well - if ((verbose & 1) != 0) - std::cout << " " << parameters_[iParam].shortHelp(); - std::cout << std::endl; - if ((verbose & 2) != 0) { - std::cout << "---- description" << std::endl; - parameters_[iParam].printLongHelp(); - std::cout << "----" << std::endl - << std::endl; - } - } else { - std::cout << std::endl; - } - } - } - } - if (across) - std::cout << std::endl; + verbose += 4; +#endif + if (verbose) { + std::cout << std::endl + << "Commands either invoke actions or set parameter values.\n" + << "When specifying multiple commands on one command line,\n" + << "parameter/action names should be prepended with a '-',\n" + << "followed by a value (some actions don't accept values as\n" + << "arguments). Specifying -stdin at anytime switches to stdin.\n" + << std::endl + << "In interactive mode, specify one command per line and\n" + << "don't prepend command names with '-'.\n" + << std::endl + << "Some actions take file names as arguments. If no file name\n" + << "is provided, then the previous name (or initial default)\n" + << "will be used.\n" + << std::endl + << "abcd? will list commands starting with 'abcd'.\n" + << "If there is only one match, a short explanation is given.\n" + << std::endl + << "abcd?? will list commands with explanations.\n" + << "If there is only one match, fuller help is given.\n" + << std::endl + << "abcd without value gives current value (for parameters).\n" + << "abcd 'value' sets value (for parameters)\n" + << std::endl + << "Commands are:" << std::endl; + } else { + std::cout << "Cbc options are set within AMPL with commands like:" + << std::endl + << std::endl; + std::cout << " option cbc_options \"cuts=root log=2 " + "feas=on slog=1\"" + << std::endl + << std::endl; + std::cout << "only maximize, dual, primal, help and quit are " + "recognized without =" + << std::endl; + } + // TODO Fix these! + int maxAcross = 10; + if ((verbose % 4) != 0){ + maxAcross = 1; } - } else if (type == CBC_PARAM_FULLGENERALQUERY) { - std::cout << "Full list of commands is:" << std::endl; - int maxAcross = 5; - int limits[] = { 1, 51, 101, 151, 201, 301, 401, 501, 601 }; std::vector< std::string > types; - types.push_back("Double parameters:"); - types.push_back("Branch and Cut double parameters:"); + types.push_back("Invalid parameters:"); + types.push_back("Action parameters:"); types.push_back("Integer parameters:"); - types.push_back("Branch and Cut integer parameters:"); + types.push_back("Double parameters:"); + types.push_back("String parameters:"); + types.push_back("Directory parameters:"); + types.push_back("File parameters:"); types.push_back("Keyword parameters:"); - types.push_back("Branch and Cut keyword parameters:"); - types.push_back("Actions or string parameters:"); - types.push_back("Branch and Cut actions:"); - int iType; - for (iType = 0; iType < 8; iType++) { - int across = 0; - std::cout << types[iType] << " "; - for (iParam = 0; iParam < (int)parameters_.size(); iParam++) { - int type = parameters_[iParam].type(); - if (type >= limits[iType] - && type < limits[iType + 1]) { - if (!across) - std::cout << " "; - std::cout << parameters_[iParam].matchName() << " "; - across++; - if (across == maxAcross) { - std::cout << std::endl; - across = 0; - } + std::cout << std::endl << "#### Cbc Parameters ####" << std::endl; + for (int type = 1; type < 8; type++) { + int across = 0; + int lengthLine = 0; + bool first = true; + for (int iParam = CbcParam::FIRSTPARAM + 1; + iParam < CbcParam::LASTPARAM; iParam++) { + //TODO Print model parameters + CbcParam *p = parameters[iParam]; + if (p->type() != type || + p->getDisplayPriority() < commandPrintLevel){ + continue; + } + if (first) { + std::cout << std::endl + << "*** " << types[type] << " ***" + << std::endl << std::endl; + first = false; + } +#if 0 + if ((verbose % 4) != 0) { + std::cout << std::endl; + } + if ((verbose & 2) != 0){ + std::cout << std::endl; + } + // TODO Fix AMPL mode stuff + // but skip if not useful for ampl (and in ampl mode) + if (verbose >= 4 && (p->whereUsed() & 4) == 0) + continue; +#endif + int length = p->lengthMatchName() + 1; + if (lengthLine + length > 80) { + std::cout << std::endl; + across = 0; + lengthLine = 0; + } + if (!across && (verbose & 2) != 0) { + std::cout << "Command "; + } + std::cout << p->matchName(); + lengthLine += length; + across++; + if (verbose) { + if ((verbose % 4) != 0) { + // put out description as well + if ((verbose & 1) != 0){ + if (length < 8){ + std::cout << "\t\t\t"; + } else if (length < 16) { + std::cout << "\t\t"; + } else { + std::cout << "\t"; + } + std::cout << p->shortHelp(); + std::cout << std::endl; + } else if ((verbose & 2) != 0) { + std::cout << "---- description" << std::endl; + p->printLongHelp(); + std::cout << "----" << std::endl << std::endl; + } + } + across = 0; + lengthLine = 0; + } else { + std::cout << " "; } - } - if (across) - std::cout << std::endl; - } - } else if (type < 101) { - // get next field as double - double value = CoinReadGetDoubleField(argc, argv, &valid); - if (!valid) { - if (type < 51) { - int returnCode; - const char *message = parameters_[iParam].setDoubleParameterWithMessage(lpSolver, value, returnCode); - if (!noPrinting_ && strlen(message)) { - generalMessageHandler->message(CLP_GENERAL, generalMessages) - << message - << CoinMessageEol; + if (across == maxAcross) { + across = 0; + lengthLine = 0; + std::cout << std::endl; } - } else if (type < 81) { - int returnCode; - const char *message = parameters_[iParam].setDoubleParameterWithMessage(model_, value, returnCode); - if (!noPrinting_ && strlen(message)) { - generalMessageHandler->message(CLP_GENERAL, generalMessages) - << message - << CoinMessageEol; + } + if (across){ + std::cout << std::endl; + } + } + std::cout << std::endl << "#### Clp Parameters ####" << std::endl; + for (int type = 1;type < 8;type++) { + int across = 0; + int lengthLine = 0; + bool first = true; + for (int iParam = ClpParam::FIRSTPARAM+1; + iParam < ClpParam::LASTPARAM; iParam++) { + if (clpParameters[iParam]->type() != type) + continue; + ClpParam *p = clpParameters[iParam]; + if (p->type() != type || + p->getDisplayPriority() < commandPrintLevel){ + continue; + } + if (first) { + std::cout << std::endl + << "*** " << types[type] << " ***" + << std::endl << std::endl; + first = false; + } + int length = p->lengthMatchName() + 1; + if (lengthLine + length > 80) { + std::cout << std::endl; + across = 0; + lengthLine = 0; + } + if (!across && (verbose & 2) != 0){ + std::cout << "Command "; + } + std::cout << p->matchName(); + lengthLine += length; + across++; + if (verbose) { + // put out description as well + if ((verbose & 1) != 0){ + if (length < 8){ + std::cout << "\t\t\t"; + } else if (length < 16) { + std::cout << "\t\t"; + } else { + std::cout << "\t"; + } + std::cout << p->shortHelp(); + std::cout << std::endl; + } else if ((verbose & 2) != 0) { + std::cout << "---- description" << std::endl; + p->printLongHelp(); + std::cout << "----" << std::endl << std::endl; + } + across = 0; + lengthLine = 0; + } else { + std::cout << " "; } - } else { - int returnCode; - const char *message = parameters_[iParam].setDoubleParameterWithMessage(lpSolver, value, returnCode); - if (!noPrinting_ && strlen(message)) { - generalMessageHandler->message(CLP_GENERAL, generalMessages) - << message - << CoinMessageEol; + if (across == maxAcross) { + across = 0; + lengthLine = 0; + std::cout << std::endl; } - switch (type) { - case CBC_PARAM_DBL_DJFIX: - djFix = value; + } + if (across){ + std::cout << std::endl; + } + } + continue; + } + + if (cbcParam->type() == CoinParam::paramDbl) { + if (status = cbcParam->readValue(inputQueue, dValue, &message)){ + printGeneralMessage(model_, message); + continue; + } + if (cbcParam->setVal(dValue, &message)){ + printGeneralMessage(model_, message); + continue; + } else { + printGeneralMessage(model_, message); + } + // TODO: These should be moved to the push function + switch (cbcParamCode) { + case CbcParam::DJFIX: + djFix = dValue; #ifndef CBC_OTHER_SOLVER - if (goodModel && djFix < 1.0e20) { - // do some fixing - clpSolver = dynamic_cast< OsiClpSolverInterface * >(model_.solver()); - clpSolver->initialSolve(); - lpSolver = clpSolver->getModelPtr(); - int numberColumns = lpSolver->numberColumns(); - int i; - const char *type = lpSolver->integerInformation(); - double *lower = lpSolver->columnLower(); - double *upper = lpSolver->columnUpper(); - double *solution = lpSolver->primalColumnSolution(); - double *dj = lpSolver->dualColumnSolution(); - int numberFixed = 0; - double dextra4 = parameters_[whichParam(CBC_PARAM_DBL_DEXTRA4, parameters_)].doubleValue(); - if (dextra4) - printf("Multiple for continuous dj fixing is %g\n", dextra4); - for (i = 0; i < numberColumns; i++) { + if (goodModel && djFix < 1.0e20) { + // do some fixing + clpSolver = + dynamic_cast(model_.solver()); + clpSolver->initialSolve(); + lpSolver = clpSolver->getModelPtr(); + int numberColumns = lpSolver->numberColumns(); + int i; + const char *type = lpSolver->integerInformation(); + double *lower = lpSolver->columnLower(); + double *upper = lpSolver->columnUpper(); + double *solution = lpSolver->primalColumnSolution(); + double *dj = lpSolver->dualColumnSolution(); + int numberFixed = 0; + double dextra4 = parameters[CbcParam::DEXTRA4]->dblVal(); + if (dextra4) + printf("Multiple for continuous dj fixing is %g\n", + dextra4); + for (i = 0; i < numberColumns; i++) { double djValue = dj[i]; if (!type[i]) - djValue *= dextra4; + djValue *= dextra4; if (type[i] || dextra4) { - double value = solution[i]; - if (value < lower[i] + 1.0e-5 && djValue > djFix) { - solution[i] = lower[i]; - upper[i] = lower[i]; - numberFixed++; - } else if (value > upper[i] - 1.0e-5 && djValue < -djFix) { - solution[i] = upper[i]; - lower[i] = upper[i]; - numberFixed++; - } - } - } - sprintf(generalPrint, "%d columns fixed\n", numberFixed); - generalMessageHandler->message(CLP_GENERAL, generalMessages) - << generalPrint - << CoinMessageEol; - } -#endif - break; - case CBC_PARAM_DBL_TIGHTENFACTOR: - tightenFactor = value; - if (!complicatedInteger) - defaultSettings = false; // user knows what she is doing - break; - default: - break; - } - } - } else if (valid == 1) { - std::cout << " is illegal for double parameter " << parameters_[iParam].name() << " value remains " << parameters_[iParam].doubleValue() << std::endl; - } else { - std::cout << parameters_[iParam].name() << " has value " << parameters_[iParam].doubleValue() << std::endl; - } - } else if (type < 201) { - // get next field as int - int value = CoinReadGetIntField(argc, argv, &valid); - if (valid == 1 && parameters_[iParam].stringValue()!="") { - // look further - value = - parameters_[iParam].optionIntField(getCoinErrorField(), &valid); - } - if (!valid) { - if (type < 151) { - if (parameters_[iParam].type() == CLP_PARAM_INT_PRESOLVEPASS) - preSolve = value; - else if (parameters_[iParam].type() == CLP_PARAM_INT_IDIOT) - doIdiot = value; - else if (parameters_[iParam].type() == CLP_PARAM_INT_SPRINT) - doSprint = value; - else if (parameters_[iParam].type() == CLP_PARAM_INT_OUTPUTFORMAT) - outputFormat = value; - else if (parameters_[iParam].type() == CLP_PARAM_INT_SLPVALUE) - slpValue = value; - else if (parameters_[iParam].type() == CLP_PARAM_INT_CPP) - cppValue = value; - else if (parameters_[iParam].type() == CLP_PARAM_INT_PRESOLVEOPTIONS) - presolveOptions = value; - else if (parameters_[iParam].type() == CLP_PARAM_INT_PRINTOPTIONS) - printOptions = value; - else if (parameters_[iParam].type() == CLP_PARAM_INT_SUBSTITUTION) - substitution = value; - else if (parameters_[iParam].type() == CLP_PARAM_INT_DUALIZE) - dualize = value; - else if (parameters_[iParam].type() == CLP_PARAM_INT_PROCESSTUNE) - tunePreProcess = value; - else if (parameters_[iParam].type() == CLP_PARAM_INT_USESOLUTION) - useSolution = value; - else if (parameters_[iParam].type() == CLP_PARAM_INT_VERBOSE) - verbose = value; - int returnCode; - const char *message = parameters_[iParam].setIntParameterWithMessage(lpSolver, value, returnCode); - if (parameters_[iParam].type() == CLP_PARAM_INT_SOLVERLOGLEVEL) - clpSolver->messageHandler()->setLogLevel(value); // as well - - if (!noPrinting_ && strlen(message)) { - generalMessageHandler->message(CLP_GENERAL, generalMessages) - << message - << CoinMessageEol; + double value = solution[i]; + if (value < lower[i] + 1.0e-5 && djValue > djFix) { + solution[i] = lower[i]; + upper[i] = lower[i]; + numberFixed++; + } else if (value > upper[i] - 1.0e-5 && + djValue < -djFix) { + solution[i] = upper[i]; + lower[i] = upper[i]; + numberFixed++; + } + } + } + buffer.str(""); + buffer << numberFixed << " columns fixed" << std::endl; + printGeneralMessage(model_, buffer.str()); } - } else { - if (parameters_[iParam].type() == CBC_PARAM_INT_CUTPASS) - cutPass = value; - else if (parameters_[iParam].type() == CBC_PARAM_INT_CUTPASSINTREE) - cutPassInTree = value; - else if (parameters_[iParam].type() == CBC_PARAM_INT_STRONGBRANCHING || parameters_[iParam].type() == CBC_PARAM_INT_NUMBERBEFORE) - strongChanged = true; - else if (parameters_[iParam].type() == CBC_PARAM_INT_FPUMPTUNE || parameters_[iParam].type() == CBC_PARAM_INT_FPUMPTUNE2 || parameters_[iParam].type() == CBC_PARAM_INT_FPUMPITS) - pumpChanged = true; - else if (parameters_[iParam].type() == CBC_PARAM_INT_BKPIVOTINGSTRATEGY) - bkPivotingStrategy = value; - else if (parameters_[iParam].type() == CBC_PARAM_INT_BKMAXCALLS) - maxCallsBK = value; - else if (parameters_[iParam].type() == CBC_PARAM_INT_BKCLQEXTMETHOD) - bkClqExtMethod = value; - else if (parameters_[iParam].type() == CBC_PARAM_INT_ODDWEXTMETHOD) - oddWExtMethod = value; - else if (parameters_[iParam].type() == CBC_PARAM_INT_EXPERIMENT - && value<10000) { - int addFlags = 0; - // switch on some later features if >999 - if (value > 999) { - int switchValue = value / 1000; - const char *message = NULL; - value -= 1000 * switchValue; - parameters_[whichParam(CBC_PARAM_INT_EXPERIMENT, parameters_)].setIntValue(0 /*value*/); - switch (switchValue) { - default: - case 4: - // hotstart 500, -200 cut passes - message = parameters_[whichParam(CBC_PARAM_INT_MAXHOTITS, parameters_)].setIntValueWithMessage(500); - if (!noPrinting_ && message) - generalMessageHandler->message(CLP_GENERAL, generalMessages) - << message << CoinMessageEol; - message = parameters_[whichParam(CBC_PARAM_INT_CUTPASS, parameters_)].setIntValueWithMessage(-200); - if (!noPrinting_ && message) - generalMessageHandler->message(CLP_GENERAL, generalMessages) - << message << CoinMessageEol; - case 3: - // multiple 4 - message = parameters_[whichParam(CBC_PARAM_INT_MULTIPLEROOTS, parameters_)].setIntValueWithMessage(4); - if (!noPrinting_ && message) - generalMessageHandler->message(CLP_GENERAL, generalMessages) - << message << CoinMessageEol; - case 2: - // rens plus all diving at root - message = parameters_[whichParam(CBC_PARAM_INT_DIVEOPT, parameters_)].setIntValueWithMessage(16); - if (!noPrinting_ && message) - generalMessageHandler->message(CLP_GENERAL, generalMessages) - << message << CoinMessageEol; - model_.setNumberAnalyzeIterations(-value); - // -tune 7 zero,lagomory,gmi at root - probing on - case 1: - tunePreProcess = 7; - message = parameters_[whichParam(CLP_PARAM_INT_PROCESSTUNE, parameters_)].setIntValueWithMessage(7); - if (!noPrinting_ && message) - generalMessageHandler->message(CLP_GENERAL, generalMessages) - << message << CoinMessageEol; - //message = parameters_[whichParam(CBC_PARAM_INT_MIPOPTIONS, parameters_)].setIntValueWithMessage(1025); - //if (!noPrinting_&&message) - // generalMessageHandler->message(CLP_GENERAL, generalMessages) - // << message << CoinMessageEol; - message = parameters_[whichParam(CBC_PARAM_STR_PROBINGCUTS, parameters_)].setCurrentOptionWithMessage("on"); - probingAction = 1; - if (!noPrinting_ && message) - generalMessageHandler->message(CLP_GENERAL, generalMessages) - << message << CoinMessageEol; - message = parameters_[whichParam(CBC_PARAM_STR_ZEROHALFCUTS, parameters_)].setCurrentOptionWithMessage("root"); - if (!noPrinting_ && message) - generalMessageHandler->message(CLP_GENERAL, generalMessages) - << message << CoinMessageEol; - message = parameters_[whichParam(CBC_PARAM_STR_LAGOMORYCUTS, parameters_)].setCurrentOptionWithMessage("root"); - if (!noPrinting_ && message) - generalMessageHandler->message(CLP_GENERAL, generalMessages) - << message << CoinMessageEol; - GMIAction = 2; - message = parameters_[whichParam(CBC_PARAM_STR_GMICUTS, parameters_)].setCurrentOptionWithMessage("root"); - if (!noPrinting_ && message) - generalMessageHandler->message(CLP_GENERAL, generalMessages) - << message << CoinMessageEol; - } - value = 0; - } - if (value >= 10) { - addFlags = 1048576 * (value / 10); - value = value % 10; - parameters_[whichParam(CBC_PARAM_INT_EXPERIMENT, parameters_)].setIntValue(value); - } -#ifndef CBC_EXPERIMENT7 - if (value == 1) { - // just experimental preprocessing and more restarts - tunePreProcess |= 8192; - model_.setSpecialOptions(model_.specialOptions()|(512|32768)); - } -#else - if (value == 1 || value == 2) { - // just experimental preprocessing and more restarts - tunePreProcess |= 8199; - model_.setSpecialOptions(model_.specialOptions()|(512|32768)); - if (value == 2) { - value = 1; - int more2 = parameters_[whichParam(CBC_PARAM_INT_MOREMOREMIPOPTIONS, parameters_)].intValue(); - parameters_[whichParam(CBC_PARAM_INT_MOREMOREMIPOPTIONS, parameters_)].setIntValue(more2|1048576); - } - } #endif - if (value > 1) { - int values[] = { 24003, 280003, 792003, 24003, 24003 }; - if (value >= 2 && value <= 3) { - // swap default diving - int iParam = whichParam(CBC_PARAM_STR_DIVINGC, parameters_); - parameters_[iParam].setCurrentOption("off"); - iParam = whichParam(CBC_PARAM_STR_DIVINGP, parameters_); - parameters_[iParam].setCurrentOption("on"); - } - int extra4 = values[value - 1] + addFlags; - parameters_[whichParam(CBC_PARAM_INT_EXTRA4, parameters_)].setIntValue(extra4); - if (!noPrinting_) { - generalMessageHandler->message(CLP_GENERAL, generalMessages) - << "switching on global root cuts for gomory and knapsack" - << CoinMessageEol; - generalMessageHandler->message(CLP_GENERAL, generalMessages) - << "using OSL factorization" - << CoinMessageEol; - generalMessageHandler->message(CLP_GENERAL, generalMessages) - << "extra options - -rens on -extra4 " - << extra4 << " -passc 1000!" - << CoinMessageEol; - } - parameters_[whichParam(CBC_PARAM_STR_PROBINGCUTS, parameters_)].setCurrentOption("forceOnStrong"); - probingAction = 8; - parameters_[whichParam(CBC_PARAM_STR_GOMORYCUTS, parameters_)].setCurrentOption("onGlobal"); - gomoryAction = 5; - parameters_[whichParam(CBC_PARAM_STR_KNAPSACKCUTS, parameters_)].setCurrentOption("onGlobal"); - knapsackAction = 5; - parameters_[whichParam(CLP_PARAM_STR_FACTORIZATION, parameters_)].setCurrentOption("osl"); - lpSolver->factorization()->forceOtherFactorization(3); - parameters_[whichParam(CBC_PARAM_INT_MAXHOTITS, parameters_)].setIntValue(100); - parameters_[whichParam(CBC_PARAM_INT_CUTPASS, parameters_)].setIntValue(1000); - cutPass = 1000; - parameters_[whichParam(CBC_PARAM_STR_RENS, parameters_)].setCurrentOption("on"); - } - } else if (parameters_[iParam].type() == CBC_PARAM_INT_STRATEGY) { - if (value == 0) { - gomoryGen.setAwayAtRoot(0.05); - int iParam; - iParam = whichParam(CBC_PARAM_INT_DIVEOPT, parameters_); - parameters_[iParam].setIntValue(-1); - iParam = whichParam(CBC_PARAM_INT_FPUMPITS, parameters_); - parameters_[iParam].setIntValue(20); - iParam = whichParam(CBC_PARAM_INT_FPUMPTUNE, parameters_); - parameters_[iParam].setIntValue(1003); - initialPumpTune = 1003; - iParam = whichParam(CLP_PARAM_INT_PROCESSTUNE, parameters_); - parameters_[iParam].setIntValue(0); - tunePreProcess = 0; - iParam = whichParam(CBC_PARAM_STR_DIVINGC, parameters_); - parameters_[iParam].setCurrentOption("off"); - iParam = whichParam(CBC_PARAM_STR_RINS, parameters_); - parameters_[iParam].setCurrentOption("off"); - iParam = whichParam(CBC_PARAM_STR_PROBINGCUTS, parameters_); - // but not if cuts off - int jParam = whichParam(CBC_PARAM_STR_CUTSSTRATEGY, parameters_); - - jParam = parameters_[jParam].currentOptionAsInteger(); - if (jParam) { - parameters_[iParam].setCurrentOption("on"); - probingAction = 1; - } else { - parameters_[iParam].setCurrentOption("off"); - probingAction = 0; - } - } - } - int returnCode; - const char *message = parameters_[iParam].setIntParameterWithMessage(model_, value, returnCode); - if (!noPrinting_ && strlen(message)) { - generalMessageHandler->message(CLP_GENERAL, generalMessages) - << message - << CoinMessageEol; - } - } - } else if (valid == 1) { - std::cout << "String of " << getCoinErrorField(); - std::cout << " is illegal for integer parameter " << parameters_[iParam].name() << " value remains " << parameters_[iParam].intValue() << std::endl; - } else { - std::cout << parameters_[iParam].name() << " has value " << parameters_[iParam].intValue() << std::endl; - } - } else if (type < 401) { - // one of several strings - std::string value = CoinReadGetString(argc, argv); - int action = parameters_[iParam].parameterOption(value); - if (action < 0) { - if (value != "EOL") { - // no match - parameters_[iParam].printOptions(); - } else { - // print current value - std::cout << parameters_[iParam].name() << " has value " << parameters_[iParam].currentOption() << std::endl; - } - } else { - const char *message = parameters_[iParam].setCurrentOptionWithMessage(action); - if (!noPrinting_ && strlen(message)) { - generalMessageHandler->message(CLP_GENERAL, generalMessages) - << message - << CoinMessageEol; - } - // for now hard wired - switch (type) { - case CLP_PARAM_STR_DIRECTION: - if (action == 0) - lpSolver->setOptimizationDirection(1); - else if (action == 1) - lpSolver->setOptimizationDirection(-1); + break; + case CbcParam::TIGHTENFACTOR: + tightenFactor = dValue; + if (!complicatedInteger) + defaultSettings = false; // user knows what she is doing + break; + default: + break; + } + } else if (clpParam->type() == CoinParam::paramDbl) { + if (status = clpParam->readValue(inputQueue, dValue, &message)){ + printGeneralMessage(model_, message); + continue; + } + // We have a Clp parameter + if (clpParam->setVal(dValue, &message)){ + printGeneralMessage(model_, message); + continue; + } + } else if (cbcParam->type() == CoinParam::paramInt){ + if (status = cbcParam->readValue(inputQueue, iValue, &message)){ + printGeneralMessage(model_, message); + continue; + } + if (cbcParamCode == CbcParam::LPLOGLEVEL){ + clpSolver->messageHandler()->setLogLevel(iValue); // as well + clpParameters[ClpParam::LOGLEVEL]->setVal(iValue, &message); + cbcParam->setVal(iValue, &message); + printGeneralMessage(model_, message); + }else{ + cbcParam->setVal(iValue, &message); + printGeneralMessage(model_, message); + if (cbcParamCode == CbcParam::CUTPASS){ + cutPass = iValue; + } else if (cbcParamCode== CbcParam::USESOLUTION) { + useSolution = iValue; + } else if (cbcParamCode == CbcParam::CUTPASSINTREE) { + cutPassInTree = iValue; + } else if (cbcParamCode == CbcParam::STRONGBRANCHING || + cbcParamCode == CbcParam::NUMBERBEFORE) { + strongChanged = true; + } else if (cbcParamCode == CbcParam::FPUMPTUNE || cbcParamCode == CbcParam::FPUMPTUNE2 || + cbcParamCode == CbcParam::FPUMPITS) { + pumpChanged = true; + } else if (cbcParamCode == CbcParam::BKPIVOTINGSTRATEGY) { + bkPivotingStrategy = iValue; + } else if (cbcParamCode == CbcParam::BKMAXCALLS) { + maxCallsBK = iValue; + } else if (cbcParamCode == CbcParam::BKCLQEXTMETHOD) { + bkClqExtMethod = iValue; + } else if (cbcParamCode == CbcParam::ODDWEXTMETHOD) { + oddWExtMethod = iValue; + } else if (cbcParamCode == CbcParam::LOGLEVEL) { + model_.messageHandler()->setLogLevel(CoinAbs(iValue)); + } else if (cbcParamCode == CbcParam::MAXNODES) { + model_.setIntParam(CbcModel::CbcMaxNumNode, iValue); + } else if (cbcParamCode == CbcParam::MAXSOLS) { + model_.setIntParam(CbcModel::CbcMaxNumSol, iValue); + } else if (cbcParamCode == CbcParam::STRONGBRANCHING) { + model_.setNumberStrong(iValue); + } else if (cbcParamCode == CbcParam::PROCESSTUNE) { + tunePreProcess = iValue; + } else if (cbcParamCode == CbcParam::VERBOSE) { + verbose = iValue; + } else if (cbcParamCode == CbcParam::EXPERIMENT && iValue < 10000) { + int addFlags = 0; + // switch on some later features if >999 + if (iValue > 999) { + int switchValue = iValue / 1000; + iValue -= 1000 * switchValue; + parameters[CbcParam::EXPERIMENT]->setVal(0 /*value*/); + switch (switchValue) { + default: + case 4: + // hotstart 500, -200 cut passes + parameters[CbcParam::MAXHOTITS]->setVal(500, &message); + printGeneralMessage(model_, message); + parameters[CbcParam::CUTPASS]->setVal(-200, &message); + printGeneralMessage(model_, message); + case 3: + // multiple 4 + parameters[CbcParam::MULTIPLEROOTS]->setVal(4, &message); + printGeneralMessage(model_, message); + case 2: + // rens plus all diving at root + parameters[CbcParam::DIVEOPT]->setVal(16, &message); + printGeneralMessage(model_, message); + model_.setNumberAnalyzeIterations(-iValue); + // -tune 7 zero,lagomory,gmi at root - probing on + case 1: + tunePreProcess = 7; + parameters[CbcParam::PROCESSTUNE]->setVal(7, &message); + printGeneralMessage(model_, message); + // message = + // parameters[CbcParam::MIPOPTIONS, + // parameters)]->setValWithMessage(1025); if + // (!noPrinting_&&message) + // generalMessageHandler->message(CLP_GENERAL, + // generalMessages) + // << message << CoinMessageEol; + parameters[CbcParam::PROBINGCUTS]->setVal("on", &message); + probingMode = CbcParameters::CGOn; + printGeneralMessage(model_, message); + parameters[CbcParam::ZEROHALFCUTS]->setVal("root", &message); + printGeneralMessage(model_, message); + parameters[CbcParam::LAGOMORYCUTS]->setVal("root", &message); + printGeneralMessage(model_, message); + GMIMode = CbcParameters::CGRoot; + parameters[CbcParam::GMICUTS]->setVal("root", &message); + printGeneralMessage(model_, message); + } + iValue = 0; + } + if (iValue >= 10) { + addFlags = 1048576 * (iValue / 10); + iValue = iValue % 10; + parameters[CbcParam::EXPERIMENT]->setVal(iValue); + } +#ifndef CBC_EXPERIMENT_JJF + if (iValue == 1) { + // just experimental preprocessing and more restarts + tunePreProcess |= 8192; + model_.setSpecialOptions(model_.specialOptions() | + (512 | 32768)); + } +#else + experimentValue = iValue; // save + if (iValue > 0 && iValue < 5) { + // more restarts + // >1 go to end in strong branching + // >2 experimental preprocessing + // 4 try ranging before strong branching + model_.setSpecialOptions(model_.specialOptions() | + (512 | 32768)); +#ifndef CBC_OTHER_SOLVER + if (iValue > 1) { + OsiClpSolverInterface *osiclp = + dynamic_cast(model_.solver()); + osiclp->setSpecialOptions(osiclp->specialOptions() & ~32); + } +#endif + if (iValue > 2) + tunePreProcess |= 8198; // was 8199; + if (iValue == 4) { + int more2 = + parameters[CbcParam::MOREMOREMIPOPTIONS]->intVal(); + parameters[CbcParam::MOREMOREMIPOPTIONS]->setVal(more2 | 1048576); + } + iValue = 1; + } +#endif + if (iValue > 1) { + int values[] = {24003, 280003, 792003, 24003, 24003}; + if (iValue >= 2 && iValue <= 3) { + // swap default diving + parameters[CbcParam::DIVINGC]->setVal("off"); + parameters[CbcParam::DIVINGP]->setVal("on"); + } + int extra4 = values[iValue - 1] + addFlags; + parameters[CbcParam::EXTRA4]->setVal(extra4); + buffer.str(""); + buffer << "switching on global root cuts for gomory and " + << "knapsack" << std::endl; + buffer << "using OSL factorization" << std::endl; + buffer << "extra options - -rens on -extra4 " << extra4 + << " -passc 1000!" << std::endl; + printGeneralMessage(model_, buffer.str()); + parameters[CbcParam::PROBINGCUTS]->setVal("forceOnStrong"); + probingMode = CbcParameters::CGForceOnStrong; + parameters[CbcParam::GOMORYCUTS]->setVal("onGlobal"); + gomoryMode = CbcParameters::CGOnGlobal; + parameters[CbcParam::KNAPSACKCUTS]->setVal("onGlobal"); + knapsackMode = CbcParameters::CGOnGlobal; + clpParameters[ClpParam::FACTORIZATION]->setVal("osl"); + lpSolver->factorization()->forceOtherFactorization(3); + parameters[CbcParam::MAXHOTITS]->setVal(100); + parameters[CbcParam::CUTPASS]->setVal(1000); + cutPass = 1000; + parameters[CbcParam::RENS]->setVal("on"); + } + } else if (cbcParamCode == CbcParam::STRATEGY) { + if (iValue == 0) { + gomoryGen.setAwayAtRoot(0.05); + parameters[CbcParam::DIVEOPT]->setVal(-1); + parameters[CbcParam::FPUMPITS]->setVal(20); + parameters[CbcParam::FPUMPTUNE]->setVal(1003); + initialPumpTune = 1003; + parameters[CbcParam::PROCESSTUNE]->setVal(0); + tunePreProcess = 0; + parameters[CbcParam::RINS]->setVal("off"); + // but not if cuts off + if (parameters[CbcParam::CUTSTRATEGY]->modeVal()){ + parameters[CbcParam::PROBINGCUTS]->setVal("on"); + probingMode = CbcParameters::CGOn; + } else { + parameters[CbcParam::PROBINGCUTS]->setVal("off"); + probingMode = CbcParameters::CGOff; + } + } + } + } + } else if (clpParam->type() == CoinParam::paramInt) { + if (status = clpParam->readValue(inputQueue, iValue, &message)){ + printGeneralMessage(model_, message); + continue; + } + if (clpParam->setVal(iValue, &message)){ + printGeneralMessage(model_, message); + continue; + } else { + printGeneralMessage(model_, message); + } + if (clpParamCode == ClpParam::PRESOLVEPASS) { + preSolve = iValue; + } else if (clpParamCode == ClpParam::IDIOT) { + doIdiot = iValue; + } else if (clpParamCode == ClpParam::SPRINT) { + doSprint = iValue; + } else if (clpParamCode == ClpParam::OUTPUTFORMAT) { + outputFormat = iValue; + } else if (clpParamCode == ClpParam::SLPVALUE) { + slpValue = iValue; + } else if (clpParamCode == ClpParam::CPP) { + cppValue = iValue; + } else if (clpParamCode == ClpParam::PRESOLVEOPTIONS) { + presolveOptions = iValue; + } else if (clpParamCode == ClpParam::PRINTOPTIONS) { + printOptions = iValue; + } else if (clpParamCode == ClpParam::SUBSTITUTION) { + substitution = iValue; + } else if (clpParamCode == ClpParam::DUALIZE) { + dualize = iValue; + } + } else if (cbcParam->type() == CoinParam::paramKwd) { + if (status = cbcParam->readValue(inputQueue, field, &message)){ + printGeneralMessage(model_, message); + continue; + } + if (cbcParam->setVal(field, &message)){ + printGeneralMessage(model_, message); + continue; + } + int mode = cbcParam->modeVal(); + // TODO: this should be part of the push method + switch (cbcParamCode) { + case CbcParam::DIRECTION: + if (mode == 0) + lpSolver->setOptimizationDirection(1); + else if (mode == 1) + lpSolver->setOptimizationDirection(-1); else - lpSolver->setOptimizationDirection(0); + lpSolver->setOptimizationDirection(0); break; - case CLP_PARAM_STR_DUALPIVOT: - if (action == 0) { - ClpDualRowSteepest steep(3); - lpSolver->setDualRowPivotAlgorithm(steep); - } else if (action == 1) { - ClpDualRowDantzig dantzig; - //ClpDualRowSteepest dantzig(5); - lpSolver->setDualRowPivotAlgorithm(dantzig); - } else if (action == 2) { - // partial steep - ClpDualRowSteepest steep(2); - lpSolver->setDualRowPivotAlgorithm(steep); - } else if (action == 3) { - ClpDualRowSteepest steep; - lpSolver->setDualRowPivotAlgorithm(steep); - } else if (action == 4) { - // Positive edge steepest - ClpPEDualRowSteepest p(fabs(parameters_[whichParam(CLP_PARAM_DBL_PSI, parameters_)].doubleValue())); - lpSolver->setDualRowPivotAlgorithm(p); - } else if (action == 5) { - // Positive edge Dantzig - ClpPEDualRowDantzig p(fabs(parameters_[whichParam(CLP_PARAM_DBL_PSI, parameters_)].doubleValue())); - lpSolver->setDualRowPivotAlgorithm(p); - } + case CbcParam::ERRORSALLOWED: + allowImportErrors = mode; break; - case CLP_PARAM_STR_PRIMALPIVOT: - if (action == 0) { - ClpPrimalColumnSteepest steep(3); - lpSolver->setPrimalColumnPivotAlgorithm(steep); - } else if (action == 1) { - ClpPrimalColumnSteepest steep(0); - lpSolver->setPrimalColumnPivotAlgorithm(steep); - } else if (action == 2) { - ClpPrimalColumnDantzig dantzig; - lpSolver->setPrimalColumnPivotAlgorithm(dantzig); - } else if (action == 3) { - ClpPrimalColumnSteepest steep(4); - lpSolver->setPrimalColumnPivotAlgorithm(steep); - } else if (action == 4) { - ClpPrimalColumnSteepest steep(1); - lpSolver->setPrimalColumnPivotAlgorithm(steep); - } else if (action == 5) { - ClpPrimalColumnSteepest steep(2); - lpSolver->setPrimalColumnPivotAlgorithm(steep); - } else if (action == 6) { - ClpPrimalColumnSteepest steep(10); - lpSolver->setPrimalColumnPivotAlgorithm(steep); - } else if (action == 7) { - // Positive edge steepest - ClpPEPrimalColumnSteepest p(fabs(parameters_[whichParam(CLP_PARAM_DBL_PSI, parameters_)].doubleValue())); - lpSolver->setPrimalColumnPivotAlgorithm(p); - } else if (action == 8) { - // Positive edge Dantzig - ClpPEPrimalColumnDantzig p(fabs(parameters_[whichParam(CLP_PARAM_DBL_PSI, parameters_)].doubleValue())); - lpSolver->setPrimalColumnPivotAlgorithm(p); - } + case CbcParam::INTPRINT: + printMode = mode; break; - case CLP_PARAM_STR_SCALING: - lpSolver->scaling(action); - solver->setHintParam(OsiDoScale, action != 0, OsiHintTry); - doScaling = action; + // case CbcParam::CLP_PARAM_NOTUSED_ALGORITHM: + // algorithm = mode; + // defaultSettings=false; // user knows what she is doing + // abort(); + // break; + case CbcParam::SOS: + doSOS = mode; break; - case CLP_PARAM_STR_AUTOSCALE: - lpSolver->setAutomaticScaling(action != 0); + case CbcParam::CLQSTRENGTHENING: + clqstrMode = field; break; - case CLP_PARAM_STR_SPARSEFACTOR: - lpSolver->setSparseFactorization((1 - action) != 0); + case CbcParam::USECGRAPH: + cgraphMode = field; break; - case CLP_PARAM_STR_BIASLU: - lpSolver->factorization()->setBiasLU(action); + case CbcParam::CLIQUECUTS: + defaultSettings = false; // user knows what she is doing + cliqueMode = mode; + oldCliqueMode = cliqueMode; break; - case CLP_PARAM_STR_PERTURBATION: - if (action == 0) - lpSolver->setPerturbation(50); - else - lpSolver->setPerturbation(100); + case CbcParam::ODDWHEELCUTS: + defaultSettings = false; // user knows what she is doing + oddWheelMode = mode; break; - case CLP_PARAM_STR_ERRORSALLOWED: - allowImportErrors = action; + case CbcParam::GOMORYCUTS: + defaultSettings = false; // user knows what she is doing + gomoryMode = mode; break; - case CLP_PARAM_STR_INTPRINT: - printMode = action; + case CbcParam::PROBINGCUTS: + defaultSettings = false; // user knows what she is doing + probingMode = mode; break; - //case CLP_PARAM_NOTUSED_ALGORITHM: - //algorithm = action; - //defaultSettings=false; // user knows what she is doing - //abort(); - //break; - case CLP_PARAM_STR_KEEPNAMES: - keepImportNames = 1 - action; + case CbcParam::KNAPSACKCUTS: + defaultSettings = false; // user knows what she is doing + knapsackMode = mode; break; - case CLP_PARAM_STR_PRESOLVE: - if (action == 0) - preSolve = 5; - else if (action == 1) - preSolve = 0; - else if (action == 2) - preSolve = 10; - else - preSolveFile = true; + case CbcParam::REDSPLITCUTS: + defaultSettings = false; // user knows what she is doing + redsplitMode = mode; break; - case CLP_PARAM_STR_PFI: - lpSolver->factorization()->setForrestTomlin(action == 0); + case CbcParam::REDSPLIT2CUTS: + defaultSettings = false; // user knows what she is doing + redsplit2Mode = mode; break; - case CLP_PARAM_STR_FACTORIZATION: - lpSolver->factorization()->forceOtherFactorization(action); + case CbcParam::GMICUTS: + defaultSettings = false; // user knows what she is doing + GMIMode = mode; break; - case CLP_PARAM_STR_CRASH: - doCrash = action; + case CbcParam::FLOWCUTS: + defaultSettings = false; // user knows what she is doing + flowMode = mode; break; - case CLP_PARAM_STR_VECTOR: - doVector = action; + case CbcParam::MIRCUTS: + defaultSettings = false; // user knows what she is doing + mixedMode = mode; break; - case CLP_PARAM_STR_MESSAGES: - lpSolver->messageHandler()->setPrefix(action != 0); + case CbcParam::TWOMIRCUTS: + defaultSettings = false; // user knows what she is doing + twomirMode = mode; break; - case CLP_PARAM_STR_CHOLESKY: - choleskyType = action; + case CbcParam::LANDPCUTS: + defaultSettings = false; // user knows what she is doing + landpMode = mode; break; - case CLP_PARAM_STR_GAMMA: - gamma = action; + case CbcParam::RESIDCAPCUTS: + defaultSettings = false; // user knows what she is doing + residualCapacityMode = mode; break; - case CLP_PARAM_STR_BARRIERSCALE: - scaleBarrier = action; + case CbcParam::ZEROHALFCUTS: + defaultSettings = false; // user knows what she is doing + zerohalfMode = mode; break; - case CLP_PARAM_STR_KKT: - doKKT = action; + case CbcParam::ROUNDING: + defaultSettings = false; // user knows what she is doing break; - case CLP_PARAM_STR_CROSSOVER: - crossover = action; + case CbcParam::FPUMP: + defaultSettings = false; // user knows what she is doing break; - case CLP_PARAM_STR_TIME_MODE: - model_.setUseElapsedTime(action != 0); + case CbcParam::RINS: break; - case CBC_PARAM_STR_SOS: - doSOS = action; + case CbcParam::DINS: break; - case CBC_PARAM_STR_CLQSTRENGTHENING: - clqstrAction = value; + case CbcParam::RENS: break; - case CBC_PARAM_STR_USECGRAPH: - cgraphAction = value; + case CbcParam::CUTSTRATEGY: + gomoryMode = mode; + probingMode = mode; + knapsackMode = mode; + cliqueMode = mode; + flowMode = mode; + mixedMode = mode; + twomirMode = mode; + zerohalfMode = mode; + oddWheelMode = mode; + parameters[CbcParam::GOMORYCUTS]->setVal(mode); + parameters[CbcParam::PROBINGCUTS]->setVal(mode); + parameters[CbcParam::KNAPSACKCUTS]->setVal(mode); + parameters[CbcParam::CLIQUECUTS]->setVal(mode); + parameters[CbcParam::FLOWCUTS]->setVal(mode); + parameters[CbcParam::MIRCUTS]->setVal(mode); + parameters[CbcParam::TWOMIRCUTS]->setVal(mode); + parameters[CbcParam::ZEROHALFCUTS]->setVal(mode); + parameters[CbcParam::ODDWHEELCUTS]->setVal(mode); + if (!mode) { + // switch off clique strengthening + clqstrMode = "off"; + } break; - case CBC_PARAM_STR_CLIQUECUTS: - defaultSettings = false; // user knows what she is doing - cliqueAction = action; + case CbcParam::HEURISTICSTRATEGY: + parameters[CbcParam::ROUNDING]->setVal(mode); + parameters[CbcParam::GREEDY]->setVal(mode); + parameters[CbcParam::COMBINE]->setVal(mode); + // parameters[CbcParam::LOCALTREE,numberParameters_,parameters)]->setVal(mode); + parameters[CbcParam::FPUMP]->setVal(mode); + parameters[CbcParam::DIVINGC]->setVal(mode); + parameters[CbcParam::RINS]->setVal(mode); break; - case CBC_PARAM_STR_ODDWHEELCUTS: + case CbcParam::GREEDY: + case CbcParam::DIVINGS: + case CbcParam::DIVINGC: + case CbcParam::DIVINGF: + case CbcParam::DIVINGG: + case CbcParam::DIVINGL: + case CbcParam::DIVINGP: + case CbcParam::DIVINGV: + case CbcParam::COMBINE: + case CbcParam::PIVOTANDCOMPLEMENT: + case CbcParam::PIVOTANDFIX: + case CbcParam::RANDROUND: + case CbcParam::LOCALTREE: + case CbcParam::NAIVE: + case CbcParam::CPX: defaultSettings = false; // user knows what she is doing - oddWheelAction = action; break; - case CBC_PARAM_STR_GOMORYCUTS: - defaultSettings = false; // user knows what she is doing - gomoryAction = action; + case CbcParam::BRANCHPRIORITY: + useCosts = mode; break; - case CBC_PARAM_STR_PROBINGCUTS: - defaultSettings = false; // user knows what she is doing - probingAction = action; + case CbcParam::NODESTRATEGY: + nodeStrategy = mode; break; - case CBC_PARAM_STR_KNAPSACKCUTS: - defaultSettings = false; // user knows what she is doing - knapsackAction = action; + case CbcParam::PREPROCESS: + preProcess = mode; break; - case CBC_PARAM_STR_REDSPLITCUTS: - defaultSettings = false; // user knows what she is doing - redsplitAction = action; + case CbcParam::TIMEMODE: + model_.setUseElapsedTime(mode != 0); break; - case CBC_PARAM_STR_REDSPLIT2CUTS: - defaultSettings = false; // user knows what she is doing - redsplit2Action = action; + default: + // abort(); break; - case CBC_PARAM_STR_GMICUTS: - defaultSettings = false; // user knows what she is doing - GMIAction = action; + } + } else if (clpParam->type() == CoinParam::paramKwd) { + if (status = clpParam->readValue(inputQueue, field, &message)){ + printGeneralMessage(model_, message); + continue; + } + if (clpParam->setVal(field, &message)){ + printGeneralMessage(model_, message); + continue; + } + int mode = clpParam->kwdToMode(field); + // for now hard wired + switch (clpParamCode) { + case ClpParam::DUALPIVOT: + if (mode == 0) { + ClpDualRowSteepest steep(3); + lpSolver->setDualRowPivotAlgorithm(steep); + } else if (mode == 1) { + ClpDualRowDantzig dantzig; + // ClpDualRowSteepest dantzig(5); + lpSolver->setDualRowPivotAlgorithm(dantzig); + } else if (mode == 2) { + // partial steep + ClpDualRowSteepest steep(2); + lpSolver->setDualRowPivotAlgorithm(steep); + } else if (mode == 3) { + ClpDualRowSteepest steep; + lpSolver->setDualRowPivotAlgorithm(steep); + } else if (mode == 4) { + // Positive edge steepest + ClpPEDualRowSteepest p(fabs(clpParameters[ClpParam::PSI]->dblVal())); + lpSolver->setDualRowPivotAlgorithm(p); + } else if (mode == 5) { + // Positive edge Dantzig + ClpPEDualRowDantzig p(fabs(clpParameters[ClpParam::PSI]->dblVal())); + lpSolver->setDualRowPivotAlgorithm(p); + } break; - case CBC_PARAM_STR_FLOWCUTS: - defaultSettings = false; // user knows what she is doing - flowAction = action; + case ClpParam::PRIMALPIVOT: + if (mode == 0) { + ClpPrimalColumnSteepest steep(3); + lpSolver->setPrimalColumnPivotAlgorithm(steep); + } else if (mode == 1) { + ClpPrimalColumnSteepest steep(0); + lpSolver->setPrimalColumnPivotAlgorithm(steep); + } else if (mode == 2) { + ClpPrimalColumnDantzig dantzig; + lpSolver->setPrimalColumnPivotAlgorithm(dantzig); + } else if (mode == 3) { + ClpPrimalColumnSteepest steep(4); + lpSolver->setPrimalColumnPivotAlgorithm(steep); + } else if (mode == 4) { + ClpPrimalColumnSteepest steep(1); + lpSolver->setPrimalColumnPivotAlgorithm(steep); + } else if (mode == 5) { + ClpPrimalColumnSteepest steep(2); + lpSolver->setPrimalColumnPivotAlgorithm(steep); + } else if (mode == 6) { + ClpPrimalColumnSteepest steep(10); + lpSolver->setPrimalColumnPivotAlgorithm(steep); + } else if (mode == 7) { + // Positive edge steepest + ClpPEPrimalColumnSteepest p(fabs(clpParameters[ClpParam::PSI]->dblVal())); + lpSolver->setPrimalColumnPivotAlgorithm(p); + } else if (mode == 8) { + // Positive edge Dantzig + ClpPEPrimalColumnDantzig p(fabs(clpParameters[ClpParam::PSI]->dblVal())); + lpSolver->setPrimalColumnPivotAlgorithm(p); + } break; - case CBC_PARAM_STR_MIXEDCUTS: - defaultSettings = false; // user knows what she is doing - mixedAction = action; + case ClpParam::SCALING: + lpSolver->scaling(mode); + solver->setHintParam(OsiDoScale, mode != 0, OsiHintTry); + doScaling = mode; break; - case CBC_PARAM_STR_TWOMIRCUTS: - defaultSettings = false; // user knows what she is doing - twomirAction = action; + case ClpParam::AUTOSCALE: + lpSolver->setAutomaticScaling(mode != 0); break; - case CBC_PARAM_STR_LANDPCUTS: - defaultSettings = false; // user knows what she is doing - landpAction = action; + case ClpParam::SPARSEFACTOR: + lpSolver->setSparseFactorization((1 - mode) != 0); break; - case CBC_PARAM_STR_RESIDCUTS: - defaultSettings = false; // user knows what she is doing - residualCapacityAction = action; + case ClpParam::BIASLU: + lpSolver->factorization()->setBiasLU(mode); break; - case CBC_PARAM_STR_ZEROHALFCUTS: - defaultSettings = false; // user knows what she is doing - zerohalfAction = action; + case ClpParam::PERTURBATION: + if (mode == 0) + lpSolver->setPerturbation(50); + else + lpSolver->setPerturbation(100); break; - case CBC_PARAM_STR_ROUNDING: - defaultSettings = false; // user knows what she is doing + case ClpParam::KEEPNAMES: + keepImportNames = 1 - mode; break; - case CBC_PARAM_STR_FPUMP: - defaultSettings = false; // user knows what she is doing + case ClpParam::PRESOLVE: + if (mode == 0) + preSolve = 5; + else if (mode == 1) + preSolve = 0; + else if (mode == 2) + preSolve = 10; + else + preSolveFile = true; break; - case CBC_PARAM_STR_RINS: + case ClpParam::PFI: + lpSolver->factorization()->setForrestTomlin(mode == 0); break; - case CBC_PARAM_STR_DINS: + case ClpParam::FACTORIZATION: + lpSolver->factorization()->forceOtherFactorization(mode); break; - case CBC_PARAM_STR_RENS: + case ClpParam::CRASH: + doCrash = mode; break; - case CBC_PARAM_STR_CUTSSTRATEGY: - gomoryAction = action; - probingAction = action; - knapsackAction = action; - cliqueAction = action; - flowAction = action; - mixedAction = action; - twomirAction = action; - zerohalfAction = action; - oddWheelAction = action; - parameters_[whichParam(CBC_PARAM_STR_GOMORYCUTS, parameters_)].setCurrentOption(action); - parameters_[whichParam(CBC_PARAM_STR_PROBINGCUTS, parameters_)].setCurrentOption(action); - parameters_[whichParam(CBC_PARAM_STR_KNAPSACKCUTS, parameters_)].setCurrentOption(action); - parameters_[whichParam(CBC_PARAM_STR_CLIQUECUTS, parameters_)].setCurrentOption(action); - parameters_[whichParam(CBC_PARAM_STR_FLOWCUTS, parameters_)].setCurrentOption(action); - parameters_[whichParam(CBC_PARAM_STR_MIXEDCUTS, parameters_)].setCurrentOption(action); - parameters_[whichParam(CBC_PARAM_STR_TWOMIRCUTS, parameters_)].setCurrentOption(action); - parameters_[whichParam(CBC_PARAM_STR_ZEROHALFCUTS, parameters_)].setCurrentOption(action); - parameters_[whichParam(CBC_PARAM_STR_ODDWHEELCUTS, parameters_)].setCurrentOption(action); - if (!action) { - // switch off clique strengthening - clqstrAction = "off"; - } + case ClpParam::VECTOR: + doVector = mode; break; - case CBC_PARAM_STR_HEURISTICSTRATEGY: - parameters_[whichParam(CBC_PARAM_STR_ROUNDING, parameters_)].setCurrentOption(action); - parameters_[whichParam(CBC_PARAM_STR_GREEDY, parameters_)].setCurrentOption(action); - parameters_[whichParam(CBC_PARAM_STR_COMBINE, parameters_)].setCurrentOption(action); - //parameters_[whichParam(CBC_PARAM_STR_LOCALTREE,numberParameters_,parameters_)].setCurrentOption(action); - parameters_[whichParam(CBC_PARAM_STR_FPUMP, parameters_)].setCurrentOption(action); - parameters_[whichParam(CBC_PARAM_STR_DIVINGC, parameters_)].setCurrentOption(action); - parameters_[whichParam(CBC_PARAM_STR_RINS, parameters_)].setCurrentOption(action); + case ClpParam::MESSAGES: + lpSolver->messageHandler()->setPrefix(mode != 0); break; - case CBC_PARAM_STR_GREEDY: - case CBC_PARAM_STR_DIVINGS: - case CBC_PARAM_STR_DIVINGC: - case CBC_PARAM_STR_DIVINGF: - case CBC_PARAM_STR_DIVINGG: - case CBC_PARAM_STR_DIVINGL: - case CBC_PARAM_STR_DIVINGP: - case CBC_PARAM_STR_DIVINGV: - case CBC_PARAM_STR_COMBINE: - case CBC_PARAM_STR_PIVOTANDCOMPLEMENT: - case CBC_PARAM_STR_PIVOTANDFIX: - case CBC_PARAM_STR_RANDROUND: - case CBC_PARAM_STR_LOCALTREE: - case CBC_PARAM_STR_NAIVE: - case CBC_PARAM_STR_CPX: - defaultSettings = false; // user knows what she is doing + case ClpParam::CHOLESKY: + choleskyType = mode; + break; + case ClpParam::GAMMA: + gamma = mode; break; - case CBC_PARAM_STR_COSTSTRATEGY: - useCosts = action; + case ClpParam::BARRIERSCALE: + scaleBarrier = mode; break; - case CBC_PARAM_STR_NODESTRATEGY: - nodeStrategy = action; + case ClpParam::KKT: + doKKT = mode; break; - case CBC_PARAM_STR_PREPROCESS: - preProcess = action; + case ClpParam::CROSSOVER: + crossover = mode; break; default: - //abort(); + // abort(); break; - } - } - } else { - // action - if (type == CLP_PARAM_ACTION_EXIT) { - if (statusUserFunction_[0]) { - if (info.numberIntegers || info.numberBinary) { - // integer - } else { - // linear + } + } else if (cbcParam->type() == CoinParam::paramDir){ + if (status = cbcParam->readValue(inputQueue, field, &message)){ + printGeneralMessage(model_, message); + continue; + } + if (cbcParam->setVal(field, &message)){ + printGeneralMessage(model_, message); + continue; + } + } else if (cbcParam->type() == CoinParam::paramFile){ + if (status = cbcParam->readValue(inputQueue, field, &message)){ + printGeneralMessage(model_, message); + continue; + } + if (cbcParam->setVal(field, &message)){ + printGeneralMessage(model_, message); + continue; + } + } else { + // action + if (cbcParamCode == CbcParam::EXIT || + cbcParamCode == CbcParam::STOP || + cbcParamCode == CbcParam::QUIT || + cbcParamCode == CbcParam::END) { + if (statusUserFunction_[0]) { + if (info && (info->numberIntegers || info->numberBinary)) { + // integer + } else { + // linear + } + writeAmpl(info); + freeArrays2(info); + freeArgs(info); + } + break; // stop all + } + + switch (clpParamCode) { + case ClpParam::DUALSIMPLEX: + case ClpParam::PRIMALSIMPLEX: + case ClpParam::BARRIER:{ + if (!goodModel) { + printGeneralWarning(model_, "** Current model not valid\n"); + continue; } - writeAmpl(&info); - freeArrays2(&info); - freeArgs(&info); - } - break; // stop all - } - switch (type) { - case CLP_PARAM_ACTION_DUALSIMPLEX: - case CLP_PARAM_ACTION_PRIMALSIMPLEX: - case CLP_PARAM_ACTION_SOLVECONTINUOUS: - case CLP_PARAM_ACTION_BARRIER: - if (goodModel) { // Say not in integer integerStatus = -1; - double objScale = parameters_[whichParam(CLP_PARAM_DBL_OBJSCALE2, parameters_)].doubleValue(); + double objScale = clpParameters[ClpParam::OBJSCALE2]->dblVal(); // deal with positive edge - double psi = parameters_[whichParam(CLP_PARAM_DBL_PSI, parameters_)].doubleValue(); + double psi = clpParameters[ClpParam::PSI]->dblVal(); if (psi > 0.0) { - ClpDualRowPivot *dualp = lpSolver->dualRowPivot(); - ClpDualRowSteepest *d1 = dynamic_cast< ClpDualRowSteepest * >(dualp); - ClpDualRowDantzig *d2 = dynamic_cast< ClpDualRowDantzig * >(dualp); - if (d1) { - ClpPEDualRowSteepest p(psi, d1->mode()); - lpSolver->setDualRowPivotAlgorithm(p); - } else if (d2) { - ClpPEDualRowDantzig p(psi); - lpSolver->setDualRowPivotAlgorithm(p); - } - ClpPrimalColumnPivot *primalp = lpSolver->primalColumnPivot(); - ClpPrimalColumnSteepest *p1 = dynamic_cast< ClpPrimalColumnSteepest * >(primalp); - ClpPrimalColumnDantzig *p2 = dynamic_cast< ClpPrimalColumnDantzig * >(primalp); - if (p1) { - ClpPEPrimalColumnSteepest p(psi, p1->mode()); - lpSolver->setPrimalColumnPivotAlgorithm(p); - } else if (p2) { - ClpPEPrimalColumnDantzig p(psi); - lpSolver->setPrimalColumnPivotAlgorithm(p); - } + ClpDualRowPivot *dualp = lpSolver->dualRowPivot(); + ClpDualRowSteepest *d1 = + dynamic_cast(dualp); + ClpDualRowDantzig *d2 = + dynamic_cast(dualp); + if (d1) { + ClpPEDualRowSteepest p(psi, d1->mode()); + lpSolver->setDualRowPivotAlgorithm(p); + } else if (d2) { + ClpPEDualRowDantzig p(psi); + lpSolver->setDualRowPivotAlgorithm(p); + } + ClpPrimalColumnPivot *primalp = lpSolver->primalColumnPivot(); + ClpPrimalColumnSteepest *p1 = + dynamic_cast(primalp); + ClpPrimalColumnDantzig *p2 = + dynamic_cast(primalp); + if (p1) { + ClpPEPrimalColumnSteepest p(psi, p1->mode()); + lpSolver->setPrimalColumnPivotAlgorithm(p); + } else if (p2) { + ClpPEPrimalColumnDantzig p(psi); + lpSolver->setPrimalColumnPivotAlgorithm(p); + } } if (objScale != 1.0) { - int iColumn; - int numberColumns = lpSolver->numberColumns(); - double *dualColumnSolution = lpSolver->dualColumnSolution(); - ClpObjective *obj = lpSolver->objectiveAsObject(); - assert(dynamic_cast< ClpLinearObjective * >(obj)); - double offset; - double *objective = obj->gradient(NULL, NULL, offset, true); - for (iColumn = 0; iColumn < numberColumns; iColumn++) { - dualColumnSolution[iColumn] *= objScale; - objective[iColumn] *= objScale; - ; - } - int iRow; - int numberRows = lpSolver->numberRows(); - double *dualRowSolution = lpSolver->dualRowSolution(); - for (iRow = 0; iRow < numberRows; iRow++) - dualRowSolution[iRow] *= objScale; - lpSolver->setObjectiveOffset(objScale * lpSolver->objectiveOffset()); + int iColumn; + int numberColumns = lpSolver->numberColumns(); + double *dualColumnSolution = lpSolver->dualColumnSolution(); + ClpObjective *obj = lpSolver->objectiveAsObject(); + assert(dynamic_cast(obj)); + double offset; + double *objective = obj->gradient(NULL, NULL, offset, true); + for (iColumn = 0; iColumn < numberColumns; iColumn++) { + dualColumnSolution[iColumn] *= objScale; + objective[iColumn] *= objScale; + ; + } + int iRow; + int numberRows = lpSolver->numberRows(); + double *dualRowSolution = lpSolver->dualRowSolution(); + for (iRow = 0; iRow < numberRows; iRow++) + dualRowSolution[iRow] *= objScale; + lpSolver->setObjectiveOffset(objScale * + lpSolver->objectiveOffset()); } ClpSolve::SolveType method; ClpSolve::PresolveType presolveType; ClpSimplex *model2 = lpSolver; if (dualize) { - bool tryIt = true; - double fractionColumn = 1.0; - double fractionRow = 1.0; - if (dualize == 3) { - dualize = 1; - int numberColumns = lpSolver->numberColumns(); - int numberRows = lpSolver->numberRows(); - if (numberRows < 50000 || 5 * numberColumns > numberRows) { - tryIt = false; - } else { - fractionColumn = 0.1; - fractionRow = 0.1; - } - } - if (tryIt) { - model2 = static_cast< ClpSimplexOther * >(model2)->dualOfModel(fractionRow, fractionColumn); - if (model2) { - sprintf(generalPrint, "Dual of model has %d rows and %d columns", - model2->numberRows(), model2->numberColumns()); - generalMessageHandler->message(CLP_GENERAL, generalMessages) - << generalPrint - << CoinMessageEol; - model2->setOptimizationDirection(1.0); - } else { - model2 = lpSolver; + bool tryIt = true; + double fractionColumn = 1.0; + double fractionRow = 1.0; + if (dualize == 3) { + dualize = 1; + int numberColumns = lpSolver->numberColumns(); + int numberRows = lpSolver->numberRows(); + if (numberRows < 50000 || 5 * numberColumns > numberRows) { + tryIt = false; + } else { + fractionColumn = 0.1; + fractionRow = 0.1; + } + } + if (tryIt) { + model2 = static_cast(model2)->dualOfModel( + fractionRow, fractionColumn); + if (model2) { + buffer.str(""); + buffer << "Dual of model has " << model2->numberRows() + << " rows and " << model2->numberColumns() + << " columns"; + printGeneralMessage(model_, buffer.str()); + model2->setOptimizationDirection(1.0); + } else { + model2 = lpSolver; + dualize = 0; + } + } else { dualize = 0; - } - } else { - dualize = 0; - } + } + } + if (parameters.noPrinting()){ + lpSolver->setLogLevel(0); } - if (noPrinting_) - lpSolver->setLogLevel(0); ClpSolve solveOptions; solveOptions.setPresolveActions(presolveOptions); solveOptions.setSubstitution(substitution); if (preSolve != 5 && preSolve) { - presolveType = ClpSolve::presolveNumber; - if (preSolve < 0) { - preSolve = -preSolve; - if (preSolve <= 100) { - presolveType = ClpSolve::presolveNumber; - sprintf(generalPrint, "Doing %d presolve passes - picking up non-costed slacks", - preSolve); - generalMessageHandler->message(CLP_GENERAL, generalMessages) - << generalPrint - << CoinMessageEol; - solveOptions.setDoSingletonColumn(true); - } else { - preSolve -= 100; - presolveType = ClpSolve::presolveNumberCost; - sprintf(generalPrint, "Doing %d presolve passes - picking up costed slacks", - preSolve); - generalMessageHandler->message(CLP_GENERAL, generalMessages) - << generalPrint - << CoinMessageEol; - } - } + presolveType = ClpSolve::presolveNumber; + if (preSolve < 0) { + preSolve = -preSolve; + if (preSolve <= 100) { + presolveType = ClpSolve::presolveNumber; + buffer.str(""); + buffer << "Doing " << preSolve + << " presolve passes - picking up non-costed slacks"; + printGeneralMessage(model_, buffer.str()); + solveOptions.setDoSingletonColumn(true); + } else { + preSolve -= 100; + presolveType = ClpSolve::presolveNumberCost; + buffer.str(""); + buffer << "Doing " << preSolve + << " presolve passes - picking up non-costed slacks"; + printGeneralMessage(model_, buffer.str()); + } + } } else if (preSolve) { - presolveType = ClpSolve::presolveOn; + presolveType = ClpSolve::presolveOn; } else { - presolveType = ClpSolve::presolveOff; + presolveType = ClpSolve::presolveOff; } solveOptions.setPresolveType(presolveType, preSolve); - if (type == CLP_PARAM_ACTION_DUALSIMPLEX || type == CLP_PARAM_ACTION_SOLVECONTINUOUS) { - method = ClpSolve::useDual; - } else if (type == CLP_PARAM_ACTION_PRIMALSIMPLEX) { - method = ClpSolve::usePrimalorSprint; + if (clpParamCode == ClpParam::DUALSIMPLEX) { + method = ClpSolve::useDual; + } else if (clpParamCode == ClpParam::PRIMALSIMPLEX) { + method = ClpSolve::usePrimalorSprint; } else { - method = ClpSolve::useBarrier; - if (crossover == 1) { - method = ClpSolve::useBarrierNoCross; - } else if (crossover == 2) { - ClpObjective *obj = lpSolver->objectiveAsObject(); - if (obj->type() > 1) { + method = ClpSolve::useBarrier; + if (crossover == 1) { method = ClpSolve::useBarrierNoCross; - presolveType = ClpSolve::presolveOff; - solveOptions.setPresolveType(presolveType, preSolve); - } - } + } else if (crossover == 2) { + ClpObjective *obj = lpSolver->objectiveAsObject(); + if (obj->type() > 1) { + method = ClpSolve::useBarrierNoCross; + presolveType = ClpSolve::presolveOff; + solveOptions.setPresolveType(presolveType, preSolve); + } + } } solveOptions.setSolveType(method); if (preSolveFile) - presolveOptions |= 0x40000000; + presolveOptions |= 0x40000000; solveOptions.setSpecialOption(4, presolveOptions); solveOptions.setSpecialOption(5, printOptions); if (doVector) { - ClpMatrixBase *matrix = lpSolver->clpMatrix(); - if (dynamic_cast< ClpPackedMatrix * >(matrix)) { - ClpPackedMatrix *clpMatrix = dynamic_cast< ClpPackedMatrix * >(matrix); - clpMatrix->makeSpecialColumnCopy(); - } + ClpMatrixBase *matrix = lpSolver->clpMatrix(); + if (dynamic_cast(matrix)) { + ClpPackedMatrix *clpMatrix = + dynamic_cast(matrix); + clpMatrix->makeSpecialColumnCopy(); + } } if (method == ClpSolve::useDual) { // dual if (doCrash) solveOptions.setSpecialOption(0, 1, doCrash); // crash else if (doIdiot) - solveOptions.setSpecialOption(0, 2, doIdiot); // possible idiot + solveOptions.setSpecialOption(0, 2, + doIdiot); // possible idiot } else if (method == ClpSolve::usePrimalorSprint) { // primal // if slp turn everything off @@ -3001,7 +2827,8 @@ int CbcMain1(int argc, const char *argv[], if (doSprint == 0) solveOptions.setSpecialOption(1, 4); // all slack else - solveOptions.setSpecialOption(1, 9); // all slack or sprint + solveOptions.setSpecialOption(1, + 9); // all slack or sprint } else { if (doSprint == 0) solveOptions.setSpecialOption(1, 8); // all slack or idiot @@ -3011,7 +2838,8 @@ int CbcMain1(int argc, const char *argv[], } if (basisHasValues == -1) solveOptions.setSpecialOption(1, 11); // switch off values - } else if (method == ClpSolve::useBarrier || method == ClpSolve::useBarrierNoCross) { + } else if (method == ClpSolve::useBarrier || + method == ClpSolve::useBarrierNoCross) { int barrierOptions = choleskyType; if (scaleBarrier) barrierOptions |= 8; @@ -3026,20 +2854,24 @@ int CbcMain1(int argc, const char *argv[], model2->setMaximumSeconds(model_.getMaximumSeconds()); #ifdef COIN_HAS_LINK OsiSolverInterface *coinSolver = model_.solver(); - OsiSolverLink *linkSolver = dynamic_cast< OsiSolverLink * >(coinSolver); + OsiSolverLink *linkSolver = + dynamic_cast(coinSolver); if (!linkSolver) { model2->initialSolve(solveOptions); } else { // special solver - int testOsiOptions = parameters_[whichParam(CBC_PARAM_INT_TESTOSI, parameters_)].intValue(); + int testOsiOptions = parameters[CbcParam::TESTOSI]->intVal(); double *solution = NULL; if (testOsiOptions < 10) { - solution = linkSolver->nonlinearSLP(slpValue > 0 ? slpValue : 20, 1.0e-5); + solution = linkSolver->nonlinearSLP( + slpValue > 0 ? slpValue : 20, 1.0e-5); } else if (testOsiOptions >= 10) { CoinModel coinModel = *linkSolver->coinModel(); - ClpSimplex *tempModel = approximateSolution(coinModel, slpValue > 0 ? slpValue : 50, 1.0e-5, 0); + ClpSimplex *tempModel = approximateSolution( + coinModel, slpValue > 0 ? slpValue : 50, 1.0e-5, 0); assert(tempModel); - solution = CoinCopyOfArray(tempModel->primalColumnSolution(), coinModel.numberColumns()); + solution = CoinCopyOfArray(tempModel->primalColumnSolution(), + coinModel.numberColumns()); model2->setObjectiveValue(tempModel->objectiveValue()); model2->setProblemStatus(tempModel->problemStatus()); model2->setSecondaryStatus(tempModel->secondaryStatus()); @@ -3047,7 +2879,9 @@ int CbcMain1(int argc, const char *argv[], } if (solution) { memcpy(model2->primalColumnSolution(), solution, - CoinMin(model2->numberColumns(), linkSolver->coinModel()->numberColumns()) * sizeof(double)); + CoinMin(model2->numberColumns(), + linkSolver->coinModel()->numberColumns()) * + sizeof(double)); delete[] solution; } else { printf("No nonlinear solution\n"); @@ -3059,55 +2893,53 @@ int CbcMain1(int argc, const char *argv[], { // map states /* clp status - -1 - unknown e.g. before solve or if postSolve says not optimal - 0 - optimal - 1 - primal infeasible + -1 - unknown e.g. before solve or if + postSolve says not optimal 0 - optimal 1 - primal infeasible 2 - dual infeasible 3 - stopped on iterations or time 4 - stopped due to errors - 5 - stopped by event handler (virtual int ClpEventHandler::event()) */ + 5 - stopped by event handler (virtual int + ClpEventHandler::event()) */ /* cbc status -1 before branchAndBound - 0 finished - check isProvenOptimal or isProvenInfeasible to see if solution found - (or check value of best solution) - 1 stopped - on maxnodes, maxsols, maxtime + 0 finished - check isProvenOptimal or + isProvenInfeasible to see if solution found (or check value + of best solution) 1 stopped - on maxnodes, maxsols, maxtime 2 difficulties so run was abandoned (5 event user programmed event occurred) */ /* clp secondary status of problem - may get extended 0 - none - 1 - primal infeasible because dual limit reached OR probably primal - infeasible but can't prove it (main status 4) - 2 - scaled problem optimal - unscaled problem has primal infeasibilities - 3 - scaled problem optimal - unscaled problem has dual infeasibilities - 4 - scaled problem optimal - unscaled problem has primal and dual infeasibilities - 5 - giving up in primal with flagged variables - 6 - failed due to empty problem check - 7 - postSolve says not optimal - 8 - failed due to bad element check - 9 - status was 3 and stopped on time - 100 up - translation of enum from ClpEventHandler + 1 - primal infeasible because dual limit + reached OR probably primal infeasible but can't prove it + (main status 4) 2 - scaled problem optimal - unscaled problem + has primal infeasibilities 3 - scaled problem optimal - + unscaled problem has dual infeasibilities 4 - scaled problem + optimal - unscaled problem has primal and dual + infeasibilities 5 - giving up in primal with flagged + variables 6 - failed due to empty problem check 7 - postSolve + says not optimal 8 - failed due to bad element check 9 - + status was 3 and stopped on time 100 up - translation of enum + from ClpEventHandler */ /* cbc secondary status of problem -1 unset (status_ will also be -1) 0 search completed with solution - 1 linear relaxation not feasible (or worse than cutoff) - 2 stopped on gap - 3 stopped on nodes - 4 stopped on time - 5 stopped on user event - 6 stopped on solutions - 7 linear relaxation unbounded - 8 stopped on iterations limit + 1 linear relaxation not feasible (or worse + than cutoff) 2 stopped on gap 3 stopped on nodes 4 stopped on + time 5 stopped on user event 6 stopped on solutions 7 linear + relaxation unbounded 8 stopped on iterations limit */ int iStatus = model2->status(); int iStatus2 = model2->secondaryStatus(); if (iStatus == 0) { iStatus2 = 0; - if (found.type() == CBC_PARAM_ACTION_BAB) { + if (cbcParamCode == CbcParam::BAB) { // set best solution in model as no integers - model_.setBestSolution(model2->primalColumnSolution(), - model2->numberColumns(), - model2->getObjValue() * model2->getObjSense()); + model_.setBestSolution( + model2->primalColumnSolution(), model2->numberColumns(), + model2->getObjValue() * model2->getObjSense()); + // Cutoff + model_.solver()->setDblParam(OsiDualObjectiveLimit, 1.0e100); } } else if (iStatus == 1) { iStatus = 0; @@ -3127,29 +2959,34 @@ int CbcMain1(int argc, const char *argv[], } model_.setProblemStatus(iStatus); model_.setSecondaryStatus(iStatus2); - if ((iStatus == 2 || iStatus2 > 0) && !noPrinting_) { - std::string statusName[] = { "", "Stopped on ", "Run abandoned", "", "", "User ctrl-c" }; - std::string minor[] = { "Optimal solution found", "Linear relaxation infeasible", "Optimal solution found (within gap tolerance)", "node limit", "time limit", "user ctrl-c", "solution limit", "Linear relaxation unbounded", "iterations limit", "Problem proven infeasible" }; - sprintf(generalPrint, "\nResult - %s%s\n\n", - statusName[iStatus].c_str(), - minor[iStatus2].c_str()); - sprintf(generalPrint + strlen(generalPrint), - "Enumerated nodes: 0\n"); - sprintf(generalPrint + strlen(generalPrint), - "Total iterations: 0\n"); + if ((iStatus == 2 || iStatus2 > 0) && parameters.noPrinting()) { + std::string statusName[] = { + "", "Stopped on ", "Run abandoned", "", + "", "User ctrl-c"}; + std::string minor[] = { + "Optimal solution found", + "Linear relaxation infeasible", + "Optimal solution found (within gap tolerance)", + "node limit", + "time limit", + "user ctrl-c", + "solution limit", + "Linear relaxation unbounded", + "iterations limit", + "Problem proven infeasible"}; + buffer.str(""); + buffer << std::endl << "Result - " << statusName[iStatus].c_str() + << minor[iStatus2].c_str() << std::endl << std::endl; + buffer << "Enumerated nodes: 0" << std::endl; + buffer << "Total iterations: 0" << std::endl; #if CBC_QUIET == 0 - sprintf(generalPrint + strlen(generalPrint), - "Time (CPU seconds): %.2f\n", - CoinCpuTime() - time0); - sprintf(generalPrint + strlen(generalPrint), - "Time (Wallclock Seconds): %.2f\n", - CoinGetTimeOfDay() - time0Elapsed); -#endif - generalMessageHandler->message(CLP_GENERAL, generalMessages) - << generalPrint - << CoinMessageEol; - } - //assert (lpSolver==clpSolver->getModelPtr()); + buffer << "Time (CPU seconds): " << CoinCpuTime() - time0 << std::endl; + buffer << "Time (Wallclock Seconds): " << CoinGetTimeOfDay() - time0Elapsed + << std::endl; +#endif + printGeneralMessage(model_, buffer.str()); + } + // assert (lpSolver==clpSolver->getModelPtr()); assert(clpSolver == model_.solver()); clpSolver->setWarmStart(NULL); // and in babModel if exists @@ -3167,7 +3004,9 @@ int CbcMain1(int argc, const char *argv[], } basisHasValues = 1; if (dualize) { - int returnCode = static_cast< ClpSimplexOther * >(lpSolver)->restoreFromDual(model2); + int returnCode = + static_cast(lpSolver)->restoreFromDual( + model2); if (model2->status() == 3) returnCode = 0; delete model2; @@ -3204,305 +3043,522 @@ int CbcMain1(int argc, const char *argv[], pos += sprintf(buf + pos, "status unknown,"); iStat = 6; } - info.problemStatus = iStat; - info.objValue = value; - pos += sprintf(buf + pos, " objective %.*g", ampl_obj_prec(), - value); - sprintf(buf + pos, "\n%d iterations", - model2->getIterationCount()); - free(info.primalSolution); - int numberColumns = model2->numberColumns(); - info.primalSolution = reinterpret_cast< double * >(malloc(numberColumns * sizeof(double))); - CoinCopyN(model2->primalColumnSolution(), numberColumns, info.primalSolution); - int numberRows = model2->numberRows(); - free(info.dualSolution); - info.dualSolution = reinterpret_cast< double * >(malloc(numberRows * sizeof(double))); - CoinCopyN(model2->dualRowSolution(), numberRows, info.dualSolution); - CoinWarmStartBasis *basis = model2->getBasis(); - free(info.rowStatus); - info.rowStatus = reinterpret_cast< int * >(malloc(numberRows * sizeof(int))); - free(info.columnStatus); - info.columnStatus = reinterpret_cast< int * >(malloc(numberColumns * sizeof(int))); - // Put basis in - int i; - // free,basic,ub,lb are 0,1,2,3 - for (i = 0; i < numberRows; i++) { - CoinWarmStartBasis::Status status = basis->getArtifStatus(i); - info.rowStatus[i] = status; - } - for (i = 0; i < numberColumns; i++) { - CoinWarmStartBasis::Status status = basis->getStructStatus(i); - info.columnStatus[i] = status; - } - // put buffer into info - strcpy(info.buffer, buf); - delete basis; - } - } else { - sprintf(generalPrint, "** Current model not valid"); - printGeneralMessage(model_, generalPrint); + if (info){ + info->problemStatus = iStat; + info->objValue = value; + pos += sprintf(buf + pos, " objective %.*g", ampl_obj_prec(), + value); + sprintf(buf + pos, "\n%d iterations", + model2->getIterationCount()); + free(info->primalSolution); + int numberColumns = model2->numberColumns(); + info->primalSolution = reinterpret_cast( + malloc(numberColumns * sizeof(double))); + CoinCopyN(model2->primalColumnSolution(), numberColumns, + info->primalSolution); + int numberRows = model2->numberRows(); + free(info->dualSolution); + info->dualSolution = reinterpret_cast( + malloc(numberRows * sizeof(double))); + CoinCopyN(model2->dualRowSolution(), numberRows, + info->dualSolution); + CoinWarmStartBasis *basis = model2->getBasis(); + free(info->rowStatus); + info->rowStatus = + reinterpret_cast(malloc(numberRows * sizeof(int))); + free(info->columnStatus); + info->columnStatus = reinterpret_cast( + malloc(numberColumns * sizeof(int))); + // Put basis in + int i; + // free,basic,ub,lb are 0,1,2,3 + for (i = 0; i < numberRows; i++) { + CoinWarmStartBasis::Status status = basis->getArtifStatus(i); + info->rowStatus[i] = status; + } + for (i = 0; i < numberColumns; i++) { + CoinWarmStartBasis::Status status = basis->getStructStatus(i); + info->columnStatus[i] = status; + } + // put buffer into info + strcpy(info->buffer, buf); + delete basis; + } + } + } break; + case ClpParam::TIGHTEN:{ + if (!goodModel) { + printGeneralMessage(model_, "** Current model not valid\n"); + continue; } - break; - case CLP_PARAM_ACTION_STATISTICS: - if (goodModel) { - // If presolve on look at presolved - bool deleteModel2 = false; - ClpSimplex *model2 = lpSolver; - if (preSolve) { - ClpPresolve pinfo; - int presolveOptions2 = presolveOptions & ~0x40000000; - if ((presolveOptions2 & 0xffff) != 0) - pinfo.setPresolveActions(presolveOptions2); - pinfo.setSubstitution(substitution); - if ((printOptions & 1) != 0) - pinfo.statistics(); - double presolveTolerance = parameters_[whichParam(CLP_PARAM_DBL_PRESOLVETOLERANCE, parameters_)].doubleValue(); - model2 = pinfo.presolvedModel(*lpSolver, presolveTolerance, - true, preSolve); - if (model2) { - printf("Statistics for presolved model\n"); - deleteModel2 = true; - } else { - printf("Presolved model looks infeasible - will use unpresolved\n"); - model2 = lpSolver; - } - } else { - printf("Statistics for unpresolved model\n"); - model2 = lpSolver; - } - statistics(lpSolver, model2); - if (deleteModel2) - delete model2; - } else { - sprintf(generalPrint, "** Current model not valid"); - printGeneralMessage(model_, generalPrint); + int numberInfeasibilities = lpSolver->tightenPrimalBounds(); + if (numberInfeasibilities) { + printGeneralMessage(model_, + "** Analysis indicates model infeasible"); } - break; - case CLP_PARAM_ACTION_TIGHTEN: + } break; + case ClpParam::PLUSMINUS:{ if (goodModel) { - int numberInfeasibilities = lpSolver->tightenPrimalBounds(); - if (numberInfeasibilities) { - sprintf(generalPrint, "** Analysis indicates model infeasible"); - printGeneralMessage(model_, generalPrint); - } - } else { - sprintf(generalPrint, "** Current model not valid"); - printGeneralMessage(model_, generalPrint); + printGeneralWarning(model_, "** Current model not valid\n"); + continue; } - break; - case CLP_PARAM_ACTION_PLUSMINUS: - if (goodModel) { - ClpMatrixBase *saveMatrix = lpSolver->clpMatrix(); - ClpPackedMatrix *clpMatrix = dynamic_cast< ClpPackedMatrix * >(saveMatrix); - if (clpMatrix) { - ClpPlusMinusOneMatrix *newMatrix = new ClpPlusMinusOneMatrix(*(clpMatrix->matrix())); - if (newMatrix->getIndices()) { + ClpMatrixBase *saveMatrix = lpSolver->clpMatrix(); + ClpPackedMatrix *clpMatrix = + dynamic_cast(saveMatrix); + if (clpMatrix) { + ClpPlusMinusOneMatrix *newMatrix = + new ClpPlusMinusOneMatrix(*(clpMatrix->matrix())); + if (newMatrix->getIndices()) { lpSolver->replaceMatrix(newMatrix); delete saveMatrix; - sprintf(generalPrint, "Matrix converted to +- one matrix"); - printGeneralMessage(model_, generalPrint); - } else { - sprintf(generalPrint, "Matrix can not be converted to +- 1 matrix"); - printGeneralMessage(model_, generalPrint); - } - } else { - sprintf(generalPrint, "Matrix not a ClpPackedMatrix"); - printGeneralMessage(model_, generalPrint); - } + printGeneralMessage(model_, + "Matrix converted to +- one matrix"); + } else { + printGeneralMessage(model_, + "Matrix can not be converted to +- 1 matrix"); + } } else { - sprintf(generalPrint, "** Current model not valid"); - printGeneralMessage(model_, generalPrint); + printGeneralMessage(model_, "Matrix not a ClpPackedMatrix"); } - break; - case CLP_PARAM_ACTION_OUTDUPROWS: + }break; + case ClpParam::OUTDUPROWS: dominatedCuts = true; #ifdef JJF_ZERO if (goodModel) { int numberRows = clpSolver->getNumRows(); - //int nOut = outDupRow(clpSolver); + // int nOut = outDupRow(clpSolver); CglDuplicateRow dupcuts(clpSolver); storedCuts = dupcuts.outDuplicates(clpSolver) != 0; int nOut = numberRows - clpSolver->getNumRows(); - if (nOut && !noPrinting_) - sprintf(generalPrint, "%d rows eliminated", nOut); - generalMessageHandler->message(CLP_GENERAL, generalMessages) - << generalPrint - << CoinMessageEol; + if (nOut){ + buffer.str(""); + buffer << nOut << " rows eliminated"; + printGeneralMessage(model_, buffer.str()); + } } else { - sprintf(generalPrint, "** Current model not valid"); - printGeneralMessage(model_, generalPrint); + printGeneralMessage(model_, "** Current model not valid\n"); } #endif break; - case CLP_PARAM_ACTION_NETWORK: - if (goodModel) { - ClpMatrixBase *saveMatrix = lpSolver->clpMatrix(); - ClpPackedMatrix *clpMatrix = dynamic_cast< ClpPackedMatrix * >(saveMatrix); - if (clpMatrix) { - ClpNetworkMatrix *newMatrix = new ClpNetworkMatrix(*(clpMatrix->matrix())); - if (newMatrix->getIndices()) { + case ClpParam::NETWORK:{ + if (!goodModel) { + printGeneralWarning(model_, "** Current model not valid\n"); + continue; + } + ClpMatrixBase *saveMatrix = lpSolver->clpMatrix(); + ClpPackedMatrix *clpMatrix = + dynamic_cast(saveMatrix); + if (clpMatrix) { + ClpNetworkMatrix *newMatrix = + new ClpNetworkMatrix(*(clpMatrix->matrix())); + if (newMatrix->getIndices()) { lpSolver->replaceMatrix(newMatrix); delete saveMatrix; - sprintf(generalPrint, "Matrix converted to network matrix"); - printGeneralMessage(model_, generalPrint); - } else { - sprintf(generalPrint, "Matrix can not be converted to network matrix"); - printGeneralMessage(model_, generalPrint); - } - } else { - sprintf(generalPrint, "Matrix not a ClpPackedMatrix"); - printGeneralMessage(model_, generalPrint); + printGeneralMessage(model_, + "Matrix converted to network matrix"); + } else { + printGeneralMessage(model_, + "Matrix can not be converted to network matrix"); + } + } else { + printGeneralMessage(model_, "Matrix not a ClpPackedMatrix"); + } + }break; + case ClpParam::BASISIN:{ + if (!goodModel){ + printGeneralWarning(model_, "** Current model not valid\n"); + continue; + } + clpParam->readValue(inputQueue, fileName, &message); + CoinParamUtils::processFile(fileName, + parameters[ClpParam::DIRECTORY]->dirName(), + &canOpen); + if (!canOpen) { + buffer.str(""); + buffer << "Unable to open file " << fileName.c_str(); + printGeneralMessage(model_, buffer.str()); + continue; + } + if (fileName == ""){ + fileName = parameters[ClpParam::BASISFILE]->fileName(); + }else{ + parameters[ClpParam::BASISFILE]->setFileName(fileName); + } +#ifndef CBC_OTHER_SOLVER + int values = lpSolver->readBasis(fileName.c_str()); + if (values == 0) + basisHasValues = -1; + else + basisHasValues = 1; + assert(lpSolver == clpSolver->getModelPtr()); + clpSolver->setWarmStart(NULL); +#endif + } break; + case ClpParam::BASISOUT:{ + if (!goodModel){ + printGeneralMessage(model_, "** Current model not valid\n"); + continue; + } + clpParam->readValue(inputQueue, fileName, &message); + CoinParamUtils::processFile(fileName, + parameters[ClpParam::DIRECTORY]->dirName(), + &canOpen); + if (!canOpen) { + buffer.str(""); + buffer << "Unable to open file " << fileName.c_str(); + printGeneralMessage(model_, buffer.str()); + continue; + } + if (fileName == ""){ + fileName = parameters[ClpParam::BASISFILE]->fileName(); + }else{ + parameters[ClpParam::BASISFILE]->setFileName(fileName); + } + ClpSimplex *model2 = lpSolver; + model2->writeBasis(fileName.c_str(), outputFormat > 1, + outputFormat - 2); + time2 = CoinCpuTime(); + totalTime += time2 - time1; + time1 = time2; + } break; + case ClpParam::ALLSLACK: + lpSolver->allSlackBasis(true); + break; + case ClpParam::NETLIB_DUAL: + case ClpParam::NETLIB_EITHER: + case ClpParam::NETLIB_BARRIER: + case ClpParam::NETLIB_PRIMAL: + case ClpParam::NETLIB_TUNE: { + printf("unit test is now only from clp - does same thing\n"); + // return(22); + } break; + case ClpParam::FAKEBOUND:{ + if (!goodModel) { + continue; + } + // get bound + if (status = clpParam->readValue(inputQueue, dValue, &message)){ + std::cout << "Must enter value for " << clpParam->name() + << std::endl; + continue; + } + buffer.str(""); + buffer << "Setting " << clpParam->name() << " to DEBUG " << dValue + << std::endl; + printGeneralMessage(model_, buffer.str()); + int iRow; + int numberRows = lpSolver->numberRows(); + double *rowLower = lpSolver->rowLower(); + double *rowUpper = lpSolver->rowUpper(); + for (iRow = 0; iRow < numberRows; iRow++) { + // leave free ones for now + if (rowLower[iRow] > -1.0e20 || rowUpper[iRow] < 1.0e20) { + rowLower[iRow] = CoinMax(rowLower[iRow], -dValue); + rowUpper[iRow] = CoinMin(rowUpper[iRow], dValue); + } + } + int iColumn; + int numberColumns = lpSolver->numberColumns(); + double *columnLower = lpSolver->columnLower(); + double *columnUpper = lpSolver->columnUpper(); + for (iColumn = 0; iColumn < numberColumns; iColumn++) { + // leave free ones for now + if (columnLower[iColumn] > -1.0e20 || + columnUpper[iColumn] < 1.0e20) { + columnLower[iColumn] = + CoinMax(columnLower[iColumn], -dValue); + columnUpper[iColumn] = CoinMin(columnUpper[iColumn], dValue); + } + } + }break; + case ClpParam::REALLY_SCALE: + if (goodModel) { + ClpSimplex newModel(*lpSolver, lpSolver->scalingFlag()); + printf("model really really scaled\n"); + *lpSolver = newModel; + } + break; + case ClpParam::USERCLP: +#ifdef USER_HAS_FAKE_CLP + // Replace the sample code by whatever you want + if (goodModel) { + // Way of using an existing piece of code + OsiClpSolverInterface *clpSolver = + dynamic_cast(model_.solver()); + ClpSimplex *lpSolver = clpSolver->getModelPtr(); + // set time from integer model + double timeToGo = model_.getMaximumSeconds(); + lpSolver->setMaximumSeconds(timeToGo); + int extra1 = parameters[CbcParam::EXTRA1]->intVal(); + fakeMain2(*lpSolver, *clpSolver, extra1); + lpSolver = clpSolver->getModelPtr(); + // My actual usage has objective only in clpSolver + // double objectiveValue=clpSolver->getObjValue(); + // int iStat = lpSolver->status(); + // int iStat2 = lpSolver->secondaryStatus(); + } +#endif + break; + case ClpParam::PARAMETRICS:{ + if (!goodModel){ + printGeneralMessage(model_, "** Current model not valid\n"); + } + cbcParam->readValue(inputQueue, fileName, &message); + CoinParamUtils::processFile(fileName, + parameters[CbcParam::DIRECTORY]->dirName(), + &canOpen); + if (!canOpen) { + buffer.str(""); + buffer << "Unable to open file " << fileName.c_str(); + printGeneralMessage(model_, buffer.str()); + continue; + } + if (fileName == ""){ + fileName = parameters[CbcParam::EXPORTFILE]->fileName(); + }else{ + parameters[CbcParam::EXPORTFILE]->setFileName(fileName); + } + static_cast(lpSolver)->parametrics( + fileName.c_str()); + time2 = CoinCpuTime(); + totalTime += time2 - time1; + time1 = time2; + } break; + case ClpParam::GUESS: + if (goodModel && model_.solver()) { + OsiClpSolverInterface *clpSolver = + dynamic_cast(model_.solver()); + assert(clpSolver); + lpSolver = clpSolver->getModelPtr(); + assert(lpSolver); + ClpSimplexOther *model2 = + static_cast(lpSolver); + //This is an ugly hack to make this compile, but we'll be getting rid of + //this soon anyway. + std::string input = model2->guess(0); + if (input != ""){ + while (!inputQueue.empty()){ + inputQueue.pop_front(); + } + std::istringstream inputStream(input); + CoinParamUtils::readFromStream(inputQueue, inputStream); + }else{ + printGeneralWarning(model, + "** Guess unable to generate commands\n"); } } else { - sprintf(generalPrint, "** Current model not valid"); - printGeneralMessage(model_, generalPrint); + printGeneralWarning(model, "** Guess needs a valid model\n"); } break; - case CBC_PARAM_ACTION_DOHEURISTIC: - if (goodModel) { -#if CBC_USE_INITIAL_TIME==1 - if (model_.useElapsedTime()) - model_.setDblParam(CbcModel::CbcStartSeconds, CoinGetTimeOfDay()); - else - model_.setDblParam(CbcModel::CbcStartSeconds, CoinCpuTime()); -#endif - int vubAction = parameters_[whichParam(CBC_PARAM_INT_VUBTRY, parameters_)].intValue(); - if (vubAction != -1) { - // look at vubs - // extra1 is number of ints to leave free - // Just ones which affect >= extra3 - int extra3 = parameters_[whichParam(CBC_PARAM_INT_EXTRA3, parameters_)].intValue(); - /* 2 is cost above which to fix if feasible - 3 is fraction of integer variables fixed if relaxing (0.97) - 4 is fraction of all variables fixed if relaxing (0.0) - */ - double dextra[6]; - int extra[5]; - extra[1] = parameters_[whichParam(CBC_PARAM_INT_EXTRA1, parameters_)].intValue(); - int exp1 = parameters_[whichParam(CBC_PARAM_INT_EXPERIMENT, parameters_)].intValue(); - if (exp1 == 4 && extra[1] == -1) + default: + // abort(); + break; + } + + switch (cbcParamCode) { + case CbcParam::SOLVECONTINUOUS: + // Solve problem dual simplex + inputQueue.push_front("-dualSimplex"); + continue; + case CbcParam::STATISTICS:{ + if (!goodModel){ + printGeneralMessage(model_, "** Current model not valid\n"); + continue; + } + // If presolve on look at presolved + bool deleteModel2 = false; + ClpSimplex *model2 = lpSolver; + if (preSolve) { + ClpPresolve pinfo; + int presolveOptions2 = presolveOptions & ~0x40000000; + if ((presolveOptions2 & 0xffff) != 0) + pinfo.setPresolveActions(presolveOptions2); + pinfo.setSubstitution(substitution); + if ((printOptions & 1) != 0) + pinfo.statistics(); + double presolveTolerance = + clpParameters[ClpParam::PRESOLVETOLERANCE]->dblVal(); + model2 = pinfo.presolvedModel(*lpSolver, presolveTolerance, + true, preSolve); + if (model2) { + printf("Statistics for presolved model\n"); + deleteModel2 = true; + } else { + printf("Presolved model looks infeasible - will use " + "unpresolved\n"); + model2 = lpSolver; + } + } else { + printf("Statistics for unpresolved model\n"); + model2 = lpSolver; + } + statistics(lpSolver, model2); + if (deleteModel2) + delete model2; + } break; + case CbcParam::DOHEURISTIC:{ + if (!goodModel){ + continue; + } +#if CBC_USE_INITIAL_TIME == 1 + if (model_.useElapsedTime()) + model_.setDblParam(CbcModel::CbcStartSeconds, + CoinGetTimeOfDay()); + else + model_.setDblParam(CbcModel::CbcStartSeconds, CoinCpuTime()); +#endif + int vubMode = parameters[CbcParam::VUBTRY]->intVal(); + if (vubMode != -1) { + // look at vubs + // extra1 is number of ints to leave free + // Just ones which affect >= extra3 + int extra3 = parameters[CbcParam::EXTRA3]->intVal(); + /* 2 is cost above which to fix if feasible + 3 is fraction of integer variables fixed if + relaxing (0.97) 4 is fraction of all variables fixed if + relaxing (0.0) + */ + double dextra[6]; + int extra[5]; + extra[1] = parameters[CbcParam::EXTRA1]->intVal(); + int exp1 = parameters[CbcParam::EXPERIMENT]->intVal(); + if (exp1 == 4 && extra[1] == -1) extra[1] = 999998; - dextra[1] = parameters_[whichParam(CBC_PARAM_DBL_FAKEINCREMENT, parameters_)].doubleValue(); - dextra[2] = parameters_[whichParam(CBC_PARAM_DBL_FAKECUTOFF, parameters_)].doubleValue(); - dextra[3] = parameters_[whichParam(CBC_PARAM_DBL_DEXTRA3, parameters_)].doubleValue(); - dextra[4] = parameters_[whichParam(CBC_PARAM_DBL_DEXTRA4, parameters_)].doubleValue(); - dextra[5] = parameters_[whichParam(CBC_PARAM_DBL_DEXTRA5, parameters_)].doubleValue(); - if (!dextra[3]) + dextra[1] = parameters[CbcParam::FAKEINCREMENT]->dblVal(); + dextra[2] = parameters[CbcParam::FAKECUTOFF]->dblVal(); + dextra[3] = parameters[CbcParam::DEXTRA3]->dblVal(); + dextra[4] = parameters[CbcParam::DEXTRA4]->dblVal(); + dextra[5] = parameters[CbcParam::DEXTRA5]->dblVal(); + if (!dextra[3]) dextra[3] = 0.97; - //OsiClpSolverInterface * newSolver = - fixVubs(model_, extra3, vubAction, generalMessageHandler, - debugValues, dextra, extra); - //assert (!newSolver); - } - // Actually do heuristics - // may need to flip objective - bool needFlip = model_.solver()->getObjSense() < 0.0; - if (needFlip) - model_.flipModel(); - //if we do then - fix priorities in clonebutmodel_.convertToDynamic(); - bool objectsExist = model_.objects() != NULL; - if (!objectsExist) { - model_.findIntegers(false); - model_.convertToDynamic(); - } - // set priorities etc - if (priorities) { - OsiObject **objects = model_.objects(); - int numberObjects = model_.numberObjects(); - for (int iObj = 0; iObj < numberObjects; iObj++) { - CbcSimpleInteger *obj = dynamic_cast< CbcSimpleInteger * >(objects[iObj]); + // OsiClpSolverInterface * newSolver = + fixVubs(model_, extra3, vubMode, generalMessageHandler, + debugValues, dextra, extra); + // assert (!newSolver); + } + // Actually do heuristics + // may need to flip objective + bool needFlip = model_.solver()->getObjSense() < 0.0; + if (needFlip) + model_.flipModel(); + // if we do then - fix priorities in + // clonebutmodel_.convertToDynamic(); + bool objectsExist = model_.objects() != NULL; + if (!objectsExist) { + model_.findIntegers(false); + model_.convertToDynamic(); + } + // set priorities etc + if (priorities) { + OsiObject **objects = model_.objects(); + int numberObjects = model_.numberObjects(); + for (int iObj = 0; iObj < numberObjects; iObj++) { + CbcSimpleInteger *obj = + dynamic_cast(objects[iObj]); if (!obj) - continue; + continue; int iColumn = obj->columnNumber(); if (branchDirection) { - obj->setPreferredWay(branchDirection[iColumn]); + obj->setPreferredWay(branchDirection[iColumn]); } if (priorities) { - int iPriority = priorities[iColumn]; - if (iPriority > 0) - obj->setPriority(iPriority); + int iPriority = priorities[iColumn]; + if (iPriority > 0) + obj->setPriority(iPriority); } if (pseudoUp && pseudoUp[iColumn]) { - CbcSimpleIntegerPseudoCost *obj1a = dynamic_cast< CbcSimpleIntegerPseudoCost * >(objects[iObj]); + CbcSimpleIntegerPseudoCost *obj1a = + dynamic_cast( + objects[iObj]); assert(obj1a); if (pseudoDown[iColumn] > 0.0) - obj1a->setDownPseudoCost(pseudoDown[iColumn]); + obj1a->setDownPseudoCost(pseudoDown[iColumn]); if (pseudoUp[iColumn] > 0.0) - obj1a->setUpPseudoCost(pseudoUp[iColumn]); + obj1a->setUpPseudoCost(pseudoUp[iColumn]); } - } - } - doHeuristics(&model_, 2, parameters_, - noPrinting_, initialPumpTune); - if (!objectsExist) { - model_.deleteObjects(false); - } - if (needFlip) - model_.flipModel(); - if (model_.bestSolution()) { - model_.setProblemStatus(1); - model_.setSecondaryStatus(6); - if (statusUserFunction_[0]) { + } + } + doHeuristics(&model_, 2, parameters, parameters.noPrinting(), + initialPumpTune); + if (!objectsExist) { + model_.deleteObjects(false); + } + if (needFlip) + model_.flipModel(); + if (model_.bestSolution()) { + model_.setProblemStatus(1); + model_.setSecondaryStatus(6); + if (statusUserFunction_[0] && info) { double value = model_.getObjValue(); char buf[300]; int pos = 0; pos += sprintf(buf + pos, "feasible,"); - info.problemStatus = 0; - info.objValue = value; + info->problemStatus = 0; + info->objValue = value; pos += sprintf(buf + pos, " objective %.*g", ampl_obj_prec(), - value); + value); sprintf(buf + pos, "\n0 iterations"); - free(info.primalSolution); + free(info->primalSolution); int numberColumns = lpSolver->numberColumns(); - info.primalSolution = reinterpret_cast< double * >(malloc(numberColumns * sizeof(double))); - CoinCopyN(model_.bestSolution(), numberColumns, info.primalSolution); + info->primalSolution = reinterpret_cast( + malloc(numberColumns * sizeof(double))); + CoinCopyN(model_.bestSolution(), numberColumns, + info->primalSolution); int numberRows = lpSolver->numberRows(); - free(info.dualSolution); - info.dualSolution = reinterpret_cast< double * >(malloc(numberRows * sizeof(double))); - CoinZeroN(info.dualSolution, numberRows); + free(info->dualSolution); + info->dualSolution = reinterpret_cast( + malloc(numberRows * sizeof(double))); + CoinZeroN(info->dualSolution, numberRows); CoinWarmStartBasis *basis = lpSolver->getBasis(); - free(info.rowStatus); - info.rowStatus = reinterpret_cast< int * >(malloc(numberRows * sizeof(int))); - free(info.columnStatus); - info.columnStatus = reinterpret_cast< int * >(malloc(numberColumns * sizeof(int))); + free(info->rowStatus); + info->rowStatus = + reinterpret_cast(malloc(numberRows * sizeof(int))); + free(info->columnStatus); + info->columnStatus = reinterpret_cast( + malloc(numberColumns * sizeof(int))); // Put basis in int i; // free,basic,ub,lb are 0,1,2,3 for (i = 0; i < numberRows; i++) { - CoinWarmStartBasis::Status status = basis->getArtifStatus(i); - info.rowStatus[i] = status; + CoinWarmStartBasis::Status status = + basis->getArtifStatus(i); + info->rowStatus[i] = status; } for (i = 0; i < numberColumns; i++) { - CoinWarmStartBasis::Status status = basis->getStructStatus(i); - info.columnStatus[i] = status; + CoinWarmStartBasis::Status status = + basis->getStructStatus(i); + info->columnStatus[i] = status; } // put buffer into info - strcpy(info.buffer, buf); + strcpy(info->buffer, buf); delete basis; - } - } - int returnCode = callBack(&model, 6); - if (returnCode) { - // exit if user wants - delete babModel_; - babModel_ = NULL; - return returnCode; - } + } } - break; - case CBC_PARAM_ACTION_MIPLIB: - // User can set options - main difference is lack of model and CglPreProcess + int returnCode = callBack(&model, 6); + if (returnCode) { + // exit if user wants + delete babModel_; + babModel_ = NULL; + return returnCode; + } + }break; + case CbcParam::MIPLIB: + // User can set options - main difference is lack of model and + // CglPreProcess goodModel = true; - parameters_[whichParam(CBC_PARAM_INT_MULTIPLEROOTS, parameters_)].setIntValue(0); + parameters[CbcParam::MULTIPLEROOTS]->setVal(0); /* - Run branch-and-cut. First set a few options -- node comparison, scaling. - Print elapsed time at the end. + Run branch-and-cut. First set a few options -- node + comparison, scaling. Print elapsed time at the end. */ - case CBC_PARAM_ACTION_BAB: // branchAndBound - // obsolete case STRENGTHEN: - if (goodModel) { - bool miplib = type == CBC_PARAM_ACTION_MIPLIB; - int logLevel = parameters_[slog].intValue(); + case CbcParam::BAB: { +#ifdef CBC_CLUMSY_CODING + parameters.setModel(&model_); + parameters.setGoodModel(true); + parameters.synchronizeModel(); +#endif + bool miplib = cbcParamCode == CbcParam::MIPLIB; + int logLevel = parameters[CbcParam::LPLOGLEVEL]->intVal(); int truncateColumns = COIN_INT_MAX; int truncateRows = -1; bool redoSOS = false; @@ -3511,23 +3567,28 @@ int CbcMain1(int argc, const char *argv[], int *newPriorities = NULL; // Reduce printout if (logLevel <= 1) { - model_.solver()->setHintParam(OsiDoReducePrint, true, OsiHintTry); + model_.solver()->setHintParam(OsiDoReducePrint, true, + OsiHintTry); } else { - model_.solver()->setHintParam(OsiDoReducePrint, false, OsiHintTry); + model_.solver()->setHintParam(OsiDoReducePrint, false, + OsiHintTry); } { OsiSolverInterface *solver = model_.solver(); #ifndef CBC_OTHER_SOLVER - OsiClpSolverInterface *si = dynamic_cast< OsiClpSolverInterface * >(solver); + OsiClpSolverInterface *si = + dynamic_cast(solver); assert(si != NULL); si->getModelPtr()->scaling(doScaling); ClpSimplex *lpSolver = si->getModelPtr(); // deal with positive edge - double psi = parameters_[whichParam(CLP_PARAM_DBL_PSI, parameters_)].doubleValue(); + double psi = clpParameters[ClpParam::PSI]->dblVal(); if (psi > 0.0) { ClpDualRowPivot *dualp = lpSolver->dualRowPivot(); - ClpDualRowSteepest *d1 = dynamic_cast< ClpDualRowSteepest * >(dualp); - ClpDualRowDantzig *d2 = dynamic_cast< ClpDualRowDantzig * >(dualp); + ClpDualRowSteepest *d1 = + dynamic_cast(dualp); + ClpDualRowDantzig *d2 = + dynamic_cast(dualp); if (d1) { ClpPEDualRowSteepest p(psi, d1->mode()); lpSolver->setDualRowPivotAlgorithm(p); @@ -3536,8 +3597,10 @@ int CbcMain1(int argc, const char *argv[], lpSolver->setDualRowPivotAlgorithm(p); } ClpPrimalColumnPivot *primalp = lpSolver->primalColumnPivot(); - ClpPrimalColumnSteepest *p1 = dynamic_cast< ClpPrimalColumnSteepest * >(primalp); - ClpPrimalColumnDantzig *p2 = dynamic_cast< ClpPrimalColumnDantzig * >(primalp); + ClpPrimalColumnSteepest *p1 = + dynamic_cast(primalp); + ClpPrimalColumnDantzig *p2 = + dynamic_cast(primalp); if (p1) { ClpPEPrimalColumnSteepest p(psi, p1->mode()); lpSolver->setPrimalColumnPivotAlgorithm(p); @@ -3548,13 +3611,15 @@ int CbcMain1(int argc, const char *argv[], } if (doVector) { ClpMatrixBase *matrix = lpSolver->clpMatrix(); - if (dynamic_cast< ClpPackedMatrix * >(matrix)) { - ClpPackedMatrix *clpMatrix = dynamic_cast< ClpPackedMatrix * >(matrix); + if (dynamic_cast(matrix)) { + ClpPackedMatrix *clpMatrix = + dynamic_cast(matrix); clpMatrix->makeSpecialColumnCopy(); } } #elif CBC_OTHER_SOLVER == 1 - OsiCpxSolverInterface *si = dynamic_cast< OsiCpxSolverInterface * >(solver); + OsiCpxSolverInterface *si = + dynamic_cast(solver); assert(si != NULL); #endif statistics_nrows = si->getNumRows(); @@ -3565,11 +3630,13 @@ int CbcMain1(int argc, const char *argv[], #ifndef CBC_OTHER_SOLVER #ifdef COIN_HAS_LINK if (!complicatedInteger) { - ClpQuadraticObjective *obj = (dynamic_cast< ClpQuadraticObjective * >(lpSolver->objectiveAsObject())); + ClpQuadraticObjective *obj = + (dynamic_cast( + lpSolver->objectiveAsObject())); if (obj) { preProcess = 0; - int testOsiOptions = parameters_[whichParam(CBC_PARAM_INT_TESTOSI, parameters_)].intValue(); - parameters_[whichParam(CBC_PARAM_INT_TESTOSI, parameters_)].setIntValue(CoinMax(0, testOsiOptions)); + int testOsiOptions = parameters[CbcParam::TESTOSI]->intVal(); + parameters[CbcParam::TESTOSI]->setVal(CoinMax(0, testOsiOptions)); // create coin model coinModel = lpSolver->createCoinModel(); assert(coinModel); @@ -3577,12 +3644,13 @@ int CbcMain1(int argc, const char *argv[], OsiSolverLink solver1; OsiSolverInterface *solver2 = solver1.clone(); model_.assignSolver(solver2, false); - OsiSolverLink *si = dynamic_cast< OsiSolverLink * >(model_.solver()); + OsiSolverLink *si = + dynamic_cast(model_.solver()); assert(si != NULL); si->setDefaultMeshSize(0.001); // need some relative granularity si->setDefaultBound(100.0); - double dextra3 = parameters_[whichParam(CBC_PARAM_DBL_DEXTRA3, parameters_)].doubleValue(); + double dextra3 = parameters[CbcParam::DEXTRA3]->dblVal(); if (dextra3) si->setDefaultMeshSize(dextra3); si->setDefaultBound(1000.0); @@ -3591,19 +3659,20 @@ int CbcMain1(int argc, const char *argv[], biLinearProblem = true; si->setSpecialOptions2(2 + 4 + 8); CoinModel *model2 = coinModel; - si->load(*model2, true, parameters_[log].intValue()); + si->load(*model2, true, parameters[CbcParam::LPLOGLEVEL]->intVal()); // redo solver = model_.solver(); - clpSolver = dynamic_cast< OsiClpSolverInterface * >(solver); + clpSolver = dynamic_cast(solver); lpSolver = clpSolver->getModelPtr(); clpSolver->messageHandler()->setLogLevel(0); testOsiParameters = 0; complicatedInteger = 2; // allow cuts OsiSolverInterface *coinSolver = model_.solver(); - OsiSolverLink *linkSolver = dynamic_cast< OsiSolverLink * >(coinSolver); + OsiSolverLink *linkSolver = + dynamic_cast(coinSolver); if (linkSolver->quadraticModel()) { ClpSimplex *qp = linkSolver->quadraticModel(); - //linkSolver->nonlinearSLP(CoinMax(slpValue,10),1.0e-5); + // linkSolver->nonlinearSLP(CoinMax(slpValue,10),1.0e-5); qp->nonlinearSLP(CoinMax(slpValue, 40), 1.0e-5); qp->primal(1); OsiSolverLinearizedQuadratic solver2(qp); @@ -3614,7 +3683,8 @@ int CbcMain1(int argc, const char *argv[], // Now do requested saves and modifications CbcModel *cbcModel = &model2; OsiSolverInterface *osiModel = model2.solver(); - OsiClpSolverInterface *osiclpModel = dynamic_cast< OsiClpSolverInterface * >(osiModel); + OsiClpSolverInterface *osiclpModel = + dynamic_cast(osiModel); ClpSimplex *clpModel = osiclpModel->getModelPtr(); // Set changed values @@ -3628,47 +3698,62 @@ int CbcMain1(int argc, const char *argv[], probing.setMaxLookRoot(10); probing.setRowCuts(3); probing.setUsingObjective(true); - cbcModel->addCutGenerator(&probing, -1, "Probing", true, false, false, -100, -1, -1); + cbcModel->addCutGenerator(&probing, -1, "Probing", true, + false, false, -100, -1, -1); cbcModel->cutGenerator(numCutGens++)->setTiming(true); CglGomory gomory; gomory.setLimitAtRoot(512); - cbcModel->addCutGenerator(&gomory, -98, "Gomory", true, false, false, -100, -1, -1); + cbcModel->addCutGenerator(&gomory, -98, "Gomory", true, + false, false, -100, -1, -1); cbcModel->cutGenerator(numCutGens++)->setTiming(true); CglKnapsackCover knapsackCover; - cbcModel->addCutGenerator(&knapsackCover, -98, "KnapsackCover", true, false, false, -100, -1, -1); + cbcModel->addCutGenerator(&knapsackCover, -98, + "KnapsackCover", true, false, + false, -100, -1, -1); cbcModel->cutGenerator(numCutGens++)->setTiming(true); CglRedSplit redSplit; - cbcModel->addCutGenerator(&redSplit, -99, "RedSplit", true, false, false, -100, -1, -1); + cbcModel->addCutGenerator(&redSplit, -99, "RedSplit", + true, false, false, -100, -1, + -1); cbcModel->cutGenerator(numCutGens++)->setTiming(true); - + CglBKClique bkClique; bkClique.setMaxCallsBK(1000); bkClique.setExtendingMethod(4); bkClique.setPivotingStrategy(3); - cbcModel->addCutGenerator(&bkClique, -98, "Clique", true, false, false, -100, -1, -1); + cbcModel->addCutGenerator(&bkClique, -98, "Clique", true, + false, false, -100, -1, -1); cbcModel->cutGenerator(numCutGens++)->setTiming(true); CglOddWheel oddWheel; oddWheel.setExtendingMethod(2); - cbcModel->addCutGenerator(&oddWheel, -98, "OddWheel", true, false, false, -100, -1, -1); + cbcModel->addCutGenerator(&oddWheel, -98, "OddWheel", + true, false, false, -100, -1, + -1); cbcModel->cutGenerator(numCutGens++)->setTiming(true); CglMixedIntegerRounding2 mixedIntegerRounding2; - cbcModel->addCutGenerator(&mixedIntegerRounding2, -98, "MixedIntegerRounding2", true, false, false, -100, -1, -1); + cbcModel->addCutGenerator(&mixedIntegerRounding2, -98, + "MixedIntegerRounding2", true, + false, false, -100, -1, -1); cbcModel->cutGenerator(numCutGens++)->setTiming(true); CglFlowCover flowCover; - cbcModel->addCutGenerator(&flowCover, -98, "FlowCover", true, false, false, -100, -1, -1); + cbcModel->addCutGenerator(&flowCover, -98, "FlowCover", + true, false, false, -100, -1, + -1); cbcModel->cutGenerator(numCutGens++)->setTiming(true); CglTwomir twomir; twomir.setMaxElements(250); - cbcModel->addCutGenerator(&twomir, -99, "Twomir", true, false, false, -100, -1, -1); + cbcModel->addCutGenerator(&twomir, -99, "Twomir", true, + false, false, -100, -1, -1); cbcModel->cutGenerator(numCutGens++)->setTiming(true); - int heuristicOption = parameters_[whichParam(CBC_PARAM_STR_HEURISTICSTRATEGY, parameters_)].currentOptionAsInteger(); + int heuristicOption = + parameters[CbcParam::HEURISTICSTRATEGY]->modeVal(); if (heuristicOption) { CbcHeuristicFPump heuristicFPump(*cbcModel); heuristicFPump.setWhen(13); @@ -3693,15 +3778,17 @@ int CbcMain1(int argc, const char *argv[], heuristicGreedyCover.setHeuristicName("greedy cover"); cbcModel->addHeuristic(&heuristicGreedyCover); - CbcHeuristicGreedyEquality heuristicGreedyEquality(*cbcModel); - heuristicGreedyEquality.setHeuristicName("greedy equality"); + CbcHeuristicGreedyEquality heuristicGreedyEquality( + *cbcModel); + heuristicGreedyEquality.setHeuristicName( + "greedy equality"); cbcModel->addHeuristic(&heuristicGreedyEquality); -#ifdef CBC_EXPERIMENT7 +#ifdef CBC_EXPERIMENT_JJF #ifndef CBC_OTHER_SOLVER - CbcHeuristicRandRound heuristicRandRound(*cbcModel); - heuristicRandRound.setHeuristicName("random rounding"); - cbcModel->addHeuristic(&heuristicRandRound); - #endif + CbcHeuristicRandRound heuristicRandRound(*cbcModel); + heuristicRandRound.setHeuristicName("random rounding"); + cbcModel->addHeuristic(&heuristicRandRound); +#endif #endif } CbcCompareDefault compare; @@ -3719,28 +3806,34 @@ int CbcMain1(int argc, const char *argv[], osiclpModel->setSpecialOptions(193); osiclpModel->messageHandler()->setLogLevel(0); osiclpModel->setIntParam(OsiMaxNumIterationHotStart, 100); - osiclpModel->setHintParam(OsiDoReducePrint, true, OsiHintTry); - // You can save some time by switching off message building - // clpModel->messagesPointer()->setDetailMessages(100,10000,(int *) NULL); + osiclpModel->setHintParam(OsiDoReducePrint, true, + OsiHintTry); + // You can save some time by switching off message + // building + // clpModel->messagesPointer()->setDetailMessages(100,10000,(int + // *) NULL); // Solve cbcModel->initialSolve(); if (clpModel->tightenPrimalBounds() != 0) { - sprintf(generalPrint, "Problem is infeasible - tightenPrimalBounds!"); - printGeneralMessage(model_, generalPrint); + buffer.str(""); + buffer << "Problem is infeasible - tightenPrimalBounds!"; + printGeneralMessage(model_, buffer.str()); break; } clpModel->dual(); // clean up cbcModel->initialSolve(); #ifdef CBC_THREAD - int numberThreads = parameters_[whichParam(CBC_PARAM_INT_THREADS, parameters_)].intValue(); + int numberThreads = parameters[CbcParam::THREADS]->intVal(); cbcModel->setNumberThreads(numberThreads % 100); cbcModel->setThreadMode(CoinMin(numberThreads / 100, 7)); #endif - //setCutAndHeuristicOptions(*cbcModel); + // setCutAndHeuristicOptions(*cbcModel); cbcModel->branchAndBound(); - OsiSolverLinearizedQuadratic *solver3 = dynamic_cast< OsiSolverLinearizedQuadratic * >(model2.solver()); + OsiSolverLinearizedQuadratic *solver3 = + dynamic_cast( + model2.solver()); assert(solver3); solution = solver3->bestSolution(); double bestObjectiveValue = solver3->bestObjectiveValue(); @@ -3763,14 +3856,18 @@ int CbcMain1(int argc, const char *argv[], if (heuristicOption) model_.addHeuristic(&dynamic); // if convex - if ((linkSolver->specialOptions2() & 4) != 0 && solution) { + if ((linkSolver->specialOptions2() & 4) != 0 && + solution) { int numberColumns = coinModel->numberColumns(); - assert(linkSolver->objectiveVariable() == numberColumns); + assert(linkSolver->objectiveVariable() == + numberColumns); // add OA cut double offset; double *gradient = new double[numberColumns + 1]; - memcpy(gradient, qp->objectiveAsObject()->gradient(qp, solution, offset, true, 2), - numberColumns * sizeof(double)); + memcpy(gradient, + qp->objectiveAsObject()->gradient( + qp, solution, offset, true, 2), + numberColumns * sizeof(double)); double rhs = 0.0; int *column = new int[numberColumns + 1]; int n = 0; @@ -3784,14 +3881,16 @@ int CbcMain1(int argc, const char *argv[], } gradient[n] = -1.0; column[n++] = numberColumns; - storedAmpl.addCut(-COIN_DBL_MAX, offset + 1.0e-7, n, column, gradient); - linkSolver->addRow(n, column, gradient, - -COIN_DBL_MAX, offset + 1.0e-7); + storedAmpl.addCut(-COIN_DBL_MAX, offset + 1.0e-7, n, + column, gradient); + linkSolver->addRow(n, column, gradient, -COIN_DBL_MAX, + offset + 1.0e-7); delete[] gradient; delete[] column; } - // could do three way branching round a) continuous b) best solution - //printf("obj %g\n", bestObjectiveValue); + // could do three way branching round a) continuous b) + // best solution + // printf("obj %g\n", bestObjectiveValue); linkSolver->initialSolve(); } } @@ -3806,13 +3905,16 @@ int CbcMain1(int argc, const char *argv[], } if (!miplib) { if (!preSolve) { - model_.solver()->setHintParam(OsiDoPresolveInInitial, false, OsiHintTry); - model_.solver()->setHintParam(OsiDoPresolveInResolve, false, OsiHintTry); + model_.solver()->setHintParam(OsiDoPresolveInInitial, false, + OsiHintTry); + model_.solver()->setHintParam(OsiDoPresolveInResolve, false, + OsiHintTry); } double time1a = CoinCpuTime(); OsiSolverInterface *solver = model_.solver(); #ifndef CBC_OTHER_SOLVER - OsiClpSolverInterface *si = dynamic_cast< OsiClpSolverInterface * >(solver); + OsiClpSolverInterface *si = + dynamic_cast(solver); if (si) si->setSpecialOptions(si->specialOptions() | 1024); #endif @@ -3857,28 +3959,25 @@ int CbcMain1(int argc, const char *argv[], babModel_->setProblemStatus(iStatus); babModel_->setSecondaryStatus(iStatus2); } - if (!noPrinting_) { - iStatus = clpSolver->status(); - const char *msg[] = { "infeasible", "unbounded", "stopped", - "difficulties", "other" }; - sprintf(generalPrint, "Problem is %s - %.2f seconds", - msg[iStatus - 1], CoinCpuTime() - time1a); - generalMessageHandler->message(CLP_GENERAL, generalMessages) - << generalPrint - << CoinMessageEol; - } + iStatus = clpSolver->status(); + const char *msg[] = {"infeasible", "unbounded", "stopped", + "difficulties", "other"}; + buffer.str(""); + buffer << "Problem is " << msg[iStatus - 1] << " - " << CoinCpuTime() - time1a + << " seconds"; + printGeneralMessage(model_, buffer.str()); break; } - clpSolver->setSpecialOptions(clpSolver->specialOptions() | IN_BRANCH_AND_BOUND); // say is Cbc (and in branch and bound) + clpSolver->setSpecialOptions( + clpSolver->specialOptions() | + IN_BRANCH_AND_BOUND); // say is Cbc (and in branch and + // bound) #elif CBC_OTHER_SOLVER == 1 #endif - if (!noPrinting_) { - sprintf(generalPrint, "Continuous objective value is %g - %.2f seconds", - solver->getObjValue(), CoinCpuTime() - time1a); - generalMessageHandler->message(CLP_GENERAL, generalMessages) - << generalPrint - << CoinMessageEol; - } + buffer.str(""); + buffer << "Continuous objective value is " << solver->getObjValue() << " - " + << CoinCpuTime() - time1a << " seconds"; + printGeneralMessage(model_, buffer.str()); if (model_.getMaximumNodes() == -987654321) { // See if No objective! int numberColumns = clpSolver->getNumCols(); @@ -3894,25 +3993,28 @@ int CbcMain1(int argc, const char *argv[], printf("************No objective!!\n"); model_.setMaximumSolutions(1); // Column copy - CoinPackedMatrix matrixByCol(*model_.solver()->getMatrixByCol()); - //const double * element = matrixByCol.getElements(); - //const int * row = matrixByCol.getIndices(); - //const CoinBigIndex * columnStart = matrixByCol.getVectorStarts(); + CoinPackedMatrix matrixByCol( + *model_.solver()->getMatrixByCol()); + // const double * element = matrixByCol.getElements(); + // const int * row = matrixByCol.getIndices(); + // const CoinBigIndex * columnStart = + // matrixByCol.getVectorStarts(); const int *columnLength = matrixByCol.getVectorLengths(); for (int i = 0; i < numberColumns; i++) { double value = (CoinDrand48() + 0.5) * 10000; value = 10; value *= columnLength[i]; - int iValue = static_cast< int >(value) / 10; - //iValue=1; + int iValue = static_cast(value) / 10; + // iValue=1; clpSolver->setObjCoeff(i, iValue); } } } #ifndef CBC_OTHER_SOLVER - if (!complicatedInteger && preProcess == 0 && clpSolver->tightenPrimalBounds(0.0, 0, true) != 0) { - sprintf(generalPrint, "Problem is infeasible - tightenPrimalBounds!"); - printGeneralMessage(model_, generalPrint); + if (!complicatedInteger && preProcess == 0 && + clpSolver->tightenPrimalBounds(0.0, 0, true) != 0) { + printGeneralMessage(model_, + "Problem is infeasible - tightenPrimalBounds!"); model_.setProblemStatus(0); model_.setSecondaryStatus(1); // say infeasible for solution @@ -3990,11 +4092,14 @@ int CbcMain1(int argc, const char *argv[], } } #ifdef COIN_DEVELOP - if (!noPrinting_) - std::cout << "Largest (scaled) away from bound " << largestScaled - << " unscaled " << largest << std::endl; + buffer.str(""); + buffer << "Largest (scaled) away from bound " + << largestScaled << " unscaled " << largest + << std::endl; + printGeneralMessage(model_, buffer.str()); #endif - clpSolver->setDualBound(CoinMax(1.0001e8, CoinMin(100.0 * largest, 1.00001e10))); + clpSolver->setDualBound( + CoinMax(1.0001e8, CoinMin(100.0 * largest, 1.00001e10))); } si->resolve(); // clean up #endif @@ -4005,19 +4110,19 @@ int CbcMain1(int argc, const char *argv[], if (!doScaling) solver->setHintParam(OsiDoScale, false, OsiHintTry); #ifndef CBC_OTHER_SOLVER - OsiClpSolverInterface *si = dynamic_cast< OsiClpSolverInterface * >(solver); + OsiClpSolverInterface *si = + dynamic_cast(solver); assert(si != NULL); // get clp itself ClpSimplex *modelC = si->getModelPtr(); - //if (modelC->tightenPrimalBounds()!=0) { - //std::cout<<"Problem is infeasible!"<tightenPrimalBounds()!=0) { + // std::cout<<"Problem is infeasible!"<tightenPrimalBounds(tightenFactor) != 0) { - sprintf(generalPrint, "Problem is infeasible!"); - printGeneralMessage(model_, generalPrint); + printGeneralMessage(model_, "Problem is infeasible!"); model_.setProblemStatus(0); model_.setSecondaryStatus(1); // and in babModel if exists @@ -4032,8 +4137,9 @@ int CbcMain1(int argc, const char *argv[], } // See if we want preprocessing - OsiSolverInterface *saveSolver = NULL; - CglPreProcess process; + // FIXME: Why does code break if this is defined here instead of up top? + //OsiSolverInterface *saveSolver = NULL; + //CglPreProcess process; // Say integers in sync bool integersOK = true; delete babModel_; @@ -4042,7 +4148,8 @@ int CbcMain1(int argc, const char *argv[], int numberChanged = 0; OsiSolverInterface *solver3 = clpSolver->clone(); babModel_->assignSolver(solver3); - OsiClpSolverInterface *clpSolver2 = dynamic_cast< OsiClpSolverInterface * >(babModel_->solver()); + OsiClpSolverInterface *clpSolver2 = + dynamic_cast(babModel_->solver()); if (clpSolver2->messageHandler()->logLevel()) clpSolver2->messageHandler()->setLogLevel(1); if (logLevel > -1) @@ -4062,10 +4169,14 @@ int CbcMain1(int argc, const char *argv[], if (numberRows < cutoff1) frequency = base + numberRows / freq0; else if (numberRows < cutoff2) - frequency = base + cutoff1 / freq0 + (numberRows - cutoff1) / freq1; + frequency = + base + cutoff1 / freq0 + (numberRows - cutoff1) / freq1; else - frequency = base + cutoff1 / freq0 + (cutoff2 - cutoff1) / freq1 + (numberRows - cutoff2) / freq2; - lpSolver->setFactorizationFrequency(CoinMin(maximum, frequency)); + frequency = base + cutoff1 / freq0 + + (cutoff2 - cutoff1) / freq1 + + (numberRows - cutoff2) / freq2; + lpSolver->setFactorizationFrequency( + CoinMin(maximum, frequency)); } #elif CBC_OTHER_SOLVER == 1 OsiSolverInterface *solver3 = model_.solver()->clone(); @@ -4073,7 +4184,7 @@ int CbcMain1(int argc, const char *argv[], #endif time2 = CoinCpuTime(); totalTime += time2 - time1; - //time1 = time2; + // time1 = time2; double timeLeft = babModel_->getMaximumSeconds(); int numberOriginalColumns = babModel_->solver()->getNumCols(); if (preProcess == 7) { @@ -4083,20 +4194,22 @@ int CbcMain1(int argc, const char *argv[], #ifdef COIN_HAS_LINK // empty out any cuts if (storedAmpl.sizeRowCuts()) { - printf("Emptying ampl stored cuts as internal preprocessing\n"); + printf( + "Emptying ampl stored cuts as internal preprocessing\n"); CglStored temp; storedAmpl = temp; } #endif } - if (preProcess && type == CBC_PARAM_ACTION_BAB) { + if (preProcess && cbcParamCode == CbcParam::BAB) { // see whether to switch off preprocessing // only allow SOS and integer OsiObject **objects = babModel_->objects(); int numberObjects = babModel_->numberObjects(); for (int iObj = 0; iObj < numberObjects; iObj++) { - CbcSOS *objSOS = dynamic_cast< CbcSOS * >(objects[iObj]); - CbcSimpleInteger *objSimpleInteger = dynamic_cast< CbcSimpleInteger * >(objects[iObj]); + CbcSOS *objSOS = dynamic_cast(objects[iObj]); + CbcSimpleInteger *objSimpleInteger = + dynamic_cast(objects[iObj]); if (!objSimpleInteger && !objSOS) { // find all integers anyway babModel_->findIntegers(true); @@ -4105,24 +4218,24 @@ int CbcMain1(int argc, const char *argv[], } } } - if (type == CBC_PARAM_ACTION_BAB) { + if (cbcParamCode == CbcParam::BAB) { if (preProcess == 0 && numberLotSizing) { if (!babModel_->numberObjects()) { /* model may not have created objects - If none then create - */ + If none then create + */ babModel_->findIntegers(true); } // Lotsizing - //int numberColumns = babModel_->solver()->getNumCols(); + // int numberColumns = babModel_->solver()->getNumCols(); CbcObject **objects = new CbcObject *[numberLotSizing]; - double points[] = { 0.0, 0.0, 0.0, 0.0 }; + double points[] = {0.0, 0.0, 0.0, 0.0}; for (int i = 0; i < numberLotSizing; i++) { int iColumn = lotsize[i].column; points[2] = lotsize[i].low; points[3] = lotsize[i].high; - objects[i] = new CbcLotsize(&model_, iColumn, 2, - points, true); + objects[i] = + new CbcLotsize(&model_, iColumn, 2, points, true); } babModel_->addObjects(numberLotSizing, objects); for (int i = 0; i < numberLotSizing; i++) @@ -4131,25 +4244,32 @@ int CbcMain1(int argc, const char *argv[], } double limit; clpSolver->getDblParam(OsiDualObjectiveLimit, limit); - if (clpSolver->getObjValue() * clpSolver->getObjSense() >= limit * clpSolver->getObjSense()) + if (clpSolver->getObjValue() * clpSolver->getObjSense() >= + limit * clpSolver->getObjSense()) preProcess = 0; } if (mipStartBefore.size()) { CbcModel tempModel = *babModel_; assert(babModel_->getNumCols() == model_.getNumCols()); - std::vector< std::string > colNames; + std::vector colNames; for (int i = 0; (i < model_.solver()->getNumCols()); ++i) colNames.push_back(model_.solver()->getColName(i)); - std::vector< double > x(model_.getNumCols(), 0.0); + std::vector x(model_.getNumCols(), 0.0); double obj; - int status = CbcMipStartIO::computeCompleteSolution(&tempModel, tempModel.solver(), colNames, mipStartBefore, &x[0], obj, 0, tempModel.messageHandler(), tempModel.messagesPointer()); + int status = CbcMipStartIO::computeCompleteSolution( + &tempModel, tempModel.solver(), colNames, mipStartBefore, + &x[0], obj, 0, tempModel.messageHandler(), + tempModel.messagesPointer()); // set cutoff ( a trifle high) if (!status) { - double newCutoff = CoinMin(babModel_->getCutoff(), obj + 1.0e-4); - babModel_->setBestSolution(&x[0], static_cast< int >(x.size()), obj, false); + double newCutoff = + CoinMin(babModel_->getCutoff(), obj + 1.0e-4); + babModel_->setBestSolution(&x[0], static_cast(x.size()), + obj, false); babModel_->setCutoff(newCutoff); babModel_->setSolutionCount(1); - model_.setBestSolution(&x[0], static_cast< int >(x.size()), obj, false); + model_.setBestSolution(&x[0], static_cast(x.size()), obj, + false); model_.setCutoff(newCutoff); model_.setSolutionCount(1); } @@ -4157,37 +4277,40 @@ int CbcMain1(int argc, const char *argv[], bool hasTimePreproc = !babModel_->maximumSecondsReached(); if (!hasTimePreproc) preProcess = 0; - // See if we need to skip preprocessing - if (preProcess) { - int numberGenerators = model_.numberCutGenerators(); - int iGenerator; - for (iGenerator = 0; iGenerator < numberGenerators; iGenerator++) { - CglCutGenerator *generator = - babModel_->cutGenerator(iGenerator)->generator(); - - if (generator->needsOriginalModel()) - break; - } - if (iGenerator < numberGenerators) { - preProcess = 0; + // See if we need to skip preprocessing + if (preProcess) { + int numberGenerators = model_.numberCutGenerators(); + int iGenerator; + for (iGenerator = 0; iGenerator < numberGenerators; + iGenerator++) { + CglCutGenerator *generator = + babModel_->cutGenerator(iGenerator)->generator(); + + if (generator->needsOriginalModel()) + break; + } + if (iGenerator < numberGenerators) { + preProcess = 0; printGeneralMessage(model_, - "PreProcessing switched off due to lazy constraints"); - } - } - if (preProcess && type == CBC_PARAM_ACTION_BAB) { + "PreProcessing switched off due to lazy constraints"); + } + } + if (preProcess && cbcParamCode == CbcParam::BAB) { saveSolver = babModel_->solver()->clone(); /* Do not try and produce equality cliques and do up to 10 passes */ OsiSolverInterface *solver2; { // Tell solver we are in Branch and Cut - saveSolver->setHintParam(OsiDoInBranchAndCut, true, OsiHintDo); + saveSolver->setHintParam(OsiDoInBranchAndCut, true, + OsiHintDo); // Default set of cut generators CglProbing generator1; generator1.setUsingObjective(1); generator1.setMaxPass(1); generator1.setMaxPassRoot(1); - generator1.setMaxProbeRoot(CoinMin(3000, saveSolver->getNumCols())); + generator1.setMaxProbeRoot( + CoinMin(3000, saveSolver->getNumCols())); generator1.setMaxElements(100); generator1.setMaxElementsRoot(200); generator1.setMaxLookRoot(50); @@ -4197,18 +4320,18 @@ int CbcMain1(int argc, const char *argv[], // switch off duplicate columns if we have a solution if (model_.bestSolution() /*||debugValues*/) tunePreProcess |= 4096; - // take off top - int tune2 = tunePreProcess % 10000; - if ((tune2 & (1|512)) != 0) { + // take off top + int tune2 = tunePreProcess % 10000; + if ((tune2 & (1 | 512)) != 0) { // heavy probing generator1.setMaxPassRoot(2); -#ifndef CBC_EXPERIMENT7 +#ifndef CBC_EXPERIMENT_JJF generator1.setMaxElements(1000); #else - if ((tune2 & 512) != 0) - generator1.setMaxElementsRoot(saveSolver->getNumCols()); - else - generator1.setMaxElements(1000); + if ((tune2 & 512) != 0) + generator1.setMaxElementsRoot(saveSolver->getNumCols()); + else + generator1.setMaxElements(1000); #endif generator1.setMaxProbeRoot(saveSolver->getNumCols()); if ((tune2 & 512) != 0) @@ -4223,12 +4346,12 @@ int CbcMain1(int argc, const char *argv[], process.addCutGenerator(&generator1); int translate[] = { 9999, 0, 0, -3, 2, 3, -2, 9999, 4, 5, 0 , -2}; process.passInMessageHandler(babModel_->messageHandler()); - //process.messageHandler()->setLogLevel(babModel_->logLevel()); - if (info.numberSos && doSOS && statusUserFunction_[0]) { + // process.messageHandler()->setLogLevel(babModel_->logLevel()); + if (info && info->numberSos && doSOS && statusUserFunction_[0]) { // SOS - numberSOS = info.numberSos; - sosStart = info.sosStart; - sosIndices = info.sosIndices; + numberSOS = info->numberSos; + sosStart = info->sosStart; + sosIndices = info->sosIndices; } if (numberSOS && doSOS) { // SOS @@ -4238,10 +4361,12 @@ int CbcMain1(int argc, const char *argv[], // worth looking to see if any members can be made integer int numberRows = saveSolver->getNumRows(); - const CoinPackedMatrix *matrixByCol = saveSolver->getMatrixByCol(); + const CoinPackedMatrix *matrixByCol = + saveSolver->getMatrixByCol(); const double *element = matrixByCol->getElements(); const int *row = matrixByCol->getIndices(); - const CoinBigIndex *columnStart = matrixByCol->getVectorStarts(); + const CoinBigIndex *columnStart = + matrixByCol->getVectorStarts(); const int *columnLength = matrixByCol->getVectorLengths(); const double *columnLower = saveSolver->getColLower(); const double *columnUpper = saveSolver->getColUpper(); @@ -4257,19 +4382,20 @@ int CbcMain1(int argc, const char *argv[], int numberChanged = 0; for (int iSet = 0; iSet < numberSOS; iSet++) { if (sosType[iSet] != 1) { - for (int i = sosStart[iSet]; - i < sosStart[iSet + 1]; i++) { + for (int i = sosStart[iSet]; i < sosStart[iSet + 1]; + i++) { numberInteresting2++; int iColumn = sosIndices[i]; prohibited[iColumn] = 1; } } else { int nUsed = 0; - for (int i = sosStart[iSet]; - i < sosStart[iSet + 1]; i++) { + for (int i = sosStart[iSet]; i < sosStart[iSet + 1]; + i++) { int iColumn = sosIndices[i]; for (CoinBigIndex j = columnStart[iColumn]; - j < columnStart[iColumn] + columnLength[iColumn]; j++) { + j < columnStart[iColumn] + columnLength[iColumn]; + j++) { int iRow = row[j]; double el = element[j]; if (rowCount[iRow]) { @@ -4286,7 +4412,8 @@ int CbcMain1(int argc, const char *argv[], double nonzeroValue = COIN_DBL_MAX; for (int iUsed = 0; iUsed < nUsed; iUsed++) { int iRow = rowUsed[iUsed]; - if (rowCount[iRow] == nInSet && sameElement[iRow] && rowLower[iRow] == rowUpper[iRow]) { + if (rowCount[iRow] == nInSet && sameElement[iRow] && + rowLower[iRow] == rowUpper[iRow]) { // all entries must be 0.0 or xx nonzeroValue = rowLower[iRow] / sameElement[iRow]; } @@ -4296,10 +4423,11 @@ int CbcMain1(int argc, const char *argv[], if (nonzeroValue != COIN_DBL_MAX) { // could do scaling otherwise if (fabs(nonzeroValue - 1.0) < 1.0e-8) { - for (int i = sosStart[iSet]; - i < sosStart[iSet + 1]; i++) { + for (int i = sosStart[iSet]; i < sosStart[iSet + 1]; + i++) { int iColumn = sosIndices[i]; - if (columnUpper[iColumn] < 0.0 || columnLower[iColumn] > 1.0) { + if (columnUpper[iColumn] < 0.0 || + columnLower[iColumn] > 1.0) { printf("sos says infeasible\n"); } if (!saveSolver->isInteger(iColumn)) { @@ -4319,8 +4447,8 @@ int CbcMain1(int argc, const char *argv[], #endif } } else { - for (int i = sosStart[iSet]; - i < sosStart[iSet + 1]; i++) { + for (int i = sosStart[iSet]; i < sosStart[iSet + 1]; + i++) { int iColumn = sosIndices[i]; #ifndef DO_LESS_PROHIBITED prohibited[iColumn] = 1; @@ -4328,8 +4456,8 @@ int CbcMain1(int argc, const char *argv[], } } } else { - for (int i = sosStart[iSet]; - i < sosStart[iSet + 1]; i++) { + for (int i = sosStart[iSet]; i < sosStart[iSet + 1]; + i++) { int iColumn = sosIndices[i]; if (!saveSolver->isInteger(iColumn)) numberInteresting1++; @@ -4342,11 +4470,11 @@ int CbcMain1(int argc, const char *argv[], } } if (numberChanged || numberInteresting1 || numberInteresting2) { - sprintf(generalPrint, "%d variables in SOS1 sets made integer, %d non integer in SOS1, %d in SOS2\n", - numberChanged, numberInteresting1, numberInteresting2); - generalMessageHandler->message(CLP_GENERAL, generalMessages) - << generalPrint - << CoinMessageEol; + buffer.str(""); + buffer << numberChanged << " variables in SOS1 sets made integer, " + << numberInteresting1 << " non integer in SOS1, " + << numberInteresting2 << " in SOS2" << std::endl; + printGeneralMessage(model_, buffer.str()); } delete[] sameElement; delete[] rowCount; @@ -4359,18 +4487,23 @@ int CbcMain1(int argc, const char *argv[], int numberColumns = saveSolver->getNumCols(); char *prohibited = new char[numberColumns]; memset(prohibited, 0, numberColumns); - const CoinPackedMatrix *matrix = saveSolver->getMatrixByCol(); + const CoinPackedMatrix *matrix = + saveSolver->getMatrixByCol(); const int *columnLength = matrix->getVectorLengths(); int numberProhibited = 0; - for (int iColumn = numberColumns - 1; iColumn >= 0; iColumn--) { - if (!saveSolver->isInteger(iColumn) || columnLength[iColumn] > 1) + for (int iColumn = numberColumns - 1; iColumn >= 0; + iColumn--) { + if (!saveSolver->isInteger(iColumn) || + columnLength[iColumn] > 1) break; numberProhibited++; prohibited[iColumn] = 1; } if (numberProhibited) { process.passInProhibited(prohibited, numberColumns); - printf("**** Treating last %d integers as special - give high priority?\n", numberProhibited); + printf("**** Treating last %d integers as special - give " + "high priority?\n", + numberProhibited); } delete[] prohibited; } @@ -4475,7 +4608,7 @@ int CbcMain1(int argc, const char *argv[], memset(prohibited, 0, numberColumns); int numberProhibited = 0; for (int iObj = 0; iObj < numberOldObjects; iObj++) { - CbcSOS *obj = dynamic_cast< CbcSOS * >(oldObjects[iObj]); + CbcSOS *obj = dynamic_cast(oldObjects[iObj]); if (obj) { int n = obj->numberMembers(); const int *which = obj->members(); @@ -4488,14 +4621,15 @@ int CbcMain1(int argc, const char *argv[], numberProhibited++; } } - CbcLotsize *obj2 = dynamic_cast< CbcLotsize * >(oldObjects[iObj]); + CbcLotsize *obj2 = + dynamic_cast(oldObjects[iObj]); if (obj2) { int iColumn = obj2->columnNumber(); prohibited[iColumn] = 1; numberProhibited++; } } - if (numberProhibited) + if (numberProhibited) process.passInProhibited(prohibited, numberColumns); delete[] prohibited; } @@ -4506,28 +4640,32 @@ int CbcMain1(int argc, const char *argv[], ClpSolve::SolveType method = ClpSolve::usePrimalorSprint; ClpSolve::PresolveType presolveType = ClpSolve::presolveOff; int numberPasses = 5; - int options[] = { 0, 3, 0, 0, 0, 0 }; - int extraInfo[] = { -1, 20, -1, -1, -1, -1 }; + int options[] = {0, 3, 0, 0, 0, 0}; + int extraInfo[] = {-1, 20, -1, -1, -1, -1}; extraInfo[1] = doSprint; - int independentOptions[] = { 0, 0, 3 }; + int independentOptions[] = {0, 0, 3}; ClpSolve clpSolve(method, presolveType, numberPasses, - options, extraInfo, independentOptions); + options, extraInfo, independentOptions); // say use in OsiClp clpSolve.setSpecialOption(6, 1); - OsiClpSolverInterface *osiclp = dynamic_cast< OsiClpSolverInterface * >(saveSolver); + OsiClpSolverInterface *osiclp = + dynamic_cast(saveSolver); osiclp->setSolveOptions(clpSolve); osiclp->setHintParam(OsiDoDualInResolve, false); // switch off row copy - osiclp->getModelPtr()->setSpecialOptions(osiclp->getModelPtr()->specialOptions() | 256); + osiclp->getModelPtr()->setSpecialOptions( + osiclp->getModelPtr()->specialOptions() | 256); osiclp->getModelPtr()->setInfeasibilityCost(1.0e11); } #endif #ifndef CBC_OTHER_SOLVER { - OsiClpSolverInterface *osiclp = dynamic_cast< OsiClpSolverInterface * >(saveSolver); + OsiClpSolverInterface *osiclp = + dynamic_cast(saveSolver); osiclp->setSpecialOptions(osiclp->specialOptions() | 1024); osiclp->getModelPtr()->setClpScaledMatrix(NULL); // safer - int savePerturbation = osiclp->getModelPtr()->perturbation(); + int savePerturbation = + osiclp->getModelPtr()->perturbation(); //#define CBC_TEMP1 #ifdef CBC_TEMP1 if (savePerturbation == 50) @@ -4537,31 +4675,38 @@ int CbcMain1(int argc, const char *argv[], process.setOptions(2 + 4 + 8); // no cuts cbcPreProcessPointer = &process; preProcessPointer = &process; // threadsafe - int saveOptions = osiclp->getModelPtr()->moreSpecialOptions(); - if ((model_.specialOptions() & 16777216) != 0 && model_.getCutoff() > 1.0e30) { - osiclp->getModelPtr()->setMoreSpecialOptions(saveOptions | 262144); + int saveOptions = + osiclp->getModelPtr()->moreSpecialOptions(); + if ((model_.specialOptions() & 16777216) != 0 && + model_.getCutoff() > 1.0e30) { + osiclp->getModelPtr()->setMoreSpecialOptions(saveOptions | + 262144); } #if DEBUG_PREPROCESS > 1 if (debugValues) { - process.setApplicationData(const_cast< double * >(debugValues)); + process.setApplicationData( + const_cast(debugValues)); } #endif - if (debugFile=="unitTest") { - babModel_->solver()->activateRowCutDebugger(argv[1]); - OsiRowCutDebugger * debugger = - babModel_->solver()->getRowCutDebuggerAlways(); - numberDebugValues = babModel_->getNumCols(); - debugValues = - CoinCopyOfArray(debugger->optimalSolution(), - numberDebugValues); - } + if (parameters[CbcParam::DEBUGFILE]->fileName() == + "unitTest") { + //This is probably wrong, will need to debug + babModel_->solver()->activateRowCutDebugger(inputQueue[0].c_str()); + OsiRowCutDebugger *debugger = + babModel_->solver()->getRowCutDebuggerAlways(); + numberDebugValues = babModel_->getNumCols(); + debugValues = CoinCopyOfArray(debugger->optimalSolution(), + numberDebugValues); + } redoSOS = true; - bool keepPPN = parameters_[whichParam(CBC_PARAM_STR_PREPROCNAMES, parameters_)].currentOptionAsInteger(); + bool keepPPN = parameters[CbcParam::PREPROCNAMES]->modeVal(); #ifdef SAVE_NAUTY - keepPPN = 1; + keepPPN = 1; #endif process.setKeepColumnNames(keepPPN); - process.setTimeLimit(babModel_->getMaximumSeconds() - babModel_->getCurrentSeconds(), babModel_->useElapsedTime()); + process.setTimeLimit(babModel_->getMaximumSeconds() - + babModel_->getCurrentSeconds(), + babModel_->useElapsedTime()); if (model.getKeepNamesPreproc()) process.setKeepColumnNames(true); if (keepPPN) @@ -4571,33 +4716,38 @@ int CbcMain1(int argc, const char *argv[], tunePreProcess); setPreProcessingMode(saveSolver,0); if (solver2) { - setPreProcessingMode(solver2,0); - model_.setOriginalColumns(process.originalColumns(), solver2->getNumCols()); + setPreProcessingMode(solver2, 0); + model_.setOriginalColumns(process.originalColumns(), + solver2->getNumCols()); osiclp->getModelPtr()->setPerturbation(savePerturbation); osiclp->getModelPtr()->setMoreSpecialOptions(saveOptions); - /* clean solvers - should be done in preProcess but - that doesn't know about Clp */ - OsiClpSolverInterface * solver; - solver = dynamic_cast(solver2); - solver->getModelPtr()->cleanScalingEtc(); - solver = dynamic_cast(process.originalModel()); - solver->getModelPtr()->cleanScalingEtc(); - solver = dynamic_cast(process.startModel()); - if (solver) - solver->getModelPtr()->cleanScalingEtc(); - int numberSolvers = process.numberSolvers(); - if (numberSolvers==99) - numberSolvers = 1; // really just 1 - // some of these may be same - for (int i=0;i(process.modelAtPass(i)); - if (solver) - solver->getModelPtr()->cleanScalingEtc(); - solver = dynamic_cast(process.modifiedModel(i)); - if (solver) - solver->getModelPtr()->cleanScalingEtc(); - } + /* clean solvers - should be done in preProcess but + that doesn't know about Clp */ + OsiClpSolverInterface *solver; + solver = dynamic_cast(solver2); + solver->getModelPtr()->cleanScalingEtc(); + solver = dynamic_cast( + process.originalModel()); + solver->getModelPtr()->cleanScalingEtc(); + solver = dynamic_cast( + process.startModel()); + if (solver) + solver->getModelPtr()->cleanScalingEtc(); + int numberSolvers = process.numberSolvers(); + if (numberSolvers == 99) + numberSolvers = 1; // really just 1 + // some of these may be same + for (int i = 0; i < numberSolvers; i++) { + solver = dynamic_cast( + process.modelAtPass(i)); + if (solver) + solver->getModelPtr()->cleanScalingEtc(); + solver = dynamic_cast( + process.modifiedModel(i)); + if (solver) + solver->getModelPtr()->cleanScalingEtc(); + } } } #elif CBC_OTHER_SOLVER == 1 @@ -4606,36 +4756,31 @@ int CbcMain1(int argc, const char *argv[], redoSOS = true; if (model.getKeepNamesPreproc()) process.setKeepColumnNames(true); - solver2 = process.preProcessNonDefault(*saveSolver, translate[preProcess], numberPasses, - tunePreProcess); + solver2 = process.preProcessNonDefault( + *saveSolver, translate[preProcess], numberPasses, + tunePreProcess); #endif integersOK = false; // We need to redo if CbcObjects exist // Tell solver we are not in Branch and Cut - saveSolver->setHintParam(OsiDoInBranchAndCut, false, OsiHintDo); + saveSolver->setHintParam(OsiDoInBranchAndCut, false, + OsiHintDo); if (solver2) - solver2->setHintParam(OsiDoInBranchAndCut, false, OsiHintDo); + solver2->setHintParam(OsiDoInBranchAndCut, false, + OsiHintDo); } - if (!solver2 && statusUserFunction_[0]) { + if (info && !solver2 && statusUserFunction_[0]) { // infeasible - info.problemStatus = 1; - info.objValue = 1.0e100; - sprintf(info.buffer, "infeasible/unbounded by pre-processing"); - info.primalSolution = NULL; - info.dualSolution = NULL; + info->problemStatus = 1; + info->objValue = 1.0e100; + sprintf(info->buffer, + "infeasible/unbounded by pre-processing"); + info->primalSolution = NULL; + info->dualSolution = NULL; break; } - if (!noPrinting_) { - if (!solver2) { - sprintf(generalPrint, "Pre-processing says infeasible or unbounded"); - generalMessageHandler->message(CLP_GENERAL, generalMessages) - << generalPrint - << CoinMessageEol; - } else { - //printf("processed model has %d rows, %d columns and %d elements\n", - // solver2->getNumRows(),solver2->getNumCols(),solver2->getNumElements()); - } - } if (!solver2) { + printGeneralMessage(model_, + "Pre-processing says infeasible or unbounded"); // say infeasible for solution integerStatus = 6; delete saveSolver; @@ -4645,6 +4790,9 @@ int CbcMain1(int argc, const char *argv[], babModel_->setProblemStatus(0); babModel_->setSecondaryStatus(1); } else { + // printf("processed model has %d rows, %d columns and %d + // elements\n", + // solver2->getNumRows(),solver2->getNumCols(),solver2->getNumElements()); statistics_nprocessedrows = solver2->getNumRows(); statistics_nprocessedcols = solver2->getNumCols(); model_.setProblemStatus(-1); @@ -4665,7 +4813,8 @@ int CbcMain1(int argc, const char *argv[], // need to redo - in case no better found in BAB // just get integer part right const int *originalColumns = process.originalColumns(); - int numberColumns = CoinMin(solver2->getNumCols(), babModel_->getNumCols()); + int numberColumns = + CoinMin(solver2->getNumCols(), babModel_->getNumCols()); double *bestSolution = babModel_->bestSolution(); const double *oldBestSolution = model_.bestSolution(); for (int i = 0; i < numberColumns; i++) { @@ -4674,9 +4823,26 @@ int CbcMain1(int argc, const char *argv[], } } //solver2->resolve(); +#ifdef CBC_NAMES_FOR_COMPARE + { + OsiClpSolverInterface * solver = + dynamic_cast(solver2); + ClpSimplex * simplex = solver->getModelPtr(); + int numberRows = simplex->numberRows(); + int numberColumns = simplex->numberColumns(); + int numberIntegers = 0; + for (int i=0;iisInteger(i)) + numberIntegers++; + } + printf("CbC %s after preprocessing %d rows, %d columns, %d integers\n", + simplex->problemName().c_str(),numberRows, + numberColumns,numberIntegers); + } +#endif if (preProcess == 2 || preProcess >= 10) { // names are wrong - redo - const int *originalColumns = process.originalColumns(); + const int *originalColumns = process.originalColumns(); int numberColumns = solver2->getNumCols(); OsiSolverInterface *originalSolver = model.solver(); int numberOriginalColumns = originalSolver->getNumCols(); @@ -4691,14 +4857,8 @@ int CbcMain1(int argc, const char *argv[], if (preProcess == 2) { strcpy(name, "presolved.mps"); } else { - //strcpy(name,lpSolver->problemName().c_str()); - int iParam; - for (iParam = 0; iParam < (int)parameters_.size(); iParam++) { - int match = parameters_[iParam].matches("import"); - if (match == 1) - break; - } - strcpy(name, parameters_[iParam].stringValue().c_str()); + strcpy(name, + parameters[CbcParam::IMPORTFILE]->fileName().c_str()); char *dot = strstr(name, ".mps"); if (!dot) dot = strstr(name, ".lp"); @@ -4708,7 +4868,7 @@ int CbcMain1(int argc, const char *argv[], } if (dot) { *dot = '\0'; - int n = static_cast< int >(dot - name); + int n = static_cast(dot - name); int i; for (i = n - 1; i >= 0; i--) { if (name[i] == '/') @@ -4731,11 +4891,14 @@ int CbcMain1(int argc, const char *argv[], } { // look at new integers - int numberOriginalColumns = process.originalModel()->getNumCols(); + int numberOriginalColumns = + process.originalModel()->getNumCols(); const int *originalColumns = process.originalColumns(); - OsiClpSolverInterface *osiclp2 = dynamic_cast< OsiClpSolverInterface * >(solver2); + OsiClpSolverInterface *osiclp2 = + dynamic_cast(solver2); int numberColumns = osiclp2->getNumCols(); - OsiClpSolverInterface *osiclp = dynamic_cast< OsiClpSolverInterface * >(saveSolver); + OsiClpSolverInterface *osiclp = + dynamic_cast(saveSolver); for (int i = 0; i < numberColumns; i++) { int iColumn = originalColumns[i]; if (iColumn < numberOriginalColumns) { @@ -4778,10 +4941,11 @@ int CbcMain1(int argc, const char *argv[], delete objects[i]; delete[] objects; if (numberLotSizing < n) { - sprintf(generalPrint, "Pre-processing reduced number of SC variables from %d to %d",n,numberLotSizing); - generalMessageHandler->message(CLP_GENERAL, generalMessages) - << generalPrint - << CoinMessageEol; + buffer.str(""); + buffer << "Pre-processing reduced number of SC" + << " variables from " << n << " to " + << numberLotSizing; + printGeneralMessage(model_, buffer.str()); } } // redo existing SOS @@ -4797,9 +4961,10 @@ int CbcMain1(int argc, const char *argv[], int numberSOSOld = osiclp->numberSOS(); int numberSOS = osiclp2->numberSOS(); assert(numberSOS == numberSOSOld); - CoinSet *setInfo = const_cast< CoinSet * >(osiclp2->setInfo()); + CoinSet *setInfo = + const_cast(osiclp2->setInfo()); for (int i = 0; i < numberSOS; i++) { - //int type = setInfo[i].setType(); + // int type = setInfo[i].setType(); int n = setInfo[i].numberEntries(); int *which = setInfo[i].modifiableWhich(); #ifndef DO_LESS_PROHIBITED @@ -4829,18 +4994,18 @@ int CbcMain1(int argc, const char *argv[], // we have to keep solver2 so pass clone solver2 = solver2->clone(); // see if extra variables wanted - int threshold = parameters_[whichParam(CBC_PARAM_INT_EXTRA_VARIABLES, parameters_)].intValue(); - int more2 = parameters_[whichParam(CBC_PARAM_INT_MOREMOREMIPOPTIONS, parameters_)].intValue(); + bool threshold = parameters[CbcParam::EXTRAVARIABLES]->intVal(); + int more2 = parameters[CbcParam::MOREMOREMIPOPTIONS]->intVal(); if (threshold || (more2 & (512 | 1024)) != 0) { int numberColumns = solver2->getNumCols(); truncateRows = solver2->getNumRows(); bool modifiedModel = false; int highPriority = 0; /* - normal - no priorities - >10000 equal high priority - >20000 higher priority for higher cost - */ + normal - no priorities + >10000 equal high priority + >20000 higher priority for higher cost + */ if (threshold > 10000) { highPriority = threshold / 10000; threshold -= 10000 * highPriority; @@ -4864,7 +5029,8 @@ int CbcMain1(int argc, const char *argv[], numberTotalIntegers++; if (columnUpper[iColumn] > columnLower[iColumn]) { numberIntegers++; - if (columnLower[iColumn] == 0.0 && columnUpper[iColumn] == 1) + if (columnLower[iColumn] == 0.0 && + columnUpper[iColumn] == 1) numberBinary++; } } @@ -4899,30 +5065,35 @@ int CbcMain1(int argc, const char *argv[], } } numberDifferentObj++; - sprintf(generalPrint, "Problem has %d integers (%d of which binary) and %d continuous", - numberIntegers, numberBinary, numberColumns - numberIntegers); - generalMessageHandler->message(CLP_GENERAL, generalMessages) - << generalPrint - << CoinMessageEol; + buffer.str(""); + buffer << "Problem has " << numberIntegers << " integers (" << numberBinary + << " of which are binary) and " << numberColumns - numberIntegers + << " continuous"; + printGeneralMessage(model_, buffer.str()); if (numberColumns > numberIntegers) { - sprintf(generalPrint, "%d continuous have nonzero objective, %d have zero objective", - numberContinuous, numberZeroContinuous); - generalMessageHandler->message(CLP_GENERAL, generalMessages) - << generalPrint - << CoinMessageEol; - } - sprintf(generalPrint, "%d integer have nonzero objective, %d have zero objective, %d different nonzero (taking abs)", - numberSort, numberZero, numberDifferentObj); - generalMessageHandler->message(CLP_GENERAL, generalMessages) - << generalPrint - << CoinMessageEol; - if (numberDifferentObj <= threshold + (numberZero) ? 1 : 0 && numberDifferentObj) { + buffer.str(""); + buffer << numberContinuous << " continuous have nonzero objective, " + << numberZeroContinuous << " have zero objective"; + printGeneralMessage(model_, buffer.str()); + } + buffer.str(""); + buffer << numberSort << " integer have nonzero objective, " + << numberZero << " have zero objective, " + << numberDifferentObj << " different nonzero (taking abs)"; + printGeneralMessage(model_, buffer.str()); + if (numberDifferentObj <= threshold + (numberZero) + ? 1 + : 0 && numberDifferentObj) { int *backward = NULL; if (highPriority) { - newPriorities = new int[numberTotalIntegers + numberDifferentObj + numberColumns]; - backward = newPriorities + numberTotalIntegers + numberDifferentObj; + newPriorities = + new int[numberTotalIntegers + numberDifferentObj + + numberColumns]; + backward = newPriorities + numberTotalIntegers + + numberDifferentObj; numberTotalIntegers = 0; - for (int iColumn = 0; iColumn < numberColumns; iColumn++) { + for (int iColumn = 0; iColumn < numberColumns; + iColumn++) { if (solver2->isInteger(iColumn)) { backward[iColumn] = numberTotalIntegers; newPriorities[numberTotalIntegers++] = 10000; @@ -4933,30 +5104,30 @@ int CbcMain1(int argc, const char *argv[], double last = obj[0]; for (int jColumn = 1; jColumn < numberSort; jColumn++) { if (fabs(obj[jColumn] - last) > 1.0e-12) { - sprintf(generalPrint, "%d variables have objective of %g", - jColumn - iLast, last); - generalMessageHandler->message(CLP_GENERAL, generalMessages) - << generalPrint - << CoinMessageEol; + buffer.str(""); + buffer << jColumn - iLast << " variables have objective of " + << last; + printGeneralMessage(model_, buffer.str()); iLast = jColumn; last = obj[jColumn]; } } - sprintf(generalPrint, "%d variables have objective of %g", - numberSort - iLast, last); - generalMessageHandler->message(CLP_GENERAL, generalMessages) - << generalPrint - << CoinMessageEol; + buffer.str(""); + buffer << numberSort - iLast << " variables have objective of " + << last; + printGeneralMessage(model_, buffer.str()); int spaceNeeded = numberSort + numberDifferentObj; - CoinBigIndex *columnAddDummy = new CoinBigIndex[numberDifferentObj + 1]; + CoinBigIndex *columnAddDummy = + new CoinBigIndex[numberDifferentObj + 1]; int *columnAdd = new int[spaceNeeded]; double *elementAdd = new double[spaceNeeded]; - CoinBigIndex *rowAdd = new CoinBigIndex[numberDifferentObj + 1]; + CoinBigIndex *rowAdd = + new CoinBigIndex[numberDifferentObj + 1]; double *objectiveNew = new double[3 * numberDifferentObj]; double *lowerNew = objectiveNew + numberDifferentObj; double *upperNew = lowerNew + numberDifferentObj; memset(columnAddDummy, 0, - (numberDifferentObj + 1) * sizeof(CoinBigIndex)); + (numberDifferentObj + 1) * sizeof(CoinBigIndex)); iLast = 0; last = obj[0]; numberDifferentObj = 0; @@ -4964,30 +5135,34 @@ int CbcMain1(int argc, const char *argv[], int numberElements = 0; rowAdd[0] = 0; for (int jColumn = 1; jColumn < numberSort + 1; jColumn++) { - if (jColumn == numberSort || fabs(obj[jColumn] - last) > 1.0e-12) { + if (jColumn == numberSort || + fabs(obj[jColumn] - last) > 1.0e-12) { // not if just one if (jColumn - iLast > 1) { // do priority if (highPriority == 1) { - newPriorities[numberTotalIntegers + numberDifferentObj] - = 500; + newPriorities[numberTotalIntegers + + numberDifferentObj] = 500; } else if (highPriority == 2) { - newPriorities[numberTotalIntegers + numberDifferentObj] - = priorityLevel; + newPriorities[numberTotalIntegers + + numberDifferentObj] = priorityLevel; priorityLevel--; } int iColumn = which[iLast]; objectiveNew[numberDifferentObj] = objective[iColumn]; double lower = 0.0; double upper = 0.0; - for (int kColumn = iLast; kColumn < jColumn; kColumn++) { + for (int kColumn = iLast; kColumn < jColumn; + kColumn++) { iColumn = which[kColumn]; if (moveObjective) solver2->setObjCoeff(iColumn, 0.0); double lowerValue = columnLower[iColumn]; double upperValue = columnUpper[iColumn]; double elementValue = -1.0; - if (objectiveNew[numberDifferentObj] * objective[iColumn] < 0.0) { + if (objectiveNew[numberDifferentObj] * + objective[iColumn] < + 0.0) { lowerValue = -columnUpper[iColumn]; upperValue = -columnLower[iColumn]; elementValue = 1.0; @@ -5009,7 +5184,8 @@ int CbcMain1(int argc, const char *argv[], upper = COIN_DBL_MAX; } } - columnAdd[numberElements] = numberColumns + numberDifferentObj; + columnAdd[numberElements] = + numberColumns + numberDifferentObj; elementAdd[numberElements++] = 1.0; lowerNew[numberDifferentObj] = lower; upperNew[numberDifferentObj] = upper; @@ -5035,13 +5211,13 @@ int CbcMain1(int argc, const char *argv[], } if (numberDifferentObj) { // add columns - solver2->addCols(numberDifferentObj, - columnAddDummy, NULL, NULL, - lowerNew, upperNew, objectiveNew); - // add constraints and make integer if all integer in group + solver2->addCols(numberDifferentObj, columnAddDummy, NULL, + NULL, lowerNew, upperNew, objectiveNew); + // add constraints and make integer if all integer in + // group #ifdef CBC_HAS_CLP - OsiClpSolverInterface *clpSolver2 - = dynamic_cast< OsiClpSolverInterface * >(solver2); + OsiClpSolverInterface *clpSolver2 = + dynamic_cast(solver2); #endif for (int iObj = 0; iObj < numberDifferentObj; iObj++) { lowerNew[iObj] = 0.0; @@ -5052,10 +5228,11 @@ int CbcMain1(int argc, const char *argv[], clpSolver2->setOptionalInteger(numberColumns + iObj); #endif } - solver2->addRows(numberDifferentObj, - rowAdd, columnAdd, elementAdd, - lowerNew, upperNew); - sprintf(generalPrint, "Replacing model - %d new variables", numberDifferentObj); + solver2->addRows(numberDifferentObj, rowAdd, columnAdd, + elementAdd, lowerNew, upperNew); + buffer.str(""); + buffer << "Replacing model - " + << numberDifferentObj << " new variables"; modifiedModel = true; } delete[] columnAdd; @@ -5101,11 +5278,19 @@ int CbcMain1(int argc, const char *argv[], newValues[n] = nearest; newColumn[n++] = iColumn; if (nearest > 0.0) { - newLower += CoinMax(columnLower[iColumn], -1.0e20) * nearest; - newUpper += CoinMin(columnUpper[iColumn], 1.0e20) * nearest; + newLower += + CoinMax(columnLower[iColumn], -1.0e20) * + nearest; + newUpper += + CoinMin(columnUpper[iColumn], 1.0e20) * + nearest; } else { - newUpper += CoinMax(columnLower[iColumn], -1.0e20) * nearest; - newLower += CoinMin(columnUpper[iColumn], 1.0e20) * nearest; + newUpper += + CoinMax(columnLower[iColumn], -1.0e20) * + nearest; + newLower += + CoinMin(columnUpper[iColumn], 1.0e20) * + nearest; } } } @@ -5113,7 +5298,8 @@ int CbcMain1(int argc, const char *argv[], } if (allInteger && n) { fudgeObjective = n; - solver2->addCol(0, NULL, NULL, newLower, newUpper, 0.0, "obj_col"); + solver2->addCol(0, NULL, NULL, newLower, newUpper, 0.0, + "obj_col"); solver2->setInteger(numberColumns); newValues[n] = -1.0; newColumn[n++] = numberColumns; @@ -5133,7 +5319,8 @@ int CbcMain1(int argc, const char *argv[], bool moveObj = false; addSlacks = 0; // get row copy - const CoinPackedMatrix *matrix = solver2->getMatrixByRow(); + const CoinPackedMatrix *matrix = + solver2->getMatrixByRow(); const double *element = matrix->getElements(); const int *column = matrix->getIndices(); const CoinBigIndex *rowStart = matrix->getVectorStarts(); @@ -5144,22 +5331,24 @@ int CbcMain1(int argc, const char *argv[], const double *columnUpper = solver2->getColUpper(); // maximum space for additional columns - CoinBigIndex *newColumnStart = new CoinBigIndex[numberRows + 1]; + CoinBigIndex *newColumnStart = + new CoinBigIndex[numberRows + 1]; newColumnStart[0] = 0; int *newRow = new int[numberRows]; double *newElement = new double[numberRows]; double *newObjective = new double[numberRows]; double *newColumnLower = new double[numberRows]; double *newColumnUpper = new double[numberRows]; - double *oldObjective = CoinCopyOfArray(solver2->getObjCoefficients(), - numberColumns); + double *oldObjective = CoinCopyOfArray( + solver2->getObjCoefficients(), numberColumns); for (iRow = 0; iRow < numberRows; iRow++) { if (rowLower[iRow] != rowUpper[iRow]) { bool allInteger = true; double newLower = 0.0; double newUpper = 0.0; double constantObjective = 0.0; - for (CoinBigIndex j = rowStart[iRow]; j < rowStart[iRow] + rowLength[iRow]; j++) { + for (CoinBigIndex j = rowStart[iRow]; + j < rowStart[iRow] + rowLength[iRow]; j++) { int iColumn = column[j]; if (!solver2->isInteger(iColumn)) { allInteger = false; @@ -5174,27 +5363,39 @@ int CbcMain1(int argc, const char *argv[], if (!oldObjective[iColumn]) constantObjective = COIN_DBL_MAX; if (!constantObjective) { - constantObjective = oldObjective[iColumn] / nearest; + constantObjective = + oldObjective[iColumn] / nearest; } else if (constantObjective != COIN_DBL_MAX) { - double newConstant = oldObjective[iColumn] / nearest; + double newConstant = + oldObjective[iColumn] / nearest; if (constantObjective > 0.0) { if (newConstant <= 0.0) constantObjective = COIN_DBL_MAX; else - constantObjective = CoinMin(constantObjective, newConstant); + constantObjective = CoinMin( + constantObjective, newConstant); } else { if (newConstant >= 0.0) constantObjective = COIN_DBL_MAX; else - constantObjective = CoinMax(constantObjective, newConstant); + constantObjective = CoinMax( + constantObjective, newConstant); } } if (nearest > 0.0) { - newLower += CoinMax(columnLower[iColumn], -1.0e20) * nearest; - newUpper += CoinMin(columnUpper[iColumn], 1.0e20) * nearest; + newLower += + CoinMax(columnLower[iColumn], -1.0e20) * + nearest; + newUpper += + CoinMin(columnUpper[iColumn], 1.0e20) * + nearest; } else { - newUpper += CoinMax(columnLower[iColumn], -1.0e20) * nearest; - newLower += CoinMin(columnUpper[iColumn], 1.0e20) * nearest; + newUpper += + CoinMax(columnLower[iColumn], -1.0e20) * + nearest; + newLower += + CoinMin(columnUpper[iColumn], 1.0e20) * + nearest; } } } @@ -5207,26 +5408,33 @@ int CbcMain1(int argc, const char *argv[], if (moveObj && constantObjective != COIN_DBL_MAX) { // move some of objective here if looks constant newObjective[addSlacks] = constantObjective; - for (CoinBigIndex j = rowStart[iRow]; j < rowStart[iRow] + rowLength[iRow]; j++) { + for (CoinBigIndex j = rowStart[iRow]; + j < rowStart[iRow] + rowLength[iRow]; j++) { int iColumn = column[j]; double value = element[j]; double nearest = floor(value + 0.5); - oldObjective[iColumn] -= nearest * constantObjective; + oldObjective[iColumn] -= + nearest * constantObjective; } } - newColumnLower[addSlacks] = CoinMax(newLower, ceil(rowLower[iRow])); + newColumnLower[addSlacks] = + CoinMax(newLower, ceil(rowLower[iRow])); ; - newColumnUpper[addSlacks] = CoinMin(newUpper, floor(rowUpper[iRow])); + newColumnUpper[addSlacks] = + CoinMin(newUpper, floor(rowUpper[iRow])); addSlacks++; } } } if (addSlacks) { solver2->setObjective(oldObjective); - solver2->addCols(addSlacks, newColumnStart, newRow, newElement, - newColumnLower, newColumnUpper, newObjective); - truncatedRhsLower = CoinCopyOfArray(solver2->getRowLower(), numberRows); - truncatedRhsUpper = CoinCopyOfArray(solver2->getRowUpper(), numberRows); + solver2->addCols(addSlacks, newColumnStart, newRow, + newElement, newColumnLower, + newColumnUpper, newObjective); + truncatedRhsLower = + CoinCopyOfArray(solver2->getRowLower(), numberRows); + truncatedRhsUpper = + CoinCopyOfArray(solver2->getRowUpper(), numberRows); for (int j = 0; j < addSlacks; j++) { int iRow = newRow[j]; solver2->setRowLower(iRow, 0.0); @@ -5242,99 +5450,112 @@ int CbcMain1(int argc, const char *argv[], if (fudgeObjective || addSlacks) { modifiedModel = true; if (fudgeObjective && addSlacks) { - sprintf(generalPrint, "Objective integer added with %d elements and %d Integer slacks added", - fudgeObjective, addSlacks); + buffer.str(""); + buffer << "Objective integer added with " + << fudgeObjective << " elements and " + << addSlacks << " Integer slacks added"; } else if (fudgeObjective) { // just objective - sprintf(generalPrint, "Objective integer added with %d elements", - fudgeObjective); + buffer.str(""); + buffer << "Objective integer added with " + << fudgeObjective << " elements", more2 &= ~1024; } else { // just slacks - sprintf(generalPrint, "%d Integer slacks added", addSlacks); + buffer.str(""); + buffer << addSlacks << " Integer slacks added", more2 &= ~512; } } else { more2 &= ~(512 | 1024); } - parameters_[whichParam(CBC_PARAM_INT_MOREMOREMIPOPTIONS, parameters_)].setIntValue(more2); + parameters[CbcParam::MOREMOREMIPOPTIONS]->setVal(more2); } if (modifiedModel) { - generalMessageHandler->message(CLP_GENERAL, generalMessages) - << generalPrint - << CoinMessageEol; + printGeneralMessage(model_, buffer.str()); truncateColumns = numberColumns; } } babModel_->assignSolver(solver2); babModel_->setOriginalColumns(process.originalColumns(), - truncateColumns); + truncateColumns); babModel_->initialSolve(); #if CBC_USE_INITIAL_TIME == 2 - // time starts from here? - time1Elapsed = CoinGetTimeOfDay(); - time1 = CoinCpuTime(); - if (babModel_->useElapsedTime()) - babModel_->setDblParam(CbcModel::CbcStartSeconds, CoinGetTimeOfDay()); - else - babModel_->setDblParam(CbcModel::CbcStartSeconds, CoinCpuTime()); - //babModel_->setMaximumSeconds(timeLeft - (CoinCpuTime() - time2)); -#endif - } - - if (cgraphAction == "off") { - // switch off new clique, odd wheel and clique strengthening - cliqueAction = 0; - oddWheelAction = 0; - clqstrAction = "off"; - } else if (cgraphAction == "clq") { - // old style - cliqueAction = 0; - oddWheelAction = 0; - clqstrAction = "off"; - } - if (clqstrAction == "after") { - CglCliqueStrengthening clqStr(babModel_->solver(), babModel_->messageHandler()); + // time starts from here? + time1Elapsed = CoinGetTimeOfDay(); + time1 = CoinCpuTime(); + if (babModel_->useElapsedTime()) + babModel_->setDblParam(CbcModel::CbcStartSeconds, + CoinGetTimeOfDay()); + else + babModel_->setDblParam(CbcModel::CbcStartSeconds, + CoinCpuTime()); + // babModel_->setMaximumSeconds(timeLeft - (CoinCpuTime() - + // time2)); +#endif + } + + if (cgraphMode == "off") { + // switch off new clique, odd wheel and clique strengthening + cliqueMode = CbcParameters::CGOff; + oddWheelMode = CbcParameters::CGOff; + clqstrMode = "off"; + } else if (cgraphMode == "clq") { + // old style + //CglClique clique; + //clique.setStarCliqueReport(false); + //clique.setRowCliqueReport(false); + //clique.setMinViolation(0.05); + //int translate[] = {-100, -1, -99, -98, 1, -1098}; + //babModel_->addCutGenerator(&clique, translate[cliqueMode], + // "Clique"); + cliqueMode = CbcParameters::CGOff; + parameters[CbcParam::CLIQUECUTS]->setVal("off"); + oddWheelMode = CbcParameters::CGOff; + parameters[CbcParam::ODDWHEELCUTS]->setVal("off"); + clqstrMode = "off"; + } + if (clqstrMode == "after") { + CglCliqueStrengthening clqStr(babModel_->solver(), + babModel_->messageHandler()); clqStr.strengthenCliques(4); - if (clqStr.constraintsExtended() + clqStr.constraintsDominated() > 0) { - OsiSolverInterface * solver = babModel_->solver(); - bool takeHint; - OsiHintStrength strength; - solver->getHintParam(OsiDoDualInResolve, - takeHint, strength); - solver->setHintParam(OsiDoDualInResolve, false,OsiHintTry); + if (clqStr.constraintsExtended() + + clqStr.constraintsDominated() > + 0) { + OsiSolverInterface *solver = babModel_->solver(); + bool takeHint; + OsiHintStrength strength; + solver->getHintParam(OsiDoDualInResolve, takeHint, strength); + solver->setHintParam(OsiDoDualInResolve, false, OsiHintTry); solver->resolve(); - solver->setHintParam(OsiDoDualInResolve, takeHint,strength); - - if (!noPrinting_ && (babModel_->messageHandler()->logLevel())) { - if (solver->isProvenPrimalInfeasible()) { - sprintf(generalPrint, "Clique Strengthening says infeasible!"); - generalMessageHandler->message(CLP_GENERAL, generalMessages) - << generalPrint - << CoinMessageEol; - } else { - sprintf(generalPrint, "After applying Clique Strengthening continuous objective value is %.2lf", solver->getObjValue()); - generalMessageHandler->message(CLP_GENERAL, generalMessages) - << generalPrint - << CoinMessageEol; - } + solver->setHintParam(OsiDoDualInResolve, takeHint, strength); + + if (solver->isProvenPrimalInfeasible()) { + printGeneralMessage(model_, + "Clique Strengthening says infeasible!"); + } else { + buffer.str(""); + buffer << "After applying Clique Strengthening continuous " + << "objective value is " + << solver->getObjValue(); + printGeneralMessage(model_, buffer.str()); } // results of clique Strengthening stengthening - } // checking impact of clique Strengthening stengthening - } // clique Strengthening + } // checking impact of clique Strengthening stengthening + } // clique Strengthening // now tighten bounds if (!miplib) { #ifndef CBC_OTHER_SOLVER - OsiClpSolverInterface *si = dynamic_cast< OsiClpSolverInterface * >(babModel_->solver()); + OsiClpSolverInterface *si = + dynamic_cast(babModel_->solver()); assert(si != NULL); // get clp itself ClpSimplex *modelC = si->getModelPtr(); - //if (noPrinting_) - //modelC->setLogLevel(0); + // if (noPrinting_) + // modelC->setLogLevel(0); if (!complicatedInteger && modelC->tightenPrimalBounds() != 0) { - sprintf(generalPrint, "Problem is infeasible!"); - printGeneralMessage(model_, generalPrint); + printGeneralMessage(model_, "Problem is infeasible!"); model_.setProblemStatus(0); model_.setSecondaryStatus(1); // say infeasible for solution @@ -5356,18 +5577,20 @@ int CbcMain1(int argc, const char *argv[], // for debug std::string problemName; babModel_->solver()->getStrParam(OsiProbName, problemName); - babModel_->solver()->activateRowCutDebugger(problemName.c_str()); + babModel_->solver()->activateRowCutDebugger( + problemName.c_str()); twomirGen.probname_ = CoinStrdup(problemName.c_str()); // checking seems odd - //redsplitGen.set_given_optsol(babModel_->solver()->getRowCutDebuggerAlways()->optimalSolution(), + // redsplitGen.set_given_optsol(babModel_->solver()->getRowCutDebuggerAlways()->optimalSolution(), // babModel_->getNumCols()); } - int testOsiOptions = parameters_[whichParam(CBC_PARAM_INT_TESTOSI, parameters_)].intValue(); + int testOsiOptions = parameters[CbcParam::TESTOSI]->intVal(); #ifndef JJF_ONE // If linked then see if expansion wanted { - OsiSolverLink *solver3 = dynamic_cast< OsiSolverLink * >(babModel_->solver()); - int options = parameters_[whichParam(CBC_PARAM_INT_MIPOPTIONS, parameters_)].intValue() / 10000; + OsiSolverLink *solver3 = + dynamic_cast(babModel_->solver()); + int options = parameters[CbcParam::MIPOPTIONS]->intVal() / 10000; if (solver3 || (options & 16) != 0) { if (options) { /* @@ -5378,22 +5601,27 @@ int CbcMain1(int argc, const char *argv[], 16 - try expanding knapsacks */ if ((options & 16)) { + // FIXME As far as I can see, saveCoinModel is never set anywhere. The only + // place it should have been set is in the AMPL parsing, but that block + // was never entered as far as I can see. Check whether this block is + // needed. int numberColumns = saveCoinModel.numberColumns(); int numberRows = saveCoinModel.numberRows(); whichColumn = new int[numberColumns]; knapsackStart = new int[numberRows + 1]; knapsackRow = new int[numberRows]; numberKnapsack = 10000; - int extra1 = parameters_[whichParam(CBC_PARAM_INT_EXTRA1, parameters_)].intValue(); - int extra2 = parameters_[whichParam(CBC_PARAM_INT_EXTRA2, parameters_)].intValue(); - int logLevel = parameters_[log].intValue(); - OsiSolverInterface *solver = expandKnapsack(saveCoinModel, whichColumn, knapsackStart, - knapsackRow, numberKnapsack, - storedAmpl, logLevel, extra1, extra2, - saveTightenedModel); + int extra1 = parameters[CbcParam::EXTRA1]->intVal(); + int extra2 = parameters[CbcParam::EXTRA2]->intVal(); + int logLevel = parameters[CbcParam::LPLOGLEVEL]->intVal(); + OsiSolverInterface *solver = expandKnapsack( + saveCoinModel, whichColumn, knapsackStart, + knapsackRow, numberKnapsack, storedAmpl, logLevel, + extra1, extra2, saveTightenedModel); if (solver) { #ifndef CBC_OTHER_SOLVER - clpSolver = dynamic_cast< OsiClpSolverInterface * >(solver); + clpSolver = + dynamic_cast(solver); assert(clpSolver); lpSolver = clpSolver->getModelPtr(); #endif @@ -5402,8 +5630,10 @@ int CbcMain1(int argc, const char *argv[], // allow gomory complicatedInteger = 0; // Priorities already done - free(info.priorities); - info.priorities = NULL; + if (info){ + free(info->priorities); + info->priorities = NULL; + } } else { numberKnapsack = 0; delete[] whichColumn; @@ -5426,7 +5656,8 @@ int CbcMain1(int argc, const char *argv[], const double *objective = babModel_->getObjCoefficients(); const double *lower = babModel_->getColLower(); const double *upper = babModel_->getColUpper(); - const CoinPackedMatrix *matrix = babModel_->solver()->getMatrixByCol(); + const CoinPackedMatrix *matrix = + babModel_->solver()->getMatrixByCol(); const int *columnLength = matrix->getVectorLengths(); int iColumn; int n = 0; @@ -5473,33 +5704,64 @@ int CbcMain1(int argc, const char *argv[], delete[] dsort; } // Set up heuristics - doHeuristics(babModel_, ((!miplib) ? 1 : 10), parameters_, - noPrinting_, initialPumpTune); + doHeuristics(babModel_, ((!miplib) ? 1 : 10), parameters, + parameters.noPrinting(), initialPumpTune); if (!miplib) { - if (parameters_[whichParam(CBC_PARAM_STR_LOCALTREE, parameters_)].currentOptionAsInteger()) { - CbcTreeLocal localTree(babModel_, NULL, 10, 0, 0, 10000, 2000); + if (parameters[CbcParam::LOCALTREE]->modeVal()) { + CbcTreeLocal localTree(babModel_, NULL, 10, 0, 0, 10000, + 2000); babModel_->passInTreeHandler(localTree); } } - if (type == CBC_PARAM_ACTION_MIPLIB) { - if (babModel_->numberStrong() == 5 && babModel_->numberBeforeTrust() == 5) + if (cbcParamCode == CbcParam::MIPLIB) { + if (babModel_->numberStrong() == 5 && + babModel_->numberBeforeTrust() == 5) babModel_->setNumberBeforeTrust(10); } - int experimentFlag = parameters_[whichParam(CBC_PARAM_INT_EXPERIMENT, parameters_)].intValue(); - int strategyFlag = parameters_[whichParam(CBC_PARAM_INT_STRATEGY, parameters_)].intValue(); + int experimentFlag = parameters[CbcParam::EXPERIMENT]->intVal(); + int strategyFlag = parameters[CbcParam::STRATEGY]->modeVal(); int bothFlags = CoinMax(CoinMin(experimentFlag, 1), strategyFlag); // add cut generators if wanted int switches[30] = {}; int accuracyFlag[30] = {}; char doAtEnd[30] = {}; + int lagrangeanFlag = + (parameters[CbcParam::MOREMOREMIPOPTIONS]->intVal()&(7*33554432))>>9; +#define ALL_LAGRANGEAN 1 int numberGenerators = 0; - int translate[] = { -100, -1, -99, -98, 1, -1098, -999, 1, 1, 1, -1 }; - int maximumSlowPasses = parameters_[whichParam(CBC_PARAM_INT_MAX_SLOW_CUTS, - parameters_)] - .intValue(); - if (probingAction) { + std::map translate; + translate[CbcParameters::CGOff] = -100; + translate[CbcParameters::CGOn] = -1; + translate[CbcParameters::CGRoot] = -99; + translate[CbcParameters::CGIfMove] = -98; + translate[CbcParameters::CGForceOn] = 1; + translate[CbcParameters::CGOnGlobal] = -1098; + translate[CbcParameters::CGForceOnGlobal] = -999; + translate[CbcParameters::CGForceOnBut] = 1; + translate[CbcParameters::CGForceOnStrong] = 1; + translate[CbcParameters::CGForceOnButStrong] = 1; + translate[CbcParameters::CGStrongRoot] = -1; + std::map laTranslate; + laTranslate[CbcParameters::CGEndOnlyRoot] = 1; + laTranslate[CbcParameters::CGEndCleanRoot] = 2; + laTranslate[CbcParameters::CGEndBothRoot] = 3; + laTranslate[CbcParameters::CGEndOnly] = 4; + laTranslate[CbcParameters::CGEndClean] = 5; + laTranslate[CbcParameters::CGEndBoth] = 6; + laTranslate[CbcParameters::CGOnlyAsWell] = 7; + laTranslate[CbcParameters::CGOnlyAsWellRoot] = 13; + laTranslate[CbcParameters::CGCleanAsWell] = 8; + laTranslate[CbcParameters::CGCleanAsWellRoot] =14; + laTranslate[CbcParameters::CGBothAsWell] = 9; + laTranslate[CbcParameters::CGBothAsWellRoot] = 15; + laTranslate[CbcParameters::CGOnlyInstead] = 10; + laTranslate[CbcParameters::CGCleanInstead] = 11; + laTranslate[CbcParameters::CGBothInstead] = 12; + int maximumSlowPasses = parameters[CbcParam::MAXSLOWCUTS]->intVal(); + assert (parameters[CbcParam::PROBINGCUTS]->modeVal()==probingMode); + if (probingMode) { int numberColumns = babModel_->solver()->getNumCols(); - if (probingAction > 7) { + if (probingMode > CbcParameters::CGForceOnBut) { probingGen.setMaxElements(numberColumns); probingGen.setMaxElementsRoot(numberColumns); } @@ -5507,9 +5769,11 @@ int CbcMain1(int argc, const char *argv[], probingGen.setMaxProbeRoot(123); probingGen.setMaxProbe(123); probingGen.setMaxLookRoot(20); - if (probingAction == 7 || probingAction == 9) + if (probingMode == CbcParameters::CGForceOnBut || + probingMode == CbcParameters::CGForceOnButStrong) probingGen.setRowCuts(-3); // strengthening etc just at root - if (probingAction == 8 || probingAction == 9) { + if (probingMode == CbcParameters::CGForceOnStrong || + probingMode == CbcParameters::CGForceOnButStrong) { // Number of unsatisfied variables to look at probingGen.setMaxProbeRoot(numberColumns); probingGen.setMaxProbe(numberColumns); @@ -5517,32 +5781,34 @@ int CbcMain1(int argc, const char *argv[], probingGen.setMaxLook(50); probingGen.setMaxLookRoot(50); } - if (probingAction == 10) { + if (probingMode == CbcParameters::CGStrongRoot) { probingGen.setMaxPassRoot(2); probingGen.setMaxProbeRoot(numberColumns); probingGen.setMaxLookRoot(numberColumns); } // If 5 then force on - int iAction = translate[probingAction]; - if (probingAction == 5) - iAction = 1; - babModel_->addCutGenerator(&probingGen, iAction, "Probing"); + int iMode = translate[probingMode]; + if (probingMode == CbcParameters::CGOnGlobal) + iMode = 1; + babModel_->addCutGenerator(&probingGen, iMode, "Probing"); accuracyFlag[numberGenerators] = 5; switches[numberGenerators++] = 0; } - if (gomoryAction && (complicatedInteger != 1 || (gomoryAction == 1 || gomoryAction >= 4))) { + assert (parameters[CbcParam::GOMORYCUTS]->modeVal()==gomoryMode); + if (gomoryMode && (complicatedInteger != 1 || + (gomoryMode == 1 || gomoryMode >= 4))) { // try larger limit int numberColumns = babModel_->getNumCols(); - if (gomoryAction == 7) { - gomoryAction = 4; + if (gomoryMode == CbcParameters::CGForceOnBut) { + gomoryMode = CbcParameters::CGForceOn; gomoryGen.setLimitAtRoot(numberColumns); gomoryGen.setLimit(numberColumns); - } else if (gomoryAction == 8) { - gomoryAction = 3; + } else if (gomoryMode == CbcParameters::CGForceOnStrong) { + gomoryMode = CbcParameters::CGIfMove; gomoryGen.setLimitAtRoot(numberColumns); gomoryGen.setLimit(200); - } else if (gomoryAction == 9) { - gomoryAction = 3; + } else if (gomoryMode == CbcParameters::CGForceOnButStrong) { + gomoryMode = CbcParameters::CGIfMove; gomoryGen.setLimitAtRoot(500); gomoryGen.setLimit(200); } else if (numberColumns > 5000) { @@ -5553,7 +5819,7 @@ int CbcMain1(int argc, const char *argv[], gomoryGen.setLimit(200); #else gomoryGen.setLimitAtRoot(2000); - //gomoryGen.setLimit(200); + // gomoryGen.setLimit(200); #endif } else { #ifdef MORE_CUTS2 @@ -5562,7 +5828,7 @@ int CbcMain1(int argc, const char *argv[], gomoryGen.setLimit(200); #endif } - int cutLength = parameters_[whichParam(CBC_PARAM_INT_CUTLENGTH, parameters_)].intValue(); + int cutLength = parameters[CbcParam::CUTLENGTH]->intVal(); if (cutLength != -1) { gomoryGen.setLimitAtRoot(cutLength); if (cutLength < 10000000) { @@ -5571,15 +5837,16 @@ int CbcMain1(int argc, const char *argv[], gomoryGen.setLimit(cutLength % 10000000); } } - int laGomory = parameters_[whichParam(CBC_PARAM_STR_LAGOMORYCUTS, parameters_)].currentOptionAsInteger(); - int gType = translate[gomoryAction]; + int laGomory = parameters[CbcParam::LAGOMORYCUTS]->modeVal(); + int gType = translate[gomoryMode]; if (!laGomory) { // Normal - babModel_->addCutGenerator(&gomoryGen, translate[gomoryAction], "Gomory"); + babModel_->addCutGenerator(&gomoryGen, + translate[gomoryMode], "Gomory"); accuracyFlag[numberGenerators] = 3; - switches[numberGenerators++] = 0; + switches[numberGenerators++] = lagrangeanFlag; } else { - laGomory--; + laGomory = laTranslate[laGomory]-1; int type = (laGomory % 3) + 1; int when = laGomory / 3; char atEnd = (when < 2) ? 1 : 0; @@ -5609,10 +5876,11 @@ int CbcMain1(int argc, const char *argv[], accuracyFlag[numberGenerators] = 3; doAtEnd[numberGenerators] = atEnd; if (atEnd) { - babModel_->cutGenerator(numberGenerators)->setMaximumTries(99999999); + babModel_->cutGenerator(numberGenerators) + ->setMaximumTries(99999999); babModel_->cutGenerator(numberGenerators)->setHowOften(1); } - switches[numberGenerators++] = 0; + switches[numberGenerators++] = 16384; } if ((type & 2) != 0) { // simple @@ -5621,10 +5889,11 @@ int CbcMain1(int argc, const char *argv[], accuracyFlag[numberGenerators] = 3; doAtEnd[numberGenerators] = atEnd; if (atEnd) { - babModel_->cutGenerator(numberGenerators)->setMaximumTries(99999999); + babModel_->cutGenerator(numberGenerators) + ->setMaximumTries(99999999); babModel_->cutGenerator(numberGenerators)->setHowOften(1); } - switches[numberGenerators++] = 0; + switches[numberGenerators++] = 32768; } } } @@ -5636,118 +5905,140 @@ int CbcMain1(int argc, const char *argv[], switches[numberGenerators++] = 0; } #endif - if (knapsackAction) { - babModel_->addCutGenerator(&knapsackGen, translate[knapsackAction], "Knapsack"); + assert (parameters[CbcParam::KNAPSACKCUTS]->modeVal()==knapsackMode); + if (knapsackMode) { + babModel_->addCutGenerator( + &knapsackGen, translate[knapsackMode], "Knapsack"); accuracyFlag[numberGenerators] = 1; switches[numberGenerators++] = -2; } - if (redsplitAction && !complicatedInteger) { - babModel_->addCutGenerator(&redsplitGen, translate[redsplitAction], "Reduce-and-split"); + if (redsplitMode && !complicatedInteger) { + babModel_->addCutGenerator(&redsplitGen, + translate[redsplitMode], + "Reduce-and-split"); accuracyFlag[numberGenerators] = 5; // slow ? - just do a few times - if (redsplitAction != 1) { - babModel_->cutGenerator(numberGenerators)->setMaximumTries(maximumSlowPasses); + if (redsplitMode != CbcParameters::CGOn) { + babModel_->cutGenerator(numberGenerators) + ->setMaximumTries(maximumSlowPasses); babModel_->cutGenerator(numberGenerators)->setHowOften(10); } - switches[numberGenerators++] = 1; + switches[numberGenerators++] = 1 | (ALL_LAGRANGEAN*lagrangeanFlag); } - if (redsplit2Action && !complicatedInteger) { + if (redsplit2Mode && !complicatedInteger) { int maxLength = 256; - if (redsplit2Action > 2) { - redsplit2Action -= 2; + if (redsplit2Mode > CbcParameters::CGRoot) { + redsplit2Mode -= 2; maxLength = COIN_INT_MAX; } CglRedSplit2Param ¶meters = redsplit2Gen.getParam(); parameters.setMaxNonzeroesTab(maxLength); - babModel_->addCutGenerator(&redsplit2Gen, translate[redsplit2Action], "Reduce-and-split(2)"); + babModel_->addCutGenerator(&redsplit2Gen, + translate[redsplit2Mode], + "Reduce-and-split(2)"); accuracyFlag[numberGenerators] = 5; // slow ? - just do a few times - if (redsplit2Action != 1) { - babModel_->cutGenerator(numberGenerators)->setHowOften(maximumSlowPasses); - babModel_->cutGenerator(numberGenerators)->setMaximumTries(maximumSlowPasses); + if (redsplit2Mode != CbcParameters::CGOn) { + babModel_->cutGenerator(numberGenerators) + ->setHowOften(maximumSlowPasses); + babModel_->cutGenerator(numberGenerators) + ->setMaximumTries(maximumSlowPasses); babModel_->cutGenerator(numberGenerators)->setHowOften(5); } - switches[numberGenerators++] = 1; + switches[numberGenerators++] = 1 | (ALL_LAGRANGEAN*lagrangeanFlag); } - if (GMIAction && !complicatedInteger) { - if (GMIAction > 5) { + if (GMIMode && !complicatedInteger) { + if (GMIMode > CbcParameters::CGOnGlobal) { // long - GMIAction -= 5; + GMIMode -= 5; CglGMIParam ¶meters = GMIGen.getParam(); parameters.setMaxSupportRel(1.0); } - babModel_->addCutGenerator(&GMIGen, translate[GMIAction], "Gomory(2)"); - if (GMIAction == 5) { + babModel_->addCutGenerator(&GMIGen, translate[GMIMode], + "Gomory(2)"); + if (GMIMode == CbcParameters::CGOnGlobal) { // just at end and root - GMIAction = 2; + GMIMode = CbcParameters::CGRoot; doAtEnd[numberGenerators] = 1; - babModel_->cutGenerator(numberGenerators)->setMaximumTries(99999999); + babModel_->cutGenerator(numberGenerators) + ->setMaximumTries(99999999); babModel_->cutGenerator(numberGenerators)->setHowOften(1); } accuracyFlag[numberGenerators] = 5; - switches[numberGenerators++] = 0; + switches[numberGenerators++] = 0 | (ALL_LAGRANGEAN*lagrangeanFlag); } - if (cliqueAction) { + if (cliqueMode) { bkCliqueGen.setMaxCallsBK(maxCallsBK); bkCliqueGen.setExtendingMethod(bkClqExtMethod); bkCliqueGen.setPivotingStrategy(bkPivotingStrategy); - babModel_->addCutGenerator(&bkCliqueGen, translate[cliqueAction], "Clique"); + babModel_->addCutGenerator(&bkCliqueGen, + translate[cliqueMode], "Clique"); accuracyFlag[numberGenerators] = 0; switches[numberGenerators++] = 0; - } else if (cgraphAction == "clq") { + } else if (cgraphMode == "clq") { // old style CglClique clique; clique.setStarCliqueReport(false); clique.setRowCliqueReport(false); clique.setMinViolation(0.05); // ifmove - babModel_->addCutGenerator(&clique, translate[cliqueAction], + babModel_->addCutGenerator(&clique, translate[oldCliqueMode], "Clique"); accuracyFlag[numberGenerators] = 0; switches[numberGenerators++] = 0; } - if (oddWheelAction) { + assert (parameters[CbcParam::ODDWHEELCUTS]->modeVal()==oddWheelMode); + if (oddWheelMode) { oddWheelGen.setExtendingMethod(oddWExtMethod); - babModel_->addCutGenerator(&oddWheelGen, translate[oddWheelAction], "OddWheel"); + babModel_->addCutGenerator( + &oddWheelGen, translate[oddWheelMode], "OddWheel"); accuracyFlag[numberGenerators] = 0; switches[numberGenerators++] = 0; } - if (mixedAction) { - babModel_->addCutGenerator(&mixedGen, translate[mixedAction], "MixedIntegerRounding2"); + assert (parameters[CbcParam::MIRCUTS]->modeVal()==mixedMode); + if (mixedMode) { + babModel_->addCutGenerator(&mixedGen, translate[mixedMode], + "MixedIntegerRounding2"); accuracyFlag[numberGenerators] = 2; - switches[numberGenerators++] = 0; + switches[numberGenerators++] = 0 | (ALL_LAGRANGEAN*lagrangeanFlag); } - if (flowAction) { - babModel_->addCutGenerator(&flowGen, translate[flowAction], "FlowCover"); + assert (parameters[CbcParam::FLOWCUTS]->modeVal()==flowMode); + if (flowMode) { + babModel_->addCutGenerator(&flowGen, translate[flowMode], + "FlowCover"); accuracyFlag[numberGenerators] = 2; - switches[numberGenerators++] = 0; + switches[numberGenerators++] = 0 | (ALL_LAGRANGEAN*lagrangeanFlag); } - if (twomirAction && (complicatedInteger != 1 || (twomirAction == 1 || twomirAction >= 4))) { + if (twomirMode && (complicatedInteger != 1 || + (twomirMode == CbcParameters::CGOn || + twomirMode >= CbcParameters::CGForceOn))) { // try larger limit int numberColumns = babModel_->getNumCols(); - if (twomirAction == 7) { - twomirAction = 4; + if (twomirMode == CbcParameters::CGForceOnBut) { + twomirMode = CbcParameters::CGForceOn; twomirGen.setMaxElements(numberColumns); - } else if (numberColumns > 5000 && twomirAction == 4) { + } else if (numberColumns > 5000 && twomirMode == CbcParameters::CGForceOn) { twomirGen.setMaxElements(2000); } - int laTwomir = parameters_[whichParam(CBC_PARAM_STR_LATWOMIRCUTS, parameters_)].currentOptionAsInteger(); - int twomirType = translate[twomirAction]; + int laTwomir = parameters[CbcParam::LATWOMIRCUTS]->modeVal(); + int twomirType = translate[twomirMode]; if (!laTwomir) { // Normal - babModel_->addCutGenerator(&twomirGen, translate[twomirAction], "TwoMirCuts"); + babModel_->addCutGenerator( + &twomirGen, translate[twomirMode], "TwoMirCuts"); accuracyFlag[numberGenerators] = 4; - switches[numberGenerators++] = 1; + switches[numberGenerators++] = 1 | lagrangeanFlag; } else { - laTwomir--; + laTwomir = laTranslate[laTwomir]-1; int type = (laTwomir % 3) + 1; int when = laTwomir / 3; char atEnd = (when < 2) ? 1 : 0; int twomirTypeMajor = 10; if (when < 3) { // normal as well - babModel_->addCutGenerator(&twomirGen, translate[twomirAction], "TwoMirCuts"); + babModel_->addCutGenerator( + &twomirGen, translate[twomirMode], "TwoMirCuts"); accuracyFlag[numberGenerators] = 4; switches[numberGenerators++] = 1; if (when == 2) @@ -5762,71 +6053,93 @@ int CbcMain1(int argc, const char *argv[], if ((type & 1) != 0) { // clean twomirGen.setTwomirType(twomirTypeMajor + 1); - babModel_->addCutGenerator(&twomirGen, twomirType, "TwoMirCutsL1"); + babModel_->addCutGenerator(&twomirGen, twomirType, + "TwoMirCutsL1"); accuracyFlag[numberGenerators] = 4; doAtEnd[numberGenerators] = atEnd; - switches[numberGenerators++] = atEnd ? 0 : 1; + switches[numberGenerators++] = (atEnd ? 0 : 1) | 16384; } if ((type & 2) != 0) { // simple twomirGen.setTwomirType(twomirTypeMajor + 2); - babModel_->addCutGenerator(&twomirGen, twomirType, "TwoMirCutsL2"); + babModel_->addCutGenerator(&twomirGen, twomirType, + "TwoMirCutsL2"); accuracyFlag[numberGenerators] = 4; doAtEnd[numberGenerators] = atEnd; - switches[numberGenerators++] = atEnd ? 0 : 1; + switches[numberGenerators++] = (atEnd ? 0 : 1) | 32768; } } } #ifndef DEBUG_MALLOC - if (landpAction) { - if (landpAction==5) { - // allow longer - landpGen.parameter().maximumCutLength = 2000000; - landpAction = 3; - } - babModel_->addCutGenerator(&landpGen, translate[landpAction], "LiftAndProject"); + assert (parameters[CbcParam::LANDPCUTS]->modeVal()==landpMode); + if (landpMode) { + if (landpMode == CbcParameters::CGOnGlobal) { + // allow longer + landpGen.parameter().maximumCutLength = 2000000; + landpMode = CbcParameters::CGIfMove; + } + babModel_->addCutGenerator(&landpGen, translate[landpMode], + "LiftAndProject"); accuracyFlag[numberGenerators] = 5; // slow ? - just do a few times - if (landpAction != 1) { - babModel_->cutGenerator(numberGenerators)->setMaximumTries(maximumSlowPasses); - babModel_->cutGenerator(numberGenerators)->setHowOften(10); + if (landpMode != CbcParameters::CGOn) { + babModel_->cutGenerator(numberGenerators) + ->setMaximumTries(maximumSlowPasses); + babModel_->cutGenerator(numberGenerators)->setHowOften(10); } - switches[numberGenerators++] = 1; + switches[numberGenerators++] = 1 | (ALL_LAGRANGEAN*lagrangeanFlag); } #endif - if (residualCapacityAction) { - babModel_->addCutGenerator(&residualCapacityGen, translate[residualCapacityAction], "ResidualCapacity"); + assert (parameters[CbcParam::RESIDCAPCUTS]->modeVal()==residualCapacityMode); + if (residualCapacityMode) { + babModel_->addCutGenerator(&residualCapacityGen, + translate[residualCapacityMode], + "ResidualCapacity"); accuracyFlag[numberGenerators] = 5; - switches[numberGenerators++] = 1; + switches[numberGenerators++] = 1 | (ALL_LAGRANGEAN*lagrangeanFlag); } - if (zerohalfAction) { - if (zerohalfAction > 4) { - //zerohalfAction -=4; + if (zerohalfMode) { + if (zerohalfMode > CbcParameters::CGForceOn) { + // zerohalfMode -=4; zerohalfGen.setFlags(1); } - babModel_->addCutGenerator(&zerohalfGen, translate[zerohalfAction], "ZeroHalf"); + babModel_->addCutGenerator( + &zerohalfGen, translate[zerohalfMode], "ZeroHalf"); accuracyFlag[numberGenerators] = 5; - babModel_->cutGenerator(numberGenerators)->setNeedsRefresh(true); - switches[numberGenerators++] = 2; + babModel_->cutGenerator(numberGenerators) + ->setNeedsRefresh(true); + switches[numberGenerators++] = 2; //| (ALL_LAGRANGEAN*lagrangeanFlag); } if (dominatedCuts) babModel_->setSpecialOptions(babModel_->specialOptions() | 64); // Say we want timings numberGenerators = babModel_->numberCutGenerators(); int iGenerator; - int cutDepth = parameters_[whichParam(CBC_PARAM_INT_CUTDEPTH, parameters_)].intValue(); - for (iGenerator = 0; iGenerator < numberGenerators; iGenerator++) { - CbcCutGenerator *generator = babModel_->cutGenerator(iGenerator); + int cutDepth = parameters[CbcParam::CUTDEPTH]->intVal(); + for (iGenerator = 0; iGenerator < numberGenerators; + iGenerator++) { + CbcCutGenerator *generator = + babModel_->cutGenerator(iGenerator); int howOften = generator->howOften(); + int iSwitch = switches[iGenerator]; + int iSwitch2, iSwitch3; + if (iSwitch>=0) { + iSwitch2 = iSwitch&127; + iSwitch3 = iSwitch & ~16383; + // say if wants modified solver + generator->setSwitches(generator->switches()|iSwitch3); + } else { + iSwitch2 = iSwitch; + } if (howOften == -98 || howOften == -99 || generator->maximumTries() > 0) - generator->setSwitchOffIfLessThan(switches[iGenerator]); + generator->setSwitchOffIfLessThan(iSwitch2); // Use if any at root as more likely later and fairly cheap - //if (switches[iGenerator]==-2) - //generator->setWhetherToUse(true); + // if (switches[iGenerator]==-2) + // generator->setWhetherToUse(true); generator->setInaccuracy(accuracyFlag[iGenerator]); if (doAtEnd[iGenerator]) { generator->setWhetherCallAtEnd(true); - //generator->setMustCallAgain(true); + // generator->setMustCallAgain(true); } generator->setTiming(true); if (cutDepth >= 0) @@ -5834,13 +6147,16 @@ int CbcMain1(int argc, const char *argv[], } // Could tune more if (!miplib) { - double minimumDrop = fabs(babModel_->solver()->getObjValue()) * 1.0e-5 + 1.0e-5; + double minimumDrop = + fabs(babModel_->solver()->getObjValue()) * 1.0e-5 + 1.0e-5; babModel_->setMinimumDrop(CoinMin(5.0e-2, minimumDrop)); if (cutPass == -1234567) { if (babModel_->getNumCols() < 500) - babModel_->setMaximumCutPassesAtRoot(-100); // always do 100 if possible + babModel_->setMaximumCutPassesAtRoot( + -100); // always do 100 if possible else if (babModel_->getNumCols() < 5000) - babModel_->setMaximumCutPassesAtRoot(100); // use minimum drop + babModel_->setMaximumCutPassesAtRoot( + 100); // use minimum drop else babModel_->setMaximumCutPassesAtRoot(50); } else { @@ -5854,43 +6170,46 @@ int CbcMain1(int argc, const char *argv[], babModel_->setMaximumCutPassesAtRoot(cutPass); } // Do more strong branching if small - //if (babModel_->getNumCols()<5000) - //babModel_->setNumberStrong(20); + // if (babModel_->getNumCols()<5000) + // babModel_->setNumberStrong(20); // Switch off strong branching if wanted - //if (babModel_->getNumCols()>10*babModel_->getNumRows()) - //babModel_->setNumberStrong(0); - if (!noPrinting_) { - int iLevel = parameters_[log].intValue(); + // if (babModel_->getNumCols()>10*babModel_->getNumRows()) + // babModel_->setNumberStrong(0); + if (!parameters.noPrinting()) { + int iLevel = parameters[CbcParam::LOGLEVEL]->intVal(); if (iLevel < 0) { if (iLevel > -10) { babModel_->setPrintingMode(1); } else { babModel_->setPrintingMode(2); iLevel += 10; - parameters_[log].setIntValue(iLevel); + parameters[CbcParam::LOGLEVEL]->setVal(iLevel); } iLevel = -iLevel; } babModel_->messageHandler()->setLogLevel(iLevel); - //if (babModel_->getNumCols() > 2000 || babModel_->getNumRows() > 1500 || babModel_->messageHandler()->logLevel() > 1) + // if (babModel_->getNumCols() > 2000 || babModel_->getNumRows() + // > 1500 || babModel_->messageHandler()->logLevel() > 1) // babModel_->setPrintFrequency(100); babModel_->setPrintFrequency(1); } - babModel_->solver()->setIntParam(OsiMaxNumIterationHotStart, - parameters_[whichParam(CBC_PARAM_INT_MAXHOTITS, parameters_)].intValue()); + babModel_->solver()->setIntParam( + OsiMaxNumIterationHotStart, + parameters[CbcParam::MAXHOTITS]->intVal()); #ifndef CBC_OTHER_SOLVER - OsiClpSolverInterface *osiclp = dynamic_cast< OsiClpSolverInterface * >(babModel_->solver()); + OsiClpSolverInterface *osiclp = + dynamic_cast(babModel_->solver()); // go faster stripes if ((osiclp->getNumRows() < 300 && osiclp->getNumCols() < 500)) { - osiclp->setupForRepeatedUse(2, parameters_[slog].intValue()); + osiclp->setupForRepeatedUse(2, parameters[CbcParam::LPLOGLEVEL]->intVal()); if (bothFlags >= 1) { ClpSimplex *lp = osiclp->getModelPtr(); int specialOptions = lp->specialOptions(); lp->setSpecialOptions(specialOptions | (2048 + 4096)); } } else { - osiclp->setupForRepeatedUse(0, parameters_[slog].intValue()); + osiclp->setupForRepeatedUse(0, parameters[CbcParam::LPLOGLEVEL]->intVal()); } if (bothFlags >= 2) { ClpSimplex *lp = osiclp->getModelPtr(); @@ -5901,7 +6220,8 @@ int CbcMain1(int argc, const char *argv[], ; int *changed = NULL; if (!miplib && increment == normalIncrement) - changed = analyze(osiclp, numberChanged, increment, false, generalMessageHandler, noPrinting); + changed = analyze(osiclp, numberChanged, increment, false, + generalMessageHandler, parameters.noPrinting()); #elif CBC_OTHER_SOLVER == 1 double increment = babModel_->getCutoffIncrement(); ; @@ -5936,7 +6256,7 @@ int CbcMain1(int argc, const char *argv[], siCopy->initialSolve(); if (siCopy->isProvenOptimal()) { memcpy(newValues, siCopy->getColSolution(), - numberColumns * sizeof(double)); + numberColumns * sizeof(double)); } else { printf("BAD debug file\n"); siCopy->writeMps("Bad"); @@ -5955,15 +6275,15 @@ int CbcMain1(int argc, const char *argv[], #endif } } - babModel_->setCutoffIncrement(CoinMax(babModel_->getCutoffIncrement(), increment)); + babModel_->setCutoffIncrement( + CoinMax(babModel_->getCutoffIncrement(), increment)); // Turn this off if you get problems // Used to be automatically set - int mipOptions = parameters_[whichParam(CBC_PARAM_INT_MIPOPTIONS, parameters_)].intValue() % 10000; + int mipOptions = parameters[CbcParam::MIPOPTIONS]->intVal() % 10000; if (mipOptions != (1057) && mipOptions != 1025) { - sprintf(generalPrint, "mip options %d", mipOptions); - generalMessageHandler->message(CLP_GENERAL, generalMessages) - << generalPrint - << CoinMessageEol; + buffer.str(""); + buffer << "mip options " << mipOptions; + printGeneralMessage(model_, buffer.str()); } #ifndef CBC_OTHER_SOLVER osiclp->setSpecialOptions(mipOptions); @@ -5972,26 +6292,30 @@ int CbcMain1(int argc, const char *argv[], // probably faster to use a basis to get integer solutions babModel_->setSpecialOptions(babModel_->specialOptions() | 2); currentBranchModel = babModel_; - //OsiSolverInterface * strengthenedModel=NULL; - if (type == CBC_PARAM_ACTION_BAB || type == CBC_PARAM_ACTION_MIPLIB) { + // OsiSolverInterface * strengthenedModel=NULL; + if (cbcParamCode == CbcParam::BAB || + cbcParamCode == CbcParam::MIPLIB) { if (strategyFlag == 1) { // try reduced model - babModel_->setSpecialOptions(babModel_->specialOptions() | 512); + babModel_->setSpecialOptions(babModel_->specialOptions() | + 512); } if (experimentFlag >= 5 || strategyFlag == 2) { // try reduced model at root - babModel_->setSpecialOptions(babModel_->specialOptions() | 32768); - if (experimentFlag >= 10000) { - // try reduced model at root with cuts - babModel_->setSpecialOptions(babModel_->specialOptions() | 512); - } - } + babModel_->setSpecialOptions(babModel_->specialOptions() | + 32768); + if (experimentFlag >= 10000) { + // try reduced model at root with cuts + babModel_->setSpecialOptions(babModel_->specialOptions() | + 512); + } + } { - int depthMiniBab = parameters_[whichParam(CBC_PARAM_INT_DEPTHMINIBAB, parameters_)].intValue(); + int depthMiniBab = parameters[CbcParam::DEPTHMINIBAB]->intVal(); if (depthMiniBab != -1) babModel_->setFastNodeDepth(depthMiniBab); } - int extra4 = parameters_[whichParam(CBC_PARAM_INT_EXTRA4, parameters_)].intValue(); + int extra4 = parameters[CbcParam::EXTRA4]->intVal(); if (extra4 >= 0) { int strategy = extra4 % 10; extra4 /= 10; @@ -6000,18 +6324,20 @@ int CbcMain1(int argc, const char *argv[], extra4 = strategy + method * 8 + extra4 * 1024; babModel_->setMoreSpecialOptions(extra4); } - int moreMipOptions = parameters_[whichParam(CBC_PARAM_INT_MOREMIPOPTIONS, parameters_)].intValue(); + int moreMipOptions = parameters[CbcParam::MOREMIPOPTIONS]->intVal(); if (moreMipOptions >= 0) { - sprintf(generalPrint, "more mip options %d", moreMipOptions); - generalMessageHandler->message(CLP_GENERAL, generalMessages) - << generalPrint - << CoinMessageEol; + buffer.str(""); + buffer << "more mip options" << moreMipOptions; + printGeneralMessage(model_, buffer.str()); #if 1 // some options may have been set already // e.g. use elapsed time - babModel_->setMoreSpecialOptions(moreMipOptions | babModel_->moreSpecialOptions()); + babModel_->setMoreSpecialOptions( + moreMipOptions | babModel_->moreSpecialOptions()); #else - OsiClpSolverInterface *osiclp = dynamic_cast< OsiClpSolverInterface * >(babModel_->solver()); + OsiClpSolverInterface *osiclp = + dynamic_cast( + babModel_->solver()); if (moreMipOptions == 10000) { // test memory saving moreMipOptions -= 10000; @@ -6019,28 +6345,31 @@ int CbcMain1(int argc, const char *argv[], lpSolver->setPersistenceFlag(1); // switch off row copy if few rows if (lpSolver->numberRows() < 150) - lpSolver->setSpecialOptions(lpSolver->specialOptions() | 256); + lpSolver->setSpecialOptions(lpSolver->specialOptions() | + 256); } if (moreMipOptions < 10000 && moreMipOptions) { if (((moreMipOptions + 1) % 1000000) != 0) babModel_->setSearchStrategy(moreMipOptions % 1000000); } else if (moreMipOptions < 100000) { // try reduced model - babModel_->setSpecialOptions(babModel_->specialOptions() | 512); + babModel_->setSpecialOptions(babModel_->specialOptions() | + 512); } // go faster stripes if (moreMipOptions >= 999999) { if (osiclp) { int save = osiclp->specialOptions(); osiclp->setupForRepeatedUse(2, 0); - osiclp->setSpecialOptions(save | osiclp->specialOptions()); + osiclp->setSpecialOptions(save | + osiclp->specialOptions()); } } #endif } } { - int extra1 = parameters_[whichParam(CBC_PARAM_INT_EXTRA1, parameters_)].intValue(); + int extra1 = parameters[CbcParam::EXTRA1]->intVal(); if (extra1 != -1) { if (extra1 < 0) { if (extra1 == -7777) @@ -6062,47 +6391,52 @@ int CbcMain1(int argc, const char *argv[], babModel_->setWhenCuts(999998); } } - if (type == CBC_PARAM_ACTION_BAB) { - if (statusUserFunction_[0]) { - priorities = info.priorities; - branchDirection = info.branchDirection; - pseudoDown = info.pseudoDown; - pseudoUp = info.pseudoUp; - solutionIn = info.primalSolution; - prioritiesIn = info.priorities; - if (info.numberSos && doSOS) { + if (cbcParamCode == CbcParam::BAB) { + if (info && statusUserFunction_[0]) { + priorities = info->priorities; + branchDirection = info->branchDirection; + pseudoDown = info->pseudoDown; + pseudoUp = info->pseudoUp; + solutionIn = info->primalSolution; + prioritiesIn = info->priorities; + if (info->numberSos && doSOS) { // SOS - numberSOS = info.numberSos; - sosStart = info.sosStart; - sosIndices = info.sosIndices; - sosType = info.sosType; - sosReference = info.sosReference; - sosPriority = info.sosPriority; + numberSOS = info->numberSos; + sosStart = info->sosStart; + sosIndices = info->sosIndices; + sosType = info->sosType; + sosReference = info->sosReference; + sosPriority = info->sosPriority; } } - const int *originalColumns = preProcess ? process.originalColumns() : NULL; + const int *originalColumns = + preProcess ? process.originalColumns() : NULL; if (model.getMIPStart().size()) mipStart = model.getMIPStart(); std::string testEmpty = mipStartFile.substr(0, 6); - if ((mipStart.size() || testEmpty == "empty.") && !mipStartBefore.size() - && babModel_->getNumCols()) { - std::vector< std::string > colNames; + if ((mipStart.size() || testEmpty == "empty.") && + !mipStartBefore.size() && babModel_->getNumCols()) { + std::vector colNames; if (preProcess) { /* translating mipstart solution */ - std::map< std::string, double > mipStartV; + std::map mipStartV; for (size_t i = 0; (i < mipStart.size()); ++i) mipStartV[mipStart[i].first] = mipStart[i].second; - std::vector< std::pair< std::string, double > > mipStart2; - for (int i = 0; (i < babModel_->solver()->getNumCols()); ++i) { + std::vector > mipStart2; + for (int i = 0; (i < babModel_->solver()->getNumCols()); + ++i) { int iColumn = babModel_->originalColumns()[i]; if (iColumn >= 0 && iColumn < model.getNumCols()) { - std::string cname = model_.solver()->getColName(iColumn); + std::string cname = + model_.solver()->getColName(iColumn); colNames.push_back(cname); babModel_->solver()->setColName(i, cname); - std::map< std::string, double >::const_iterator msIt = mipStartV.find(cname); + std::map::const_iterator msIt = + mipStartV.find(cname); if (msIt != mipStartV.end()) - mipStart2.push_back(std::pair< std::string, double >(cname, msIt->second)); + mipStart2.push_back(std::pair( + cname, msIt->second)); } else { // created variable char newName[15]; @@ -6112,30 +6446,40 @@ int CbcMain1(int argc, const char *argv[], } mipStart = mipStart2; } else { - for (int i = 0; (i < babModel_->solver()->getNumCols()); ++i) + for (int i = 0; (i < babModel_->solver()->getNumCols()); + ++i) colNames.push_back(model_.solver()->getColName(i)); } - //printf("--- %s %d\n", babModel_->solver()->getColName(0).c_str(), babModel_->solver()->getColNames().size() ); - //printf("-- SIZES of models %d %d %d\n", model_.getNumCols(), babModel_->solver()->getNumCols(), babModel_->solver()->getColNames().size() ); - std::vector< double > x(babModel_->getNumCols(), 0.0); + // printf("--- %s %d\n", + // babModel_->solver()->getColName(0).c_str(), + // babModel_->solver()->getColNames().size() ); printf("-- + // SIZES of models %d %d %d\n", model_.getNumCols(), + // babModel_->solver()->getNumCols(), + // babModel_->solver()->getColNames().size() ); + std::vector x(babModel_->getNumCols(), 0.0); double obj; babModel_->findIntegers(true); int extraActions = 0; int lengthFileName = mipStartFile.size(); - const char *checkEnd[6] = { - ".low", ".high", ".lowcheap", ".highcheap", ".lowexpensive", ".highexpensive" - }; + const char *checkEnd[6] = {".low", ".high", + ".lowcheap", ".highcheap", + ".lowexpensive", ".highexpensive"}; for (extraActions = 0; extraActions < 6; extraActions++) { - if (ends_with(mipStartFile, std::string(checkEnd[extraActions]))) + if (ends_with(mipStartFile, + std::string(checkEnd[extraActions]))) break; } if (extraActions == 6) extraActions = 0; else extraActions++; - int status = CbcMipStartIO::computeCompleteSolution(babModel_, babModel_->solver(), colNames, mipStart, &x[0], obj, extraActions, babModel_->messageHandler(), babModel_->messagesPointer()); + int status = CbcMipStartIO::computeCompleteSolution( + babModel_, babModel_->solver(), colNames, mipStart, &x[0], + obj, extraActions, babModel_->messageHandler(), + babModel_->messagesPointer()); if (!status) { - // need to check more babModel_->setBestSolution( &x[0], static_cast(x.size()), obj, false ); + // need to check more babModel_->setBestSolution( &x[0], + // static_cast(x.size()), obj, false ); OsiBabSolver dummy; babModel_->passInSolverCharacteristics(&dummy); babModel_->createContinuousSolver(); @@ -6217,6 +6561,13 @@ int CbcMain1(int argc, const char *argv[], babModel_->setCutoff(-obj-increment); babModel_->setMinimizationObjValue(-obj); } + /* But this is outside branchAndBound so needs to know + about direction */ + if (babModel_->getObjSense() == -1.0) { + double increment = obj - babModel_->getCutoff(); + babModel_->setCutoff(-obj - increment); + babModel_->setMinimizationObjValue(-obj); + } babModel_->clearContinuousSolver(); babModel_->passInSolverCharacteristics(NULL); if (useSolution == 0) @@ -6234,7 +6585,8 @@ int CbcMain1(int argc, const char *argv[], } else { n = babModel_->getNumCols(); } - prioritiesIn = reinterpret_cast< int * >(malloc(n * sizeof(int))); + prioritiesIn = + reinterpret_cast(malloc(n * sizeof(int))); for (int i = 0; i < n; i++) prioritiesIn[i] = 100; } @@ -6268,25 +6620,29 @@ int CbcMain1(int argc, const char *argv[], prioritiesIn2[i] = prioritiesIn2[iColumn]; } if (useSolution) - babModel_->setHotstartSolution(solutionIn2, prioritiesIn2); + babModel_->setHotstartSolution(solutionIn2, + prioritiesIn2); else babModel_->setBestSolution(solutionIn2, numberColumns, - COIN_DBL_MAX, true); + COIN_DBL_MAX, true); delete[] solutionIn2; delete[] prioritiesIn2; } else { if (useSolution) babModel_->setHotstartSolution(solutionIn, prioritiesIn); else - babModel_->setBestSolution(solutionIn, babModel_->getNumCols(), - COIN_DBL_MAX, true); + babModel_->setBestSolution(solutionIn, + babModel_->getNumCols(), + COIN_DBL_MAX, true); } } - OsiSolverInterface *testOsiSolver = (testOsiOptions >= 0) ? babModel_->solver() : NULL; + OsiSolverInterface *testOsiSolver = + (testOsiOptions >= 0) ? babModel_->solver() : NULL; if (!testOsiSolver) { // ************************************************************* // CbcObjects - if (preProcess && (process.numberSOS() || babModel_->numberObjects())) { + if (preProcess && + (process.numberSOS() || babModel_->numberObjects())) { int numberSOS = process.numberSOS(); int numberIntegers = babModel_->numberIntegers(); /* model may not have created objects @@ -6309,12 +6665,14 @@ int CbcMain1(int argc, const char *argv[], int n = CoinMin(truncateColumns, numberColumns); // allow for empty problem n = (n) ? originalColumns[n - 1] + 1 : 0; - n = CoinMax(n, CoinMax(numberColumns, numberOriginalColumns)); + n = CoinMax(n, + CoinMax(numberColumns, numberOriginalColumns)); int *newColumn = new int[n]; int i; for (i = 0; i < numberOriginalColumns; i++) newColumn[i] = -1; - for (i = 0; i < CoinMin(truncateColumns, numberColumns); i++) + for (i = 0; i < CoinMin(truncateColumns, numberColumns); + i++) newColumn[originalColumns[i]] = i; int nMissing = 0; for (int iObj = 0; iObj < numberOldObjects; iObj++) { @@ -6323,7 +6681,8 @@ int CbcMain1(int argc, const char *argv[], int iColumn = oldObjects[iObj]->columnNumber(); if (iColumn < 0 || iColumn >= numberOriginalColumns) { if (redoSOS) { // now done earlier?? - CbcSOS *obj = dynamic_cast< CbcSOS * >(oldObjects[iObj]); + CbcSOS *obj = + dynamic_cast(oldObjects[iObj]); if (obj) { int n = obj->numberMembers(); int *which = obj->mutableMembers(); @@ -6347,17 +6706,21 @@ int CbcMain1(int argc, const char *argv[], if (originalColumns) iColumn = originalColumns[iColumn]; if (branchDirection) { - CbcSimpleInteger *obj = dynamic_cast< CbcSimpleInteger * >(oldObjects[iObj]); + CbcSimpleInteger *obj = + dynamic_cast(oldObjects[iObj]); if (obj) { obj->setPreferredWay(branchDirection[iColumn]); } else { - CbcObject *obj = dynamic_cast< CbcObject * >(oldObjects[iObj]); + CbcObject *obj = + dynamic_cast(oldObjects[iObj]); assert(obj); obj->setPreferredWay(branchDirection[iColumn]); } } if (pseudoUp) { - CbcSimpleIntegerPseudoCost *obj1a = dynamic_cast< CbcSimpleIntegerPseudoCost * >(oldObjects[iObj]); + CbcSimpleIntegerPseudoCost *obj1a = + dynamic_cast( + oldObjects[iObj]); assert(obj1a); if (pseudoDown[iColumn] > 0.0) obj1a->setDownPseudoCost(pseudoDown[iColumn]); @@ -6367,13 +6730,14 @@ int CbcMain1(int argc, const char *argv[], } if (nMissing) { #ifndef DO_LESS_PROHIBITED - sprintf(generalPrint, "%d SOS variables vanished due to pre processing? - check validity?", nMissing); + buffer.str(""); + buffer << nMissing << " SOS variables vanished due to preprocessing?" + << " - check validity?"; #else - sprintf(generalPrint, "%d SOS variables eliminated by pre processing", nMissing); + buffer.str(""); + buffer << nMissing << " SOS variables eliminated by preprocessing"; #endif - generalMessageHandler->message(CLP_GENERAL, generalMessages) - << generalPrint - << CoinMessageEol; + printGeneralMessage(model_, buffer.str()); } delete[] newColumn; const int *starts = process.startSOS(); @@ -6386,11 +6750,12 @@ int CbcMain1(int argc, const char *argv[], int n = starts[iSOS + 1] - iStart; //#define MAKE_SOS_CLIQUES #ifndef MAKE_SOS_CLIQUES - objects[iSOS] = new CbcSOS(babModel_, n, which + iStart, weight + iStart, - iSOS, type[iSOS]); + objects[iSOS] = + new CbcSOS(babModel_, n, which + iStart, + weight + iStart, iSOS, type[iSOS]); #else - objects[iSOS] = new CbcClique(babModel_, 1, n, which + iStart, - NULL, -iSOS - 1); + objects[iSOS] = new CbcClique( + babModel_, 1, n, which + iStart, NULL, -iSOS - 1); #endif // branch on long sets first objects[iSOS]->setPriority(numberColumns - n); @@ -6400,7 +6765,8 @@ int CbcMain1(int argc, const char *argv[], for (iSOS = 0; iSOS < numberSOS; iSOS++) delete objects[iSOS]; delete[] objects; - } else if (priorities || branchDirection || pseudoDown || pseudoUp || numberSOS) { + } else if (priorities || branchDirection || pseudoDown || + pseudoUp || numberSOS) { // do anyway for priorities etc int numberIntegers = babModel_->numberIntegers(); /* model may not have created objects @@ -6457,33 +6823,35 @@ int CbcMain1(int argc, const char *argv[], delete[] back; if (nMissing) { #ifndef DO_LESS_PROHIBITED - sprintf(generalPrint, "%d SOS variables vanished due to pre processing? - check validity?", nMissing); + buffer.str(""); + buffer << nMissing << " SOS variables vanished due to preprocessing?" + << " - check validity?"; #else - sprintf(generalPrint, "%d SOS variables eliminated by pre processing", nMissing); + buffer.str(""); + buffer << nMissing << " SOS variables eliminated by preprocessing"; #endif - generalMessageHandler->message(CLP_GENERAL, generalMessages) - << generalPrint - << CoinMessageEol; + printGeneralMessage(model_, buffer.str()); } } - int sosPriorityOption = parameters_[whichParam(CBC_PARAM_STR_SOSPRIORITIZE, parameters_)].currentOptionAsInteger(); + int sosPriorityOption = + parameters[CbcParam::SOSPRIORITIZE]->modeVal(); if (sosPriorityOption) { const char *msg[4] = { - "high with equal priority", - "low with equal priority", - "high but with decreasing priority", - "low and decreasing priority" - }; - sprintf(generalPrint, "Setting %d SOS priorities %s", numberSOS, msg[sosPriorityOption - 1]); - generalMessageHandler->message(CLP_GENERAL, generalMessages) - << generalPrint - << CoinMessageEol; + "high with equal priority", + "low with equal priority", + "high but with decreasing priority", + "low and decreasing priority"}; + buffer.str(""); + buffer << "Setting " << numberSOS << " SOS priorities " + << msg[sosPriorityOption - 1]; + printGeneralMessage(model_, buffer.str()); } for (iSOS = 0; iSOS < numberSOS; iSOS++) { int iStart = sosStart[iSOS]; int n = sosStart[iSOS + 1] - iStart; - CbcSOS *sosObject = new CbcSOS(babModel_, n, sosIndices + iStart, sosReference + iStart, - iSOS, sosType[iSOS]); + CbcSOS *sosObject = new CbcSOS( + babModel_, n, sosIndices + iStart, + sosReference + iStart, iSOS, sosType[iSOS]); if (sosPriority) { sosObject->setPriority(sosPriority[iSOS]); } else if (sosPriorityOption) { @@ -6512,8 +6880,8 @@ int CbcMain1(int argc, const char *argv[], int nNew = 0; for (int i = 0; i < numberObjects; i++) { OsiObject *objThis = oldObjects[i]; - CbcSOS *obj1 = dynamic_cast< CbcSOS * >(objThis); - OsiSOS *obj2 = dynamic_cast< OsiSOS * >(objThis); + CbcSOS *obj1 = dynamic_cast(objThis); + OsiSOS *obj2 = dynamic_cast(objThis); if (!obj1 && !obj2) { oldObjects[nNew++] = objThis; } else { @@ -6531,12 +6899,13 @@ int CbcMain1(int argc, const char *argv[], int numberObjects = babModel_->numberObjects(); for (int iObj = 0; iObj < numberObjects; iObj++) { // skip sos - CbcSOS *objSOS = dynamic_cast< CbcSOS * >(objects[iObj]); + CbcSOS *objSOS = dynamic_cast(objects[iObj]); if (objSOS) continue; #ifdef MAKE_SOS_CLIQUES // skip cliques - CbcClique *objClique = dynamic_cast< CbcClique * >(objects[iObj]); + CbcClique *objClique = + dynamic_cast(objects[iObj]); if (objClique) continue; #endif @@ -6545,11 +6914,13 @@ int CbcMain1(int argc, const char *argv[], if (originalColumns) iColumn = originalColumns[iColumn]; if (branchDirection) { - CbcSimpleInteger *obj = dynamic_cast< CbcSimpleInteger * >(objects[iObj]); + CbcSimpleInteger *obj = + dynamic_cast(objects[iObj]); if (obj) { obj->setPreferredWay(branchDirection[iColumn]); } else { - CbcObject *obj = dynamic_cast< CbcObject * >(objects[iObj]); + CbcObject *obj = + dynamic_cast(objects[iObj]); assert(obj); obj->setPreferredWay(branchDirection[iColumn]); } @@ -6560,7 +6931,9 @@ int CbcMain1(int argc, const char *argv[], objects[iObj]->setPriority(iPriority); } if (pseudoUp && pseudoUp[iColumn]) { - CbcSimpleIntegerPseudoCost *obj1a = dynamic_cast< CbcSimpleIntegerPseudoCost * >(objects[iObj]); + CbcSimpleIntegerPseudoCost *obj1a = + dynamic_cast( + objects[iObj]); assert(obj1a); if (pseudoDown[iColumn] > 0.0) obj1a->setDownPseudoCost(pseudoDown[iColumn]); @@ -6578,7 +6951,7 @@ int CbcMain1(int argc, const char *argv[], If none then create */ if (!numberIntegers || !testOsiSolver->numberObjects()) { - //int type = (pseudoUp) ? 1 : 0; + // int type = (pseudoUp) ? 1 : 0; testOsiSolver->findIntegers(false); numberIntegers = testOsiSolver->getNumIntegers(); } @@ -6599,11 +6972,13 @@ int CbcMain1(int argc, const char *argv[], if (originalColumns) iColumn = originalColumns[iColumn]; if (branchDirection) { - OsiSimpleInteger *obj = dynamic_cast< OsiSimpleInteger * >(oldObjects[iObj]); + OsiSimpleInteger *obj = + dynamic_cast(oldObjects[iObj]); if (obj) { obj->setPreferredWay(branchDirection[iColumn]); } else { - OsiObject2 *obj = dynamic_cast< OsiObject2 * >(oldObjects[iObj]); + OsiObject2 *obj = + dynamic_cast(oldObjects[iObj]); if (obj) obj->setPreferredWay(branchDirection[iColumn]); } @@ -6620,8 +6995,9 @@ int CbcMain1(int argc, const char *argv[], for (iSOS = 0; iSOS < numberSOS; iSOS++) { int iStart = starts[iSOS]; int n = starts[iSOS + 1] - iStart; - objects[iSOS] = new OsiSOS(testOsiSolver, n, which + iStart, weight + iStart, - type[iSOS]); + objects[iSOS] = + new OsiSOS(testOsiSolver, n, which + iStart, + weight + iStart, type[iSOS]); // branch on long sets first objects[iSOS]->setPriority(numberColumns - n); } @@ -6629,7 +7005,8 @@ int CbcMain1(int argc, const char *argv[], for (iSOS = 0; iSOS < numberSOS; iSOS++) delete objects[iSOS]; delete[] objects; - } else if (priorities || branchDirection || pseudoDown || pseudoUp || numberSOS) { + } else if (priorities || branchDirection || pseudoDown || + pseudoUp || numberSOS) { if (numberSOS) { // Do sets and priorities OsiObject **objects = new OsiObject *[numberSOS]; @@ -6657,17 +7034,18 @@ int CbcMain1(int argc, const char *argv[], } delete[] back; if (nMissing) { - sprintf(generalPrint, "%d SOS variables vanished due to pre processing? - check validity?", nMissing); - generalMessageHandler->message(CLP_GENERAL, generalMessages) - << generalPrint - << CoinMessageEol; + buffer.str(""); + buffer << nMissing << " SOS variables vanished due to preprocessing?" + << " - check validity?"; + printGeneralMessage(model_, buffer.str()); } } for (iSOS = 0; iSOS < numberSOS; iSOS++) { int iStart = sosStart[iSOS]; int n = sosStart[iSOS + 1] - iStart; - objects[iSOS] = new OsiSOS(testOsiSolver, n, sosIndices + iStart, sosReference + iStart, - sosType[iSOS]); + objects[iSOS] = + new OsiSOS(testOsiSolver, n, sosIndices + iStart, + sosReference + iStart, sosType[iSOS]); if (sosPriority) objects[iSOS]->setPriority(sosPriority[iSOS]); else if (!prioritiesIn) @@ -6679,8 +7057,8 @@ int CbcMain1(int argc, const char *argv[], int nNew = 0; for (int i = 0; i < numberObjects; i++) { OsiObject *objThis = oldObjects[i]; - OsiSOS *obj1 = dynamic_cast< OsiSOS * >(objThis); - OsiSOS *obj2 = dynamic_cast< OsiSOS * >(objThis); + OsiSOS *obj1 = dynamic_cast(objThis); + OsiSOS *obj2 = dynamic_cast(objThis); if (!obj1 && !obj2) { oldObjects[nNew++] = objThis; } else { @@ -6696,13 +7074,14 @@ int CbcMain1(int argc, const char *argv[], } OsiObject **objects = testOsiSolver->objects(); int numberObjects = testOsiSolver->numberObjects(); - int logLevel = parameters_[log].intValue(); + int logLevel = parameters[CbcParam::LPLOGLEVEL]->intVal(); for (int iObj = 0; iObj < numberObjects; iObj++) { // skip sos - OsiSOS *objSOS = dynamic_cast< OsiSOS * >(objects[iObj]); + OsiSOS *objSOS = dynamic_cast(objects[iObj]); if (objSOS) { if (logLevel > 2) - printf("Set %d is SOS - priority %d\n", iObj, objSOS->priority()); + printf("Set %d is SOS - priority %d\n", iObj, + objSOS->priority()); continue; } int iColumn = objects[iObj]->columnNumber(); @@ -6710,11 +7089,13 @@ int CbcMain1(int argc, const char *argv[], if (originalColumns) iColumn = originalColumns[iColumn]; if (branchDirection) { - OsiSimpleInteger *obj = dynamic_cast< OsiSimpleInteger * >(objects[iObj]); + OsiSimpleInteger *obj = + dynamic_cast(objects[iObj]); if (obj) { obj->setPreferredWay(branchDirection[iColumn]); } else { - OsiObject2 *obj = dynamic_cast< OsiObject2 * >(objects[iObj]); + OsiObject2 *obj = + dynamic_cast(objects[iObj]); if (obj) obj->setPreferredWay(branchDirection[iColumn]); } @@ -6725,7 +7106,8 @@ int CbcMain1(int argc, const char *argv[], objects[iObj]->setPriority(iPriority); } if (logLevel > 2) - printf("Obj %d is int? - priority %d\n", iObj, objects[iObj]->priority()); + printf("Obj %d is int? - priority %d\n", iObj, + objects[iObj]->priority()); if (pseudoUp && pseudoUp[iColumn]) { abort(); } @@ -6770,7 +7152,7 @@ int CbcMain1(int argc, const char *argv[], OsiObject **objects = babModel_->objects(); int numberObjects = babModel_->numberObjects(); for (int iObj = 0; iObj < numberObjects; iObj++) { - CbcObject *obj = dynamic_cast< CbcObject * >(objects[iObj]); + CbcObject *obj = dynamic_cast(objects[iObj]); assert(obj); obj->setPreferredWay(way); } @@ -6782,7 +7164,8 @@ int CbcMain1(int argc, const char *argv[], compare.setWeight(-3.0); babModel_->setNodeComparison(compare); } else if (nodeStrategy == 0) { - // hybrid was default i.e. mixture of low depth and infeasibility + // hybrid was default i.e. mixture of low depth and + // infeasibility } else if (nodeStrategy == 1) { // real fewest CbcCompareDefault compare; @@ -6793,75 +7176,85 @@ int CbcMain1(int argc, const char *argv[], if (cppValue >= 0) { int prepro = useStrategy ? -1 : preProcess; // generate code - FILE *fp = fopen("user_driver.cpp", "w"); + fp = fopen("user_driver.cpp", "w"); if (fp) { // generate enough to do BAB babModel_->generateCpp(fp, 1); - OsiClpSolverInterface *osiclp = dynamic_cast< OsiClpSolverInterface * >(babModel_->solver()); + OsiClpSolverInterface *osiclp = + dynamic_cast( + babModel_->solver()); // Make general so do factorization - int factor = osiclp->getModelPtr()->factorizationFrequency(); + int factor = + osiclp->getModelPtr()->factorizationFrequency(); osiclp->getModelPtr()->setFactorizationFrequency(200); osiclp->generateCpp(fp); osiclp->getModelPtr()->setFactorizationFrequency(factor); - //solveOptions.generateCpp(fp); + // solveOptions.generateCpp(fp); fclose(fp); // now call generate code - generateCode(babModel_, "user_driver.cpp", cppValue, prepro); + generateCode(babModel_, "user_driver.cpp", cppValue, + prepro); } else { - std::cout << "Unable to open file user_driver.cpp" << std::endl; + std::cout << "Unable to open file user_driver.cpp" + << std::endl; } } - if (!babModel_->numberStrong() && babModel_->numberBeforeTrust() > 0) + if (!babModel_->numberStrong() && + babModel_->numberBeforeTrust() > 0) babModel_->setNumberBeforeTrust(0); if (useStrategy) { - CbcStrategyDefault strategy(1, babModel_->numberStrong(), babModel_->numberBeforeTrust()); + CbcStrategyDefault strategy(1, babModel_->numberStrong(), + babModel_->numberBeforeTrust()); strategy.setupPreProcessing(1); babModel_->setStrategy(strategy); } if (testOsiOptions >= 0) { - sprintf(generalPrint, "Testing OsiObject options %d", testOsiOptions); - generalMessageHandler->message(CLP_GENERAL, generalMessages) - << generalPrint - << CoinMessageEol; + buffer.str(""); + buffer << "Testing OsiObject options " << testOsiOptions; + printGeneralMessage(model_, buffer.str()); if (!numberSOS) { babModel_->solver()->findIntegersAndSOS(false); #ifdef COIN_HAS_LINK // If linked then pass in model - OsiSolverLink *solver3 = dynamic_cast< OsiSolverLink * >(babModel_->solver()); + OsiSolverLink *solver3 = + dynamic_cast(babModel_->solver()); if (solver3) { CbcHeuristicDynamic3 serendipity(*babModel_); serendipity.setHeuristicName("linked"); - int heuristicOption = parameters_[whichParam(CBC_PARAM_STR_HEURISTICSTRATEGY, parameters_)].currentOptionAsInteger(); + int heuristicOption = + parameters[CbcParam::HEURISTICSTRATEGY]->modeVal(); if (heuristicOption) babModel_->addHeuristic(&serendipity); - double dextra3 = parameters_[whichParam(CBC_PARAM_DBL_DEXTRA3, parameters_)].doubleValue(); + double dextra3 = parameters[CbcParam::DEXTRA3]->dblVal(); if (dextra3) solver3->setMeshSizes(dextra3); - int options = parameters_[whichParam(CBC_PARAM_INT_MIPOPTIONS, parameters_)].intValue() / 10000; + int options = parameters[CbcParam::MIPOPTIONS]->intVal() / 10000; CglStored stored; if (options) { printf("nlp options %d\n", options); /* - 1 - force mini branch and bound - 2 - set priorities high on continuous - 4 - try adding OA cuts - 8 - try doing quadratic linearization + 1 - force mini branch and + bound 2 - set priorities high on continuous 4 - try + adding OA cuts 8 - try doing quadratic linearization 16 - try expanding knapsacks - 32 - OA cuts strictly concave - 64 - no branching at all on bilinear x-x! + 32 - OA cuts + strictly concave 64 - no branching at all on bilinear + x-x! */ if ((options & 2)) { - solver3->setBiLinearPriorities(10, tightenFactor > 0.0 ? tightenFactor : 1.0); + solver3->setBiLinearPriorities( + 10, tightenFactor > 0.0 ? tightenFactor : 1.0); } else if (tightenFactor > 0.0) { // set grid size for all continuous bi-linear solver3->setMeshSizes(tightenFactor); } if ((options & 4)) { - solver3->setSpecialOptions2(solver3->specialOptions2() | (8 + 4)); + solver3->setSpecialOptions2( + solver3->specialOptions2() | (8 + 4)); // say convex solver3->sayConvex((options & 32) == 0); } - int extra1 = parameters_[whichParam(CBC_PARAM_INT_EXTRA1, parameters_)].intValue(); + int extra1 = parameters[CbcParam::EXTRA1]->intVal(); if ((options & 1) != 0 && extra1 > 0) solver3->setFixedPriority(extra1); double cutoff = COIN_DBL_MAX; @@ -6870,9 +7263,10 @@ int CbcMain1(int argc, const char *argv[], if (cutoff < babModel_->getCutoff()) { babModel_->setCutoff(cutoff); // and solution - //babModel_->setBestObjectiveValue(solver3->bestObjectiveValue()); - babModel_->setBestSolution(solver3->bestSolution(), solver3->getNumCols(), - solver3->bestObjectiveValue()); + // babModel_->setBestObjectiveValue(solver3->bestObjectiveValue()); + babModel_->setBestSolution( + solver3->bestSolution(), solver3->getNumCols(), + solver3->bestObjectiveValue()); } if ((options & 64)) solver3->setBranchingStrategyOnVariables(16, -1, 4); @@ -6882,24 +7276,29 @@ int CbcMain1(int argc, const char *argv[], babModel_->addCutGenerator(&stored, 1, "Stored"); CglTemporary temp; babModel_->addCutGenerator(&temp, 1, "OnceOnly"); - //choose.setNumberBeforeTrusted(2000); - //choose.setNumberStrong(20); + // choose.setNumberBeforeTrusted(2000); + // choose.setNumberStrong(20); } // For temporary testing of heuristics - //int testOsiOptions = parameters_[whichParam(CBC_PARAM_INT_TESTOSI,numberParameters_,parameters_)].intValue(); + // int testOsiOptions = + // parameters[CbcParam::TESTOSI,numberParameters_,parameters)]->intVal(); if (testOsiOptions >= 10) { if (testOsiOptions >= 20) testOsiOptions -= 10; - printf("*** Temp heuristic with mode %d\n", testOsiOptions - 10); - OsiSolverLink *solver3 = dynamic_cast< OsiSolverLink * >(babModel_->solver()); + printf("*** Temp heuristic with mode %d\n", + testOsiOptions - 10); + OsiSolverLink *solver3 = + dynamic_cast(babModel_->solver()); assert(solver3); - int extra1 = parameters_[whichParam(CBC_PARAM_INT_EXTRA1, parameters_)].intValue(); + int extra1 = parameters[CbcParam::EXTRA1]->intVal(); solver3->setBiLinearPriority(extra1); printf("bilinear priority now %d\n", extra1); - int extra2 = parameters_[whichParam(CBC_PARAM_INT_EXTRA2, parameters_)].intValue(); + int extra2 = parameters[CbcParam::EXTRA2]->intVal(); double saveDefault = solver3->defaultBound(); - solver3->setDefaultBound(static_cast< double >(extra2)); - double *solution = solver3->heuristicSolution(slpValue > 0 ? slpValue : 40, 1.0e-5, testOsiOptions - 10); + solver3->setDefaultBound(static_cast(extra2)); + double *solution = solver3->heuristicSolution( + slpValue > 0 ? slpValue : 40, 1.0e-5, + testOsiOptions - 10); solver3->setDefaultBound(saveDefault); if (!solution) printf("Heuristic failed\n"); @@ -6908,12 +7307,13 @@ int CbcMain1(int argc, const char *argv[], } else { // move across babModel_->deleteObjects(false); - //babModel_->addObjects(babModel_->solver()->numberObjects(),babModel_->solver()->objects()); + // babModel_->addObjects(babModel_->solver()->numberObjects(),babModel_->solver()->objects()); } CbcBranchDefaultDecision decision; if (babModel_->numberStrong()) { OsiChooseStrong choose(babModel_->solver()); - choose.setNumberBeforeTrusted(babModel_->numberBeforeTrust()); + choose.setNumberBeforeTrusted( + babModel_->numberBeforeTrust()); choose.setNumberStrong(babModel_->numberStrong()); choose.setShadowPriceMode(testOsiOptions); decision.setChooseMethod(choose); @@ -6935,7 +7335,8 @@ int CbcMain1(int argc, const char *argv[], const double *objective = babModel_->getObjCoefficients(); const double *lower = babModel_->getColLower(); const double *upper = babModel_->getColUpper(); - const CoinPackedMatrix *matrix = babModel_->solver()->getMatrixByCol(); + const CoinPackedMatrix *matrix = + babModel_->solver()->getMatrixByCol(); const int *columnLength = matrix->getVectorLengths(); int iColumn; for (iColumn = 0; iColumn < numberColumns; iColumn++) { @@ -6981,19 +7382,22 @@ int CbcMain1(int argc, const char *argv[], ClpSolve::SolveType method = ClpSolve::usePrimalorSprint; ClpSolve::PresolveType presolveType = ClpSolve::presolveOff; int numberPasses = 5; - int options[] = { 0, 3, 0, 0, 0, 0 }; - int extraInfo[] = { -1, 20, -1, -1, -1, -1 }; + int options[] = {0, 3, 0, 0, 0, 0}; + int extraInfo[] = {-1, 20, -1, -1, -1, -1}; extraInfo[1] = doSprint; - int independentOptions[] = { 0, 0, 3 }; - ClpSolve clpSolve(method, presolveType, numberPasses, - options, extraInfo, independentOptions); + int independentOptions[] = {0, 0, 3}; + ClpSolve clpSolve(method, presolveType, numberPasses, options, + extraInfo, independentOptions); // say use in OsiClp clpSolve.setSpecialOption(6, 1); - OsiClpSolverInterface *osiclp = dynamic_cast< OsiClpSolverInterface * >(babModel_->solver()); + OsiClpSolverInterface *osiclp = + dynamic_cast( + babModel_->solver()); osiclp->setSolveOptions(clpSolve); osiclp->setHintParam(OsiDoDualInResolve, false); // switch off row copy - osiclp->getModelPtr()->setSpecialOptions(osiclp->getModelPtr()->specialOptions() | 256); + osiclp->getModelPtr()->setSpecialOptions( + osiclp->getModelPtr()->specialOptions() | 256); osiclp->getModelPtr()->setInfeasibilityCost(1.0e11); } #ifdef COIN_HAS_LINK @@ -7052,13 +7456,14 @@ int CbcMain1(int argc, const char *argv[], #endif #ifndef CBC_OTHER_SOLVER if (outputFormat == 5) { - osiclp = dynamic_cast< OsiClpSolverInterface * >(babModel_->solver()); + osiclp = dynamic_cast( + babModel_->solver()); lpSolver = osiclp->getModelPtr(); lpSolver->setPersistenceFlag(1); } #endif // add in lotsizing - if (statusUserFunction_[0] && info.special) { + if (info && statusUserFunction_[0] && info->special) { int numberColumns = babModel_->getNumCols(); int i; int n = 0; @@ -7067,12 +7472,12 @@ int CbcMain1(int argc, const char *argv[], for (i = 0; i < numberColumns; i++) { int iColumn = originalColumns[i]; assert(iColumn >= i); - int iType = info.special[iColumn]; + int iType = info->special[iColumn]; if (iType) { assert(iType == 1); n++; } - info.special[i] = iType; + info->special[i] = iType; } } if (n) { @@ -7110,18 +7515,20 @@ int CbcMain1(int argc, const char *argv[], OsiObject **objects = new OsiObject *[n]; n = 0; // set new objects to have one lower priority - double ranges[] = { -COIN_DBL_MAX, -1.0, 1.0, COIN_DBL_MAX }; + double ranges[] = {-COIN_DBL_MAX, -1.0, 1.0, COIN_DBL_MAX}; for (int iObj = 0; iObj < numberOldObjects; iObj++) { int iColumn = oldObjects[iObj]->columnNumber(); - if (iColumn >= 0 && info.special[iColumn]) { + if (iColumn >= 0 && info && info->special[iColumn]) { if (lower[iColumn] <= -1.0 && upper[iColumn] >= 0.0) { ranges[0] = lower[iColumn]; ranges[3] = upper[iColumn]; int priority = oldObjects[iObj]->priority(); if (testOsiOptions < 0) { - objects[n] = new CbcLotsize(babModel_, iColumn, 2, ranges, true); + objects[n] = new CbcLotsize(babModel_, iColumn, 2, + ranges, true); } else { - objects[n] = new OsiLotsize(testOsiSolver, iColumn, 2, ranges, true); + objects[n] = new OsiLotsize(testOsiSolver, iColumn, + 2, ranges, true); } objects[n++]->setPriority(priority - 1); } @@ -7138,15 +7545,16 @@ int CbcMain1(int argc, const char *argv[], } } if (storedAmpl.sizeRowCuts()) { - //babModel_->addCutGenerator(&storedAmpl,1,"AmplStored"); + // babModel_->addCutGenerator(&storedAmpl,1,"AmplStored"); int numberRowCuts = storedAmpl.sizeRowCuts(); for (int i = 0; i < numberRowCuts; i++) { - const OsiRowCut *rowCutPointer = storedAmpl.rowCutPointer(i); + const OsiRowCut *rowCutPointer = + storedAmpl.rowCutPointer(i); babModel_->makeGlobalCut(rowCutPointer); } } // If defaults then increase trust for small models - if (!strongChanged) { + if (!strongChanged && false) { // out for now int numberColumns = babModel_->getNumCols(); if (numberColumns <= 50) babModel_->setNumberBeforeTrust(1000); @@ -7156,7 +7564,7 @@ int CbcMain1(int argc, const char *argv[], babModel_->setNumberBeforeTrust(50); } #ifdef CBC_THREAD - int numberThreads = parameters_[whichParam(CBC_PARAM_INT_THREADS, parameters_)].intValue(); + int numberThreads = parameters[CbcParam::THREADS]->intVal(); babModel_->setNumberThreads(numberThreads % 100); babModel_->setThreadMode(numberThreads / 100); #endif @@ -7170,9 +7578,10 @@ int CbcMain1(int argc, const char *argv[], return returnCode; } #ifndef CBC_OTHER_SOLVER - osiclp = dynamic_cast< OsiClpSolverInterface * >(babModel_->solver()); + osiclp = + dynamic_cast(babModel_->solver()); lpSolver = osiclp->getModelPtr(); - int hotits = parameters_[whichParam(CBC_PARAM_INT_MAXHOTITS, parameters_)].intValue(); + int hotits = parameters[CbcParam::MAXHOTITS]->intVal(); if (hotits > 100) { osiclp->setSpecialOptions(osiclp->specialOptions() & ~32); osiclp->setIntParam(OsiMaxNumIterationHotStart, hotits); @@ -7181,24 +7590,34 @@ int CbcMain1(int argc, const char *argv[], } #elif CBC_OTHER_SOLVER == 1 #endif - if ((experimentFlag >= 1 || strategyFlag >= 1) && babModel_->fastNodeDepth() == -1) { - if (babModel_->solver()->getNumCols() + babModel_->solver()->getNumRows() < 500) - babModel_->setFastNodeDepth(-12); + if ((experimentFlag >= 1 || strategyFlag >= 1) && + abs(babModel_->fastNodeDepth()) == 1) { + int iType = babModel_->fastNodeDepth(); + int iDepth = iType <0 ? -12 : 8; + int iSize = iType <0 ? 10000 : 500; + if (babModel_->solver()->getNumCols() + + babModel_->solver()->getNumRows() < iSize) { + babModel_->setFastNodeDepth(iDepth); + } else { + babModel_->setFastNodeDepth(-1); // not sure about when +1 + } } else if (babModel_->fastNodeDepth() == -999) { babModel_->setFastNodeDepth(-1); } - int heurOptions = parameters_[whichParam(CBC_PARAM_INT_HOPTIONS, parameters_)].intValue(); + int heurOptions = parameters[CbcParam::HEUROPTIONS]->intVal(); if (heurOptions > 100) - babModel_->setSpecialOptions(babModel_->specialOptions() | 8192); + babModel_->setSpecialOptions(babModel_->specialOptions() | + 8192); #ifndef CBC_OTHER_SOLVER #ifdef CLP_MULTIPLE_FACTORIZATIONS - int denseCode = parameters_[whichParam(CBC_PARAM_INT_DENSE, parameters_)].intValue(); - int smallCode = parameters_[whichParam(CBC_PARAM_INT_SMALLFACT, parameters_)].intValue(); + int denseCode = clpParameters[ClpParam::DENSE]->intVal(); + int smallCode = clpParameters[ClpParam::SMALLFACT]->intVal(); if (bothFlags >= 1) { if (denseCode < 0) denseCode = 40; - if (smallCode < 0 && !lpSolver->factorization()->isDenseOrSmall()) + if (smallCode < 0 && + !lpSolver->factorization()->isDenseOrSmall()) smallCode = 40; } if (denseCode > 0) { @@ -7208,8 +7627,8 @@ int CbcMain1(int argc, const char *argv[], } if (smallCode > 0 && smallCode > denseCode) lpSolver->factorization()->setGoSmallThreshold(smallCode); - //if (denseCode>=lpSolver->numberRows()) { - //lpSolver->factorization()->goDense(); + // if (denseCode>=lpSolver->numberRows()) { + // lpSolver->factorization()->goDense(); //} if (lpSolver->factorization()->goOslThreshold() > 1000) { // use osl in gomory (may not if CglGomory decides not to) @@ -7217,13 +7636,17 @@ int CbcMain1(int argc, const char *argv[], int nGomory = 0; for (int iGenerator = 0; iGenerator < numberGenerators; iGenerator++) { - CbcCutGenerator *generator = babModel_->cutGenerator(iGenerator); - CglGomory *gomory = dynamic_cast< CglGomory * >(generator->generator()); + CbcCutGenerator *generator = + babModel_->cutGenerator(iGenerator); + CglGomory *gomory = + dynamic_cast(generator->generator()); if (gomory) { if (nGomory < 2) { gomory->useAlternativeFactorization(); } else if (gomory->originalSolver()) { - OsiClpSolverInterface *clpSolver = dynamic_cast< OsiClpSolverInterface * >(gomory->originalSolver()); + OsiClpSolverInterface *clpSolver = + dynamic_cast( + gomory->originalSolver()); if (clpSolver) { ClpSimplex *simplex = clpSolver->getModelPtr(); simplex->factorization()->setGoOslThreshold(0); @@ -7244,11 +7667,13 @@ int CbcMain1(int argc, const char *argv[], #ifdef SOS_AS_CUTS #ifdef CBC_HAS_CLP /* SOS as cuts - Could be a bit more sophisticated e.g. only non duplicates - Could do something for SOS 2? - */ + Could be a bit more sophisticated e.g. only + non duplicates Could do something for SOS 2? + */ { - OsiClpSolverInterface *clpSolver = dynamic_cast< OsiClpSolverInterface * >(babModel_->solver()); + OsiClpSolverInterface *clpSolver = + dynamic_cast( + babModel_->solver()); if (clpSolver && clpSolver->numberSOS()) { // SOS int numberSOS = clpSolver->numberSOS(); @@ -7267,7 +7692,8 @@ int CbcMain1(int argc, const char *argv[], double *lo = els + nEls; double *up = lo + numberSOS; // need to get rid of sos - ClpSimplex *fakeSimplex = new ClpSimplex(*clpSolver->getModelPtr()); + ClpSimplex *fakeSimplex = + new ClpSimplex(*clpSolver->getModelPtr()); #if 0 int numberRows=fakeSimplex->numberRows(); int * starts = @@ -7308,9 +7734,8 @@ int CbcMain1(int argc, const char *argv[], } } if (nAdded) - fakeSimplex->addRows(nAdded, - lo, up, - starts, columns, els); + fakeSimplex->addRows(nAdded, lo, up, starts, columns, + els); if (nAdded) { OsiClpSolverInterface fakeSolver(fakeSimplex); CglFakeClique fakeGen(&fakeSolver, false); @@ -7318,8 +7743,9 @@ int CbcMain1(int argc, const char *argv[], fakeGen.setRowCliqueReport(false); fakeGen.setMinViolation(0.05); babModel_->addCutGenerator(&fakeGen, 1, "SosCuts"); - //fakeSimplex->writeMps("bad.mps",0,1); - sosCuts.setProbingInfo(new CglTreeProbingInfo(&fakeSolver)); + // fakeSimplex->writeMps("bad.mps",0,1); + sosCuts.setProbingInfo( + new CglTreeProbingInfo(&fakeSolver)); } delete fakeSimplex; // End Cliques @@ -7342,8 +7768,7 @@ int CbcMain1(int argc, const char *argv[], previous = upper[iColumn]; } if (n > 0) { - sosCuts.addCut(0.0, rhs, - n, which, els); + sosCuts.addCut(0.0, rhs, n, which, els); nAdded++; } } @@ -7357,14 +7782,16 @@ int CbcMain1(int argc, const char *argv[], } #endif #endif - if (useSolution > 1) { + if (useSolution > 1) { // use hotstart to try and find solution CbcHeuristicPartial partial(*babModel_, 10000, useSolution); partial.setHeuristicName("Partial solution given"); babModel_->addHeuristic(&partial); } - if (logLevel <= 1 && babModel_->solver()->messageHandler() != babModel_->messageHandler()) - babModel_->solver()->setHintParam(OsiDoReducePrint, true, OsiHintTry); + if (logLevel <= 1 && babModel_->solver()->messageHandler() != + babModel_->messageHandler()) + babModel_->solver()->setHintParam(OsiDoReducePrint, true, + OsiHintTry); #ifdef CBC_TEMP1 if (osiclp->getModelPtr()->perturbation() == 50) osiclp->getModelPtr()->setPerturbation(52); // try less @@ -7372,7 +7799,7 @@ int CbcMain1(int argc, const char *argv[], #ifdef JJF_ZERO if (osiclp->getNumCols() == 29404) { void restoreSolution(ClpSimplex * lpSolver, - std::string fileName, int mode); + std::string fileName, int mode); restoreSolution(osiclp->getModelPtr(), "debug.file", 0); int numberColumns = osiclp->getNumCols(); const double *solution = osiclp->getColSolution(); @@ -7389,8 +7816,7 @@ int CbcMain1(int argc, const char *argv[], } saveSolver->writeMps("fixed"); babModel_->setBestSolution(osiclp->getColSolution(), - osiclp->getNumCols(), - 1.5325e10); + osiclp->getNumCols(), 1.5325e10); } else { babModel_->branchAndBound(statistics); } @@ -7400,7 +7826,7 @@ int CbcMain1(int argc, const char *argv[], orbit.morph(); exit(1); #endif - int hOp1 = parameters_[whichParam(CBC_PARAM_INT_HOPTIONS, parameters_)].intValue() / 100000; + int hOp1 = parameters[CbcParam::HEUROPTIONS]->intVal() / 100000; if (hOp1 % 10) { CbcCompareDefault compare; compare.setBreadthDepth(hOp1 % 10); @@ -7410,17 +7836,19 @@ int CbcMain1(int argc, const char *argv[], babModel_->setNodeComparison(compare); } #if CBC_OTHER_SOLVER == 1 - if (dynamic_cast< OsiCpxSolverInterface * >(babModel_->solver())) + if (dynamic_cast(babModel_->solver())) babModel_->solver()->messageHandler()->setLogLevel(0); #endif - if (parameters_[whichParam(CBC_PARAM_STR_CPX, parameters_)].currentOptionAsInteger()) { - babModel_->setSpecialOptions(babModel_->specialOptions() | 16384); - //if (babModel_->fastNodeDepth()==-1) + if (parameters[CbcParam::CPX]->modeVal()) { + babModel_->setSpecialOptions(babModel_->specialOptions() | + 16384); + // if (babModel_->fastNodeDepth()==-1) babModel_->setFastNodeDepth(-2); // Use Cplex at root } - int hOp2 = parameters_[whichParam(CBC_PARAM_INT_HOPTIONS, parameters_)].intValue() / 10000; + int hOp2 = parameters[CbcParam::HEUROPTIONS]->intVal() / 10000; if (hOp2 % 10) { - babModel_->setSpecialOptions(babModel_->specialOptions() | 16384); + babModel_->setSpecialOptions(babModel_->specialOptions() | + 16384); if (babModel_->fastNodeDepth() == -1) babModel_->setFastNodeDepth(-2); // Use Cplex at root } @@ -7430,7 +7858,8 @@ int CbcMain1(int argc, const char *argv[], donor.setSpecialOptions(options | 262144); ClpSimplex *lpSolver2; OsiClpSolverInterface *clpSolver2; - clpSolver2 = dynamic_cast< OsiClpSolverInterface * >(donor.solver()); + clpSolver2 = + dynamic_cast(donor.solver()); assert(clpSolver2); lpSolver2 = clpSolver2->getModelPtr(); assert(lpSolver2); @@ -7444,8 +7873,10 @@ int CbcMain1(int argc, const char *argv[], int numberGenerators = donor.numberCutGenerators(); for (int iGenerator = 0; iGenerator < numberGenerators; iGenerator++) { - CbcCutGenerator *generator = donor.cutGenerator(iGenerator); - CglGomory *gomory = dynamic_cast< CglGomory * >(generator->generator()); + CbcCutGenerator *generator = + donor.cutGenerator(iGenerator); + CglGomory *gomory = + dynamic_cast(generator->generator()); if (gomory) gomory->useAlternativeFactorization(false); } @@ -7461,7 +7892,7 @@ int CbcMain1(int argc, const char *argv[], donor.setStoredRowCuts(NULL); } // We may have priorities from extra variables - int more2 = parameters_[whichParam(CBC_PARAM_INT_MOREMOREMIPOPTIONS, parameters_)].intValue(); + int more2 = parameters[CbcParam::MOREMOREMIPOPTIONS]->intVal(); if (newPriorities) { if (truncateColumns < babModel_->getNumCols()) { // set new ones as high prority @@ -7472,11 +7903,12 @@ int CbcMain1(int argc, const char *argv[], babModel_->findIntegers(true); int numberIntegers = babModel_->numberIntegers(); int *newPriorities = new int[numberIntegers]; - int n = numberIntegers - (babModel_->getNumCols() - truncateColumns); + int n = numberIntegers - + (babModel_->getNumCols() - truncateColumns); for (int i = 0; i < n; i++) newPriorities[i] = babModel_->priority(i); #if 1 - int ixxxxxx = parameters_[whichParam(CBC_PARAM_INT_MAXNODES, parameters_)].intValue(); + int ixxxxxx = parameters[CbcParam::MAXNODES]->intVal(); int obj_priority = 1000; int slack_priority = 1000; if (ixxxxxx >= 1000000 && ixxxxxx < 1010000) { @@ -7549,33 +7981,35 @@ int CbcMain1(int argc, const char *argv[], delete[] newPriorities; } #ifdef JJF_ZERO - int extra5 = parameters_[whichParam(EXTRA5, parameters_)].intValue(); + //TODO this doesn't look like it will build at the moment + int extra5 = parameters[CbcParam::EXTRA5]->intVal(); if (extra5 > 0) { int numberGenerators = babModel_->numberCutGenerators(); for (int iGenerator = 0; iGenerator < numberGenerators; iGenerator++) { - CbcCutGenerator *generator = babModel_->cutGenerator(iGenerator); - CglGomory *gomory = dynamic_cast< CglGomory * >(generator->generator()); + CbcCutGenerator *generator = + babModel_->cutGenerator(iGenerator); + CglGomory *gomory = + dynamic_cast(generator->generator()); if (gomory) { CglGomory gomory2(*gomory); - gomory2.useAlternativeFactorization(!gomory->alternativeFactorization()); + gomory2.useAlternativeFactorization( + !gomory->alternativeFactorization()); babModel_->addCutGenerator(&gomory2, -99, "Gomory2"); } } } #endif - int specialOptions = parameters_[whichParam(CBC_PARAM_INT_STRONG_STRATEGY, parameters_)].intValue(); + int specialOptions = parameters[CbcParam::STRONGSTRATEGY]->intVal(); if (specialOptions >= 0) babModel_->setStrongStrategy(specialOptions); - int jParam = whichParam(CBC_PARAM_STR_CUTOFF_CONSTRAINT, - parameters_); - if (parameters_[jParam].currentOptionAsInteger()) { + if (parameters[CbcParam::CUTOFFCONSTRAINT]->modeVal()) { babModel_->setCutoffAsConstraint(true); int moreOptions = babModel_->moreSpecialOptions(); - if (parameters_[jParam].currentOptionAsInteger() == 4) + if (parameters[CbcParam::CUTOFFCONSTRAINT]->modeVal() == 4) babModel_->setMoreSpecialOptions(moreOptions | 4194304); } - int multipleRoot = parameters_[whichParam(CBC_PARAM_INT_MULTIPLEROOTS, parameters_)].intValue(); + int multipleRoot = parameters[CbcParam::MULTIPLEROOTS]->intVal(); if (multipleRoot < 10000) { babModel_->setMultipleRootTries(multipleRoot); } else { @@ -7598,39 +8032,46 @@ int CbcMain1(int argc, const char *argv[], double **bestSolutions = new double *[numberGoes]; int *which = new int[numberGoes]; int numberSolutions = 0; - sprintf(generalPrint, "Starting %d passes each with %d solvers", - numberGoes, multipleRoot % 10); - generalMessageHandler->message(CLP_GENERAL, generalMessages) - << generalPrint - << CoinMessageEol; + buffer.str(""); + buffer << "Starting " << numberGoes << " passes each with " + << multipleRoot % 10 << " solvers"; + printGeneralMessage(model_, buffer.str()); for (int iGo = 0; iGo < numberGoes; iGo++) { - sprintf(generalPrint, "Starting pass %d", iGo + 1); - generalMessageHandler->message(CLP_GENERAL, generalMessages) - << generalPrint - << CoinMessageEol; + buffer.str(""); + buffer << "Starting pass " << iGo + 1; + printGeneralMessage(model_, buffer.str()); CbcModel tempModel = *babModel_; tempModel.setMaximumNodes(0); // switch off cuts if none generated int numberGenerators = tempModel.numberCutGenerators(); - for (int iGenerator = 0; iGenerator < numberGenerators; iGenerator++) { - CbcCutGenerator *generator = tempModel.cutGenerator(iGenerator); + for (int iGenerator = 0; iGenerator < numberGenerators; + iGenerator++) { + CbcCutGenerator *generator = + tempModel.cutGenerator(iGenerator); generator->setSwitchOffIfLessThan(1); } // random - tempModel.setRandomSeed(tempModel.getRandomSeed() + 100000000 * (iGo + 1 + 5 * numberGoes)); + tempModel.setRandomSeed(tempModel.getRandomSeed() + + 100000000 * + (iGo + 1 + 5 * numberGoes)); for (int i = 0; i < tempModel.numberHeuristics(); i++) - tempModel.heuristic(i)->setSeed(tempModel.heuristic(i)->getSeed() + 100000000 * iGo); + tempModel.heuristic(i)->setSeed( + tempModel.heuristic(i)->getSeed() + 100000000 * iGo); #ifndef CBC_OTHER_SOLVER - OsiClpSolverInterface *solver = dynamic_cast< OsiClpSolverInterface * >(tempModel.solver()); + OsiClpSolverInterface *solver = + dynamic_cast( + tempModel.solver()); ClpSimplex *simplex = solver->getModelPtr(); - int solverSeed = simplex->randomNumberGenerator()->getSeed(); + int solverSeed = + simplex->randomNumberGenerator()->getSeed(); simplex->setRandomSeed(solverSeed + 100000000 * (iGo + 1)); #endif tempModel.branchAndBound(); if (tempModel.bestSolution()) { - bestSolutions[numberSolutions] = CoinCopyOfArray(tempModel.bestSolution(), - numberColumns); - bestValues[numberSolutions] = -tempModel.getMinimizationObjValue(); + bestSolutions[numberSolutions] = CoinCopyOfArray( + tempModel.bestSolution(), numberColumns); + bestValues[numberSolutions] = + -tempModel.getMinimizationObjValue(); which[numberSolutions] = numberSolutions; numberSolutions++; } @@ -7643,46 +8084,54 @@ int CbcMain1(int argc, const char *argv[], for (int i = 0; i < numberSolutions; i++) { int k = which[i]; if (bestValues[i] < babModel_->getCutoff()) { - babModel_->setBestSolution(bestSolutions[k], numberColumns, - -bestValues[i] * sense, true); + babModel_->setBestSolution(bestSolutions[k], + numberColumns, + -bestValues[i] * sense, true); babModel_->incrementUsed(bestSolutions[k]); } delete[] bestSolutions[k]; } babModel_->setMoreSpecialOptions(moreOptions); - if (numberSolutions) - sprintf(generalPrint, "Ending major passes - best solution %g", -bestValues[numberSolutions - 1]); - else - sprintf(generalPrint, "Ending major passes - no solution found"); - generalMessageHandler->message(CLP_GENERAL, generalMessages) - << generalPrint - << CoinMessageEol; + if (numberSolutions){ + buffer.str(""); + buffer << "Ending major passes - best solution " + << -bestValues[numberSolutions - 1]; + } else { + buffer.str(""); + buffer << "Ending major passes - no solution found"; + } + printGeneralMessage(model_, buffer.str()); delete[] which; delete[] bestValues; delete[] bestSolutions; } if (biLinearProblem) - babModel_->setSpecialOptions(babModel_->specialOptions() & (~(512 | 32768))); - babModel_->setMoreSpecialOptions2(parameters_[whichParam(CBC_PARAM_INT_MOREMOREMIPOPTIONS, parameters_)].intValue()); + babModel_->setSpecialOptions(babModel_->specialOptions() & + (~(512 | 32768))); + babModel_->setMoreSpecialOptions2( + parameters[CbcParam::MOREMOREMIPOPTIONS]->intVal()); #ifdef CBC_HAS_NAUTY int nautyAdded = 0; { - int jParam = whichParam(CBC_PARAM_STR_ORBITAL, - parameters_); - if (parameters_[jParam].currentOptionAsInteger()) { - int k = parameters_[jParam].currentOptionAsInteger(); + if (parameters[CbcParam::ORBITAL]->modeVal()) { + int k = parameters[CbcParam::ORBITAL]->modeVal(); if (k < 4) { - babModel_->setMoreSpecialOptions2(babModel_->moreSpecialOptions2() | (k * 128)); + babModel_->setMoreSpecialOptions2( + babModel_->moreSpecialOptions2() | (k * 128)); } else if (k == 4) { #define MAX_NAUTY_PASS 2000 - nautyAdded = nautiedConstraints(*babModel_, - MAX_NAUTY_PASS); - } else { - assert (k==5 || k ==6); - if (k ==5) - babModel_->setMoreSpecialOptions2(babModel_->moreSpecialOptions2() | 128 | 256 | 131072); - else - babModel_->setMoreSpecialOptions2(babModel_->moreSpecialOptions2() | 128 | 256 | 131072 | 262144); + nautyAdded = + nautiedConstraints(*babModel_, MAX_NAUTY_PASS); + } else { + assert(k == 5 || k == 6); + if (k == 5) + babModel_->setMoreSpecialOptions2( + babModel_->moreSpecialOptions2() | 128 | 256 | + 131072); + else + babModel_->setMoreSpecialOptions2( + babModel_->moreSpecialOptions2() | 128 | 256 | + 131072 | 262144); } } } @@ -7710,13 +8159,23 @@ int CbcMain1(int argc, const char *argv[], } else { babModel_->setSecsPrintFrequency(value); } - } +#ifdef CBC_EXPERIMENT_JJF + // deal with experiment + if (experimentValue > 0 && experimentValue < 5) { + if (experimentValue > 1) { + // go to end in strong branching + solver->setSpecialOptions(solver->specialOptions() & ~32); + } + } +#endif + } #endif babModel_->branchAndBound(statistics); #ifdef CBC_HAS_NAUTY if (nautyAdded) { int *which = new int[nautyAdded]; - int numberOldRows = babModel_->solver()->getNumRows() - nautyAdded; + int numberOldRows = + babModel_->solver()->getNumRows() - nautyAdded; for (int i = 0; i < nautyAdded; i++) which[i] = i + numberOldRows; babModel_->solver()->deleteRows(nautyAdded, which); @@ -7752,8 +8211,7 @@ int CbcMain1(int argc, const char *argv[], #ifdef CLP_FACTORIZATION_INSTRUMENT extern double factorization_instrument(int type); double facTime = factorization_instrument(0); - printf("Factorization %g seconds\n", - facTime); + printf("Factorization %g seconds\n", facTime); #endif #endif #ifdef COIN_DEVELOP @@ -7787,24 +8245,25 @@ int CbcMain1(int argc, const char *argv[], malloc_stats2(); #endif checkSOS(babModel_, babModel_->solver()); - } else if (type == CBC_PARAM_ACTION_MIPLIB) { + } else if (cbcParamCode == CbcParam::MIPLIB) { int typeOfCuts = babModel_->numberCutGenerators() ? 1 : -1; CbcStrategyDefault strategy(typeOfCuts, - babModel_->numberStrong(), - babModel_->numberBeforeTrust()); + babModel_->numberStrong(), + babModel_->numberBeforeTrust()); // Set up pre-processing - int translate2[] = { 9999, 1, 1, 3, 2, 4, 5, 6, 6 }; + int translate2[] = {9999, 1, 1, 3, 2, 4, 5, 6, 6}; if (preProcess) strategy.setupPreProcessing(translate2[preProcess]); babModel_->setStrategy(strategy); #ifdef CBC_THREAD - int numberThreads = parameters_[whichParam(CBC_PARAM_INT_THREADS, parameters_)].intValue(); + int numberThreads = parameters[CbcParam::THREADS]->intVal(); babModel_->setNumberThreads(numberThreads % 100); babModel_->setThreadMode(numberThreads / 100); #endif #ifndef CBC_OTHER_SOLVER if (outputFormat == 5) { - osiclp = dynamic_cast< OsiClpSolverInterface * >(babModel_->solver()); + osiclp = dynamic_cast( + babModel_->solver()); lpSolver = osiclp->getModelPtr(); lpSolver->setPersistenceFlag(1); } @@ -7816,23 +8275,29 @@ int CbcMain1(int argc, const char *argv[], choose.setNumberBeforeTrusted(babModel_->numberBeforeTrust()); choose.setNumberStrong(babModel_->numberStrong()); choose.setShadowPriceMode(testOsiOptions); - //babModel_->deleteObjects(false); + // babModel_->deleteObjects(false); decision.setChooseMethod(choose); babModel_->setBranchingMethod(decision); } model_ = *babModel_; #ifndef CBC_OTHER_SOLVER { - osiclp = dynamic_cast< OsiClpSolverInterface * >(model_.solver()); + osiclp = + dynamic_cast(model_.solver()); lpSolver = osiclp->getModelPtr(); - lpSolver->setSpecialOptions(lpSolver->specialOptions() | IN_BRANCH_AND_BOUND); // say is Cbc (and in branch and bound) + lpSolver->setSpecialOptions( + lpSolver->specialOptions() | + IN_BRANCH_AND_BOUND); // say is Cbc (and in branch and + // bound) if (lpSolver->factorization()->goOslThreshold() > 1000) { // use osl in gomory (may not if CglGomory decides not to) int numberGenerators = model_.numberCutGenerators(); for (int iGenerator = 0; iGenerator < numberGenerators; iGenerator++) { - CbcCutGenerator *generator = model_.cutGenerator(iGenerator); - CglGomory *gomory = dynamic_cast< CglGomory * >(generator->generator()); + CbcCutGenerator *generator = + model_.cutGenerator(iGenerator); + CglGomory *gomory = + dynamic_cast(generator->generator()); if (gomory) gomory->useAlternativeFactorization(); } @@ -7840,47 +8305,51 @@ int CbcMain1(int argc, const char *argv[], } #endif /* LL: this was done in CoinSolve.cpp: main(argc, argv). - I have moved it here so that the miplib directory location - could be passed to CbcClpUnitTest. */ + I have moved it here so that the miplib + directory location could be passed to CbcClpUnitTest. */ /* JJF: No need to have 777 flag at all - user says -miplib */ - int extra2 = parameters_[whichParam(CBC_PARAM_INT_EXTRA2, parameters_)].intValue(); + int extra2 = parameters[CbcParam::EXTRA2]->intVal(); double stuff[11]; - stuff[0] = parameters_[whichParam(CBC_PARAM_DBL_FAKEINCREMENT, parameters_)].doubleValue(); - stuff[1] = parameters_[whichParam(CBC_PARAM_DBL_FAKECUTOFF, parameters_)].doubleValue(); - stuff[2] = parameters_[whichParam(CBC_PARAM_DBL_DEXTRA3, parameters_)].doubleValue(); - stuff[3] = parameters_[whichParam(CBC_PARAM_DBL_DEXTRA4, parameters_)].doubleValue(); - stuff[4] = parameters_[whichParam(CBC_PARAM_INT_DENSE, parameters_)].intValue(); - stuff[5] = parameters_[whichParam(CBC_PARAM_INT_EXTRA1, parameters_)].intValue(); - stuff[6] = parameters_[whichParam(CBC_PARAM_INT_EXTRA3, parameters_)].intValue(); - stuff[7] = parameters_[whichParam(CBC_PARAM_INT_DEPTHMINIBAB, parameters_)].intValue(); + stuff[0] = parameters[CbcParam::FAKEINCREMENT]->dblVal(); + stuff[1] = parameters[CbcParam::FAKECUTOFF]->dblVal(); + stuff[2] = parameters[CbcParam::DEXTRA3]->dblVal(); + stuff[3] = parameters[CbcParam::DEXTRA4]->dblVal(); + stuff[4] = clpParameters[ClpParam::DENSE]->intVal(); + stuff[5] = parameters[CbcParam::EXTRA1]->intVal(); + stuff[6] = parameters[CbcParam::EXTRA3]->intVal(); + stuff[7] = parameters[CbcParam::DEPTHMINIBAB]->intVal(); stuff[8] = bothFlags; stuff[9] = doVector; - stuff[10] = parameters_[whichParam(CBC_PARAM_INT_SMALLFACT, parameters_)].intValue(); - if (dominatedCuts) + stuff[10] = clpParameters[ClpParam::SMALLFACT]->intVal(); + if (dominatedCuts){ model_.setSpecialOptions(model_.specialOptions() | 64); - if (parameters_[whichParam(CBC_PARAM_STR_CPX, parameters_)].currentOptionAsInteger()) { + } + if (parameters[CbcParam::CPX]->modeVal()) { model_.setSpecialOptions(model_.specialOptions() | 16384); - //if (model_.fastNodeDepth()==-1) + // if (model_.fastNodeDepth()==-1) model_.setFastNodeDepth(-2); // Use Cplex at root } - int hOp2 = parameters_[whichParam(CBC_PARAM_INT_HOPTIONS, parameters_)].intValue() / 10000; + int hOp2 = + parameters[CbcParam::HEUROPTIONS]->intVal() / 10000; if (hOp2 % 10) { model_.setSpecialOptions(model_.specialOptions() | 16384); if (model_.fastNodeDepth() == -1) model_.setFastNodeDepth(-2); // Use Cplex at root } - int multipleRoot = parameters_[whichParam(CBC_PARAM_INT_MULTIPLEROOTS, parameters_)].intValue(); + int multipleRoot = parameters[CbcParam::MULTIPLEROOTS]->intVal(); model_.setMultipleRootTries(multipleRoot); - int specialOptions = parameters_[whichParam(CBC_PARAM_INT_STRONG_STRATEGY, parameters_)].intValue(); + int specialOptions = parameters[CbcParam::STRONGSTRATEGY]->intVal(); if (specialOptions >= 0) model_.setStrongStrategy(specialOptions); if (!pumpChanged) { // Make more lightweight - for (int iHeur = 0; iHeur < model_.numberHeuristics(); iHeur++) { + for (int iHeur = 0; iHeur < model_.numberHeuristics(); + iHeur++) { CbcHeuristic *heuristic = model_.heuristic(iHeur); - CbcHeuristicFPump *pump = dynamic_cast< CbcHeuristicFPump * >(heuristic); + CbcHeuristicFPump *pump = + dynamic_cast(heuristic); if (pump) { CbcHeuristicFPump heuristic4(model_); heuristic4.setFractionSmall(0.5); @@ -7888,54 +8357,62 @@ int CbcMain1(int argc, const char *argv[], heuristic4.setFeasibilityPumpOptions(30); heuristic4.setWhen(13); heuristic4.setHeuristicName("feasibility pump"); - //CbcHeuristicFPump & pump2 = pump; + // CbcHeuristicFPump & pump2 = pump; *pump = heuristic4; } } } #ifndef CBC_OTHER_SOLVER - { - OsiClpSolverInterface *solver = dynamic_cast< OsiClpSolverInterface * >(model_.solver()); - ClpSimplex *simplex = solver->getModelPtr(); - // if wanted go back to old printing method - double value = simplex->getMinIntervalProgressUpdate(); - if (value<=0.0) { - model_.setSecsPrintFrequency(-1.0); - if (value<0.0) { - model_.setPrintFrequency(static_cast(-value)); - } - } else { - model_.setSecsPrintFrequency(value); - } - } + { + OsiClpSolverInterface *solver = + dynamic_cast(model_.solver()); + ClpSimplex *simplex = solver->getModelPtr(); + // if wanted go back to old printing method + double value = simplex->getMinIntervalProgressUpdate(); + if (value <= 0.0) { + model_.setSecsPrintFrequency(-1.0); + if (value < 0.0) { + model_.setPrintFrequency(static_cast(-value)); + } + } else { + model_.setSecsPrintFrequency(value); + } + } #endif - int returnCode = CbcClpUnitTest(model_, dirMiplib, extra2, stuff,argc,argv,callBack,parameterData); - babModel_ = NULL; - return returnCode; + std::string dirMiplib = + parameters[CbcParam::DIRMIPLIB]->dirName(); + if (dirMiplib != ""){ + int returnCode = + CbcClpUnitTest(model_, dirMiplib, extra2, stuff, + saveInputQueue, callBack, parameters); + babModel_ = NULL; + return returnCode; + } } else { abort(); // can't get here - //strengthenedModel = babModel_->strengthenedModel(); + // strengthenedModel = babModel_->strengthenedModel(); } currentBranchModel = NULL; #ifndef CBC_OTHER_SOLVER - osiclp = dynamic_cast< OsiClpSolverInterface * >(babModel_->solver()); - if (debugFile == "createAfterPre" && babModel_->bestSolution()) { + osiclp = + dynamic_cast(babModel_->solver()); + if (parameters[CbcParam::DEBUGFILE]->fileName() == + "createAfterPre" && babModel_->bestSolution()) { lpSolver = osiclp->getModelPtr(); - //move best solution (should be there -- but ..) + // move best solution (should be there -- but ..) int n = lpSolver->getNumCols(); - memcpy(lpSolver->primalColumnSolution(), babModel_->bestSolution(), n * sizeof(double)); - saveSolution(osiclp->getModelPtr(), "debug.file"); + memcpy(lpSolver->primalColumnSolution(), + babModel_->bestSolution(), n * sizeof(double)); + ClpParamUtils::saveSolution(osiclp->getModelPtr(), "debug.file"); } #endif statistics_cut_time = 0.0; - if (!noPrinting_) { // Print more statistics - sprintf(generalPrint, "Cuts at root node changed objective from %g to %g", - babModel_->getContinuousObjective(), babModel_->rootObjectiveAfterCuts()); - generalMessageHandler->message(CLP_GENERAL, generalMessages) - << generalPrint - << CoinMessageEol; - + buffer.str(""); + buffer << "Cuts at root node changed objective from " + << babModel_->getContinuousObjective() << " to " + << babModel_->rootObjectiveAfterCuts(); + printGeneralMessage(model_, buffer.str()); numberGenerators = babModel_->numberCutGenerators(); // can get here twice! if (statistics_number_cuts != NULL) @@ -7949,52 +8426,56 @@ int CbcMain1(int argc, const char *argv[], statistics_number_generators = numberGenerators; char timing[30]; - for (iGenerator = 0; iGenerator < numberGenerators; iGenerator++) { - CbcCutGenerator *generator = babModel_->cutGenerator(iGenerator); - statistics_name_generators[iGenerator] = generator->cutGeneratorName(); - statistics_number_cuts[iGenerator] = generator->numberCutsInTotal(); - sprintf(generalPrint, "%s was tried %d times and created %d cuts of which %d were active after adding rounds of cuts", - generator->cutGeneratorName(), - generator->numberTimesEntered(), - generator->numberCutsInTotal() + generator->numberColumnCuts(), - generator->numberCutsActive()); + for (iGenerator = 0; iGenerator < numberGenerators; + iGenerator++) { + CbcCutGenerator *generator = + babModel_->cutGenerator(iGenerator); + statistics_name_generators[iGenerator] = + generator->cutGeneratorName(); + statistics_number_cuts[iGenerator] = + generator->numberCutsInTotal(); + buffer.str(""); + buffer << generator->cutGeneratorName() << " was tried " + << generator->numberTimesEntered() << " times and created " + << generator->numberCutsInTotal() + generator->numberColumnCuts() + << " cuts of which " + << generator->numberCutsActive() + << " were active after adding rounds of cuts"; if (generator->timing()) { - sprintf(timing, " (%.3f seconds)", generator->timeInCutGenerator()); - strcat(generalPrint, timing); - statistics_cut_time += generator->timeInCutGenerator(); + buffer << " (" << generator->timeInCutGenerator() << " seconds)"; + statistics_cut_time += generator->timeInCutGenerator(); } - CglStored *stored = dynamic_cast< CglStored * >(generator->generator()); - if (stored && !generator->numberCutsInTotal()) + CglStored *stored = dynamic_cast(generator->generator()); + if (stored && !generator->numberCutsInTotal()){ continue; + } #ifndef CLP_INVESTIGATE - CglImplication *implication = dynamic_cast< CglImplication * >(generator->generator()); + CglImplication *implication = + dynamic_cast(generator->generator()); if (implication && !generator->numberCutsInTotal()) continue; #endif - generalMessageHandler->message(CLP_GENERAL, generalMessages) - << generalPrint - << CoinMessageEol; + printGeneralMessage(model_, buffer.str()); } #ifdef COIN_DEVELOP printf("%d solutions found by heuristics\n", - babModel_->getNumberHeuristicSolutions()); + babModel_->getNumberHeuristicSolutions()); // Not really generator but I am feeling lazy - for (iGenerator = 0; iGenerator < babModel_->numberHeuristics(); iGenerator++) { + for (iGenerator = 0; iGenerator < babModel_->numberHeuristics(); + iGenerator++) { CbcHeuristic *heuristic = babModel_->heuristic(iGenerator); if (heuristic->numRuns()) { // Need to bring others inline - sprintf(generalPrint, "%s was tried %d times out of %d and created %d solutions\n", - heuristic->heuristicName(), - heuristic->numRuns(), - heuristic->numCouldRun(), - heuristic->numberSolutionsFound()); - generalMessageHandler->message(CLP_GENERAL, generalMessages) - << generalPrint - << CoinMessageEol; + buffer.str(""); + buffer << heuristic->heuristicName() << " was tried " + << heuristic->numRuns() << " times out of " + << heuristic->numCouldRun() << " and created " + << heuristic->numberSolutionsFound() + << " solutions" << std::endl; + printGeneralMessage(model_, buffer.str()); } } #endif - } // adjust time to allow for children on some systems time2 = CoinCpuTime() + CoinCpuTimeJustChildren(); totalTime += time2 - time1; @@ -8014,16 +8495,21 @@ int CbcMain1(int argc, const char *argv[], saveSolver = NULL; } } - if (babModel_->getMinimizationObjValue() < 1.0e50 && type == CBC_PARAM_ACTION_BAB) { + if (babModel_->getMinimizationObjValue() < 1.0e50 && + cbcParamCode == CbcParam::BAB) { // post process int n; if (preProcess) { n = saveSolver->getNumCols(); bestSolution = new double[n]; #ifndef CBC_OTHER_SOLVER - OsiClpSolverInterface *clpSolver = dynamic_cast< OsiClpSolverInterface * >(babModel_->solver()); + OsiClpSolverInterface *clpSolver = + dynamic_cast( + babModel_->solver()); #else - OsiCpxSolverInterface *clpSolver = dynamic_cast< OsiCpxSolverInterface * >(babModel_->solver()); + OsiCpxSolverInterface *clpSolver = + dynamic_cast( + babModel_->solver()); #endif // Save bounds on processed model const int *originalColumns = process.originalColumns(); @@ -8045,15 +8531,20 @@ int CbcMain1(int argc, const char *argv[], } #ifndef CBC_OTHER_SOLVER ClpSimplex *lpSolver = clpSolver->getModelPtr(); - lpSolver->setSpecialOptions(lpSolver->specialOptions() | IN_BRANCH_AND_BOUND); // say is Cbc (and in branch and bound) + lpSolver->setSpecialOptions( + lpSolver->specialOptions() | + IN_BRANCH_AND_BOUND); // say is Cbc (and in branch and + // bound) #endif // put back any saved solutions putBackOtherSolutions(babModel_, &model_, &process); - setPreProcessingMode(babModel_->solver(),2); + setPreProcessingMode(babModel_->solver(), 2); process.postProcess(*babModel_->solver()); - setPreProcessingMode(saveSolver,0); + setPreProcessingMode(saveSolver, 0); #ifdef COIN_DEVELOP - if (model_.bestSolution() && fabs(model_.getMinimizationObjValue() - babModel_->getMinimizationObjValue()) < 1.0e-8) { + if (model_.bestSolution() && + fabs(model_.getMinimizationObjValue() - + babModel_->getMinimizationObjValue()) < 1.0e-8) { const double *b1 = model_.bestSolution(); const double *b2 = saveSolver->getColSolution(); const double *columnLower = saveSolver->getColLower(); @@ -8061,17 +8552,17 @@ int CbcMain1(int argc, const char *argv[], for (int i = 0; i < n; i++) { if (fabs(b1[i] - b2[i]) > 1.0e-7) { printf("%d %g %g %g %g\n", i, b1[i], b2[i], - columnLower[i], columnUpper[i]); + columnLower[i], columnUpper[i]); } } } #endif bool tightenB = false; - { + if (testOsiOptions<0) { int n = babModel_->numberObjects(); for (int i = 0; i < n; i++) { const OsiObject *obj = babModel_->object(i); - if (!dynamic_cast< const CbcSimpleInteger * >(obj)) { + if (!dynamic_cast(obj)) { tightenB = true; break; } @@ -8081,7 +8572,7 @@ int CbcMain1(int argc, const char *argv[], // Double check bounds columnLower = saveSolver->getColLower(); columnUpper = saveSolver->getColUpper(); - if ((process.options()&128)!=0) + // skip tighten if not integer if ((process.options()&128)!=0) tightenB = false; int numberChanged = 0; if ((process.options()&256)==0) { @@ -8147,65 +8638,89 @@ int CbcMain1(int argc, const char *argv[], delete[] lower2; delete[] upper2; if (numberChanged) { - sprintf(generalPrint, "%d bounds tightened after postprocessing\n", - numberChanged); - generalMessageHandler->message(CLP_GENERAL, generalMessages) - << generalPrint - << CoinMessageEol; + buffer.str(""); + buffer << numberChanged << " bounds tightened after postprocessing" + << std::endl; + printGeneralMessage(model_, buffer.str()); } - //saveSolver->resolve(); + // saveSolver->resolve(); if (true /*!saveSolver->isProvenOptimal()*/) { // try all slack - CoinWarmStartBasis *basis = dynamic_cast< CoinWarmStartBasis * >(babModel_->solver()->getEmptyWarmStart()); + CoinWarmStartBasis *basis = + dynamic_cast( + babModel_->solver()->getEmptyWarmStart()); saveSolver->setWarmStart(basis); delete basis; saveSolver->initialSolve(); #ifdef COIN_DEVELOP saveSolver->writeMps("inf2"); #endif - OsiClpSolverInterface *osiclp = dynamic_cast< OsiClpSolverInterface * >(saveSolver); + OsiClpSolverInterface *osiclp = + dynamic_cast(saveSolver); if (osiclp) osiclp->getModelPtr()->checkUnscaledSolution(); } - //assert(saveSolver->isProvenOptimal()); + // assert(saveSolver->isProvenOptimal()); #ifndef CBC_OTHER_SOLVER // and original solver - originalSolver->setDblParam(OsiDualObjectiveLimit, COIN_DBL_MAX); + originalSolver->setDblParam(OsiDualObjectiveLimit, + COIN_DBL_MAX); assert(n >= originalSolver->getNumCols()); n = originalSolver->getNumCols(); originalSolver->setColLower(saveSolver->getColLower()); originalSolver->setColUpper(saveSolver->getColUpper()); // basis - CoinWarmStartBasis *basis = dynamic_cast< CoinWarmStartBasis * >(babModel_->solver()->getWarmStart()); + CoinWarmStartBasis *basis = + dynamic_cast( + babModel_->solver()->getWarmStart()); originalSolver->setBasis(*basis); delete basis; originalSolver->resolve(); if (!originalSolver->isProvenOptimal()) { // try all slack - CoinWarmStartBasis *basis = dynamic_cast< CoinWarmStartBasis * >(babModel_->solver()->getEmptyWarmStart()); + CoinWarmStartBasis *basis = + dynamic_cast( + babModel_->solver()->getEmptyWarmStart()); originalSolver->setBasis(*basis); delete basis; originalSolver->initialSolve(); - OsiClpSolverInterface *osiclp = dynamic_cast< OsiClpSolverInterface * >(originalSolver); + OsiClpSolverInterface *osiclp = + dynamic_cast(originalSolver); if (osiclp) osiclp->getModelPtr()->checkUnscaledSolution(); } - //assert(originalSolver->isProvenOptimal()); + // assert(originalSolver->isProvenOptimal()); #endif babModel_->assignSolver(saveSolver); - memcpy(bestSolution, babModel_->solver()->getColSolution(), n * sizeof(double)); + memcpy(bestSolution, babModel_->solver()->getColSolution(), + n * sizeof(double)); } else { n = babModel_->solver()->getNumCols(); bestSolution = new double[n]; - memcpy(bestSolution, babModel_->solver()->getColSolution(), n * sizeof(double)); + memcpy(bestSolution, babModel_->solver()->getColSolution(), + n * sizeof(double)); +#ifndef CBC_OTHER_SOLVER + // and put back bounds in very original solver + ClpSimplex *original = originalSolver->getModelPtr(); + double *lower = original->columnLower(); + double *upper = original->columnUpper(); + int n2 = original->numberColumns(); + memcpy(lower,babModel_->solver()->getColLower(), + n2*sizeof(double)); + memcpy(upper,babModel_->solver()->getColUpper(), + n2*sizeof(double)); + originalSolver->resolve(); +#endif } if (returnMode == 1 && model_.numberSavedSolutions() < 2) { model_.deleteSolutions(); - model_.setBestSolution(bestSolution, n, babModel_->getMinimizationObjValue()); + model_.setBestSolution(bestSolution, n, + babModel_->getMinimizationObjValue()); } babModel_->deleteSolutions(); - babModel_->setBestSolution(bestSolution, n, babModel_->getMinimizationObjValue()); + babModel_->setBestSolution( + bestSolution, n, babModel_->getMinimizationObjValue()); #ifndef CBC_OTHER_SOLVER // and put back in very original solver { @@ -8214,7 +8729,7 @@ int CbcMain1(int argc, const char *argv[], double *upper = original->columnUpper(); double *solution = original->primalColumnSolution(); int n = original->numberColumns(); - //assert (!n||n==babModel_->solver()->getNumCols()); + // assert (!n||n==babModel_->solver()->getNumCols()); for (int i = 0; i < n; i++) { solution[i] = bestSolution[i]; if (originalSolver->isInteger(i)) { @@ -8223,30 +8738,39 @@ int CbcMain1(int argc, const char *argv[], } } // basis - CoinWarmStartBasis *basis = dynamic_cast< CoinWarmStartBasis * >(babModel_->solver()->getWarmStart()); + CoinWarmStartBasis *basis = + dynamic_cast( + babModel_->solver()->getWarmStart()); originalSolver->setBasis(*basis); delete basis; - originalSolver->setDblParam(OsiDualObjectiveLimit, COIN_DBL_MAX); + originalSolver->setDblParam(OsiDualObjectiveLimit, + COIN_DBL_MAX); #ifdef COIN_HAS_LINK - if (originalSolver->getMatrixByCol()) - originalSolver->setHintParam(OsiDoPresolveInResolve, true, OsiHintTry); + if (originalSolver->getMatrixByCol()) + originalSolver->setHintParam(OsiDoPresolveInResolve, true, + OsiHintTry); #else - originalSolver->setHintParam(OsiDoPresolveInResolve, true, OsiHintTry); + originalSolver->setHintParam(OsiDoPresolveInResolve, true, + OsiHintTry); #endif originalSolver->resolve(); if (!originalSolver->isProvenOptimal()) { // try all slack - CoinWarmStartBasis *basis = dynamic_cast< CoinWarmStartBasis * >(babModel_->solver()->getEmptyWarmStart()); + CoinWarmStartBasis *basis = + dynamic_cast( + babModel_->solver()->getEmptyWarmStart()); originalSolver->setBasis(*basis); delete basis; originalSolver->initialSolve(); - OsiClpSolverInterface *osiclp = dynamic_cast< OsiClpSolverInterface * >(originalSolver); + OsiClpSolverInterface *osiclp = + dynamic_cast(originalSolver); if (osiclp) osiclp->getModelPtr()->checkUnscaledSolution(); #ifdef CLP_INVESTIGATE if (!originalSolver->isProvenOptimal()) { if (saveSolver) { - printf("saveSolver and originalSolver matrices saved\n"); + printf( + "saveSolver and originalSolver matrices saved\n"); saveSolver->writeMps("infA"); } else { printf("originalSolver matrix saved\n"); @@ -8255,23 +8779,28 @@ int CbcMain1(int argc, const char *argv[], } #endif } - //assert(originalSolver->isProvenOptimal()); + // assert(originalSolver->isProvenOptimal()); } #endif checkSOS(babModel_, babModel_->solver()); - } else if (model_.bestSolution() && type == CBC_PARAM_ACTION_BAB && model_.getMinimizationObjValue() < 1.0e50 && preProcess) { - sprintf(generalPrint, "Restoring heuristic best solution of %g", model_.getMinimizationObjValue()); - generalMessageHandler->message(CLP_GENERAL, generalMessages) - << generalPrint - << CoinMessageEol; + } else if (model_.bestSolution() && + cbcParamCode == CbcParam::BAB && + model_.getMinimizationObjValue() < 1.0e50 && + preProcess) { + buffer.str(""); + buffer << "Restoring heuristic best solution of " + << model_.getMinimizationObjValue(); + printGeneralMessage(model_, buffer.str()); int n = saveSolver->getNumCols(); bestSolution = new double[n]; // Put solution now back in saveSolver saveSolver->setColSolution(model_.bestSolution()); babModel_->assignSolver(saveSolver); saveSolver = NULL; - babModel_->setMinimizationObjValue(model_.getMinimizationObjValue()); - memcpy(bestSolution, babModel_->solver()->getColSolution(), n * sizeof(double)); + babModel_->setMinimizationObjValue( + model_.getMinimizationObjValue()); + memcpy(bestSolution, babModel_->solver()->getColSolution(), + n * sizeof(double)); #ifndef CBC_OTHER_SOLVER // and put back in very original solver { @@ -8280,7 +8809,7 @@ int CbcMain1(int argc, const char *argv[], double *upper = original->columnUpper(); double *solution = original->primalColumnSolution(); int n = original->numberColumns(); - //assert (!n||n==babModel_->solver()->getNumCols()); + // assert (!n||n==babModel_->solver()->getNumCols()); for (int i = 0; i < n; i++) { solution[i] = bestSolution[i]; if (originalSolver->isInteger(i)) { @@ -8289,17 +8818,21 @@ int CbcMain1(int argc, const char *argv[], } } // basis - CoinWarmStartBasis *basis = dynamic_cast< CoinWarmStartBasis * >(babModel_->solver()->getWarmStart()); + CoinWarmStartBasis *basis = + dynamic_cast( + babModel_->solver()->getWarmStart()); originalSolver->setBasis(*basis); delete basis; } #endif } #ifndef CBC_OTHER_SOLVER - //if (type==CBC_PARAM_ACTION_STRENGTHEN&&strengthenedModel) - //clpSolver = dynamic_cast< OsiClpSolverInterface*> (strengthenedModel); + // if (type==STRENGTHEN&&strengthenedModel) + // clpSolver = dynamic_cast< OsiClpSolverInterface*> + // (strengthenedModel); else if (statusUserFunction_[0]) - clpSolver = dynamic_cast< OsiClpSolverInterface * >(babModel_->solver()); + clpSolver = + dynamic_cast(babModel_->solver()); lpSolver = clpSolver->getModelPtr(); if (numberChanged) { for (int i = 0; i < numberChanged; i++) { @@ -8309,12 +8842,13 @@ int CbcMain1(int argc, const char *argv[], delete[] changed; } #endif - if (type == CBC_PARAM_ACTION_BAB) { + if (cbcParamCode == CbcParam::BAB) { #ifndef CBC_OTHER_SOLVER - //move best solution (should be there -- but ..) + // move best solution (should be there -- but ..) int n = lpSolver->getNumCols(); if (bestSolution) { - memcpy(lpSolver->primalColumnSolution(), bestSolution, n * sizeof(double)); + memcpy(lpSolver->primalColumnSolution(), bestSolution, + n * sizeof(double)); // now see what that does to row solution int numberRows = lpSolver->numberRows(); double *rowSolution = lpSolver->primalRowSolution(); @@ -8322,8 +8856,9 @@ int CbcMain1(int argc, const char *argv[], lpSolver->clpMatrix()->times(1.0, bestSolution, rowSolution); lpSolver->setObjectiveValue(babModel_->getObjValue()); } - if (debugFile == "create" && bestSolution) { - saveSolution(lpSolver, "debug.file"); + if (parameters[CbcParam::DEBUGFILE]->fileName() == + "create" && bestSolution) { + ClpParamUtils::saveSolution(lpSolver, "debug.file"); } #else if (bestSolution) { @@ -8332,8 +8867,18 @@ int CbcMain1(int argc, const char *argv[], #endif delete saveSolver; delete[] bestSolution; - std::string statusName[] = { "", "Stopped on ", "Run abandoned", "", "", "User ctrl-c" }; - std::string minor[] = { "Optimal solution found", "Linear relaxation infeasible", "Optimal solution found (within gap tolerance)", "node limit", "time limit", "user ctrl-c", "solution limit", "Linear relaxation unbounded", "Problem proven infeasible" }; + std::string statusName[] = { + "", "Stopped on ", "Run abandoned", "", "", "User ctrl-c"}; + std::string minor[] = { + "Optimal solution found", + "Linear relaxation infeasible", + "Optimal solution found (within gap tolerance)", + "node limit", + "time limit", + "user ctrl-c", + "solution limit", + "Linear relaxation unbounded", + "Problem proven infeasible"}; int iStat = babModel_->status(); int iStat2 = babModel_->secondaryStatus(); if (!iStat && !iStat2 && !bestSolution) @@ -8348,54 +8893,43 @@ int CbcMain1(int argc, const char *argv[], statistics_tighter = babModel_->rootObjectiveAfterCuts(); statistics_nodes = babModel_->getNodeCount(); statistics_iterations = babModel_->getIterationCount(); - ; statistics_result = statusName[iStat]; - ; - if (!noPrinting_) { - sprintf(generalPrint, "\nResult - %s%s\n", - statusName[iStat].c_str(), - minor[iStat2].c_str()); - generalMessageHandler->message(CLP_GENERAL, generalMessages) - << generalPrint - << CoinMessageEol; - if (babModel_->bestSolution()) { - sprintf(generalPrint, - "Objective value: %.8f\n", - babModel_->getObjValue()); - } else { - sprintf(generalPrint, - "No feasible solution found\n"); - } - if (iStat2 >= 2 && iStat2 <= 6) { - bool minimizing = babModel_->solver()->getObjSense() > 0.0; - sprintf(generalPrint + strlen(generalPrint), - "%s bound: %.3f\n", - minimizing ? "Lower" : "Upper", - babModel_->getBestPossibleObjValue()); - if (babModel_->bestSolution()) { - sprintf(generalPrint + strlen(generalPrint), - "Gap: %.2f\n", - (babModel_->getObjValue() - babModel_->getBestPossibleObjValue()) / fabs(babModel_->getBestPossibleObjValue())); - } - } - sprintf(generalPrint + strlen(generalPrint), - "Enumerated nodes: %d\n", - babModel_->getNodeCount()); - sprintf(generalPrint + strlen(generalPrint), - "Total iterations: %d\n", - babModel_->getIterationCount()); + buffer.str(""); + buffer << std::endl << "Result - " + << statusName[iStat].c_str() << minor[iStat2].c_str() + << std::endl; + printGeneralMessage(model_, buffer.str()); + if (babModel_->bestSolution()) { + buffer.str(""); + buffer << "Objective value: " + << babModel_->getObjValue() << std::endl; + } else { + buffer.str(""); + buffer << "No feasible solution found\n"; + } + if (iStat2 >= 2 && iStat2 <= 6) { + bool minimizing = babModel_->solver()->getObjSense() > 0.0; + std::string tmp = minimizing ? "Lower" : "Upper"; + buffer << tmp << " bound: " + << babModel_->getBestPossibleObjValue() << std::endl; + if (babModel_->bestSolution()) { + buffer << "Gap: " + << (babModel_->getObjValue() - + babModel_->getBestPossibleObjValue()) / + fabs(babModel_->getBestPossibleObjValue()) << std::endl; + } + } + buffer << "Enumerated nodes: " + << babModel_->getNodeCount() << std::endl; + buffer << "Total iterations: "; + buffer << babModel_->getIterationCount() << std::endl; #if CBC_QUIET == 0 - sprintf(generalPrint + strlen(generalPrint), - "Time (CPU seconds): %.2f\n", - CoinCpuTime() - time1); - sprintf(generalPrint + strlen(generalPrint), - "Time (Wallclock seconds): %.2f\n", - CoinGetTimeOfDay() - time1Elapsed); + buffer << "Time (CPU seconds): " + << CoinCpuTime() - time1 << std::endl; + buffer << "Time (Wallclock seconds): " + << CoinGetTimeOfDay() - time1Elapsed << std::endl; #endif - generalMessageHandler->message(CLP_GENERAL, generalMessages) - << generalPrint - << CoinMessageEol; - } + printGeneralMessage(model_, buffer.str()); int returnCode = 0; if (callBack != NULL) returnCode = callBack(babModel_, 5); @@ -8406,10 +8940,12 @@ int CbcMain1(int argc, const char *argv[], babModel_ = NULL; return returnCode; } - if (statusUserFunction_[0]) { - clpSolver = dynamic_cast< OsiClpSolverInterface * >(babModel_->solver()); + if (info && statusUserFunction_[0]) { + clpSolver = dynamic_cast( + babModel_->solver()); lpSolver = clpSolver->getModelPtr(); - double value = babModel_->getObjValue() * lpSolver->getObjSense(); + double value = + babModel_->getObjValue() * lpSolver->getObjSense(); char buf[300]; int pos = 0; if (iStat == 0) { @@ -8425,7 +8961,8 @@ int CbcMain1(int argc, const char *argv[], iStat = 3; else iStat = 4; - pos += sprintf(buf + pos, "stopped on %s,", minor[iStat2].c_str()); + pos += sprintf(buf + pos, "stopped on %s,", + minor[iStat2].c_str()); } else if (iStat == 2) { iStat = 7; pos += sprintf(buf + pos, "stopped on difficulties,"); @@ -8436,68 +8973,71 @@ int CbcMain1(int argc, const char *argv[], pos += sprintf(buf + pos, "status unknown,"); iStat = 6; } - info.problemStatus = iStat; - info.objValue = value; + info->problemStatus = iStat; + info->objValue = value; if (babModel_->getObjValue() < 1.0e40) { int precision = ampl_obj_prec(); if (precision > 0) pos += sprintf(buf + pos, " objective %.*g", precision, - value); + value); else pos += sprintf(buf + pos, " objective %g", value); } sprintf(buf + pos, "\n%d nodes, %d iterations, %g seconds", - babModel_->getNodeCount(), - babModel_->getIterationCount(), - totalTime); + babModel_->getNodeCount(), + babModel_->getIterationCount(), totalTime); if (bestSolution) { - free(info.primalSolution); + free(info->primalSolution); if (!numberKnapsack) { - info.primalSolution = (double *)malloc(n * sizeof(double)); - CoinCopyN(lpSolver->primalColumnSolution(), n, info.primalSolution); + info->primalSolution = + (double *)malloc(n * sizeof(double)); + CoinCopyN(lpSolver->primalColumnSolution(), n, + info->primalSolution); int numberRows = lpSolver->numberRows(); - free(info.dualSolution); - info.dualSolution = (double *)malloc(numberRows * sizeof(double)); - CoinCopyN(lpSolver->dualRowSolution(), numberRows, info.dualSolution); + free(info->dualSolution); + info->dualSolution = + (double *)malloc(numberRows * sizeof(double)); + CoinCopyN(lpSolver->dualRowSolution(), numberRows, + info->dualSolution); } else { // expanded knapsack - info.dualSolution = NULL; + info->dualSolution = NULL; int numberColumns = saveCoinModel.numberColumns(); - info.primalSolution = (double *)malloc(numberColumns * sizeof(double)); + info->primalSolution = + (double *)malloc(numberColumns * sizeof(double)); // Fills in original solution (coinModel length) - afterKnapsack(saveTightenedModel, whichColumn, knapsackStart, - knapsackRow, numberKnapsack, - lpSolver->primalColumnSolution(), info.primalSolution, 1); + afterKnapsack(saveTightenedModel, whichColumn, + knapsackStart, knapsackRow, numberKnapsack, + lpSolver->primalColumnSolution(), + info->primalSolution, 1); } } else { - info.primalSolution = NULL; - info.dualSolution = NULL; + info->primalSolution = NULL; + info->dualSolution = NULL; } // put buffer into info - strcpy(info.buffer, buf); + strcpy(info->buffer, buf); } } else { - sprintf(generalPrint, "Model strengthened - now has %d rows", - clpSolver->getNumRows()); - printGeneralMessage(model_, generalPrint); + buffer.str(""); + buffer << "Model strengthened - now has " + << clpSolver->getNumRows() << " rows"; + printGeneralMessage(model_, buffer.str()); } time1 = time2; if (statusUserFunction_[0]) { // keep if going to be destroyed OsiSolverInterface *solver = babModel_->solver(); - OsiClpSolverInterface *clpSolver = dynamic_cast< OsiClpSolverInterface * >(solver); + OsiClpSolverInterface *clpSolver = + dynamic_cast(solver); ClpSimplex *lpSolver2 = clpSolver->getModelPtr(); if (lpSolver == lpSolver2) babModel_->setModelOwnsSolver(false); } - //delete babModel_; - //babModel_=NULL; - } else { - sprintf(generalPrint, "** Current model not valid"); - printGeneralMessage(model_, generalPrint); - } - break; - case CLP_PARAM_ACTION_IMPORT: { + // delete babModel_; + // babModel_=NULL; + } break; + case CbcParam::IMPORT: { if (!statusUserFunction_[0]) { free(priorities); priorities = NULL; @@ -8524,186 +9064,176 @@ int CbcMain1(int argc, const char *argv[], free(sosPriority); sosPriority = NULL; } - //delete babModel_; - //babModel_=NULL; - // get next field - field = CoinReadGetString(argc, argv); - if (field == "$") { - field = parameters_[iParam].stringValue(); - } else if (field == "EOL") { - parameters_[iParam].printString(); - break; - } else { - parameters_[iParam].setStringValue(field); + // delete babModel_; + // babModel_=NULL; + // see if we have a file name + cbcParam->readValue(inputQueue, fileName, &message); + // TODO Think about how to do this right + canOpen = false; + bool absolutePath = true; + CoinParamUtils::processFile(fileName, + parameters[CbcParam::DIRECTORY]->dirName()); + if (fileName == ""){ + fileName = parameters[CbcParam::IMPORTFILE]->fileName(); + }else{ + parameters[CbcParam::IMPORTFILE]->setFileName(fileName); + } + if (fileName[0] != '/' && fileName[0] != '\\' && + !strchr(fileName.c_str(), ':')) { + absolutePath = false; } - std::string fileName; - bool canOpen = false; // See if gmpl file int gmpl = 0; std::string gmplData; - if (field == "-" || field == "stdin") { + if (fileName == "-") { // stdin canOpen = true; - fileName = "-"; - } else if (field == "-lp" || field == "stdin_lp") { + } else if (fileName == "-lp") { // stdin canOpen = true; fileName = "-"; gmpl = -1; //.lp format } else { // See if .lp - { - const char *c_name = field.c_str(); - size_t length = strlen(c_name); - if ((length > 3 && !strncmp(c_name + length - 3, ".lp", 3)) || (length > 6 && !strncmp(c_name + length - 6, ".lp.gz", 6)) || (length > 7 && !strncmp(c_name + length - 7, ".lp.bz2", 7))) - gmpl = -1; // .lp - } - bool absolutePath; - if (dirsep == '/') { - // non Windows (or cygwin) - absolutePath = (field[0] == '/'); - } else { - //Windows (non cycgwin) - absolutePath = (field[0] == '\\'); - // but allow for : - if (strchr(field.c_str(), ':')) - absolutePath = true; - } - if (absolutePath) { - fileName = field; - size_t length = field.size(); - size_t percent = field.find('%'); - if (percent < length && percent > 0) { - gmpl = 1; - fileName = field.substr(0, percent); - gmplData = field.substr(percent + 1); - if (percent < length - 1) - gmpl = 2; // two files - printf("GMPL model file %s and data file %s\n", - fileName.c_str(), gmplData.c_str()); - } - } else if (field[0] == '~') { - char *environVar = getenv("HOME"); - if (environVar) { - std::string home(environVar); - field = field.erase(0, 1); - fileName = home + field; - } else { - fileName = field; - } - } else { - fileName = directory + field; - // See if gmpl (model & data) - or even lp file - size_t length = field.size(); - size_t percent = field.find('%'); - if (percent < length && percent > 0) { - gmpl = 1; - fileName = directory + field.substr(0, percent); - gmplData = directory + field.substr(percent + 1); - if (percent < length - 1) - gmpl = 2; // two files - printf("GMPL model file %s and data file %s\n", - fileName.c_str(), gmplData.c_str()); - } + const char *c_name = fileName.c_str(); + size_t length = strlen(c_name); + if ((length > 3 && !strncmp(c_name + length - 3, ".lp", 3)) || + (length > 6 && + !strncmp(c_name + length - 6, ".lp.gz", 6)) || + (length > 7 && !strncmp(c_name + length - 7, ".lp.bz2", 7))){ + gmpl = -1; // .lp + } + length = fileName.size(); + size_t percent = fileName.find('%'); + if (percent < length && percent > 0) { +#ifdef COINUTILS_HAS_GLPK + gmpl = 1; + fileName = fileName.substr(0, percent); + gmplData = fileName.substr(percent + 1); + if (!absolutePath){ + fileName = parameters[CbcParam::DIRECTORY]->dirName() + + fileName; + gmplData = parameters[CbcParam::DIRECTORY]->dirName() + + fileName; + } + gmpl = (percent < length - 1) ? 2 : 1; + printf("GMPL model file %s and data file %s\n", + fileName.c_str(), gmplData.c_str()); +#else + printf("Cbc was not built with GMPL support. Exiting.\n"); + // This is surely not the right thing to do here. Should we + // throw an exceptioon? Exit? + abort(); +#endif } - std::string name = fileName; - if (fileCoinReadable(name)) { + if (fileCoinReadable(fileName)) { // can open - lets go for it canOpen = true; if (gmpl == 2) { - FILE *fp; + fp; fp = fopen(gmplData.c_str(), "r"); if (fp) { fclose(fp); } else { canOpen = false; - sprintf(generalPrint, "Unable to open file %s", gmplData.c_str()); - printGeneralMessage(model_, generalPrint); + buffer.str(""); + buffer << "Unable to open file " << gmplData.c_str(); + printGeneralMessage(model_, buffer.str()); + continue; } } } else { - sprintf(generalPrint, "Unable to open file %s", fileName.c_str()); - printGeneralMessage(model_, generalPrint); + buffer.str(""); + buffer << "Unable to open file " << fileName.c_str(); + printGeneralMessage(model_, buffer.str()); + continue; } } - if (canOpen) { - int status; - numberLotSizing = 0; - delete[] lotsize; + int status; + numberLotSizing = 0; + delete[] lotsize; #ifndef CBC_OTHER_SOLVER - ClpSimplex *lpSolver = clpSolver->getModelPtr(); - if (!gmpl) { - status = clpSolver->readMps(fileName.c_str(), - keepImportNames != 0, - allowImportErrors != 0); - } else if (gmpl > 0) { - status = lpSolver->readGMPL(fileName.c_str(), - (gmpl == 2) ? gmplData.c_str() : NULL, - keepImportNames != 0); + ClpSimplex *lpSolver = clpSolver->getModelPtr(); + if (!gmpl) { + status = + clpSolver->readMps(fileName.c_str(), keepImportNames != 0, + allowImportErrors != 0); + } else if (gmpl > 0) { +#ifdef COINUTILS_HAS_GLPK + status = lpSolver->readGMPL( + fileName.c_str(), (gmpl == 2) ? gmplData.c_str() : NULL, + keepImportNames != 0, &coin_glp_tran, &coin_glp_prob); +#endif } else { #ifdef KILL_ZERO_READLP - status = clpSolver->readLp(fileName.c_str(), lpSolver->getSmallElementValue()); + status = clpSolver->readLp(fileName.c_str(), + lpSolver->getSmallElementValue()); #else - status = clpSolver->readLp(fileName.c_str(), 1.0e-12); + status = clpSolver->readLp(fileName.c_str(), 1.0e-12); #endif - } + } #else - status = clpSolver->readMps(fileName.c_str(), ""); + status = clpSolver->readMps(fileName.c_str(), ""); #endif - if (!status || (status > 0 && allowImportErrors)) { + if (!status || (status > 0 && allowImportErrors)) { #ifndef CBC_OTHER_SOLVER - if (keepImportNames) { + if (keepImportNames) { lengthName = lpSolver->lengthNames(); rowNames = *(lpSolver->rowNames()); columnNames = *(lpSolver->columnNames()); - } else { + } else { lengthName = 0; - } - // really just for testing - double objScale = parameters_[whichParam(CLP_PARAM_DBL_OBJSCALE2, parameters_)].doubleValue(); - if (objScale != 1.0) { + } + // really just for testing + double objScale = clpParameters[ClpParam::OBJSCALE2]->dblVal(); + if (objScale != 1.0) { int iColumn; int numberColumns = lpSolver->numberColumns(); double *dualColumnSolution = lpSolver->dualColumnSolution(); ClpObjective *obj = lpSolver->objectiveAsObject(); - assert(dynamic_cast< ClpLinearObjective * >(obj)); + assert(dynamic_cast(obj)); double offset; double *objective = obj->gradient(NULL, NULL, offset, true); for (iColumn = 0; iColumn < numberColumns; iColumn++) { - dualColumnSolution[iColumn] *= objScale; - objective[iColumn] *= objScale; + dualColumnSolution[iColumn] *= objScale; + objective[iColumn] *= objScale; } int iRow; int numberRows = lpSolver->numberRows(); double *dualRowSolution = lpSolver->dualRowSolution(); for (iRow = 0; iRow < numberRows; iRow++) - dualRowSolution[iRow] *= objScale; - lpSolver->setObjectiveOffset(objScale * lpSolver->objectiveOffset()); - } - goodModel = true; - // sets to all slack (not necessary?) - lpSolver->createStatus(); - // See if sos - if (clpSolver->numberSOS()) { + dualRowSolution[iRow] *= objScale; + lpSolver->setObjectiveOffset(objScale * + lpSolver->objectiveOffset()); + } + goodModel = true; + // sets to all slack (not necessary?) + lpSolver->createStatus(); + // See if sos + if (clpSolver->numberSOS()) { // SOS numberSOS = clpSolver->numberSOS(); const CoinSet *setInfo = clpSolver->setInfo(); - sosStart = reinterpret_cast< int * >(malloc((numberSOS + 1) * sizeof(int))); - sosType = reinterpret_cast< char * >(malloc(numberSOS * sizeof(char))); + sosStart = reinterpret_cast( + malloc((numberSOS + 1) * sizeof(int))); + sosType = reinterpret_cast( + malloc(numberSOS * sizeof(char))); const double *lower = clpSolver->getColLower(); const double *upper = clpSolver->getColUpper(); int i; int nTotal = 0; sosStart[0] = 0; for (i = 0; i < numberSOS; i++) { - int type = setInfo[i].setType(); - int n = setInfo[i].numberEntries(); - sosType[i] = static_cast< char >(type); - nTotal += n; - sosStart[i + 1] = nTotal; - } - sosIndices = reinterpret_cast< int * >(malloc(nTotal * sizeof(int))); - sosReference = reinterpret_cast< double * >(malloc(nTotal * sizeof(double))); + int type = setInfo[i].setType(); + int n = setInfo[i].numberEntries(); + sosType[i] = static_cast(type); + nTotal += n; + sosStart[i + 1] = nTotal; + } + sosIndices = + reinterpret_cast(malloc(nTotal * sizeof(int))); + sosReference = reinterpret_cast( + malloc(nTotal * sizeof(double))); for (i = 0; i < numberSOS; i++) { int n = setInfo[i].numberEntries(); const int *which = setInfo[i].which(); @@ -8717,726 +9247,581 @@ int CbcMain1(int argc, const char *argv[], if (lower[k] < -1.0e15) clpSolver->setColLower(k, -1.0e15); sosIndices[j + base] = k; - sosReference[j + base] = weights ? weights[j] : static_cast< double >(j); + sosReference[j + base] = + weights ? weights[j] : static_cast(j); } } - } - // make sure integer - // also deal with semi-continuous - int numberColumns = lpSolver->numberColumns(); - int i; - for (i = 0; i < numberColumns; i++) { + } + // make sure integer + // also deal with semi-continuous + int numberColumns = lpSolver->numberColumns(); + int i; + for (i = 0; i < numberColumns; i++) { if (clpSolver->integerType(i) > 2) - break; + break; if (lpSolver->isInteger(i)) - clpSolver->setInteger(i); - } - if (i < numberColumns) { + clpSolver->setInteger(i); + } + if (i < numberColumns) { // semi-continuous - clpSolver->setSpecialOptions(clpSolver->specialOptions() | 8388608); + clpSolver->setSpecialOptions(clpSolver->specialOptions() | + 8388608); int iStart = i; for (i = iStart; i < numberColumns; i++) { - if (clpSolver->integerType(i) > 2) - numberLotSizing++; + if (clpSolver->integerType(i) > 2) + numberLotSizing++; } lotsize = new lotStruct[numberLotSizing]; numberLotSizing = 0; const double *lower = clpSolver->getColLower(); const double *upper = clpSolver->getColUpper(); for (i = iStart; i < numberColumns; i++) { - if (clpSolver->integerType(i) > 2) { - int iType = clpSolver->integerType(i) - 3; - if (!iType) - clpSolver->setContinuous(i); - else - clpSolver->setInteger(i); - lotsize[numberLotSizing].column = i; - lotsize[numberLotSizing].high = upper[i]; - if (lower[i]) { - lotsize[numberLotSizing++].low = lower[i]; - clpSolver->setColLower(i, 0.0); - } else { - lotsize[numberLotSizing++].low = 1.0; - } - } + if (clpSolver->integerType(i) > 2) { + int iType = clpSolver->integerType(i) - 3; + if (!iType) + clpSolver->setContinuous(i); + else + clpSolver->setInteger(i); + lotsize[numberLotSizing].column = i; + lotsize[numberLotSizing].high = upper[i]; + if (lower[i]) { + lotsize[numberLotSizing++].low = lower[i]; + clpSolver->setColLower(i, 0.0); + } else { + lotsize[numberLotSizing++].low = 1.0; + } + } } - } + } #else - lengthName = 0; - goodModel = true; -#endif - time2 = CoinCpuTime(); - totalTime += time2 - time1; - time1 = time2; - // Go to canned file if just input file - if (getCbcOrClpReadMode() == 2 && argc == 2) { + lengthName = 0; + goodModel = true; +#endif + time2 = CoinCpuTime(); + totalTime += time2 - time1; + time1 = time2; + // Go to canned file if just input file + if (inputQueue.empty()) { // only if ends .mps - char *find = const_cast< char * >(strstr(fileName.c_str(), ".mps")); + char *find = + const_cast(strstr(fileName.c_str(), ".mps")); if (find && find[4] == '\0') { - find[1] = 'p'; - find[2] = 'a'; - find[3] = 'r'; - FILE *fp = fopen(fileName.c_str(), "r"); - if (fp) { - setCbcOrClpReadCommand(fp); // Read from that file - setCbcOrClpReadMode(-1); - } + find[1] = 'p'; + find[2] = 'a'; + find[3] = 'r'; + std::ifstream ifs(fileName.c_str()); + if (ifs.is_open()) { + while (!inputQueue.empty()){ + inputQueue.pop_front(); + } + CoinParamUtils::readFromStream(inputQueue, ifs); + } } - } - } else { - // errors - sprintf(generalPrint, "There were %d errors on input", status); - printGeneralMessage(model_, generalPrint); - } + } + } else { + // errors + buffer.str(""); + buffer << "There were " << status << " errors on input"; + printGeneralMessage(model_, buffer.str()); } } break; - case CLP_PARAM_ACTION_MODELIN: -#ifndef CBC_OTHER_SOLVER -#ifdef COIN_HAS_LINK - { - // get next field - field = CoinReadGetString(argc, argv); - if (field == "$") { - field = parameters_[iParam].stringValue(); - } else if (field == "EOL") { - parameters_[iParam].printString(); - break; - } else { - parameters_[iParam].setStringValue(field); + case CbcParam::EXPORT: { + if (!goodModel) { + printGeneralMessage(model_, "** Current model not valid\n"); + continue; } - std::string fileName; - bool canOpen = false; - if (field == "-") { - // stdin - canOpen = true; - fileName = "-"; - } else { - bool absolutePath; - if (dirsep == '/') { - // non Windows (or cygwin) - absolutePath = (field[0] == '/'); - } else { - //Windows (non cycgwin) - absolutePath = (field[0] == '\\'); - // but allow for : - if (strchr(field.c_str(), ':')) - absolutePath = true; - } - if (absolutePath) { - fileName = field; - } else if (field[0] == '~') { - char *environVar = getenv("HOME"); - if (environVar) { - std::string home(environVar); - field = field.erase(0, 1); - fileName = home + field; - } else { - fileName = field; - } - } else { - fileName = directory + field; - } - FILE *fp = fopen(fileName.c_str(), "r"); - if (fp) { - // can open - lets go for it - fclose(fp); - canOpen = true; - } else { - sprintf(generalPrint, "Unable to open file %s", fileName.c_str()); - printGeneralMessage(model_, generalPrint); - } + cbcParam->readValue(inputQueue, fileName, &message); + CoinParamUtils::processFile(fileName, + parameters[CbcParam::DIRECTORY]->dirName()); + if (fileName == ""){ + fileName = parameters[CbcParam::EXPORTFILE]->fileName(); + }else{ + parameters[CbcParam::EXPORTFILE]->setFileName(fileName); } - if (canOpen) { - CoinModel coinModel(fileName.c_str(), 2); - // load from coin model - OsiSolverLink solver1; - OsiSolverInterface *solver2 = solver1.clone(); - model_.assignSolver(solver2, false); - OsiSolverLink *si = dynamic_cast< OsiSolverLink * >(model_.solver()); - assert(si != NULL); - si->setDefaultMeshSize(0.001); - // need some relative granularity - si->setDefaultBound(100.0); - double dextra3 = parameters_[whichParam(CBC_PARAM_DBL_DEXTRA3, parameters_)].doubleValue(); - if (dextra3) - si->setDefaultMeshSize(dextra3); - si->setDefaultBound(100.0); - si->setIntegerPriority(1000); - si->setBiLinearPriority(10000); - CoinModel *model2 = &coinModel; - si->load(*model2); - // redo - solver = model_.solver(); - clpSolver = dynamic_cast< OsiClpSolverInterface * >(solver); - lpSolver = clpSolver->getModelPtr(); - clpSolver->messageHandler()->setLogLevel(0); - testOsiParameters = 0; - complicatedInteger = 2; + // If presolve on then save presolved + bool deleteModel2 = false; + ClpSimplex *model2 = lpSolver; + if (dualize && dualize < 3) { + model2 = + static_cast(model2)->dualOfModel(); + buffer.str(""); + buffer << "Dual of model has " << model2->numberRows() << " rows and " + << model2->numberColumns() << " columns"; + printGeneralMessage(model_, buffer.str()); + model2->setOptimizationDirection(1.0); } - } -#endif -#endif - break; - case CLP_PARAM_ACTION_EXPORT: - if (goodModel) { - // get next field - field = CoinReadGetString(argc, argv); - if (field == "$") { - field = parameters_[iParam].stringValue(); - } else if (field == "EOL") { - parameters_[iParam].printString(); - break; - } else { - parameters_[iParam].setStringValue(field); - } - std::string fileName; - bool canOpen = false; - if (field[0] == '/' || field[0] == '\\') { - fileName = field; - } else if (field[0] == '~') { - char *environVar = getenv("HOME"); - if (environVar) { - std::string home(environVar); - field = field.erase(0, 1); - fileName = home + field; - } else { - fileName = field; - } - } else { - fileName = directory + field; - } - FILE *fp = fopen(fileName.c_str(), "w"); - if (fp) { - // can open - lets go for it - fclose(fp); - canOpen = true; - } else { - sprintf(generalPrint, "Unable to open file %s", fileName.c_str()); - printGeneralMessage(model_, generalPrint); - } - if (canOpen) { - // If presolve on then save presolved - bool deleteModel2 = false; - ClpSimplex *model2 = lpSolver; - if (dualize && dualize < 3) { - model2 = static_cast< ClpSimplexOther * >(model2)->dualOfModel(); - sprintf(generalPrint, "Dual of model has %d rows and %d columns", - model2->numberRows(), model2->numberColumns()); - generalMessageHandler->message(CLP_GENERAL, generalMessages) - << generalPrint - << CoinMessageEol; - model2->setOptimizationDirection(1.0); - } #ifndef CBC_OTHER_SOLVER - if (info.numberSos && doSOS && statusUserFunction_[0]) { - // SOS - numberSOS = info.numberSos; - sosStart = info.sosStart; - sosIndices = info.sosIndices; - sosReference = info.sosReference; - clpSolver->setSOSData(numberSOS, info.sosType, sosStart, sosIndices, sosReference); - } - numberSOS = clpSolver->numberSOS(); - if (numberSOS || lotsize) - preSolve = false; -#endif - if (preSolve) { - ClpPresolve pinfo; - int presolveOptions2 = presolveOptions & ~0x40000000; - if ((presolveOptions2 & 0xffff) != 0) - pinfo.setPresolveActions(presolveOptions2); - if ((printOptions & 1) != 0) - pinfo.statistics(); - double presolveTolerance = parameters_[whichParam(CLP_PARAM_DBL_PRESOLVETOLERANCE, parameters_)].doubleValue(); - model2 = pinfo.presolvedModel(*lpSolver, presolveTolerance, - true, preSolve); - if (model2) { - printf("Saving presolved model on %s\n", - fileName.c_str()); - deleteModel2 = true; - } else { - printf("Presolved model looks infeasible - saving original on %s\n", - fileName.c_str()); - deleteModel2 = false; - model2 = lpSolver; - } - // see if extension lp - bool writeLp = false; - { - int lengthName = strlen(fileName.c_str()); - if (lengthName > 3 && !strcmp(fileName.c_str() + lengthName - 3, ".lp")) - writeLp = true; - } - if (!writeLp) { - model2->writeMps(fileName.c_str(), (outputFormat - 1) / 2, 1 + ((outputFormat - 1) & 1)); - } else { - FILE *fp = fopen(fileName.c_str(), "w"); - assert(fp); - OsiClpSolverInterface solver(model2); - solver.writeLp(fp, 1.0e-12); - fclose(fp); - } - if (deleteModel2) - delete model2; - } else { - printf("Saving model on %s\n", - fileName.c_str()); + if (info && info->numberSos && doSOS && statusUserFunction_[0]) { + // SOS + numberSOS = info->numberSos; + sosStart = info->sosStart; + sosIndices = info->sosIndices; + sosReference = info->sosReference; + clpSolver->setSOSData(numberSOS, info->sosType, sosStart, + sosIndices, sosReference); + } + numberSOS = clpSolver->numberSOS(); + if (numberSOS || lotsize) + preSolve = false; +#endif + if (preSolve) { + ClpPresolve pinfo; + int presolveOptions2 = presolveOptions & ~0x40000000; + if ((presolveOptions2 & 0xffff) != 0) + pinfo.setPresolveActions(presolveOptions2); + if ((printOptions & 1) != 0) + pinfo.statistics(); + double presolveTolerance = + clpParameters[ClpParam::PRESOLVETOLERANCE]->dblVal(); + model2 = pinfo.presolvedModel(*lpSolver, presolveTolerance, + true, preSolve); + if (model2) { + printf("Saving presolved model on %s\n", fileName.c_str()); + deleteModel2 = true; + } else { + printf("Presolved model looks infeasible - saving original " + "on %s\n", + fileName.c_str()); + deleteModel2 = false; + model2 = lpSolver; + } + // see if extension lp + bool writeLp = false; + { + int lengthName = strlen(fileName.c_str()); + if (lengthName > 3 && + !strcmp(fileName.c_str() + lengthName - 3, ".lp")) + writeLp = true; + } + if (!writeLp) { + model2->writeMps(fileName.c_str(), (outputFormat - 1) / 2, + 1 + ((outputFormat - 1) & 1)); + } else { + fp = fopen(fileName.c_str(), "w"); + if (!fp) { + buffer.str(""); + buffer << "Unable to open file " << fileName.c_str(); + printGeneralMessage(model_, buffer.str()); + continue; + } + OsiClpSolverInterface solver(model2); + solver.writeLp(fp, 1.0e-12); + fclose(fp); + } + if (deleteModel2) + delete model2; + } else { + printf("Saving model on %s\n", fileName.c_str()); #ifdef COIN_HAS_LINK - OsiSolverLink *linkSolver = dynamic_cast< OsiSolverLink * >(clpSolver); - if (!linkSolver || !linkSolver->quadraticModel()) { + OsiSolverLink *linkSolver = + dynamic_cast(clpSolver); + if (!linkSolver || !linkSolver->quadraticModel()) { #endif - // Convert names - int iRow; - int numberRows = model2->numberRows(); - int iColumn; - int numberColumns = model2->numberColumns(); - - char **rowNames = NULL; - char **columnNames = NULL; - if (model2->lengthNames()) { - rowNames = new char *[numberRows]; - for (iRow = 0; iRow < numberRows; iRow++) { - rowNames[iRow] = CoinStrdup(model2->rowName(iRow).c_str()); - } - - columnNames = new char *[numberColumns]; - for (iColumn = 0; iColumn < numberColumns; iColumn++) { - columnNames[iColumn] = CoinStrdup(model2->columnName(iColumn).c_str()); - } - } - // see if extension lp - bool writeLp = false; - { - int lengthName = strlen(fileName.c_str()); - if (lengthName > 3 && !strcmp(fileName.c_str() + lengthName - 3, ".lp")) + // Convert names + int iRow; + int numberRows = model2->numberRows(); + int iColumn; + int numberColumns = model2->numberColumns(); + + char **rowNames = NULL; + char **columnNames = NULL; + if (model2->lengthNames()) { + rowNames = new char *[numberRows]; + for (iRow = 0; iRow < numberRows; iRow++) { + rowNames[iRow] = + CoinStrdup(model2->rowName(iRow).c_str()); + } + + columnNames = new char *[numberColumns]; + for (iColumn = 0; iColumn < numberColumns; iColumn++) { + columnNames[iColumn] = + CoinStrdup(model2->columnName(iColumn).c_str()); + } + } + // see if extension lp + bool writeLp = false; + { + int lengthName = strlen(fileName.c_str()); + if (lengthName > 3 && + !strcmp(fileName.c_str() + lengthName - 3, ".lp")) writeLp = true; - } - if (lotsize) { - for (int i = 0; i < numberLotSizing; i++) { + } + if (lotsize) { + for (int i = 0; i < numberLotSizing; i++) { int iColumn = lotsize[i].column; double low = lotsize[i].low; if (low != 1.0) - clpSolver->setColLower(iColumn, low); + clpSolver->setColLower(iColumn, low); int type; if (clpSolver->isInteger(iColumn)) - type = 4; + type = 4; else - type = 3; + type = 3; clpSolver->setColumnType(iColumn, type); - } - } - if (!writeLp) { - remove(fileName.c_str()); - //model_.addSOSEtcToSolver(); - clpSolver->writeMpsNative(fileName.c_str(), const_cast< const char ** >(rowNames), const_cast< const char ** >(columnNames), - (outputFormat - 1) / 2, 1 + ((outputFormat - 1) & 1)); - } else { - FILE *fp = fopen(fileName.c_str(), "w"); - assert(fp); - clpSolver->writeLp(fp, 1.0e-12); - } - if (rowNames) { - for (iRow = 0; iRow < numberRows; iRow++) { + } + } + if (!writeLp) { + remove(fileName.c_str()); + // model_.addSOSEtcToSolver(); + clpSolver->writeMpsNative( + fileName.c_str(), const_cast(rowNames), + const_cast(columnNames), + (outputFormat - 1) / 2, 1 + ((outputFormat - 1) & 1)); + } else { + fp = fopen(fileName.c_str(), "w"); + if (!fp) { + buffer.str(""); + buffer << "Unable to open file " << fileName.c_str(); + printGeneralMessage(model_, buffer.str()); + continue; + } + clpSolver->writeLp(fp, 1.0e-12); + } + if (rowNames) { + for (iRow = 0; iRow < numberRows; iRow++) { free(rowNames[iRow]); - } - delete[] rowNames; - for (iColumn = 0; iColumn < numberColumns; iColumn++) { + } + delete[] rowNames; + for (iColumn = 0; iColumn < numberColumns; iColumn++) { free(columnNames[iColumn]); - } - delete[] columnNames; - } - if (lotsize) { - for (int i = 0; i < numberLotSizing; i++) { + } + delete[] columnNames; + } + if (lotsize) { + for (int i = 0; i < numberLotSizing; i++) { int iColumn = lotsize[i].column; int itype = clpSolver->integerType(iColumn); clpSolver->setColLower(iColumn, 0.0); if (itype == 3) - clpSolver->setContinuous(iColumn); + clpSolver->setContinuous(iColumn); else - clpSolver->setInteger(iColumn); - } - } -#ifdef COIN_HAS_LINK - } else { - linkSolver->quadraticModel()->writeMps(fileName.c_str(), (outputFormat - 1) / 2, 1 + ((outputFormat - 1) & 1)); + clpSolver->setInteger(iColumn); + } } +#ifdef COIN_HAS_LINK + } else { + linkSolver->quadraticModel()->writeMps( + fileName.c_str(), (outputFormat - 1) / 2, + 1 + ((outputFormat - 1) & 1)); + } #endif - } - time2 = CoinCpuTime(); - totalTime += time2 - time1; - time1 = time2; - } - } else { - sprintf(generalPrint, "** Current model not valid"); - printGeneralMessage(model_, generalPrint); } - break; - case CLP_PARAM_ACTION_BASISIN: - if (goodModel) { - // get next field - field = CoinReadGetString(argc, argv); - if (field == "$") { - field = parameters_[iParam].stringValue(); - } else if (field == "EOL") { - parameters_[iParam].printString(); - break; - } else { - parameters_[iParam].setStringValue(field); - } - std::string fileName; - bool canOpen = false; - if (field == "-") { - // stdin - canOpen = true; - fileName = "-"; - } else { - if (field[0] == '/' || field[0] == '\\') { - fileName = field; - } else if (field[0] == '~') { - char *environVar = getenv("HOME"); - if (environVar) { - std::string home(environVar); - field = field.erase(0, 1); - fileName = home + field; - } else { - fileName = field; - } - } else { - fileName = directory + field; - } - FILE *fp = fopen(fileName.c_str(), "r"); - if (fp) { - // can open - lets go for it - fclose(fp); - canOpen = true; - } else { - sprintf(generalPrint, "Unable to open file %s", fileName.c_str()); - printGeneralMessage(model_, generalPrint); - } - } - if (canOpen) { -#ifndef CBC_OTHER_SOLVER - int values = lpSolver->readBasis(fileName.c_str()); - if (values == 0) - basisHasValues = -1; - else - basisHasValues = 1; - assert(lpSolver == clpSolver->getModelPtr()); - clpSolver->setWarmStart(NULL); -#endif - } - } else { - sprintf(generalPrint, "** Current model not valid"); - printGeneralMessage(model_, generalPrint); + time2 = CoinCpuTime(); + totalTime += time2 - time1; + time1 = time2; + } break; + case CbcParam::READPRIORITIES:{ + if (!goodModel){ + printGeneralMessage(model_, "** Current model not valid\n"); + continue; } - break; - case CBC_PARAM_ACTION_PRIORITYIN: - if (goodModel) { - // get next field - field = CoinReadGetString(argc, argv); - if (field == "$") { - field = parameters_[iParam].stringValue(); - } else if (field == "EOL") { - parameters_[iParam].printString(); - break; - } else { - parameters_[iParam].setStringValue(field); - } - std::string fileName; - if (field[0] == '/' || field[0] == '\\') { - fileName = field; - } else if (field[0] == '~') { - char *environVar = getenv("HOME"); - if (environVar) { - std::string home(environVar); - field = field.erase(0, 1); - fileName = home + field; - } else { - fileName = field; - } - } else { - fileName = directory + field; - } - FILE *fp = fopen(fileName.c_str(), "r"); - if (fp) { - // can open - lets go for it - std::string headings[] = { "name", "number", "direction", "priority", "up", "down", - "solution", "priin" }; - int got[] = { -1, -1, -1, -1, -1, -1, -1, -1 }; - int order[8]; - bool useMasks = false; - if (strstr(fileName.c_str(), "mask_")) { - // look more closely - const char *name = fileName.c_str(); - int length = strlen(name); - for (int i = length - 1; i >= 0; i--) { - if (name[i] == dirsep) { - name += i + 1; - break; - } - } - useMasks = !strncmp(name, "mask_", 5); - } - assert(sizeof(got) == sizeof(order)); - int nAcross = 0; - char line[1000]; - int numberColumns = lpSolver->numberColumns(); - if (!fgets(line, 1000, fp)) { - std::cout << "Odd file " << fileName << std::endl; - } else { - char *pos = line; - char *put = line; - while (*pos >= ' ' && *pos != '\n') { - if (*pos != ' ' && *pos != '\t') { - *put = static_cast< char >(tolower(*pos)); - put++; - } - pos++; - } - *put = '\0'; - pos = line; - int i; - bool good = true; - while (pos) { - char *comma = strchr(pos, ','); - if (comma) - *comma = '\0'; - for (i = 0; i < static_cast< int >(sizeof(got) / sizeof(int)); i++) { - if (headings[i] == pos) { + cbcParam->readValue(inputQueue, fileName, &message); + CoinParamUtils::processFile(fileName, + parameters[CbcParam::DIRECTORY]->dirName(), + &canOpen); + if (!canOpen) { + buffer.str(""); + buffer << "Unable to open file " << fileName.c_str(); + printGeneralMessage(model_, buffer.str()); + continue; + } + if (fileName == ""){ + fileName = parameters[CbcParam::PRIORITYFILE]->fileName(); + }else{ + parameters[CbcParam::PRIORITYFILE]->setFileName(fileName); + } + fp = fopen(fileName.c_str(), "r"); + std::string headings[] = {"name", "number", "direction", + "priority", "up", "down", + "solution", "priin"}; + int got[] = {-1, -1, -1, -1, -1, -1, -1, -1}; + int order[8]; + bool useMasks = false; + if (strstr(fileName.c_str(), "mask_")) { + // look more closely + const char *name = fileName.c_str(); + int length = strlen(name); + for (int i = length - 1; i >= 0; i--) { + if (name[i] == dirsep) { + name += i + 1; + break; + } + } + useMasks = !strncmp(name, "mask_", 5); + } + assert(sizeof(got) == sizeof(order)); + int nAcross = 0; + char line[1000]; + int numberColumns = lpSolver->numberColumns(); + if (!fgets(line, 1000, fp)) { + std::cout << "Odd file " << fileName << std::endl; + } else { + char *pos = line; + char *put = line; + while (*pos >= ' ' && *pos != '\n') { + if (*pos != ' ' && *pos != '\t') { + *put = static_cast(tolower(*pos)); + put++; + } + pos++; + } + *put = '\0'; + pos = line; + int i; + bool good = true; + while (pos) { + char *comma = strchr(pos, ','); + if (comma) + *comma = '\0'; + for (i = 0; i < static_cast(sizeof(got) / sizeof(int)); + i++) { + if (headings[i] == pos) { if (got[i] < 0) { - order[nAcross] = i; - got[i] = nAcross++; + order[nAcross] = i; + got[i] = nAcross++; } else { - // duplicate - good = false; + // duplicate + good = false; } break; - } - } - if (i == static_cast< int >(sizeof(got) / sizeof(int))) - good = false; - if (comma) { - *comma = ','; - pos = comma + 1; - } else { - break; - } + } } - if (got[0] < 0 && got[1] < 0) - good = false; - if (got[0] >= 0 && got[1] >= 0) - good = false; - if (got[0] >= 0 && !lpSolver->lengthNames()) - good = false; - int numberFields = 99; - if (good && (strstr(fileName.c_str(), ".mst") || strstr(fileName.c_str(), ".MST") || strstr(fileName.c_str(), ".csv"))) { - numberFields = 0; - for (i = 2; i < static_cast< int >(sizeof(got) / sizeof(int)); i++) { - if (got[i] >= 0) + if (i == static_cast(sizeof(got) / sizeof(int))) + good = false; + if (comma) { + *comma = ','; + pos = comma + 1; + } else { + break; + } + } + if (got[0] < 0 && got[1] < 0) + good = false; + if (got[0] >= 0 && got[1] >= 0) + good = false; + if (got[0] >= 0 && !lpSolver->lengthNames()) + good = false; + int numberFields = 99; + if (good && (strstr(fileName.c_str(), ".mst") || + strstr(fileName.c_str(), ".MST") || + strstr(fileName.c_str(), ".csv"))) { + numberFields = 0; + for (i = 2; i < static_cast(sizeof(got) / sizeof(int)); + i++) { + if (got[i] >= 0) numberFields++; - } - if (!numberFields) { - // Like Cplex format - order[nAcross] = 6; - got[6] = nAcross++; - } - } - if (good) { - char **columnNames = new char *[numberColumns]; - //pseudoDown = NULL; - //pseudoUp = NULL; - //branchDirection = NULL; - //if (got[5]!=-1) - pseudoDown = reinterpret_cast< double * >(malloc(numberColumns * sizeof(double))); - //if (got[4]!=-1) - pseudoUp = reinterpret_cast< double * >(malloc(numberColumns * sizeof(double))); - //if (got[2]!=-1) - branchDirection = reinterpret_cast< int * >(malloc(numberColumns * sizeof(int))); - priorities = reinterpret_cast< int * >(malloc(numberColumns * sizeof(int))); - free(solutionIn); - solutionIn = NULL; - free(prioritiesIn); - prioritiesIn = NULL; - int iColumn; - if (got[6] >= 0) { - solutionIn = reinterpret_cast< double * >(malloc(numberColumns * sizeof(double))); - for (iColumn = 0; iColumn < numberColumns; iColumn++) + } + if (!numberFields) { + // Like Cplex format + order[nAcross] = 6; + got[6] = nAcross++; + } + } + if (good) { + char **columnNames = new char *[numberColumns]; + // pseudoDown = NULL; + // pseudoUp = NULL; + // branchDirection = NULL; + // if (got[5]!=-1) + pseudoDown = reinterpret_cast( + malloc(numberColumns * sizeof(double))); + // if (got[4]!=-1) + pseudoUp = reinterpret_cast( + malloc(numberColumns * sizeof(double))); + // if (got[2]!=-1) + branchDirection = reinterpret_cast( + malloc(numberColumns * sizeof(int))); + priorities = reinterpret_cast( + malloc(numberColumns * sizeof(int))); + free(solutionIn); + solutionIn = NULL; + free(prioritiesIn); + prioritiesIn = NULL; + int iColumn; + if (got[6] >= 0) { + solutionIn = reinterpret_cast( + malloc(numberColumns * sizeof(double))); + for (iColumn = 0; iColumn < numberColumns; iColumn++) solutionIn[iColumn] = -COIN_DBL_MAX; - } - if (got[7] >= 0 || !numberFields) { - prioritiesIn = reinterpret_cast< int * >(malloc(numberColumns * sizeof(int))); - for (iColumn = 0; iColumn < numberColumns; iColumn++) + } + if (got[7] >= 0 || !numberFields) { + prioritiesIn = reinterpret_cast( + malloc(numberColumns * sizeof(int))); + for (iColumn = 0; iColumn < numberColumns; iColumn++) prioritiesIn[iColumn] = 10000; - } - for (iColumn = 0; iColumn < numberColumns; iColumn++) { - columnNames[iColumn] = CoinStrdup(lpSolver->columnName(iColumn).c_str()); - //if (got[5]!=-1) - pseudoDown[iColumn] = 0.0; - //if (got[4]!=-1) - pseudoUp[iColumn] = 0.0; - //if (got[2]!=-1) - branchDirection[iColumn] = 0; - priorities[iColumn] = useMasks ? -123456789 : 0; - } - int nBadPseudo = 0; - int nBadDir = 0; - int nBadPri = 0; - int nBadName = 0; - int nBadLine = 0; - int nLine = 0; - iColumn = -1; - int lowestPriority = -COIN_INT_MAX; - bool needCard = true; - while (!needCard || fgets(line, 1000, fp)) { - if (!strncmp(line, "ENDATA", 6) || !strncmp(line, "endata", 6)) + } + for (iColumn = 0; iColumn < numberColumns; iColumn++) { + columnNames[iColumn] = + CoinStrdup(lpSolver->columnName(iColumn).c_str()); + // if (got[5]!=-1) + pseudoDown[iColumn] = 0.0; + // if (got[4]!=-1) + pseudoUp[iColumn] = 0.0; + // if (got[2]!=-1) + branchDirection[iColumn] = 0; + priorities[iColumn] = useMasks ? -123456789 : 0; + } + int nBadPseudo = 0; + int nBadDir = 0; + int nBadPri = 0; + int nBadName = 0; + int nBadLine = 0; + int nLine = 0; + iColumn = -1; + int lowestPriority = -COIN_INT_MAX; + bool needCard = true; + while (!needCard || fgets(line, 1000, fp)) { + if (!strncmp(line, "ENDATA", 6) || + !strncmp(line, "endata", 6)) break; - nLine++; - if (!useMasks) + nLine++; + if (!useMasks) iColumn = -1; - else + else needCard = false; - double up = 0.0; - double down = 0.0; - int pri = 0; - int dir = 0; - double solValue = COIN_DBL_MAX; - int priValue = 1000000; - char *pos = line; - char *put = line; - if (!numberFields) { + double up = 0.0; + double down = 0.0; + int pri = 0; + int dir = 0; + double solValue = COIN_DBL_MAX; + int priValue = 1000000; + char *pos = line; + char *put = line; + if (!numberFields) { // put in , for (i = 4; i < 100; i++) { - if (line[i] == ' ' || line[i] == '\t') { - line[i] = ','; - break; - } + if (line[i] == ' ' || line[i] == '\t') { + line[i] = ','; + break; + } } - } - while (*pos >= ' ' && *pos != '\n') { + } + while (*pos >= ' ' && *pos != '\n') { if (*pos != ' ' && *pos != '\t') { - *put = *pos; - put++; + *put = *pos; + put++; } pos++; - } - *put = '\0'; - pos = line; - for (int i = 0; i < nAcross; i++) { + } + *put = '\0'; + pos = line; + for (int i = 0; i < nAcross; i++) { char *comma = strchr(pos, ','); if (comma) { - *comma = '\0'; + *comma = '\0'; } else if (i < nAcross - 1) { - nBadLine++; - break; + nBadLine++; + break; } switch (order[i]) { - // name - case 0: - iColumn++; - for (; iColumn < numberColumns; iColumn++) { - if (priorities[iColumn] != -123456789) { - if (!strcmp(columnNames[iColumn], pos)) - break; - } else { - // mask (at present ? and trailing *) - const char *name = columnNames[iColumn]; - int length = strlen(name); - int lengthMask = strlen(pos); - bool asterisk = pos[lengthMask - 1] == '*'; - if (asterisk) - length = lengthMask - 1; - int i; - for (i = 0; i < length; i++) { - if (name[i] != pos[i]) { - if (pos[i] != '?') + // name + case 0: + iColumn++; + for (; iColumn < numberColumns; iColumn++) { + if (priorities[iColumn] != -123456789) { + if (!strcmp(columnNames[iColumn], pos)) + break; + } else { + // mask (at present ? and trailing *) + const char *name = columnNames[iColumn]; + int length = strlen(name); + int lengthMask = strlen(pos); + bool asterisk = pos[lengthMask - 1] == '*'; + if (asterisk) + length = lengthMask - 1; + int i; + for (i = 0; i < length; i++) { + if (name[i] != pos[i]) { + if (pos[i] != '?') + break; + } + } + if (i == length) break; - } } - if (i == length) - break; - } - } - if (iColumn == numberColumns) { - iColumn = -1; - needCard = true; - } - break; - // number - case 1: - iColumn = atoi(pos); - if (iColumn < 0 || iColumn >= numberColumns) - iColumn = -1; - break; - // direction - case 2: - if (*pos == 'D') - dir = -1; - else if (*pos == 'U') - dir = 1; - else if (*pos == 'N') - dir = 0; - else if (*pos == '1' && *(pos + 1) == '\0') - dir = 1; - else if (*pos == '0' && *(pos + 1) == '\0') - dir = 0; - else if (*pos == '1' && *(pos + 1) == '1' && *(pos + 2) == '\0') - dir = -1; - else - dir = -2; // bad - break; - // priority - case 3: - pri = atoi(pos); - lowestPriority = CoinMax(lowestPriority, pri); - break; - // up - case 4: - up = atof(pos); - break; - // down - case 5: - down = atof(pos); - break; - // sol value - case 6: - solValue = atof(pos); - break; - // priority in value - case 7: - priValue = atoi(pos); - break; + } + if (iColumn == numberColumns) { + iColumn = -1; + needCard = true; + } + break; + // number + case 1: + iColumn = atoi(pos); + if (iColumn < 0 || iColumn >= numberColumns) + iColumn = -1; + break; + // direction + case 2: + if (*pos == 'D') + dir = -1; + else if (*pos == 'U') + dir = 1; + else if (*pos == 'N') + dir = 0; + else if (*pos == '1' && *(pos + 1) == '\0') + dir = 1; + else if (*pos == '0' && *(pos + 1) == '\0') + dir = 0; + else if (*pos == '1' && *(pos + 1) == '1' && + *(pos + 2) == '\0') + dir = -1; + else + dir = -2; // bad + break; + // priority + case 3: + pri = atoi(pos); + lowestPriority = CoinMax(lowestPriority, pri); + break; + // up + case 4: + up = atof(pos); + break; + // down + case 5: + down = atof(pos); + break; + // sol value + case 6: + solValue = atof(pos); + break; + // priority in value + case 7: + priValue = atoi(pos); + break; } if (comma) { - *comma = ','; - pos = comma + 1; + *comma = ','; + pos = comma + 1; } - } - if (iColumn >= 0) { + } + if (iColumn >= 0) { if (down < 0.0) { - nBadPseudo++; - down = 0.0; + nBadPseudo++; + down = 0.0; } if (up < 0.0) { - nBadPseudo++; - up = 0.0; + nBadPseudo++; + up = 0.0; } if (!up) - up = down; + up = down; if (!down) - down = up; + down = up; if (dir < -1 || dir > 1) { - nBadDir++; - dir = 0; + nBadDir++; + dir = 0; } if (pri < 0) { - nBadPri++; - pri = 0; + nBadPri++; + pri = 0; } - //if (got[5]!=-1) + // if (got[5]!=-1) pseudoDown[iColumn] = down; - //if (got[4]!=-1) + // if (got[4]!=-1) pseudoUp[iColumn] = up; - //if (got[2]!=-1) + // if (got[2]!=-1) branchDirection[iColumn] = dir; priorities[iColumn] = pri; if (solValue != COIN_DBL_MAX) { @@ -9451,565 +9836,328 @@ int CbcMain1(int argc, const char *argv[], nBadName++; } } - for (iColumn = 0; iColumn < numberColumns; iColumn++) { - if (priorities[iColumn] == -123456789) + for (iColumn = 0; iColumn < numberColumns; iColumn++) { + if (priorities[iColumn] == -123456789) priorities[iColumn] = lowestPriority + 1; - } - if (!noPrinting_) { - printf("%d fields and %d records", nAcross, nLine); - if (nBadPseudo) + } + if (!parameters.noPrinting()) { + printf("%d fields and %d records", nAcross, nLine); + if (nBadPseudo) printf(" %d bad pseudo costs", nBadPseudo); - if (nBadDir) + if (nBadDir) printf(" %d bad directions", nBadDir); - if (nBadPri) + if (nBadPri) printf(" %d bad priorities", nBadPri); - if (nBadName) - printf(" ** %d records did not match on name/sequence", nBadName); - printf("\n"); - } - for (iColumn = 0; iColumn < numberColumns; iColumn++) { - free(columnNames[iColumn]); - } - delete[] columnNames; - } else { - std::cout << "Duplicate or unknown keyword - or name/number fields wrong" << line << std::endl; + if (nBadName) + printf(" ** %d records did not match on name/sequence", + nBadName); + printf("\n"); } - } - fclose(fp); - } else { - sprintf(generalPrint, "Unable to open file %s", fileName.c_str()); - printGeneralMessage(model_, generalPrint); - } - } else { - sprintf(generalPrint, "** Current model not valid"); - printGeneralMessage(model_, generalPrint); + for (iColumn = 0; iColumn < numberColumns; iColumn++) { + free(columnNames[iColumn]); + } + delete[] columnNames; + } else { + std::cout << "Duplicate or unknown keyword - or " + "name/number fields wrong" + << line << std::endl; + } } - break; - case CBC_PARAM_ACTION_MIPSTART: - if (goodModel) { - // get next field - field = CoinReadGetString(argc, argv); - mipStartFile = field; - if (field == "$") { - field = parameters_[iParam].stringValue(); - } else if (field == "EOL") { - parameters_[iParam].printString(); - break; - } else { - parameters_[iParam].setStringValue(field); - } - std::string fileName; - if (field[0] == '/' || field[0] == '\\') { - fileName = field; - } else if (field[0] == '~') { - char *environVar = getenv("HOME"); - if (environVar) { - std::string home(environVar); - field = field.erase(0, 1); - fileName = home + field; - } else { - fileName = field; - } - } else { - fileName = directory + field; - } - sprintf(generalPrint, "opening mipstart file %s.", fileName.c_str()); - generalMessageHandler->message(CLP_GENERAL, generalMessages) << generalPrint << CoinMessageEol; - double msObj; - - CbcMipStartIO::read(model_.solver(), fileName.c_str(), mipStart, msObj, model_.messageHandler(), model_.messagesPointer()); - // copy to before preprocess if has .before. - if (strstr(fileName.c_str(), ".before.")) { - mipStartBefore = mipStart; - sprintf(generalPrint, "file %s will be used before preprocessing.", fileName.c_str()); - generalMessageHandler->message(CLP_GENERAL, generalMessages) - << generalPrint - << CoinMessageEol; - } - } else { - sprintf(generalPrint, "** Current model not valid"); - printGeneralMessage(model_, generalPrint); + fclose(fp); + } break; + case CbcParam::READMIPSTART: + case CbcParam::READSOL: { + if (!goodModel){ + printGeneralWarning(model_, "** Current model not valid\n"); + continue; } - break; - case CLP_PARAM_ACTION_DEBUG: - if (goodModel) { - delete[] debugValues; - debugValues = NULL; - // get next field - field = CoinReadGetString(argc, argv); - if (field == "$") { - field = parameters_[iParam].stringValue(); - } else if (field == "EOL") { - parameters_[iParam].printString(); - break; - } else { - parameters_[iParam].setStringValue(field); - debugFile = field; - if (debugFile == "create" || debugFile == "createAfterPre") { - printf("Will create a debug file so this run should be a good one\n"); - break; - } else if (debugFile == "unitTest") { - printf("debug will be done using file name of model\n"); - break; - } - } - std::string fileName; - if (field[0] == '/' || field[0] == '\\') { - fileName = field; - } else if (field[0] == '~') { - char *environVar = getenv("HOME"); - if (environVar) { - std::string home(environVar); - field = field.erase(0, 1); - fileName = home + field; - } else { - fileName = field; - } - } else { - fileName = directory + field; - } - FILE *fp = fopen(fileName.c_str(), "rb"); - if (fp) { - // can open - lets go for it - int numRows; - double obj; - size_t nRead; - nRead = fread(&numRows, sizeof(int), 1, fp); - if (nRead != 1) - throw("Error in fread"); - nRead = fread(&numberDebugValues, sizeof(int), 1, fp); - if (nRead != 1) - throw("Error in fread"); - nRead = fread(&obj, sizeof(double), 1, fp); - if (nRead != 1) - throw("Error in fread"); - debugValues = new double[numberDebugValues + numRows]; - nRead = fread(debugValues, sizeof(double), numRows, fp); - if (nRead != static_cast< size_t >(numRows)) - throw("Error in fread"); - nRead = fread(debugValues, sizeof(double), numRows, fp); - if (nRead != static_cast< size_t >(numRows)) - throw("Error in fread"); - nRead = fread(debugValues, sizeof(double), numberDebugValues, fp); - if (nRead != static_cast< size_t >(numberDebugValues)) - throw("Error in fread"); - printf("%d doubles read into debugValues\n", numberDebugValues); -#if DEBUG_PREPROCESS > 1 - debugSolution = debugValues; - debugNumberColumns = numberDebugValues; -#endif - if (numberDebugValues < 200) { - for (int i = 0; i < numberDebugValues; i++) { - if (clpSolver->isInteger(i) && debugValues[i]) - printf("%d %g\n", i, debugValues[i]); - } - } - fclose(fp); - } else { - sprintf(generalPrint, "Unable to open file %s", fileName.c_str()); - printGeneralMessage(model_, generalPrint); - } + cbcParam->readValue(inputQueue, fileName, &message); + CoinParamUtils::processFile(fileName, + parameters[CbcParam::DIRECTORY]->dirName(), + &canOpen); + if (fileName == ""){ + fileName = parameters[CbcParam::MIPSTARTFILE]->fileName(); + }else{ + parameters[CbcParam::MIPSTARTFILE]->setFileName(fileName); + } + mipStartFile = fileName; + buffer.str(""); + if (canOpen){ + buffer << "opening mipstart file " << fileName.c_str(); + printGeneralMessage(model_, buffer.str()); } else { - sprintf(generalPrint, "** Current model not valid"); - printGeneralMessage(model_, generalPrint); + buffer << "Unable to open file " << fileName.c_str(); + printGeneralMessage(model_, buffer.str()); + continue; + } + double msObj; + + CbcMipStartIO::read(model_.solver(), fileName.c_str(), mipStart, + msObj, model_.messageHandler(), + model_.messagesPointer()); + // copy to before preprocess if has .before. + if (strstr(fileName.c_str(), ".before.")) { + mipStartBefore = mipStart; + buffer.str(""); + buffer << "file " << fileName.c_str() << " will be used before preprocessing."; + printGeneralMessage(model_, buffer.str()); } - break; - case CLP_PARAM_ACTION_PRINTMASK: - // get next field - { - std::string name = CoinReadGetString(argc, argv); - if (name != "EOL") { - parameters_[iParam].setStringValue(name); - printMask = name; - } else { - parameters_[iParam].printString(); - } + } break; + case CbcParam::DEBUG:{ + if (!goodModel){ + printGeneralWarning(model_, "** Current model not valid\n"); + continue; } - break; - case CLP_PARAM_ACTION_BASISOUT: - if (goodModel) { - // get next field - field = CoinReadGetString(argc, argv); - if (field == "$") { - field = parameters_[iParam].stringValue(); - } else if (field == "EOL") { - parameters_[iParam].printString(); - break; - } else { - parameters_[iParam].setStringValue(field); - } - std::string fileName; - bool canOpen = false; - if (field[0] == '/' || field[0] == '\\') { - fileName = field; - } else if (field[0] == '~') { - char *environVar = getenv("HOME"); - if (environVar) { - std::string home(environVar); - field = field.erase(0, 1); - fileName = home + field; - } else { - fileName = field; - } - } else { - fileName = directory + field; - } - FILE *fp = fopen(fileName.c_str(), "w"); - if (fp) { - // can open - lets go for it - fclose(fp); - canOpen = true; - } else { - sprintf(generalPrint, "Unable to open file %s", fileName.c_str()); - printGeneralMessage(model_, generalPrint); - } - if (canOpen) { - ClpSimplex *model2 = lpSolver; - model2->writeBasis(fileName.c_str(), outputFormat > 1, outputFormat - 2); - time2 = CoinCpuTime(); - totalTime += time2 - time1; - time1 = time2; - } - } else { - sprintf(generalPrint, "** Current model not valid"); - printGeneralMessage(model_, generalPrint); + delete[] debugValues; + debugValues = NULL; + cbcParam->readValue(inputQueue, fileName, &message); + if (fileName == "create" || fileName == "createAfterPre") { + parameters[CbcParam::DEBUGFILE]->setFileName(fileName); + printGeneralMessage(model_, "Will create a debug file so " + "this run should be a good one"); + break; + } else if (fileName == "unitTest") { + printGeneralMessage(model_, "debug will be done using file " + "name of model"); + parameters[CbcParam::DEBUGFILE]->setFileName(fileName); + break; } - break; - case CLP_PARAM_ACTION_SAVE: { - // get next field - field = CoinReadGetString(argc, argv); - if (field == "$") { - field = parameters_[iParam].stringValue(); - } else if (field == "EOL") { - parameters_[iParam].printString(); - break; - } else { - parameters_[iParam].setStringValue(field); + CoinParamUtils::processFile(fileName, + parameters[CbcParam::DIRECTORY]->dirName(), + &canOpen); + if (!canOpen){ + buffer.str(""); + buffer << "Unable to open file " << fileName.c_str(); + printGeneralMessage(model_, buffer.str()); + continue; } - std::string fileName; - bool canOpen = false; - if (field[0] == '/' || field[0] == '\\') { - fileName = field; - } else if (field[0] == '~') { - char *environVar = getenv("HOME"); - if (environVar) { - std::string home(environVar); - field = field.erase(0, 1); - fileName = home + field; - } else { - fileName = field; - } - } else { - fileName = directory + field; + if (fileName == ""){ + fileName = parameters[CbcParam::DEBUGFILE]->fileName(); + }else{ + parameters[CbcParam::DEBUGFILE]->setFileName(fileName); } - FILE *fp = fopen(fileName.c_str(), "wb"); - if (fp) { - // can open - lets go for it - fclose(fp); - canOpen = true; - } else { - sprintf(generalPrint, "Unable to open file %s", fileName.c_str()); - printGeneralMessage(model_, generalPrint); + fp = fopen(fileName.c_str(), "rb"); + // can open - lets go for it + int numRows; + double obj; + size_t nRead; + nRead = fread(&numRows, sizeof(int), 1, fp); + if (nRead != 1) + throw("Error in fread"); + nRead = fread(&numberDebugValues, sizeof(int), 1, fp); + if (nRead != 1) + throw("Error in fread"); + nRead = fread(&obj, sizeof(double), 1, fp); + if (nRead != 1) + throw("Error in fread"); + debugValues = new double[numberDebugValues + numRows]; + nRead = fread(debugValues, sizeof(double), numRows, fp); + if (nRead != static_cast(numRows)) + throw("Error in fread"); + nRead = fread(debugValues, sizeof(double), numRows, fp); + if (nRead != static_cast(numRows)) + throw("Error in fread"); + nRead = + fread(debugValues, sizeof(double), numberDebugValues, fp); + if (nRead != static_cast(numberDebugValues)) + throw("Error in fread"); + printf("%d doubles read into debugValues\n", numberDebugValues); +#if DEBUG_PREPROCESS > 1 + debugSolution = debugValues; + debugNumberColumns = numberDebugValues; +#endif + if (numberDebugValues < 200) { + for (int i = 0; i < numberDebugValues; i++) { + if (clpSolver->isInteger(i) && debugValues[i]) + printf("%d %g\n", i, debugValues[i]); + } } - if (canOpen) { - int status; - // If presolve on then save presolved - bool deleteModel2 = false; - ClpSimplex *model2 = lpSolver; - if (preSolve) { - ClpPresolve pinfo; - double presolveTolerance = parameters_[whichParam(CLP_PARAM_DBL_PRESOLVETOLERANCE, parameters_)].doubleValue(); - model2 = pinfo.presolvedModel(*lpSolver, presolveTolerance, - false, preSolve); - if (model2) { + } break; + case CbcParam::PRINTMASK: + if (status = cbcParam->readValue(inputQueue, field, &message)){ + printGeneralMessage(model_, message); + continue; + } + if (cbcParam->setVal(field, &message)){ + printGeneralMessage(model_, message); + continue; + } + break; + + case CbcParam::WRITEMODEL:{ + cbcParam->readValue(inputQueue, fileName, &message); + CoinParamUtils::processFile(fileName, + parameters[CbcParam::DIRECTORY]->dirName()); + if (fileName == ""){ + fileName = parameters[CbcParam::MODELFILE]->fileName(); + }else{ + parameters[CbcParam::MODELFILE]->setFileName(fileName); + } + int status; + // If presolve on then save presolved + bool deleteModel2 = false; + ClpSimplex *model2 = lpSolver; + if (preSolve) { + ClpPresolve pinfo; + double presolveTolerance = + parameters[ClpParam::PRESOLVETOLERANCE]->dblVal(); + model2 = pinfo.presolvedModel(*lpSolver, presolveTolerance, + false, preSolve); + if (model2) { printf("Saving presolved model on %s\n", - fileName.c_str()); + fileName.c_str()); deleteModel2 = true; - } else { + } else { printf("Presolved model looks infeasible - saving original on %s\n", - fileName.c_str()); + fileName.c_str()); deleteModel2 = false; model2 = lpSolver; - } - } else { - printf("Saving model on %s\n", - fileName.c_str()); - } - status = model2->saveModel(fileName.c_str()); - if (deleteModel2) - delete model2; - if (!status) { - goodModel = true; - time2 = CoinCpuTime(); - totalTime += time2 - time1; - time1 = time2; - } else { - // errors - sprintf(generalPrint, "There were errors on output"); - printGeneralMessage(model_, generalPrint); - } - } - } break; - case CLP_PARAM_ACTION_RESTORE: { - // get next field - field = CoinReadGetString(argc, argv); - if (field == "$") { - field = parameters_[iParam].stringValue(); - } else if (field == "EOL") { - parameters_[iParam].printString(); - break; - } else { - parameters_[iParam].setStringValue(field); - } - std::string fileName; - bool canOpen = false; - if (field[0] == '/' || field[0] == '\\') { - fileName = field; - } else if (field[0] == '~') { - char *environVar = getenv("HOME"); - if (environVar) { - std::string home(environVar); - field = field.erase(0, 1); - fileName = home + field; - } else { - fileName = field; - } - } else { - fileName = directory + field; - } - FILE *fp = fopen(fileName.c_str(), "rb"); - if (fp) { - // can open - lets go for it - fclose(fp); - canOpen = true; + } } else { - sprintf(generalPrint, "Unable to open file %s", fileName.c_str()); - printGeneralMessage(model_, generalPrint); - } - if (canOpen) { - int status = lpSolver->restoreModel(fileName.c_str()); - if (!status) { - goodModel = true; - time2 = CoinCpuTime(); - totalTime += time2 - time1; - time1 = time2; - } else { - // errors - sprintf(generalPrint, "There were errors on input"); - printGeneralMessage(model_, generalPrint); - } - } - } break; - case CLP_PARAM_ACTION_MAXIMIZE: - lpSolver->setOptimizationDirection(-1); - break; - case CLP_PARAM_ACTION_MINIMIZE: - lpSolver->setOptimizationDirection(1); - break; - case CLP_PARAM_ACTION_ALLSLACK: - lpSolver->allSlackBasis(true); - break; - case CLP_PARAM_ACTION_REVERSE: - if (goodModel) { - int iColumn; - int numberColumns = lpSolver->numberColumns(); - double *dualColumnSolution = lpSolver->dualColumnSolution(); - ClpObjective *obj = lpSolver->objectiveAsObject(); - assert(dynamic_cast< ClpLinearObjective * >(obj)); - double offset; - double *objective = obj->gradient(NULL, NULL, offset, true); - for (iColumn = 0; iColumn < numberColumns; iColumn++) { - dualColumnSolution[iColumn] = dualColumnSolution[iColumn]; - objective[iColumn] = -objective[iColumn]; - } - int iRow; - int numberRows = lpSolver->numberRows(); - double *dualRowSolution = lpSolver->dualRowSolution(); - for (iRow = 0; iRow < numberRows; iRow++) - dualRowSolution[iRow] = dualRowSolution[iRow]; + printf("Saving model on %s\n", + fileName.c_str()); } - break; - case CLP_PARAM_ACTION_DIRECTORY: { - std::string name = CoinReadGetString(argc, argv); - if (name != "EOL") { - size_t length = name.length(); - if (length > 0 && name[length - 1] == dirsep) { - directory = name; - } else { - directory = name + dirsep; - } - parameters_[iParam].setStringValue(directory); + status = model2->saveModel(fileName.c_str()); + if (deleteModel2) + delete model2; + if (!status) { + goodModel = true; + time2 = CoinCpuTime(); + totalTime += time2 - time1; + time1 = time2; } else { - parameters_[iParam].printString(); + // errors + printGeneralMessage(model_, "There were errors on output"); } } break; - case CLP_PARAM_ACTION_DIRSAMPLE: { - std::string name = CoinReadGetString(argc, argv); - if (name != "EOL") { - size_t length = name.length(); - if (length > 0 && name[length - 1] == dirsep) { - dirSample = name; - } else { - dirSample = name + dirsep; - } - parameters_[iParam].setStringValue(dirSample); - } else { - parameters_[iParam].printString(); + + case CbcParam::READMODEL: { + + cbcParam->readValue(inputQueue, fileName, &message); + CoinParamUtils::processFile(fileName, + parameters[CbcParam::DIRECTORY]->dirName(), + &canOpen); + if (!canOpen) { + buffer.str(""); + buffer << "Unable to open file " << fileName.c_str(); + printGeneralMessage(model_, buffer.str()); + continue; } - } break; - case CLP_PARAM_ACTION_DIRNETLIB: { - std::string name = CoinReadGetString(argc, argv); - if (name != "EOL") { - size_t length = name.length(); - if (length > 0 && name[length - 1] == dirsep) { - dirNetlib = name; - } else { - dirNetlib = name + dirsep; - } - parameters_[iParam].setStringValue(dirNetlib); - } else { - parameters_[iParam].printString(); + if (fileName == ""){ + fileName = parameters[CbcParam::MODELFILE]->fileName(); + }else{ + parameters[CbcParam::MODELFILE]->setFileName(fileName); } - } break; - case CBC_PARAM_ACTION_DIRMIPLIB: { - std::string name = CoinReadGetString(argc, argv); - if (name != "EOL") { - size_t length = name.length(); - if (length > 0 && name[length - 1] == dirsep) { - dirMiplib = name; - } else { - dirMiplib = name + dirsep; - } - parameters_[iParam].setStringValue(dirMiplib); + int status = lpSolver->restoreModel(fileName.c_str()); + if (!status) { + goodModel = true; + time2 = CoinCpuTime(); + totalTime += time2 - time1; + time1 = time2; } else { - parameters_[iParam].printString(); + // errors + buffer.str(""); + buffer << "There were errors on input"; + printGeneralMessage(model_, buffer.str()); } } break; - case CLP_PARAM_ACTION_STDIN: - setCbcOrClpReadMode(-1); + case CbcParam::MAXIMIZE: + lpSolver->setOptimizationDirection(-1); break; - case CLP_PARAM_ACTION_NETLIB_DUAL: - case CLP_PARAM_ACTION_NETLIB_EITHER: - case CLP_PARAM_ACTION_NETLIB_BARRIER: - case CLP_PARAM_ACTION_NETLIB_PRIMAL: - case CLP_PARAM_ACTION_NETLIB_TUNE: { - printf("unit test is now only from clp - does same thing\n"); - //return(22); - } break; - case CLP_PARAM_ACTION_UNITTEST: { - int returnCode; - if (!strcmp(argv[1],"-dirMiplib") || !strcmp(argv[1],"-dirmiplib")) - returnCode = CbcClpUnitTest(model_, dirMiplib, -3, NULL, - argc,argv,callBack,parameterData); - else - returnCode = CbcClpUnitTest(model_, dirSample, -2, NULL, - argc,argv,callBack,parameterData); - babModel_ = NULL; - return returnCode; - } - case CLP_PARAM_ACTION_FAKEBOUND: - if (goodModel) { - // get bound - double value = CoinReadGetDoubleField(argc, argv, &valid); - if (!valid) { - sprintf(generalPrint, "Setting %s to DEBUG %g", parameters_[iParam].name().c_str(), value); - printGeneralMessage(model_, generalPrint); - int iRow; - int numberRows = lpSolver->numberRows(); - double *rowLower = lpSolver->rowLower(); - double *rowUpper = lpSolver->rowUpper(); - for (iRow = 0; iRow < numberRows; iRow++) { - // leave free ones for now - if (rowLower[iRow] > -1.0e20 || rowUpper[iRow] < 1.0e20) { - rowLower[iRow] = CoinMax(rowLower[iRow], -value); - rowUpper[iRow] = CoinMin(rowUpper[iRow], value); - } - } - int iColumn; - int numberColumns = lpSolver->numberColumns(); - double *columnLower = lpSolver->columnLower(); - double *columnUpper = lpSolver->columnUpper(); - for (iColumn = 0; iColumn < numberColumns; iColumn++) { - // leave free ones for now - if (columnLower[iColumn] > -1.0e20 || columnUpper[iColumn] < 1.0e20) { - columnLower[iColumn] = CoinMax(columnLower[iColumn], -value); - columnUpper[iColumn] = CoinMin(columnUpper[iColumn], value); - } - } - } else if (valid == 1) { - abort(); - } else { - std::cout << "enter value for " << parameters_[iParam].name() << std::endl; - } - } + case CbcParam::MINIMIZE: + lpSolver->setOptimizationDirection(1); break; - case CLP_PARAM_ACTION_REALLY_SCALE: - if (goodModel) { - ClpSimplex newModel(*lpSolver, - lpSolver->scalingFlag()); - printf("model really really scaled\n"); - *lpSolver = newModel; + case CbcParam::REVERSE:{ + if (!goodModel){ + continue; } - break; - case CLP_PARAM_ACTION_USERCLP: -#ifdef USER_HAS_FAKE_CLP - // Replace the sample code by whatever you want - if (goodModel) { - // Way of using an existing piece of code - OsiClpSolverInterface *clpSolver = dynamic_cast< OsiClpSolverInterface * >(model_.solver()); - ClpSimplex *lpSolver = clpSolver->getModelPtr(); - // set time from integer model - double timeToGo = model_.getMaximumSeconds(); - lpSolver->setMaximumSeconds(timeToGo); - int extra1 = parameters_[whichParam(CBC_PARAM_INT_EXTRA1, parameters_)].intValue(); - fakeMain2(*lpSolver, *clpSolver, extra1); - lpSolver = clpSolver->getModelPtr(); - // My actual usage has objective only in clpSolver - //double objectiveValue=clpSolver->getObjValue(); - //int iStat = lpSolver->status(); - //int iStat2 = lpSolver->secondaryStatus(); + int iColumn; + int numberColumns = lpSolver->numberColumns(); + double *dualColumnSolution = lpSolver->dualColumnSolution(); + ClpObjective *obj = lpSolver->objectiveAsObject(); + assert(dynamic_cast(obj)); + double offset; + double *objective = obj->gradient(NULL, NULL, offset, true); + for (iColumn = 0; iColumn < numberColumns; iColumn++) { + dualColumnSolution[iColumn] = dualColumnSolution[iColumn]; + objective[iColumn] = -objective[iColumn]; } -#endif + int iRow; + int numberRows = lpSolver->numberRows(); + double *dualRowSolution = lpSolver->dualRowSolution(); + for (iRow = 0; iRow < numberRows; iRow++) + dualRowSolution[iRow] = dualRowSolution[iRow]; + } break; + case CbcParam::STDIN: + interactiveMode = true; + while (!inputQueue.empty()) + inputQueue.pop_front(); break; - case CBC_PARAM_ACTION_USERCBC: + case CbcParam::UNITTEST: { + int returnCode = -1; + std::string dirMiplib = parameters[CbcParam::DIRMIPLIB]->dirName(); + std::string dirSample = parameters[CbcParam::DIRSAMPLE]->dirName(); + if (dirMiplib != ""){ + returnCode = CbcClpUnitTest(model_, dirMiplib, -3, NULL, + saveInputQueue,callBack, parameters); + } else if (dirSample != ""){ + returnCode = CbcClpUnitTest(model_, dirSample, -2, NULL, + saveInputQueue,callBack, parameters); + } else { + buffer.str(""); + buffer << "No directory specified for input files" + << "Please use dirMiplib or dirSample to set directory name"; + printGeneralMessage(model_, buffer.str()); + } + babModel_ = NULL; + return returnCode; + } + case CbcParam::USERCBC: { #ifdef USER_HAS_FAKE_CBC // Replace the sample code by whatever you want - if (goodModel) { - // Way of using an existing piece of code - OsiClpSolverInterface *clpSolver = dynamic_cast< OsiClpSolverInterface * >(model_.solver()); - ClpSimplex *lpSolver = clpSolver->getModelPtr(); - // set time from integer model - double timeToGo = model_.getMaximumSeconds(); - lpSolver->setMaximumSeconds(timeToGo); - fakeMain(*lpSolver, *clpSolver, model); - // My actual usage has objective only in clpSolver - double objectiveValue = clpSolver->getObjValue(); - int iStat = lpSolver->status(); - int iStat2 = lpSolver->secondaryStatus(); - // make sure solution back in correct place - clpSolver = dynamic_cast< OsiClpSolverInterface * >(model_.solver()); - lpSolver = clpSolver->getModelPtr(); - if (statusUserFunction_[0]) { - int n = clpSolver->getNumCols(); - double value = objectiveValue * lpSolver->getObjSense(); - char buf[300]; - int pos = 0; - std::string minor[] = { "", "", "gap", "nodes", "time", "", "solutions", "user ctrl-c" }; - if (iStat == 0) { + if (!goodModel){ + printGeneralWarning(model_, "** Current model not valid\n"); + continue; + } + // Way of using an existing piece of code + OsiClpSolverInterface *clpSolver = + dynamic_cast(model_.solver()); + ClpSimplex *lpSolver = clpSolver->getModelPtr(); + // set time from integer model + double timeToGo = model_.getMaximumSeconds(); + lpSolver->setMaximumSeconds(timeToGo); + fakeMain(*lpSolver, *clpSolver, model); + // My actual usage has objective only in clpSolver + double objectiveValue = clpSolver->getObjValue(); + int iStat = lpSolver->status(); + int iStat2 = lpSolver->secondaryStatus(); + // make sure solution back in correct place + clpSolver = + dynamic_cast(model_.solver()); + lpSolver = clpSolver->getModelPtr(); + if (info && statusUserFunction_[0]) { + int n = clpSolver->getNumCols(); + double value = objectiveValue * lpSolver->getObjSense(); + char buf[300]; + int pos = 0; + std::string minor[] = {"", "", "gap", "nodes", + "time", "", "solutions", "user ctrl-c"}; + if (iStat == 0) { if (objectiveValue < 1.0e40) { - pos += sprintf(buf + pos, "optimal,"); + pos += sprintf(buf + pos, "optimal,"); } else { - // infeasible - iStat = 1; - pos += sprintf(buf + pos, "infeasible,"); + // infeasible + iStat = 1; + pos += sprintf(buf + pos, "infeasible,"); } - } else if (iStat == 1) { + } else if (iStat == 1) { if (iStat2 != 6) - iStat = 3; + iStat = 3; else - iStat = 4; - pos += sprintf(buf + pos, "stopped on %s,", minor[iStat2].c_str()); - } else if (iStat == 2) { + iStat = 4; + pos += sprintf(buf + pos, "stopped on %s,", + minor[iStat2].c_str()); + } else if (iStat == 2) { iStat = 7; pos += sprintf(buf + pos, "stopped on difficulties,"); } else if (iStat == 5) { @@ -10023,40 +10171,41 @@ int CbcMain1(int argc, const char *argv[], pos += sprintf(buf + pos, "status unknown,"); iStat = 6; } - info.problemStatus = iStat; - info.objValue = value; + info->problemStatus = iStat; + info->objValue = value; if (objectiveValue < 1.0e40) pos += sprintf(buf + pos, " objective %.*g", ampl_obj_prec(), - value); + value); sprintf(buf + pos, "\n%d nodes, %d iterations", - model_.getNodeCount(), - model_.getIterationCount()); + model_.getNodeCount(), model_.getIterationCount()); if (objectiveValue < 1.0e50) { - free(info.primalSolution); - info.primalSolution = (double *)malloc(n * sizeof(double)); - CoinCopyN(lpSolver->primalColumnSolution(), n, info.primalSolution); + free(info->primalSolution); + info->primalSolution = (double *)malloc(n * sizeof(double)); + CoinCopyN(lpSolver->primalColumnSolution(), n, + info->primalSolution); int numberRows = lpSolver->numberRows(); - free(info.dualSolution); - info.dualSolution = (double *)malloc(numberRows * sizeof(double)); - CoinCopyN(lpSolver->dualRowSolution(), numberRows, info.dualSolution); + free(info->dualSolution); + info->dualSolution = + (double *)malloc(numberRows * sizeof(double)); + CoinCopyN(lpSolver->dualRowSolution(), numberRows, + info->dualSolution); } else { - info.primalSolution = NULL; - info.dualSolution = NULL; + info->primalSolution = NULL; + info->dualSolution = NULL; } // put buffer into info - strcpy(info.buffer, buf); + strcpy(info->buffer, buf); } - } #endif - break; - case CLP_PARAM_ACTION_HELP: - std::cout << "Cbc version " << CBC_VERSION - << ", build " << __DATE__ << std::endl; - std::cout << "Non default values:-" << std::endl; - std::cout << "Perturbation " << lpSolver->perturbation() << " (default 100)" + } break; + case CbcParam::HELP: + std::cout << "Cbc version " << CBC_VERSION << ", build " << __DATE__ << std::endl; - CoinReadPrintit( - "Presolve being done with 5 passes\n\ +#if 0 + std::cout << "Non default values:-" << std::endl; + std::cout << "Perturbation " << lpSolver->perturbation() + << " (default 100)" << std::endl; + std::cout << CoinParamUtils::printString("Presolve being done with 5 passes\n\ Dual steepest edge steep/partial on matrix shape and factorization density\n\ Clpnnnn taken out of messages\n\ If Factorization frequency default then done on size of matrix\n\n\ @@ -10064,40 +10213,28 @@ If Factorization frequency default then done on size of matrix\n\n\ You can switch to interactive mode at any time so\n\ clp watson.mps -scaling off -primalsimplex\nis the same as\n\ clp watson.mps -\nscaling off\nprimalsimplex"); + std::endl; +#endif + std::cout << "Use ? or ??? to see list of commands" << std::endl; + std::cout << "Set allcommands to all to see less common commands" << std::endl; break; - case CLP_PARAM_ACTION_CSVSTATISTICS: { - // get next field - field = CoinReadGetString(argc, argv); - if (field == "$") { - field = parameters_[iParam].stringValue(); - } else if (field == "EOL") { - parameters_[iParam].printString(); - break; - } else { - parameters_[iParam].setStringValue(field); - } - std::string fileName; - if (field[0] == '/' || field[0] == '\\') { - fileName = field; - } else if (field[0] == '~') { - char *environVar = getenv("HOME"); - if (environVar) { - std::string home(environVar); - field = field.erase(0, 1); - fileName = home + field; - } else { - fileName = field; - } - } else { - fileName = directory + field; + case CbcParam::WRITESTATS: { + cbcParam->readValue(inputQueue, fileName, &message); + CoinParamUtils::processFile(fileName, + parameters[CbcParam::DIRECTORY]->dirName()); + if (fileName == ""){ + fileName = parameters[CbcParam::CSVSTATSFILE]->fileName(); + }else{ + parameters[CbcParam::CSVSTATSFILE]->setFileName(fileName); } int state = 0; - char buffer[1000]; - FILE *fp = fopen(fileName.c_str(), "r"); + // FIXME: This needs to fixed up to use modern C++ and to use the inputQueue properly + char cbuffer[1000]; + fp = fopen(fileName.c_str(), "r"); if (fp) { // file already there state = 1; - char *getBuffer = fgets(buffer, 1000, fp); + char *getBuffer = fgets(cbuffer, 1000, fp); if (getBuffer) { // assume header there state = 2; @@ -10105,123 +10242,155 @@ clp watson.mps -\nscaling off\nprimalsimplex"); fclose(fp); } fp = fopen(fileName.c_str(), "a"); - if (fp) { - // can open - lets go for it - // first header if needed - if (state != 2) { - fprintf(fp, "Name,result,time,sys,elapsed,objective,continuous,tightened,cut_time,nodes,iterations,rows,columns,processed_rows,processed_columns"); - for (int i = 0; i < statistics_number_generators; i++) + if (!fp) { + buffer.str(""); + buffer << "Unable to open file " << fileName.c_str(); + printGeneralMessage(model_, buffer.str()); + continue; + } + // can open - lets go for it + // first header if needed + if (state != 2) { + fprintf(fp, "Name,result,time,sys,elapsed,objective,continuous," + "tightened,cut_time,nodes,iterations,rows,columns," + "processed_rows,processed_columns"); + for (int i = 0; i < statistics_number_generators; i++) fprintf(fp, ",%s", statistics_name_generators[i]); - fprintf(fp, ",runtime_options"); - fprintf(fp, "\n"); - } - strcpy(buffer, argv[1]); - char *slash = buffer; - for (int i = 0; i < static_cast< int >(strlen(buffer)); i++) { - if (buffer[i] == '/' || buffer[i] == '\\') - slash = buffer + i + 1; - } - fprintf(fp, "%s,%s,%.2f,%.2f,%.2f,%.16g,%g,%g,%.2f,%d,%d,%d,%d,%d,%d", - slash, statistics_result.c_str(), statistics_seconds, - statistics_sys_seconds, statistics_elapsed_seconds, - statistics_obj, - statistics_continuous, statistics_tighter, statistics_cut_time, statistics_nodes, - statistics_iterations, statistics_nrows, statistics_ncols, - statistics_nprocessedrows, statistics_nprocessedcols); - for (int i = 0; i < statistics_number_generators; i++) - fprintf(fp, ",%d", statistics_number_cuts != NULL ? statistics_number_cuts[i] : 0); - fprintf(fp, ","); - for (int i = 1; i < argc; i++) { - if (strstr(argv[i], ".gz") || strstr(argv[i], ".mps")) + fprintf(fp, ",runtime_options"); + fprintf(fp, "\n"); + } + strcpy(cbuffer, inputQueue[0].c_str()); + char *slash = cbuffer; + for (int i = 0; i < static_cast(strlen(cbuffer)); i++) { + if (cbuffer[i] == '/' || cbuffer[i] == '\\') + slash = cbuffer + i + 1; + } + fprintf(fp, + "%s,%s,%.2f,%.2f,%.2f,%.16g,%g,%g,%.2f,%d,%d,%d,%d,%d,%d", + slash, statistics_result.c_str(), statistics_seconds, + statistics_sys_seconds, statistics_elapsed_seconds, + statistics_obj, statistics_continuous, statistics_tighter, + statistics_cut_time, statistics_nodes, + statistics_iterations, statistics_nrows, statistics_ncols, + statistics_nprocessedrows, statistics_nprocessedcols); + for (int i = 0; i < statistics_number_generators; i++) + fprintf(fp, ",%d", + statistics_number_cuts != NULL + ? statistics_number_cuts[i] + : 0); + fprintf(fp, ","); + for (int i = 0; i < inputQueue.size(); i++) { + if (strstr(inputQueue[i].c_str(), ".gz") || + strstr(inputQueue[i].c_str(), ".mps")){ continue; - if (!argv[i] || !strncmp(argv[i], "-csv", 4)) + } + if (!inputQueue[i].c_str() || !strncmp(inputQueue[i].c_str(), "-csv", 4)){ break; - fprintf(fp, "%s ", argv[i]); - } - fprintf(fp, "\n"); - fclose(fp); - } else { - sprintf(generalPrint, "Unable to open file %s", fileName.c_str()); - printGeneralMessage(model_, generalPrint); + } + fprintf(fp, "%s ", inputQueue[i].c_str()); } + fprintf(fp, "\n"); + fclose(fp); } break; - case CLP_PARAM_ACTION_SOLUTION: - case CLP_PARAM_ACTION_NEXTBESTSOLUTION: - case CLP_PARAM_ACTION_GMPL_SOLUTION: - if (goodModel) { + case CbcParam::PRINTSOL: + case CbcParam::WRITESOL: + case CbcParam::WRITENEXTSOL: + + case CbcParam::WRITEGMPLSOL:{ + if (!goodModel){ + printGeneralWarning(model_, "** Current model not valid\n"); + continue; + } + fp = NULL; + bool append = true; ClpSimplex *saveLpSolver = NULL; - // get next field - field = CoinReadGetString(argc, argv); - bool append = false; - if (field == "append$") { - field = "$"; - append = true; - } - if (field == "$") { - field = parameters_[iParam].stringValue(); - } else if (field == "EOL") { - parameters_[iParam].printString(); - break; - } else { - parameters_[iParam].setStringValue(field); - } - std::string fileName; - FILE *fp = NULL; - if (field == "-" || field == "EOL" || field == "stdout") { - // stdout - fp = stdout; - } else if (field == "stderr") { - // stderr - fp = stderr; + canOpen = false; + if (cbcParamCode == CbcParam::PRINTSOL) { + fp = stdout; + fprintf(fp, "\n"); } else { - bool absolutePath; - if (dirsep == '/') { - // non Windows (or cygwin) - absolutePath = (field[0] == '/'); - } else { - //Windows (non cycgwin) - absolutePath = (field[0] == '\\'); - // but allow for : - if (strchr(field.c_str(), ':')) - absolutePath = true; - } - if (absolutePath) { - fileName = field; - } else if (field[0] == '~') { - char *environVar = getenv("HOME"); - if (environVar) { - std::string home(environVar); - field = field.erase(0, 1); - fileName = home + field; - } else { - fileName = field; - } - } else { - fileName = directory + field; - } - if (!append) - fp = fopen(fileName.c_str(), "w"); - else - fp = fopen(fileName.c_str(), "a"); + cbcParam->readValue(inputQueue, fileName, &message); + if (fileName == "append"){ + switch (cbcParamCode){ + case CbcParam::WRITESOL: + fileName = + parameters[CbcParam::SOLUTIONFILE]->fileName(); + break; + case CbcParam::WRITENEXTSOL: + fileName = + parameters[CbcParam::NEXTSOLFILE]->fileName(); + break; + case CbcParam::WRITEGMPLSOL: + fileName = + parameters[CbcParam::SOLUTIONFILE]->fileName(); + break; + } + CoinParamUtils::processFile(fileName, + parameters[CbcParam::DIRECTORY]->dirName(), + &canOpen); + if (!canOpen) { + buffer.str(""); + buffer << "Unable to open file " << fileName.c_str(); + printGeneralMessage(model_, buffer.str()); + continue; + } + append = true; + } else if (cbcParamCode == CbcParam::WRITESOL) { + CoinParamUtils::processFile(fileName, + parameters[CbcParam::DIRECTORY]->dirName()); + if (fileName == ""){ + fileName = + parameters[CbcParam::SOLUTIONFILE]->fileName(); + }else{ + parameters[CbcParam::SOLUTIONFILE]->setFileName(fileName); + } + } else if (cbcParamCode == CbcParam::WRITENEXTSOL) { + CoinParamUtils::processFile(fileName, + parameters[CbcParam::DIRECTORY]->dirName()); + if (fileName == ""){ + fileName = parameters[CbcParam::NEXTSOLFILE]->fileName(); + }else{ + parameters[CbcParam::NEXTSOLFILE]->setFileName(fileName); + } + } else if (cbcParamCode == CbcParam::WRITEGMPLSOL) { + CoinParamUtils::processFile(fileName, + parameters[CbcParam::DIRECTORY]->dirName()); + if (fileName == ""){ + fileName = parameters[CbcParam::GMPLSOLFILE]->fileName(); + }else{ + parameters[CbcParam::GMPLSOLFILE]->setFileName(fileName); + } + } + if (!append){ + fp = fopen(fileName.c_str(), "w"); + } else { + fp = fopen(fileName.c_str(), "a"); + } + if (!fp) { + buffer.str(""); + buffer << "Unable to open file " << fileName.c_str(); + printGeneralMessage(model_, buffer.str()); + continue; + } } - if (fp) { + + #ifndef CBC_OTHER_SOLVER - // See if Glpk - if (type == CLP_PARAM_ACTION_GMPL_SOLUTION) { + // See if Glpk + if (cbcParamCode == CbcParam::WRITEGMPLSOL) { int numberRows = lpSolver->getNumRows(); int numberColumns = lpSolver->getNumCols(); int numberGlpkRows = numberRows + 1; -#ifdef CBC_HAS_GLPK - if (cbc_glp_prob) { +#ifdef COINUTILS_HAS_GLPK + if (coin_glp_prob) { // from gmpl - numberGlpkRows = glp_get_num_rows(cbc_glp_prob); + numberGlpkRows = glp_get_num_rows(coin_glp_prob); if (numberGlpkRows != numberRows) - printf("Mismatch - cbc %d rows, glpk %d\n", - numberRows, numberGlpkRows); + printf("Mismatch - cbc %d rows, glpk %d\n", numberRows, + numberGlpkRows); } #endif - fprintf(fp, "%d %d\n", numberGlpkRows, - numberColumns); + fprintf(fp, "%d %d\n", numberGlpkRows, numberColumns); int iStat = lpSolver->status(); int iStat2 = GLP_UNDEF; bool integerProblem = false; @@ -10264,47 +10433,48 @@ clp watson.mps -\nscaling off\nprimalsimplex"); fprintf(fp, "4 %g 1.0\n", objValue); } } - int lookup[6] = { 4, 1, 3, 2, 4, 5 }; - const double *primalRowSolution = lpSolver->primalRowSolution(); + int lookup[6] = {4, 1, 3, 2, 4, 5}; + const double *primalRowSolution = + lpSolver->primalRowSolution(); const double *dualRowSolution = lpSolver->dualRowSolution(); for (int i = 0; i < numberRows; i++) { if (integerProblem) { fprintf(fp, "%g\n", primalRowSolution[i]); } else { - fprintf(fp, "%d %g %g\n", lookup[lpSolver->getRowStatus(i)], - primalRowSolution[i], dualRowSolution[i]); + fprintf(fp, "%d %g %g\n", + lookup[lpSolver->getRowStatus(i)], + primalRowSolution[i], dualRowSolution[i]); } } - const double *primalColumnSolution = lpSolver->primalColumnSolution(); - const double *dualColumnSolution = lpSolver->dualColumnSolution(); + const double *primalColumnSolution = + lpSolver->primalColumnSolution(); + const double *dualColumnSolution = + lpSolver->dualColumnSolution(); for (int i = 0; i < numberColumns; i++) { if (integerProblem) { fprintf(fp, "%g\n", primalColumnSolution[i]); } else { - fprintf(fp, "%d %g %g\n", lookup[lpSolver->getColumnStatus(i)], - primalColumnSolution[i], dualColumnSolution[i]); + fprintf(fp, "%d %g %g\n", + lookup[lpSolver->getColumnStatus(i)], + primalColumnSolution[i], dualColumnSolution[i]); } } fclose(fp); -#ifdef CBC_HAS_GLPK - if (cbc_glp_prob) { +#ifdef COINUTILS_HAS_GLPK + if (coin_glp_prob) { if (integerProblem) { - glp_read_mip(cbc_glp_prob, fileName.c_str()); - glp_mpl_postsolve(cbc_glp_tran, - cbc_glp_prob, - GLP_MIP); + glp_read_mip(coin_glp_prob, fileName.c_str()); + glp_mpl_postsolve(coin_glp_tran, coin_glp_prob, GLP_MIP); } else { - glp_read_sol(cbc_glp_prob, fileName.c_str()); - glp_mpl_postsolve(cbc_glp_tran, - cbc_glp_prob, - GLP_SOL); + glp_read_sol(coin_glp_prob, fileName.c_str()); + glp_mpl_postsolve(coin_glp_tran, coin_glp_prob, GLP_SOL); } // free up as much as possible - glp_free(cbc_glp_prob); - glp_mpl_free_wksp(cbc_glp_tran); - cbc_glp_prob = NULL; - cbc_glp_tran = NULL; - //gmp_free_mem(); + glp_free(coin_glp_prob); + glp_mpl_free_wksp(coin_glp_tran); + coin_glp_prob = NULL; + coin_glp_tran = NULL; + // gmp_free_mem(); /* check that no memory blocks are still allocated */ glp_free_env(); } @@ -10312,20 +10482,20 @@ clp watson.mps -\nscaling off\nprimalsimplex"); break; } if (printMode < 5) { - if (type == CLP_PARAM_ACTION_NEXTBESTSOLUTION) { + if (cbcParamCode == CbcParam::WRITENEXTSOL) { // save - const double *nextBestSolution = model_.savedSolution(currentBestSolution++); + const double *nextBestSolution = + model_.savedSolution(currentBestSolution++); if (!nextBestSolution) { - sprintf(generalPrint, "All alternative solutions printed"); - generalMessageHandler->message(CLP_GENERAL, generalMessages) - << generalPrint - << CoinMessageEol; + buffer.str(""); + buffer << "All alternative solutions printed"; + printGeneralMessage(model_, buffer.str()); break; } else { - sprintf(generalPrint, "Alternative solution - %d remaining", model_.numberSavedSolutions() - 2); - generalMessageHandler->message(CLP_GENERAL, generalMessages) - << generalPrint - << CoinMessageEol; + buffer.str(""); + buffer << "Alternative solution - " + << model_.numberSavedSolutions() - 2 << " remaining"; + printGeneralMessage(model_, buffer.str()); } saveLpSolver = lpSolver; assert(clpSolver->getModelPtr() == saveLpSolver); @@ -10340,7 +10510,8 @@ clp watson.mps -\nscaling off\nprimalsimplex"); double *lower = lpSolver->columnLower(); double *upper = lpSolver->columnUpper(); int numberColumns = lpSolver->numberColumns(); - memcpy(solution, nextBestSolution, numberColumns * sizeof(double)); + memcpy(solution, nextBestSolution, + numberColumns * sizeof(double)); model_.deleteSavedSolution(1); for (int i = 0; i < numberColumns; i++) { if (clpSolver->isInteger(i)) { @@ -10417,14 +10588,17 @@ clp watson.mps -\nscaling off\nprimalsimplex"); const double *rowUpper = clpSolver->getRowUpper(); double primalTolerance; clpSolver->getDblParam(OsiPrimalTolerance, primalTolerance); - size_t lengthPrint = static_cast< size_t >(CoinMax(lengthName, 8)); - bool doMask = (printMask != "" && lengthName); + size_t lengthPrint = + static_cast(CoinMax(lengthName, 8)); + bool doMask = (parameters[CbcParam::PRINTMASK]->strVal() + != "" && lengthName); int *maskStarts = NULL; int maxMasks = 0; char **masks = NULL; if (doMask) { int nAst = 0; - const char *pMask2 = printMask.c_str(); + const char *pMask2 = + parameters[CbcParam::PRINTMASK]->strVal().c_str(); char pMask[100]; size_t iChar; size_t lengthMask = strlen(pMask2); @@ -10448,7 +10622,7 @@ clp watson.mps -\nscaling off\nprimalsimplex"); } else { strcpy(pMask, pMask2); } - if (lengthMask > static_cast< size_t >(lengthName)) { + if (lengthMask > static_cast(lengthName)) { printf("mask %s too long - skipping\n", pMask); break; } @@ -10481,7 +10655,8 @@ clp watson.mps -\nscaling off\nprimalsimplex"); size_t nAfter = length - nBefore; // and add null nAfter++; - for (int i = 0; i <= lengthName - static_cast< int >(length); i++) { + for (int i = 0; + i <= lengthName - static_cast(length); i++) { char *maskOut = newMasks[nEntries]; memcpy(maskOut, oldMask, nBefore); for (int k = 0; k < i; k++) @@ -10503,7 +10678,7 @@ clp watson.mps -\nscaling off\nprimalsimplex"); while (length > 0 && maskThis[length - 1] == ' ') length--; maskThis[length] = '\0'; - sort[i] = static_cast< int >(length); + sort[i] = static_cast(length); } CoinSort_2(sort, sort + nEntries, masks); int lastLength = -1; @@ -10521,7 +10696,7 @@ clp watson.mps -\nscaling off\nprimalsimplex"); if (printMode > 5 && printMode < 12) { ClpSimplex *solver = clpSolver->getModelPtr(); int numberColumns = numberPrintingColumns(clpSolver); - //int numberColumns = solver->numberColumns(); + // int numberColumns = solver->numberColumns(); // column length unless rhs ranging int number = numberColumns; if (lpSolver->status()) { @@ -10593,22 +10768,27 @@ clp watson.mps -\nscaling off\nprimalsimplex"); // bound or rhs ranging case 6: case 7: - solver->primalRanging(numberRows, - which, valueIncrease, sequenceIncrease, - valueDecrease, sequenceDecrease); + solver->primalRanging(numberRows, which, valueIncrease, + sequenceIncrease, valueDecrease, + sequenceDecrease); break; // objective ranging case 8: - solver->dualRanging(number, - which, valueIncrease, sequenceIncrease, - valueDecrease, sequenceDecrease); + solver->dualRanging(number, which, valueIncrease, + sequenceIncrease, valueDecrease, + sequenceDecrease); break; } for (int i = 0; i < number; i++) { int iWhich = which[i]; - fprintf(fp, "%d,", (iWhich < numberColumns) ? iWhich : iWhich - numberColumns); + fprintf(fp, "%d,", + (iWhich < numberColumns) ? iWhich + : iWhich - numberColumns); if (lengthName) { - const char *name = (printMode == 7) ? rowNames[iWhich - numberColumns].c_str() : columnNames[iWhich].c_str(); + const char *name = + (printMode == 7) + ? rowNames[iWhich - numberColumns].c_str() + : columnNames[iWhich].c_str(); fprintf(fp, "%s,", name); } if (valueIncrease[i] < 1.0e30) { @@ -10666,12 +10846,15 @@ clp watson.mps -\nscaling off\nprimalsimplex"); } char printFormat[50]; sprintf(printFormat, " %s %s\n", - CLP_QUOTE(CLP_OUTPUT_FORMAT), - CLP_QUOTE(CLP_OUTPUT_FORMAT)); + CLP_QUOTE(CLP_OUTPUT_FORMAT), + CLP_QUOTE(CLP_OUTPUT_FORMAT)); if (printMode > 2 && printMode < 5) { for (iRow = 0; iRow < numberRows; iRow++) { int type = printMode - 3; - if (primalRowSolution[iRow] > rowUpper[iRow] + primalTolerance || primalRowSolution[iRow] < rowLower[iRow] - primalTolerance) { + if (primalRowSolution[iRow] > + rowUpper[iRow] + primalTolerance || + primalRowSolution[iRow] < + rowLower[iRow] - primalTolerance) { fprintf(fp, "** "); type = 2; } else if (fabs(primalRowSolution[iRow]) > 1.0e-8) { @@ -10679,7 +10862,8 @@ clp watson.mps -\nscaling off\nprimalsimplex"); } else if (numberRows < 50) { type = 3; } - if (doMask && !maskMatches(maskStarts, masks, rowNames[iRow])) + if (doMask && + !maskMatches(maskStarts, masks, rowNames[iRow])) type = 0; if (type) { fprintf(fp, "%7d ", iRow); @@ -10693,14 +10877,15 @@ clp watson.mps -\nscaling off\nprimalsimplex"); fprintf(fp, " "); } fprintf(fp, printFormat, primalRowSolution[iRow], - dualRowSolution[iRow]); + dualRowSolution[iRow]); } } } int iColumn; int numberColumns = numberPrintingColumns(clpSolver); const double *dualColumnSolution = clpSolver->getReducedCost(); - const double *primalColumnSolution = clpSolver->getColSolution(); + const double *primalColumnSolution = + clpSolver->getColSolution(); const double *columnLower = clpSolver->getColLower(); const double *columnUpper = clpSolver->getColUpper(); if (printMode != 2 && printMode < 12) { @@ -10713,7 +10898,10 @@ clp watson.mps -\nscaling off\nprimalsimplex"); } for (iColumn = 0; iColumn < numberColumns; iColumn++) { int type = (printMode > 3) ? 1 : 0; - if (primalColumnSolution[iColumn] > columnUpper[iColumn] + primalTolerance || primalColumnSolution[iColumn] < columnLower[iColumn] - primalTolerance) { + if (primalColumnSolution[iColumn] > + columnUpper[iColumn] + primalTolerance || + primalColumnSolution[iColumn] < + columnLower[iColumn] - primalTolerance) { fprintf(fp, "** "); type = 2; } else if (fabs(primalColumnSolution[iColumn]) > 1.0e-8) { @@ -10722,10 +10910,12 @@ clp watson.mps -\nscaling off\nprimalsimplex"); type = 3; } // see if integer - if ((!clpSolver->isInteger(iColumn) || fabs(primalColumnSolution[iColumn]) < 1.0e-8) - && printMode == 1) + if ((!clpSolver->isInteger(iColumn) || + fabs(primalColumnSolution[iColumn]) < 1.0e-8) && + printMode == 1) type = 0; - if (doMask && !maskMatches(maskStarts, masks, columnNames[iColumn])) + if (doMask && + !maskMatches(maskStarts, masks, columnNames[iColumn])) type = 0; if (type) { if (printMode != 5) { @@ -10739,9 +10929,8 @@ clp watson.mps -\nscaling off\nprimalsimplex"); for (; i < lengthPrint; i++) fprintf(fp, " "); } - fprintf(fp, printFormat, - primalColumnSolution[iColumn], - dualColumnSolution[iColumn]); + fprintf(fp, printFormat, primalColumnSolution[iColumn], + dualColumnSolution[iColumn]); } else { char temp[100]; if (lengthName) { @@ -10753,7 +10942,7 @@ clp watson.mps -\nscaling off\nprimalsimplex"); sprintf(temp, "%7d", iColumn); } sprintf(temp + strlen(temp), ", %15.8g", - primalColumnSolution[iColumn]); + primalColumnSolution[iColumn]); size_t n = strlen(temp); size_t k = 0; for (size_t i = 0; i < n + 1; i++) { @@ -10764,7 +10953,7 @@ clp watson.mps -\nscaling off\nprimalsimplex"); } } } - if (type == CLP_PARAM_ACTION_NEXTBESTSOLUTION) { + if (cbcParamCode == CbcParam::WRITENEXTSOL) { if (saveLpSolver) { clpSolver->swapModelPtr(saveLpSolver); delete lpSolver; @@ -10779,7 +10968,8 @@ clp watson.mps -\nscaling off\nprimalsimplex"); bool newLine = false; fprintf(fp, "\tint intIndicesV[]={\n"); for (iColumn = 0; iColumn < numberColumns; iColumn++) { - if (primalColumnSolution[iColumn] > 0.5 && model_.solver()->isInteger(iColumn)) { + if (primalColumnSolution[iColumn] > 0.5 && + model_.solver()->isInteger(iColumn)) { if (comma) fprintf(fp, ","); if (newLine) @@ -10800,12 +10990,14 @@ clp watson.mps -\nscaling off\nprimalsimplex"); newLine = false; fprintf(fp, "\tdouble intSolnV[]={\n"); for (iColumn = 0; iColumn < numberColumns; iColumn++) { - if (primalColumnSolution[iColumn] > 0.5 && model_.solver()->isInteger(iColumn)) { + if (primalColumnSolution[iColumn] > 0.5 && + model_.solver()->isInteger(iColumn)) { if (comma) fprintf(fp, ","); if (newLine) fprintf(fp, "\n"); - int value = static_cast< int >(primalColumnSolution[iColumn] + 0.5); + int value = + static_cast(primalColumnSolution[iColumn] + 0.5); fprintf(fp, "%d. ", value); comma = true; newLine = false; @@ -10821,7 +11013,8 @@ clp watson.mps -\nscaling off\nprimalsimplex"); // Make up a fake bounds section char outputValue[24]; for (iColumn = 0; iColumn < numberColumns; iColumn++) { - if (printMode == 13 || model_.solver()->isInteger(iColumn)) { + if (printMode == 13 || + model_.solver()->isInteger(iColumn)) { fprintf(fp, " FX BOUND001 "); const char *name = columnNames[iColumn].c_str(); size_t n = strlen(name); @@ -10831,7 +11024,7 @@ clp watson.mps -\nscaling off\nprimalsimplex"); for (; i < lengthPrint; i++) fprintf(fp, " "); CoinConvertDouble(5, 2, primalColumnSolution[iColumn], - outputValue); + outputValue); fprintf(fp, " %s\n", outputValue); } else { fprintf(fp, " LO BOUND001 "); @@ -10842,21 +11035,26 @@ clp watson.mps -\nscaling off\nprimalsimplex"); fprintf(fp, "%c", name[i]); for (; i < lengthPrint; i++) fprintf(fp, " "); - CoinConvertDouble(5, 2, CoinMax(-1.0e30, columnLower[iColumn]), - outputValue); + CoinConvertDouble(5, 2, + CoinMax(-1.0e30, columnLower[iColumn]), + outputValue); fprintf(fp, " %s\n", outputValue); fprintf(fp, " UP BOUND001 "); for (i = 0; i < n; i++) fprintf(fp, "%c", name[i]); for (; i < lengthPrint; i++) fprintf(fp, " "); - CoinConvertDouble(5, 2, CoinMin(1.0e30, columnUpper[iColumn]), - outputValue); + CoinConvertDouble(5, 2, + CoinMin(1.0e30, columnUpper[iColumn]), + outputValue); fprintf(fp, " %s\n", outputValue); } } for (iColumn = 0; iColumn < numberColumns; iColumn++) { - if (primalColumnSolution[iColumn] > columnUpper[iColumn] + primalTolerance || primalColumnSolution[iColumn] < columnLower[iColumn] - primalTolerance) { + if (primalColumnSolution[iColumn] > + columnUpper[iColumn] + primalTolerance || + primalColumnSolution[iColumn] < + columnLower[iColumn] - primalTolerance) { fprintf(fp, " FX BOUND002 "); const char *name = columnNames[iColumn].c_str(); size_t n = strlen(name); @@ -10866,7 +11064,7 @@ clp watson.mps -\nscaling off\nprimalsimplex"); for (; i < lengthPrint; i++) fprintf(fp, " "); CoinConvertDouble(5, 2, primalColumnSolution[iColumn], - outputValue); + outputValue); fprintf(fp, " %s\n", outputValue); } } @@ -10879,160 +11077,67 @@ clp watson.mps -\nscaling off\nprimalsimplex"); delete[] masks[i]; delete[] masks; } - } else { - sprintf(generalPrint, "Unable to open file %s", fileName.c_str()); - printGeneralMessage(model_, generalPrint); - } - } else { - sprintf(generalPrint, "** Current model not valid"); - printGeneralMessage(model_, generalPrint); + } break; + case CbcParam::WRITESOLBINARY: + if (!goodModel){ + printGeneralWarning(model_, "** Current model not valid\n"); + continue; } - break; - case CLP_PARAM_ACTION_SAVESOL: - if (goodModel) { - // get next field - field = CoinReadGetString(argc, argv); - if (field == "$") { - field = parameters_[iParam].stringValue(); - } else if (field == "EOL") { - parameters_[iParam].printString(); - break; - } else { - parameters_[iParam].setStringValue(field); - } - std::string fileName; - if (field[0] == '/' || field[0] == '\\') { - fileName = field; - } else if (field[0] == '~') { - char *environVar = getenv("HOME"); - if (environVar) { - std::string home(environVar); - field = field.erase(0, 1); - fileName = home + field; - } else { - fileName = field; - } - } else { - fileName = directory + field; - } - saveSolution(lpSolver, fileName); - } else { - sprintf(generalPrint, "** Current model not valid"); - printGeneralMessage(model_, generalPrint); + cbcParam->readValue(inputQueue, fileName, &message); + CoinParamUtils::processFile(fileName, + parameters[CbcParam::DIRECTORY]->dirName()); + if (fileName == ""){ + fileName = parameters[CbcParam::SOLUTIONBINARYFILE]->fileName(); + }else{ + parameters[CbcParam::SOLUTIONBINARYFILE]->setFileName(fileName); } + ClpParamUtils::saveSolution(lpSolver, fileName); break; - case CLP_PARAM_ACTION_DUMMY: - break; - case CLP_PARAM_ACTION_ENVIRONMENT: - CbcOrClpEnvironmentIndex = 0; - break; - case CLP_PARAM_ACTION_PARAMETRICS: - if (goodModel) { - // get next field - field = CoinReadGetString(argc, argv); - if (field == "$") { - field = parameters_[iParam].stringValue(); - } else if (field == "EOL") { - parameters_[iParam].printString(); - break; - } else { - parameters_[iParam].setStringValue(field); - } - std::string fileName; - //bool canOpen = false; - if (field[0] == '/' || field[0] == '\\') { - fileName = field; - } else if (field[0] == '~') { - char *environVar = getenv("HOME"); - if (environVar) { - std::string home(environVar); - field = field.erase(0, 1); - fileName = home + field; - } else { - fileName = field; - } - } else { - fileName = directory + field; - } - static_cast< ClpSimplexOther * >(lpSolver)->parametrics(fileName.c_str()); - time2 = CoinCpuTime(); - totalTime += time2 - time1; - time1 = time2; - } else { - sprintf(generalPrint, "** Current model not valid"); - printGeneralMessage(model_, generalPrint); + case CbcParam::ENVIRONMENT: { +#if !defined(_MSC_VER) && !defined(__MSVCRT__) + // Don't think it will work with Visual Studio + char *input = getenv("CBC_ENVIRONMENT"); + if (input){ + while (!inputQueue.empty()){ + inputQueue.pop_front(); + } + std::istringstream inputStream(input); + CoinParamUtils::readFromStream(inputQueue, inputStream); } - break; - case CLP_PARAM_ACTION_GUESS: - if (goodModel && model_.solver()) { - delete[] alternativeEnvironment; - OsiClpSolverInterface *clpSolver = dynamic_cast< OsiClpSolverInterface * >(model_.solver()); - assert(clpSolver); - lpSolver = clpSolver->getModelPtr(); - assert(lpSolver); - ClpSimplexOther *model2 = static_cast< ClpSimplexOther * >(lpSolver); - alternativeEnvironment = model2->guess(1); - if (alternativeEnvironment) - CbcOrClpEnvironmentIndex = 0; - else - std::cout << "** Guess unable to generate commands" << std::endl; - } else { - std::cout << "** Guess needs a valid model" << std::endl; +#else + std::cout << "** Parameter not valid on Windows with Visual Studio" + << std::endl; +#endif } break; + case CbcParam::DUMMY: + break; default: - abort(); - } - } - } else if (!numberMatches) { - std::cout << "No match for " << field << " - ? for list of commands" - << std::endl; - } else if (numberMatches == 1) { - if (!numberQuery) { - std::cout << "Short match for " << field << " - completion: "; - std::cout << parameters_[firstMatch].matchName() << std::endl; - } else if (numberQuery) { - std::cout << parameters_[firstMatch].matchName() << " : "; - std::cout << parameters_[firstMatch].shortHelp() << std::endl; - if (numberQuery >= 2) - parameters_[firstMatch].printLongHelp(); - } - } else { - if (!numberQuery) - std::cout << "Multiple matches for " << field << " - possible completions:" - << std::endl; - else - std::cout << "Completions of " << field << ":" << std::endl; - for (iParam = 0; iParam < (int)parameters_.size(); iParam++) { - int match = parameters_[iParam].matches(field); - if (match && parameters_[iParam].displayThis()) { - std::cout << parameters_[iParam].matchName(); - if (numberQuery >= 2) - std::cout << " : " << parameters_[iParam].shortHelp(); - std::cout << std::endl; + // abort(); + break; } } +#if 0 } +#endif } delete coinModel; } #if CBC_QUIET == 0 - sprintf(generalPrint, - "Total time (CPU seconds): %.2f (Wallclock seconds): %.2f\n", - CoinCpuTime() - time0, - CoinGetTimeOfDay() - time0Elapsed); - generalMessageHandler->message(CLP_GENERAL, generalMessages) - << generalPrint - << CoinMessageEol; -#endif -#ifdef CBC_HAS_GLPK - if (cbc_glp_prob) { + buffer.str(""); + buffer << "Total time (CPU seconds): " << CoinCpuTime() - time0 + << " (Wallclock seconds): " + << CoinGetTimeOfDay() - time0Elapsed << std::endl; + printGeneralMessage(model_, buffer.str()); +#endif +#ifdef COINUTILS_HAS_GLPK + if (coin_glp_prob) { // free up as much as possible - glp_free(cbc_glp_prob); - glp_mpl_free_wksp(cbc_glp_tran); + glp_free(coin_glp_prob); + glp_mpl_free_wksp(coin_glp_tran); glp_free_env(); - cbc_glp_prob = NULL; - cbc_glp_tran = NULL; + coin_glp_prob = NULL; + coin_glp_tran = NULL; } #endif delete[] lotsize; @@ -11043,229 +11148,97 @@ clp watson.mps -\nscaling off\nprimalsimplex"); delete[] statistics_name_generators; // By now all memory should be freed #ifdef DMALLOC - //dmalloc_log_unfreed(); - //dmalloc_shutdown(); + // dmalloc_log_unfreed(); + // dmalloc_shutdown(); #endif if (babModel_) { model_.moveInfo(*babModel_); #ifndef CBC_OTHER_SOLVER - OsiClpSolverInterface *clpSolver0 = dynamic_cast< OsiClpSolverInterface * >(babModel_->solver()); + OsiClpSolverInterface *clpSolver0 = + dynamic_cast(babModel_->solver()); ClpSimplex *lpSolver0 = clpSolver0->getModelPtr(); - OsiClpSolverInterface *clpSolver = dynamic_cast< OsiClpSolverInterface * >(model_.solver()); + OsiClpSolverInterface *clpSolver = + dynamic_cast(model_.solver()); ClpSimplex *lpSolver = clpSolver->getModelPtr(); if (lpSolver0 != lpSolver && lpSolver != originalSolver->getModelPtr()) lpSolver->moveInfo(*lpSolver0); - //babModel_->setModelOwnsSolver(false); + // babModel_->setModelOwnsSolver(false); #endif } - delete babModel_; + delete babModel_; babModel_ = NULL; model_.solver()->setWarmStart(NULL); - //sprintf(generalPrint, "Total time %.2f", CoinCpuTime() - time0); - //generalMessageHandler->message(CLP_GENERAL, generalMessages) + buffer.str(""); + buffer << "Total time " << CoinCpuTime() - time0; + // generalMessageHandler->message(CLP_GENERAL, generalMessages) //<< generalPrint //<< CoinMessageEol; return 0; } -int CbcMain(int argc, const char *argv[], - CbcModel &model) -{ - CbcSolverUsefulData cbcData; - cbcData.noPrinting_ = false; - CbcMain0(model, cbcData); - return CbcMain1(argc, argv, model, dummyCallBack, cbcData); -} +//########################################################################### +//########################################################################### -void CbcMain0(CbcModel &model, - CbcSolverUsefulData ¶meterData) +int cbcReadAmpl(ampl_info *info, int argc, char **argv, CbcModel &model) { -#ifdef HAVE_SIGNAL_H -#ifdef HAVE_EXECINFO_H - signal(SIGSEGV, CbcCrashHandler); - signal(SIGABRT, CbcCrashHandler); - signal(SIGFPE, CbcCrashHandler); - -#endif -#endif - - std::vector< CbcOrClpParam > ¶meters = parameterData.parameters_; - -#ifndef CBC_OTHER_SOLVER - OsiClpSolverInterface *originalSolver = dynamic_cast< OsiClpSolverInterface * >(model.solver()); -#elif CBC_OTHER_SOLVER == 1 - OsiCpxSolverInterface *originalSolver = dynamic_cast< OsiCpxSolverInterface * >(model.solver()); - // Dummy solvers - OsiClpSolverInterface dummySolver; - ClpSimplex *lpSolver = dummySolver.getModelPtr(); - OsiCpxSolverInterface *clpSolver = originalSolver; -#endif - assert(originalSolver); - CoinMessageHandler *generalMessageHandler = originalSolver->messageHandler(); - generalMessageHandler->setPrefix(true); -#ifndef CBC_OTHER_SOLVER - OsiSolverInterface *solver = model.solver(); - OsiClpSolverInterface *clpSolver = dynamic_cast< OsiClpSolverInterface * >(solver); - ClpSimplex *lpSolver = clpSolver->getModelPtr(); - lpSolver->setPerturbation(50); - lpSolver->messageHandler()->setPrefix(false); -#endif - //establishParams(numberParameters, parameters) ; - const char dirsep = CoinFindDirSeparator(); - std::string directory; - std::string dirSample; - std::string dirNetlib; - std::string dirMiplib; - if (dirsep == '/') { - directory = "./"; - dirSample = "../../Data/Sample/"; - dirNetlib = "../../Data/Netlib/"; - dirMiplib = "../../Data/miplib3/"; - } else { - directory = ".\\"; - dirSample = "..\\..\\..\\..\\Data\\Sample\\"; - dirNetlib = "..\\..\\..\\..\\Data\\Netlib\\"; - dirMiplib = "..\\..\\..\\..\\Data\\miplib3\\"; - } - std::string defaultDirectory = directory; - std::string importFile = ""; - std::string exportFile = "default.mps"; - std::string importBasisFile = ""; - std::string importPriorityFile = ""; - std::string debugFile = ""; - std::string printMask = ""; - std::string exportBasisFile = "default.bas"; - std::string saveFile = "default.prob"; - std::string restoreFile = "default.prob"; - std::string solutionFile = "stdout"; - std::string solutionSaveFile = "solution.file"; - int doIdiot = -1; - int outputFormat = 2; - int substitution = 3; - int dualize = 3; - int preSolve = 5; - int doSprint = -1; - int testOsiParameters = -1; - parameters[whichParam(CLP_PARAM_ACTION_BASISIN, parameters)].setStringValue(importBasisFile); - parameters[whichParam(CBC_PARAM_ACTION_PRIORITYIN, parameters)].setStringValue(importPriorityFile); - parameters[whichParam(CLP_PARAM_ACTION_BASISOUT, parameters)].setStringValue(exportBasisFile); - parameters[whichParam(CLP_PARAM_ACTION_DEBUG, parameters)].setStringValue(debugFile); - parameters[whichParam(CLP_PARAM_ACTION_PRINTMASK, parameters)].setStringValue(printMask); - parameters[whichParam(CLP_PARAM_ACTION_DIRECTORY, parameters)].setStringValue(directory); - parameters[whichParam(CLP_PARAM_ACTION_DIRSAMPLE, parameters)].setStringValue(dirSample); - parameters[whichParam(CLP_PARAM_ACTION_DIRNETLIB, parameters)].setStringValue(dirNetlib); - parameters[whichParam(CBC_PARAM_ACTION_DIRMIPLIB, parameters)].setStringValue(dirMiplib); - parameters[whichParam(CLP_PARAM_DBL_DUALBOUND, parameters)].setDoubleValue(lpSolver->dualBound()); - parameters[whichParam(CLP_PARAM_DBL_DUALTOLERANCE, parameters)].setDoubleValue(lpSolver->dualTolerance()); - parameters[whichParam(CLP_PARAM_ACTION_EXPORT, parameters)].setStringValue(exportFile); - parameters[whichParam(CLP_PARAM_INT_IDIOT, parameters)].setIntValue(doIdiot); - parameters[whichParam(CLP_PARAM_ACTION_IMPORT, parameters)].setStringValue(importFile); - parameters[whichParam(CLP_PARAM_DBL_PRESOLVETOLERANCE, parameters)].setDoubleValue(1.0e-8); - int slog = whichParam(CLP_PARAM_INT_SOLVERLOGLEVEL, parameters); - int log = whichParam(CLP_PARAM_INT_LOGLEVEL, parameters); - parameters[slog].setIntValue(1); - clpSolver->messageHandler()->setLogLevel(1); - model.messageHandler()->setLogLevel(1); - lpSolver->setLogLevel(1); - parameters[log].setIntValue(1); - parameters[whichParam(CLP_PARAM_INT_MAXFACTOR, parameters)].setIntValue(lpSolver->factorizationFrequency()); - parameters[whichParam(CLP_PARAM_INT_MAXITERATION, parameters)].setIntValue(lpSolver->maximumIterations()); - parameters[whichParam(CLP_PARAM_INT_OUTPUTFORMAT, parameters)].setIntValue(outputFormat); - parameters[whichParam(CLP_PARAM_INT_PRESOLVEPASS, parameters)].setIntValue(preSolve); - parameters[whichParam(CLP_PARAM_INT_PERTVALUE, parameters)].setIntValue(lpSolver->perturbation()); - parameters[whichParam(CLP_PARAM_DBL_PRIMALTOLERANCE, parameters)].setDoubleValue(lpSolver->primalTolerance()); - parameters[whichParam(CLP_PARAM_DBL_PRIMALWEIGHT, parameters)].setDoubleValue(lpSolver->infeasibilityCost()); - parameters[whichParam(CLP_PARAM_ACTION_RESTORE, parameters)].setStringValue(restoreFile); - parameters[whichParam(CLP_PARAM_ACTION_SAVE, parameters)].setStringValue(saveFile); - //parameters[whichParam(CLP_PARAM_DBL_TIMELIMIT,numberParameters,parameters)].setDoubleValue(1.0e8); - parameters[whichParam(CBC_PARAM_DBL_TIMELIMIT_BAB, parameters)].setDoubleValue(1.0e8); - parameters[whichParam(CLP_PARAM_ACTION_SOLUTION, parameters)].setStringValue(solutionFile); - parameters[whichParam(CLP_PARAM_ACTION_NEXTBESTSOLUTION, parameters)].setStringValue(solutionFile); - parameters[whichParam(CLP_PARAM_ACTION_SAVESOL, parameters)].setStringValue(solutionSaveFile); - parameters[whichParam(CLP_PARAM_INT_SPRINT, parameters)].setIntValue(doSprint); - parameters[whichParam(CLP_PARAM_INT_SUBSTITUTION, parameters)].setIntValue(substitution); - parameters[whichParam(CLP_PARAM_INT_DUALIZE, parameters)].setIntValue(dualize); - model.setNumberBeforeTrust(10); - parameters[whichParam(CBC_PARAM_INT_NUMBERBEFORE, parameters)].setIntValue(5); - parameters[whichParam(CBC_PARAM_INT_MAXNODES, parameters)].setIntValue(model.getMaximumNodes()); - model.setNumberStrong(5); - parameters[whichParam(CBC_PARAM_INT_STRONGBRANCHING, parameters)].setIntValue(model.numberStrong()); - parameters[whichParam(CBC_PARAM_DBL_INFEASIBILITYWEIGHT, parameters)].setDoubleValue(model.getDblParam(CbcModel::CbcInfeasibilityWeight)); - parameters[whichParam(CBC_PARAM_DBL_INTEGERTOLERANCE, parameters)].setDoubleValue(model.getDblParam(CbcModel::CbcIntegerTolerance)); - parameters[whichParam(CBC_PARAM_DBL_INCREMENT, parameters)].setDoubleValue(model.getDblParam(CbcModel::CbcCutoffIncrement)); - parameters[whichParam(CBC_PARAM_INT_TESTOSI, parameters)].setIntValue(testOsiParameters); - parameters[whichParam(CBC_PARAM_INT_FPUMPTUNE, parameters)].setIntValue(1003); - initialPumpTune = 1003; -#ifdef CBC_THREAD - parameters[whichParam(CBC_PARAM_INT_THREADS, parameters)].setIntValue(0); -#endif - // Set up likely cut generators and defaults - parameters[whichParam(CBC_PARAM_STR_CLIQUECUTS, parameters)].setCurrentOption("ifmove"); - parameters[whichParam(CBC_PARAM_STR_ODDWHEELCUTS, parameters)].setCurrentOption("ifmove"); - parameters[whichParam(CBC_PARAM_STR_CLQSTRENGTHENING, parameters)].setCurrentOption("after"); - parameters[whichParam(CBC_PARAM_STR_USECGRAPH, parameters)].setCurrentOption("on"); - parameters[whichParam(CBC_PARAM_INT_BKPIVOTINGSTRATEGY, parameters)].setIntValue(3); - parameters[whichParam(CBC_PARAM_INT_BKMAXCALLS, parameters)].setIntValue(1000); - parameters[whichParam(CBC_PARAM_INT_BKCLQEXTMETHOD, parameters)].setIntValue(4); - parameters[whichParam(CBC_PARAM_INT_ODDWEXTMETHOD, parameters)].setIntValue(2); - parameters[whichParam(CBC_PARAM_STR_PREPROCESS, parameters)].setCurrentOption("sos"); - parameters[whichParam(CBC_PARAM_INT_MIPOPTIONS, parameters)].setIntValue(1057); - parameters[whichParam(CBC_PARAM_INT_CUTPASSINTREE, parameters)].setIntValue(1); - parameters[whichParam(CBC_PARAM_INT_MOREMIPOPTIONS, parameters)].setIntValue(-1); - parameters[whichParam(CBC_PARAM_INT_MAXHOTITS, parameters)].setIntValue(100); - parameters[whichParam(CBC_PARAM_STR_CUTSSTRATEGY, parameters)].setCurrentOption("on"); - parameters[whichParam(CBC_PARAM_STR_HEURISTICSTRATEGY, parameters)].setCurrentOption("on"); - parameters[whichParam(CBC_PARAM_STR_NODESTRATEGY, parameters)].setCurrentOption("fewest"); - parameters[whichParam(CBC_PARAM_STR_GOMORYCUTS, parameters)].setCurrentOption("ifmove"); - parameters[whichParam(CBC_PARAM_STR_PROBINGCUTS, parameters)].setCurrentOption("ifmove"); - parameters[whichParam(CBC_PARAM_STR_KNAPSACKCUTS, parameters)].setCurrentOption("ifmove"); - parameters[whichParam(CBC_PARAM_STR_ZEROHALFCUTS, parameters)].setCurrentOption("ifmove"); - parameters[whichParam(CBC_PARAM_STR_REDSPLITCUTS, parameters)].setCurrentOption("off"); - parameters[whichParam(CBC_PARAM_STR_REDSPLIT2CUTS, parameters)].setCurrentOption("off"); - parameters[whichParam(CBC_PARAM_STR_GMICUTS, parameters)].setCurrentOption("off"); - parameters[whichParam(CBC_PARAM_STR_MIXEDCUTS, parameters)].setCurrentOption("ifmove"); - parameters[whichParam(CBC_PARAM_STR_FLOWCUTS, parameters)].setCurrentOption("ifmove"); - parameters[whichParam(CBC_PARAM_STR_TWOMIRCUTS, parameters)].setCurrentOption("root"); - parameters[whichParam(CBC_PARAM_STR_LANDPCUTS, parameters)].setCurrentOption("off"); - parameters[whichParam(CBC_PARAM_STR_RESIDCUTS, parameters)].setCurrentOption("off"); - parameters[whichParam(CBC_PARAM_STR_ROUNDING, parameters)].setCurrentOption("on"); - parameters[whichParam(CBC_PARAM_STR_FPUMP, parameters)].setCurrentOption("on"); - parameters[whichParam(CBC_PARAM_STR_GREEDY, parameters)].setCurrentOption("on"); - parameters[whichParam(CBC_PARAM_STR_COMBINE, parameters)].setCurrentOption("off"); - parameters[whichParam(CBC_PARAM_STR_CROSSOVER2, parameters)].setCurrentOption("off"); - parameters[whichParam(CBC_PARAM_STR_PIVOTANDCOMPLEMENT, parameters)].setCurrentOption("off"); - parameters[whichParam(CBC_PARAM_STR_PIVOTANDFIX, parameters)].setCurrentOption("off"); - parameters[whichParam(CBC_PARAM_STR_RANDROUND, parameters)].setCurrentOption("off"); - parameters[whichParam(CBC_PARAM_STR_NAIVE, parameters)].setCurrentOption("off"); - parameters[whichParam(CBC_PARAM_STR_RINS, parameters)].setCurrentOption("off"); - parameters[whichParam(CBC_PARAM_STR_DINS, parameters)].setCurrentOption("off"); - parameters[whichParam(CBC_PARAM_STR_RENS, parameters)].setCurrentOption("off"); - parameters[whichParam(CBC_PARAM_STR_LOCALTREE, parameters)].setCurrentOption("off"); - parameters[whichParam(CBC_PARAM_STR_COSTSTRATEGY, parameters)].setCurrentOption("off"); -#ifdef CBC_HAS_NAUTY - parameters[whichParam(CBC_PARAM_STR_ORBITAL, parameters)].setCurrentOption("on"); -#endif + OsiSolverInterface *solver = model.solver(); + memset(&info, 0, sizeof(info)); + if (argc > 2 && !strcmp(argv[2], "-AMPL")) { + // see if log in list + bool noPrinting = true; + for (int i = 1; i < argc; i++) { + if (!strncmp(argv[i], "log", 3)) { + const char *equals = strchr(argv[i], '='); + if (equals && atoi(equals + 1) > 0) { + noPrinting = false; + info->logLevel = atoi(equals + 1); + // mark so won't be overWritten + info->numberRows = -1234567; + break; + } + } + } + + void *voidModel; + int returnCode = readAmpl(info, argc, const_cast(argv), + &voidModel, "cbc"); + if (returnCode){ + return returnCode; + } + // see if log in list (including environment) + for (int i = 1; i < info->numberArguments; i++) { + if (!strcmp(info->arguments[i], "log")) { + if (i < info->numberArguments - 1 && atoi(info->arguments[i + 1]) > 0) + noPrinting = false; + break; + } + } + if (noPrinting) { + model.messageHandler()->setLogLevel(0); + } + if (!noPrinting){ + printf("%d rows, %d columns and %d elements\n", info->numberRows, + info->numberColumns, info->numberElements); + } + } + return 0; } -/* - Routines to print statistics. -*/ -static void breakdown(const char *name, int numberLook, const double *region) -{ +//########################################################################### +// Routines to print statistics. +//########################################################################### + +static void breakdown(const char *name, int numberLook, const double *region) { double range[] = { - -COIN_DBL_MAX, - -1.0e15, -1.0e11, -1.0e8, -1.0e5, -1.0e4, -1.0e3, -1.0e2, -1.0e1, - -1.0, - -1.0e-1, -1.0e-2, -1.0e-3, -1.0e-4, -1.0e-5, -1.0e-8, -1.0e-11, -1.0e-15, - 0.0, - 1.0e-15, 1.0e-11, 1.0e-8, 1.0e-5, 1.0e-4, 1.0e-3, 1.0e-2, 1.0e-1, - 1.0, - 1.0e1, 1.0e2, 1.0e3, 1.0e4, 1.0e5, 1.0e8, 1.0e11, 1.0e15, - COIN_DBL_MAX - }; - int nRanges = static_cast< int >(sizeof(range) / sizeof(double)); + -COIN_DBL_MAX, -1.0e15, -1.0e11, -1.0e8, -1.0e5, -1.0e4, -1.0e3, + -1.0e2, -1.0e1, -1.0, -1.0e-1, -1.0e-2, -1.0e-3, -1.0e-4, + -1.0e-5, -1.0e-8, -1.0e-11, -1.0e-15, 0.0, 1.0e-15, 1.0e-11, + 1.0e-8, 1.0e-5, 1.0e-4, 1.0e-3, 1.0e-2, 1.0e-1, 1.0, + 1.0e1, 1.0e2, 1.0e3, 1.0e4, 1.0e5, 1.0e8, 1.0e11, + 1.0e15, COIN_DBL_MAX}; + int nRanges = static_cast(sizeof(range) / sizeof(double)); int *number = new int[nRanges]; memset(number, 0, nRanges * sizeof(int)); int *numberExact = new int[nRanges]; @@ -11298,14 +11271,8 @@ static void breakdown(const char *name, int numberLook, const double *region) delete[] number; delete[] numberExact; } -static void sortOnOther(int *column, - const CoinBigIndex *rowStart, - int *order, - int *other, - int nRow, - int nInRow, - int where) -{ +static void sortOnOther(int *column, const CoinBigIndex *rowStart, int *order, + int *other, int nRow, int nInRow, int where) { if (nRow < 2 || where >= nInRow) return; // do initial sort @@ -11334,14 +11301,17 @@ static void sortOnOther(int *column, break; } // sort - sortOnOther(column, rowStart, order + first, other, kRow - first, - nInRow, where + 1); + sortOnOther(column, rowStart, order + first, other, kRow - first, nInRow, + where + 1); firstC = lastC; first = kRow; } } -static void statistics(ClpSimplex *originalModel, ClpSimplex *model) -{ + +//########################################################################### +//########################################################################### + +static void statistics(ClpSimplex *originalModel, ClpSimplex *model) { int numberColumns = originalModel->numberColumns(); const char *integerInformation = originalModel->integerInformation(); const double *columnLower = originalModel->columnLower(); @@ -11360,7 +11330,7 @@ static void statistics(ClpSimplex *originalModel, ClpSimplex *model) } } printf("Original problem has %d integers (%d of which binary)\n", - numberIntegers, numberBinary); + numberIntegers, numberBinary); } numberColumns = model->numberColumns(); int numberRows = model->numberRows(); @@ -11386,7 +11356,7 @@ static void statistics(ClpSimplex *originalModel, ClpSimplex *model) } if (numberColumns != originalModel->numberColumns()) printf("Presolved problem has %d integers (%d of which binary)\n", - numberIntegers, numberBinary); + numberIntegers, numberBinary); for (int ifInt = 0; ifInt < 2; ifInt++) { for (int ifAbs = 0; ifAbs < 2; ifAbs++) { int numberSort = 0; @@ -11395,7 +11365,8 @@ static void statistics(ClpSimplex *originalModel, ClpSimplex *model) for (int iColumn = 0; iColumn < numberColumns; iColumn++) { if (columnUpper[iColumn] > columnLower[iColumn]) { if (!ifInt || integerInformation[iColumn]) { - obj[numberSort] = (ifAbs) ? fabs(objective[iColumn]) : objective[iColumn]; + obj[numberSort] = + (ifAbs) ? fabs(objective[iColumn]) : objective[iColumn]; which[numberSort++] = iColumn; if (!objective[iColumn]) numberZero++; @@ -11436,26 +11407,28 @@ static void statistics(ClpSimplex *originalModel, ClpSimplex *model) double last = obj[0]; for (int jColumn = 1; jColumn < numberSort; jColumn++) { if (fabs(obj[jColumn] - last) > 1.0e-12) { - printf("%d variables have objective of %g\n", - jColumn - iLast, last); + printf("%d variables have objective of %g\n", jColumn - iLast, + last); iLast = jColumn; last = obj[jColumn]; } } - printf("%d variables have objective of %g\n", - numberSort - iLast, last); + printf("%d variables have objective of %g\n", numberSort - iLast, + last); if (saveModel) { int spaceNeeded = numberSort + numberDifferentObj; - CoinBigIndex *columnAddDummy = new CoinBigIndex[numberDifferentObj + 1]; + CoinBigIndex *columnAddDummy = + new CoinBigIndex[numberDifferentObj + 1]; int *columnAdd = new int[spaceNeeded]; double *elementAdd = new double[spaceNeeded]; CoinBigIndex *rowAdd = new CoinBigIndex[2 * numberDifferentObj + 1]; - int *newIsInteger = reinterpret_cast< int * >(rowAdd + numberDifferentObj + 1); + int *newIsInteger = + reinterpret_cast(rowAdd + numberDifferentObj + 1); double *objectiveNew = new double[3 * numberDifferentObj]; double *lowerNew = objectiveNew + numberDifferentObj; double *upperNew = lowerNew + numberDifferentObj; memset(columnAddDummy, 0, - (numberDifferentObj + 1) * sizeof(CoinBigIndex)); + (numberDifferentObj + 1) * sizeof(CoinBigIndex)); ClpSimplex tempModel = *model; int iLast = 0; double last = obj[0]; @@ -11464,7 +11437,8 @@ static void statistics(ClpSimplex *originalModel, ClpSimplex *model) rowAdd[0] = 0; double *objective = tempModel.objective(); for (int jColumn = 1; jColumn < numberSort + 1; jColumn++) { - if (jColumn == numberSort || fabs(obj[jColumn] - last) > 1.0e-12) { + if (jColumn == numberSort || + fabs(obj[jColumn] - last) > 1.0e-12) { // not if just one if (jColumn - iLast > 1) { bool allInteger = integerInformation != NULL; @@ -11478,7 +11452,8 @@ static void statistics(ClpSimplex *originalModel, ClpSimplex *model) double lowerValue = columnLower[iColumn]; double upperValue = columnUpper[iColumn]; double elementValue = -1.0; - if (objectiveNew[numberDifferentObj] * objective[iColumn] < 0.0) { + if (objectiveNew[numberDifferentObj] * objective[iColumn] < + 0.0) { lowerValue = -columnUpper[iColumn]; upperValue = -columnLower[iColumn]; elementValue = 1.0; @@ -11500,7 +11475,8 @@ static void statistics(ClpSimplex *originalModel, ClpSimplex *model) upper = COIN_DBL_MAX; } } - columnAdd[numberElements] = numberColumns + numberDifferentObj; + columnAdd[numberElements] = + numberColumns + numberDifferentObj; elementAdd[numberElements++] = 1.0; newIsInteger[numberDifferentObj] = (allInteger) ? 1 : 0; lowerNew[numberDifferentObj] = lower; @@ -11514,8 +11490,7 @@ static void statistics(ClpSimplex *originalModel, ClpSimplex *model) } // add columns tempModel.addColumns(numberDifferentObj, lowerNew, upperNew, - objectiveNew, - columnAddDummy, NULL, NULL); + objectiveNew, columnAddDummy, NULL, NULL); // add constraints and make integer if all integer in group for (int iObj = 0; iObj < numberDifferentObj; iObj++) { lowerNew[iObj] = 0.0; @@ -11523,8 +11498,8 @@ static void statistics(ClpSimplex *originalModel, ClpSimplex *model) if (newIsInteger[iObj]) tempModel.setInteger(numberColumns + iObj); } - tempModel.addRows(numberDifferentObj, lowerNew, upperNew, - rowAdd, columnAdd, elementAdd); + tempModel.addRows(numberDifferentObj, lowerNew, upperNew, rowAdd, + columnAdd, elementAdd); delete[] columnAdd; delete[] columnAddDummy; delete[] elementAdd; @@ -11549,7 +11524,7 @@ static void statistics(ClpSimplex *originalModel, ClpSimplex *model) CoinPackedMatrix *matrix = model->matrix(); CoinBigIndex numberElements = matrix->getNumElements(); const int *columnLength = matrix->getVectorLengths(); - //const CoinBigIndex * columnStart = matrix->getVectorStarts(); + // const CoinBigIndex * columnStart = matrix->getVectorStarts(); const double *elementByColumn = matrix->getElements(); int *number = new int[numberRows + 1]; memset(number, 0, (numberRows + 1) * sizeof(int)); @@ -11559,8 +11534,9 @@ static void statistics(ClpSimplex *originalModel, ClpSimplex *model) 8 0/1 */ int cType[9]; - std::string cName[] = { "0.0->inf,", "0.0->up,", "lo->inf,", "lo->up,", "free,", "fixed,", "-inf->0.0,", - "-inf->up,", "0.0->1.0" }; + std::string cName[] = {"0.0->inf,", "0.0->up,", "lo->inf,", + "lo->up,", "free,", "fixed,", + "-inf->0.0,", "-inf->up,", "0.0->1.0"}; int nObjective = 0; memset(cType, 0, sizeof(cType)); for (iColumn = 0; iColumn < numberColumns; iColumn++) { @@ -11602,8 +11578,10 @@ static void statistics(ClpSimplex *originalModel, ClpSimplex *model) 7 L 0, 8 L 1, 9 L other, 10 Range 0/1, 11 Range other, 12 free */ int rType[13]; - std::string rName[] = { "E 0.0,", "E 1.0,", "E -1.0,", "E other,", "G 0.0,", "G 1.0,", "G other,", - "L 0.0,", "L 1.0,", "L other,", "Range 0.0->1.0,", "Range other,", "Free" }; + std::string rName[] = { + "E 0.0,", "E 1.0,", "E -1.0,", "E other,", "G 0.0,", + "G 1.0,", "G other,", "L 0.0,", "L 1.0,", "L other,", + "Range 0.0->1.0,", "Range other,", "Free"}; memset(rType, 0, sizeof(rType)); for (iRow = 0; iRow < numberRows; iRow++) { if (rowLower[iRow] > -1.0e20) { @@ -11650,8 +11628,9 @@ static void statistics(ClpSimplex *originalModel, ClpSimplex *model) } } // Basic statistics - printf("\n\nProblem has %d rows, %d columns (%d with objective) and %d elements\n", - numberRows, numberColumns, nObjective, numberElements); + printf("\n\nProblem has %d rows, %d columns (%d with objective) and %d " + "elements\n", + numberRows, numberColumns, nObjective, numberElements); if (number[0] + number[1]) { printf("There are "); if (numberObjSingletons) @@ -11665,7 +11644,7 @@ static void statistics(ClpSimplex *originalModel, ClpSimplex *model) } printf("Column breakdown:\n"); int k; - for (k = 0; k < static_cast< int >(sizeof(cType) / sizeof(int)); k++) { + for (k = 0; k < static_cast(sizeof(cType) / sizeof(int)); k++) { printf("%d of type %s ", cType[k], cName[k].c_str()); if (((k + 1) % 3) == 0) printf("\n"); @@ -11673,7 +11652,7 @@ static void statistics(ClpSimplex *originalModel, ClpSimplex *model) if ((k % 3) != 0) printf("\n"); printf("Row breakdown:\n"); - for (k = 0; k < static_cast< int >(sizeof(rType) / sizeof(int)); k++) { + for (k = 0; k < static_cast(sizeof(rType) / sizeof(int)); k++) { printf("%d of type %s ", rType[k], rName[k].c_str()); if (((k + 1) % 3) == 0) printf("\n"); @@ -11723,7 +11702,7 @@ static void statistics(ClpSimplex *originalModel, ClpSimplex *model) printf("\n\n"); if (model->logLevel() == 63 #ifdef SYM - || true + || true #endif ) { // get column copy @@ -11759,8 +11738,8 @@ static void statistics(ClpSimplex *originalModel, ClpSimplex *model) if (number[iRow]) { printf("XX %d columns have %d entries\n", number[iRow], iRow); int kColumn = jColumn + number[iRow]; - sortOnOther(row, columnStart, - order + jColumn, other, number[iRow], iRow, 0); + sortOnOther(row, columnStart, order + jColumn, other, number[iRow], + iRow, 0); // Now print etc if (iRow < 500000) { for (int lColumn = jColumn; lColumn < kColumn; lColumn++) { @@ -11811,15 +11790,18 @@ static void statistics(ClpSimplex *originalModel, ClpSimplex *model) double element1 = element[columnStart[iColumn] + 1]; int n0 = rowLength[iRow0]; int n1 = rowLength[iRow1]; - printf("Doubleton free %d - cost %g - %g in %srow with %d entries and %g in %srow with %d entries\n", - iColumn, objective[iColumn], element0, (rowLower[iRow0] == rowUpper[iRow0]) ? "==" : "", n0, - element1, (rowLower[iRow1] == rowUpper[iRow1]) ? "==" : "", n1); + printf("Doubleton free %d - cost %g - %g in %srow with %d entries " + "and %g in %srow with %d entries\n", + iColumn, objective[iColumn], element0, + (rowLower[iRow0] == rowUpper[iRow0]) ? "==" : "", n0, element1, + (rowLower[iRow1] == rowUpper[iRow1]) ? "==" : "", n1); } } if (length == 1) { int iRow = row[columnStart[iColumn]]; double value = COIN_DBL_MAX; - for (CoinBigIndex i = rowStart[iRow]; i < rowStart[iRow] + rowLength[iRow]; i++) { + for (CoinBigIndex i = rowStart[iRow]; + i < rowStart[iRow] + rowLength[iRow]; i++) { int jColumn = column[i]; if (jColumn != iColumn) { if (value != elementByRow[i]) { @@ -11834,27 +11816,32 @@ static void statistics(ClpSimplex *originalModel, ClpSimplex *model) } if (!objective[iColumn]) { if (model->logLevel() > 4) - printf("Singleton %d with no objective in row with %d elements - rhs %g,%g\n", iColumn, rowLength[iRow], rowLower[iRow], rowUpper[iRow]); + printf("Singleton %d with no objective in row with %d elements - " + "rhs %g,%g\n", + iColumn, rowLength[iRow], rowLower[iRow], rowUpper[iRow]); nPossibleZeroCost++; } else if (value != -COIN_DBL_MAX) { if (model->logLevel() > 4) - printf("Singleton %d (%s) with objective in row %d (%s) with %d equal elements - rhs %g,%g\n", iColumn, model->getColumnName(iColumn).c_str(), - iRow, model->getRowName(iRow).c_str(), - rowLength[iRow], rowLower[iRow], rowUpper[iRow]); + printf("Singleton %d (%s) with objective in row %d (%s) with %d " + "equal elements - rhs %g,%g\n", + iColumn, model->getColumnName(iColumn).c_str(), iRow, + model->getRowName(iRow).c_str(), rowLength[iRow], + rowLower[iRow], rowUpper[iRow]); nPossibleNonzeroCost++; } } } if (nPossibleZeroCost || nPossibleNonzeroCost) printf("%d singletons with zero cost, %d with valid cost\n", - nPossibleZeroCost, nPossibleNonzeroCost); + nPossibleZeroCost, nPossibleNonzeroCost); // look for DW - int *blockStart = new int[2 * (numberRows + numberColumns) + 1 + numberRows]; + int *blockStart = + new int[2 * (numberRows + numberColumns) + 1 + numberRows]; int *columnBlock = blockStart + numberRows; int *nextColumn = columnBlock + numberColumns; int *blockCount = nextColumn + numberColumns; int *blockEls = blockCount + numberRows + 1; - int direction[2] = { -1, 1 }; + int direction[2] = {-1, 1}; int bestBreak = -1; double bestValue = 0.0; int iPass = 0; @@ -11877,7 +11864,8 @@ static void statistics(ClpSimplex *originalModel, ClpSimplex *model) blockCount[i] = 0; for (int iRow = start; iRow != stop; iRow += increment) { int iBlock = -1; - for (CoinBigIndex j = rowStart[iRow]; j < rowStart[iRow] + rowLength[iRow]; j++) { + for (CoinBigIndex j = rowStart[iRow]; + j < rowStart[iRow] + rowLength[iRow]; j++) { int iColumn = column[j]; int whichColumnBlock = columnBlock[iColumn]; if (whichColumnBlock >= 0) { @@ -11903,7 +11891,7 @@ static void statistics(ClpSimplex *originalModel, ClpSimplex *model) } int n = numberMarkedColumns; if (iBlock < 0) { - //new block + // new block if (rowLength[iRow]) { numberBlocks++; iBlock = numberBlocks; @@ -11911,7 +11899,8 @@ static void statistics(ClpSimplex *originalModel, ClpSimplex *model) columnBlock[jColumn] = iBlock; blockStart[iBlock] = jColumn; numberMarkedColumns++; - for (CoinBigIndex j = rowStart[iRow] + 1; j < rowStart[iRow] + rowLength[iRow]; j++) { + for (CoinBigIndex j = rowStart[iRow] + 1; + j < rowStart[iRow] + rowLength[iRow]; j++) { int iColumn = column[j]; columnBlock[iColumn] = iBlock; numberMarkedColumns++; @@ -11926,7 +11915,8 @@ static void statistics(ClpSimplex *originalModel, ClpSimplex *model) } else { // put in existing block int jColumn = blockStart[iBlock]; - for (CoinBigIndex j = rowStart[iRow]; j < rowStart[iRow] + rowLength[iRow]; j++) { + for (CoinBigIndex j = rowStart[iRow]; + j < rowStart[iRow] + rowLength[iRow]; j++) { int iColumn = column[j]; assert(columnBlock[iColumn] < 0 || columnBlock[iColumn] == iBlock); if (columnBlock[iColumn] < 0) { @@ -11941,9 +11931,11 @@ static void statistics(ClpSimplex *originalModel, ClpSimplex *model) } maximumBlockSize = CoinMax(maximumBlockSize, blockCount[iBlock]); numberRowsDone++; - if (thisBestValue * numberRowsDone > maximumBlockSize && numberRowsDone > halfway) { + if (thisBestValue * numberRowsDone > maximumBlockSize && + numberRowsDone > halfway) { thisBestBreak = iRow; - thisBestValue = static_cast< double >(maximumBlockSize) / static_cast< double >(numberRowsDone); + thisBestValue = static_cast(maximumBlockSize) / + static_cast(numberRowsDone); } } if (thisBestBreak == stop) @@ -11964,7 +11956,7 @@ static void statistics(ClpSimplex *originalModel, ClpSimplex *model) } if (firstMaster < lastMaster) { printf("%d master rows %d <= < %d\n", lastMaster - firstMaster, - firstMaster, lastMaster); + firstMaster, lastMaster); for (int i = 0; i < numberRows + 2 * numberColumns; i++) blockStart[i] = -1; for (int i = firstMaster; i < lastMaster; i++) @@ -11984,7 +11976,8 @@ static void statistics(ClpSimplex *originalModel, ClpSimplex *model) blockCount[0] = firstRow; while (numberStack) { int iRow = blockCount[--numberStack]; - for (CoinBigIndex j = rowStart[iRow]; j < rowStart[iRow] + rowLength[iRow]; j++) { + for (CoinBigIndex j = rowStart[iRow]; + j < rowStart[iRow] + rowLength[iRow]; j++) { int iColumn = column[j]; int iBlock = columnBlock[iColumn]; if (iBlock < 0) { @@ -12053,10 +12046,11 @@ static void statistics(ClpSimplex *originalModel, ClpSimplex *model) bool useful = true; if (numberMaster > halfway || largestRows * 3 > numberRows) useful = false; - printf("%s %d blocks (largest %d,%d), %d master rows (%d empty) out of %d, %d master columns (%d empty) out of %d\n", - useful ? "**Useful" : "NoGood", - numberBlocks, largestRows, largestColumns, numberMaster, numberEmpty, numberRows, - numberMasterColumns, numberEmptyColumns, numberColumns); + printf("%s %d blocks (largest %d,%d), %d master rows (%d empty) out of " + "%d, %d master columns (%d empty) out of %d\n", + useful ? "**Useful" : "NoGood", numberBlocks, largestRows, + largestColumns, numberMaster, numberEmpty, numberRows, + numberMasterColumns, numberEmptyColumns, numberColumns); FILE *fp = NULL; bool justIntegers = true; bool oneFile = true; @@ -12069,8 +12063,8 @@ static void statistics(ClpSimplex *originalModel, ClpSimplex *model) if (logLevel == 19) justIntegers = false; for (int i = 0; i < numberBlocks; i++) - printf("Block %d has %d rows and %d columns (%d elements)\n", - i, blockCount[i], nextColumn[i], blockEls[i]); + printf("Block %d has %d rows and %d columns (%d elements)\n", i, + blockCount[i], nextColumn[i], blockEls[i]); if (logLevel >= 17 && logLevel <= 21) { int *whichRows = new int[numberRows + numberColumns]; int *whichColumns = whichRows + numberRows; @@ -12117,12 +12111,12 @@ static void statistics(ClpSimplex *originalModel, ClpSimplex *model) assert(fp); } fprintf(fp, "BBB objective %g for block %d\n", - smallModel.getObjValue(), iBlock); + smallModel.getObjValue(), iBlock); for (int jColumn = 0; jColumn < nColumns; jColumn++) { if (subset.isInteger(jColumn) || !justIntegers) fprintf(fp, " FX BOUND1 %.8s %g\n", - subset.getColumnName(jColumn).c_str(), - solution[jColumn]); + subset.getColumnName(jColumn).c_str(), + solution[jColumn]); } if (!oneFile) fclose(fp); @@ -12180,7 +12174,7 @@ static void statistics(ClpSimplex *originalModel, ClpSimplex *model) } if (model->logLevel() == 63 #ifdef SYM - || true + || true #endif ) { int *column = rowCopy.getMutableIndices(); @@ -12227,8 +12221,8 @@ static void statistics(ClpSimplex *originalModel, ClpSimplex *model) if (number[iColumn]) { printf("XX %d rows have %d entries\n", number[iColumn], iColumn); int kRow = jRow + number[iColumn]; - sortOnOther(column, rowStart, - order + jRow, other, number[iColumn], iColumn, 0); + sortOnOther(column, rowStart, order + jRow, other, number[iColumn], + iColumn, 0); // Now print etc if (iColumn < 500000) { int nLook = 0; @@ -12275,7 +12269,7 @@ static void statistics(ClpSimplex *originalModel, ClpSimplex *model) if (iLast >= 0) { int n = iLook - iLast; if (n > 1) { - //printf("%d rows possible?\n",n); + // printf("%d rows possible?\n",n); } } iLast = iLook; @@ -12326,7 +12320,7 @@ static void statistics(ClpSimplex *originalModel, ClpSimplex *model) if (iLast >= 0) { int n = iLook - iLast; if (n > 1) { - //printf("%d columns possible?\n",n); + // printf("%d columns possible?\n",n); } for (int i = iLast; i < iLook; i++) { possibleColumn[sortColumn[i]] = n; @@ -12345,8 +12339,8 @@ static void statistics(ClpSimplex *originalModel, ClpSimplex *model) double value = element[i]; jColumn = backColumn[jColumn]; sum += value * randomColumn[jColumn]; - //if (iColumn==23089||iRow==23729) - //printf("row %d cola %d colb %d value %g rand %g sum %g\n", + // if (iColumn==23089||iRow==23729) + // printf("row %d cola %d colb %d value %g rand %g sum %g\n", // iRow,jColumn,column[i],value,randomColumn[jColumn],sum); } sortRow[iRow] = iRow; @@ -12370,7 +12364,7 @@ static void statistics(ClpSimplex *originalModel, ClpSimplex *model) if (iLast >= 0) { int n = iLook - iLast; if (n > 1) { - //printf("%d rows possible?\n",n); + // printf("%d rows possible?\n",n); // Within group sort as for original "order" for (int i = iLast; i < iLook; i++) { int jRow = sortRow[i]; @@ -12399,7 +12393,7 @@ static void statistics(ClpSimplex *originalModel, ClpSimplex *model) } int n = numberPossible; if (numberPossible > 1) { - //printf("pppppossible %d\n",numberPossible); + // printf("pppppossible %d\n",numberPossible); for (int jLook = iLook + 1; jLook < iLook + numberPossible; jLook++) { int jRow = sortRow[jLook]; CoinBigIndex start2 = rowStart[jRow]; @@ -12435,7 +12429,7 @@ static void statistics(ClpSimplex *originalModel, ClpSimplex *model) numberIntegers++; } if (numberPossible > 1 && !numberIntegers) { - //printf("possible %d - but no integers\n",numberPossible); + // printf("possible %d - but no integers\n",numberPossible); } if (numberPossible > 1 && (numberIntegers || false)) { // @@ -12476,7 +12470,8 @@ static void statistics(ClpSimplex *originalModel, ClpSimplex *model) for (CoinBigIndex i = start1; i < start1 + length; i++) { int jColumn1 = column[i]; int jColumn2 = column[i + offset2]; - if (randomColumn[backColumn[jColumn1]] != randomColumn[backColumn[jColumn2]]) { + if (randomColumn[backColumn[jColumn1]] != + randomColumn[backColumn[jColumn2]]) { good = false; break; } @@ -12490,7 +12485,8 @@ static void statistics(ClpSimplex *originalModel, ClpSimplex *model) stackColumn[nStackC++] = jColumn1; } } else { - if (mapColumn[jColumn1] != jColumn2 || mapColumn[jColumn2] != jColumn1) { + if (mapColumn[jColumn1] != jColumn2 || + mapColumn[jColumn2] != jColumn1) { // bad good = false; printf("bad col\n"); @@ -12515,14 +12511,15 @@ static void statistics(ClpSimplex *originalModel, ClpSimplex *model) if (mapRow[iRow] == iRow) { // First (but be careful) if (iRow != iRow2) { - //mapRow[iRow]=iRow2; - //mapRow[iRow2]=iRow; + // mapRow[iRow]=iRow2; + // mapRow[iRow2]=iRow; int iBack = backRow[iRow]; int iBack2 = backRow[iRow2]; - if (randomRow[iBack] == randomRow[iBack2] && iBack2 - iBack == offset) { + if (randomRow[iBack] == randomRow[iBack2] && + iBack2 - iBack == offset) { stackRow[nStackR++] = iBack; } else { - //printf("randomRow diff - weights %g %g\n", + // printf("randomRow diff - weights %g %g\n", // weight[iRow],weight[iRow2]); // bad good = false; @@ -12550,7 +12547,7 @@ static void statistics(ClpSimplex *originalModel, ClpSimplex *model) if (mapRow[iRow] == iRow) { for (CoinBigIndex i = start; i < start + length; i++) { int jColumn = column[i]; - backColumn2[jColumn] = static_cast< int >(i - start); + backColumn2[jColumn] = static_cast(i - start); } for (CoinBigIndex i = start; i < start + length; i++) { int jColumn = column[i]; @@ -12571,7 +12568,8 @@ static void statistics(ClpSimplex *originalModel, ClpSimplex *model) } else { int row2 = mapRow[iRow]; assert(iRow = mapRow[row2]); - if (rowLower[iRow] != rowLower[row2] || rowLower[row2] != rowLower[iRow]) + if (rowLower[iRow] != rowLower[row2] || + rowLower[row2] != rowLower[iRow]) good = false; CoinBigIndex offset2 = rowStart[row2] - start; for (CoinBigIndex i = start; i < start + length; i++) { @@ -12579,7 +12577,8 @@ static void statistics(ClpSimplex *originalModel, ClpSimplex *model) double value = element[i]; int jColumn2 = column[i + offset2]; double value2 = element[i + offset2]; - if (value != value2 || mapColumn[jColumn] != jColumn2 || mapColumn[jColumn2] != jColumn) + if (value != value2 || mapColumn[jColumn] != jColumn2 || + mapColumn[jColumn2] != jColumn) good = false; } } @@ -12603,7 +12602,7 @@ static void statistics(ClpSimplex *originalModel, ClpSimplex *model) if (good) { // temp if (nMapRow < 0) { - //const double * solution = model->primalColumnSolution(); + // const double * solution = model->primalColumnSolution(); // find mapped int nMapColumn = 0; for (int i = 0; i < numberColumns; i++) { @@ -12668,16 +12667,15 @@ static void statistics(ClpSimplex *originalModel, ClpSimplex *model) double *lower = new double[nAddRows]; double *upper = new double[nAddRows]; int i; - //const double * solution = model->primalColumnSolution(); + // const double * solution = model->primalColumnSolution(); for (i = 0; i < nAddRows; i++) { lower[i] = 0.0; upper[i] = COIN_DBL_MAX; } - printf("Adding %d rows with %d elements\n", nAddRows, - startAdd[nAddRows]); - //ClpSimplex newModel(*model); - //newModel.addRows(nAddRows,lower,upper,startAdd,columnAdd,elementAdd); - //newModel.writeMps("modified.mps"); + printf("Adding %d rows with %d elements\n", nAddRows, startAdd[nAddRows]); + // ClpSimplex newModel(*model); + // newModel.addRows(nAddRows,lower,upper,startAdd,columnAdd,elementAdd); + // newModel.writeMps("modified.mps"); delete[] lower; delete[] upper; } @@ -12703,7 +12701,7 @@ static void statistics(ClpSimplex *originalModel, ClpSimplex *model) } delete[] number; // Now do breakdown of ranges - breakdown("Elements", static_cast< int >(numberElements), elementByColumn); + breakdown("Elements", static_cast(numberElements), elementByColumn); breakdown("RowLower", numberRows, rowLower); breakdown("RowUpper", numberRows, rowUpper); breakdown("ColumnLower", numberColumns, columnLower); @@ -12711,9 +12709,10 @@ static void statistics(ClpSimplex *originalModel, ClpSimplex *model) breakdown("Objective", numberColumns, objective); } -static bool maskMatches(const int *starts, char **masks, - std::string &check) -{ +//########################################################################### +//########################################################################### + +static bool maskMatches(const int *starts, char **masks, std::string &check) { // back to char as I am old fashioned const char *checkC = check.c_str(); size_t length = strlen(checkC); @@ -12732,16 +12731,21 @@ static bool maskMatches(const int *starts, char **masks, return false; } -static void clean(char *temp) -{ +//########################################################################### +//########################################################################### + +static void clean(char *temp) { char *put = temp; while (*put >= ' ') put++; *put = '\0'; } -static void generateCode(CbcModel * /*model*/, const char *fileName, int type, int preProcess) -{ +//########################################################################### +//########################################################################### + +static void generateCode(CbcModel * /*model*/, const char *fileName, int type, + int preProcess) { // options on code generation bool sizecode = (type & 4) != 0; type &= 3; @@ -12764,11 +12768,13 @@ static void generateCode(CbcModel * /*model*/, const char *fileName, int type, i strcpy(line[numberLines++], "0#include \"CglPreProcess.hpp\""); strcpy(line[numberLines++], "0#include \"CoinTime.hpp\""); if (preProcess > 0) - strcpy(line[numberLines++], "0#include \"CglProbing.hpp\""); // possibly redundant + strcpy(line[numberLines++], + "0#include \"CglProbing.hpp\""); // possibly redundant // To allow generated 5's to be just before branchAndBound - do rest here strcpy(line[numberLines++], "5 cbcModel->initialSolve();"); strcpy(line[numberLines++], "5 if (clpModel->tightenPrimalBounds()!=0) {"); - strcpy(line[numberLines++], "5 std::cout<<\"Problem is infeasible - tightenPrimalBounds!\"<dual(); // clean up"); @@ -12776,13 +12782,20 @@ static void generateCode(CbcModel * /*model*/, const char *fileName, int type, i // override some settings strcpy(line[numberLines++], "5 // compute some things using problem size"); strcpy(line[numberLines++], "5 cbcModel->setMinimumDrop(CoinMin(5.0e-2,"); - strcpy(line[numberLines++], "5 fabs(cbcModel->getMinimizationObjValue())*1.0e-3+1.0e-4));"); + strcpy( + line[numberLines++], + "5 fabs(cbcModel->getMinimizationObjValue())*1.0e-3+1.0e-4));"); strcpy(line[numberLines++], "5 if (cbcModel->getNumCols()<500)"); - strcpy(line[numberLines++], "5 cbcModel->setMaximumCutPassesAtRoot(-100); // always do 100 if possible"); + strcpy(line[numberLines++], + "5 cbcModel->setMaximumCutPassesAtRoot(-100); // always do 100 " + "if possible"); strcpy(line[numberLines++], "5 else if (cbcModel->getNumCols()<5000)"); - strcpy(line[numberLines++], "5 cbcModel->setMaximumCutPassesAtRoot(100); // use minimum drop"); + strcpy( + line[numberLines++], + "5 cbcModel->setMaximumCutPassesAtRoot(100); // use minimum drop"); strcpy(line[numberLines++], "5 else"); - strcpy(line[numberLines++], "5 cbcModel->setMaximumCutPassesAtRoot(20);"); + strcpy(line[numberLines++], + "5 cbcModel->setMaximumCutPassesAtRoot(20);"); strcpy(line[numberLines++], "5 cbcModel->setMaximumCutPasses(1);"); } if (preProcess <= 0) { @@ -12794,37 +12807,52 @@ static void generateCode(CbcModel * /*model*/, const char *fileName, int type, i strcpy(line[numberLines++], "5 cbcModel->setStrategy(strategy);"); } } else { - int translate[] = { 9999, 0, 0, -1, 2, 3, -2 }; + int translate[] = {9999, 0, 0, -1, 2, 3, -2}; strcpy(line[numberLines++], "5 // Hand coded preprocessing"); strcpy(line[numberLines++], "5 CglPreProcess process;"); - strcpy(line[numberLines++], "5 OsiSolverInterface * saveSolver=cbcModel->solver()->clone();"); + strcpy(line[numberLines++], + "5 OsiSolverInterface * saveSolver=cbcModel->solver()->clone();"); strcpy(line[numberLines++], "5 // Tell solver we are in Branch and Cut"); - strcpy(line[numberLines++], "5 saveSolver->setHintParam(OsiDoInBranchAndCut,true,OsiHintDo) ;"); + strcpy(line[numberLines++], + "5 saveSolver->setHintParam(OsiDoInBranchAndCut,true,OsiHintDo) ;"); strcpy(line[numberLines++], "5 // Default set of cut generators"); strcpy(line[numberLines++], "5 CglProbing generator1;"); strcpy(line[numberLines++], "5 generator1.setUsingObjective(1);"); strcpy(line[numberLines++], "5 generator1.setMaxPass(3);"); - strcpy(line[numberLines++], "5 generator1.setMaxProbeRoot(saveSolver->getNumCols());"); + strcpy(line[numberLines++], + "5 generator1.setMaxProbeRoot(saveSolver->getNumCols());"); strcpy(line[numberLines++], "5 generator1.setMaxElements(100);"); strcpy(line[numberLines++], "5 generator1.setMaxLookRoot(50);"); strcpy(line[numberLines++], "5 generator1.setRowCuts(3);"); strcpy(line[numberLines++], "5 // Add in generators"); strcpy(line[numberLines++], "5 process.addCutGenerator(&generator1);"); - strcpy(line[numberLines++], "5 process.messageHandler()->setLogLevel(cbcModel->logLevel());"); + strcpy(line[numberLines++], + "5 process.messageHandler()->setLogLevel(cbcModel->logLevel());"); strcpy(line[numberLines++], "5 OsiSolverInterface * solver2 = "); - sprintf(line[numberLines++], "5 process.preProcessNonDefault(*saveSolver,%d,10);", translate[preProcess]); - strcpy(line[numberLines++], "5 // Tell solver we are not in Branch and Cut"); - strcpy(line[numberLines++], "5 saveSolver->setHintParam(OsiDoInBranchAndCut,false,OsiHintDo) ;"); + sprintf(line[numberLines++], + "5 process.preProcessNonDefault(*saveSolver,%d,10);", + translate[preProcess]); + strcpy(line[numberLines++], + "5 // Tell solver we are not in Branch and Cut"); + strcpy( + line[numberLines++], + "5 saveSolver->setHintParam(OsiDoInBranchAndCut,false,OsiHintDo) ;"); strcpy(line[numberLines++], "5 if (solver2)"); - strcpy(line[numberLines++], "5 solver2->setHintParam(OsiDoInBranchAndCut,false,OsiHintDo) ;"); + strcpy(line[numberLines++], + "5 solver2->setHintParam(OsiDoInBranchAndCut,false,OsiHintDo) ;"); strcpy(line[numberLines++], "5 if (!solver2) {"); - strcpy(line[numberLines++], "5 std::cout<<\"Pre-processing says infeasible!\"<getNumRows()"); - strcpy(line[numberLines++], "5 <<\" rows, \"<getNumCols()"); - strcpy(line[numberLines++], "5 <<\" columns and \"<getNumElements()"); - strcpy(line[numberLines++], "5 <<\" elements\"<getNumElements()<getNumRows()"); + strcpy(line[numberLines++], + "5 <<\" rows, \"<getNumCols()"); + strcpy(line[numberLines++], + "5 <<\" columns and \"<getNumElements()"); + strcpy(line[numberLines++], + "5 <<\" elements\"<getNumElements()<clone();"); @@ -12841,63 +12869,96 @@ static void generateCode(CbcModel * /*model*/, const char *fileName, int type, i strcpy(line[numberLines++], "0 OsiClpSolverInterface solver1;"); strcpy(line[numberLines++], "0 int status=1;"); strcpy(line[numberLines++], "0 if (argc<2)"); - strcpy(line[numberLines++], "0 std::cout<<\"Please give file name\"< (osiModel);"); - strcpy(line[numberLines++], "0 ClpSimplex * clpModel = osiclpModel->getModelPtr();"); + strcpy(line[numberLines++], + "0 OsiSolverInterface * osiModel = model.solver();"); + strcpy(line[numberLines++], + "0 OsiClpSolverInterface * osiclpModel = dynamic_cast< " + "OsiClpSolverInterface*> (osiModel);"); + strcpy(line[numberLines++], + "0 ClpSimplex * clpModel = osiclpModel->getModelPtr();"); // add in comments about messages - strcpy(line[numberLines++], "3 // You can save some time by switching off message building"); - strcpy(line[numberLines++], "3 // clpModel->messagesPointer()->setDetailMessages(100,10000,(int *) NULL);"); + strcpy(line[numberLines++], + "3 // You can save some time by switching off message building"); + strcpy(line[numberLines++], + "3 // clpModel->messagesPointer()->setDetailMessages(100,10000,(int " + "*) NULL);"); // add in actual solve strcpy(line[numberLines++], "5 cbcModel->branchAndBound();"); - strcpy(line[numberLines++], "8 std::cout<getNodeCount()<<\" nodes with objective \""); + strcpy( + line[numberLines++], + "8 std::cout<getNodeCount()<<\" nodes with objective \""); strcpy(line[numberLines++], "8 <getObjValue()"); - strcpy(line[numberLines++], "8 <<(!cbcModel->status() ? \" Finished\" : \" Not finished\")"); + strcpy(line[numberLines++], "8 <<(!cbcModel->status() ? \" " + "Finished\" : \" Not finished\")"); strcpy(line[numberLines++], "8 <getMinimizationObjValue()<1.0e50) {"); + strcpy(line[numberLines++], + "5 if (cbcModel->getMinimizationObjValue()<1.0e50) {"); if (preProcess > 0) { strcpy(line[numberLines++], "5 // post process"); - strcpy(line[numberLines++], "5 process.postProcess(*cbcModel->solver());"); + strcpy(line[numberLines++], + "5 process.postProcess(*cbcModel->solver());"); strcpy(line[numberLines++], "5 // Solution now back in saveSolver"); strcpy(line[numberLines++], "5 cbcModel->assignSolver(saveSolver);"); - strcpy(line[numberLines++], "5 memcpy(cbcModel->bestSolution(),cbcModel->solver()->getColSolution(),"); + strcpy(line[numberLines++], "5 " + "memcpy(cbcModel->bestSolution(),cbcModel->" + "solver()->getColSolution(),"); strcpy(line[numberLines++], "5 numberColumns*sizeof(double));"); } strcpy(line[numberLines++], "5 // put back in original solver"); - strcpy(line[numberLines++], "5 solver1.setColSolution(cbcModel->bestSolution());"); - strcpy(line[numberLines++], "5 const double * solution = solver1.getColSolution();"); + strcpy(line[numberLines++], + "5 solver1.setColSolution(cbcModel->bestSolution());"); + strcpy(line[numberLines++], + "5 const double * solution = solver1.getColSolution();"); strcpy(line[numberLines++], "8 \n // Now you would use solution etc etc\n"); strcpy(line[numberLines++], "5"); - strcpy(line[numberLines++], "5 // Get names from solver1 (as OsiSolverInterface may lose)"); - strcpy(line[numberLines++], "5 std::vector columnNames = *solver1.getModelPtr()->columnNames();"); + strcpy(line[numberLines++], + "5 // Get names from solver1 (as OsiSolverInterface may lose)"); + strcpy(line[numberLines++], "5 std::vector columnNames = " + "*solver1.getModelPtr()->columnNames();"); strcpy(line[numberLines++], "5 "); strcpy(line[numberLines++], "5 int iColumn;"); - strcpy(line[numberLines++], "5 std::cout<1.0e-7&&solver1.isInteger(iColumn)) "); - strcpy(line[numberLines++], "5 std::cout<1.0e-7&&solver1.isInteger(iColumn)) "); + strcpy(line[numberLines++], + "5 std::cout< 1) wanted[2] = wanted[4] = wanted[7] = 1; - std::string header[9] = { "", "Save values", "Redundant save of default values", "Set changed values", - "Redundant set default values", "Solve", "Restore values", "Redundant restore values", "Finish up" }; + std::string header[9] = {"", + "Save values", + "Redundant save of default values", + "Set changed values", + "Redundant set default values", + "Solve", + "Restore values", + "Redundant restore values", + "Finish up"}; for (int iType = 0; iType < 9; iType++) { if (!wanted[iType]) continue; @@ -12923,7 +12991,8 @@ static void generateCode(CbcModel * /*model*/, const char *fileName, int type, i fprintf(fp, "\n // %s\n\n", header[iType].c_str()); n++; // skip save and clp as cloned - if (!strstr(line[iLine], "save") || (!strstr(line[iLine], "clpMo") && !strstr(line[iLine], "_Osi"))) + if (!strstr(line[iLine], "save") || + (!strstr(line[iLine], "clpMo") && !strstr(line[iLine], "_Osi"))) fprintf(fp, "%s\n", line[iLine] + 1); } } @@ -12931,20 +13000,41 @@ static void generateCode(CbcModel * /*model*/, const char *fileName, int type, i fclose(fp); printf("C++ file written to %s\n", fileName); } -// Print a general message -static void printGeneralMessage(CbcModel &model, const char *message) +// To allow old way of CbcMain1 +int CbcMain1(int argc, const char *argv[], + CbcModel &model, + CbcParameters ¶meterData, + int callBack(CbcModel *currentSolver, int whereFrom), + ampl_info *info) +{ + std::deque inputQueue; + CoinParamUtils::formInputQueue(inputQueue, "cbc", argc, const_cast< char ** >(argv)); + return CbcMain1(inputQueue,model,parameterData,callBack,info); +} + +int CbcMain1(int argc, const char *argv[], + CbcModel &model, + int callBack(CbcModel *currentSolver, int whereFrom), + CbcParameters ¶meterData) { + std::deque inputQueue; + CoinParamUtils::formInputQueue(inputQueue, "cbc", argc, const_cast< char ** >(argv)); + return CbcMain1(inputQueue,model,parameterData,callBack,NULL); +} +//########################################################################### +// Print a general message +//########################################################################### + +static void printGeneralMessage(CbcModel &model, const char *message) { #ifndef DISALLOW_PRINTING model.messageHandler()->message(CBC_FPUMP1, model.messages()) - << message - << CoinMessageEol; + << message << CoinMessageEol; #endif } #ifdef CBC_HAS_NAUTY #include "CbcSymmetry.hpp" // returns number of constraints added -static int nautiedConstraints(CbcModel &model, int maxPass) -{ +static int nautiedConstraints(CbcModel &model, int maxPass) { bool changed = true; int numberAdded = 0; int numberPasses = 0; @@ -12960,14 +13050,14 @@ static int nautiedConstraints(CbcModel &model, int maxPass) while (changed) { changed = false; CbcSymmetry symmetryInfo; - //symmetryInfo.setModel(&model); + // symmetryInfo.setModel(&model); // for now strong is just on counts - use user option - //int maxN=5000000; - //OsiSolverInterface * solver = model.solver(); + // int maxN=5000000; + // OsiSolverInterface * solver = model.solver(); symmetryInfo.setupSymmetry(&model); int numberGenerators = symmetryInfo.statsOrbits(&model, 0); if (numberGenerators) { - //symmetryInfo.Print_Orbits(); + // symmetryInfo.Print_Orbits(); int numberUsefulOrbits = symmetryInfo.numberUsefulOrbits(); if (numberUsefulOrbits) { symmetryInfo.Compute_Symmetry(); @@ -13046,7 +13136,7 @@ static int nautiedConstraints(CbcModel &model, int maxPass) } } if (nIn > 1) { - //printf("Using orbit length %d\n",nIn); + // printf("Using orbit length %d\n",nIn); CoinSort_2(size, size + nIn, which); size[0] = 1.0; size[1] = -1.0; @@ -13078,15 +13168,17 @@ static int nautiedConstraints(CbcModel &model, int maxPass) char general[100]; if (numberPasses < maxPass) sprintf(general, "%d constraints added in %d passes", numberAdded, - numberPasses); + numberPasses); else - sprintf(general, "%d constraints added in %d passes (maximum) - must be better way", numberAdded, - numberPasses); - model.messageHandler()->message(CBC_GENERAL, - model.messages()) - << general << CoinMessageEol; + sprintf( + general, + "%d constraints added in %d passes (maximum) - must be better way", + numberAdded, numberPasses); + model.messageHandler()->message(CBC_GENERAL, model.messages()) + << general << CoinMessageEol; #ifdef SAVE_NAUTY - OsiClpSolverInterface *clpSolver = dynamic_cast< OsiClpSolverInterface * >(solver); + OsiClpSolverInterface *clpSolver = + dynamic_cast(solver); ClpSimplex *lpSolver = clpSolver->getModelPtr(); char name[100]; strcpy(name, lpSolver->problemName().c_str()); @@ -13121,62 +13213,6 @@ static int nautiedConstraints(CbcModel &model, int maxPass) } #endif -static char cbcCrashAnnounced = 0; - -#ifdef HAVE_EXECINFO_H -#ifdef HAVE_SIGNAL_H -void CbcCrashHandler( int sig ) { - char signame[256] = ""; - switch (sig) { - case SIGILL: - strcpy(signame, "SIGILL"); - break; - case SIGSEGV: - strcpy(signame, "SIGSEGV"); - break; - case SIGABRT: - strcpy(signame, "SIGABRT"); - break; - } - - fflush(stderr); - fflush(stdout); - fprintf(stderr, "\n\nERROR while running Cbc. Signal %s caught. Getting stack trace.\n", signame); fflush(stderr); - { - char *st = getenv("RUNNING_TEST"); - if (st) { - fprintf(stderr, "Error happened while running the \"%s\" test\n", st); - fflush(stderr); - } - } - -#define MAX_FRAMES 50 - void *array[MAX_FRAMES]; - size_t size; - char **strings; - size_t i; - - size = backtrace (array, MAX_FRAMES); - strings = backtrace_symbols (array, size); - - for (i = 0; i < size; i++) { - fprintf (stderr, "%s\n", strings[i]); - fflush(stderr); - } - fprintf(stderr, "\n\n"); fflush(stderr); - - free (strings); - - if (!cbcCrashAnnounced) { - cbcCrashAnnounced = 1; - abort(); - } -#undef MAX_FRAMES -} -#endif -#endif - - /* Version 1.00.00 November 16 2005. This is to stop me (JJF) messing about too much. @@ -13184,14 +13220,14 @@ void CbcCrashHandler( int sig ) { The testing next version may be activated by CBC_NEXT_VERSION This applies to OsiClp, Clp etc Version 1.00.01 November 24 2005 - Added several classes for advanced users. This can't affect code (if you don't use it) - Made some tiny changes (for N way branching) which should not change anything. - CbcNWay object class - for N way branching this also allows use of CbcConsequence class. - CbcBranchAllDifferent object class - for branching on general integer variables - to stop them having same value so branches are x >= y+1 and x <= y-1. - Added two new Cgl classes - CglAllDifferent which does column fixing (too slowly) - and CglStored which just has a list of cuts which can be activated. - Modified preprocess option to SOS + Added several classes for advanced users. This can't affect code (if you + don't use it) Made some tiny changes (for N way branching) which should not + change anything. CbcNWay object class - for N way branching this also allows + use of CbcConsequence class. CbcBranchAllDifferent object class - for + branching on general integer variables to stop them having same value so + branches are x >= y+1 and x <= y-1. Added two new Cgl classes - + CglAllDifferent which does column fixing (too slowly) and CglStored which just + has a list of cuts which can be activated. Modified preprocess option to SOS Version 1.00.02 December 9 2005 Added use of CbcStrategy to do clean preprocessing Added use of referenceSolver for cleaner repetition of Cbc diff --git a/src/CbcSolver.hpp b/src/CbcSolver.hpp index f74d83348..1e5767dfb 100644 --- a/src/CbcSolver.hpp +++ b/src/CbcSolver.hpp @@ -16,23 +16,31 @@ #ifndef CbcSolver_H #define CbcSolver_H +#include "CoinUtilsConfig.h" + #include #include + #include "CoinMessageHandler.hpp" -#include "OsiClpSolverInterface.hpp" +#include "CoinModel.hpp" +#include "OsiClpSolverInterface.hpp" #if CBC_OTHER_SOLVER == 1 #include "OsiCpxSolverInterface.hpp" #endif +#include "ClpParameters.hpp" + +#include "CglCutGenerator.hpp" + #include "CbcModel.hpp" -#include "CbcOrClpParam.hpp" -#include "CbcSolverConfig.h" +#include "CbcParameters.hpp" +#include "CbcMessage.hpp" class CbcUser; class CbcStopNow; -class CglCutGenerator; +//############################################################################# //############################################################################# /*! \brief This allows the use of the standalone solver in a flexible manner. @@ -52,7 +60,7 @@ class CglCutGenerator; Parameter initialisation is at last centralised in fillParameters(). */ -class CBCSOLVERLIB_EXPORT CbcSolver { +class CBCLIB_EXPORT CbcSolver { public: ///@name Solve method @@ -130,13 +138,13 @@ class CBCSOLVERLIB_EXPORT CbcSolver { ///@name useful stuff //@{ /// Get int value - int intValue(CbcOrClpParameterType type) const; + int intValue(int code); /// Set int value - void setIntValue(CbcOrClpParameterType type, int value); + void setIntValue(int code, int value); /// Get double value - double doubleValue(CbcOrClpParameterType type) const; + double doubleValue(int code); /// Set double value - void setDoubleValue(CbcOrClpParameterType type, double value); + void setDoubleValue(int code, double value); /// User function (NULL if no match) CbcUser *userFunction(const char *name) const; /// Return original Cbc model @@ -233,7 +241,8 @@ class CBCSOLVERLIB_EXPORT CbcSolver { /// Cpu time at instantiation double startTime_; /// Parameters and values - std::vector< CbcOrClpParam > parameters_; + ClpParameters clpParameters_; + CbcParameters parameters_; /// Whether to do miplib test bool doMiplib_; /// Whether to print to std::cout @@ -242,105 +251,15 @@ class CBCSOLVERLIB_EXPORT CbcSolver { int readMode_; //@} }; -//############################################################################# - -/// Structure to hold useful arrays -typedef struct { - // Priorities - int *priorities_; - // SOS priorities - int *sosPriority_; - // Direction to branch first - int *branchDirection_; - // Input solution - double *primalSolution_; - // Down pseudo costs - double *pseudoDown_; - // Up pseudo costs - double *pseudoUp_; -} CbcSolverUsefulData2; //############################################################################# - -/** - The CbcSolver class was taken out at a 9/12/09 meeting - This is a feeble replacement. - At present everything is public -*/ -class CBCSOLVERLIB_EXPORT CbcSolverUsefulData { - -public: - ///@name Constructors and destructors etc - //@{ - /// Default Constructor - CbcSolverUsefulData(); - - /** Copy constructor . - */ - CbcSolverUsefulData(const CbcSolverUsefulData &rhs); - - /// Assignment operator - CbcSolverUsefulData &operator=(const CbcSolverUsefulData &rhs); - - /// Destructor - ~CbcSolverUsefulData(); - //@} - - ///@name Member data - //@{ - // For time - double totalTime_; - // Parameters - std::vector parameters_; - // Printing - bool noPrinting_; - // Whether to use signal handler - bool useSignalHandler_; - // Default pump tuning - int initialPumpTune_; - // even with verbose >=1 this may not be the first call to - // the solver - bool printWelcome_; - - //@} -}; -/// And this uses it -// When we want to load up CbcModel with options first -CBCSOLVERLIB_EXPORT -void CbcMain0(CbcModel &babSolver, CbcSolverUsefulData &solverData); -CBCSOLVERLIB_EXPORT -int CbcMain1(int argc, const char *argv[], CbcModel &babSolver, int(CbcModel *currentSolver, int whereFrom), CbcSolverUsefulData &solverData); -CBCSOLVERLIB_EXPORT -int CbcMain1(int argc, const char *argv[], CbcModel &babSolver, - CbcSolverUsefulData &solverData); - -CBCSOLVERLIB_EXPORT -int CbcMain(int argc, const char *argv[], CbcModel &babSolver); -// four ways of calling -CBCSOLVERLIB_EXPORT -int callCbc(const char *input2, OsiClpSolverInterface &solver1); -CBCSOLVERLIB_EXPORT -int callCbc(const char *input2); -CBCSOLVERLIB_EXPORT -int callCbc(const std::string input2, OsiClpSolverInterface &solver1); -CBCSOLVERLIB_EXPORT -int callCbc(const std::string input2); -// two ways of calling -CBCSOLVERLIB_EXPORT -int callCbc(const char *input2, CbcModel &babSolver); -CBCSOLVERLIB_EXPORT -int callCbc(const std::string input2, CbcModel &babSolver); -// And when CbcMain0 already called to initialize (with call back) (see CbcMain1 for whereFrom) -CBCSOLVERLIB_EXPORT -int callCbc1(const char *input2, CbcModel &babSolver, int(CbcModel *currentSolver, int whereFrom)); - //############################################################################# /*! \brief A class to allow the use of unknown user functionality For example, access to a modelling language (CbcAmpl). */ -class CBCSOLVERLIB_EXPORT CbcUser { +class CBCLIB_EXPORT CbcUser { public: ///@name import/export methods @@ -372,7 +291,7 @@ class CBCSOLVERLIB_EXPORT CbcUser { /// Get useful stuff virtual void fillInformation(CbcSolver * /*model*/, - CbcSolverUsefulData & /*info*/) {} + CbcParameters & /*info*/) {} //@} ///@name usage methods @@ -428,6 +347,8 @@ class CBCSOLVERLIB_EXPORT CbcUser { //@} }; + +//############################################################################# //############################################################################# /*! \brief Support the use of a call back class to decide whether to stop @@ -435,7 +356,7 @@ class CBCSOLVERLIB_EXPORT CbcUser { Definitely under construction. */ -class CBCSOLVERLIB_EXPORT CbcStopNow { +class CBCLIB_EXPORT CbcStopNow { public: ///@name Decision methods @@ -485,5 +406,36 @@ class CBCSOLVERLIB_EXPORT CbcStopNow { }; #endif -/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 -*/ +//########################################################################### +// Empty callback to pass as default (why needed?) +//########################################################################### + +static int dummyCallback(CbcModel * /*model*/, int /*whereFrom*/) { return 0; } + +//############################################################################# +//############################################################################# + +// When we want to load up CbcModel with options first +CBCLIB_EXPORT +void CbcMain0(CbcModel &model, CbcParameters ¶meters); +CBCLIB_EXPORT +int CbcMain1(std::deque inputQueue, CbcModel &model, + CbcParameters ¶meters, + int callBack(CbcModel *currentSolver, int whereFrom) = + dummyCallback, ampl_info *info = NULL); + +void printGeneralMessage(CbcModel &model, std::string message, int type = CBC_GENERAL); +void printGeneralWarning(CbcModel &model, std::string message, int type = CBC_GENERAL_WARNING); +CBCLIB_EXPORT +int cbcReadAmpl(ampl_info *info, int argc, char **argv, CbcModel &model); +// for backward compatibility (samples) +#define CbcSolverUsefulData CbcParameters +CBCLIB_EXPORT +int CbcMain1(int argc, const char *argv[], + CbcModel &model, CbcParameters ¶meterData, + int callBack(CbcModel *currentSolver, int whereFrom) = + dummyCallback, ampl_info *info = NULL); +int CbcMain1(int argc, const char *argv[], + CbcModel &model, + int callBack(CbcModel *currentSolver, int whereFrom), + CbcParameters ¶meterData); diff --git a/src/CbcSolverAnalyze.cpp b/src/CbcSolverAnalyze.cpp index 4dd55db88..fddd45ead 100644 --- a/src/CbcSolverAnalyze.cpp +++ b/src/CbcSolverAnalyze.cpp @@ -313,10 +313,12 @@ int *analyze(OsiClpSolverInterface *solverMod, int &numberChanged, if (increment2 > increment && increment2 > 0.0) { if (!noPrinting_) { sprintf(generalPrint, "Cutoff increment increased from %g to %g", increment, increment2); - CoinMessages generalMessages = solverMod->getModelPtr()->messages(); - generalMessageHandler->message(CLP_GENERAL, generalMessages) + bool usePrefix = generalMessageHandler->prefix(); + generalMessageHandler->setPrefix(true); + generalMessageHandler->message(CBC_GENERAL, model.messages()) << generalPrint << CoinMessageEol; + generalMessageHandler->setPrefix(usePrefix); } increment = increment2; } @@ -328,5 +330,3 @@ int *analyze(OsiClpSolverInterface *solverMod, int &numberChanged, } #endif // ifndef CBC_OTHER_SOLVER -/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 -*/ diff --git a/src/CbcSolverConfig.h b/src/CbcSolverConfig.h deleted file mode 100644 index 4129ea821..000000000 --- a/src/CbcSolverConfig.h +++ /dev/null @@ -1,76 +0,0 @@ -/* Copyright (C) 2011 - * All Rights Reserved. - * This code is published under the Eclipse Public License. - * - * - * Include file for the configuration of Cbc. - * - * On systems where the code is configured with the configure script - * (i.e., compilation is always done with HAVE_CONFIG_H defined), this - * header file includes the automatically generated header file, and - * undefines macros that might configure with other Config.h files. - * - * On systems that are compiled in other ways (e.g., with the - * Developer Studio), a header files is included to define those - * macros that depend on the operating system and the compiler. The - * macros that define the configuration of the particular user setting - * (e.g., presence of other COIN-OR packages or third party code) are set - * by the files config_*default.h. The project maintainer needs to remember - * to update these file and choose reasonable defines. - * A user can modify the default setting by editing the config_*default.h files. - * - */ - -#ifndef __CBCSOLVERCONFIG_H__ -#define __CBCSOLVERCONFIG_H__ - -#ifdef HAVE_CONFIG_H -#ifdef CBCSOLVERLIB_BUILD -#include "config.h" - -/* overwrite CBCSOLVERLIB_EXPORT from config.h when building Cbc - * we want it to be __declspec(dllexport) when building a DLL on Windows - * we want it to be __attribute__((__visibility__("default"))) when building with GCC, - * so user can compile with -fvisibility=hidden - */ -#ifdef DLL_EXPORT -#undef CBCSOLVERLIB_EXPORT -#define CBCSOLVERLIB_EXPORT __declspec(dllexport) -#elif defined(__GNUC__) && __GNUC__ >= 4 -#undef CBCSOLVERLIB_EXPORT -#define CBCSOLVERLIB_EXPORT __attribute__((__visibility__("default"))) -#endif - -#else -#include "config_cbcsolver.h" -#endif - -#else /* HAVE_CONFIG_H */ - -#ifdef CBCSOLVERLIB_BUILD -#include "config_default.h" -#else -#include "config_cbc_default.h" -#endif - -#ifndef CBCSOLVERLIB_EXPORT -# if defined(_WIN32) && defined(DLL_EXPORT) -# ifdef CBCSOLVERLIB_BUILD -# define CBCSOLVERLIB_EXPORT __declspec(dllexport) -# else -# define CBCSOLVERLIB_EXPORT __declspec(dllimport) -# endif -# elif defined(__GNUC__) && __GNUC__ >= 4 -# define CBCSOLVERLIB_EXPORT __attribute__((__visibility__("default"))) -# else -# define CBCSOLVERLIB_EXPORT -# endif -#endif - - -#endif /* HAVE_CONFIG_H */ - -#endif /*__CBCSOLVERCONFIG_H__*/ - -/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 -*/ diff --git a/src/CbcSolverHeuristics.cpp b/src/CbcSolverHeuristics.cpp index fdcdba3e2..9da479b8a 100644 --- a/src/CbcSolverHeuristics.cpp +++ b/src/CbcSolverHeuristics.cpp @@ -7,44 +7,38 @@ */ #include "CbcConfig.h" -#include "CoinPragma.hpp" +#include "CoinPragma.hpp" #include "CoinTime.hpp" +#include "OsiAuxInfo.hpp" #include "OsiClpSolverInterface.hpp" #include "ClpPresolve.hpp" +#include "ClpSimplexOther.hpp" -#include "CbcSolverConfig.h" -#include "CbcOrClpParam.hpp" - +#include "CbcParam.hpp" #include "CbcModel.hpp" - #include "CbcHeuristicLocal.hpp" #include "CbcHeuristicPivotAndFix.hpp" //#include "CbcHeuristicPivotAndComplement.hpp" -#include "CbcHeuristicRandRound.hpp" -#include "CbcHeuristicGreedy.hpp" +#include "CbcHeuristicDW.hpp" #include "CbcHeuristicFPump.hpp" +#include "CbcHeuristicGreedy.hpp" #include "CbcHeuristicRINS.hpp" -#include "CbcHeuristicDW.hpp" +#include "CbcHeuristicRandRound.hpp" #include "CbcHeuristicVND.hpp" - #include "CbcHeuristicDiveCoefficient.hpp" #include "CbcHeuristicDiveFractional.hpp" #include "CbcHeuristicDiveGuided.hpp" -#include "CbcHeuristicDiveVectorLength.hpp" -#include "CbcHeuristicDivePseudoCost.hpp" #include "CbcHeuristicDiveLineSearch.hpp" - +#include "CbcHeuristicDivePseudoCost.hpp" +#include "CbcHeuristicDiveVectorLength.hpp" +#include "CbcParameters.hpp" #include "CbcStrategy.hpp" -#include "OsiAuxInfo.hpp" - -#include "ClpSimplexOther.hpp" // Crunch down model -void crunchIt(ClpSimplex *model) -{ +void crunchIt(ClpSimplex *model) { #ifdef JJF_ZERO model->dual(); #else @@ -55,13 +49,14 @@ void crunchIt(ClpSimplex *model) int *whichRow = new int[3 * numberRows]; int *whichColumn = new int[2 * numberColumns]; int nBound; - ClpSimplex *small = static_cast< ClpSimplexOther * >(model)->crunch(rhs, whichRow, whichColumn, - nBound, false, false); + ClpSimplex *small = static_cast(model)->crunch( + rhs, whichRow, whichColumn, nBound, false, false); if (small) { small->dual(); if (small->problemStatus() == 0) { model->setProblemStatus(0); - static_cast< ClpSimplexOther * >(model)->afterCrunch(*small, whichRow, whichColumn, nBound); + static_cast(model)->afterCrunch(*small, whichRow, + whichColumn, nBound); } else if (small->problemStatus() != 3) { model->setProblemStatus(1); } else { @@ -87,23 +82,21 @@ void crunchIt(ClpSimplex *model) doAction - 0 just fix in original and return NULL 1 return fixed non-presolved solver 2 as one but use presolve Inside this - 3 use presolve and fix ones with large cost + 3 use presolve and fix ones with large cost ? do heuristics and set best solution - ? do BAB and just set best solution - 10+ then use lastSolution and relax a few + ? do BAB and just set best solution + 10+ then use lastSolution and relax a few -2 cleanup afterwards if using 2 On output - number fixed */ -OsiClpSolverInterface * -fixVubs(CbcModel &model, int skipZero2, - int &doAction, - CoinMessageHandler * /*generalMessageHandler*/, - const double *lastSolution, double dextra[6], - int extra[5]) -{ +OsiClpSolverInterface *fixVubs(CbcModel &model, int skipZero2, int &doAction, + CoinMessageHandler * /*generalMessageHandler*/, + const double *lastSolution, double dextra[6], + int extra[5]) { if (doAction == 11 && !lastSolution) lastSolution = model.bestSolution(); - assert(((doAction >= 0 && doAction <= 3) && !lastSolution) || (doAction == 11 && lastSolution)); + assert(((doAction >= 0 && doAction <= 3) && !lastSolution) || + (doAction == 11 && lastSolution)); double fractionIntFixed = dextra[3]; double fractionFixed = dextra[4]; double fixAbove = dextra[2]; @@ -113,7 +106,8 @@ fixVubs(CbcModel &model, int skipZero2, #endif int leaveIntFree = extra[1]; OsiSolverInterface *originalSolver = model.solver(); - OsiClpSolverInterface *originalClpSolver = dynamic_cast< OsiClpSolverInterface * >(originalSolver); + OsiClpSolverInterface *originalClpSolver = + dynamic_cast(originalSolver); ClpSimplex *originalLpSolver = originalClpSolver->getModelPtr(); int *originalColumns = NULL; OsiClpSolverInterface *clpSolver; @@ -129,7 +123,8 @@ fixVubs(CbcModel &model, int skipZero2, double time1 = CoinCpuTime(); #endif originalClpSolver->initialSolve(); - COIN_DETAIL_PRINT(printf("first solve took %g seconds\n", CoinCpuTime() - time1)); + COIN_DETAIL_PRINT( + printf("first solve took %g seconds\n", CoinCpuTime() - time1)); double *columnLower = originalLpSolver->columnLower(); double *columnUpper = originalLpSolver->columnUpper(); const double *solution = originalLpSolver->primalColumnSolution(); @@ -156,7 +151,8 @@ fixVubs(CbcModel &model, int skipZero2, } } } - COIN_DETAIL_PRINT(printf("%d artificials fixed, %d left as in solution\n", nFix, nArt)); + COIN_DETAIL_PRINT( + printf("%d artificials fixed, %d left as in solution\n", nFix, nArt)); lpSolver = pinfo.presolvedModel(*originalLpSolver, 1.0e-8, true, 10); if (!lpSolver || doAction == 2) { // take off fixing in original @@ -182,15 +178,17 @@ fixVubs(CbcModel &model, int skipZero2, doAction = 1; } else { OsiSolverInterface *solver = originalSolver->clone(); - clpSolver = dynamic_cast< OsiClpSolverInterface * >(solver); + clpSolver = dynamic_cast(solver); lpSolver = clpSolver->getModelPtr(); } // Tighten bounds lpSolver->tightenPrimalBounds(0.0, 11, true); int numberColumns = clpSolver->getNumCols(); - double *saveColumnLower = CoinCopyOfArray(lpSolver->columnLower(), numberColumns); - double *saveColumnUpper = CoinCopyOfArray(lpSolver->columnUpper(), numberColumns); - //char generalPrint[200]; + double *saveColumnLower = + CoinCopyOfArray(lpSolver->columnLower(), numberColumns); + double *saveColumnUpper = + CoinCopyOfArray(lpSolver->columnUpper(), numberColumns); + // char generalPrint[200]; const double *objective = lpSolver->getObjCoefficients(); double *columnLower = lpSolver->columnLower(); double *columnUpper = lpSolver->columnUpper(); @@ -206,7 +204,7 @@ fixVubs(CbcModel &model, int skipZero2, // Column copy CoinPackedMatrix matrixByCol(*clpSolver->getMatrixByCol()); - //const double * element = matrixByCol.getElements(); + // const double * element = matrixByCol.getElements(); const int *row = matrixByCol.getIndices(); const CoinBigIndex *columnStart = matrixByCol.getVectorStarts(); const int *columnLength = matrixByCol.getVectorLengths(); @@ -323,10 +321,12 @@ fixVubs(CbcModel &model, int skipZero2, maximumDown -= 1.0e-8 * fabs(maximumDown); double maxUp = maximumUp + infiniteUpper * 1.0e31; double maxDown = maximumDown - infiniteLower * 1.0e31; - if (maxUp <= rowUpper[iRow] + tolerance && maxDown >= rowLower[iRow] - tolerance) { - //printf("Redundant row in vubs %d\n",iRow); + if (maxUp <= rowUpper[iRow] + tolerance && + maxDown >= rowLower[iRow] - tolerance) { + // printf("Redundant row in vubs %d\n",iRow); } else { - if (maxUp < rowLower[iRow] - 100.0 * tolerance || maxDown > rowUpper[iRow] + 100.0 * tolerance) { + if (maxUp < rowLower[iRow] - 100.0 * tolerance || + maxDown > rowUpper[iRow] + 100.0 * tolerance) { infeasible = true; break; } @@ -391,7 +391,8 @@ fixVubs(CbcModel &model, int skipZero2, newBound = nowLower; } } - if (!newBound || (clpSolver->isInteger(kColumn) && newBound < 0.999)) { + if (!newBound || + (clpSolver->isInteger(kColumn) && newBound < 0.999)) { // fix to zero if (!mark[kColumn]) { otherColumn[numberOther++] = kColumn; @@ -432,7 +433,8 @@ fixVubs(CbcModel &model, int skipZero2, newBound = nowLower; } } - if (!newBound || (clpSolver->isInteger(kColumn) && newBound < 0.999)) { + if (!newBound || + (clpSolver->isInteger(kColumn) && newBound < 0.999)) { // fix to zero if (!mark[kColumn]) { otherColumn[numberOther++] = kColumn; @@ -519,7 +521,8 @@ fixVubs(CbcModel &model, int skipZero2, int numberLayered = 0; for (iColumn = 0; iColumn < numberColumns; iColumn++) { if (fix[iColumn] == kLayer) { - for (CoinBigIndex i = fixColumn2[iColumn]; i < fixColumn2[iColumn + 1]; i++) { + for (CoinBigIndex i = fixColumn2[iColumn]; i < fixColumn2[iColumn + 1]; + i++) { int jColumn = otherColumn2[i]; if (fix[jColumn] == kLayer) { fix[iColumn] = kLayer + 100; @@ -538,8 +541,9 @@ fixVubs(CbcModel &model, int skipZero2, } for (int iPass = 0; iPass < 2; iPass++) { for (int jLayer = 0; jLayer < kLayer; jLayer++) { - int check[] = { -1, 0, 1, 2, 3, 4, 5, 10, 50, 100, 500, 1000, 5000, 10000, COIN_INT_MAX }; - int nCheck = static_cast< int >(sizeof(check) / sizeof(int)); + int check[] = {-1, 0, 1, 2, 3, 4, 5, 10, + 50, 100, 500, 1000, 5000, 10000, COIN_INT_MAX}; + int nCheck = static_cast(sizeof(check) / sizeof(int)); int countsI[20]; int countsC[20]; assert(nCheck <= 20); @@ -551,11 +555,13 @@ fixVubs(CbcModel &model, int skipZero2, for (iColumn = 0; iColumn < numberColumns; iColumn++) { if (fix[iColumn] == jLayer) { numberLayered++; - int nFix = static_cast< int >(fixColumn[iColumn + 1] - fixColumn[iColumn]); + int nFix = + static_cast(fixColumn[iColumn + 1] - fixColumn[iColumn]); if (iPass) { // just integers nFix = 0; - for (CoinBigIndex i = fixColumn[iColumn]; i < fixColumn[iColumn + 1]; i++) { + for (CoinBigIndex i = fixColumn[iColumn]; + i < fixColumn[iColumn + 1]; i++) { int jColumn = otherColumn[i]; if (clpSolver->isInteger(jColumn)) nFix++; @@ -577,7 +583,8 @@ fixVubs(CbcModel &model, int skipZero2, } #ifdef COIN_DETAIL if (numberLayered) { - printf("%d (%d integer) at priority %d\n", numberLayered, numberInteger, 1 + (jLayer / 100)); + printf("%d (%d integer) at priority %d\n", numberLayered, numberInteger, + 1 + (jLayer / 100)); char buffer[50]; for (int i = 1; i < nCheck; i++) { if (countsI[i] || countsC[i]) { @@ -587,7 +594,8 @@ fixVubs(CbcModel &model, int skipZero2, sprintf(buffer, "> %6d and <= %6d ", check[i - 1], check[i]); else sprintf(buffer, "> %6d ", check[i - 1]); - printf("%s %8d integers and %8d continuous\n", buffer, countsI[i], countsC[i]); + printf("%s %8d integers and %8d continuous\n", buffer, countsI[i], + countsC[i]); } } } @@ -599,9 +607,9 @@ fixVubs(CbcModel &model, int skipZero2, { // switch off presolve and up weight ClpSolve solveOptions; - //solveOptions.setPresolveType(ClpSolve::presolveOff,0); + // solveOptions.setPresolveType(ClpSolve::presolveOff,0); solveOptions.setSolveType(ClpSolve::usePrimalorSprint); - //solveOptions.setSpecialOption(1,3,30); // sprint + // solveOptions.setSpecialOption(1,3,30); // sprint int numberColumns = lpSolver->numberColumns(); int iColumn; bool allSlack = true; @@ -665,9 +673,10 @@ fixVubs(CbcModel &model, int skipZero2, if (columnUpper[iColumn] > columnLower[iColumn] + 1.0e-8) { if (clpSolver->isInteger(iColumn)) { double value = lastSolution[iColumn]; - int iValue = static_cast< int >(value + 0.5); - assert(fabs(value - static_cast< double >(iValue)) < 1.0e-3); - assert(iValue >= columnLower[iColumn] && iValue <= columnUpper[iColumn]); + int iValue = static_cast(value + 0.5); + assert(fabs(value - static_cast(iValue)) < 1.0e-3); + assert(iValue >= columnLower[iColumn] && + iValue <= columnUpper[iColumn]); columnLower[iColumn] = iValue; columnUpper[iColumn] = iValue; } @@ -681,9 +690,10 @@ fixVubs(CbcModel &model, int skipZero2, if (columnUpper[iColumn] > columnLower[iColumn] + 1.0e-8) { if (clpSolver->isInteger(iColumn)) { double value = lastSolution[iColumn]; - int iValue = static_cast< int >(value + 0.5); - assert(fabs(value - static_cast< double >(iValue)) < 1.0e-3); - assert(iValue >= columnLower[iColumn] && iValue <= columnUpper[iColumn]); + int iValue = static_cast(value + 0.5); + assert(fabs(value - static_cast(iValue)) < 1.0e-3); + assert(iValue >= columnLower[iColumn] && + iValue <= columnUpper[iColumn]); if (!fix[iColumn]) { if (iValue == 0) { state[iColumn] = 0; @@ -715,11 +725,13 @@ fixVubs(CbcModel &model, int skipZero2, nFixed = 0; for (iColumn = 0; iColumn < numberColumns; iColumn++) { if (columnUpper[iColumn] == 0.0 && fix[iColumn] == jLayer) { - for (CoinBigIndex i = fixColumn[iColumn]; i < fixColumn[iColumn + 1]; i++) { + for (CoinBigIndex i = fixColumn[iColumn]; + i < fixColumn[iColumn + 1]; i++) { int jColumn = otherColumn[i]; if (columnUpper[jColumn]) { bool canFix = true; - for (CoinBigIndex k = fixColumn2[jColumn]; k < fixColumn2[jColumn + 1]; k++) { + for (CoinBigIndex k = fixColumn2[jColumn]; + k < fixColumn2[jColumn + 1]; k++) { int kColumn = otherColumn2[k]; if (state[kColumn] == 1) { canFix = false; @@ -737,7 +749,8 @@ fixVubs(CbcModel &model, int skipZero2, nTotalFixed += nFixed; jLayer += 100; } - COIN_DETAIL_PRINT(printf("This fixes %d variables in lower priorities\n", nTotalFixed)); + COIN_DETAIL_PRINT(printf( + "This fixes %d variables in lower priorities\n", nTotalFixed)); break; } for (iColumn = 0; iColumn < numberColumns; iColumn++) { @@ -786,12 +799,15 @@ fixVubs(CbcModel &model, int skipZero2, } } if (toZero || toOne) - COIN_DETAIL_PRINT(printf("%d at 0 fixed and %d at one fixed\n", toZero, toOne)); - COIN_DETAIL_PRINT(printf("%d variables free, %d fixed to 0, %d to 1 - smallest %g, largest %g\n", - numberFree, atZero, atOne, smallest, largest)); + COIN_DETAIL_PRINT( + printf("%d at 0 fixed and %d at one fixed\n", toZero, toOne)); + COIN_DETAIL_PRINT(printf("%d variables free, %d fixed to 0, %d to 1 - " + "smallest %g, largest %g\n", + numberFree, atZero, atOne, smallest, largest)); if (numberGreater && !iPass) - COIN_DETAIL_PRINT(printf("%d variables have value > 1.0\n", numberGreater)); - //skipZero2=0; // leave 0 fixing + COIN_DETAIL_PRINT( + printf("%d variables have value > 1.0\n", numberGreater)); + // skipZero2=0; // leave 0 fixing int jLayer = 0; int nFixed = -1; int nTotalFixed = 0; @@ -799,11 +815,13 @@ fixVubs(CbcModel &model, int skipZero2, nFixed = 0; for (iColumn = 0; iColumn < numberColumns; iColumn++) { if (columnUpper[iColumn] == 0.0 && fix[iColumn] == jLayer) { - for (CoinBigIndex i = fixColumn[iColumn]; i < fixColumn[iColumn + 1]; i++) { + for (CoinBigIndex i = fixColumn[iColumn]; + i < fixColumn[iColumn + 1]; i++) { int jColumn = otherColumn[i]; if (columnUpper[jColumn]) { bool canFix = true; - for (CoinBigIndex k = fixColumn2[jColumn]; k < fixColumn2[jColumn + 1]; k++) { + for (CoinBigIndex k = fixColumn2[jColumn]; + k < fixColumn2[jColumn + 1]; k++) { int kColumn = otherColumn2[k]; if (state[kColumn] == 1) { canFix = false; @@ -821,12 +839,14 @@ fixVubs(CbcModel &model, int skipZero2, nTotalFixed += nFixed; jLayer += 100; } - COIN_DETAIL_PRINT(printf("This fixes %d variables in lower priorities\n", nTotalFixed)); + COIN_DETAIL_PRINT( + printf("This fixes %d variables in lower priorities\n", nTotalFixed)); if (iLargest < 0 || numberFree <= leaveIntFree) break; double movement; int way; - if (smallest <= 1.0 - largest && smallest < 0.2 && largest < fixAboveValue) { + if (smallest <= 1.0 - largest && smallest < 0.2 && + largest < fixAboveValue) { columnUpper[iSmallest] = 0.0; state[iSmallest] = 0; movement = smallest; @@ -843,7 +863,8 @@ fixVubs(CbcModel &model, int skipZero2, models[kPass] = *lpSolver; if (way == -1) { // fix others - for (CoinBigIndex i = fixColumn[iSmallest]; i < fixColumn[iSmallest + 1]; i++) { + for (CoinBigIndex i = fixColumn[iSmallest]; + i < fixColumn[iSmallest + 1]; i++) { int jColumn = otherColumn[i]; if (state[jColumn] == -1) { columnUpper[jColumn] = 0.0; @@ -859,7 +880,7 @@ fixVubs(CbcModel &model, int skipZero2, crunchIt(lpSolver); double moveObj = lpSolver->objectiveValue() - saveObj; COIN_DETAIL_PRINT(printf("movement %s was %g costing %g\n", - (way == -1) ? "down" : "up", movement, moveObj)); + (way == -1) ? "down" : "up", movement, moveObj)); if (way == -1 && (moveObj >= maxCostUp || lpSolver->status())) { // go up columnLower = models[kPass].columnLower(); @@ -875,7 +896,8 @@ fixVubs(CbcModel &model, int skipZero2, columnUpper[iSmallest] = saveColumnUpper[iSmallest]; state[iSmallest] = 1; // unfix others - for (CoinBigIndex i = fixColumn[iSmallest]; i < fixColumn[iSmallest + 1]; i++) { + for (CoinBigIndex i = fixColumn[iSmallest]; + i < fixColumn[iSmallest + 1]; i++) { int jColumn = otherColumn[i]; if (state[jColumn] == 3) { columnUpper[jColumn] = saveColumnUpper[jColumn]; @@ -887,7 +909,8 @@ fixVubs(CbcModel &model, int skipZero2, models[kPass] = *lpSolver; } lpSolver->dual(); - COIN_DETAIL_PRINT(printf("Fixing took %g seconds\n", CoinCpuTime() - time1)); + COIN_DETAIL_PRINT( + printf("Fixing took %g seconds\n", CoinCpuTime() - time1)); columnLower = lpSolver->columnLower(); columnUpper = lpSolver->columnUpper(); fullSolution = lpSolver->primalColumnSolution(); @@ -896,7 +919,7 @@ fixVubs(CbcModel &model, int skipZero2, double *dsort = new double[numberColumns]; int chunk = 20; int iRelax = 0; - //double fractionFixed=6.0/8.0; + // double fractionFixed=6.0/8.0; // relax while lots fixed while (true) { if (skipZero2 > 10 && doAction < 10) @@ -917,19 +940,20 @@ fixVubs(CbcModel &model, int skipZero2, assert(columnLower[iColumn]); assert(fullSolution[iColumn] > 0.1); if (djValue > 0.0) { - //printf("YY dj of %d at %g is %g\n",iColumn,value,djValue); + // printf("YY dj of %d at %g is %g\n",iColumn,value,djValue); sum1 += djValue; sort[n] = iColumn; dsort[n++] = -djValue; } else { - //printf("dj of %d at %g is %g\n",iColumn,value,djValue); + // printf("dj of %d at %g is %g\n",iColumn,value,djValue); } } else if (state[iColumn] == 0 || state[iColumn] == 10) { assert(fullSolution[iColumn] < 0.1); assert(!columnUpper[iColumn]); double otherValue = 0.0; int nn = 0; - for (CoinBigIndex i = fixColumn[iColumn]; i < fixColumn[iColumn + 1]; i++) { + for (CoinBigIndex i = fixColumn[iColumn]; i < fixColumn[iColumn + 1]; + i++) { int jColumn = otherColumn[i]; if (columnUpper[jColumn] == 0.0) { if (dj[jColumn] < -1.0e-5) { @@ -939,7 +963,8 @@ fixVubs(CbcModel &model, int skipZero2, } } if (djValue < -1.0e-2 || otherValue < -1.0e-2) { - //printf("XX dj of %d at %g is %g - %d out of %d contribute %g\n",iColumn,value,djValue, + // printf("XX dj of %d at %g is %g - %d out of %d contribute + // %g\n",iColumn,value,djValue, // nn,fixColumn[iColumn+1]-fixColumn[iColumn],otherValue); if (djValue < 1.0e-8) { sum0 -= djValue; @@ -951,7 +976,8 @@ fixVubs(CbcModel &model, int skipZero2, dsort[n++] = djValue + 0.001 * otherValue; } } else { - //printf("dj of %d at %g is %g - no contribution from %d\n",iColumn,value,djValue, + // printf("dj of %d at %g is %g - no contribution from + // %d\n",iColumn,value,djValue, // fixColumn[iColumn+1]-fixColumn[iColumn]); } } @@ -976,11 +1002,13 @@ fixVubs(CbcModel &model, int skipZero2, assert(lo[iColumn] == 0.0); nFixed++; nFixed0++; - for (CoinBigIndex i = fixColumn[iColumn]; i < fixColumn[iColumn + 1]; i++) { + for (CoinBigIndex i = fixColumn[iColumn]; i < fixColumn[iColumn + 1]; + i++) { int jColumn = otherColumn[i]; if (columnUpper[jColumn]) { bool canFix = true; - for (CoinBigIndex k = fixColumn2[jColumn]; k < fixColumn2[jColumn + 1]; k++) { + for (CoinBigIndex k = fixColumn2[jColumn]; + k < fixColumn2[jColumn + 1]; k++) { int kColumn = otherColumn2[k]; if (state[kColumn] == 1 || state[kColumn] == -2) { canFix = false; @@ -999,7 +1027,8 @@ fixVubs(CbcModel &model, int skipZero2, nFixed1++; } } - COIN_DETAIL_PRINT(printf("%d fixed %d orig 0 %d 1\n", nFixed, nFixed0, nFixed1)); + COIN_DETAIL_PRINT( + printf("%d fixed %d orig 0 %d 1\n", nFixed, nFixed0, nFixed1)); int jLayer = 0; nFixed = -1; int nTotalFixed = 0; @@ -1007,11 +1036,13 @@ fixVubs(CbcModel &model, int skipZero2, nFixed = 0; for (iColumn = 0; iColumn < numberColumns; iColumn++) { if (columnUpper[iColumn] == 0.0 && fix[iColumn] == jLayer) { - for (CoinBigIndex i = fixColumn[iColumn]; i < fixColumn[iColumn + 1]; i++) { + for (CoinBigIndex i = fixColumn[iColumn]; + i < fixColumn[iColumn + 1]; i++) { int jColumn = otherColumn[i]; if (columnUpper[jColumn]) { bool canFix = true; - for (CoinBigIndex k = fixColumn2[jColumn]; k < fixColumn2[jColumn + 1]; k++) { + for (CoinBigIndex k = fixColumn2[jColumn]; + k < fixColumn2[jColumn + 1]; k++) { int kColumn = otherColumn2[k]; if (state[kColumn] == 1 || state[kColumn] == -2) { canFix = false; @@ -1039,17 +1070,24 @@ fixVubs(CbcModel &model, int skipZero2, nFixed++; } } - COIN_DETAIL_PRINT(printf("This fixes %d variables in lower priorities - total %d (%d integer) - all target %d, int target %d\n", - nTotalFixed, nFixed, nFixedI, static_cast< int >(fractionFixed * numberColumns), static_cast< int >(fractionIntFixed * numberInteger))); + COIN_DETAIL_PRINT( + printf("This fixes %d variables in lower priorities - total %d (%d " + "integer) - all target %d, int target %d\n", + nTotalFixed, nFixed, nFixedI, + static_cast(fractionFixed * numberColumns), + static_cast(fractionIntFixed * numberInteger))); int nBad = 0; int nRelax = 0; for (iColumn = 0; iColumn < numberColumns; iColumn++) { - if (lo[iColumn] < columnLower[iColumn] || up[iColumn] > columnUpper[iColumn]) { - COIN_DETAIL_PRINT(printf("bad %d old %g %g, new %g %g\n", iColumn, lo[iColumn], up[iColumn], - columnLower[iColumn], columnUpper[iColumn])); + if (lo[iColumn] < columnLower[iColumn] || + up[iColumn] > columnUpper[iColumn]) { + COIN_DETAIL_PRINT(printf("bad %d old %g %g, new %g %g\n", iColumn, + lo[iColumn], up[iColumn], + columnLower[iColumn], columnUpper[iColumn])); nBad++; } - if (lo[iColumn] > columnLower[iColumn] || up[iColumn] < columnUpper[iColumn]) { + if (lo[iColumn] > columnLower[iColumn] || + up[iColumn] < columnUpper[iColumn]) { nRelax++; } } @@ -1062,7 +1100,8 @@ fixVubs(CbcModel &model, int skipZero2, delete[] lo; delete[] up; lpSolver->primal(1); - if (nFixed < fractionFixed * numberColumns || nFixedI < fractionIntFixed * numberInteger || !nRelax) + if (nFixed < fractionFixed * numberColumns || + nFixedI < fractionIntFixed * numberInteger || !nRelax) break; } delete[] state; @@ -1089,8 +1128,10 @@ fixVubs(CbcModel &model, int skipZero2, double *newColumnUpper = lpSolver->columnUpper(); for (iColumn = 0; iColumn < numberColumns; iColumn++) { int jColumn = originalColumns[iColumn]; - columnLower[jColumn] = CoinMax(columnLower[jColumn], newColumnLower[iColumn]); - columnUpper[jColumn] = CoinMin(columnUpper[jColumn], newColumnUpper[iColumn]); + columnLower[jColumn] = + CoinMax(columnLower[jColumn], newColumnLower[iColumn]); + columnUpper[jColumn] = + CoinMin(columnUpper[jColumn], newColumnUpper[iColumn]); } numberColumns = originalLpSolver->numberColumns(); delete[] originalColumns; @@ -1099,9 +1140,12 @@ fixVubs(CbcModel &model, int skipZero2, delete[] saveColumnUpper; if (!originalColumns) { // Basis - memcpy(originalLpSolver->statusArray(), lpSolver->statusArray(), numberRows + numberColumns); - memcpy(originalLpSolver->primalColumnSolution(), lpSolver->primalColumnSolution(), numberColumns * sizeof(double)); - memcpy(originalLpSolver->primalRowSolution(), lpSolver->primalRowSolution(), numberRows * sizeof(double)); + memcpy(originalLpSolver->statusArray(), lpSolver->statusArray(), + numberRows + numberColumns); + memcpy(originalLpSolver->primalColumnSolution(), + lpSolver->primalColumnSolution(), numberColumns * sizeof(double)); + memcpy(originalLpSolver->primalRowSolution(), lpSolver->primalRowSolution(), + numberRows * sizeof(double)); // Fix in solver columnLower = lpSolver->columnLower(); columnUpper = lpSolver->columnUpper(); @@ -1124,59 +1168,60 @@ fixVubs(CbcModel &model, int skipZero2, return NULL; } -int doHeuristics(CbcModel *model, int type, std::vector< CbcOrClpParam > parameters_, - int noPrinting_, int initialPumpTune) -{ -#ifdef JJF_ZERO //NEW_STYLE_SOLVER==0 - CbcOrClpParam *parameters_ = parameters; +int doHeuristics(CbcModel *model, int type, CbcParameters ¶meters, + int noPrinting_, int initialPumpTune) { +#ifdef JJF_ZERO // NEW_STYLE_SOLVER==0 + CbcParam *parameters_ = parameters; int numberParameters_ = numberParameters; bool noPrinting_ = noPrinting_; #endif char generalPrint[10000]; CoinMessages generalMessages = model->messages(); CoinMessageHandler *generalMessageHandler = model->messageHandler(); - //generalMessageHandler->setPrefix(false); + // generalMessageHandler->setPrefix(false); bool anyToDo = false; - int logLevel = parameters_[whichParam(CLP_PARAM_INT_LOGLEVEL, parameters_)].intValue(); - int useFpump = parameters_[whichParam(CBC_PARAM_STR_FPUMP, parameters_)].currentOptionAsInteger(); - int useRounding = parameters_[whichParam(CBC_PARAM_STR_ROUNDING, parameters_)].currentOptionAsInteger(); - int useGreedy = parameters_[whichParam(CBC_PARAM_STR_GREEDY, parameters_)].currentOptionAsInteger(); - int useCombine = parameters_[whichParam(CBC_PARAM_STR_COMBINE, parameters_)].currentOptionAsInteger(); - int useProximity = parameters_[whichParam(CBC_PARAM_STR_PROXIMITY, parameters_)].currentOptionAsInteger(); - int useCrossover = parameters_[whichParam(CBC_PARAM_STR_CROSSOVER2, parameters_)].currentOptionAsInteger(); - //int usePivotC = parameters_[whichParam(CBC_PARAM_STR_PIVOTANDCOMPLEMENT, parameters_)].currentOptionAsInteger(); - int usePivotF = parameters_[whichParam(CBC_PARAM_STR_PIVOTANDFIX, parameters_)].currentOptionAsInteger(); - int useRand = parameters_[whichParam(CBC_PARAM_STR_RANDROUND, parameters_)].currentOptionAsInteger(); - int useRINS = parameters_[whichParam(CBC_PARAM_STR_RINS, parameters_)].currentOptionAsInteger(); - int useRENS = parameters_[whichParam(CBC_PARAM_STR_RENS, parameters_)].currentOptionAsInteger(); - int useVND = parameters_[whichParam(CBC_PARAM_STR_VND, parameters_)].currentOptionAsInteger(); - int useDINS = parameters_[whichParam(CBC_PARAM_STR_DINS, parameters_)].currentOptionAsInteger(); - int useDIVING2 = parameters_[whichParam(CBC_PARAM_STR_DIVINGS, parameters_)].currentOptionAsInteger(); - int useNaive = parameters_[whichParam(CBC_PARAM_STR_NAIVE, parameters_)].currentOptionAsInteger(); - int useDW = parameters_[whichParam(CBC_PARAM_STR_DW, parameters_)].currentOptionAsInteger(); + int logLevel = parameters[CbcParam::LPLOGLEVEL]->intVal(); + int useFpump = parameters[CbcParam::FPUMP]->modeVal(); + int useRounding = parameters[CbcParam::ROUNDING]->modeVal(); + int useGreedy = parameters[CbcParam::GREEDY]->modeVal(); + int useCombine = parameters[CbcParam::COMBINE]->modeVal(); + int useProximity = parameters[CbcParam::PROXIMITY]->modeVal(); + int useCrossover = parameters[CbcParam::CROSSOVER]->modeVal(); + // int usePivotC = parameters[CbcParam::PIVOTANDCOMPLEMENT, + // parameters)]->modeVal(); + int usePivotF = parameters[CbcParam::PIVOTANDFIX]->modeVal(); + int useRand = parameters[CbcParam::RANDROUND]->modeVal(); + int useRINS = parameters[CbcParam::RINS]->modeVal(); + int useRENS = parameters[CbcParam::RENS]->modeVal(); + int useVND = parameters[CbcParam::VND]->modeVal(); + int useDINS = parameters[CbcParam::DINS]->modeVal(); + int useDIVING2 = parameters[CbcParam::DIVINGS]->modeVal(); + int useNaive = parameters[CbcParam::NAIVE]->modeVal(); + int useDW = parameters[CbcParam::DW]->modeVal(); int kType = (type < 10) ? type : 1; assert(kType == 1 || kType == 2); // FPump done first as it only works if no solution if (useFpump >= kType && useFpump <= kType + 1) { anyToDo = true; CbcHeuristicFPump heuristic4(*model); - double dextra3 = parameters_[whichParam(CBC_PARAM_DBL_SMALLBAB, parameters_)].doubleValue(); + double dextra3 = parameters[CbcParam::SMALLBAB]->dblVal(); heuristic4.setFractionSmall(dextra3); - double dextra1 = parameters_[whichParam(CBC_PARAM_DBL_ARTIFICIALCOST, parameters_)].doubleValue(); + double dextra1 = parameters[CbcParam::ARTIFICIALCOST]->dblVal(); if (dextra1) heuristic4.setArtificialCost(dextra1); - heuristic4.setMaximumPasses(parameters_[whichParam(CBC_PARAM_INT_FPUMPITS, parameters_)].intValue()); - if (parameters_[whichParam(CBC_PARAM_INT_FPUMPITS, parameters_)].intValue() == 21) + heuristic4.setMaximumPasses( + parameters[CbcParam::FPUMPITS]->intVal()); + if (parameters[CbcParam::FPUMPITS]->intVal() == 21) heuristic4.setIterationRatio(1.0); - int pumpTune = parameters_[whichParam(CBC_PARAM_INT_FPUMPTUNE, parameters_)].intValue(); - int pumpTune2 = parameters_[whichParam(CBC_PARAM_INT_FPUMPTUNE2, parameters_)].intValue(); + int pumpTune = parameters[CbcParam::FPUMPTUNE]->intVal(); + int pumpTune2 = parameters[CbcParam::FPUMPTUNE2]->intVal(); if (pumpTune > 0) { - bool printStuff = (pumpTune != initialPumpTune || logLevel > 1 || pumpTune2 > 0) - && !noPrinting_; + bool printStuff = + (pumpTune != initialPumpTune || logLevel > 1 || pumpTune2 > 0) && + !noPrinting_; if (printStuff) { generalMessageHandler->message(CBC_GENERAL, generalMessages) - << "Options for feasibility pump - " - << CoinMessageEol; + << "Options for feasibility pump - " << CoinMessageEol; } /* >=10000000 for using obj @@ -1184,11 +1229,12 @@ int doHeuristics(CbcModel *model, int type, std::vector< CbcOrClpParam > paramet >=1000 use index+1 as number of large loops >=100 use dextra1 as cutoff %100 == 10,20 etc for experimentation - 1 == fix ints at bounds, 2 fix all integral ints, 3 and continuous at bounds - 4 and static continuous, 5 as 3 but no internal integers - 6 as 3 but all slack basis! + 1 == fix ints at bounds, 2 fix all integral ints, 3 and continuous + at bounds 4 and static continuous, 5 as 3 but no internal integers 6 as + 3 but all slack basis! */ - double value = model->solver()->getObjSense() * model->solver()->getObjValue(); + double value = + model->solver()->getObjSense() * model->solver()->getObjValue(); int w = pumpTune / 10; int i = w % 10; w /= 10; @@ -1202,16 +1248,16 @@ int doHeuristics(CbcModel *model, int type, std::vector< CbcOrClpParam > paramet accumulate -= 100 * which; which--; // weights and factors - double weight[] = { 0.01, 0.01, 0.1, 0.1, 0.5, 0.5, 1.0, 1.0, 5.0, 5.0 }; - double factor[] = { 0.1, 0.5, 0.1, 0.5, 0.1, 0.5, 0.1, 0.5, 0.1, 0.5 }; + double weight[] = {0.01, 0.01, 0.1, 0.1, 0.5, 0.5, 1.0, 1.0, 5.0, 5.0}; + double factor[] = {0.1, 0.5, 0.1, 0.5, 0.1, 0.5, 0.1, 0.5, 0.1, 0.5}; heuristic4.setInitialWeight(weight[which]); heuristic4.setWeightFactor(factor[which]); if (printStuff) { - sprintf(generalPrint, "Initial weight for objective %g, decay factor %g", - weight[which], factor[which]); + sprintf(generalPrint, + "Initial weight for objective %g, decay factor %g", + weight[which], factor[which]); generalMessageHandler->message(CBC_GENERAL, generalMessages) - << generalPrint - << CoinMessageEol; + << generalPrint << CoinMessageEol; } } // fake cutoff @@ -1219,15 +1265,15 @@ int doHeuristics(CbcModel *model, int type, std::vector< CbcOrClpParam > paramet double cutoff; model->solver()->getDblParam(OsiDualObjectiveLimit, cutoff); cutoff = CoinMin(cutoff, value + 0.05 * fabs(value) * c); - double fakeCutoff = parameters_[whichParam(CBC_PARAM_DBL_FAKECUTOFF, parameters_)].doubleValue(); + double fakeCutoff = + parameters[CbcParam::FAKECUTOFF]->dblVal(); if (fakeCutoff) cutoff = fakeCutoff; heuristic4.setFakeCutoff(cutoff); if (printStuff) { sprintf(generalPrint, "Fake cutoff of %g", cutoff); generalMessageHandler->message(CBC_GENERAL, generalMessages) - << generalPrint - << CoinMessageEol; + << generalPrint << CoinMessageEol; } } int offRandomEtc = 0; @@ -1236,8 +1282,7 @@ int doHeuristics(CbcModel *model, int type, std::vector< CbcOrClpParam > paramet offRandomEtc = 1000000 * (pumpTune2 / 1000); if (printStuff) { generalMessageHandler->message(CBC_GENERAL, generalMessages) - << "Feasibility pump may run twice" - << CoinMessageEol; + << "Feasibility pump may run twice" << CoinMessageEol; } pumpTune2 = pumpTune2 % 1000; } @@ -1245,19 +1290,16 @@ int doHeuristics(CbcModel *model, int type, std::vector< CbcOrClpParam > paramet offRandomEtc += 100 * (pumpTune2 / 100); if (printStuff) { generalMessageHandler->message(CBC_GENERAL, generalMessages) - << "Not using randomized objective" - << CoinMessageEol; + << "Not using randomized objective" << CoinMessageEol; } } int maxAllowed = pumpTune2 % 100; if (maxAllowed) { offRandomEtc += 1000 * maxAllowed; if (printStuff) { - sprintf(generalPrint, "Fixing if same for %d passes", - maxAllowed); + sprintf(generalPrint, "Fixing if same for %d passes", maxAllowed); generalMessageHandler->message(CBC_GENERAL, generalMessages) - << generalPrint - << CoinMessageEol; + << generalPrint << CoinMessageEol; } } } @@ -1267,16 +1309,16 @@ int doHeuristics(CbcModel *model, int type, std::vector< CbcOrClpParam > paramet if (accumulate) { sprintf(generalPrint, "Accumulate of %d", accumulate); generalMessageHandler->message(CBC_GENERAL, generalMessages) - << generalPrint - << CoinMessageEol; + << generalPrint << CoinMessageEol; } } } if (r) { // also set increment - //double increment = (0.01*i+0.005)*(fabs(value)+1.0e-12); + // double increment = (0.01*i+0.005)*(fabs(value)+1.0e-12); double increment = 0.0; - double fakeIncrement = parameters_[whichParam(CBC_PARAM_DBL_FAKEINCREMENT, parameters_)].doubleValue(); + double fakeIncrement = + parameters[CbcParam::FAKEINCREMENT]->dblVal(); if (fakeIncrement) increment = fakeIncrement; if (increment >= 0.0) @@ -1291,23 +1333,20 @@ int doHeuristics(CbcModel *model, int type, std::vector< CbcOrClpParam > paramet else sprintf(generalPrint, "Relative increment of %g", -increment); generalMessageHandler->message(CBC_GENERAL, generalMessages) - << generalPrint - << CoinMessageEol; + << generalPrint << CoinMessageEol; } sprintf(generalPrint, "%d retries", r + 1); generalMessageHandler->message(CBC_GENERAL, generalMessages) - << generalPrint - << CoinMessageEol; + << generalPrint << CoinMessageEol; } } if (i + offRandomEtc) { heuristic4.setFeasibilityPumpOptions(i * 10 + offRandomEtc); if (printStuff) { sprintf(generalPrint, "Feasibility pump options of %d", - i * 10 + offRandomEtc); + i * 10 + offRandomEtc); generalMessageHandler->message(CBC_GENERAL, generalMessages) - << generalPrint - << CoinMessageEol; + << generalPrint << CoinMessageEol; } } pumpTune = pumpTune % 100; @@ -1317,8 +1356,7 @@ int doHeuristics(CbcModel *model, int type, std::vector< CbcOrClpParam > paramet if (printStuff) { sprintf(generalPrint, "Tuning (fixing) %d", pumpTune % 10); generalMessageHandler->message(CBC_GENERAL, generalMessages) - << generalPrint - << CoinMessageEol; + << generalPrint << CoinMessageEol; } } heuristic4.setHeuristicName("feasibility pump"); @@ -1377,7 +1415,7 @@ int doHeuristics(CbcModel *model, int type, std::vector< CbcOrClpParam > paramet heuristic6.setHeuristicName("RENS"); heuristic6.setFractionSmall(0.4); heuristic6.setFeasibilityPumpOptions(1008003); - int nodes[] = { -2, 50, 50, 50, 200, 1000, 10000, -1, -1, 200 }; + int nodes[] = {-2, 50, 50, 50, 200, 1000, 10000, -1, -1, 200}; heuristic6.setNumberNodes(nodes[useRENS]); heuristic6.setRensType(useRENS != 9 ? 0 : 32); model->addHeuristic(&heuristic6); @@ -1388,7 +1426,7 @@ int doHeuristics(CbcModel *model, int type, std::vector< CbcOrClpParam > paramet heuristic6b.setHeuristicName("VND"); heuristic6b.setFractionSmall(0.4); heuristic6b.setFeasibilityPumpOptions(1008003); - int nodes[] = { -2, 50, 50, 50, 200, 1000, 10000 }; + int nodes[] = {-2, 50, 50, 50, 200, 1000, 10000}; heuristic6b.setNumberNodes(nodes[useVND]); model->addHeuristic(&heuristic6b); anyToDo = true; @@ -1404,21 +1442,21 @@ int doHeuristics(CbcModel *model, int type, std::vector< CbcOrClpParam > paramet int useDIVING = 0; { int useD; - useD = parameters_[whichParam(CBC_PARAM_STR_DIVINGV, parameters_)].currentOptionAsInteger(); + useD = parameters[CbcParam::DIVINGV]->modeVal(); useDIVING |= 1 * ((useD >= kType) ? 1 : 0); - useD = parameters_[whichParam(CBC_PARAM_STR_DIVINGG, parameters_)].currentOptionAsInteger(); + useD = parameters[CbcParam::DIVINGG]->modeVal(); useDIVING |= 2 * ((useD >= kType) ? 1 : 0); - useD = parameters_[whichParam(CBC_PARAM_STR_DIVINGF, parameters_)].currentOptionAsInteger(); + useD = parameters[CbcParam::DIVINGF]->modeVal(); useDIVING |= 4 * ((useD >= kType) ? 1 : 0); - useD = parameters_[whichParam(CBC_PARAM_STR_DIVINGC, parameters_)].currentOptionAsInteger(); + useD = parameters[CbcParam::DIVINGC]->modeVal(); useDIVING |= 8 * ((useD >= kType) ? 1 : 0); - useD = parameters_[whichParam(CBC_PARAM_STR_DIVINGL, parameters_)].currentOptionAsInteger(); + useD = parameters[CbcParam::DIVINGL]->modeVal(); useDIVING |= 16 * ((useD >= kType) ? 1 : 0); - useD = parameters_[whichParam(CBC_PARAM_STR_DIVINGP, parameters_)].currentOptionAsInteger(); + useD = parameters[CbcParam::DIVINGP]->modeVal(); useDIVING |= 32 * ((useD >= kType) ? 1 : 0); } if (useDIVING2 >= kType && useDIVING2 <= kType + 1) { - int diveOptions = parameters_[whichParam(CBC_PARAM_INT_DIVEOPT, parameters_)].intValue(); + int diveOptions = parameters[CbcParam::DIVEOPT]->intVal(); if (diveOptions < 0 || diveOptions > 10) diveOptions = 2; CbcHeuristicJustOne heuristicJustOne(*model); @@ -1449,8 +1487,8 @@ int doHeuristics(CbcModel *model, int type, std::vector< CbcOrClpParam > paramet } if (useDIVING > 0) { - int majorIterations = parameters_[whichParam(CBC_PARAM_INT_DIVEOPTSOLVES, parameters_)].intValue(); - int diveOptions2 = parameters_[whichParam(CBC_PARAM_INT_DIVEOPT, parameters_)].intValue(); + int majorIterations = parameters[CbcParam::DIVEOPTSOLVES]->intVal(); + int diveOptions2 = parameters[CbcParam::DIVEOPT]->intVal(); int diveOptions; if (diveOptions2 > 99) { // switch on various active set stuff @@ -1481,7 +1519,8 @@ int doHeuristics(CbcModel *model, int type, std::vector< CbcOrClpParam > paramet if (diveOptions2) { heuristicDV.setPercentageToFix(0.0); heuristicDV.setMaxSimplexIterations(COIN_INT_MAX); - heuristicDV.setMaxSimplexIterationsAtRoot(COIN_INT_MAX - (diveOptions2 - 1)); + heuristicDV.setMaxSimplexIterationsAtRoot(COIN_INT_MAX - + (diveOptions2 - 1)); } model->addHeuristic(&heuristicDV); } @@ -1493,7 +1532,8 @@ int doHeuristics(CbcModel *model, int type, std::vector< CbcOrClpParam > paramet if (diveOptions2) { heuristicDG.setPercentageToFix(0.0); heuristicDG.setMaxSimplexIterations(COIN_INT_MAX); - heuristicDG.setMaxSimplexIterationsAtRoot(COIN_INT_MAX - (diveOptions2 - 1)); + heuristicDG.setMaxSimplexIterationsAtRoot(COIN_INT_MAX - + (diveOptions2 - 1)); } model->addHeuristic(&heuristicDG); } @@ -1505,7 +1545,8 @@ int doHeuristics(CbcModel *model, int type, std::vector< CbcOrClpParam > paramet if (diveOptions2) { heuristicDF.setPercentageToFix(0.0); heuristicDF.setMaxSimplexIterations(COIN_INT_MAX); - heuristicDF.setMaxSimplexIterationsAtRoot(COIN_INT_MAX - (diveOptions2 - 1)); + heuristicDF.setMaxSimplexIterationsAtRoot(COIN_INT_MAX - + (diveOptions2 - 1)); } model->addHeuristic(&heuristicDF); } @@ -1517,7 +1558,8 @@ int doHeuristics(CbcModel *model, int type, std::vector< CbcOrClpParam > paramet if (diveOptions2) { heuristicDC.setPercentageToFix(0.0); heuristicDC.setMaxSimplexIterations(COIN_INT_MAX); - heuristicDC.setMaxSimplexIterationsAtRoot(COIN_INT_MAX - (diveOptions2 - 1)); + heuristicDC.setMaxSimplexIterationsAtRoot(COIN_INT_MAX - + (diveOptions2 - 1)); } model->addHeuristic(&heuristicDC); } @@ -1529,7 +1571,8 @@ int doHeuristics(CbcModel *model, int type, std::vector< CbcOrClpParam > paramet if (diveOptions2) { heuristicDL.setPercentageToFix(0.0); heuristicDL.setMaxSimplexIterations(COIN_INT_MAX); - heuristicDL.setMaxSimplexIterationsAtRoot(COIN_INT_MAX - (diveOptions2 - 1)); + heuristicDL.setMaxSimplexIterationsAtRoot(COIN_INT_MAX - + (diveOptions2 - 1)); } model->addHeuristic(&heuristicDL); } @@ -1541,7 +1584,8 @@ int doHeuristics(CbcModel *model, int type, std::vector< CbcOrClpParam > paramet if (diveOptions2) { heuristicDP.setPercentageToFix(0.0); heuristicDP.setMaxSimplexIterations(COIN_INT_MAX); - heuristicDP.setMaxSimplexIterationsAtRoot(COIN_INT_MAX - (diveOptions2 - 1)); + heuristicDP.setMaxSimplexIterationsAtRoot(COIN_INT_MAX - + (diveOptions2 - 1)); } model->addHeuristic(&heuristicDP); } @@ -1622,21 +1666,30 @@ int doHeuristics(CbcModel *model, int type, std::vector< CbcOrClpParam > paramet model->addHeuristic(&heuristic2); anyToDo = true; } - if ((useProximity >= kType && useProximity <= kType + 1) || (kType == 1 && useProximity > 3)) { + if ((useProximity >= kType && useProximity <= kType + 1) || + (kType == 1 && useProximity > 3)) { CbcHeuristicProximity heuristic2a(*model); heuristic2a.setHeuristicName("Proximity Search"); heuristic2a.setFractionSmall(9999999.0); heuristic2a.setNumberNodes(30); heuristic2a.setFeasibilityPumpOptions(-2); if (useProximity >= 4) { - const int nodes[] = { 10, 100, 300 }; + const int nodes[] = {10, 100, 300}; heuristic2a.setNumberNodes(nodes[useProximity - 4]); // more print out and stronger feasibility pump if (useProximity == 6) heuristic2a.setFeasibilityPumpOptions(-3); } else { - int proximityNumber; - parameters_[whichParam(CBC_PARAM_STR_PROXIMITY, parameters_)].currentOptionAsInteger(proximityNumber); + //TODO: there should be a separate parameter for setting proximity number + std::string proximityKwd = parameters[CbcParam::PROXIMITY]->kwdVal(); + int proximityNumber = 0; + if (proximityKwd == "10"){ + proximityNumber = 10; + }else if (proximityKwd == "100"){ + proximityNumber = 300; + }else if (proximityKwd == "300"){ + proximityNumber = 300; + } if (proximityNumber > 0) { heuristic2a.setNumberNodes(proximityNumber); // more print out and stronger feasibility pump @@ -1657,7 +1710,8 @@ int doHeuristics(CbcModel *model, int type, std::vector< CbcOrClpParam > paramet model->setMaximumSavedSolutions(5); anyToDo = true; } - int heurSwitches = parameters_[whichParam(CBC_PARAM_INT_HOPTIONS, parameters_)].intValue() % 100; + int heurSwitches = parameters[CbcParam::HEUROPTIONS]->intVal() % + 100; if (heurSwitches) { for (int iHeur = 0; iHeur < model->numberHeuristics(); iHeur++) { CbcHeuristic *heuristic = model->heuristic(iHeur); @@ -1674,14 +1728,14 @@ int doHeuristics(CbcModel *model, int type, std::vector< CbcOrClpParam > paramet if (logLevel <= 1) model2.solver()->setHintParam(OsiDoReducePrint, true, OsiHintTry); OsiBabSolver defaultC; - //solver_->setAuxiliaryInfo(&defaultC); + // solver_->setAuxiliaryInfo(&defaultC); model2.passInSolverCharacteristics(&defaultC); // Save bounds int numberColumns = model2.solver()->getNumCols(); model2.createContinuousSolver(); bool cleanModel = !model2.numberIntegers() && !model2.numberObjects(); model2.findIntegers(false); - int heurOptions = (parameters_[whichParam(CBC_PARAM_INT_HOPTIONS, parameters_)].intValue() / 100) % 100; + int heurOptions = (parameters[CbcParam::HEUROPTIONS]->intVal() / 100) % 100; if (heurOptions == 0 || heurOptions == 2) { model2.doHeuristicsAtRoot(1); } else if (heurOptions == 1 || heurOptions == 3) { @@ -1704,7 +1758,7 @@ int doHeuristics(CbcModel *model, int type, std::vector< CbcOrClpParam > paramet if (logLevel <= 1) model->solver()->setHintParam(OsiDoReducePrint, true, OsiHintTry); OsiBabSolver defaultC; - //solver_->setAuxiliaryInfo(&defaultC); + // solver_->setAuxiliaryInfo(&defaultC); model->passInSolverCharacteristics(&defaultC); // Save bounds int numberColumns = model->solver()->getNumCols(); @@ -1722,4 +1776,4 @@ int doHeuristics(CbcModel *model, int type, std::vector< CbcOrClpParam > paramet } /* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 -*/ + */ diff --git a/src/CbcSolverHeuristics.hpp b/src/CbcSolverHeuristics.hpp index c4913878f..8fbb029d3 100644 --- a/src/CbcSolverHeuristics.hpp +++ b/src/CbcSolverHeuristics.hpp @@ -35,8 +35,8 @@ fixVubs(CbcModel &model, int skipZero2, 3 - for miplib test so skip some (out model later) */ -int doHeuristics(CbcModel *model, int type, std::vector< CbcOrClpParam > parameters_, - int noPrinting_, int initialPumpTune); +int doHeuristics(CbcModel *model, int type, CbcParameters ¶meters, + int noPrinting_, int initialPumpTune); #endif //CbcSolverHeuristics_H diff --git a/src/Cbc_C_Interface.cpp b/src/Cbc_C_Interface.cpp index 24f4098ef..3e4220a73 100644 --- a/src/Cbc_C_Interface.cpp +++ b/src/Cbc_C_Interface.cpp @@ -10,6 +10,7 @@ #include #include #include +#include #include "Cbc_C_Interface.h" @@ -62,7 +63,6 @@ using namespace std; -static char **to_char_vec( const vector< string > &names ); static void *xmalloc( const size_t size ); static void *xrealloc( void *ptr, const size_t newSize ); static void Cbc_updateSlack( Cbc_Model *model, const double *ractivity ); @@ -323,7 +323,8 @@ struct Cbc_Model { m->model_->solver()->prop(index, val); \ } -const int VERBOSE = 0; +//TODO Why is this here? +//const int VERBOSE = 0; typedef std::map< std::string, int > NameIndex; @@ -1469,7 +1470,7 @@ void CBC_LINKAGE Cbc_computeFeatures(Cbc_Model *model, double *features) { OsiFeatures::compute(features, model->solver_); } -CBCSOLVERLIB_EXPORT int CBC_LINKAGE +CBCLIB_EXPORT int CBC_LINKAGE Cbc_nFeatures() { return OsiFeatures::n; } @@ -1774,7 +1775,11 @@ Cbc_solveLinearProgram(Cbc_Model *model) if (model->lp_method == LPM_Auto) { ClpSimplexOther *clpo = static_cast(clps); assert(clpo); - char *opts = clpo->guess(0); + // Hacky for now + std::string opts_str(clpo->guess(0)); + char opts[256]; + assert (opts_str.length() <= 256); + strcpy(opts, opts_str.c_str()); if (opts) { if (strstr(opts, "-primals") != NULL) { @@ -1834,7 +1839,6 @@ Cbc_solveLinearProgram(Cbc_Model *model) //printf("Setting dual pivot to pesteep.\n"); } } // dual pivot - delete[] opts; } } // auto @@ -2258,9 +2262,9 @@ Cbc_solve(Cbc_Model *model) cbcModel.passInMessageHandler(cbcmh); } - CbcSolverUsefulData cbcData; - CbcMain0(cbcModel, cbcData); - cbcData.printWelcome_ = false; + CbcParameters parameters; + CbcMain0(cbcModel, parameters); + parameters.disableWelcomePrinting(); // adds SOSs if any Cbc_addAllSOS(model, cbcModel); @@ -2288,28 +2292,23 @@ Cbc_solve(Cbc_Model *model) cbcModel.setLogLevel( model->int_param[INT_PARAM_LOG_LEVEL] ); // aditional parameters specified by user as strings - std::vector< string > argv; - argv.push_back("Cbc_C_Interface"); + std::deque< string > inputQueue; for ( size_t i=0 ; ivcbcOptions.size() ; ++i ) { string param = model->vcbcOptions[i]; string val = model->cbcOptions[param]; if (val.size()) { stringstream ss; ss << "-" << param << "=" << val; - argv.push_back(ss.str().c_str()); + inputQueue.push_back(ss.str().c_str()); } else { stringstream ss; ss << "-" << param; - argv.push_back(ss.str()); + inputQueue.push_back(ss.str()); } } - argv.push_back("-solve"); - argv.push_back("-quit"); - - char **charCbcOpts = to_char_vec(argv); - const int nargs = (int) argv.size(); - const char **args = (const char **)charCbcOpts; + inputQueue.push_back("-solve"); + inputQueue.push_back("-quit"); OsiBabSolver defaultC; if (model->cutCBAtSol) { @@ -2335,12 +2334,10 @@ Cbc_solve(Cbc_Model *model) cbcModel.setRandomSeed(model->int_param[INT_PARAM_RANDOM_SEED]); cbcModel.setUseElapsedTime( (model->int_param[INT_PARAM_ELAPSED_TIME] == 1) ); - CbcMain1( nargs, args, cbcModel, cbc_callb, cbcData ); + CbcMain1(inputQueue, cbcModel, parameters, cbc_callb); Cbc_getMIPOptimizationResults( model, cbcModel ); - free(charCbcOpts); - if (cbc_eh) delete cbc_eh; @@ -4714,26 +4711,6 @@ Cbc_getRowNameIndex(Cbc_Model *model, const char *name) return it->second; } -static char **to_char_vec( const vector< string > &names ) -{ - size_t spaceVec = (sizeof(char*)*names.size()); - size_t totLen = names.size(); // all \0 - for ( int i=0 ; (i<(int)names.size()) ; ++i ) - totLen += names[i].size(); - totLen *= sizeof(char); - - char **r = (char **)xmalloc(spaceVec+totLen); - assert( r ); - r[0] = (char *)(r + names.size()); - for ( size_t i=1 ; (i=, E if =, R if ranged and N if free * @param rhs right hand size * */ -CBCSOLVERLIB_EXPORT void CBC_LINKAGE +CBCLIB_EXPORT void CBC_LINKAGE Cbc_addRow(Cbc_Model *model, const char *name, int nz, const int *cols, const double *coefs, char sense, double rhs); @@ -256,7 +256,7 @@ Cbc_addRow(Cbc_Model *model, const char *name, int nz, * integer solution violating it is generated. * **/ -CBCSOLVERLIB_EXPORT void CBC_LINKAGE +CBCLIB_EXPORT void CBC_LINKAGE Cbc_addLazyConstraint(Cbc_Model *model, int nz, int *cols, double *coefs, char sense, double rhs); @@ -268,16 +268,16 @@ Cbc_addLazyConstraint(Cbc_Model *model, int nz, * @param numRows number of rows * @param rows rows to be deleted * */ -CBCSOLVERLIB_EXPORT void CBC_LINKAGE +CBCLIB_EXPORT void CBC_LINKAGE Cbc_deleteRows(Cbc_Model *model, int numRows, const int rows[]); /** @brief Add SOS constraints to the model using row-order matrix */ -CBCSOLVERLIB_EXPORT void CBC_LINKAGE +CBCLIB_EXPORT void CBC_LINKAGE Cbc_addSOS(Cbc_Model *model, int numRows, const int *rowStarts, const int *colIndices, const double *weights, const int type); /** @brief Queries the number os SOS objects */ -CBCSOLVERLIB_EXPORT int CBC_LINKAGE Cbc_numberSOS(Cbc_Model *model); +CBCLIB_EXPORT int CBC_LINKAGE Cbc_numberSOS(Cbc_Model *model); /** Loads a problem (the constraints on the rows are given by lower and upper bounds). If a pointer is NULL then the @@ -298,7 +298,7 @@ CBCSOLVERLIB_EXPORT int CBC_LINKAGE Cbc_numberSOS(Cbc_Model *model);
  • value[k] stores the coefficient of the kth nonzero element */ -CBCSOLVERLIB_EXPORT void CBC_LINKAGE +CBCLIB_EXPORT void CBC_LINKAGE Cbc_loadProblem(Cbc_Model *model, const int numcols, const int numrows, const CoinBigIndex *start, const int *index, const double *value, @@ -312,7 +312,7 @@ Cbc_loadProblem(Cbc_Model *model, const int numcols, const int numrows, * @param iColumn column index * @param column name **/ -CBCSOLVERLIB_EXPORT void CBC_LINKAGE +CBCLIB_EXPORT void CBC_LINKAGE Cbc_setColName(Cbc_Model *model, int iColumn, const char *name); /** @brief Set the name of a row @@ -321,7 +321,7 @@ Cbc_setColName(Cbc_Model *model, int iColumn, const char *name); * @param iRow row index * @param name row name **/ -CBCSOLVERLIB_EXPORT void CBC_LINKAGE +CBCLIB_EXPORT void CBC_LINKAGE Cbc_setRowName(Cbc_Model *model, int iRow, const char *name); /** @brief Sets optimization direction @@ -329,7 +329,7 @@ Cbc_setRowName(Cbc_Model *model, int iRow, const char *name); * @param model problem object * @param sense: direction of optimization (1 - minimize, -1 - maximize, 0 - ignore) **/ -CBCSOLVERLIB_EXPORT void CBC_LINKAGE +CBCLIB_EXPORT void CBC_LINKAGE Cbc_setObjSense(Cbc_Model *model, double sense); /** @brief Set the lower bound of a single constraint @@ -338,7 +338,7 @@ Cbc_setObjSense(Cbc_Model *model, double sense); * @param index row index * @param value new row lower bound **/ -CBCSOLVERLIB_EXPORT void CBC_LINKAGE +CBCLIB_EXPORT void CBC_LINKAGE Cbc_setRowLower(Cbc_Model *model, int index, double value); /** @brief Set the upper bound of a single constraint @@ -347,7 +347,7 @@ Cbc_setRowLower(Cbc_Model *model, int index, double value); * @param index row index * @param value new row upper bound **/ -CBCSOLVERLIB_EXPORT void CBC_LINKAGE +CBCLIB_EXPORT void CBC_LINKAGE Cbc_setRowUpper(Cbc_Model *model, int index, double value); /** @brief Sets the RHS of a constraint @@ -356,7 +356,7 @@ Cbc_setRowUpper(Cbc_Model *model, int index, double value); * @param row row index * @param rhs value of the new RHS **/ -CBCSOLVERLIB_EXPORT void CBC_LINKAGE +CBCLIB_EXPORT void CBC_LINKAGE Cbc_setRowRHS(Cbc_Model *model, int row, double rhs); /** @brief Set the objective coefficient of a single variable @@ -365,7 +365,7 @@ Cbc_setRowRHS(Cbc_Model *model, int row, double rhs); * @param index variable index * @param value new objective function coefficient for this variable **/ -CBCSOLVERLIB_EXPORT void CBC_LINKAGE +CBCLIB_EXPORT void CBC_LINKAGE Cbc_setObjCoeff(Cbc_Model *model, int index, double value); /** @brief Set the lower bound of a single variable @@ -374,7 +374,7 @@ Cbc_setObjCoeff(Cbc_Model *model, int index, double value); * @param index variable index * @param value variable lower bound **/ -CBCSOLVERLIB_EXPORT void CBC_LINKAGE +CBCLIB_EXPORT void CBC_LINKAGE Cbc_setColLower(Cbc_Model *model, int index, double value); /** @brief Set the upper bound of a single variable @@ -383,7 +383,7 @@ Cbc_setColLower(Cbc_Model *model, int index, double value); * @param index variable index * @param value new variable upper bound **/ -CBCSOLVERLIB_EXPORT void CBC_LINKAGE +CBCLIB_EXPORT void CBC_LINKAGE Cbc_setColUpper(Cbc_Model *model, int index, double value); /** @brief Set this variable to be continuous @@ -391,7 +391,7 @@ Cbc_setColUpper(Cbc_Model *model, int index, double value); * @param model problem object * @param iColumn column index **/ -CBCSOLVERLIB_EXPORT void CBC_LINKAGE +CBCLIB_EXPORT void CBC_LINKAGE Cbc_setContinuous(Cbc_Model *model, int iColumn); /** @brief Set this variable to be integer @@ -399,13 +399,13 @@ Cbc_setContinuous(Cbc_Model *model, int iColumn); * @param model problem object * @param iColumn column index **/ -CBCSOLVERLIB_EXPORT void CBC_LINKAGE +CBCLIB_EXPORT void CBC_LINKAGE Cbc_setInteger(Cbc_Model *model, int iColumn); /** @brief Frees memory of model object * * @param model problem object */ -CBCSOLVERLIB_EXPORT void CBC_LINKAGE +CBCLIB_EXPORT void CBC_LINKAGE Cbc_deleteModel(Cbc_Model *model); /** @brief Enter initial feasible solution @@ -421,7 +421,7 @@ Cbc_deleteModel(Cbc_Model *model); * @param colValues variable values * **/ -CBCSOLVERLIB_EXPORT void CBC_LINKAGE +CBCLIB_EXPORT void CBC_LINKAGE Cbc_setMIPStart(Cbc_Model *model, int count, const char **colNames, const double colValues[]); /** @brief Enter initial feasible solution @@ -437,7 +437,7 @@ Cbc_setMIPStart(Cbc_Model *model, int count, const char **colNames, const double * @param colValues variable values * **/ -CBCSOLVERLIB_EXPORT void CBC_LINKAGE +CBCLIB_EXPORT void CBC_LINKAGE Cbc_setMIPStartI(Cbc_Model *model, int count, const int colIdxs[], const double colValues[]); /** @brief Reads an initial feasible solution from a file @@ -450,7 +450,7 @@ Cbc_setMIPStartI(Cbc_Model *model, int count, const int colIdxs[], const double * @param model problem object * @param fileName problem object **/ -CBCSOLVERLIB_EXPORT void CBC_LINKAGE +CBCLIB_EXPORT void CBC_LINKAGE Cbc_readMIPStart(Cbc_Model *model, const char fileName[]); /** @brief Creates a copy of the current model @@ -458,7 +458,7 @@ Cbc_readMIPStart(Cbc_Model *model, const char fileName[]); * @param model problem object * @return model copy **/ -CBCSOLVERLIB_EXPORT Cbc_Model *CBC_LINKAGE +CBCLIB_EXPORT Cbc_Model *CBC_LINKAGE Cbc_clone(Cbc_Model *model); /** @brief Clears the current solution @@ -467,7 +467,7 @@ Cbc_clone(Cbc_Model *model); * * @param model problem object **/ -CBCSOLVERLIB_EXPORT void CBC_LINKAGE +CBCLIB_EXPORT void CBC_LINKAGE Cbc_reset(Cbc_Model *model); /** \name Routines to query problem contents @@ -479,7 +479,7 @@ Cbc_reset(Cbc_Model *model); * @param maxNumberCharacters space in string array * @param array string where problem name will be saved **/ -CBCSOLVERLIB_EXPORT void CBC_LINKAGE +CBCLIB_EXPORT void CBC_LINKAGE Cbc_problemName(Cbc_Model *model, int maxNumberCharacters, char *array); /** @brief Number of nonzero elements in constraint matrix @@ -487,7 +487,7 @@ Cbc_problemName(Cbc_Model *model, int maxNumberCharacters, char *array); * @param model problem object * @return number of non-zero entries in constraint matrix **/ -CBCSOLVERLIB_EXPORT int CBC_LINKAGE +CBCLIB_EXPORT int CBC_LINKAGE Cbc_getNumElements(Cbc_Model *model); /** @brief Number of variables in the model @@ -495,7 +495,7 @@ Cbc_getNumElements(Cbc_Model *model); * @param model problem object * @return number of columns (variables) **/ -CBCSOLVERLIB_EXPORT int CBC_LINKAGE +CBCLIB_EXPORT int CBC_LINKAGE Cbc_getNumCols(Cbc_Model *model); /** @brief Number of integer variables in the model @@ -503,14 +503,14 @@ Cbc_getNumCols(Cbc_Model *model); * @param model problem object * @return number of integer variables in this model **/ -CBCSOLVERLIB_EXPORT int CBC_LINKAGE +CBCLIB_EXPORT int CBC_LINKAGE Cbc_getNumIntegers(Cbc_Model *model); /** @brief Number of constraints in the model * @param model problem object * @return number of rows (constraints) in the model **/ -CBCSOLVERLIB_EXPORT int CBC_LINKAGE +CBCLIB_EXPORT int CBC_LINKAGE Cbc_getNumRows(Cbc_Model *model); /** @brief Queries row name @@ -520,7 +520,7 @@ Cbc_getNumRows(Cbc_Model *model); * @param name string where row name will be stored * @param string where row name will be stored **/ -CBCSOLVERLIB_EXPORT void CBC_LINKAGE +CBCLIB_EXPORT void CBC_LINKAGE Cbc_getRowName(Cbc_Model *model, int iRow, char *name, size_t maxLength); /** @brief Queries column name @@ -530,7 +530,7 @@ Cbc_getRowName(Cbc_Model *model, int iRow, char *name, size_t maxLength); * @param name where name will be stored * @param maxLength maximum length of name string **/ -CBCSOLVERLIB_EXPORT void CBC_LINKAGE +CBCLIB_EXPORT void CBC_LINKAGE Cbc_getColName(Cbc_Model *model, int iColumn, char *name, size_t maxLength); /** @brief searches columns by name and returns its index @@ -541,7 +541,7 @@ Cbc_getColName(Cbc_Model *model, int iColumn, char *name, size_t maxLength); * @param name column (variable) name * @return column index or -1 if not found **/ -CBCSOLVERLIB_EXPORT int CBC_LINKAGE +CBCLIB_EXPORT int CBC_LINKAGE Cbc_getColNameIndex(Cbc_Model *model, const char *name); /** @brief searches rows by name and returns its index @@ -552,7 +552,7 @@ Cbc_getColNameIndex(Cbc_Model *model, const char *name); * @param name row (constraint) name * @return row index or -1 if not found **/ -CBCSOLVERLIB_EXPORT int CBC_LINKAGE +CBCLIB_EXPORT int CBC_LINKAGE Cbc_getRowNameIndex(Cbc_Model *model, const char *name); /** @brief Number of non-zero entries in a row @@ -561,7 +561,7 @@ Cbc_getRowNameIndex(Cbc_Model *model, const char *name); * @param row row index * @return number of non-zero entries in row **/ -CBCSOLVERLIB_EXPORT int CBC_LINKAGE +CBCLIB_EXPORT int CBC_LINKAGE Cbc_getRowNz(Cbc_Model *model, int row); /** @brief Indices of variables that appear on a row @@ -570,7 +570,7 @@ Cbc_getRowNz(Cbc_Model *model, int row); * @param row row index * @return vector with indexes of columns that appear on this row **/ -CBCSOLVERLIB_EXPORT const int *CBC_LINKAGE +CBCLIB_EXPORT const int *CBC_LINKAGE Cbc_getRowIndices(Cbc_Model *model, int row); /** @brief Coefficients of variables that appear on this row @@ -579,7 +579,7 @@ Cbc_getRowIndices(Cbc_Model *model, int row); * @param row row index * @return coefficients of variables that appear on this row **/ -CBCSOLVERLIB_EXPORT const double *CBC_LINKAGE +CBCLIB_EXPORT const double *CBC_LINKAGE Cbc_getRowCoeffs(Cbc_Model *model, int row); typedef struct { @@ -598,7 +598,7 @@ typedef struct { * @param rowIdx row index * @return a Cbc_Row structure, with all the row information **/ -CBCSOLVERLIB_EXPORT Cbc_Row CBC_LINKAGE Cbc_getRow( Cbc_Model *model, int rowIdx ); +CBCLIB_EXPORT Cbc_Row CBC_LINKAGE Cbc_getRow( Cbc_Model *model, int rowIdx ); /** @brief Number of non-zero entries in a column * @@ -606,7 +606,7 @@ CBCSOLVERLIB_EXPORT Cbc_Row CBC_LINKAGE Cbc_getRow( Cbc_Model *model, int rowIdx * @param col column index * @return numbef of rows that this column appears **/ -CBCSOLVERLIB_EXPORT int CBC_LINKAGE +CBCLIB_EXPORT int CBC_LINKAGE Cbc_getColNz(Cbc_Model *model, int col); /** @brief Indices of rows that a column appears @@ -615,7 +615,7 @@ Cbc_getColNz(Cbc_Model *model, int col); * @param col column index * @return indices of rows that this column appears **/ -CBCSOLVERLIB_EXPORT const int *CBC_LINKAGE +CBCLIB_EXPORT const int *CBC_LINKAGE Cbc_getColIndices(Cbc_Model *model, int col); /** @brief Coefficients that a column appear in rows @@ -624,7 +624,7 @@ Cbc_getColIndices(Cbc_Model *model, int col); * @param col column index * @return coefficients of this column in rows **/ -CBCSOLVERLIB_EXPORT const double *CBC_LINKAGE +CBCLIB_EXPORT const double *CBC_LINKAGE Cbc_getColCoeffs(Cbc_Model *model, int col); typedef struct { @@ -642,7 +642,7 @@ typedef struct { * @param idx column index * @return column information in a Cbc_Column structure **/ -CBCSOLVERLIB_EXPORT Cbc_Column CBC_LINKAGE +CBCLIB_EXPORT Cbc_Column CBC_LINKAGE Cbc_getColumn(Cbc_Model *model, int colIdx ); @@ -653,7 +653,7 @@ Cbc_getColumn(Cbc_Model *model, int colIdx ); * @param row row index * @return row right hand side **/ -CBCSOLVERLIB_EXPORT double CBC_LINKAGE +CBCLIB_EXPORT double CBC_LINKAGE Cbc_getRowRHS(Cbc_Model *model, int row); /** @brief Upper bound of ranged constraint @@ -662,7 +662,7 @@ Cbc_getRowRHS(Cbc_Model *model, int row); * @param row row index * @return row upper bound **/ -CBCSOLVERLIB_EXPORT double CBC_LINKAGE +CBCLIB_EXPORT double CBC_LINKAGE Cbc_getRowUB(Cbc_Model *model, int row); /** @brief Lower bound of ranged constraint @@ -671,7 +671,7 @@ Cbc_getRowUB(Cbc_Model *model, int row); * @param row row index * @return row lower bound **/ -CBCSOLVERLIB_EXPORT double CBC_LINKAGE +CBCLIB_EXPORT double CBC_LINKAGE Cbc_getRowLB(Cbc_Model *model, int row); @@ -683,7 +683,7 @@ Cbc_getRowLB(Cbc_Model *model, int row); * @param row row index * @return row sense: E for =, L for <=, G for >= and R for ranged row **/ -CBCSOLVERLIB_EXPORT char CBC_LINKAGE +CBCLIB_EXPORT char CBC_LINKAGE Cbc_getRowSense(Cbc_Model *model, int row); /** @brief Direction of optimization @@ -691,7 +691,7 @@ Cbc_getRowSense(Cbc_Model *model, int row); * @param model problem object * @return Direction of optimization (1 - minimize, -1 - maximize, 0 - ignore) **/ -CBCSOLVERLIB_EXPORT double CBC_LINKAGE +CBCLIB_EXPORT double CBC_LINKAGE Cbc_getObjSense(Cbc_Model *model); /** @brief Constraint lower bounds @@ -699,7 +699,7 @@ Cbc_getObjSense(Cbc_Model *model); * @param model problem object * @return vector with lower bounds of constraints **/ -CBCSOLVERLIB_EXPORT const double *CBC_LINKAGE +CBCLIB_EXPORT const double *CBC_LINKAGE Cbc_getRowLower(Cbc_Model *model); /** @brief Constraint upper bounds @@ -707,7 +707,7 @@ Cbc_getRowLower(Cbc_Model *model); * @param model problem object * @return constraint upper bounds **/ -CBCSOLVERLIB_EXPORT const double *CBC_LINKAGE +CBCLIB_EXPORT const double *CBC_LINKAGE Cbc_getRowUpper(Cbc_Model *model); /** @brief Objective function coefficients vector @@ -715,7 +715,7 @@ Cbc_getRowUpper(Cbc_Model *model); * @param model problem object * @return vector with coefficients of variables in the objective function **/ -CBCSOLVERLIB_EXPORT const double *CBC_LINKAGE +CBCLIB_EXPORT const double *CBC_LINKAGE Cbc_getObjCoefficients(Cbc_Model *model); /** @brief Queries the objective function coefficient of one variable @@ -724,7 +724,7 @@ Cbc_getObjCoefficients(Cbc_Model *model); * @param colIdx column index * @return objective function coefficient of the variable **/ -CBCSOLVERLIB_EXPORT double CBC_LINKAGE +CBCLIB_EXPORT double CBC_LINKAGE Cbc_getColObj(Cbc_Model *model, int colIdx); /** @brief Variable lower bounds @@ -732,7 +732,7 @@ Cbc_getColObj(Cbc_Model *model, int colIdx); * @param model problem object * @return vector with lower bounds of variables **/ -CBCSOLVERLIB_EXPORT const double *CBC_LINKAGE +CBCLIB_EXPORT const double *CBC_LINKAGE Cbc_getColLower(Cbc_Model *model); /** @brief Queries the lower bound of one variable @@ -741,7 +741,7 @@ Cbc_getColLower(Cbc_Model *model); * @param colIdx column index * @return lower bound of the variable **/ -CBCSOLVERLIB_EXPORT double CBC_LINKAGE +CBCLIB_EXPORT double CBC_LINKAGE Cbc_getColLB(Cbc_Model *model, int colIdx); @@ -750,7 +750,7 @@ Cbc_getColLB(Cbc_Model *model, int colIdx); * @param model problem object * @return vector with column upper bounds **/ -CBCSOLVERLIB_EXPORT const double *CBC_LINKAGE +CBCLIB_EXPORT const double *CBC_LINKAGE Cbc_getColUpper(Cbc_Model *model); /** @brief Queries the upper bound of one variable @@ -759,7 +759,7 @@ Cbc_getColUpper(Cbc_Model *model); * @param colIdx column index * @return upper bound of the variable **/ -CBCSOLVERLIB_EXPORT double CBC_LINKAGE +CBCLIB_EXPORT double CBC_LINKAGE Cbc_getColUB(Cbc_Model *model, int colIdx); @@ -769,7 +769,7 @@ Cbc_getColUB(Cbc_Model *model, int colIdx); * @param i variable index * @return 1 if variable is integer, 0 otherwise **/ -CBCSOLVERLIB_EXPORT int CBC_LINKAGE +CBCLIB_EXPORT int CBC_LINKAGE Cbc_isInteger(Cbc_Model *model, int i); /** @brief Computes vector of instance features @@ -780,7 +780,7 @@ Cbc_isInteger(Cbc_Model *model, int i); * @param model problem object * @param features vector of size Cbc_nFeatures() that will be filled with problem features **/ -CBCSOLVERLIB_EXPORT void CBC_LINKAGE +CBCLIB_EXPORT void CBC_LINKAGE Cbc_computeFeatures(Cbc_Model *model, double *features); /** @brief Returns the number of instance features @@ -788,7 +788,7 @@ Cbc_computeFeatures(Cbc_Model *model, double *features); * Returns the number of instance features that can be computed in function * Cbc_computeFeatures. **/ -CBCSOLVERLIB_EXPORT int CBC_LINKAGE +CBCLIB_EXPORT int CBC_LINKAGE Cbc_nFeatures(); /** @brief Name of the i-th instance features @@ -798,7 +798,7 @@ Cbc_nFeatures(); * * @param model problem object **/ - CBCSOLVERLIB_EXPORT const char * CBC_LINKAGE + CBCLIB_EXPORT const char * CBC_LINKAGE Cbc_featureName(int i); /** @brief Returns the conflict graph of the model @@ -809,13 +809,13 @@ Cbc_nFeatures(); * @param model problem object * @return a CoinConflictGraph object **/ -CBCSOLVERLIB_EXPORT const void *CBC_LINKAGE Cbc_conflictGraph( Cbc_Model *model ); +CBCLIB_EXPORT const void *CBC_LINKAGE Cbc_conflictGraph( Cbc_Model *model ); /** @brief Updates (or creates, if first time) the conflict graph * * @param model problem object **/ -CBCSOLVERLIB_EXPORT void CBC_LINKAGE Cbc_updateConflictGraph( Cbc_Model *model ); +CBCLIB_EXPORT void CBC_LINKAGE Cbc_updateConflictGraph( Cbc_Model *model ); /** \name Routines to load and save problems from disk */ @@ -825,7 +825,7 @@ CBCSOLVERLIB_EXPORT void CBC_LINKAGE Cbc_updateConflictGraph( Cbc_Model *model ) * @param model problem object * @param fileName file name **/ -CBCSOLVERLIB_EXPORT int CBC_LINKAGE +CBCLIB_EXPORT int CBC_LINKAGE Cbc_readMps(Cbc_Model *model, const char *filename); /** @brief Read a LP file from the given filename @@ -833,7 +833,7 @@ Cbc_readMps(Cbc_Model *model, const char *filename); * @param model problem object * @param fileName file name **/ -CBCSOLVERLIB_EXPORT int CBC_LINKAGE +CBCLIB_EXPORT int CBC_LINKAGE Cbc_readLp(Cbc_Model *model, const char *filename); /** @brief Read the optimal basis for the linear program @@ -842,7 +842,7 @@ Cbc_readLp(Cbc_Model *model, const char *filename); * @param fileName file name * @return returns -1 on file error, 0 if no values, 1 if values. **/ -CBCSOLVERLIB_EXPORT int CBC_LINKAGE +CBCLIB_EXPORT int CBC_LINKAGE Cbc_readBasis(Cbc_Model *model, const char *filename); @@ -851,7 +851,7 @@ Cbc_readBasis(Cbc_Model *model, const char *filename); * @param model problem object * @param fileName file name **/ -CBCSOLVERLIB_EXPORT void CBC_LINKAGE +CBCLIB_EXPORT void CBC_LINKAGE Cbc_writeMps(Cbc_Model *model, const char *filename); /** @brief Write an LP file from the given filename @@ -859,7 +859,7 @@ Cbc_writeMps(Cbc_Model *model, const char *filename); * @param model problem object * @param fileName file name **/ -CBCSOLVERLIB_EXPORT void CBC_LINKAGE +CBCLIB_EXPORT void CBC_LINKAGE Cbc_writeLp(Cbc_Model *model, const char *filename); /** @brief Saves the optimal basis for the linear program @@ -870,7 +870,7 @@ Cbc_writeLp(Cbc_Model *model, const char *filename); * @param formatType 0 - normal, 1 - extra accuracy, 2 - IEEE hex(later) * @return non-zero on IO error **/ -CBCSOLVERLIB_EXPORT int CBC_LINKAGE +CBCLIB_EXPORT int CBC_LINKAGE Cbc_writeBasis(Cbc_Model *model, const char *filename, char writeValues, int formatType); @@ -878,14 +878,14 @@ Cbc_writeBasis(Cbc_Model *model, const char *filename, char writeValues, int for * * @return 1 if yes, 0 otherwise **/ -CBCSOLVERLIB_EXPORT char CBC_LINKAGE +CBCLIB_EXPORT char CBC_LINKAGE Cbc_supportsGzip(); /** @brief If Cbc was built with bzip2 compressed files support * * @return 1 if yes, 0 otherwise **/ -CBCSOLVERLIB_EXPORT char CBC_LINKAGE +CBCLIB_EXPORT char CBC_LINKAGE Cbc_supportsBzip2(); /**@name Getting and setting model data @@ -901,23 +901,23 @@ Cbc_supportsBzip2(); /** Provide an initial feasible solution to accelerate branch-and-bound Note that feasibility of the solution is *not* verified. */ -CBCSOLVERLIB_EXPORT void CBC_LINKAGE +CBCLIB_EXPORT void CBC_LINKAGE Cbc_setInitialSolution(Cbc_Model *model, const double *sol); /** "Column start" vector of constraint matrix. Same format as Cbc_loadProblem() */ -CBCSOLVERLIB_EXPORT const CoinBigIndex *CBC_LINKAGE +CBCLIB_EXPORT const CoinBigIndex *CBC_LINKAGE Cbc_getVectorStarts(Cbc_Model *model); /** "Row index" vector of constraint matrix */ -CBCSOLVERLIB_EXPORT const int *CBC_LINKAGE +CBCLIB_EXPORT const int *CBC_LINKAGE Cbc_getIndices(Cbc_Model *model); /** Coefficient vector of constraint matrix */ -CBCSOLVERLIB_EXPORT const double *CBC_LINKAGE +CBCLIB_EXPORT const double *CBC_LINKAGE Cbc_getElements(Cbc_Model *model); /** Maximum lenght of a row or column name */ -CBCSOLVERLIB_EXPORT size_t CBC_LINKAGE +CBCLIB_EXPORT size_t CBC_LINKAGE Cbc_maxNameLength(Cbc_Model *model); /*@}*/ @@ -932,7 +932,7 @@ Cbc_maxNameLength(Cbc_Model *model); * @param name parameter value, e.g. off * **/ -CBCSOLVERLIB_EXPORT void CBC_LINKAGE +CBCLIB_EXPORT void CBC_LINKAGE Cbc_setParameter(Cbc_Model *model, const char *name, const char *value); /** Gets the current value of an integer parameter @@ -942,7 +942,7 @@ Cbc_setParameter(Cbc_Model *model, const char *name, const char *value); * @return parameter value * **/ -CBCSOLVERLIB_EXPORT int CBC_LINKAGE +CBCLIB_EXPORT int CBC_LINKAGE Cbc_getIntParam(Cbc_Model *model, enum IntParam which); /** Sets an integer parameter @@ -952,7 +952,7 @@ Cbc_getIntParam(Cbc_Model *model, enum IntParam which); * @param val value * **/ -CBCSOLVERLIB_EXPORT void CBC_LINKAGE +CBCLIB_EXPORT void CBC_LINKAGE Cbc_setIntParam(Cbc_Model *model, enum IntParam which, const int val); /** Sets a double parameter @@ -962,7 +962,7 @@ Cbc_setIntParam(Cbc_Model *model, enum IntParam which, const int val); * @param val value * **/ -CBCSOLVERLIB_EXPORT void CBC_LINKAGE +CBCLIB_EXPORT void CBC_LINKAGE Cbc_setDblParam(Cbc_Model *model, enum DblParam which, const double val); /** Gets the current value of a double parameter @@ -972,7 +972,7 @@ Cbc_setDblParam(Cbc_Model *model, enum DblParam which, const double val); * @return parameter value * **/ -CBCSOLVERLIB_EXPORT double CBC_LINKAGE +CBCLIB_EXPORT double CBC_LINKAGE Cbc_getDblParam(Cbc_Model *model, enum DblParam which); /** @brief returns the allowable gap @@ -981,7 +981,7 @@ Cbc_getDblParam(Cbc_Model *model, enum DblParam which); * @return the maximum allowable gap between the lower bound and the upper bound, when * the gap decrease to a smaller value the search is concluded */ -CBCSOLVERLIB_EXPORT double CBC_LINKAGE +CBCLIB_EXPORT double CBC_LINKAGE Cbc_getAllowableGap(Cbc_Model *model); /** @brief sets the allowable gap @@ -991,104 +991,104 @@ Cbc_getAllowableGap(Cbc_Model *model); * the gap decrease to a smaller value the search is concluded */ -CBCSOLVERLIB_EXPORT void CBC_LINKAGE +CBCLIB_EXPORT void CBC_LINKAGE Cbc_setAllowableGap(Cbc_Model *model, double allowedGap); /** returns the allowable fraction gap */ -CBCSOLVERLIB_EXPORT double CBC_LINKAGE +CBCLIB_EXPORT double CBC_LINKAGE Cbc_getAllowableFractionGap(Cbc_Model *model); /** sets the allowable fraction gap */ -CBCSOLVERLIB_EXPORT void CBC_LINKAGE +CBCLIB_EXPORT void CBC_LINKAGE Cbc_setAllowableFractionGap(Cbc_Model *model, double allowedFracionGap); /** gets the tolerance for infeasibility in the LP solver */ -CBCSOLVERLIB_EXPORT double CBC_LINKAGE +CBCLIB_EXPORT double CBC_LINKAGE Cbc_getPrimalTolerance(Cbc_Model *model); /** sets the tolerance for infeasibility in the LP solver */ -CBCSOLVERLIB_EXPORT void CBC_LINKAGE +CBCLIB_EXPORT void CBC_LINKAGE Cbc_setPrimalTolerance(Cbc_Model *model, double tol); /** gets the tolerance for optimality in the LP solver */ -CBCSOLVERLIB_EXPORT double CBC_LINKAGE +CBCLIB_EXPORT double CBC_LINKAGE Cbc_getDualTolerance(Cbc_Model *model); /** sets the tolerance for optimality in the LP solver */ -CBCSOLVERLIB_EXPORT void CBC_LINKAGE +CBCLIB_EXPORT void CBC_LINKAGE Cbc_setDualTolerance(Cbc_Model *model, double tol); /** returns the time limit for the search process */ -CBCSOLVERLIB_EXPORT double CBC_LINKAGE +CBCLIB_EXPORT double CBC_LINKAGE Cbc_getMaximumSeconds(Cbc_Model *model); /** sets the time limit for the search process */ -CBCSOLVERLIB_EXPORT void CBC_LINKAGE +CBCLIB_EXPORT void CBC_LINKAGE Cbc_setMaximumSeconds(Cbc_Model *model, double maxSeconds); /** returns the maximum number of nodes that can be explored in the search tree */ -CBCSOLVERLIB_EXPORT int CBC_LINKAGE +CBCLIB_EXPORT int CBC_LINKAGE Cbc_getMaximumNodes(Cbc_Model *model); /** sets the maximum number of nodes that can be explored in the search tree */ -CBCSOLVERLIB_EXPORT void CBC_LINKAGE +CBCLIB_EXPORT void CBC_LINKAGE Cbc_setMaximumNodes(Cbc_Model *model, int maxNodes); /** returns solution limit for the search process */ -CBCSOLVERLIB_EXPORT int CBC_LINKAGE +CBCLIB_EXPORT int CBC_LINKAGE Cbc_getMaximumSolutions(Cbc_Model *model); /** sets a solution limit as a stopping criterion */ -CBCSOLVERLIB_EXPORT void CBC_LINKAGE +CBCLIB_EXPORT void CBC_LINKAGE Cbc_setMaximumSolutions(Cbc_Model *model, int maxSolutions); /** returns the current log leven */ -CBCSOLVERLIB_EXPORT int CBC_LINKAGE +CBCLIB_EXPORT int CBC_LINKAGE Cbc_getLogLevel(Cbc_Model *model); /** sets the log level */ -CBCSOLVERLIB_EXPORT void CBC_LINKAGE +CBCLIB_EXPORT void CBC_LINKAGE Cbc_setLogLevel(Cbc_Model *model, int logLevel); /** returns the cutoff */ -CBCSOLVERLIB_EXPORT double CBC_LINKAGE +CBCLIB_EXPORT double CBC_LINKAGE Cbc_getCutoff(Cbc_Model *model); /** sets the cutoff */ -CBCSOLVERLIB_EXPORT void CBC_LINKAGE +CBCLIB_EXPORT void CBC_LINKAGE Cbc_setCutoff(Cbc_Model *model, double cutoff); /** sets which method will be used to solve the linear programming problem */ -CBCSOLVERLIB_EXPORT void CBC_LINKAGE +CBCLIB_EXPORT void CBC_LINKAGE Cbc_setLPmethod(Cbc_Model *model, enum LPMethod lpm ); /** Returns a pointer to the OsiClpSolverInterface object * containing the problem */ -CBCSOLVERLIB_EXPORT void * CBC_LINKAGE +CBCLIB_EXPORT void * CBC_LINKAGE Cbc_getSolverPtr(Cbc_Model *model); /** sets which pivotting method should be used in the dual simplex */ -CBCSOLVERLIB_EXPORT void CBC_LINKAGE +CBCLIB_EXPORT void CBC_LINKAGE Cbc_setDualPivot(Cbc_Model *model, enum DualPivot dp ); /*@}*/ @@ -1096,12 +1096,12 @@ Cbc_setDualPivot(Cbc_Model *model, enum DualPivot dp ); /*@{*/ /** Pass in Callback function. Message numbers up to 1000000 are Clp, Coin ones have 1000000 added */ -CBCSOLVERLIB_EXPORT void CBC_LINKAGE +CBCLIB_EXPORT void CBC_LINKAGE Cbc_registerCallBack(Cbc_Model *model, cbc_callback userCallBack); /** Unset Callback function */ -CBCSOLVERLIB_EXPORT void CBC_LINKAGE +CBCLIB_EXPORT void CBC_LINKAGE Cbc_clearCallBack(Cbc_Model *model); /** @brief adds a callback to generate cutting planes @@ -1115,7 +1115,7 @@ Cbc_clearCallBack(Cbc_Model *model); * was obtained with these cuts. -99 for cut generators that will be called only at the root node * @param atSolution if the cut generator must to be called also when an integer solution if found (=1) or zero otherwise **/ -CBCSOLVERLIB_EXPORT void CBC_LINKAGE Cbc_addCutCallback( +CBCLIB_EXPORT void CBC_LINKAGE Cbc_addCutCallback( Cbc_Model *model, cbc_cut_callback cutcb, const char *name, @@ -1124,13 +1124,13 @@ CBCSOLVERLIB_EXPORT void CBC_LINKAGE Cbc_addCutCallback( char atSolution ); /** callback to monitor new incumbent solutions **/ -CBCSOLVERLIB_EXPORT void CBC_LINKAGE Cbc_addIncCallback( +CBCLIB_EXPORT void CBC_LINKAGE Cbc_addIncCallback( Cbc_Model *model, cbc_incumbent_callback inccb, void *appData ); /** callback to monitor improvements in lower or upper * bounds */ -CBCSOLVERLIB_EXPORT void CBC_LINKAGE Cbc_addProgrCallback( +CBCLIB_EXPORT void CBC_LINKAGE Cbc_addProgrCallback( Cbc_Model *model, cbc_progress_callback prgcbc, void *appData); @@ -1149,7 +1149,7 @@ CBCSOLVERLIB_EXPORT void CBC_LINKAGE Cbc_addProgrCallback( * 2 difficulties so run was abandoned * 5 event user programmed event occurred **/ -CBCSOLVERLIB_EXPORT int CBC_LINKAGE +CBCLIB_EXPORT int CBC_LINKAGE Cbc_solve(Cbc_Model *model); /** @brief Solves only the linear programming relaxation @@ -1161,14 +1161,14 @@ Cbc_solve(Cbc_Model *model); * 2 infeasible * 3 unbounded **/ -CBCSOLVERLIB_EXPORT int CBC_LINKAGE +CBCLIB_EXPORT int CBC_LINKAGE Cbc_solveLinearProgram(Cbc_Model *model); /** @brief This is a pre-processing that tries to * strengthen set packing constraints. Dominated constraints are * removed. */ -CBCSOLVERLIB_EXPORT void CBC_LINKAGE +CBCLIB_EXPORT void CBC_LINKAGE Cbc_strengthenPacking(Cbc_Model *model); /** @brief This is a pre-processing that tries to @@ -1179,7 +1179,7 @@ Cbc_strengthenPacking(Cbc_Model *model); * @param rows rows indices * */ -CBCSOLVERLIB_EXPORT void CBC_LINKAGE +CBCLIB_EXPORT void CBC_LINKAGE Cbc_strengthenPackingRows(Cbc_Model *model, size_t n, const size_t rows[]); @@ -1194,7 +1194,7 @@ Cbc_strengthenPackingRows(Cbc_Model *model, size_t n, const size_t rows[]); * @param model problem object * @return vector with best solution found **/ -CBCSOLVERLIB_EXPORT const double *CBC_LINKAGE +CBCLIB_EXPORT const double *CBC_LINKAGE Cbc_getColSolution(Cbc_Model *model); @@ -1208,7 +1208,7 @@ Cbc_getColSolution(Cbc_Model *model); * @param colIdx pointer to integer where index of most violated column will be stored * @return 1 if feasible, 0 otherwise **/ -CBCSOLVERLIB_EXPORT char CBC_LINKAGE +CBCLIB_EXPORT char CBC_LINKAGE Cbc_checkFeasibility(Cbc_Model *model, const double x[], double *maxViolRow, int *rowIdx, double *maxViolCol, int *colIdx); @@ -1218,7 +1218,7 @@ Cbc_checkFeasibility(Cbc_Model *model, const double x[], * @param model problem object * @return best possible cost (lower bound) **/ -CBCSOLVERLIB_EXPORT double CBC_LINKAGE +CBCLIB_EXPORT double CBC_LINKAGE Cbc_getBestPossibleObjValue(Cbc_Model *model); /** @brief Best integer feasible solution @@ -1228,7 +1228,7 @@ Cbc_getBestPossibleObjValue(Cbc_Model *model); * @param model problem object * @return vector with the best solution found or NULL if no feasible solution was found **/ -CBCSOLVERLIB_EXPORT const double *CBC_LINKAGE +CBCLIB_EXPORT const double *CBC_LINKAGE Cbc_bestSolution(Cbc_Model *model); /** @brief number of integer feasible solution saved @@ -1236,7 +1236,7 @@ Cbc_bestSolution(Cbc_Model *model); * @param model problem object * @return number of saved solutions **/ -CBCSOLVERLIB_EXPORT int CBC_LINKAGE +CBCLIB_EXPORT int CBC_LINKAGE Cbc_numberSavedSolutions(Cbc_Model *model); /** @brief Vector with the i-th saved solution @@ -1245,7 +1245,7 @@ Cbc_numberSavedSolutions(Cbc_Model *model); * @param whichSol index of the solution to be retrieved * @return vector with integer feasible solution **/ -CBCSOLVERLIB_EXPORT const double *CBC_LINKAGE +CBCLIB_EXPORT const double *CBC_LINKAGE Cbc_savedSolution(Cbc_Model *model, int whichSol); /** @brief Cost of the whichSol solution @@ -1254,7 +1254,7 @@ Cbc_savedSolution(Cbc_Model *model, int whichSol); * @param whichSol solution index * @return solution cost **/ -CBCSOLVERLIB_EXPORT double CBC_LINKAGE +CBCLIB_EXPORT double CBC_LINKAGE Cbc_savedSolutionObj(Cbc_Model *model, int whichSol); /** @brief Queries vector of reduced costs @@ -1262,7 +1262,7 @@ Cbc_savedSolutionObj(Cbc_Model *model, int whichSol); * @param model problem object * @return reduced cost vector **/ -CBCSOLVERLIB_EXPORT const double *CBC_LINKAGE +CBCLIB_EXPORT const double *CBC_LINKAGE Cbc_getReducedCost(Cbc_Model *model); /** @brief Queries vector of row prices (values for dual variables) @@ -1270,7 +1270,7 @@ Cbc_getReducedCost(Cbc_Model *model); * @param model problem object * @return reduced cost vector */ -CBCSOLVERLIB_EXPORT const double *CBC_LINKAGE +CBCLIB_EXPORT const double *CBC_LINKAGE Cbc_getRowPrice(Cbc_Model *model); /** If optimization was abandoned due to numerical difficulties @@ -1278,7 +1278,7 @@ Cbc_getRowPrice(Cbc_Model *model); * @param model problem object * @returns 1 if numerical difficulties interrupted the optimization, 0 otherwise * */ -CBCSOLVERLIB_EXPORT int CBC_LINKAGE +CBCLIB_EXPORT int CBC_LINKAGE Cbc_isAbandoned(Cbc_Model *model); /** @brief If the optimal solution was found @@ -1286,7 +1286,7 @@ Cbc_isAbandoned(Cbc_Model *model); * @param model problem object * @return 1 if optimal solution was found, 0 otherwise **/ -CBCSOLVERLIB_EXPORT int CBC_LINKAGE +CBCLIB_EXPORT int CBC_LINKAGE Cbc_isProvenOptimal(Cbc_Model *model); /** @brief If infeasibility was proven @@ -1297,7 +1297,7 @@ Cbc_isProvenOptimal(Cbc_Model *model); * @param model problem object * @return 1 if model is infeasible, 0 otherwise **/ -CBCSOLVERLIB_EXPORT int CBC_LINKAGE +CBCLIB_EXPORT int CBC_LINKAGE Cbc_isProvenInfeasible(Cbc_Model *model); /** @brief Is continuous model unbounded ? @@ -1305,7 +1305,7 @@ Cbc_isProvenInfeasible(Cbc_Model *model); * @param model problem object * @return 1 if model is unbounded, 0 otherwise * */ -CBCSOLVERLIB_EXPORT int CBC_LINKAGE +CBCLIB_EXPORT int CBC_LINKAGE Cbc_isContinuousUnbounded(Cbc_Model *model); /** Objective value of best feasible solution @@ -1313,7 +1313,7 @@ Cbc_isContinuousUnbounded(Cbc_Model *model); * @param model problem object * @return cost of the best solution found * */ -CBCSOLVERLIB_EXPORT double CBC_LINKAGE +CBCLIB_EXPORT double CBC_LINKAGE Cbc_getObjValue(Cbc_Model *model); /** @brief Final optimization status @@ -1331,7 +1331,7 @@ Cbc_getObjValue(Cbc_Model *model); * @param model problem object * @return problem status */ -CBCSOLVERLIB_EXPORT int CBC_LINKAGE Cbc_status(Cbc_Model *model); +CBCLIB_EXPORT int CBC_LINKAGE Cbc_status(Cbc_Model *model); /** @brief Secondary status of problem * @@ -1351,41 +1351,41 @@ CBCSOLVERLIB_EXPORT int CBC_LINKAGE Cbc_status(Cbc_Model *model); * @model problem object * @return optimization status */ -CBCSOLVERLIB_EXPORT int CBC_LINKAGE +CBCLIB_EXPORT int CBC_LINKAGE Cbc_secondaryStatus(Cbc_Model *model); /** Number of iterations */ -CBCSOLVERLIB_EXPORT int CBC_LINKAGE +CBCLIB_EXPORT int CBC_LINKAGE Cbc_getIterationCount(Cbc_Model *model); /** Node limit reached? */ -CBCSOLVERLIB_EXPORT int CBC_LINKAGE +CBCLIB_EXPORT int CBC_LINKAGE Cbc_isNodeLimitReached(Cbc_Model *model); /** Time limit reached? */ -CBCSOLVERLIB_EXPORT int CBC_LINKAGE +CBCLIB_EXPORT int CBC_LINKAGE Cbc_isSecondsLimitReached(Cbc_Model *model); /** Solution limit reached? */ -CBCSOLVERLIB_EXPORT int CBC_LINKAGE +CBCLIB_EXPORT int CBC_LINKAGE Cbc_isSolutionLimitReached(Cbc_Model *model); /** Are there numerical difficulties (for initialSolve) ? */ -CBCSOLVERLIB_EXPORT int CBC_LINKAGE +CBCLIB_EXPORT int CBC_LINKAGE Cbc_isInitialSolveAbandoned(Cbc_Model *model); /** Is optimality proven (for initialSolve) ? */ -CBCSOLVERLIB_EXPORT int CBC_LINKAGE +CBCLIB_EXPORT int CBC_LINKAGE Cbc_isInitialSolveProvenOptimal(Cbc_Model *model); /** Is primal infeasiblity proven (for initialSolve) ? */ -CBCSOLVERLIB_EXPORT int CBC_LINKAGE +CBCLIB_EXPORT int CBC_LINKAGE Cbc_isInitialSolveProvenPrimalInfeasible(Cbc_Model *model); /** "row" solution * This is the vector A*x, where A is the constraint matrix * and x is the current solution. */ -CBCSOLVERLIB_EXPORT const double *CBC_LINKAGE +CBCLIB_EXPORT const double *CBC_LINKAGE Cbc_getRowActivity(Cbc_Model *model); /** Row slack @@ -1395,13 +1395,13 @@ Cbc_getRowActivity(Cbc_Model *model); * @param model problem object * @return vector with row slacks * */ -CBCSOLVERLIB_EXPORT const double *CBC_LINKAGE +CBCLIB_EXPORT const double *CBC_LINKAGE Cbc_getRowSlack(Cbc_Model *model); /** Number of nodes explored in B&B tree */ -CBCSOLVERLIB_EXPORT int CBC_LINKAGE +CBCLIB_EXPORT int CBC_LINKAGE Cbc_getNodeCount(Cbc_Model *model); /*@}*/ @@ -1409,87 +1409,87 @@ Cbc_getNodeCount(Cbc_Model *model); /** \name OsiSolverInterface related routines (used in callbacks) */ /** @brief Creates a new OsiClpSolverInterface and returns a pointer to an OsiSolverInterface object */ -CBCSOLVERLIB_EXPORT void * CBC_LINKAGE +CBCLIB_EXPORT void * CBC_LINKAGE Osi_newSolver(); /** @brief Solves initial LP relaxation */ -CBCSOLVERLIB_EXPORT void CBC_LINKAGE +CBCLIB_EXPORT void CBC_LINKAGE Osi_initialSolve(void *osi); /** @brief Reoptimizes linear program */ -CBCSOLVERLIB_EXPORT void CBC_LINKAGE +CBCLIB_EXPORT void CBC_LINKAGE Osi_resolve(void *osi); /** @brief Performs branch and bound */ -CBCSOLVERLIB_EXPORT void CBC_LINKAGE +CBCLIB_EXPORT void CBC_LINKAGE Osi_branchAndBound(void *osi); /** @brief Checks if optimization was abandoned */ -CBCSOLVERLIB_EXPORT char CBC_LINKAGE +CBCLIB_EXPORT char CBC_LINKAGE Osi_isAbandoned(void *osi); /** @brief Checks if optimal solution was found */ -CBCSOLVERLIB_EXPORT char CBC_LINKAGE +CBCLIB_EXPORT char CBC_LINKAGE Osi_isProvenOptimal(void *osi); /** @brief Checks if problem is primal infeasible */ -CBCSOLVERLIB_EXPORT char CBC_LINKAGE +CBCLIB_EXPORT char CBC_LINKAGE Osi_isProvenPrimalInfeasible(void *osi); /** @brief Checks if problem is dual infeasible */ -CBCSOLVERLIB_EXPORT char CBC_LINKAGE +CBCLIB_EXPORT char CBC_LINKAGE Osi_isProvenDualInfeasible(void *osi); /** @brief Checks if primal objective limit was reached */ -CBCSOLVERLIB_EXPORT char CBC_LINKAGE +CBCLIB_EXPORT char CBC_LINKAGE Osi_isPrimalObjectiveLimitReached(void *osi); /** @brief Checks if dual objective limit was reached */ -CBCSOLVERLIB_EXPORT char CBC_LINKAGE +CBCLIB_EXPORT char CBC_LINKAGE Osi_isDualObjectiveLimitReached(void *osi); /** @brief Checks if iteration limit was reached */ -CBCSOLVERLIB_EXPORT char CBC_LINKAGE +CBCLIB_EXPORT char CBC_LINKAGE Osi_isIterationLimitReached(void *osi); /** @brief Returns number of cols in OsiSolverInterface object */ -CBCSOLVERLIB_EXPORT int CBC_LINKAGE +CBCLIB_EXPORT int CBC_LINKAGE Osi_getNumCols( void *osi ); /** @brief Returns column name in OsiSolverInterface object */ -CBCSOLVERLIB_EXPORT void CBC_LINKAGE +CBCLIB_EXPORT void CBC_LINKAGE Osi_getColName( void *osi, int i, char *name, int maxLen ); /** @brief Returns column lower bounds in OsiSolverInterface object */ -CBCSOLVERLIB_EXPORT const double * CBC_LINKAGE +CBCLIB_EXPORT const double * CBC_LINKAGE Osi_getColLower( void *osi ); /** @brief Returns column upper bounds in OsiSolverInterface object */ -CBCSOLVERLIB_EXPORT const double * CBC_LINKAGE +CBCLIB_EXPORT const double * CBC_LINKAGE Osi_getColUpper( void *osi ); /** @brief Returns integrality information for columns in OsiSolverInterface object */ -CBCSOLVERLIB_EXPORT int CBC_LINKAGE +CBCLIB_EXPORT int CBC_LINKAGE Osi_isInteger( void *osi, int col ); /** @brief Returns number of rows in OsiSolverInterface object */ -CBCSOLVERLIB_EXPORT int CBC_LINKAGE +CBCLIB_EXPORT int CBC_LINKAGE Osi_getNumRows( void *osi ); /** @brief Returns number non-zeros in the constraint matrix */ -CBCSOLVERLIB_EXPORT int CBC_LINKAGE +CBCLIB_EXPORT int CBC_LINKAGE Osi_getNumNz( void *osi ); /** @brief Returns number integer/binary variables */ -CBCSOLVERLIB_EXPORT int CBC_LINKAGE +CBCLIB_EXPORT int CBC_LINKAGE Osi_getNumIntegers( void *osi ); -CBCSOLVERLIB_EXPORT int CBC_LINKAGE +CBCLIB_EXPORT int CBC_LINKAGE Osi_getRowNz(void *osi, int row); /** @brief Indices of variables that appear on a row */ -CBCSOLVERLIB_EXPORT const int *CBC_LINKAGE +CBCLIB_EXPORT const int *CBC_LINKAGE Osi_getRowIndices(void *osi, int row); /** @brief Coefficients of variables that appear on this row @@ -1498,7 +1498,7 @@ Osi_getRowIndices(void *osi, int row); * @param row row index * @return coefficients of variables that appear on this row **/ -CBCSOLVERLIB_EXPORT const double *CBC_LINKAGE +CBCLIB_EXPORT const double *CBC_LINKAGE Osi_getRowCoeffs(void *osi, int row); /** @brief Right hand side of a row @@ -1507,7 +1507,7 @@ Osi_getRowCoeffs(void *osi, int row); * @param row row index * @return row right hand side **/ -CBCSOLVERLIB_EXPORT double CBC_LINKAGE +CBCLIB_EXPORT double CBC_LINKAGE Osi_getRowRHS(void *osi, int row); /** @brief Sense a row @@ -1515,43 +1515,43 @@ Osi_getRowRHS(void *osi, int row); * @param row row index * @return row sense: E for =, L for <=, G for >= and R for ranged row **/ -CBCSOLVERLIB_EXPORT char CBC_LINKAGE +CBCLIB_EXPORT char CBC_LINKAGE Osi_getRowSense(void *osi, int row); /** @brief Returns vector with objective function coefficients */ -CBCSOLVERLIB_EXPORT const double * CBC_LINKAGE +CBCLIB_EXPORT const double * CBC_LINKAGE Osi_getObjCoefficients(); /** @brief Returns the objective sense: 1 for MIN and -1 for MAX */ -CBCSOLVERLIB_EXPORT double CBC_LINKAGE +CBCLIB_EXPORT double CBC_LINKAGE Osi_getObjSense(); /** @brief Returns solution vector in OsiSolverInterface object */ -CBCSOLVERLIB_EXPORT const double * CBC_LINKAGE +CBCLIB_EXPORT const double * CBC_LINKAGE Osi_getColSolution( void *osi ); /** @brief Returns vector of reduced costs */ -CBCSOLVERLIB_EXPORT const double * CBC_LINKAGE +CBCLIB_EXPORT const double * CBC_LINKAGE Osi_getReducedCost( void *osi ); /** @brief Returns of dual variables */ -CBCSOLVERLIB_EXPORT const double *CBC_LINKAGE +CBCLIB_EXPORT const double *CBC_LINKAGE Osi_getRowPrice( void *osi ); /** @brief Returns the objective function value */ -CBCSOLVERLIB_EXPORT double CBC_LINKAGE +CBCLIB_EXPORT double CBC_LINKAGE Osi_getObjValue( void *osi ); /** @brief Sets column upper bound */ -CBCSOLVERLIB_EXPORT void CBC_LINKAGE +CBCLIB_EXPORT void CBC_LINKAGE Osi_setColUpper (void *osi, int elementIndex, double ub); /** @brief Sets column upper bound */ -CBCSOLVERLIB_EXPORT void CBC_LINKAGE +CBCLIB_EXPORT void CBC_LINKAGE Osi_setColLower(void *osi, int elementIndex, double lb); /** @brief Sets one objective function coefficient */ -CBCSOLVERLIB_EXPORT void CBC_LINKAGE +CBCLIB_EXPORT void CBC_LINKAGE Osi_setObjCoef(void *osi, int elementIndex, double obj); /** @brief Sets optimization direction @@ -1559,15 +1559,15 @@ Osi_setObjCoef(void *osi, int elementIndex, double obj); * @param osi OsiSolverInterface object * @param sense: direction of optimization (1 - minimize, -1 - maximize, 0 - ignore) **/ -CBCSOLVERLIB_EXPORT void CBC_LINKAGE +CBCLIB_EXPORT void CBC_LINKAGE Osi_setObjSense(void *osi, double sense); /** @brief Sets a variable to integer */ -CBCSOLVERLIB_EXPORT void CBC_LINKAGE +CBCLIB_EXPORT void CBC_LINKAGE Osi_setInteger(void *osi, int index); /** @brief Sets a variable to continuous */ -CBCSOLVERLIB_EXPORT void CBC_LINKAGE +CBCLIB_EXPORT void CBC_LINKAGE Osi_setContinuous(void *osi, int index); /** @brief Number of non-zero entries in a column @@ -1576,7 +1576,7 @@ Osi_setContinuous(void *osi, int index); * @param col column index * @return numbef of rows that this column appears **/ -CBCSOLVERLIB_EXPORT int CBC_LINKAGE +CBCLIB_EXPORT int CBC_LINKAGE Osi_getColNz(void *model, int col); /** @brief Indices of rows that a column appears @@ -1585,7 +1585,7 @@ Osi_getColNz(void *model, int col); * @param col column index * @return indices of rows that this column appears **/ -CBCSOLVERLIB_EXPORT const int *CBC_LINKAGE +CBCLIB_EXPORT const int *CBC_LINKAGE Osi_getColIndices(void *model, int col); /** @brief Coefficients that a column appear in rows @@ -1594,7 +1594,7 @@ Osi_getColIndices(void *model, int col); * @param col column index * @return coefficients of this column in rows **/ -CBCSOLVERLIB_EXPORT const double *CBC_LINKAGE +CBCLIB_EXPORT const double *CBC_LINKAGE Osi_getColCoeffs(void *model, int col); /** @brief Creates a new column @@ -1611,7 +1611,7 @@ Osi_getColCoeffs(void *model, int col); * @param rows index of rows where this column appears, NULL if rows will be added later * @param coefs coefficients that this column appears in its rows, NULL if rows will be added later ***/ -CBCSOLVERLIB_EXPORT void CBC_LINKAGE +CBCLIB_EXPORT void CBC_LINKAGE Osi_addCol(void *osi, const char *name, double lb, double ub, double obj, char isInteger, int nz, int *rows, double *coefs); @@ -1628,37 +1628,37 @@ Osi_addCol(void *osi, const char *name, double lb, * @param sense constraint sense: L if <=, G if >=, E if =, R if ranged and N if free * @param rhs right hand size * */ -CBCSOLVERLIB_EXPORT void CBC_LINKAGE +CBCLIB_EXPORT void CBC_LINKAGE Osi_addRow(void *osi, const char *name, int nz, const int *cols, const double *coefs, char sense, double rhs); /** @brief Returns the integer tolerance **/ -CBCSOLVERLIB_EXPORT double CBC_LINKAGE +CBCLIB_EXPORT double CBC_LINKAGE Osi_getIntegerTolerance(void *osi); /** @brief Deletes an OsiSolverInterface object */ -CBCSOLVERLIB_EXPORT void CBC_LINKAGE +CBCLIB_EXPORT void CBC_LINKAGE Osi_deleteSolver( void *osi ); /** @brief Creates (it not yet) the conflict graph */ -CBCSOLVERLIB_EXPORT void CBC_LINKAGE +CBCLIB_EXPORT void CBC_LINKAGE Osi_checkCGraph( void *osi ); /** @brief Returns the conflict graph */ -CBCSOLVERLIB_EXPORT const void * CBC_LINKAGE +CBCLIB_EXPORT const void * CBC_LINKAGE Osi_CGraph( void *osi ); /** @brief Computes instance features (can be used for machine learning) */ -CBCSOLVERLIB_EXPORT void CBC_LINKAGE +CBCLIB_EXPORT void CBC_LINKAGE Osi_compute_features(void *solver, double *features); /** @brief Number of instance features available */ -CBCSOLVERLIB_EXPORT int CBC_LINKAGE +CBCLIB_EXPORT int CBC_LINKAGE Osi_n_features(); /** @brief Name of feature i */ -CBCSOLVERLIB_EXPORT const char * CBC_LINKAGE +CBCLIB_EXPORT const char * CBC_LINKAGE Osi_feature_name(int i); /*@}*/ @@ -1666,15 +1666,15 @@ Osi_feature_name(int i); /** \name Conflict Graph related routines */ /** @brief Number of nodes in the conflict graph */ -CBCSOLVERLIB_EXPORT size_t CBC_LINKAGE +CBCLIB_EXPORT size_t CBC_LINKAGE CG_nodes( void *cgraph ); /** @brief If two nodes are conflicting */ -CBCSOLVERLIB_EXPORT char CBC_LINKAGE +CBCLIB_EXPORT char CBC_LINKAGE CG_conflicting( void *cgraph, int n1, int n2 ); /** @brief Density of the conflict graph */ -CBCSOLVERLIB_EXPORT double CBC_LINKAGE +CBCLIB_EXPORT double CBC_LINKAGE CG_density( void *cgraph ); @@ -1693,7 +1693,7 @@ typedef struct { * may be updated. * * */ -CBCSOLVERLIB_EXPORT CGNeighbors CBC_LINKAGE +CBCLIB_EXPORT CGNeighbors CBC_LINKAGE CG_conflictingNodes(Cbc_Model *model, void *cgraph, size_t node); @@ -1713,7 +1713,7 @@ CG_conflictingNodes(Cbc_Model *model, void *cgraph, size_t node); * @param depth current three depth, cuts may use this info to decide which strategy to use * @param pass cut pass number * */ -CBCSOLVERLIB_EXPORT void CBC_LINKAGE Cbc_generateCuts( Cbc_Model *cbcModel, enum CutType ct, void *oc, int depth, int pass ); +CBCLIB_EXPORT void CBC_LINKAGE Cbc_generateCuts( Cbc_Model *cbcModel, enum CutType ct, void *oc, int depth, int pass ); /*@}*/ @@ -1721,43 +1721,43 @@ CBCSOLVERLIB_EXPORT void CBC_LINKAGE Cbc_generateCuts( Cbc_Model *cbcModel, enum /** \name OsiCuts related routines (used in callbacks) */ /** Creates a new cut pool and returns its pointer */ -CBCSOLVERLIB_EXPORT void * CBC_LINKAGE +CBCLIB_EXPORT void * CBC_LINKAGE OsiCuts_new(); /** adds a row cut (used in callback) */ -CBCSOLVERLIB_EXPORT void CBC_LINKAGE +CBCLIB_EXPORT void CBC_LINKAGE OsiCuts_addRowCut( void *osiCuts, int nz, const int *idx, const double *coef, char sense, double rhs ); /** adds a row cut (used in callback), stating that this is a globally valid cut */ -CBCSOLVERLIB_EXPORT void CBC_LINKAGE +CBCLIB_EXPORT void CBC_LINKAGE OsiCuts_addGlobalRowCut( void *osiCuts, int nz, const int *idx, const double *coef, char sense, double rhs ); /** Returns the number of row cuts stored */ -CBCSOLVERLIB_EXPORT int CBC_LINKAGE +CBCLIB_EXPORT int CBC_LINKAGE OsiCuts_sizeRowCuts( void *osiCuts ); /** Returns the number of row cuts stored */ -CBCSOLVERLIB_EXPORT int CBC_LINKAGE +CBCLIB_EXPORT int CBC_LINKAGE OsiCuts_nzRowCut( void *osiCuts, int iRowCut ); /** Returns the variable indexes in a row cut */ -CBCSOLVERLIB_EXPORT const int * CBC_LINKAGE +CBCLIB_EXPORT const int * CBC_LINKAGE OsiCuts_idxRowCut( void *osiCuts, int iRowCut ); /** Returns the variable coefficients in a row cut */ -CBCSOLVERLIB_EXPORT const double * CBC_LINKAGE +CBCLIB_EXPORT const double * CBC_LINKAGE OsiCuts_coefRowCut( void *osiCuts, int iRowCut ); /** Returns the variable coefficients in a row cut */ -CBCSOLVERLIB_EXPORT double CBC_LINKAGE +CBCLIB_EXPORT double CBC_LINKAGE OsiCuts_rhsRowCut( void *osiCuts, int iRowCut ); /** Returns the sense of a row cut */ -CBCSOLVERLIB_EXPORT char CBC_LINKAGE +CBCLIB_EXPORT char CBC_LINKAGE OsiCuts_senseRowCut( void *osiCuts, int iRowCut ); /** Deletes a cut pool */ -CBCSOLVERLIB_EXPORT void CBC_LINKAGE +CBCLIB_EXPORT void CBC_LINKAGE OsiCuts_delete( void *osiCuts ); diff --git a/src/ClpAmplObjective.hpp b/src/ClpAmplObjective.hpp index 0e361a74f..b0639e75b 100644 --- a/src/ClpAmplObjective.hpp +++ b/src/ClpAmplObjective.hpp @@ -14,7 +14,7 @@ */ -class CBCSOLVERLIB_EXPORT ClpAmplObjective : public ClpObjective { +class CBCLIB_EXPORT ClpAmplObjective : public ClpObjective { public: ///@name Stuff diff --git a/src/ClpConstraintAmpl.hpp b/src/ClpConstraintAmpl.hpp index f4ad6d778..740f44a3a 100644 --- a/src/ClpConstraintAmpl.hpp +++ b/src/ClpConstraintAmpl.hpp @@ -13,7 +13,7 @@ */ -class CBCSOLVERLIB_EXPORT ClpConstraintAmpl : public ClpConstraint { +class CBCLIB_EXPORT ClpConstraintAmpl : public ClpConstraint { public: ///@name Stuff diff --git a/src/CoinSolve.cpp b/src/CoinSolve.cpp index 84cb76c56..3f7a4f546 100644 --- a/src/CoinSolve.cpp +++ b/src/CoinSolve.cpp @@ -6,19 +6,20 @@ \brief Main routine for the cbc stand-alone solver. */ -#undef CBCSOLVERLIB_BUILD +#include "CbcConfig.h" -/* would normally be a separate config header file, but the cbc exe has only one source file */ -#ifdef HAVE_CONFIG_H -#include "config.h" -#else /* HAVE_CONFIG_H */ -#include "config_default.h" -#endif /* HAVE_CONFIG_H */ -#define __CBCCONFIG_H__ +#include +#include +#include +#include +#include +#include #include "CoinPragma.hpp" +#include "CoinModel.hpp" #include "CbcModel.hpp" #include "CbcSolver.hpp" +#include "CbcDebug.hpp" #include "OsiClpSolverInterface.hpp" /* @@ -63,16 +64,9 @@ Hooks for a debugging wrapper for malloc/free. This bit of definition hooks C++ new / delete and diverts them into the debugging wrapper. */ + //#define CLP_DEBUG_MALLOC #ifdef CLP_DEBUG_MALLOC -/*extern "C" */ void clp_memory(int type); -/*extern "C" */ -void *clp_malloc(int length); -/*extern "C" */ -void clp_free(void *array); -#include -#include -#include void *operator new(size_t size) throw(std::bad_alloc) { void *p = clp_malloc(size); @@ -84,163 +78,11 @@ void operator delete(void *p) throw() } #endif // CLP_DEBUG_MALLOC -#include -#include -#include -#include -#include -#include - -// define TEST_MESSAGE_HANDLER to check works on all messages -// #define TEST_MESSAGE_HANDLER -#ifdef TEST_MESSAGE_HANDLER -// This driver shows how to trap messages - this is just as in unitTest.cpp -// ****** THis code is similar to MyMessageHandler.hpp and MyMessagehandler.cpp -#include "CoinMessageHandler.hpp" - -/** This just adds a model to CoinMessage and a void pointer so - user can trap messages and do useful stuff. - This is used in Clp/Test/unitTest.cpp - - The file pointer is just there as an example of user stuff. - - -- lh 071026 -- An accurate summary. Nothing is actually happening here - except that messages will be prefixed with "==", which serves the purpose - of demonstrating that this message handler is active. The extra parameters - (CbcModel, FILE) are unused. - -*/ -class CbcModel; - -class MyMessageHandler2 : public CoinMessageHandler { - -public: - /**@name Overrides */ - //@{ - virtual int print(); - //@} - /**@name set and get */ - //@{ - /// Model - const CbcModel *model() const; - void setModel(CbcModel *model); - //@} - - /**@name Constructors, destructor */ - //@{ - /** Default constructor. */ - MyMessageHandler2(); - /// Constructor with pointer to model - MyMessageHandler2(CbcModel *model, - FILE *userPointer = NULL); - /** Destructor */ - virtual ~MyMessageHandler2(); - //@} - - /**@name Copy method */ - //@{ - /** The copy constructor. */ - MyMessageHandler2(const MyMessageHandler2 &); - /** The copy constructor from an CoinSimplexMessageHandler. */ - MyMessageHandler2(const CoinMessageHandler &); - - MyMessageHandler2 &operator=(const MyMessageHandler2 &); - /// Clone - virtual CoinMessageHandler *clone() const; - //@} - -protected: - /**@name Data members - The data members are protected to allow access for derived classes. */ - //@{ - /// Pointer back to model - CbcModel *model_; - //@} -}; - //############################################################################# -// Constructors / Destructor / Assignment -//############################################################################# - -//------------------------------------------------------------------- -// Default Constructor -//------------------------------------------------------------------- -MyMessageHandler2::MyMessageHandler2() - : CoinMessageHandler() - , model_(NULL) -{ -} - -//------------------------------------------------------------------- -// Copy constructor -//------------------------------------------------------------------- -MyMessageHandler2::MyMessageHandler2(const MyMessageHandler2 &rhs) - : CoinMessageHandler(rhs) - , model_(rhs.model_) -{ -} - -MyMessageHandler2::MyMessageHandler2(const CoinMessageHandler &rhs) - : CoinMessageHandler() - , model_(NULL) -{ -} - -// Constructor with pointer to model -MyMessageHandler2::MyMessageHandler2(CbcModel *model, - FILE *userPointer) - : CoinMessageHandler() - , model_(model) -{ -} - -//------------------------------------------------------------------- -// Destructor -//------------------------------------------------------------------- -MyMessageHandler2::~MyMessageHandler2() -{ -} - -//---------------------------------------------------------------- -// Assignment operator -//------------------------------------------------------------------- -MyMessageHandler2 & -MyMessageHandler2::operator=(const MyMessageHandler2 &rhs) -{ - if (this != &rhs) { - CoinMessageHandler::operator=(rhs); - model_ = rhs.model_; - } - return *this; -} -//------------------------------------------------------------------- -// Clone -//------------------------------------------------------------------- -CoinMessageHandler *MyMessageHandler2::clone() const -{ - return new MyMessageHandler2(*this); -} -int MyMessageHandler2::print() -{ - // Just add == - fprintf(fp_, " == "); - fprintf(fp_, "%s\n", messageBuffer_); - return 0; -} -const CbcModel * -MyMessageHandler2::model() const -{ - return model_; -} -void MyMessageHandler2::setModel(CbcModel *model) -{ - model_ = model; -} -#endif /* TEST_MESSAGE_HANDLER */ - //############################################################################# -// To use USERCBC or USERCLP change 0 to 1 in defines and add in your fake main program(s) and any other code +// To use USERCBC or USERCLP change 0 to 1 in defines and add in your fake +// main program(s) and any other code //#define USER_HAS_FAKE_CBC //#define USER_HAS_FAKE_CLP @@ -276,6 +118,7 @@ void fakeMain2(ClpSimplex & /*model*/, } // End any fake main program +//############################################################################# //############################################################################# // void CbcClpUnitTest (const CbcModel & saveModel); @@ -298,6 +141,9 @@ void cbc_resolve_check(const OsiSolverInterface *solver) } #endif +//############################################################################# +//############################################################################# + /* Somehow with some BLAS we get multithreaded by default For 99.99% of problems this is not a good idea. @@ -309,10 +155,28 @@ void openblas_set_num_threads(int num_threads); } #endif -static int dummyCallBack(CbcModel * /*model*/, int /*whereFrom*/) -{ - return 0; +//############################################################################# +//############################################################################# + +#ifdef TEST_MESSAGE_HANDLER +void test_message_handler(CbcModel &model){ + MyMessageHandler2 messageHandler(&model); + std::cout << "Testing derived message handler" << std::endl; + model.passInMessageHandler(&messageHandler); + OsiClpSolverInterface *clpSolver = + dynamic_cast< OsiClpSolverInterface * >(model.solver()); + // Could use different handlers (if different log levels) + clpSolver->passInMessageHandler(&messageHandler); + //clpSolver->getModelPtr()->passInMessageHandler(&messageHandler); + + // Set log levels same so can use one message handler + clpSolver->messageHandler()->setLogLevel(1); + model.messageHandler()->setLogLevel(1); } +#endif + +//############################################################################# +//############################################################################# int main(int argc, const char *argv[]) { @@ -320,47 +184,49 @@ int main(int argc, const char *argv[]) #ifdef CLP_DEBUG_MALLOC clp_memory(0); #endif - { #ifndef CBC_OTHER_SOLVER - OsiClpSolverInterface solver1; + OsiClpSolverInterface solver1; #if CLP_USE_OPENBLAS - openblas_set_num_threads(CLP_USE_OPENBLAS); + openblas_set_num_threads(CLP_USE_OPENBLAS); #endif #elif CBC_OTHER_SOLVER == 1 - OsiCpxSolverInterface solver1; + OsiCpxSolverInterface solver1; #endif - CbcModel model(solver1); - - // define TEST_MESSAGE_HANDLER at top of file to check works on all messages -#ifdef TEST_MESSAGE_HANDLER - MyMessageHandler2 messageHandler(&model); - std::cout << "Testing derived message handler" << std::endl; - model.passInMessageHandler(&messageHandler); - OsiClpSolverInterface *clpSolver = dynamic_cast< OsiClpSolverInterface * >(model.solver()); - // Could use different handlers (if different log levels) - clpSolver->passInMessageHandler(&messageHandler); - //clpSolver->getModelPtr()->passInMessageHandler(&messageHandler); -#endif - - CbcSolverUsefulData cbcData; + CbcModel model(solver1); + + CbcParameters parameters; #ifndef CBC_NO_INTERRUPT - cbcData.useSignalHandler_ = true; + parameters.enableSignalHandler(); #endif - cbcData.noPrinting_ = false; - // initialize - CbcMain0(model, cbcData); - + // initialize + CbcMain0(model, parameters); + + // define TEST_MESSAGE_HANDLER at top of file to check works on all messages #ifdef TEST_MESSAGE_HANDLER - // Set log levels same so can use one message handler - clpSolver->messageHandler()->setLogLevel(1); - model.messageHandler()->setLogLevel(1); - // switch off some printing - void setCbcOrClpPrinting(bool yesNo); - setCbcOrClpPrinting(false); + test_message_handler(&model); #endif - - returnCode = CbcMain1(argc, argv, model, dummyCallBack, cbcData); - } + + std::deque inputQueue; + + if (argc > 2 && !strcmp(argv[2], "-AMPL")) { + ampl_info info; + returnCode = cbcReadAmpl(&info, argc, const_cast< char ** >(argv), model); + if (!returnCode) { + // Put arguments into a queue. + // This should be moved to constructor of ClpSolver + CoinParamUtils::formInputQueue(inputQueue, "cbc", info.numberArguments, + info.arguments); + // We don't need to first two arguments from here on + inputQueue.pop_front(); + inputQueue.pop_front(); + returnCode = CbcMain1(inputQueue, model, parameters, dummyCallback, + &info); + } + } else { + // Put arguments into a queue. + CoinParamUtils::formInputQueue(inputQueue, "cbc", argc, const_cast< char ** >(argv)); + returnCode = CbcMain1(inputQueue, model, parameters); + } #ifdef CLP_DEBUG_MALLOC clp_memory(1); @@ -373,6 +239,9 @@ int main(int argc, const char *argv[]) } } +//############################################################################# +// Some old comments for historical interest +//############################################################################# /* Version 1.00.00 November 16 2005. This is to stop me (JJF) messing about too much. diff --git a/src/Makefile.am b/src/Makefile.am index 2e2c91f08..bc735b801 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -10,11 +10,12 @@ # Name of the library compiled in this directory. # We want it to be installed in the 'lib' directory -lib_LTLIBRARIES = libCbc.la libCbcSolver.la +lib_LTLIBRARIES = libCbc.la # List all source files for this library, including headers libCbc_la_SOURCES = \ CbcConfig.h \ + CbcBab.cpp \ CbcBranchActual.hpp \ CbcBranchAllDifferent.cpp CbcBranchAllDifferent.hpp \ CbcBranchBase.hpp \ @@ -67,44 +68,42 @@ libCbc_la_SOURCES = \ CbcHeuristicVND.cpp CbcHeuristicVND.hpp \ CbcHeuristicDW.cpp CbcHeuristicDW.hpp \ CbcMessage.cpp CbcMessage.hpp \ + CbcMipStartIO.cpp CbcMipStartIO.hpp \ CbcModel.cpp CbcModel.hpp \ CbcNode.cpp CbcNode.hpp \ CbcNodeInfo.cpp CbcNodeInfo.hpp \ CbcNWay.cpp CbcNWay.hpp \ CbcObject.cpp CbcObject.hpp \ CbcObjectUpdateData.cpp CbcObjectUpdateData.hpp \ + CbcParam.cpp CbcParam.hpp \ + CbcParamUtils.cpp CbcParamUtils.hpp CbcCbcparam.cpp \ CbcPartialNodeInfo.cpp CbcPartialNodeInfo.hpp \ CbcSimpleInteger.cpp CbcSimpleInteger.hpp \ CbcSimpleIntegerDynamicPseudoCost.cpp \ CbcSimpleIntegerDynamicPseudoCost.hpp \ CbcSimpleIntegerPseudoCost.cpp \ CbcSimpleIntegerPseudoCost.hpp \ - CbcSOS.cpp CbcSOS.hpp \ + CbcSOS.cpp CbcSOS.hpp CbcSolution.cpp \ + CbcSolver.cpp CbcSolverAnalyze.cpp CbcSolverAnalyze.hpp \ + CbcSolverExpandKnapsack.cpp CbcSolverExpandKnapsack.hpp \ + CbcSolverHeuristics.cpp CbcSolverHeuristics.hpp \ + CbcParameters.cpp CbcParameters.hpp \ CbcStatistics.cpp CbcStatistics.hpp \ CbcStrategy.cpp CbcStrategy.hpp \ CbcSubProblem.cpp CbcSubProblem.hpp \ CbcSymmetry.cpp CbcSymmetry.hpp \ CbcThread.cpp CbcThread.hpp \ CbcTree.cpp CbcTree.hpp \ - CbcTreeLocal.cpp CbcTreeLocal.hpp - -libCbcSolver_la_SOURCES = \ + CbcTreeLocal.cpp CbcTreeLocal.hpp \ Cbc_C_Interface.cpp Cbc_C_Interface.h \ - CbcCbcParam.cpp \ CbcLinked.cpp CbcLinked.hpp CbcLinkedUtils.cpp \ - unitTestClp.cpp CbcSolver.cpp \ - CbcSolverHeuristics.cpp CbcSolverHeuristics.hpp \ - CbcSolverAnalyze.cpp CbcSolverAnalyze.hpp \ - CbcMipStartIO.cpp CbcMipStartIO.hpp \ - CbcSolverExpandKnapsack.cpp CbcSolverExpandKnapsack.hpp + unitTestClp.cpp # List all additionally required libraries libCbc_la_LIBADD = $(CBCLIB_LFLAGS) -libCbcSolver_la_LIBADD = $(CBCSOLVERLIB_LFLAGS) libCbc.la # Some common setup for cbc and cbc-generic. libCbc_la_CPPFLAGS = $(CBCLIB_CFLAGS) -libCbcSolver_la_CPPFLAGS = $(CBCSOLVERLIB_CFLAGS) ######################################################################## # cbc program # @@ -122,44 +121,10 @@ bin_PROGRAMS += cbc cbc_SOURCES = CoinSolve.cpp # Additional libraries -cbc_LDADD = libCbcSolver.la libCbc.la +cbc_LDADD = libCbc.la # not really accurate to use these CFLAGS, but they should have everything -cbc_CPPFLAGS = $(CBCSOLVERLIB_CFLAGS) - -endif - - -######################################################################## -# cbc-generic program # -######################################################################## - -if CBC_BUILD_CBC_GENERIC - -# Name of the executable compiled in this directory. We want it to be -# installed in the 'bin' directory - -bin_PROGRAMS += cbc-generic - -# List all source files for this executable, including headers - -cbc_generic_SOURCES = \ - CbcGenBaB.cpp \ - CbcGenCbcParam.cpp CbcGenCbcParam.hpp CbcGenCbcParamUtils.cpp \ - CbcGenCtlBlk.cpp CbcGenCtlBlk.hpp \ - CbcGeneric.cpp \ - CbcGenMessages.cpp CbcGenMessages.hpp \ - CbcGenOsiParam.cpp CbcGenOsiParam.hpp CbcGenOsiParamUtils.cpp \ - CbcGenParam.cpp CbcGenParam.hpp CbcGenParamUtils.cpp \ - CbcGenSolution.cpp \ - CbcGenSolvers.cpp - -# List all additionally required solver and Osi libraries -# the flags for all available LP solvers should have been collected -# by configure in CBCGENERIC_LFLAGS and CBCGENERIC_CFLAGS - -cbc_generic_LDADD = libCbcSolver.la libCbc.la $(CBCGENERIC_LFLAGS) -cbc_generic_CPPFLAGS = $(CBCGENERIC_CFLAGS) +cbc_CPPFLAGS = $(CBCLIB_CFLAGS) endif @@ -212,6 +177,7 @@ includecoin_HEADERS = \ CbcFullNodeInfo.hpp \ CbcGeneral.hpp \ CbcGeneralDepth.hpp \ + CbcGenMessages.hpp \ CbcHeuristic.hpp \ CbcHeuristicDINS.hpp \ CbcHeuristicDive.hpp \ @@ -239,6 +205,7 @@ includecoin_HEADERS = \ CbcObjectUpdateData.hpp \ CbcParam.hpp \ CbcPartialNodeInfo.hpp \ + CbcParameters.hpp \ CbcSimpleInteger.hpp \ CbcSimpleIntegerDynamicPseudoCost.hpp \ CbcSimpleIntegerPseudoCost.hpp \ @@ -259,7 +226,6 @@ includecoin_HEADERS = \ install-exec-local: $(install_sh_DATA) config_cbc.h $(DESTDIR)$(includecoindir)/CbcConfig.h - $(install_sh_DATA) config_cbcsolver.h $(DESTDIR)$(includecoindir)/CbcSolverConfig.h uninstall-local: rm -f $(DESTDIR)$(includecoindir)/CbcConfig.h $(DESTDIR)$(includecoindir)/CbcSolverConfig.h diff --git a/src/Makefile.in b/src/Makefile.in index 6786bfe22..a6ebc9798 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -100,19 +100,11 @@ PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ -bin_PROGRAMS = $(am__EXEEXT_1) $(am__EXEEXT_2) +bin_PROGRAMS = $(am__EXEEXT_1) # Name of the executable compiled in this directory. We want it to be # installed in the 'bin' directory @COIN_HAS_CLP_TRUE@am__append_1 = cbc - -######################################################################## -# cbc-generic program # -######################################################################## - -# Name of the executable compiled in this directory. We want it to be -# installed in the 'bin' directory -@CBC_BUILD_CBC_GENERIC_TRUE@am__append_2 = cbc-generic subdir = src ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/configure.ac @@ -120,12 +112,11 @@ am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(includecoin_HEADERS) mkinstalldirs = $(install_sh) -d -CONFIG_HEADER = config.h config_cbc.h config_cbcsolver.h \ +CONFIG_HEADER = config.h config_cbc.h \ $(top_builddir)/src/OsiCbc/config_osicbc.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = @COIN_HAS_CLP_TRUE@am__EXEEXT_1 = cbc$(EXEEXT) -@CBC_BUILD_CBC_GENERIC_TRUE@am__EXEEXT_2 = cbc-generic$(EXEEXT) am__installdirs = "$(DESTDIR)$(bindir)" "$(DESTDIR)$(libdir)" \ "$(DESTDIR)$(includecoindir)" PROGRAMS = $(bin_PROGRAMS) @@ -159,8 +150,11 @@ am__uninstall_files_from_dir = { \ LTLIBRARIES = $(lib_LTLIBRARIES) am__DEPENDENCIES_1 = libCbc_la_DEPENDENCIES = $(am__DEPENDENCIES_1) -am_libCbc_la_OBJECTS = libCbc_la-CbcBranchAllDifferent.lo \ - libCbc_la-CbcBranchCut.lo libCbc_la-CbcBranchDecision.lo \ +# CbcSolver moved to beginning for faster build +am_libCbc_la_OBJECTS = libCbc_la-CbcBab.lo \ + libCbc_la-CbcSolver.lo \ + libCbc_la-CbcBranchAllDifferent.lo libCbc_la-CbcBranchCut.lo \ + libCbc_la-CbcBranchDecision.lo \ libCbc_la-CbcBranchDefaultDecision.lo \ libCbc_la-CbcBranchDynamic.lo libCbc_la-CbcBranchingObject.lo \ libCbc_la-CbcBranchLotsize.lo libCbc_la-CbcBranchToFixLots.lo \ @@ -189,52 +183,32 @@ am_libCbc_la_OBJECTS = libCbc_la-CbcBranchAllDifferent.lo \ libCbc_la-CbcHeuristicRandRound.lo \ libCbc_la-CbcHeuristicRENS.lo libCbc_la-CbcHeuristicRINS.lo \ libCbc_la-CbcHeuristicVND.lo libCbc_la-CbcHeuristicDW.lo \ - libCbc_la-CbcMessage.lo libCbc_la-CbcModel.lo \ - libCbc_la-CbcNode.lo libCbc_la-CbcNodeInfo.lo \ - libCbc_la-CbcNWay.lo libCbc_la-CbcObject.lo \ - libCbc_la-CbcObjectUpdateData.lo \ + libCbc_la-CbcMessage.lo libCbc_la-CbcMipStartIO.lo \ + libCbc_la-CbcModel.lo libCbc_la-CbcNode.lo \ + libCbc_la-CbcNodeInfo.lo libCbc_la-CbcNWay.lo \ + libCbc_la-CbcObject.lo libCbc_la-CbcObjectUpdateData.lo \ + libCbc_la-CbcParam.lo libCbc_la-CbcParamUtils.lo libCbc_la-CbcCbcParam.lo \ libCbc_la-CbcPartialNodeInfo.lo libCbc_la-CbcSimpleInteger.lo \ libCbc_la-CbcSimpleIntegerDynamicPseudoCost.lo \ libCbc_la-CbcSimpleIntegerPseudoCost.lo libCbc_la-CbcSOS.lo \ + libCbc_la-CbcSolution.lo \ + libCbc_la-CbcSolverAnalyze.lo \ + libCbc_la-CbcSolverExpandKnapsack.lo \ + libCbc_la-CbcSolverHeuristics.lo libCbc_la-CbcParameters.lo \ libCbc_la-CbcStatistics.lo libCbc_la-CbcStrategy.lo \ libCbc_la-CbcSubProblem.lo libCbc_la-CbcSymmetry.lo \ libCbc_la-CbcThread.lo libCbc_la-CbcTree.lo \ - libCbc_la-CbcTreeLocal.lo + libCbc_la-CbcTreeLocal.lo libCbc_la-Cbc_C_Interface.lo \ + libCbc_la-CbcLinked.lo libCbc_la-CbcLinkedUtils.lo \ + libCbc_la-unitTestClp.lo libCbc_la_OBJECTS = $(am_libCbc_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = -libCbcSolver_la_DEPENDENCIES = $(am__DEPENDENCIES_1) libCbc.la -am_libCbcSolver_la_OBJECTS = libCbcSolver_la-Cbc_C_Interface.lo \ - libCbcSolver_la-CbcCbcParam.lo libCbcSolver_la-CbcLinked.lo \ - libCbcSolver_la-CbcLinkedUtils.lo \ - libCbcSolver_la-unitTestClp.lo libCbcSolver_la-CbcSolver.lo \ - libCbcSolver_la-CbcSolverHeuristics.lo \ - libCbcSolver_la-CbcSolverAnalyze.lo \ - libCbcSolver_la-CbcMipStartIO.lo \ - libCbcSolver_la-CbcSolverExpandKnapsack.lo -libCbcSolver_la_OBJECTS = $(am_libCbcSolver_la_OBJECTS) @COIN_HAS_CLP_TRUE@am_cbc_OBJECTS = cbc-CoinSolve.$(OBJEXT) cbc_OBJECTS = $(am_cbc_OBJECTS) -@COIN_HAS_CLP_TRUE@cbc_DEPENDENCIES = libCbcSolver.la libCbc.la -@CBC_BUILD_CBC_GENERIC_TRUE@am_cbc_generic_OBJECTS = \ -@CBC_BUILD_CBC_GENERIC_TRUE@ cbc_generic-CbcGenBaB.$(OBJEXT) \ -@CBC_BUILD_CBC_GENERIC_TRUE@ cbc_generic-CbcGenCbcParam.$(OBJEXT) \ -@CBC_BUILD_CBC_GENERIC_TRUE@ cbc_generic-CbcGenCbcParamUtils.$(OBJEXT) \ -@CBC_BUILD_CBC_GENERIC_TRUE@ cbc_generic-CbcGenCtlBlk.$(OBJEXT) \ -@CBC_BUILD_CBC_GENERIC_TRUE@ cbc_generic-CbcGeneric.$(OBJEXT) \ -@CBC_BUILD_CBC_GENERIC_TRUE@ cbc_generic-CbcGenMessages.$(OBJEXT) \ -@CBC_BUILD_CBC_GENERIC_TRUE@ cbc_generic-CbcGenOsiParam.$(OBJEXT) \ -@CBC_BUILD_CBC_GENERIC_TRUE@ cbc_generic-CbcGenOsiParamUtils.$(OBJEXT) \ -@CBC_BUILD_CBC_GENERIC_TRUE@ cbc_generic-CbcGenParam.$(OBJEXT) \ -@CBC_BUILD_CBC_GENERIC_TRUE@ cbc_generic-CbcGenParamUtils.$(OBJEXT) \ -@CBC_BUILD_CBC_GENERIC_TRUE@ cbc_generic-CbcGenSolution.$(OBJEXT) \ -@CBC_BUILD_CBC_GENERIC_TRUE@ cbc_generic-CbcGenSolvers.$(OBJEXT) -cbc_generic_OBJECTS = $(am_cbc_generic_OBJECTS) -@CBC_BUILD_CBC_GENERIC_TRUE@cbc_generic_DEPENDENCIES = \ -@CBC_BUILD_CBC_GENERIC_TRUE@ libCbcSolver.la libCbc.la \ -@CBC_BUILD_CBC_GENERIC_TRUE@ $(am__DEPENDENCIES_1) +@COIN_HAS_CLP_TRUE@cbc_DEPENDENCIES = libCbc.la AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false @@ -251,28 +225,7 @@ DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/src/OsiCbc depcomp = $(SHELL) $(top_srcdir)/depcomp am__maybe_remake_depfiles = depfiles am__depfiles_remade = ./$(DEPDIR)/cbc-CoinSolve.Po \ - ./$(DEPDIR)/cbc_generic-CbcGenBaB.Po \ - ./$(DEPDIR)/cbc_generic-CbcGenCbcParam.Po \ - ./$(DEPDIR)/cbc_generic-CbcGenCbcParamUtils.Po \ - ./$(DEPDIR)/cbc_generic-CbcGenCtlBlk.Po \ - ./$(DEPDIR)/cbc_generic-CbcGenMessages.Po \ - ./$(DEPDIR)/cbc_generic-CbcGenOsiParam.Po \ - ./$(DEPDIR)/cbc_generic-CbcGenOsiParamUtils.Po \ - ./$(DEPDIR)/cbc_generic-CbcGenParam.Po \ - ./$(DEPDIR)/cbc_generic-CbcGenParamUtils.Po \ - ./$(DEPDIR)/cbc_generic-CbcGenSolution.Po \ - ./$(DEPDIR)/cbc_generic-CbcGenSolvers.Po \ - ./$(DEPDIR)/cbc_generic-CbcGeneric.Po \ - ./$(DEPDIR)/libCbcSolver_la-CbcCbcParam.Plo \ - ./$(DEPDIR)/libCbcSolver_la-CbcLinked.Plo \ - ./$(DEPDIR)/libCbcSolver_la-CbcLinkedUtils.Plo \ - ./$(DEPDIR)/libCbcSolver_la-CbcMipStartIO.Plo \ - ./$(DEPDIR)/libCbcSolver_la-CbcSolver.Plo \ - ./$(DEPDIR)/libCbcSolver_la-CbcSolverAnalyze.Plo \ - ./$(DEPDIR)/libCbcSolver_la-CbcSolverExpandKnapsack.Plo \ - ./$(DEPDIR)/libCbcSolver_la-CbcSolverHeuristics.Plo \ - ./$(DEPDIR)/libCbcSolver_la-Cbc_C_Interface.Plo \ - ./$(DEPDIR)/libCbcSolver_la-unitTestClp.Plo \ + ./$(DEPDIR)/libCbc_la-CbcBab.Plo \ ./$(DEPDIR)/libCbc_la-CbcBranchAllDifferent.Plo \ ./$(DEPDIR)/libCbc_la-CbcBranchCut.Plo \ ./$(DEPDIR)/libCbc_la-CbcBranchDecision.Plo \ @@ -318,25 +271,39 @@ am__depfiles_remade = ./$(DEPDIR)/cbc-CoinSolve.Po \ ./$(DEPDIR)/libCbc_la-CbcHeuristicRINS.Plo \ ./$(DEPDIR)/libCbc_la-CbcHeuristicRandRound.Plo \ ./$(DEPDIR)/libCbc_la-CbcHeuristicVND.Plo \ + ./$(DEPDIR)/libCbc_la-CbcLinked.Plo \ + ./$(DEPDIR)/libCbc_la-CbcLinkedUtils.Plo \ ./$(DEPDIR)/libCbc_la-CbcMessage.Plo \ + ./$(DEPDIR)/libCbc_la-CbcMipStartIO.Plo \ ./$(DEPDIR)/libCbc_la-CbcModel.Plo \ ./$(DEPDIR)/libCbc_la-CbcNWay.Plo \ ./$(DEPDIR)/libCbc_la-CbcNode.Plo \ ./$(DEPDIR)/libCbc_la-CbcNodeInfo.Plo \ ./$(DEPDIR)/libCbc_la-CbcObject.Plo \ ./$(DEPDIR)/libCbc_la-CbcObjectUpdateData.Plo \ + ./$(DEPDIR)/libCbc_la-CbcParam.Plo \ + ./$(DEPDIR)/libCbc_la-CbcParamUtils.Plo \ + ./$(DEPDIR)/libCbc_la-CbcCbcParam.Plo \ + ./$(DEPDIR)/libCbc_la-CbcParameters.Plo \ ./$(DEPDIR)/libCbc_la-CbcPartialNodeInfo.Plo \ ./$(DEPDIR)/libCbc_la-CbcSOS.Plo \ ./$(DEPDIR)/libCbc_la-CbcSimpleInteger.Plo \ ./$(DEPDIR)/libCbc_la-CbcSimpleIntegerDynamicPseudoCost.Plo \ ./$(DEPDIR)/libCbc_la-CbcSimpleIntegerPseudoCost.Plo \ + ./$(DEPDIR)/libCbc_la-CbcSolution.Plo \ + ./$(DEPDIR)/libCbc_la-CbcSolver.Plo \ + ./$(DEPDIR)/libCbc_la-CbcSolverAnalyze.Plo \ + ./$(DEPDIR)/libCbc_la-CbcSolverExpandKnapsack.Plo \ + ./$(DEPDIR)/libCbc_la-CbcSolverHeuristics.Plo \ ./$(DEPDIR)/libCbc_la-CbcStatistics.Plo \ ./$(DEPDIR)/libCbc_la-CbcStrategy.Plo \ ./$(DEPDIR)/libCbc_la-CbcSubProblem.Plo \ ./$(DEPDIR)/libCbc_la-CbcSymmetry.Plo \ ./$(DEPDIR)/libCbc_la-CbcThread.Plo \ ./$(DEPDIR)/libCbc_la-CbcTree.Plo \ - ./$(DEPDIR)/libCbc_la-CbcTreeLocal.Plo + ./$(DEPDIR)/libCbc_la-CbcTreeLocal.Plo \ + ./$(DEPDIR)/libCbc_la-Cbc_C_Interface.Plo \ + ./$(DEPDIR)/libCbc_la-unitTestClp.Plo am__mv = mv -f CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) @@ -374,8 +341,7 @@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = -SOURCES = $(libCbc_la_SOURCES) $(libCbcSolver_la_SOURCES) \ - $(cbc_SOURCES) $(cbc_generic_SOURCES) +SOURCES = $(libCbc_la_SOURCES) $(cbc_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ @@ -383,7 +349,7 @@ am__can_run_installinfo = \ esac HEADERS = $(includecoin_HEADERS) am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) \ - config.h.in config_cbc.h.in config_cbcsolver.h.in + config.h.in config_cbc.h.in # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. @@ -423,11 +389,8 @@ CBCLIB_CFLAGS_NOPC = @CBCLIB_CFLAGS_NOPC@ CBCLIB_LFLAGS = @CBCLIB_LFLAGS@ CBCLIB_LFLAGS_NOPC = @CBCLIB_LFLAGS_NOPC@ CBCLIB_PCFILES = @CBCLIB_PCFILES@ -CBCSOLVERLIB_CFLAGS = @CBCSOLVERLIB_CFLAGS@ CBCSOLVERLIB_CFLAGS_NOPC = @CBCSOLVERLIB_CFLAGS_NOPC@ -CBCSOLVERLIB_LFLAGS = @CBCSOLVERLIB_LFLAGS@ CBCSOLVERLIB_LFLAGS_NOPC = @CBCSOLVERLIB_LFLAGS_NOPC@ -CBCSOLVERLIB_PCFILES = @CBCSOLVERLIB_PCFILES@ CBCUNITTEST_CFLAGS = @CBCUNITTEST_CFLAGS@ CBCUNITTEST_CFLAGS_NOPC = @CBCUNITTEST_CFLAGS_NOPC@ CBCUNITTEST_LFLAGS = @CBCUNITTEST_LFLAGS@ @@ -568,11 +531,12 @@ top_srcdir = @top_srcdir@ # Name of the library compiled in this directory. # We want it to be installed in the 'lib' directory -lib_LTLIBRARIES = libCbc.la libCbcSolver.la +lib_LTLIBRARIES = libCbc.la # List all source files for this library, including headers libCbc_la_SOURCES = \ CbcConfig.h \ + CbcBab.cpp \ CbcBranchActual.hpp \ CbcBranchAllDifferent.cpp CbcBranchAllDifferent.hpp \ CbcBranchBase.hpp \ @@ -625,73 +589,52 @@ libCbc_la_SOURCES = \ CbcHeuristicVND.cpp CbcHeuristicVND.hpp \ CbcHeuristicDW.cpp CbcHeuristicDW.hpp \ CbcMessage.cpp CbcMessage.hpp \ + CbcMipStartIO.cpp CbcMipStartIO.hpp \ CbcModel.cpp CbcModel.hpp \ CbcNode.cpp CbcNode.hpp \ CbcNodeInfo.cpp CbcNodeInfo.hpp \ CbcNWay.cpp CbcNWay.hpp \ CbcObject.cpp CbcObject.hpp \ CbcObjectUpdateData.cpp CbcObjectUpdateData.hpp \ + CbcParam.cpp CbcParam.hpp \ + CbcParamUtils.cpp CbcParamUtils.hpp CbcCbcParam.cpp \ CbcPartialNodeInfo.cpp CbcPartialNodeInfo.hpp \ CbcSimpleInteger.cpp CbcSimpleInteger.hpp \ CbcSimpleIntegerDynamicPseudoCost.cpp \ CbcSimpleIntegerDynamicPseudoCost.hpp \ CbcSimpleIntegerPseudoCost.cpp \ CbcSimpleIntegerPseudoCost.hpp \ - CbcSOS.cpp CbcSOS.hpp \ + CbcSOS.cpp CbcSOS.hpp CbcSolution.cpp \ + CbcSolver.cpp CbcSolverAnalyze.cpp CbcSolverAnalyze.hpp \ + CbcSolverExpandKnapsack.cpp CbcSolverExpandKnapsack.hpp \ + CbcSolverHeuristics.cpp CbcSolverHeuristics.hpp \ + CbcParameters.cpp CbcParameters.hpp \ CbcStatistics.cpp CbcStatistics.hpp \ CbcStrategy.cpp CbcStrategy.hpp \ CbcSubProblem.cpp CbcSubProblem.hpp \ CbcSymmetry.cpp CbcSymmetry.hpp \ CbcThread.cpp CbcThread.hpp \ CbcTree.cpp CbcTree.hpp \ - CbcTreeLocal.cpp CbcTreeLocal.hpp - -libCbcSolver_la_SOURCES = \ + CbcTreeLocal.cpp CbcTreeLocal.hpp \ Cbc_C_Interface.cpp Cbc_C_Interface.h \ - CbcCbcParam.cpp \ CbcLinked.cpp CbcLinked.hpp CbcLinkedUtils.cpp \ - unitTestClp.cpp CbcSolver.cpp \ - CbcSolverHeuristics.cpp CbcSolverHeuristics.hpp \ - CbcSolverAnalyze.cpp CbcSolverAnalyze.hpp \ - CbcMipStartIO.cpp CbcMipStartIO.hpp \ - CbcSolverExpandKnapsack.cpp CbcSolverExpandKnapsack.hpp + unitTestClp.cpp # List all additionally required libraries libCbc_la_LIBADD = $(CBCLIB_LFLAGS) -libCbcSolver_la_LIBADD = $(CBCSOLVERLIB_LFLAGS) libCbc.la # Some common setup for cbc and cbc-generic. libCbc_la_CPPFLAGS = $(CBCLIB_CFLAGS) -libCbcSolver_la_CPPFLAGS = $(CBCSOLVERLIB_CFLAGS) # List all source files for this executable, including headers @COIN_HAS_CLP_TRUE@cbc_SOURCES = CoinSolve.cpp # Additional libraries -@COIN_HAS_CLP_TRUE@cbc_LDADD = libCbcSolver.la libCbc.la +@COIN_HAS_CLP_TRUE@cbc_LDADD = libCbc.la # not really accurate to use these CFLAGS, but they should have everything -@COIN_HAS_CLP_TRUE@cbc_CPPFLAGS = $(CBCSOLVERLIB_CFLAGS) - -# List all source files for this executable, including headers -@CBC_BUILD_CBC_GENERIC_TRUE@cbc_generic_SOURCES = \ -@CBC_BUILD_CBC_GENERIC_TRUE@ CbcGenBaB.cpp \ -@CBC_BUILD_CBC_GENERIC_TRUE@ CbcGenCbcParam.cpp CbcGenCbcParam.hpp CbcGenCbcParamUtils.cpp \ -@CBC_BUILD_CBC_GENERIC_TRUE@ CbcGenCtlBlk.cpp CbcGenCtlBlk.hpp \ -@CBC_BUILD_CBC_GENERIC_TRUE@ CbcGeneric.cpp \ -@CBC_BUILD_CBC_GENERIC_TRUE@ CbcGenMessages.cpp CbcGenMessages.hpp \ -@CBC_BUILD_CBC_GENERIC_TRUE@ CbcGenOsiParam.cpp CbcGenOsiParam.hpp CbcGenOsiParamUtils.cpp \ -@CBC_BUILD_CBC_GENERIC_TRUE@ CbcGenParam.cpp CbcGenParam.hpp CbcGenParamUtils.cpp \ -@CBC_BUILD_CBC_GENERIC_TRUE@ CbcGenSolution.cpp \ -@CBC_BUILD_CBC_GENERIC_TRUE@ CbcGenSolvers.cpp - - -# List all additionally required solver and Osi libraries -# the flags for all available LP solvers should have been collected -# by configure in CBCGENERIC_LFLAGS and CBCGENERIC_CFLAGS -@CBC_BUILD_CBC_GENERIC_TRUE@cbc_generic_LDADD = libCbcSolver.la libCbc.la $(CBCGENERIC_LFLAGS) -@CBC_BUILD_CBC_GENERIC_TRUE@cbc_generic_CPPFLAGS = $(CBCGENERIC_CFLAGS) +@COIN_HAS_CLP_TRUE@cbc_CPPFLAGS = $(CBCLIB_CFLAGS) ######################################################################## # Additional flags # @@ -742,6 +685,7 @@ includecoin_HEADERS = \ CbcFullNodeInfo.hpp \ CbcGeneral.hpp \ CbcGeneralDepth.hpp \ + CbcGenMessages.hpp \ CbcHeuristic.hpp \ CbcHeuristicDINS.hpp \ CbcHeuristicDive.hpp \ @@ -769,6 +713,7 @@ includecoin_HEADERS = \ CbcObjectUpdateData.hpp \ CbcParam.hpp \ CbcPartialNodeInfo.hpp \ + CbcParameters.hpp \ CbcSimpleInteger.hpp \ CbcSimpleIntegerDynamicPseudoCost.hpp \ CbcSimpleIntegerPseudoCost.hpp \ @@ -783,7 +728,7 @@ includecoin_HEADERS = \ ClpConstraintAmpl.hpp \ ClpAmplObjective.hpp -all: config.h config_cbc.h config_cbcsolver.h +all: config.h config_cbc.h $(MAKE) $(AM_MAKEFLAGS) all-am .SUFFIXES: @@ -838,16 +783,8 @@ stamp-h2: $(srcdir)/config_cbc.h.in $(top_builddir)/config.status @rm -f stamp-h2 cd $(top_builddir) && $(SHELL) ./config.status src/config_cbc.h -config_cbcsolver.h: stamp-h3 - @test -f $@ || rm -f stamp-h3 - @test -f $@ || $(MAKE) $(AM_MAKEFLAGS) stamp-h3 - -stamp-h3: $(srcdir)/config_cbcsolver.h.in $(top_builddir)/config.status - @rm -f stamp-h3 - cd $(top_builddir) && $(SHELL) ./config.status src/config_cbcsolver.h - distclean-hdr: - -rm -f config.h stamp-h1 config_cbc.h stamp-h2 config_cbcsolver.h stamp-h3 + -rm -f config.h stamp-h1 config_cbc.h stamp-h2 install-binPROGRAMS: $(bin_PROGRAMS) @$(NORMAL_INSTALL) @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ @@ -936,17 +873,10 @@ clean-libLTLIBRARIES: libCbc.la: $(libCbc_la_OBJECTS) $(libCbc_la_DEPENDENCIES) $(EXTRA_libCbc_la_DEPENDENCIES) $(AM_V_CXXLD)$(CXXLINK) -rpath $(libdir) $(libCbc_la_OBJECTS) $(libCbc_la_LIBADD) $(LIBS) -libCbcSolver.la: $(libCbcSolver_la_OBJECTS) $(libCbcSolver_la_DEPENDENCIES) $(EXTRA_libCbcSolver_la_DEPENDENCIES) - $(AM_V_CXXLD)$(CXXLINK) -rpath $(libdir) $(libCbcSolver_la_OBJECTS) $(libCbcSolver_la_LIBADD) $(LIBS) - cbc$(EXEEXT): $(cbc_OBJECTS) $(cbc_DEPENDENCIES) $(EXTRA_cbc_DEPENDENCIES) @rm -f cbc$(EXEEXT) $(AM_V_CXXLD)$(CXXLINK) $(cbc_OBJECTS) $(cbc_LDADD) $(LIBS) -cbc-generic$(EXEEXT): $(cbc_generic_OBJECTS) $(cbc_generic_DEPENDENCIES) $(EXTRA_cbc_generic_DEPENDENCIES) - @rm -f cbc-generic$(EXEEXT) - $(AM_V_CXXLD)$(CXXLINK) $(cbc_generic_OBJECTS) $(cbc_generic_LDADD) $(LIBS) - mostlyclean-compile: -rm -f *.$(OBJEXT) @@ -954,28 +884,7 @@ distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cbc-CoinSolve.Po@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cbc_generic-CbcGenBaB.Po@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cbc_generic-CbcGenCbcParam.Po@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cbc_generic-CbcGenCbcParamUtils.Po@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cbc_generic-CbcGenCtlBlk.Po@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cbc_generic-CbcGenMessages.Po@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cbc_generic-CbcGenOsiParam.Po@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cbc_generic-CbcGenOsiParamUtils.Po@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cbc_generic-CbcGenParam.Po@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cbc_generic-CbcGenParamUtils.Po@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cbc_generic-CbcGenSolution.Po@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cbc_generic-CbcGenSolvers.Po@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cbc_generic-CbcGeneric.Po@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libCbcSolver_la-CbcCbcParam.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libCbcSolver_la-CbcLinked.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libCbcSolver_la-CbcLinkedUtils.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libCbcSolver_la-CbcMipStartIO.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libCbcSolver_la-CbcSolver.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libCbcSolver_la-CbcSolverAnalyze.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libCbcSolver_la-CbcSolverExpandKnapsack.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libCbcSolver_la-CbcSolverHeuristics.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libCbcSolver_la-Cbc_C_Interface.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libCbcSolver_la-unitTestClp.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libCbc_la-CbcBab.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libCbc_la-CbcBranchAllDifferent.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libCbc_la-CbcBranchCut.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libCbc_la-CbcBranchDecision.Plo@am__quote@ # am--include-marker @@ -1021,18 +930,30 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libCbc_la-CbcHeuristicRINS.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libCbc_la-CbcHeuristicRandRound.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libCbc_la-CbcHeuristicVND.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libCbc_la-CbcLinked.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libCbc_la-CbcLinkedUtils.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libCbc_la-CbcMessage.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libCbc_la-CbcMipStartIO.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libCbc_la-CbcModel.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libCbc_la-CbcNWay.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libCbc_la-CbcNode.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libCbc_la-CbcNodeInfo.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libCbc_la-CbcObject.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libCbc_la-CbcObjectUpdateData.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libCbc_la-CbcParam.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libCbc_la-CbcParamUtils.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libCbc_la-CbcCbcParam.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libCbc_la-CbcParameters.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libCbc_la-CbcPartialNodeInfo.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libCbc_la-CbcSOS.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libCbc_la-CbcSimpleInteger.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libCbc_la-CbcSimpleIntegerDynamicPseudoCost.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libCbc_la-CbcSimpleIntegerPseudoCost.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libCbc_la-CbcSolution.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libCbc_la-CbcSolver.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libCbc_la-CbcSolverAnalyze.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libCbc_la-CbcSolverExpandKnapsack.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libCbc_la-CbcSolverHeuristics.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libCbc_la-CbcStatistics.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libCbc_la-CbcStrategy.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libCbc_la-CbcSubProblem.Plo@am__quote@ # am--include-marker @@ -1040,6 +961,8 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libCbc_la-CbcThread.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libCbc_la-CbcTree.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libCbc_la-CbcTreeLocal.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libCbc_la-Cbc_C_Interface.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libCbc_la-unitTestClp.Plo@am__quote@ # am--include-marker $(am__depfiles_remade): @$(MKDIR_P) $(@D) @@ -1071,6 +994,13 @@ am--depfiles: $(am__depfiles_remade) @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LTCXXCOMPILE) -c -o $@ $< +libCbc_la-CbcBab.lo: CbcBab.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libCbc_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libCbc_la-CbcBab.lo -MD -MP -MF $(DEPDIR)/libCbc_la-CbcBab.Tpo -c -o libCbc_la-CbcBab.lo `test -f 'CbcBab.cpp' || echo '$(srcdir)/'`CbcBab.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libCbc_la-CbcBab.Tpo $(DEPDIR)/libCbc_la-CbcBab.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='CbcBab.cpp' object='libCbc_la-CbcBab.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libCbc_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libCbc_la-CbcBab.lo `test -f 'CbcBab.cpp' || echo '$(srcdir)/'`CbcBab.cpp + libCbc_la-CbcBranchAllDifferent.lo: CbcBranchAllDifferent.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libCbc_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libCbc_la-CbcBranchAllDifferent.lo -MD -MP -MF $(DEPDIR)/libCbc_la-CbcBranchAllDifferent.Tpo -c -o libCbc_la-CbcBranchAllDifferent.lo `test -f 'CbcBranchAllDifferent.cpp' || echo '$(srcdir)/'`CbcBranchAllDifferent.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libCbc_la-CbcBranchAllDifferent.Tpo $(DEPDIR)/libCbc_la-CbcBranchAllDifferent.Plo @@ -1393,6 +1323,13 @@ libCbc_la-CbcMessage.lo: CbcMessage.cpp @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libCbc_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libCbc_la-CbcMessage.lo `test -f 'CbcMessage.cpp' || echo '$(srcdir)/'`CbcMessage.cpp +libCbc_la-CbcMipStartIO.lo: CbcMipStartIO.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libCbc_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libCbc_la-CbcMipStartIO.lo -MD -MP -MF $(DEPDIR)/libCbc_la-CbcMipStartIO.Tpo -c -o libCbc_la-CbcMipStartIO.lo `test -f 'CbcMipStartIO.cpp' || echo '$(srcdir)/'`CbcMipStartIO.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libCbc_la-CbcMipStartIO.Tpo $(DEPDIR)/libCbc_la-CbcMipStartIO.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='CbcMipStartIO.cpp' object='libCbc_la-CbcMipStartIO.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libCbc_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libCbc_la-CbcMipStartIO.lo `test -f 'CbcMipStartIO.cpp' || echo '$(srcdir)/'`CbcMipStartIO.cpp + libCbc_la-CbcModel.lo: CbcModel.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libCbc_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libCbc_la-CbcModel.lo -MD -MP -MF $(DEPDIR)/libCbc_la-CbcModel.Tpo -c -o libCbc_la-CbcModel.lo `test -f 'CbcModel.cpp' || echo '$(srcdir)/'`CbcModel.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libCbc_la-CbcModel.Tpo $(DEPDIR)/libCbc_la-CbcModel.Plo @@ -1435,6 +1372,27 @@ libCbc_la-CbcObjectUpdateData.lo: CbcObjectUpdateData.cpp @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libCbc_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libCbc_la-CbcObjectUpdateData.lo `test -f 'CbcObjectUpdateData.cpp' || echo '$(srcdir)/'`CbcObjectUpdateData.cpp +libCbc_la-CbcParam.lo: CbcParam.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libCbc_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libCbc_la-CbcParam.lo -MD -MP -MF $(DEPDIR)/libCbc_la-CbcParam.Tpo -c -o libCbc_la-CbcParam.lo `test -f 'CbcParam.cpp' || echo '$(srcdir)/'`CbcParam.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libCbc_la-CbcParam.Tpo $(DEPDIR)/libCbc_la-CbcParam.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='CbcParam.cpp' object='libCbc_la-CbcParam.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libCbc_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libCbc_la-CbcParam.lo `test -f 'CbcParam.cpp' || echo '$(srcdir)/'`CbcParam.cpp + +libCbc_la-CbcParamUtils.lo: CbcParamUtils.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libCbc_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libCbc_la-CbcParamUtils.lo -MD -MP -MF $(DEPDIR)/libCbc_la-CbcParamUtils.Tpo -c -o libCbc_la-CbcParamUtils.lo `test -f 'CbcParamUtils.cpp' || echo '$(srcdir)/'`CbcParamUtils.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libCbc_la-CbcParamUtils.Tpo $(DEPDIR)/libCbc_la-CbcParamUtils.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='CbcParamUtils.cpp' object='libCbc_la-CbcParamUtils.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libCbc_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libCbc_la-CbcParamUtils.lo `test -f 'CbcParamUtils.cpp' || echo '$(srcdir)/'`CbcParamUtils.cpp + +libCbc_la-CbcCbcParam.lo: CbcCbcParam.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libCbc_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libCbc_la-CbcCbcParam.lo -MD -MP -MF $(DEPDIR)/libCbc_la-CbcCbcParam.Tpo -c -o libCbc_la-CbcCbcParam.lo `test -f 'CbcCbcParam.cpp' || echo '$(srcdir)/'`CbcCbcParam.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libCbc_la-CbcCbcParam.Tpo $(DEPDIR)/libCbc_la-CbcCbcParam.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='CbcCbcParam.cpp' object='libCbc_la-CbcCbcParam.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libCbc_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libCbc_la-CbcCbcParam.lo `test -f 'CbcCbcParam.cpp' || echo '$(srcdir)/'`CbcCbcParam.cpp + libCbc_la-CbcPartialNodeInfo.lo: CbcPartialNodeInfo.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libCbc_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libCbc_la-CbcPartialNodeInfo.lo -MD -MP -MF $(DEPDIR)/libCbc_la-CbcPartialNodeInfo.Tpo -c -o libCbc_la-CbcPartialNodeInfo.lo `test -f 'CbcPartialNodeInfo.cpp' || echo '$(srcdir)/'`CbcPartialNodeInfo.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libCbc_la-CbcPartialNodeInfo.Tpo $(DEPDIR)/libCbc_la-CbcPartialNodeInfo.Plo @@ -1470,6 +1428,48 @@ libCbc_la-CbcSOS.lo: CbcSOS.cpp @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libCbc_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libCbc_la-CbcSOS.lo `test -f 'CbcSOS.cpp' || echo '$(srcdir)/'`CbcSOS.cpp +libCbc_la-CbcSolution.lo: CbcSolution.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libCbc_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libCbc_la-CbcSolution.lo -MD -MP -MF $(DEPDIR)/libCbc_la-CbcSolution.Tpo -c -o libCbc_la-CbcSolution.lo `test -f 'CbcSolution.cpp' || echo '$(srcdir)/'`CbcSolution.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libCbc_la-CbcSolution.Tpo $(DEPDIR)/libCbc_la-CbcSolution.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='CbcSolution.cpp' object='libCbc_la-CbcSolution.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libCbc_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libCbc_la-CbcSolution.lo `test -f 'CbcSolution.cpp' || echo '$(srcdir)/'`CbcSolution.cpp + +libCbc_la-CbcSolver.lo: CbcSolver.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libCbc_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libCbc_la-CbcSolver.lo -MD -MP -MF $(DEPDIR)/libCbc_la-CbcSolver.Tpo -c -o libCbc_la-CbcSolver.lo `test -f 'CbcSolver.cpp' || echo '$(srcdir)/'`CbcSolver.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libCbc_la-CbcSolver.Tpo $(DEPDIR)/libCbc_la-CbcSolver.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='CbcSolver.cpp' object='libCbc_la-CbcSolver.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libCbc_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libCbc_la-CbcSolver.lo `test -f 'CbcSolver.cpp' || echo '$(srcdir)/'`CbcSolver.cpp + +libCbc_la-CbcSolverAnalyze.lo: CbcSolverAnalyze.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libCbc_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libCbc_la-CbcSolverAnalyze.lo -MD -MP -MF $(DEPDIR)/libCbc_la-CbcSolverAnalyze.Tpo -c -o libCbc_la-CbcSolverAnalyze.lo `test -f 'CbcSolverAnalyze.cpp' || echo '$(srcdir)/'`CbcSolverAnalyze.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libCbc_la-CbcSolverAnalyze.Tpo $(DEPDIR)/libCbc_la-CbcSolverAnalyze.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='CbcSolverAnalyze.cpp' object='libCbc_la-CbcSolverAnalyze.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libCbc_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libCbc_la-CbcSolverAnalyze.lo `test -f 'CbcSolverAnalyze.cpp' || echo '$(srcdir)/'`CbcSolverAnalyze.cpp + +libCbc_la-CbcSolverExpandKnapsack.lo: CbcSolverExpandKnapsack.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libCbc_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libCbc_la-CbcSolverExpandKnapsack.lo -MD -MP -MF $(DEPDIR)/libCbc_la-CbcSolverExpandKnapsack.Tpo -c -o libCbc_la-CbcSolverExpandKnapsack.lo `test -f 'CbcSolverExpandKnapsack.cpp' || echo '$(srcdir)/'`CbcSolverExpandKnapsack.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libCbc_la-CbcSolverExpandKnapsack.Tpo $(DEPDIR)/libCbc_la-CbcSolverExpandKnapsack.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='CbcSolverExpandKnapsack.cpp' object='libCbc_la-CbcSolverExpandKnapsack.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libCbc_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libCbc_la-CbcSolverExpandKnapsack.lo `test -f 'CbcSolverExpandKnapsack.cpp' || echo '$(srcdir)/'`CbcSolverExpandKnapsack.cpp + +libCbc_la-CbcSolverHeuristics.lo: CbcSolverHeuristics.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libCbc_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libCbc_la-CbcSolverHeuristics.lo -MD -MP -MF $(DEPDIR)/libCbc_la-CbcSolverHeuristics.Tpo -c -o libCbc_la-CbcSolverHeuristics.lo `test -f 'CbcSolverHeuristics.cpp' || echo '$(srcdir)/'`CbcSolverHeuristics.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libCbc_la-CbcSolverHeuristics.Tpo $(DEPDIR)/libCbc_la-CbcSolverHeuristics.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='CbcSolverHeuristics.cpp' object='libCbc_la-CbcSolverHeuristics.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libCbc_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libCbc_la-CbcSolverHeuristics.lo `test -f 'CbcSolverHeuristics.cpp' || echo '$(srcdir)/'`CbcSolverHeuristics.cpp + +libCbc_la-CbcParameters.lo: CbcParameters.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libCbc_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libCbc_la-CbcParameters.lo -MD -MP -MF $(DEPDIR)/libCbc_la-CbcParameters.Tpo -c -o libCbc_la-CbcParameters.lo `test -f 'CbcParameters.cpp' || echo '$(srcdir)/'`CbcParameters.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libCbc_la-CbcParameters.Tpo $(DEPDIR)/libCbc_la-CbcParameters.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='CbcParameters.cpp' object='libCbc_la-CbcParameters.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libCbc_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libCbc_la-CbcParameters.lo `test -f 'CbcParameters.cpp' || echo '$(srcdir)/'`CbcParameters.cpp + libCbc_la-CbcStatistics.lo: CbcStatistics.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libCbc_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libCbc_la-CbcStatistics.lo -MD -MP -MF $(DEPDIR)/libCbc_la-CbcStatistics.Tpo -c -o libCbc_la-CbcStatistics.lo `test -f 'CbcStatistics.cpp' || echo '$(srcdir)/'`CbcStatistics.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libCbc_la-CbcStatistics.Tpo $(DEPDIR)/libCbc_la-CbcStatistics.Plo @@ -1519,75 +1519,33 @@ libCbc_la-CbcTreeLocal.lo: CbcTreeLocal.cpp @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libCbc_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libCbc_la-CbcTreeLocal.lo `test -f 'CbcTreeLocal.cpp' || echo '$(srcdir)/'`CbcTreeLocal.cpp -libCbcSolver_la-Cbc_C_Interface.lo: Cbc_C_Interface.cpp -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libCbcSolver_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libCbcSolver_la-Cbc_C_Interface.lo -MD -MP -MF $(DEPDIR)/libCbcSolver_la-Cbc_C_Interface.Tpo -c -o libCbcSolver_la-Cbc_C_Interface.lo `test -f 'Cbc_C_Interface.cpp' || echo '$(srcdir)/'`Cbc_C_Interface.cpp -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libCbcSolver_la-Cbc_C_Interface.Tpo $(DEPDIR)/libCbcSolver_la-Cbc_C_Interface.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='Cbc_C_Interface.cpp' object='libCbcSolver_la-Cbc_C_Interface.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libCbcSolver_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libCbcSolver_la-Cbc_C_Interface.lo `test -f 'Cbc_C_Interface.cpp' || echo '$(srcdir)/'`Cbc_C_Interface.cpp - -libCbcSolver_la-CbcCbcParam.lo: CbcCbcParam.cpp -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libCbcSolver_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libCbcSolver_la-CbcCbcParam.lo -MD -MP -MF $(DEPDIR)/libCbcSolver_la-CbcCbcParam.Tpo -c -o libCbcSolver_la-CbcCbcParam.lo `test -f 'CbcCbcParam.cpp' || echo '$(srcdir)/'`CbcCbcParam.cpp -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libCbcSolver_la-CbcCbcParam.Tpo $(DEPDIR)/libCbcSolver_la-CbcCbcParam.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='CbcCbcParam.cpp' object='libCbcSolver_la-CbcCbcParam.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libCbcSolver_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libCbcSolver_la-CbcCbcParam.lo `test -f 'CbcCbcParam.cpp' || echo '$(srcdir)/'`CbcCbcParam.cpp - -libCbcSolver_la-CbcLinked.lo: CbcLinked.cpp -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libCbcSolver_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libCbcSolver_la-CbcLinked.lo -MD -MP -MF $(DEPDIR)/libCbcSolver_la-CbcLinked.Tpo -c -o libCbcSolver_la-CbcLinked.lo `test -f 'CbcLinked.cpp' || echo '$(srcdir)/'`CbcLinked.cpp -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libCbcSolver_la-CbcLinked.Tpo $(DEPDIR)/libCbcSolver_la-CbcLinked.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='CbcLinked.cpp' object='libCbcSolver_la-CbcLinked.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libCbcSolver_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libCbcSolver_la-CbcLinked.lo `test -f 'CbcLinked.cpp' || echo '$(srcdir)/'`CbcLinked.cpp - -libCbcSolver_la-CbcLinkedUtils.lo: CbcLinkedUtils.cpp -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libCbcSolver_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libCbcSolver_la-CbcLinkedUtils.lo -MD -MP -MF $(DEPDIR)/libCbcSolver_la-CbcLinkedUtils.Tpo -c -o libCbcSolver_la-CbcLinkedUtils.lo `test -f 'CbcLinkedUtils.cpp' || echo '$(srcdir)/'`CbcLinkedUtils.cpp -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libCbcSolver_la-CbcLinkedUtils.Tpo $(DEPDIR)/libCbcSolver_la-CbcLinkedUtils.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='CbcLinkedUtils.cpp' object='libCbcSolver_la-CbcLinkedUtils.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libCbcSolver_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libCbcSolver_la-CbcLinkedUtils.lo `test -f 'CbcLinkedUtils.cpp' || echo '$(srcdir)/'`CbcLinkedUtils.cpp - -libCbcSolver_la-unitTestClp.lo: unitTestClp.cpp -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libCbcSolver_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libCbcSolver_la-unitTestClp.lo -MD -MP -MF $(DEPDIR)/libCbcSolver_la-unitTestClp.Tpo -c -o libCbcSolver_la-unitTestClp.lo `test -f 'unitTestClp.cpp' || echo '$(srcdir)/'`unitTestClp.cpp -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libCbcSolver_la-unitTestClp.Tpo $(DEPDIR)/libCbcSolver_la-unitTestClp.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='unitTestClp.cpp' object='libCbcSolver_la-unitTestClp.lo' libtool=yes @AMDEPBACKSLASH@ +libCbc_la-Cbc_C_Interface.lo: Cbc_C_Interface.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libCbc_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libCbc_la-Cbc_C_Interface.lo -MD -MP -MF $(DEPDIR)/libCbc_la-Cbc_C_Interface.Tpo -c -o libCbc_la-Cbc_C_Interface.lo `test -f 'Cbc_C_Interface.cpp' || echo '$(srcdir)/'`Cbc_C_Interface.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libCbc_la-Cbc_C_Interface.Tpo $(DEPDIR)/libCbc_la-Cbc_C_Interface.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='Cbc_C_Interface.cpp' object='libCbc_la-Cbc_C_Interface.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libCbcSolver_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libCbcSolver_la-unitTestClp.lo `test -f 'unitTestClp.cpp' || echo '$(srcdir)/'`unitTestClp.cpp +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libCbc_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libCbc_la-Cbc_C_Interface.lo `test -f 'Cbc_C_Interface.cpp' || echo '$(srcdir)/'`Cbc_C_Interface.cpp -libCbcSolver_la-CbcSolver.lo: CbcSolver.cpp -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libCbcSolver_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libCbcSolver_la-CbcSolver.lo -MD -MP -MF $(DEPDIR)/libCbcSolver_la-CbcSolver.Tpo -c -o libCbcSolver_la-CbcSolver.lo `test -f 'CbcSolver.cpp' || echo '$(srcdir)/'`CbcSolver.cpp -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libCbcSolver_la-CbcSolver.Tpo $(DEPDIR)/libCbcSolver_la-CbcSolver.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='CbcSolver.cpp' object='libCbcSolver_la-CbcSolver.lo' libtool=yes @AMDEPBACKSLASH@ +libCbc_la-CbcLinked.lo: CbcLinked.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libCbc_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libCbc_la-CbcLinked.lo -MD -MP -MF $(DEPDIR)/libCbc_la-CbcLinked.Tpo -c -o libCbc_la-CbcLinked.lo `test -f 'CbcLinked.cpp' || echo '$(srcdir)/'`CbcLinked.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libCbc_la-CbcLinked.Tpo $(DEPDIR)/libCbc_la-CbcLinked.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='CbcLinked.cpp' object='libCbc_la-CbcLinked.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libCbcSolver_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libCbcSolver_la-CbcSolver.lo `test -f 'CbcSolver.cpp' || echo '$(srcdir)/'`CbcSolver.cpp +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libCbc_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libCbc_la-CbcLinked.lo `test -f 'CbcLinked.cpp' || echo '$(srcdir)/'`CbcLinked.cpp -libCbcSolver_la-CbcSolverHeuristics.lo: CbcSolverHeuristics.cpp -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libCbcSolver_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libCbcSolver_la-CbcSolverHeuristics.lo -MD -MP -MF $(DEPDIR)/libCbcSolver_la-CbcSolverHeuristics.Tpo -c -o libCbcSolver_la-CbcSolverHeuristics.lo `test -f 'CbcSolverHeuristics.cpp' || echo '$(srcdir)/'`CbcSolverHeuristics.cpp -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libCbcSolver_la-CbcSolverHeuristics.Tpo $(DEPDIR)/libCbcSolver_la-CbcSolverHeuristics.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='CbcSolverHeuristics.cpp' object='libCbcSolver_la-CbcSolverHeuristics.lo' libtool=yes @AMDEPBACKSLASH@ +libCbc_la-CbcLinkedUtils.lo: CbcLinkedUtils.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libCbc_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libCbc_la-CbcLinkedUtils.lo -MD -MP -MF $(DEPDIR)/libCbc_la-CbcLinkedUtils.Tpo -c -o libCbc_la-CbcLinkedUtils.lo `test -f 'CbcLinkedUtils.cpp' || echo '$(srcdir)/'`CbcLinkedUtils.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libCbc_la-CbcLinkedUtils.Tpo $(DEPDIR)/libCbc_la-CbcLinkedUtils.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='CbcLinkedUtils.cpp' object='libCbc_la-CbcLinkedUtils.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libCbcSolver_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libCbcSolver_la-CbcSolverHeuristics.lo `test -f 'CbcSolverHeuristics.cpp' || echo '$(srcdir)/'`CbcSolverHeuristics.cpp +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libCbc_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libCbc_la-CbcLinkedUtils.lo `test -f 'CbcLinkedUtils.cpp' || echo '$(srcdir)/'`CbcLinkedUtils.cpp -libCbcSolver_la-CbcSolverAnalyze.lo: CbcSolverAnalyze.cpp -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libCbcSolver_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libCbcSolver_la-CbcSolverAnalyze.lo -MD -MP -MF $(DEPDIR)/libCbcSolver_la-CbcSolverAnalyze.Tpo -c -o libCbcSolver_la-CbcSolverAnalyze.lo `test -f 'CbcSolverAnalyze.cpp' || echo '$(srcdir)/'`CbcSolverAnalyze.cpp -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libCbcSolver_la-CbcSolverAnalyze.Tpo $(DEPDIR)/libCbcSolver_la-CbcSolverAnalyze.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='CbcSolverAnalyze.cpp' object='libCbcSolver_la-CbcSolverAnalyze.lo' libtool=yes @AMDEPBACKSLASH@ +libCbc_la-unitTestClp.lo: unitTestClp.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libCbc_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libCbc_la-unitTestClp.lo -MD -MP -MF $(DEPDIR)/libCbc_la-unitTestClp.Tpo -c -o libCbc_la-unitTestClp.lo `test -f 'unitTestClp.cpp' || echo '$(srcdir)/'`unitTestClp.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libCbc_la-unitTestClp.Tpo $(DEPDIR)/libCbc_la-unitTestClp.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='unitTestClp.cpp' object='libCbc_la-unitTestClp.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libCbcSolver_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libCbcSolver_la-CbcSolverAnalyze.lo `test -f 'CbcSolverAnalyze.cpp' || echo '$(srcdir)/'`CbcSolverAnalyze.cpp - -libCbcSolver_la-CbcMipStartIO.lo: CbcMipStartIO.cpp -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libCbcSolver_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libCbcSolver_la-CbcMipStartIO.lo -MD -MP -MF $(DEPDIR)/libCbcSolver_la-CbcMipStartIO.Tpo -c -o libCbcSolver_la-CbcMipStartIO.lo `test -f 'CbcMipStartIO.cpp' || echo '$(srcdir)/'`CbcMipStartIO.cpp -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libCbcSolver_la-CbcMipStartIO.Tpo $(DEPDIR)/libCbcSolver_la-CbcMipStartIO.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='CbcMipStartIO.cpp' object='libCbcSolver_la-CbcMipStartIO.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libCbcSolver_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libCbcSolver_la-CbcMipStartIO.lo `test -f 'CbcMipStartIO.cpp' || echo '$(srcdir)/'`CbcMipStartIO.cpp - -libCbcSolver_la-CbcSolverExpandKnapsack.lo: CbcSolverExpandKnapsack.cpp -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libCbcSolver_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libCbcSolver_la-CbcSolverExpandKnapsack.lo -MD -MP -MF $(DEPDIR)/libCbcSolver_la-CbcSolverExpandKnapsack.Tpo -c -o libCbcSolver_la-CbcSolverExpandKnapsack.lo `test -f 'CbcSolverExpandKnapsack.cpp' || echo '$(srcdir)/'`CbcSolverExpandKnapsack.cpp -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libCbcSolver_la-CbcSolverExpandKnapsack.Tpo $(DEPDIR)/libCbcSolver_la-CbcSolverExpandKnapsack.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='CbcSolverExpandKnapsack.cpp' object='libCbcSolver_la-CbcSolverExpandKnapsack.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libCbcSolver_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libCbcSolver_la-CbcSolverExpandKnapsack.lo `test -f 'CbcSolverExpandKnapsack.cpp' || echo '$(srcdir)/'`CbcSolverExpandKnapsack.cpp +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libCbc_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libCbc_la-unitTestClp.lo `test -f 'unitTestClp.cpp' || echo '$(srcdir)/'`unitTestClp.cpp cbc-CoinSolve.o: CoinSolve.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cbc_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT cbc-CoinSolve.o -MD -MP -MF $(DEPDIR)/cbc-CoinSolve.Tpo -c -o cbc-CoinSolve.o `test -f 'CoinSolve.cpp' || echo '$(srcdir)/'`CoinSolve.cpp @@ -1603,174 +1561,6 @@ cbc-CoinSolve.obj: CoinSolve.cpp @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cbc_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o cbc-CoinSolve.obj `if test -f 'CoinSolve.cpp'; then $(CYGPATH_W) 'CoinSolve.cpp'; else $(CYGPATH_W) '$(srcdir)/CoinSolve.cpp'; fi` -cbc_generic-CbcGenBaB.o: CbcGenBaB.cpp -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cbc_generic_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT cbc_generic-CbcGenBaB.o -MD -MP -MF $(DEPDIR)/cbc_generic-CbcGenBaB.Tpo -c -o cbc_generic-CbcGenBaB.o `test -f 'CbcGenBaB.cpp' || echo '$(srcdir)/'`CbcGenBaB.cpp -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/cbc_generic-CbcGenBaB.Tpo $(DEPDIR)/cbc_generic-CbcGenBaB.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='CbcGenBaB.cpp' object='cbc_generic-CbcGenBaB.o' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cbc_generic_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o cbc_generic-CbcGenBaB.o `test -f 'CbcGenBaB.cpp' || echo '$(srcdir)/'`CbcGenBaB.cpp - -cbc_generic-CbcGenBaB.obj: CbcGenBaB.cpp -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cbc_generic_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT cbc_generic-CbcGenBaB.obj -MD -MP -MF $(DEPDIR)/cbc_generic-CbcGenBaB.Tpo -c -o cbc_generic-CbcGenBaB.obj `if test -f 'CbcGenBaB.cpp'; then $(CYGPATH_W) 'CbcGenBaB.cpp'; else $(CYGPATH_W) '$(srcdir)/CbcGenBaB.cpp'; fi` -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/cbc_generic-CbcGenBaB.Tpo $(DEPDIR)/cbc_generic-CbcGenBaB.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='CbcGenBaB.cpp' object='cbc_generic-CbcGenBaB.obj' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cbc_generic_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o cbc_generic-CbcGenBaB.obj `if test -f 'CbcGenBaB.cpp'; then $(CYGPATH_W) 'CbcGenBaB.cpp'; else $(CYGPATH_W) '$(srcdir)/CbcGenBaB.cpp'; fi` - -cbc_generic-CbcGenCbcParam.o: CbcGenCbcParam.cpp -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cbc_generic_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT cbc_generic-CbcGenCbcParam.o -MD -MP -MF $(DEPDIR)/cbc_generic-CbcGenCbcParam.Tpo -c -o cbc_generic-CbcGenCbcParam.o `test -f 'CbcGenCbcParam.cpp' || echo '$(srcdir)/'`CbcGenCbcParam.cpp -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/cbc_generic-CbcGenCbcParam.Tpo $(DEPDIR)/cbc_generic-CbcGenCbcParam.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='CbcGenCbcParam.cpp' object='cbc_generic-CbcGenCbcParam.o' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cbc_generic_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o cbc_generic-CbcGenCbcParam.o `test -f 'CbcGenCbcParam.cpp' || echo '$(srcdir)/'`CbcGenCbcParam.cpp - -cbc_generic-CbcGenCbcParam.obj: CbcGenCbcParam.cpp -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cbc_generic_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT cbc_generic-CbcGenCbcParam.obj -MD -MP -MF $(DEPDIR)/cbc_generic-CbcGenCbcParam.Tpo -c -o cbc_generic-CbcGenCbcParam.obj `if test -f 'CbcGenCbcParam.cpp'; then $(CYGPATH_W) 'CbcGenCbcParam.cpp'; else $(CYGPATH_W) '$(srcdir)/CbcGenCbcParam.cpp'; fi` -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/cbc_generic-CbcGenCbcParam.Tpo $(DEPDIR)/cbc_generic-CbcGenCbcParam.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='CbcGenCbcParam.cpp' object='cbc_generic-CbcGenCbcParam.obj' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cbc_generic_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o cbc_generic-CbcGenCbcParam.obj `if test -f 'CbcGenCbcParam.cpp'; then $(CYGPATH_W) 'CbcGenCbcParam.cpp'; else $(CYGPATH_W) '$(srcdir)/CbcGenCbcParam.cpp'; fi` - -cbc_generic-CbcGenCbcParamUtils.o: CbcGenCbcParamUtils.cpp -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cbc_generic_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT cbc_generic-CbcGenCbcParamUtils.o -MD -MP -MF $(DEPDIR)/cbc_generic-CbcGenCbcParamUtils.Tpo -c -o cbc_generic-CbcGenCbcParamUtils.o `test -f 'CbcGenCbcParamUtils.cpp' || echo '$(srcdir)/'`CbcGenCbcParamUtils.cpp -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/cbc_generic-CbcGenCbcParamUtils.Tpo $(DEPDIR)/cbc_generic-CbcGenCbcParamUtils.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='CbcGenCbcParamUtils.cpp' object='cbc_generic-CbcGenCbcParamUtils.o' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cbc_generic_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o cbc_generic-CbcGenCbcParamUtils.o `test -f 'CbcGenCbcParamUtils.cpp' || echo '$(srcdir)/'`CbcGenCbcParamUtils.cpp - -cbc_generic-CbcGenCbcParamUtils.obj: CbcGenCbcParamUtils.cpp -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cbc_generic_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT cbc_generic-CbcGenCbcParamUtils.obj -MD -MP -MF $(DEPDIR)/cbc_generic-CbcGenCbcParamUtils.Tpo -c -o cbc_generic-CbcGenCbcParamUtils.obj `if test -f 'CbcGenCbcParamUtils.cpp'; then $(CYGPATH_W) 'CbcGenCbcParamUtils.cpp'; else $(CYGPATH_W) '$(srcdir)/CbcGenCbcParamUtils.cpp'; fi` -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/cbc_generic-CbcGenCbcParamUtils.Tpo $(DEPDIR)/cbc_generic-CbcGenCbcParamUtils.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='CbcGenCbcParamUtils.cpp' object='cbc_generic-CbcGenCbcParamUtils.obj' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cbc_generic_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o cbc_generic-CbcGenCbcParamUtils.obj `if test -f 'CbcGenCbcParamUtils.cpp'; then $(CYGPATH_W) 'CbcGenCbcParamUtils.cpp'; else $(CYGPATH_W) '$(srcdir)/CbcGenCbcParamUtils.cpp'; fi` - -cbc_generic-CbcGenCtlBlk.o: CbcGenCtlBlk.cpp -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cbc_generic_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT cbc_generic-CbcGenCtlBlk.o -MD -MP -MF $(DEPDIR)/cbc_generic-CbcGenCtlBlk.Tpo -c -o cbc_generic-CbcGenCtlBlk.o `test -f 'CbcGenCtlBlk.cpp' || echo '$(srcdir)/'`CbcGenCtlBlk.cpp -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/cbc_generic-CbcGenCtlBlk.Tpo $(DEPDIR)/cbc_generic-CbcGenCtlBlk.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='CbcGenCtlBlk.cpp' object='cbc_generic-CbcGenCtlBlk.o' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cbc_generic_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o cbc_generic-CbcGenCtlBlk.o `test -f 'CbcGenCtlBlk.cpp' || echo '$(srcdir)/'`CbcGenCtlBlk.cpp - -cbc_generic-CbcGenCtlBlk.obj: CbcGenCtlBlk.cpp -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cbc_generic_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT cbc_generic-CbcGenCtlBlk.obj -MD -MP -MF $(DEPDIR)/cbc_generic-CbcGenCtlBlk.Tpo -c -o cbc_generic-CbcGenCtlBlk.obj `if test -f 'CbcGenCtlBlk.cpp'; then $(CYGPATH_W) 'CbcGenCtlBlk.cpp'; else $(CYGPATH_W) '$(srcdir)/CbcGenCtlBlk.cpp'; fi` -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/cbc_generic-CbcGenCtlBlk.Tpo $(DEPDIR)/cbc_generic-CbcGenCtlBlk.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='CbcGenCtlBlk.cpp' object='cbc_generic-CbcGenCtlBlk.obj' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cbc_generic_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o cbc_generic-CbcGenCtlBlk.obj `if test -f 'CbcGenCtlBlk.cpp'; then $(CYGPATH_W) 'CbcGenCtlBlk.cpp'; else $(CYGPATH_W) '$(srcdir)/CbcGenCtlBlk.cpp'; fi` - -cbc_generic-CbcGeneric.o: CbcGeneric.cpp -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cbc_generic_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT cbc_generic-CbcGeneric.o -MD -MP -MF $(DEPDIR)/cbc_generic-CbcGeneric.Tpo -c -o cbc_generic-CbcGeneric.o `test -f 'CbcGeneric.cpp' || echo '$(srcdir)/'`CbcGeneric.cpp -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/cbc_generic-CbcGeneric.Tpo $(DEPDIR)/cbc_generic-CbcGeneric.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='CbcGeneric.cpp' object='cbc_generic-CbcGeneric.o' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cbc_generic_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o cbc_generic-CbcGeneric.o `test -f 'CbcGeneric.cpp' || echo '$(srcdir)/'`CbcGeneric.cpp - -cbc_generic-CbcGeneric.obj: CbcGeneric.cpp -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cbc_generic_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT cbc_generic-CbcGeneric.obj -MD -MP -MF $(DEPDIR)/cbc_generic-CbcGeneric.Tpo -c -o cbc_generic-CbcGeneric.obj `if test -f 'CbcGeneric.cpp'; then $(CYGPATH_W) 'CbcGeneric.cpp'; else $(CYGPATH_W) '$(srcdir)/CbcGeneric.cpp'; fi` -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/cbc_generic-CbcGeneric.Tpo $(DEPDIR)/cbc_generic-CbcGeneric.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='CbcGeneric.cpp' object='cbc_generic-CbcGeneric.obj' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cbc_generic_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o cbc_generic-CbcGeneric.obj `if test -f 'CbcGeneric.cpp'; then $(CYGPATH_W) 'CbcGeneric.cpp'; else $(CYGPATH_W) '$(srcdir)/CbcGeneric.cpp'; fi` - -cbc_generic-CbcGenMessages.o: CbcGenMessages.cpp -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cbc_generic_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT cbc_generic-CbcGenMessages.o -MD -MP -MF $(DEPDIR)/cbc_generic-CbcGenMessages.Tpo -c -o cbc_generic-CbcGenMessages.o `test -f 'CbcGenMessages.cpp' || echo '$(srcdir)/'`CbcGenMessages.cpp -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/cbc_generic-CbcGenMessages.Tpo $(DEPDIR)/cbc_generic-CbcGenMessages.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='CbcGenMessages.cpp' object='cbc_generic-CbcGenMessages.o' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cbc_generic_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o cbc_generic-CbcGenMessages.o `test -f 'CbcGenMessages.cpp' || echo '$(srcdir)/'`CbcGenMessages.cpp - -cbc_generic-CbcGenMessages.obj: CbcGenMessages.cpp -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cbc_generic_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT cbc_generic-CbcGenMessages.obj -MD -MP -MF $(DEPDIR)/cbc_generic-CbcGenMessages.Tpo -c -o cbc_generic-CbcGenMessages.obj `if test -f 'CbcGenMessages.cpp'; then $(CYGPATH_W) 'CbcGenMessages.cpp'; else $(CYGPATH_W) '$(srcdir)/CbcGenMessages.cpp'; fi` -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/cbc_generic-CbcGenMessages.Tpo $(DEPDIR)/cbc_generic-CbcGenMessages.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='CbcGenMessages.cpp' object='cbc_generic-CbcGenMessages.obj' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cbc_generic_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o cbc_generic-CbcGenMessages.obj `if test -f 'CbcGenMessages.cpp'; then $(CYGPATH_W) 'CbcGenMessages.cpp'; else $(CYGPATH_W) '$(srcdir)/CbcGenMessages.cpp'; fi` - -cbc_generic-CbcGenOsiParam.o: CbcGenOsiParam.cpp -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cbc_generic_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT cbc_generic-CbcGenOsiParam.o -MD -MP -MF $(DEPDIR)/cbc_generic-CbcGenOsiParam.Tpo -c -o cbc_generic-CbcGenOsiParam.o `test -f 'CbcGenOsiParam.cpp' || echo '$(srcdir)/'`CbcGenOsiParam.cpp -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/cbc_generic-CbcGenOsiParam.Tpo $(DEPDIR)/cbc_generic-CbcGenOsiParam.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='CbcGenOsiParam.cpp' object='cbc_generic-CbcGenOsiParam.o' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cbc_generic_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o cbc_generic-CbcGenOsiParam.o `test -f 'CbcGenOsiParam.cpp' || echo '$(srcdir)/'`CbcGenOsiParam.cpp - -cbc_generic-CbcGenOsiParam.obj: CbcGenOsiParam.cpp -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cbc_generic_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT cbc_generic-CbcGenOsiParam.obj -MD -MP -MF $(DEPDIR)/cbc_generic-CbcGenOsiParam.Tpo -c -o cbc_generic-CbcGenOsiParam.obj `if test -f 'CbcGenOsiParam.cpp'; then $(CYGPATH_W) 'CbcGenOsiParam.cpp'; else $(CYGPATH_W) '$(srcdir)/CbcGenOsiParam.cpp'; fi` -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/cbc_generic-CbcGenOsiParam.Tpo $(DEPDIR)/cbc_generic-CbcGenOsiParam.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='CbcGenOsiParam.cpp' object='cbc_generic-CbcGenOsiParam.obj' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cbc_generic_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o cbc_generic-CbcGenOsiParam.obj `if test -f 'CbcGenOsiParam.cpp'; then $(CYGPATH_W) 'CbcGenOsiParam.cpp'; else $(CYGPATH_W) '$(srcdir)/CbcGenOsiParam.cpp'; fi` - -cbc_generic-CbcGenOsiParamUtils.o: CbcGenOsiParamUtils.cpp -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cbc_generic_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT cbc_generic-CbcGenOsiParamUtils.o -MD -MP -MF $(DEPDIR)/cbc_generic-CbcGenOsiParamUtils.Tpo -c -o cbc_generic-CbcGenOsiParamUtils.o `test -f 'CbcGenOsiParamUtils.cpp' || echo '$(srcdir)/'`CbcGenOsiParamUtils.cpp -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/cbc_generic-CbcGenOsiParamUtils.Tpo $(DEPDIR)/cbc_generic-CbcGenOsiParamUtils.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='CbcGenOsiParamUtils.cpp' object='cbc_generic-CbcGenOsiParamUtils.o' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cbc_generic_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o cbc_generic-CbcGenOsiParamUtils.o `test -f 'CbcGenOsiParamUtils.cpp' || echo '$(srcdir)/'`CbcGenOsiParamUtils.cpp - -cbc_generic-CbcGenOsiParamUtils.obj: CbcGenOsiParamUtils.cpp -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cbc_generic_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT cbc_generic-CbcGenOsiParamUtils.obj -MD -MP -MF $(DEPDIR)/cbc_generic-CbcGenOsiParamUtils.Tpo -c -o cbc_generic-CbcGenOsiParamUtils.obj `if test -f 'CbcGenOsiParamUtils.cpp'; then $(CYGPATH_W) 'CbcGenOsiParamUtils.cpp'; else $(CYGPATH_W) '$(srcdir)/CbcGenOsiParamUtils.cpp'; fi` -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/cbc_generic-CbcGenOsiParamUtils.Tpo $(DEPDIR)/cbc_generic-CbcGenOsiParamUtils.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='CbcGenOsiParamUtils.cpp' object='cbc_generic-CbcGenOsiParamUtils.obj' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cbc_generic_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o cbc_generic-CbcGenOsiParamUtils.obj `if test -f 'CbcGenOsiParamUtils.cpp'; then $(CYGPATH_W) 'CbcGenOsiParamUtils.cpp'; else $(CYGPATH_W) '$(srcdir)/CbcGenOsiParamUtils.cpp'; fi` - -cbc_generic-CbcGenParam.o: CbcGenParam.cpp -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cbc_generic_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT cbc_generic-CbcGenParam.o -MD -MP -MF $(DEPDIR)/cbc_generic-CbcGenParam.Tpo -c -o cbc_generic-CbcGenParam.o `test -f 'CbcGenParam.cpp' || echo '$(srcdir)/'`CbcGenParam.cpp -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/cbc_generic-CbcGenParam.Tpo $(DEPDIR)/cbc_generic-CbcGenParam.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='CbcGenParam.cpp' object='cbc_generic-CbcGenParam.o' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cbc_generic_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o cbc_generic-CbcGenParam.o `test -f 'CbcGenParam.cpp' || echo '$(srcdir)/'`CbcGenParam.cpp - -cbc_generic-CbcGenParam.obj: CbcGenParam.cpp -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cbc_generic_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT cbc_generic-CbcGenParam.obj -MD -MP -MF $(DEPDIR)/cbc_generic-CbcGenParam.Tpo -c -o cbc_generic-CbcGenParam.obj `if test -f 'CbcGenParam.cpp'; then $(CYGPATH_W) 'CbcGenParam.cpp'; else $(CYGPATH_W) '$(srcdir)/CbcGenParam.cpp'; fi` -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/cbc_generic-CbcGenParam.Tpo $(DEPDIR)/cbc_generic-CbcGenParam.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='CbcGenParam.cpp' object='cbc_generic-CbcGenParam.obj' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cbc_generic_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o cbc_generic-CbcGenParam.obj `if test -f 'CbcGenParam.cpp'; then $(CYGPATH_W) 'CbcGenParam.cpp'; else $(CYGPATH_W) '$(srcdir)/CbcGenParam.cpp'; fi` - -cbc_generic-CbcGenParamUtils.o: CbcGenParamUtils.cpp -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cbc_generic_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT cbc_generic-CbcGenParamUtils.o -MD -MP -MF $(DEPDIR)/cbc_generic-CbcGenParamUtils.Tpo -c -o cbc_generic-CbcGenParamUtils.o `test -f 'CbcGenParamUtils.cpp' || echo '$(srcdir)/'`CbcGenParamUtils.cpp -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/cbc_generic-CbcGenParamUtils.Tpo $(DEPDIR)/cbc_generic-CbcGenParamUtils.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='CbcGenParamUtils.cpp' object='cbc_generic-CbcGenParamUtils.o' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cbc_generic_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o cbc_generic-CbcGenParamUtils.o `test -f 'CbcGenParamUtils.cpp' || echo '$(srcdir)/'`CbcGenParamUtils.cpp - -cbc_generic-CbcGenParamUtils.obj: CbcGenParamUtils.cpp -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cbc_generic_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT cbc_generic-CbcGenParamUtils.obj -MD -MP -MF $(DEPDIR)/cbc_generic-CbcGenParamUtils.Tpo -c -o cbc_generic-CbcGenParamUtils.obj `if test -f 'CbcGenParamUtils.cpp'; then $(CYGPATH_W) 'CbcGenParamUtils.cpp'; else $(CYGPATH_W) '$(srcdir)/CbcGenParamUtils.cpp'; fi` -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/cbc_generic-CbcGenParamUtils.Tpo $(DEPDIR)/cbc_generic-CbcGenParamUtils.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='CbcGenParamUtils.cpp' object='cbc_generic-CbcGenParamUtils.obj' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cbc_generic_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o cbc_generic-CbcGenParamUtils.obj `if test -f 'CbcGenParamUtils.cpp'; then $(CYGPATH_W) 'CbcGenParamUtils.cpp'; else $(CYGPATH_W) '$(srcdir)/CbcGenParamUtils.cpp'; fi` - -cbc_generic-CbcGenSolution.o: CbcGenSolution.cpp -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cbc_generic_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT cbc_generic-CbcGenSolution.o -MD -MP -MF $(DEPDIR)/cbc_generic-CbcGenSolution.Tpo -c -o cbc_generic-CbcGenSolution.o `test -f 'CbcGenSolution.cpp' || echo '$(srcdir)/'`CbcGenSolution.cpp -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/cbc_generic-CbcGenSolution.Tpo $(DEPDIR)/cbc_generic-CbcGenSolution.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='CbcGenSolution.cpp' object='cbc_generic-CbcGenSolution.o' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cbc_generic_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o cbc_generic-CbcGenSolution.o `test -f 'CbcGenSolution.cpp' || echo '$(srcdir)/'`CbcGenSolution.cpp - -cbc_generic-CbcGenSolution.obj: CbcGenSolution.cpp -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cbc_generic_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT cbc_generic-CbcGenSolution.obj -MD -MP -MF $(DEPDIR)/cbc_generic-CbcGenSolution.Tpo -c -o cbc_generic-CbcGenSolution.obj `if test -f 'CbcGenSolution.cpp'; then $(CYGPATH_W) 'CbcGenSolution.cpp'; else $(CYGPATH_W) '$(srcdir)/CbcGenSolution.cpp'; fi` -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/cbc_generic-CbcGenSolution.Tpo $(DEPDIR)/cbc_generic-CbcGenSolution.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='CbcGenSolution.cpp' object='cbc_generic-CbcGenSolution.obj' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cbc_generic_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o cbc_generic-CbcGenSolution.obj `if test -f 'CbcGenSolution.cpp'; then $(CYGPATH_W) 'CbcGenSolution.cpp'; else $(CYGPATH_W) '$(srcdir)/CbcGenSolution.cpp'; fi` - -cbc_generic-CbcGenSolvers.o: CbcGenSolvers.cpp -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cbc_generic_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT cbc_generic-CbcGenSolvers.o -MD -MP -MF $(DEPDIR)/cbc_generic-CbcGenSolvers.Tpo -c -o cbc_generic-CbcGenSolvers.o `test -f 'CbcGenSolvers.cpp' || echo '$(srcdir)/'`CbcGenSolvers.cpp -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/cbc_generic-CbcGenSolvers.Tpo $(DEPDIR)/cbc_generic-CbcGenSolvers.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='CbcGenSolvers.cpp' object='cbc_generic-CbcGenSolvers.o' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cbc_generic_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o cbc_generic-CbcGenSolvers.o `test -f 'CbcGenSolvers.cpp' || echo '$(srcdir)/'`CbcGenSolvers.cpp - -cbc_generic-CbcGenSolvers.obj: CbcGenSolvers.cpp -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cbc_generic_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT cbc_generic-CbcGenSolvers.obj -MD -MP -MF $(DEPDIR)/cbc_generic-CbcGenSolvers.Tpo -c -o cbc_generic-CbcGenSolvers.obj `if test -f 'CbcGenSolvers.cpp'; then $(CYGPATH_W) 'CbcGenSolvers.cpp'; else $(CYGPATH_W) '$(srcdir)/CbcGenSolvers.cpp'; fi` -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/cbc_generic-CbcGenSolvers.Tpo $(DEPDIR)/cbc_generic-CbcGenSolvers.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='CbcGenSolvers.cpp' object='cbc_generic-CbcGenSolvers.obj' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cbc_generic_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o cbc_generic-CbcGenSolvers.obj `if test -f 'CbcGenSolvers.cpp'; then $(CYGPATH_W) 'CbcGenSolvers.cpp'; else $(CYGPATH_W) '$(srcdir)/CbcGenSolvers.cpp'; fi` - mostlyclean-libtool: -rm -f *.lo @@ -1852,7 +1642,7 @@ distclean-tags: check-am: all-am check: check-am all-am: Makefile $(PROGRAMS) $(LTLIBRARIES) $(HEADERS) config.h \ - config_cbc.h config_cbcsolver.h + config_cbc.h install-binPROGRAMS: install-libLTLIBRARIES installdirs: @@ -1896,28 +1686,7 @@ clean-am: clean-binPROGRAMS clean-generic clean-libLTLIBRARIES \ distclean: distclean-am -rm -f ./$(DEPDIR)/cbc-CoinSolve.Po - -rm -f ./$(DEPDIR)/cbc_generic-CbcGenBaB.Po - -rm -f ./$(DEPDIR)/cbc_generic-CbcGenCbcParam.Po - -rm -f ./$(DEPDIR)/cbc_generic-CbcGenCbcParamUtils.Po - -rm -f ./$(DEPDIR)/cbc_generic-CbcGenCtlBlk.Po - -rm -f ./$(DEPDIR)/cbc_generic-CbcGenMessages.Po - -rm -f ./$(DEPDIR)/cbc_generic-CbcGenOsiParam.Po - -rm -f ./$(DEPDIR)/cbc_generic-CbcGenOsiParamUtils.Po - -rm -f ./$(DEPDIR)/cbc_generic-CbcGenParam.Po - -rm -f ./$(DEPDIR)/cbc_generic-CbcGenParamUtils.Po - -rm -f ./$(DEPDIR)/cbc_generic-CbcGenSolution.Po - -rm -f ./$(DEPDIR)/cbc_generic-CbcGenSolvers.Po - -rm -f ./$(DEPDIR)/cbc_generic-CbcGeneric.Po - -rm -f ./$(DEPDIR)/libCbcSolver_la-CbcCbcParam.Plo - -rm -f ./$(DEPDIR)/libCbcSolver_la-CbcLinked.Plo - -rm -f ./$(DEPDIR)/libCbcSolver_la-CbcLinkedUtils.Plo - -rm -f ./$(DEPDIR)/libCbcSolver_la-CbcMipStartIO.Plo - -rm -f ./$(DEPDIR)/libCbcSolver_la-CbcSolver.Plo - -rm -f ./$(DEPDIR)/libCbcSolver_la-CbcSolverAnalyze.Plo - -rm -f ./$(DEPDIR)/libCbcSolver_la-CbcSolverExpandKnapsack.Plo - -rm -f ./$(DEPDIR)/libCbcSolver_la-CbcSolverHeuristics.Plo - -rm -f ./$(DEPDIR)/libCbcSolver_la-Cbc_C_Interface.Plo - -rm -f ./$(DEPDIR)/libCbcSolver_la-unitTestClp.Plo + -rm -f ./$(DEPDIR)/libCbc_la-CbcBab.Plo -rm -f ./$(DEPDIR)/libCbc_la-CbcBranchAllDifferent.Plo -rm -f ./$(DEPDIR)/libCbc_la-CbcBranchCut.Plo -rm -f ./$(DEPDIR)/libCbc_la-CbcBranchDecision.Plo @@ -1963,18 +1732,30 @@ distclean: distclean-am -rm -f ./$(DEPDIR)/libCbc_la-CbcHeuristicRINS.Plo -rm -f ./$(DEPDIR)/libCbc_la-CbcHeuristicRandRound.Plo -rm -f ./$(DEPDIR)/libCbc_la-CbcHeuristicVND.Plo + -rm -f ./$(DEPDIR)/libCbc_la-CbcLinked.Plo + -rm -f ./$(DEPDIR)/libCbc_la-CbcLinkedUtils.Plo -rm -f ./$(DEPDIR)/libCbc_la-CbcMessage.Plo + -rm -f ./$(DEPDIR)/libCbc_la-CbcMipStartIO.Plo -rm -f ./$(DEPDIR)/libCbc_la-CbcModel.Plo -rm -f ./$(DEPDIR)/libCbc_la-CbcNWay.Plo -rm -f ./$(DEPDIR)/libCbc_la-CbcNode.Plo -rm -f ./$(DEPDIR)/libCbc_la-CbcNodeInfo.Plo -rm -f ./$(DEPDIR)/libCbc_la-CbcObject.Plo -rm -f ./$(DEPDIR)/libCbc_la-CbcObjectUpdateData.Plo + -rm -f ./$(DEPDIR)/libCbc_la-CbcParam.Plo + -rm -f ./$(DEPDIR)/libCbc_la-CbcParamUtils.Plo + -rm -f ./$(DEPDIR)/libCbc_la-CbcCbcParam.Plo + -rm -f ./$(DEPDIR)/libCbc_la-CbcParameters.Plo -rm -f ./$(DEPDIR)/libCbc_la-CbcPartialNodeInfo.Plo -rm -f ./$(DEPDIR)/libCbc_la-CbcSOS.Plo -rm -f ./$(DEPDIR)/libCbc_la-CbcSimpleInteger.Plo -rm -f ./$(DEPDIR)/libCbc_la-CbcSimpleIntegerDynamicPseudoCost.Plo -rm -f ./$(DEPDIR)/libCbc_la-CbcSimpleIntegerPseudoCost.Plo + -rm -f ./$(DEPDIR)/libCbc_la-CbcSolution.Plo + -rm -f ./$(DEPDIR)/libCbc_la-CbcSolver.Plo + -rm -f ./$(DEPDIR)/libCbc_la-CbcSolverAnalyze.Plo + -rm -f ./$(DEPDIR)/libCbc_la-CbcSolverExpandKnapsack.Plo + -rm -f ./$(DEPDIR)/libCbc_la-CbcSolverHeuristics.Plo -rm -f ./$(DEPDIR)/libCbc_la-CbcStatistics.Plo -rm -f ./$(DEPDIR)/libCbc_la-CbcStrategy.Plo -rm -f ./$(DEPDIR)/libCbc_la-CbcSubProblem.Plo @@ -1982,6 +1763,8 @@ distclean: distclean-am -rm -f ./$(DEPDIR)/libCbc_la-CbcThread.Plo -rm -f ./$(DEPDIR)/libCbc_la-CbcTree.Plo -rm -f ./$(DEPDIR)/libCbc_la-CbcTreeLocal.Plo + -rm -f ./$(DEPDIR)/libCbc_la-Cbc_C_Interface.Plo + -rm -f ./$(DEPDIR)/libCbc_la-unitTestClp.Plo -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-hdr distclean-tags @@ -2029,28 +1812,7 @@ installcheck-am: maintainer-clean: maintainer-clean-am -rm -f ./$(DEPDIR)/cbc-CoinSolve.Po - -rm -f ./$(DEPDIR)/cbc_generic-CbcGenBaB.Po - -rm -f ./$(DEPDIR)/cbc_generic-CbcGenCbcParam.Po - -rm -f ./$(DEPDIR)/cbc_generic-CbcGenCbcParamUtils.Po - -rm -f ./$(DEPDIR)/cbc_generic-CbcGenCtlBlk.Po - -rm -f ./$(DEPDIR)/cbc_generic-CbcGenMessages.Po - -rm -f ./$(DEPDIR)/cbc_generic-CbcGenOsiParam.Po - -rm -f ./$(DEPDIR)/cbc_generic-CbcGenOsiParamUtils.Po - -rm -f ./$(DEPDIR)/cbc_generic-CbcGenParam.Po - -rm -f ./$(DEPDIR)/cbc_generic-CbcGenParamUtils.Po - -rm -f ./$(DEPDIR)/cbc_generic-CbcGenSolution.Po - -rm -f ./$(DEPDIR)/cbc_generic-CbcGenSolvers.Po - -rm -f ./$(DEPDIR)/cbc_generic-CbcGeneric.Po - -rm -f ./$(DEPDIR)/libCbcSolver_la-CbcCbcParam.Plo - -rm -f ./$(DEPDIR)/libCbcSolver_la-CbcLinked.Plo - -rm -f ./$(DEPDIR)/libCbcSolver_la-CbcLinkedUtils.Plo - -rm -f ./$(DEPDIR)/libCbcSolver_la-CbcMipStartIO.Plo - -rm -f ./$(DEPDIR)/libCbcSolver_la-CbcSolver.Plo - -rm -f ./$(DEPDIR)/libCbcSolver_la-CbcSolverAnalyze.Plo - -rm -f ./$(DEPDIR)/libCbcSolver_la-CbcSolverExpandKnapsack.Plo - -rm -f ./$(DEPDIR)/libCbcSolver_la-CbcSolverHeuristics.Plo - -rm -f ./$(DEPDIR)/libCbcSolver_la-Cbc_C_Interface.Plo - -rm -f ./$(DEPDIR)/libCbcSolver_la-unitTestClp.Plo + -rm -f ./$(DEPDIR)/libCbc_la-CbcBab.Plo -rm -f ./$(DEPDIR)/libCbc_la-CbcBranchAllDifferent.Plo -rm -f ./$(DEPDIR)/libCbc_la-CbcBranchCut.Plo -rm -f ./$(DEPDIR)/libCbc_la-CbcBranchDecision.Plo @@ -2096,18 +1858,30 @@ maintainer-clean: maintainer-clean-am -rm -f ./$(DEPDIR)/libCbc_la-CbcHeuristicRINS.Plo -rm -f ./$(DEPDIR)/libCbc_la-CbcHeuristicRandRound.Plo -rm -f ./$(DEPDIR)/libCbc_la-CbcHeuristicVND.Plo + -rm -f ./$(DEPDIR)/libCbc_la-CbcLinked.Plo + -rm -f ./$(DEPDIR)/libCbc_la-CbcLinkedUtils.Plo -rm -f ./$(DEPDIR)/libCbc_la-CbcMessage.Plo + -rm -f ./$(DEPDIR)/libCbc_la-CbcMipStartIO.Plo -rm -f ./$(DEPDIR)/libCbc_la-CbcModel.Plo -rm -f ./$(DEPDIR)/libCbc_la-CbcNWay.Plo -rm -f ./$(DEPDIR)/libCbc_la-CbcNode.Plo -rm -f ./$(DEPDIR)/libCbc_la-CbcNodeInfo.Plo -rm -f ./$(DEPDIR)/libCbc_la-CbcObject.Plo -rm -f ./$(DEPDIR)/libCbc_la-CbcObjectUpdateData.Plo + -rm -f ./$(DEPDIR)/libCbc_la-CbcParam.Plo + -rm -f ./$(DEPDIR)/libCbc_la-CbcParamUtils.Plo + -rm -f ./$(DEPDIR)/libCbc_la-CbcCbcParam.Plo + -rm -f ./$(DEPDIR)/libCbc_la-CbcParameters.Plo -rm -f ./$(DEPDIR)/libCbc_la-CbcPartialNodeInfo.Plo -rm -f ./$(DEPDIR)/libCbc_la-CbcSOS.Plo -rm -f ./$(DEPDIR)/libCbc_la-CbcSimpleInteger.Plo -rm -f ./$(DEPDIR)/libCbc_la-CbcSimpleIntegerDynamicPseudoCost.Plo -rm -f ./$(DEPDIR)/libCbc_la-CbcSimpleIntegerPseudoCost.Plo + -rm -f ./$(DEPDIR)/libCbc_la-CbcSolution.Plo + -rm -f ./$(DEPDIR)/libCbc_la-CbcSolver.Plo + -rm -f ./$(DEPDIR)/libCbc_la-CbcSolverAnalyze.Plo + -rm -f ./$(DEPDIR)/libCbc_la-CbcSolverExpandKnapsack.Plo + -rm -f ./$(DEPDIR)/libCbc_la-CbcSolverHeuristics.Plo -rm -f ./$(DEPDIR)/libCbc_la-CbcStatistics.Plo -rm -f ./$(DEPDIR)/libCbc_la-CbcStrategy.Plo -rm -f ./$(DEPDIR)/libCbc_la-CbcSubProblem.Plo @@ -2115,6 +1889,8 @@ maintainer-clean: maintainer-clean-am -rm -f ./$(DEPDIR)/libCbc_la-CbcThread.Plo -rm -f ./$(DEPDIR)/libCbc_la-CbcTree.Plo -rm -f ./$(DEPDIR)/libCbc_la-CbcTreeLocal.Plo + -rm -f ./$(DEPDIR)/libCbc_la-Cbc_C_Interface.Plo + -rm -f ./$(DEPDIR)/libCbc_la-unitTestClp.Plo -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic @@ -2163,7 +1939,6 @@ uninstall-am: uninstall-binPROGRAMS uninstall-includecoinHEADERS \ install-exec-local: $(install_sh_DATA) config_cbc.h $(DESTDIR)$(includecoindir)/CbcConfig.h - $(install_sh_DATA) config_cbcsolver.h $(DESTDIR)$(includecoindir)/CbcSolverConfig.h uninstall-local: rm -f $(DESTDIR)$(includecoindir)/CbcConfig.h $(DESTDIR)$(includecoindir)/CbcSolverConfig.h diff --git a/src/OsiCbc/Makefile.in b/src/OsiCbc/Makefile.in index e363335f2..59629bfa7 100644 --- a/src/OsiCbc/Makefile.in +++ b/src/OsiCbc/Makefile.in @@ -120,8 +120,7 @@ am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ DIST_COMMON = $(srcdir)/Makefile.am $(includecoin_HEADERS) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/src/config.h \ - $(top_builddir)/src/config_cbc.h \ - $(top_builddir)/src/config_cbcsolver.h config_osicbc.h + $(top_builddir)/src/config_cbc.h config_osicbc.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; @@ -268,11 +267,8 @@ CBCLIB_CFLAGS_NOPC = @CBCLIB_CFLAGS_NOPC@ CBCLIB_LFLAGS = @CBCLIB_LFLAGS@ CBCLIB_LFLAGS_NOPC = @CBCLIB_LFLAGS_NOPC@ CBCLIB_PCFILES = @CBCLIB_PCFILES@ -CBCSOLVERLIB_CFLAGS = @CBCSOLVERLIB_CFLAGS@ CBCSOLVERLIB_CFLAGS_NOPC = @CBCSOLVERLIB_CFLAGS_NOPC@ -CBCSOLVERLIB_LFLAGS = @CBCSOLVERLIB_LFLAGS@ CBCSOLVERLIB_LFLAGS_NOPC = @CBCSOLVERLIB_LFLAGS_NOPC@ -CBCSOLVERLIB_PCFILES = @CBCSOLVERLIB_PCFILES@ CBCUNITTEST_CFLAGS = @CBCUNITTEST_CFLAGS@ CBCUNITTEST_CFLAGS_NOPC = @CBCUNITTEST_CFLAGS_NOPC@ CBCUNITTEST_LFLAGS = @CBCUNITTEST_LFLAGS@ @@ -474,16 +470,16 @@ $(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): -config_osicbc.h: stamp-h4 - @test -f $@ || rm -f stamp-h4 - @test -f $@ || $(MAKE) $(AM_MAKEFLAGS) stamp-h4 +config_osicbc.h: stamp-h3 + @test -f $@ || rm -f stamp-h3 + @test -f $@ || $(MAKE) $(AM_MAKEFLAGS) stamp-h3 -stamp-h4: $(srcdir)/config_osicbc.h.in $(top_builddir)/config.status - @rm -f stamp-h4 +stamp-h3: $(srcdir)/config_osicbc.h.in $(top_builddir)/config.status + @rm -f stamp-h3 cd $(top_builddir) && $(SHELL) ./config.status src/OsiCbc/config_osicbc.h distclean-hdr: - -rm -f config_osicbc.h stamp-h4 + -rm -f config_osicbc.h stamp-h3 install-libLTLIBRARIES: $(lib_LTLIBRARIES) @$(NORMAL_INSTALL) diff --git a/src/config.h.in b/src/config.h.in index 3eff9a39a..d2000428c 100644 --- a/src/config.h.in +++ b/src/config.h.in @@ -31,9 +31,6 @@ /* Define to 1 if the Cplex package is available */ #undef CBC_HAS_CPLEX -/* Define to 1 if Glpk is available. */ -#undef CBC_HAS_GLPK - /* Define to 1 if Miplib3 is available. */ #undef CBC_HAS_MIPLIB3 diff --git a/src/config_cbcsolver.h.in b/src/config_cbcsolver.h.in deleted file mode 100644 index 36d311cb3..000000000 --- a/src/config_cbcsolver.h.in +++ /dev/null @@ -1,9 +0,0 @@ -/* src/config_cbcsolver.h.in. */ - -#ifndef __CONFIG_CBCSOLVER_H__ -#define __CONFIG_CBCSOLVER_H__ - -/* Library Visibility Attribute */ -#undef CBCSOLVERLIB_EXPORT - -#endif diff --git a/src/config_default.h b/src/config_default.h index 2f68ad9a4..55ad79a70 100644 --- a/src/config_default.h +++ b/src/config_default.h @@ -43,9 +43,6 @@ /* Define to 1 if the Dylp package is used */ /* #undef COIN_HAS_DYLP */ -/* Define to 1 if the Glpk package is used */ -/* #undef CBC_HAS_GLPK */ - /* Define to 1 if the Mosek package is used */ /* #undef COIN_HAS_MSK */ diff --git a/src/unitTestClp.cpp b/src/unitTestClp.cpp index f63fd7e26..2132c4f53 100644 --- a/src/unitTestClp.cpp +++ b/src/unitTestClp.cpp @@ -7,6 +7,7 @@ #include #include #include +#include #include "CoinTime.hpp" #include "CoinFileIO.hpp" @@ -126,10 +127,10 @@ bool CbcTestMpsFile(std::string &fname) 100*(number with bad objective)+(number that exceeded node limit) */ int CbcClpUnitTest(const CbcModel &saveModel, const std::string &dirMiplibIn, - int testSwitch, const double *stuff, int argc, - const char ** argv, + int testSwitch, const double *stuff, + std::deque originalInputQueue, int callBack(CbcModel *currentSolver, int whereFrom), - CbcSolverUsefulData ¶meterData) + CbcParameters ¶meters) { // Stop Windows popup WindowsErrorPopupBlocker(); @@ -525,6 +526,23 @@ int CbcClpUnitTest(const CbcModel &saveModel, const std::string &dirMiplibIn, int numberAttempts = 0; int numProbSolved = 0; double timeTaken = 0.0; + // tidy original input queue + std::deque inputQueue = originalInputQueue; + { + // take off first two parameters of initial queue + inputQueue.pop_front(); + inputQueue.pop_front(); + // take off unitTest + std::string unitTest = inputQueue.back(); + std::string check="-unitTest"; + size_t i; + for (i = 0; i < unitTest.size(); i++) { + if (tolower(unitTest[i]) != tolower(check[i])) + break; + } + assert (i == unitTest.size()); + inputQueue.pop_back(); + } //#define CLP_FACTORIZATION_INSTRUMENT #ifdef CLP_FACTORIZATION_INSTRUMENT @@ -562,46 +580,48 @@ int CbcClpUnitTest(const CbcModel &saveModel, const std::string &dirMiplibIn, model->solver()->readMps(fn.c_str(), ""); } else { OsiClpSolverInterface solver1; - const char * newArgv[200]; + std::deque newInputQueue; char replace[100]; - int newArgc = 2; - newArgv[0] = "unitTestCbc"; - newArgv[1] = fn.c_str(); - for (int i = 3;i < argc-1; i++) { - if (!strstr(argv[i],"++")) { - if (testSwitch >=1000000) { - // take out dextra3 - if (strstr(argv[i],"dextra3")) { - i++; - continue; - } - } - newArgv[newArgc++] = argv[i]; + //newArgv[0] = "unitTestCbc"; + newInputQueue.push_back(fn); + for (int i = 0; i < inputQueue.size(); i++) { + if (inputQueue[i] != "++") { + if (testSwitch >=1000000) { + // take out dextra3 + if (inputQueue[i] == "dextra3") { + continue; + } + } + newInputQueue.push_back(inputQueue[i]); } else { - int n = strstr(argv[i],"++")-argv[i]; - strncpy(replace,argv[i],n); + //FIXME: This should be changed to use modern C++ + int n = strstr(inputQueue[i].c_str(), "++") - inputQueue[i].c_str(); + strncpy(replace, inputQueue[i].c_str(), n); const char * mipname = mpsName[m].c_str(); int n1 = n; - for (int j=0;jgetNumRows() != nRows[m] || model->getNumCols() != nCols[m]) && model->getNumRows()) diff --git a/test/Makefile.am b/test/Makefile.am index fb229405d..5534bd284 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -59,7 +59,7 @@ gamstests: gamsTest$(EXEEXT) bin_PROGRAMS = gamsTest osiUnitTest CInterfaceTest gamsTest_SOURCES = gamsTest.cpp -gamsTest_LDADD = ../src/libCbcSolver.la ../src/libCbc.la +gamsTest_LDADD = ../src/libCbc.la ######################################################################## # unitTest for OsiCbc # @@ -79,7 +79,7 @@ ositests: osiUnitTest$(EXEEXT) CInterfaceTest_SOURCES = CInterfaceTest.c nodist_EXTRA_CInterfaceTest_SOURCES = dummy.cpp # force using C++ linker -CInterfaceTest_LDADD = ../src/libCbcSolver.la ../src/libCbc.la +CInterfaceTest_LDADD = ../src/libCbc.la ctests: CInterfaceTest$(EXEEXT) export RUNNING_TEST="CInterfaceTest" ; ./CInterfaceTest$(EXEEXT) $(MIPLIB3_DATA) $(SAMPLE_DATA) diff --git a/test/Makefile.in b/test/Makefile.in index 125409dac..048986f87 100644 --- a/test/Makefile.in +++ b/test/Makefile.in @@ -112,7 +112,6 @@ DIST_COMMON = $(srcdir)/Makefile.am mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/src/config.h \ $(top_builddir)/src/config_cbc.h \ - $(top_builddir)/src/config_cbcsolver.h \ $(top_builddir)/src/OsiCbc/config_osicbc.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = @@ -120,14 +119,14 @@ am__installdirs = "$(DESTDIR)$(bindir)" PROGRAMS = $(bin_PROGRAMS) am_CInterfaceTest_OBJECTS = CInterfaceTest.$(OBJEXT) CInterfaceTest_OBJECTS = $(am_CInterfaceTest_OBJECTS) -CInterfaceTest_DEPENDENCIES = ../src/libCbcSolver.la ../src/libCbc.la +CInterfaceTest_DEPENDENCIES = ../src/libCbc.la AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = am_gamsTest_OBJECTS = gamsTest.$(OBJEXT) gamsTest_OBJECTS = $(am_gamsTest_OBJECTS) -gamsTest_DEPENDENCIES = ../src/libCbcSolver.la ../src/libCbc.la +gamsTest_DEPENDENCIES = ../src/libCbc.la am_osiUnitTest_OBJECTS = osiUnitTest.$(OBJEXT) \ OsiCbcSolverInterfaceTest.$(OBJEXT) osiUnitTest_OBJECTS = $(am_osiUnitTest_OBJECTS) @@ -237,11 +236,8 @@ CBCLIB_CFLAGS_NOPC = @CBCLIB_CFLAGS_NOPC@ CBCLIB_LFLAGS = @CBCLIB_LFLAGS@ CBCLIB_LFLAGS_NOPC = @CBCLIB_LFLAGS_NOPC@ CBCLIB_PCFILES = @CBCLIB_PCFILES@ -CBCSOLVERLIB_CFLAGS = @CBCSOLVERLIB_CFLAGS@ CBCSOLVERLIB_CFLAGS_NOPC = @CBCSOLVERLIB_CFLAGS_NOPC@ -CBCSOLVERLIB_LFLAGS = @CBCSOLVERLIB_LFLAGS@ CBCSOLVERLIB_LFLAGS_NOPC = @CBCSOLVERLIB_LFLAGS_NOPC@ -CBCSOLVERLIB_PCFILES = @CBCSOLVERLIB_PCFILES@ CBCUNITTEST_CFLAGS = @CBCUNITTEST_CFLAGS@ CBCUNITTEST_CFLAGS_NOPC = @CBCUNITTEST_CFLAGS_NOPC@ CBCUNITTEST_LFLAGS = @CBCUNITTEST_LFLAGS@ @@ -389,7 +385,7 @@ CBC_TEST_TGTS = gamstests ositests $(am__append_1) $(am__append_2) cbcflags = $(am__append_4) ositestsflags = $(am__append_3) $(am__append_5) gamsTest_SOURCES = gamsTest.cpp -gamsTest_LDADD = ../src/libCbcSolver.la ../src/libCbc.la +gamsTest_LDADD = ../src/libCbc.la ######################################################################## # unitTest for OsiCbc # @@ -402,7 +398,7 @@ osiUnitTest_LDADD = ../src/OsiCbc/libOsiCbc.la ../src/libCbc.la $(CBCUNITTEST_LF ######################################################################## CInterfaceTest_SOURCES = CInterfaceTest.c nodist_EXTRA_CInterfaceTest_SOURCES = dummy.cpp # force using C++ linker -CInterfaceTest_LDADD = ../src/libCbcSolver.la ../src/libCbc.la +CInterfaceTest_LDADD = ../src/libCbc.la all: all-am .SUFFIXES: diff --git a/test/gamsTest.cpp b/test/gamsTest.cpp index d60b85d3b..e652aef3f 100644 --- a/test/gamsTest.cpp +++ b/test/gamsTest.cpp @@ -96,17 +96,20 @@ void sos1a(int &error_count, int &warning_count) solver1.loadProblem(numcols, numrows, start, index, value, collb, colub, obj, rowlb, rowub); solver1.setObjSense(-1); - CbcSolverUsefulData data; + CbcParameters parameters; CbcModel model(solver1); - CbcMain0(model, data); + CbcMain0(model, parameters); int which[3] = { 0, 1, 2 }; CbcObject *sosobject = new CbcSOS(&model, 3, which, NULL, 0, 1); model.addObjects(1, &sosobject); delete sosobject; - const char *argv2[] = { "gamstest_sos1a", "-solve", "-quit" }; - CbcMain1(3, argv2, model, NULL, data); + std::deque inputQueue; + inputQueue.push_back("-solve"); + inputQueue.push_back("-quit"); + + CbcMain1(inputQueue, model, parameters); cout << endl; if (!model.isProvenOptimal()) { cerr << "Error: Model sos1a not solved to optimality." << endl; @@ -293,15 +296,19 @@ void sos2a(int &error_count, int &warning_count) break; } CbcModel model(solver1); - CbcSolverUsefulData data; - CbcMain0(model, data); + CbcParameters parameters; + CbcMain0(model, parameters); int which[3] = { 0, 1, 2 }; CbcObject *sosobject = new CbcSOS(&model, 3, which, NULL, 0, 2); model.addObjects(1, &sosobject); delete sosobject; const char *argv2[] = { "gamstest_sos2a", "-solve", "-quit" }; cout << "\nSolving sos2a model with last row having lhs " << solver1.getRowLower()[5] << endl; - CbcMain1(3, argv2, model, data); + std::deque inputQueue; + inputQueue.push_back("-solve"); + inputQueue.push_back("-quit"); + + CbcMain1(inputQueue, model, parameters); cout << endl; if (!model.isProvenOptimal()) { cerr << "Error: Model sos2a not solved to optimality." << endl; @@ -408,8 +415,8 @@ void semicon1(int &error_count, int &warning_count) solver1.loadProblem(numcols, numrows, start, index, value, collb, colub, obj, rowlb, rowub); for (int testcase = 0; testcase < 5; ++testcase) { CbcModel model(solver1); - CbcSolverUsefulData data; - CbcMain0(model, data); + CbcParameters parameters; + CbcMain0(model, parameters); double points[4] = { 0., 0., 0., 10. }; double objval; @@ -482,8 +489,11 @@ void semicon1(int &error_count, int &warning_count) cout << "\nSolving semicon1 model for lotsize variable being either 0 or between " << points[2] << " and 10.\n" << endl; - const char *argv2[] = { "gamstest_semicon1", "-solve", "-quit" }; - CbcMain1(3, argv2, model, NULL, data); + std::deque inputQueue; + inputQueue.push_back("-solve"); + inputQueue.push_back("-quit"); + + CbcMain1(inputQueue, model, parameters); cout << endl; if (!model.isProvenOptimal()) { cerr << "Error: Model semicon1 not solved to optimality." << endl; @@ -619,8 +629,8 @@ void semiint1(int &error_count, int &warning_count) for (int testcase = 0; testcase < 6; ++testcase) { CbcModel model(solver1); - CbcSolverUsefulData data; - CbcMain0(model, data); + CbcParameters parameters; + CbcMain0(model, parameters); double points[10]; points[0] = 0.; @@ -714,10 +724,13 @@ void semiint1(int &error_count, int &warning_count) delete semiintobject; } - cout << "\nSolving semiint1 model for integer lotsize variable being either 0 or between " << points[2] << " and 10.\n" + cout << "\nSolving semiint1 model for testcase " << testcase << ".\n" << endl; - const char *argv2[] = { "gamstest_semiint1", "-solve", "-quit" }; - CbcMain1(3, argv2, model, NULL, data); + std::deque inputQueue; + inputQueue.push_back("-solve"); + inputQueue.push_back("-quit"); + + CbcMain1(inputQueue, model, parameters); cout << endl; if (!model.isProvenOptimal()) { cerr << "Error: Model semiint1 not solved to optimality." << endl;