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