00001
00002
00003
00004 #include "CoinPragma.hpp"
00005 #include "BonLpBranchingSolver.hpp"
00006 #include "OsiClpSolverInterface.hpp"
00007 #include <vector>
00008
00009 namespace Bonmin
00010 {
00011
00012 LpBranchingSolver::LpBranchingSolver(BabSetupBase * b) :
00013 StrongBranchingSolver(b->nonlinearSolver()),
00014 lin_(NULL),
00015 warm_(NULL),
00016 ecp_(NULL)
00017 {
00018 Ipopt::SmartPtr<TNLPSolver> tnlp_solver =
00019 static_cast<TNLPSolver *> (b->nonlinearSolver()->solver());
00020 Ipopt::SmartPtr<Ipopt::OptionsList> options = tnlp_solver->options();
00021
00022 options->GetIntegerValue("ecp_max_rounds_strong",
00023 maxCuttingPlaneIterations_,
00024 b->nonlinearSolver()->prefix());
00025 options->GetNumericValue("ecp_abs_tol_strong",
00026 abs_ecp_tol_,
00027 b->nonlinearSolver()->prefix());
00028 options->GetNumericValue("ecp_rel_tol_strong",
00029 rel_ecp_tol_,
00030 b->nonlinearSolver()->prefix());
00031 int dummy;
00032 options->GetEnumValue("lp_strong_warmstart_method",
00033 dummy,
00034 b->nonlinearSolver()->prefix());
00035 warm_start_mode_ = (WarmStartMethod) dummy;
00036 }
00037
00038 LpBranchingSolver::LpBranchingSolver(const LpBranchingSolver & rhs) :
00039 StrongBranchingSolver(rhs),
00040 lin_(NULL),
00041 warm_(NULL),
00042 ecp_(NULL),
00043 maxCuttingPlaneIterations_(rhs.maxCuttingPlaneIterations_),
00044 abs_ecp_tol_(rhs.abs_ecp_tol_),
00045 rel_ecp_tol_(rhs.rel_ecp_tol_),
00046 warm_start_mode_(rhs.warm_start_mode_)
00047 {}
00048
00049 LpBranchingSolver &
00050 LpBranchingSolver::operator=(const LpBranchingSolver & rhs)
00051 {
00052 if (this != &rhs) {
00053 StrongBranchingSolver::operator=(rhs);
00054 }
00055 maxCuttingPlaneIterations_ = rhs.maxCuttingPlaneIterations_;
00056 abs_ecp_tol_ = rhs.abs_ecp_tol_;
00057 rel_ecp_tol_ = rhs.rel_ecp_tol_;
00058 warm_start_mode_ = rhs.warm_start_mode_;
00059
00060 delete lin_;
00061 delete warm_;
00062 delete ecp_;
00063 lin_ = NULL;
00064 warm_ = NULL;
00065 ecp_ = NULL;
00066 return *this;
00067 }
00068
00069 LpBranchingSolver::~LpBranchingSolver ()
00070 {
00071 delete lin_;
00072 delete warm_;
00073 delete ecp_;
00074 }
00075
00076 void LpBranchingSolver::
00077 markHotStart(OsiTMINLPInterface* tminlp_interface)
00078 {
00079 lin_ = new OsiClpSolverInterface();
00080 tminlp_interface->extractLinearRelaxation(*lin_, tminlp_interface->getColSolution(),
00081 true);
00082 double cutoff = -DBL_MAX;
00083 tminlp_interface->getDblParam(OsiDualObjectiveLimit, cutoff);
00084 lin_->setDblParam(OsiDualObjectiveLimit, cutoff);
00085
00086 lin_->messageHandler()->setLogLevel(0);
00087 lin_->resolve();
00088 warm_ = lin_->getWarmStart();
00089
00090
00091
00092 }
00093
00094 void LpBranchingSolver::
00095 unmarkHotStart(OsiTMINLPInterface* tminlp_interface)
00096 {
00097
00098 delete lin_;
00099 delete warm_;
00100 delete ecp_;
00101 lin_ = NULL;
00102 warm_ = NULL;
00103 ecp_ = NULL;
00104 }
00105
00106 TNLPSolver::ReturnStatus LpBranchingSolver::
00107 solveFromHotStart(OsiTMINLPInterface* tminlp_interface)
00108 {
00109 TNLPSolver::ReturnStatus retstatus = TNLPSolver::solvedOptimal;
00110
00111
00112 std::vector<int> diff_low_bnd_index;
00113 std::vector<double> diff_low_bnd_value;
00114 std::vector<int> diff_up_bnd_index;
00115 std::vector<double> diff_up_bnd_value;
00116
00117
00118
00119 const int numCols = tminlp_interface->getNumCols();
00120 const double* colLow_orig = lin_->getColLower();
00121 const double* colUp_orig = lin_->getColUpper();
00122 const double* colLow = tminlp_interface->getColLower();
00123 const double* colUp = tminlp_interface->getColUpper();
00124
00125 OsiSolverInterface * lin = lin_;
00126
00127 if(warm_start_mode_ == Clone){
00128 lin = lin_->clone();
00129
00130 }
00131
00132
00133 for (int i=0; i<numCols; i++) {
00134 const double& lo = colLow[i];
00135 if (colLow_orig[i] < lo) {
00136 if(warm_start_mode_ == Basis){
00137 diff_low_bnd_value.push_back(colLow_orig[i]);
00138 diff_low_bnd_index.push_back(i);
00139 }
00140 lin->setColLower(i,lo);
00141 }
00142 const double& up = colUp[i];
00143 if (colUp_orig[i] > up) {
00144 if(warm_start_mode_ == Basis){
00145 diff_up_bnd_index.push_back(i);
00146 diff_up_bnd_value.push_back(colUp_orig[i]);
00147 }
00148 lin->setColUpper(i,lo);
00149 }
00150 }
00151
00152 if(warm_start_mode_ == Basis){
00153 lin->setWarmStart(warm_);
00154 }
00155
00156 lin->resolve();
00157
00158 double obj = lin->getObjValue();
00159 bool go_on = true;
00160 if (lin->isProvenPrimalInfeasible() ||
00161 lin->isDualObjectiveLimitReached()) {
00162 retstatus = TNLPSolver::provenInfeasible;
00163 go_on = false;
00164 }
00165 else if (lin->isIterationLimitReached()) {
00166 retstatus = TNLPSolver::iterationLimit;
00167 go_on = false;
00168 }
00169 else {
00170 if (maxCuttingPlaneIterations_ > 0 && go_on) {
00171 double violation;
00172 obj = ecp_->doEcpRounds(*lin, true, &violation);
00173 if (obj == COIN_DBL_MAX) {
00174 retstatus = TNLPSolver::provenInfeasible;
00175 }
00176 else if (violation <= 1e-8) {
00177 retstatus = TNLPSolver::solvedOptimal;
00178 }
00179 }
00180 }
00181 tminlp_interface->problem()->set_obj_value(obj);
00182 tminlp_interface->problem()->Set_x_sol(numCols, lin_->getColSolution());
00183
00184
00185 if(warm_start_mode_ == Basis){
00186 for (unsigned int i = 0; i < diff_low_bnd_index.size(); i++) {
00187 lin_->setColLower(diff_low_bnd_index[i],diff_low_bnd_value[i]);
00188 }
00189 for (unsigned int i = 0; i < diff_up_bnd_index.size(); i++) {
00190 lin_->setColUpper(diff_up_bnd_index[i],diff_up_bnd_value[i]);
00191 }
00192 }
00193 else {
00194 delete lin;
00195 }
00196 return retstatus;
00197 }
00198
00199 void
00200 LpBranchingSolver::registerOptions(Ipopt::SmartPtr<Bonmin::RegisteredOptions> roptions)
00201 {
00202 roptions->SetRegisteringCategory("ECP based strong branching",RegisteredOptions::UndocumentedCategory);
00203 roptions->AddLowerBoundedIntegerOption
00204 ("ecp_max_rounds_strong",
00205 "Set the maximal number of rounds of ECP cuts in strong branching.",
00206 0,0,
00207 "");
00208 roptions->setOptionExtraInfo("ecp_max_rounds_strong",63);
00209 roptions->AddLowerBoundedNumberOption
00210 ("ecp_abs_tol_strong",
00211 "Set the absolute termination tolerance for ECP rounds in strong branching.",
00212 0,false,1e-6,
00213 "");
00214 roptions->setOptionExtraInfo("ecp_abs_tol_strong",63);
00215 roptions->AddLowerBoundedNumberOption
00216 ("ecp_rel_tol_strong",
00217 "Set the relative termination tolerance for ECP rounds in strong branching.",
00218 0,false,1e-1,
00219 "");
00220 roptions->setOptionExtraInfo("ecp_rel_tol_strong",63);
00221 roptions->AddStringOption2
00222 ("lp_strong_warmstart_method",
00223 "Choose method to use for warm starting lp in strong branching",
00224 "Basis",
00225 "Basis", "Use optimal basis of node",
00226 "Clone", "Clone optimal problem of node",
00227 "(Advanced stuff)");
00228 roptions->setOptionExtraInfo("lp_strong_warmstart_method",63);
00229 }
00230
00231 }