diff --git a/ortools/linear_solver/cplex_interface.cc b/ortools/linear_solver/cplex_interface.cc index f0db8ea8d06..d2341155c39 100644 --- a/ortools/linear_solver/cplex_interface.cc +++ b/ortools/linear_solver/cplex_interface.cc @@ -17,6 +17,7 @@ #include #include "absl/strings/str_format.h" +#include "absl/strings/str_split.h" #include "ortools/base/integral_types.h" #include "ortools/base/logging.h" #include "ortools/base/timer.h" @@ -115,6 +116,8 @@ class CplexInterface : public MPSolverInterface { virtual bool IsLP() const { return !mMip; } virtual bool IsMIP() const { return mMip; } + bool SetSolverSpecificParametersAsString( + const std::string ¶meters) override; virtual void ExtractNewVariables(); virtual void ExtractNewConstraints(); virtual void ExtractObjective(); @@ -1108,6 +1111,18 @@ MPSolver::ResultStatus CplexInterface::Solve(MPSolverParameters const& param) { CHECK_STATUS( CPXXsetintparam(mEnv, CPX_PARAM_SCRIND, quiet() ? CPX_OFF : CPX_ON)); + if (!solver_->solution_hint_.empty()) { + int const sol_count = solver_->solution_hint_.size(); + long long int beg[1] = {0}; + int *varindices = new int[sol_count]; + double *values = new double[sol_count]; + + for (int i=0; isolution_hint_[i].first->index(); + values[i] = solver_->solution_hint_[i].second; + } + CPXaddmipstarts (mEnv, mLp, 1, sol_count, beg, varindices, values, NULL, NULL); + } // Set parameters. // NOTE: We must invoke SetSolverSpecificParametersAsString() _first_. // Its current implementation invokes ReadParameterFile() which in @@ -1272,5 +1287,47 @@ MPSolverInterface* BuildCplexInterface(bool mip, MPSolver* const solver) { return new CplexInterface(solver, mip); } +bool CplexInterface::SetSolverSpecificParametersAsString( + const std::string ¶meters) { + if (parameters.empty()) + return true; + for (const auto parameter : absl::StrSplit(parameters, absl::ByAnyChar(","), + absl::SkipWhitespace())) { + std::vector key_value = + absl::StrSplit(parameter, absl::ByAnyChar("="), absl::SkipWhitespace()); + if (key_value.size() != 2) { + LOG(WARNING) << absl::StrFormat( + "Cannot parse parameter '%s'. Expected format is 'parameter/name = " + "value'", + parameter); + continue; + } + std::string identifier = key_value[0]; + absl::RemoveExtraAsciiWhitespace(&identifier); + + std::string value = key_value[1]; + absl::RemoveExtraAsciiWhitespace(&value); + + try { + if(identifier.find("LogFile") != std::string::npos) { + CPXXsetlogfilename (mEnv, value.c_str(), "w"); + } else { + std::string delimiter = "."; + if (value.find(delimiter) == std::string::npos) { + (void)CPXXsetintparam(mEnv, std::stoi(identifier), std::stoi(value)); + } else { + (void)CPXXsetdblparam(mEnv, std::stoi(identifier), std::stod(value)); + } + VLOG(2) << absl::StrFormat("Set parameter %s to %s", identifier, value); + } + } catch (...) { + LOG(WARNING) << absl::StrFormat( + "Cannot parse parameter '%s'. Expected format is 'parameter/name = value'", + identifier); + } + } + return true; + } + } // namespace operations_research #endif // #if defined(USE_CPLEX)