diff --git a/ortools/constraint_solver/constraint_solveri.h b/ortools/constraint_solver/constraint_solveri.h index d3271bacb7b..682cd284097 100644 --- a/ortools/constraint_solver/constraint_solveri.h +++ b/ortools/constraint_solver/constraint_solveri.h @@ -1869,7 +1869,7 @@ class LocalSearchState { VariableDomainId domain_id; int input_index; ConstraintId constraint_id; -}; + }; // Adds all dependencies domains[i] -> constraint labelled by i. void AddDomainsConstraintDependencies( const std::vector& domain_ids, diff --git a/ortools/linear_solver/linear_solver.cc b/ortools/linear_solver/linear_solver.cc index e00b640fd22..7f8e3f7487e 100644 --- a/ortools/linear_solver/linear_solver.cc +++ b/ortools/linear_solver/linear_solver.cc @@ -406,7 +406,6 @@ extern MPSolverInterface* BuildCplexInterface(bool mip, MPSolver* const solver); extern MPSolverInterface* BuildXpressInterface(bool mip, MPSolver* const solver); - namespace { MPSolverInterface* BuildSolverInterface(MPSolver* const solver) { DCHECK(solver != nullptr); diff --git a/ortools/linear_solver/proto_solver/xpress_proto_solver.cc b/ortools/linear_solver/proto_solver/xpress_proto_solver.cc index 0e209d4b788..20da17f8896 100644 --- a/ortools/linear_solver/proto_solver/xpress_proto_solver.cc +++ b/ortools/linear_solver/proto_solver/xpress_proto_solver.cc @@ -50,7 +50,8 @@ namespace operations_research { // bool XPressCodeToInvalidResponse(int error_code, const char* source_file, // int source_line, const char* statement, -// XPRSprob prob, MPSolutionResponse* response) { +// XPRSprob prob, MPSolutionResponse* response) +// { // if (error_code == XPRS_OK) return true; // response->set_status(); // response->set_status_message(absl::StrFormat( @@ -83,7 +84,8 @@ namespace operations_research { // if (cst.upper_bound() < std::numeric_limits::infinity() && // cst.lower_bound() != cst.upper_bound()) { // return XPRSaddgenconstrIndicator(xpress_model, gen_cst.name().c_str(), -// ind_cst.var_index(), ind_cst.var_value(), +// ind_cst.var_index(), +// ind_cst.var_value(), // cst.var_index_size(), // cst.mutable_var_index()->mutable_data(), // cst.mutable_coefficient()->mutable_data(), @@ -169,7 +171,8 @@ namespace operations_research { // } // int AddAndConstraint(const MPGeneralConstraintProto& gen_cst, -// XPRSprob xpress_model, std::vector* tmp_variables) { +// XPRSprob xpress_model, std::vector* tmp_variables) +// { // CHECK(xpress_model != nullptr); // CHECK(tmp_variables != nullptr); @@ -197,7 +200,8 @@ namespace operations_research { // } // int AddMinConstraint(const MPGeneralConstraintProto& gen_cst, -// XPRSprob xpress_model, std::vector* tmp_variables) { +// XPRSprob xpress_model, std::vector* tmp_variables) +// { // CHECK(xpress_model != nullptr); // CHECK(tmp_variables != nullptr); @@ -214,7 +218,8 @@ namespace operations_research { // } // int AddMaxConstraint(const MPGeneralConstraintProto& gen_cst, -// XPRSprob xpress_model, std::vector* tmp_variables) { +// XPRSprob xpress_model, std::vector* tmp_variables) +// { // CHECK(xpress_model != nullptr); // CHECK(tmp_variables != nullptr); @@ -245,7 +250,8 @@ namespace operations_research { // absl::StrSplit(line, ',', absl::SkipWhitespace())) { // if (token.empty()) continue; // std::vector key_value = -// absl::StrSplit(token, absl::ByAnyChar(" ="), absl::SkipWhitespace()); +// absl::StrSplit(token, absl::ByAnyChar(" ="), +// absl::SkipWhitespace()); // // If one parameter fails, we keep processing the list of parameters. // if (key_value.size() != 2) { // const std::string current_message = @@ -264,7 +270,8 @@ namespace operations_research { // error_messages.push_back(current_message); // continue; // } -// VLOG(2) << absl::StrCat("Set parameter '", key_value[0], "' to value '", +// VLOG(2) << absl::StrCat("Set parameter '", key_value[0], "' to value +// '", // key_value[1]); // } // } @@ -276,648 +283,686 @@ namespace operations_research { MPSolutionResponse XPressSolveProto(const MPModelRequest& request) { MPSolutionResponse response; response.set_status(MPSolverResponseStatus::MPSOLVER_SOLVER_TYPE_UNAVAILABLE); - -// const absl::optional> optional_model = -// ExtractValidMPModelOrPopulateResponseStatus(request, &response); -// if (!optional_model) return response; -// const MPModelProto& model = optional_model->get(); - -// // We set `xpress_env` to point to a new environment if no existing one is -// // provided. We must make sure that we free this environment when we exit this -// // function. -// bool xpress_env_was_created = false; -// auto xpress_env_deleter = absl::MakeCleanup([&]() { -// if (xpress_env_was_created && xpress_env != nullptr) { -// XPRSfreeenv(xpress_env); -// } -// }); -// if (xpress_env == nullptr) { -// ASSIGN_OR_RETURN(xpress_env, GetXPressEnv()); -// xpress_env_was_created = true; -// } -// XPRSprob xpress_model = nullptr; -// auto xpress_model_deleter = absl::MakeCleanup([&]() { -// const int error_code = XPRSfreemodel(xpress_model); -// LOG_IF(DFATAL, error_code != XPRS_OK) -// << "XPRSfreemodel failed with error " << error_code << ": " -// << XPRSgeterrormsg(xpress_env); -// }); - -// // `xpress_env` references ther XPRSenv argument. -// #define RETURN_IF_XPRESS_ERROR(x) \ + // const absl::optional> optional_model = + // ExtractValidMPModelOrPopulateResponseStatus(request, &response); + // if (!optional_model) return response; + // const MPModelProto& model = optional_model->get(); + + // // We set `xpress_env` to point to a new environment if no existing one + // is + // // provided. We must make sure that we free this environment when we exit + // this + // // function. + // bool xpress_env_was_created = false; + // auto xpress_env_deleter = absl::MakeCleanup([&]() { + // if (xpress_env_was_created && xpress_env != nullptr) { + // XPRSfreeenv(xpress_env); + // } + // }); + // if (xpress_env == nullptr) { + // ASSIGN_OR_RETURN(xpress_env, GetXPressEnv()); + // xpress_env_was_created = true; + // } + + // XPRSprob xpress_model = nullptr; + // auto xpress_model_deleter = absl::MakeCleanup([&]() { + // const int error_code = XPRSfreemodel(xpress_model); + // LOG_IF(DFATAL, error_code != XPRS_OK) + // << "XPRSfreemodel failed with error " << error_code << ": " + // << XPRSgeterrormsg(xpress_env); + // }); + + // // `xpress_env` references ther XPRSenv argument. + // #define RETURN_IF_XPRESS_ERROR(x) \ // RETURN_IF_ERROR( \ -// if (!XPressCodeToInvalidResponse(x, __FILE__, __LINE__, #x, xpress, &response)) { \ +// if (!XPressCodeToInvalidResponse(x, __FILE__, __LINE__, #x, xpress, + // &response)) { \ // return response; \ // }) -// RETURN_IF_XPRESS_ERROR(XPRSnewmodel(xpress_env, &xpress_model, -// model.name().c_str(), -// /*numvars=*/0, -// /*obj=*/nullptr, -// /*lb=*/nullptr, -// /*ub=*/nullptr, -// /*vtype=*/nullptr, -// /*varnames=*/nullptr)); -// XPRSprob const model_env = XPRSgetenv(xpress_model); - -// if (request.has_solver_specific_parameters()) { -// const auto parameters_status = SetSolverSpecificParameters( -// request.solver_specific_parameters(), model_env); -// if (!parameters_status.ok()) { -// response.set_status(MPSOLVER_MODEL_INVALID_SOLVER_PARAMETERS); -// response.set_status_str( -// std::string(parameters_status.message())); // NOLINT -// return response; -// } -// } -// if (request.solver_time_limit_seconds() > 0) { -// RETURN_IF_XPRESS_ERROR( -// XPRSsetdblparam(model_env, XPRS_DBL_PAR_TIMELIMIT, -// request.solver_time_limit_seconds())); -// } -// RETURN_IF_XPRESS_ERROR( -// XPRSsetintparam(model_env, XPRS_INT_PAR_OUTPUTFLAG, -// request.enable_internal_solver_output())); - -// const int variable_size = model.variable_size(); -// bool has_integer_variables = false; -// { -// std::vector obj_coeffs(variable_size, 0); -// std::vector lb(variable_size); -// std::vector ub(variable_size); -// std::vector ctype(variable_size); -// std::vector varnames(variable_size); -// for (int v = 0; v < variable_size; ++v) { -// const MPVariableProto& variable = model.variable(v); -// obj_coeffs[v] = variable.objective_coefficient(); -// lb[v] = variable.lower_bound(); -// ub[v] = variable.upper_bound(); -// ctype[v] = variable.is_integer() && -// request.solver_type() ==SolutionRes -// : XPRS_CONTINUOUS; -// if (variable.is_integer()) has_integer_variables = true; -// if (!variable.name().empty()) varnames[v] = variable.name().c_str(); -// } - -// RETURN_IF_XPRESS_ERROR( -// XPRSaddvars(xpress_model, variable_size, 0, nullptr, nullptr, nullptr, -// /*obj=*/obj_coeffs.data(), -// /*lb=*/lb.data(), /*ub=*/ub.data(), /*vtype=*/ctype.data(), -// /*varnames=*/const_cast(varnames.data()))); - -// // Set solution hints if any. -// for (int i = 0; i < model.solution_hint().var_index_size(); ++i) { -// RETURN_IF_XPRESS_ERROR(XPRSsetdblattrelement( -// xpress_model, XPRS_DBL_ATTR_START, model.solution_hint().var_inde const absl::optional> optional_model = -// ExtractValidMPModelOrPopulateResponseStatus(request, &response); -// if (!optional_model) return response; -// const MPModelProto& model = optional_model->get(); - -// // We set `xpress_env` to point to a new environment if no existing one is -// // provided. We must make sure that we free this environment when we exit this -// // function. -// bool xpress_env_was_created = false; -// auto xpress_env_deleter = absl::MakeCleanup([&]() { -// if (xpress_env_was_created && xpress_env != nullptr) { -// XPRSfreeenv(xpress_env); -// } -// }); -// if (xpress_env == nullptr) { -// ASSIGN_OR_RETURN(xpress_env, GetXPressEnv()); -// xpress_env_was_created = true; -// } - -// XPRSprob xpress_model = nullptr; -// auto xpress_model_deleter = absl::MakeCleanup([&]() { -// const int error_code = XPRSfreemodel(xpress_model); -// LOG_IF(DFATAL, error_code != XPRS_OK) -// << "XPRSfreemodel failed with error " << error_code << ": " -// << XPRSgeterrormsg(xpress_env); -// }); - -// // `xpress_env` references ther XPRSenv argument. -// #define RETURN_IF_XPRESS_ERROR(x) \ + // RETURN_IF_XPRESS_ERROR(XPRSnewmodel(xpress_env, &xpress_model, + // model.name().c_str(), + // /*numvars=*/0, + // /*obj=*/nullptr, + // /*lb=*/nullptr, + // /*ub=*/nullptr, + // /*vtype=*/nullptr, + // /*varnames=*/nullptr)); + // XPRSprob const model_env = XPRSgetenv(xpress_model); + + // if (request.has_solver_specific_parameters()) { + // const auto parameters_status = SetSolverSpecificParameters( + // request.solver_specific_parameters(), model_env); + // if (!parameters_status.ok()) { + // response.set_status(MPSOLVER_MODEL_INVALID_SOLVER_PARAMETERS); + // response.set_status_str( + // std::string(parameters_status.message())); // NOLINT + // return response; + // } + // } + // if (request.solver_time_limit_seconds() > 0) { + // RETURN_IF_XPRESS_ERROR( + // XPRSsetdblparam(model_env, XPRS_DBL_PAR_TIMELIMIT, + // request.solver_time_limit_seconds())); + // } + // RETURN_IF_XPRESS_ERROR( + // XPRSsetintparam(model_env, XPRS_INT_PAR_OUTPUTFLAG, + // request.enable_internal_solver_output())); + + // const int variable_size = model.variable_size(); + // bool has_integer_variables = false; + // { + // std::vector obj_coeffs(variable_size, 0); + // std::vector lb(variable_size); + // std::vector ub(variable_size); + // std::vector ctype(variable_size); + // std::vector varnames(variable_size); + // for (int v = 0; v < variable_size; ++v) { + // const MPVariableProto& variable = model.variable(v); + // obj_coeffs[v] = variable.objective_coefficient(); + // lb[v] = variable.lower_bound(); + // ub[v] = variable.upper_bound(); + // ctype[v] = variable.is_integer() && + // request.solver_type() ==SolutionRes + // : XPRS_CONTINUOUS; + // if (variable.is_integer()) has_integer_variables = true; + // if (!variable.name().empty()) varnames[v] = variable.name().c_str(); + // } + + // RETURN_IF_XPRESS_ERROR( + // XPRSaddvars(xpress_model, variable_size, 0, nullptr, nullptr, + // nullptr, + // /*obj=*/obj_coeffs.data(), + // /*lb=*/lb.data(), /*ub=*/ub.data(), + // /*vtype=*/ctype.data(), + // /*varnames=*/const_cast(varnames.data()))); + + // // Set solution hints if any. + // for (int i = 0; i < model.solution_hint().var_index_size(); ++i) { + // RETURN_IF_XPRESS_ERROR(XPRSsetdblattrelement( + // xpress_model, XPRS_DBL_ATTR_START, model.solution_hint().var_inde + // const absl::optional> + // optional_model = + // ExtractValidMPModelOrPopulateResponseStatus(request, &response); + // if (!optional_model) return response; + // const MPModelProto& model = optional_model->get(); + + // // We set `xpress_env` to point to a new environment if no existing one + // is + // // provided. We must make sure that we free this environment when we exit + // this + // // function. + // bool xpress_env_was_created = false; + // auto xpress_env_deleter = absl::MakeCleanup([&]() { + // if (xpress_env_was_created && xpress_env != nullptr) { + // XPRSfreeenv(xpress_env); + // } + // }); + // if (xpress_env == nullptr) { + // ASSIGN_OR_RETURN(xpress_env, GetXPressEnv()); + // xpress_env_was_created = true; + // } + + // XPRSprob xpress_model = nullptr; + // auto xpress_model_deleter = absl::MakeCleanup([&]() { + // const int error_code = XPRSfreemodel(xpress_model); + // LOG_IF(DFATAL, error_code != XPRS_OK) + // << "XPRSfreemodel failed with error " << error_code << ": " + // << XPRSgeterrormsg(xpress_env); + // }); + + // // `xpress_env` references ther XPRSenv argument. + // #define RETURN_IF_XPRESS_ERROR(x) \ // RETURN_IF_ERROR( \ // XPressCodeToUtilStatus(x, __FILE__, __LINE__, #x, xpress_env)); -// RETURN_IF_XPRESS_ERROR(XPRSnewmodel(xpress_env, &xpress_model, -// model.name().c_str(), -// /*numvars=*/0, -// /*obj=*/nullptr, -// /*lb=*/nullptr, -// /*ub=*/nullptr, -// /*vtype=*/nullptr, -// /*varnames=*/nullptr)); -// XPRSprob const model_env = XPRSgetenv(xpress_model); - -// if (request.has_solver_specific_parameters()) { -// const auto parameters_status = SetSolverSpecificParameters( -// request.solver_specific_parameters(), model_env); -// if (!parameters_status.ok()) { -// response.set_status(MPSOLVER_MODEL_INVALID_SOLVER_PARAMETERS); -// response.set_status_str( -// std::string(parameters_status.message())); // NOLINT -// return response; -// } -// } -// if (request.solver_time_limit_seconds() > 0) { -// RETURN_IF_XPRESS_ERROR( -// XPRSsetdblparam(model_env, XPRS_DBL_PAR_TIMELIMIT, -// request.solver_time_limit_seconds())); -// } -// RETURN_IF_XPRESS_ERROR( -// XPRSsetintparam(model_env, XPRS_INT_PAR_OUTPUTFLAG, -// request.enable_internal_solver_output())); - -// const int variable_size = model.variable_size(); -// bool has_integer_variables = false; -// { -// std::vector obj_coeffs(variable_size, 0); -// std::vector lb(variable_size); -// std::vector ub(variable_size); -// std::vector ctype(variable_size); -// std::vector varnames(variable_size); -// for (int v = 0; v < variable_size; ++v) { -// const MPVariableProto& variable = model.variable(v); -// obj_coeffs[v] = variable.objective_coefficient(); -// lb[v] = variable.lower_bound(); -// ub[v] = variable.upper_bound(); -// ctype[v] = variable.is_integer() && -// request.solver_type() == -// MPModelRequest::XPRESS_MIXED_INTEGER_PROGRAMMING -// ? XPRS_INTEGER -// : XPRS_CONTINUOUS; -// if (variable.is_integer()) has_integer_variables = true; -// if (!variable.name().empty()) varnames[v] = variable.name().c_str(); -// } - -// RETURN_IF_XPRESS_ERROR( -// XPRSaddvars(xpress_model, variable_size, 0, nullptr, nullptr, nullptr, -// /*obj=*/obj_coeffs.data(), -// /*lb=*/lb.data(), /*ub=*/ub.data(), /*vtype=*/ctype.data(), -// /*varnames=*/const_cast(varnames.data()))); - -// // Set solution hints if any. -// for (int i = 0; i < model.solution_hint().var_index_size(); ++i) { -// RETURN_IF_XPRESS_ERROR(XPRSsetdblattrelement( -// xpress_model, XPRS_DBL_ATTR_START, model.solution_hint().var_index(i), -// model.solution_hint().var_value(i))); -// } -// } - -// { -// std::vector ct_variables; -// std::vector ct_coefficients; -// for (int c = 0; c < model.constraint_size(); ++c) { -// const MPConstraintProto& constraint = model.constraint(c); -// const int size = constraint.var_index_size(); -// ct_variables.resize(size, 0); -// ct_coefficients.resize(size, 0); -// for (int i = 0; i < size; ++i) { -// ct_variables[i] = constraint.var_index(i); -// ct_coefficients[i] = constraint.coefficient(i); -// } -// // Using XPRSaddrangeconstr for constraints that don't require it adds -// // a slack which is not always removed by presolve. -// if (constraint.lower_bound() == constraint.upper_bound()) { -// RETURN_IF_XPRESS_ERROR(XPRSaddconstr( -// xpress_model, /*numnz=*/size, /*cind=*/ct_variables.data(), -// /*cval=*/ct_coefficients.data(), -// /*sense=*/XPRS_EQUAL, /*rhs=*/constraint.lower_bound(), -// /*constrname=*/constraint.name().c_str())); -// } else if (constraint.lower_bound() == -// -std::numeric_limits::infinity()) { -// RETURN_IF_XPRESS_ERROR(XPRSaddconstr( -// xpress_model, /*numnz=*/size, /*cind=*/ct_variables.data(), -// /*cval=*/ct_coefficients.data(), -// /*sense=*/XPRS_LESS_EQUAL, /*rhs=*/constraint.upper_bound(), -// /*constrname=*/constraint.name().c_str())); -// } else if (constraint.upper_bound() == -// std::numeric_limits::infinity()) { -// RETURN_IF_XPRESS_ERROR(XPRSaddconstr( -// xpress_model, /*numnz=*/size, /*cind=*/ct_variables.data(), -// /*cval=*/ct_coefficients.data(), -// /*sense=*/XPRS_GREATER_EQUAL, /*rhs=*/constraint.lower_bound(), -// /*constrname=*/constraint.name().c_str())); -// } else { -// RETURN_IF_XPRESS_ERROR(XPRSaddrangeconstr( -// xpress_model, /*numnz=*/size, /*cind=*/ct_variables.data(), -// /*cval=*/ct_coefficients.data(), -// /*lower=*/constraint.lower_bound(), -// /*upper=*/constraint.upper_bound(), -// /*constrname=*/constraint.name().c_str())); -// } -// } - -// for (const auto& gen_cst : model.general_constraint()) { -// switch (gen_cst.general_constraint_case()) { -// case MPGeneralConstraintProto::kIndicatorConstraint: { -// RETURN_IF_XPRESS_ERROR(AddIndicatorConstraint( -// gen_cst, xpress_model, &ct_variables, &ct_coefficients)); -// break; -// } -// case MPGeneralConstraintProto::kSosConstraint: { -// RETURN_IF_XPRESS_ERROR(AddSosConstraint(gen_cst.sos_constraint(), -// xpress_model, &ct_variables, -// &ct_coefficients)); -// break; -// } -// case MPGeneralConstraintProto::kQuadraticConstraint: { -// RETURN_IF_XPRESS_ERROR(AddQuadraticConstraint(gen_cst, xpress_model)); -// break; -// } -// case MPGeneralConstraintProto::kAbsConstraint: { -// RETURN_IF_XPRESS_ERROR(XPRSaddgenconstrAbs( -// xpress_model, -// /*name=*/gen_cst.name().c_str(), -// /*resvar=*/gen_cst.abs_constraint().resultant_var_index(), -// /*argvar=*/gen_cst.abs_constraint().var_index())); -// break; -// } -// case MPGeneralConstraintProto::kAndConstraint: { -// RETURN_IF_XPRESS_ERROR( -// AddAndConstraint(gen_cst, xpress_model, &ct_variables)); -// break; -// } -// case MPGeneralConstraintProto::kOrConstraint: { -// RETURN_IF_XPRESS_ERROR( -// AddOrConstraint(gen_cst, xpress_model, &ct_variables)); -// break; -// } -// case MPGeneralConstraintProto::kMinConstraint: { -// RETURN_IF_XPRESS_ERROR( -// AddMinConstraint(gen_cst, xpress_model, &ct_variables)); -// break; -// } -// case MPGeneralConstraintProto::kMaxConstraint: { -// RETURN_IF_XPRESS_ERROR( -// AddMaxConstraint(gen_cst, xpress_model, &ct_variables)); -// break; -// } -// default: -// return absl::UnimplementedError( -// absl::StrFormat("General constraints of type %i not supported.", -// gen_cst.general_constraint_case())); -// } -// } -// } - -// RETURN_IF_XPRESS_ERROR(XPRSsetintattr(xpress_model, XPRS_INT_ATTR_MODELSENSE, -// model.maximize() ? -1 : 1)); -// RETURN_IF_XPRESS_ERROR(XPRSsetdblattr(xpress_model, XPRS_DBL_ATTR_OBJCON, -// model.objective_offset())); -// if (model.has_quadratic_objective()) { -// MPQuadraticObjective qobj = model.quadratic_objective(); -// if (qobj.coefficient_size() > 0) { -// RETURN_IF_XPRESS_ERROR( -// XPRSaddqpterms(xpress_model, /*numqnz=*/qobj.coefficient_size(), -// /*qrow=*/qobj.mutable_qvar1_index()->mutable_data(), -// /*qcol=*/qobj.mutable_qvar2_index()->mutable_data(), -// /*qval=*/qobj.mutable_coefficient()->mutable_data())); -// } -// } - -// RETURN_IF_XPRESS_ERROR(XPRSupdatemodel(xpress_model)); - -// const absl::Time time_before = absl::Now(); -// UserTimer user_timer; -// user_timer.Start(); - -// RETURN_IF_XPRESS_ERROR(XPRSoptimize(xpress_model)); - -// const absl::Duration solving_duration = absl::Now() - time_before; -// user_timer.Stop(); -// VLOG(1) << "Finished solving in XPressSolveProto(), walltime = " -// << solving_duration << ", usertime = " << user_timer.GetDuration(); -// response.mutable_solve_info()->set_solve_wall_time_seconds( -// absl::ToDoubleSeconds(solving_duration)); -// response.mutable_solve_info()->set_solve_user_time_seconds( -// absl::ToDoubleSeconds(user_timer.GetDuration())); - -// int optimization_status = 0; -// RETURN_IF_XPRESS_ERROR( -// XPRSgetintattr(xpress_model, XPRS_INT_ATTR_STATUS, &optimization_status)); -// int solution_count = 0; -// RETURN_IF_XPRESS_ERROR( -// XPRSgetintattr(xpress_model, XPRS_INT_ATTR_SOLCOUNT, &solution_count)); -// switch (optimization_status) { -// case XPRS_OPTIMAL: -// response.set_status(MPSOLVER_OPTIMAL); -// break; -// case XPRS_INF_OR_UNBD: -// DLOG(INFO) << "XPress solve returned XPRS_INF_OR_UNBD, which we treat as " -// "INFEASIBLE even though it may mean UNBOUNDED."; -// response.set_status_str( -// "The model may actually be unbounded: XPress returned " -// "XPRS_INF_OR_UNBD"); -// ABSL_FALLTHROUGH_INTENDED; -// case XPRS_INFEASIBLE: -// response.set_status(MPSOLVER_INFEASIBLE); -// break; -// case XPRS_UNBOUNDED: -// response.set_status(MPSOLVER_UNBOUNDED); -// break; -// default: { -// if (solution_count > 0) { -// response.set_status(MPSOLVER_FEASIBLE); -// } else { -// response.set_status(MPSOLVER_NOT_SOLVED); -// response.set_status_str( -// absl::StrFormat("XPress status code %d", optimization_status)); -// } -// break; -// } -// } - -// if (solution_count > 0 && (response.status() == MPSOLVER_FEASIBLE || -// response.status() == MPSOLVER_OPTIMAL)) { -// double objective_value = 0; -// RETURN_IF_XPRESS_ERROR( -// XPRSgetdblattr(xpress_model, XPRS_DBL_ATTR_OBJVAL, &objective_value)); -// response.set_objective_value(objective_value); -// double best_objective_bound = 0; -// const int error = XPRSgetdblattr(xpress_model, XPRS_DBL_ATTR_OBJBOUND, -// &best_objective_bound); -// if (response.status() == MPSOLVER_OPTIMAL && -// error == XPRS_ERROR_DATA_NOT_AVAILABLE) { -// // If the presolve deletes all variables, there's no best bound. -// response.set_best_objective_bound(objective_value); -// } else { -// RETURN_IF_XPRESS_ERROR(error); -// response.set_best_objective_bound(best_objective_bound); -// } - -// response.mutable_variable_value()->Resize(variable_size, 0); -// RETURN_IF_XPRESS_ERROR( -// XPRSgetdblattrarray(xpress_model, XPRS_DBL_ATTR_X, 0, variable_size, -// response.mutable_variable_value()->mutable_data())); -// // NOTE, XPressSolveProto() is exposed to external clients via MPSolver API, -// // which assumes the solution values of integer variables are rounded to -// // integer values. -// auto round_values_of_integer_variables_fn = -// [&](google::protobuf::RepeatedField* values) { -// for (int v = 0; v < variable_size; ++v) { -// if (model.variable(v).is_integer()) { -// (*values)[v] = std::round((*values)[v]); -// } -// } -// }; -// round_values_of_integer_variables_fn(response.mutable_variable_value()); -// if (!has_integer_variables && model.general_constraint_size() == 0) { -// response.mutable_dual_value()->Resize(model.constraint_size(), 0); -// RETURN_IF_XPRESS_ERROR(XPRSgetdblattrarray( -// xpress_model, XPRS_DBL_ATTR_PI, 0, model.constraint_size(), -// response.mutable_dual_value()->mutable_data())); -// } -// const int additional_solutions = std::min( -// solution_count, std::min(request.populate_additional_solutions_up_to(), -// std::numeric_limits::max() - 1) + -// 1); -// for (int i = 1; i < additional_solutions; ++i) { -// RETURN_IF_XPRESS_ERROR( -// XPRSsetintparam(model_env, XPRS_INT_PAR_SOLUTIONNUMBER, i)); -// MPSolution* solution = response.add_additional_solutions(); -// solution->mutable_variable_value()->Resize(variable_size, 0); -// double objective_value = 0; -// RETURN_IF_XPRESS_ERROR(XPRSgetdblattr( -// xpress_model, XPRS_DBL_ATTR_POOLOBJVAL, &objective_value)); -// solution->set_objective_value(objective_value); -// RETURN_IF_XPRESS_ERROR(XPRSgetdblattrarray( -// xpress_model, XPRS_DBL_ATTR_XN, 0, variable_size, -// solution->mutable_variable_value()->mutable_data())); -// round_values_of_integer_variables_fn(solution->mutable_variable_value()); -// } -// } -// #undef RETURN_IF_XPRESS_ERRORx(i), -// model.solution_hint().var_value(i))); -// } -// } - -// { -// std::vector ct_variables; -// std::vector ct_coefficients; -// for (int c = 0; c < model.constraint_size(); ++c) { -// const MPConstraintProto& constraint = model.constraint(c); -// const int size = constraint.var_index_size(); -// ct_variables.resize(size, 0); -// ct_coefficients.resize(size, 0); -// for (int i = 0; i < size; ++i) { -// ct_variables[i] = constraint.var_index(i); -// ct_coefficients[i] = constraint.coefficient(i); -// } -// // Using XPRSaddrangeconstr for constraints that don't require it adds -// // a slack which is not always removed by presolve. -// if (constraint.lower_bound() == constraint.upper_bound()) { -// RETURN_IF_XPRESS_ERROR(XPRSaddconstr( -// xpress_model, /*numnz=*/size, /*cind=*/ct_variables.data(), -// /*cval=*/ct_coefficients.data(), -// /*sense=*/XPRS_EQUAL, /*rhs=*/constraint.lower_bound(), -// /*constrname=*/constraint.name().c_str())); -// } else if (constraint.lower_bound() == -// -std::numeric_limits::infinity()) { -// RETURN_IF_XPRESS_ERROR(XPRSaddconstr( -// xpress_model, /*numnz=*/size, /*cind=*/ct_variables.data(), -// /*cval=*/ct_coefficients.data(), -// /*sense=*/XPRS_LESS_EQUAL, /*rhs=*/constraint.upper_bound(), -// /*constrname=*/constraint.name().c_str())); -// } else if (constraint.upper_bound() == -// std::numeric_limits::infinity()) { -// RETURN_IF_XPRESS_ERROR(XPRSaddconstr( -// xpress_model, /*numnz=*/size, /*cind=*/ct_variables.data(), -// /*cval=*/ct_coefficients.data(), -// /*sense=*/XPRS_GREATER_EQUAL, /*rhs=*/constraint.lower_bound(), -// /*constrname=*/constraint.name().c_str())); -// } else { -// RETURN_IF_XPRESS_ERROR(XPRSaddrangeconstr( -// xpress_model, /*numnz=*/size, /*cind=*/ct_variables.data(), -// /*cval=*/ct_coefficients.data(), -// /*lower=*/constraint.lower_bound(), -// /*upper=*/constraint.upper_bound(), -// /*constrname=*/constraint.name().c_str())); -// } -// } - -// for (const auto& gen_cst : model.general_constraint()) { -// switch (gen_cst.general_constraint_case()) { -// case MPGeneralConstraintProto::kIndicatorConstraint: { -// RETURN_IF_XPRESS_ERROR(AddIndicatorConstraint( -// gen_cst, xpress_model, &ct_variables, &ct_coefficients)); -// break; -// } -// case MPGeneralConstraintProto::kSosConstraint: { -// RETURN_IF_XPRESS_ERROR(AddSosConstraint(gen_cst.sos_constraint(), -// xpress_model, &ct_variables, -// &ct_coefficients)); -// break; -// } -// case MPGeneralConstraintProto::kQuadraticConstraint: { -// RETURN_IF_XPRESS_ERROR(AddQuadraticConstraint(gen_cst, xpress_model)); -// break; -// } -// case MPGeneralConstraintProto::kAbsConstraint: { -// RETURN_IF_XPRESS_ERROR(XPRSaddgenconstrAbs( -// xpress_model, -// /*name=*/gen_cst.name().c_str(), -// /*resvar=*/gen_cst.abs_constraint().resultant_var_index(), -// /*argvar=*/gen_cst.abs_constraint().var_index())); -// break; -// } -// case MPGeneralConstraintProto::kAndConstraint: { -// RETURN_IF_XPRESS_ERROR( -// AddAndConstraint(gen_cst, xpress_model, &ct_variables)); -// break; -// } -// case MPGeneralConstraintProto::kOrConstraint: { -// RETURN_IF_XPRESS_ERROR( -// AddOrConstraint(gen_cst, xpress_model, &ct_variables)); -// break; -// } -// case MPGeneralConstraintProto::kMinConstraint: { -// RETURN_IF_XPRESS_ERROR( -// AddMinConstraint(gen_cst, xpress_model, &ct_variables)); -// break; -// } -// case MPGeneralConstraintProto::kMaxConstraint: { -// RETURN_IF_XPRESS_ERROR( -// AddMaxConstraint(gen_cst, xpress_model, &ct_variables)); -// break; -// } -// default: -// return absl::UnimplementedError( -// absl::StrFormat("General constraints of type %i not supported.", -// gen_cst.general_constraint_case())); -// } -// } -// } - -// RETURN_IF_XPRESS_ERROR(XPRSsetintattr(xpress_model, XPRS_INT_ATTR_MODELSENSE, -// model.maximize() ? -1 : 1)); -// RETURN_IF_XPRESS_ERROR(XPRSsetdblattr(xpress_model, XPRS_DBL_ATTR_OBJCON, -// model.objective_offset())); -// if (model.has_quadratic_objective()) { -// MPQuadraticObjective qobj = model.quadratic_objective(); -// if (qobj.coefficient_size() > 0) { -// RETURN_IF_XPRESS_ERROR( -// XPRSaddqpterms(xpress_model, /*numqnz=*/qobj.coefficient_size(), -// /*qrow=*/qobj.mutable_qvar1_index()->mutable_data(), -// /*qcol=*/qobj.mutable_qvar2_index()->mutable_data(), -// /*qval=*/qobj.mutable_coefficient()->mutable_data())); -// } -// } - -// RETURN_IF_XPRESS_ERROR(XPRSupdatemodel(xpress_model)); - -// const absl::Time time_before = absl::Now(); -// UserTimer user_timer; -// user_timer.Start(); - -// RETURN_IF_XPRESS_ERROR(XPRSoptimize(xpress_model)); - -// const absl::Duration solving_duration = absl::Now() - time_before; -// user_timer.Stop(); -// VLOG(1) << "Finished solving in XPressSolveProto(), walltime = " -// << solving_duration << ", usertime = " << user_timer.GetDuration(); -// response.mutable_solve_info()->set_solve_wall_time_seconds( -// absl::ToDoubleSeconds(solving_duration)); -// response.mutable_solve_info()->set_solve_user_time_seconds( -// absl::ToDoubleSeconds(user_timer.GetDuration())); - -// int optimization_status = 0; -// RETURN_IF_XPRESS_ERROR( -// XPRSgetintattr(xpress_model, XPRS_INT_ATTR_STATUS, &optimization_status)); -// int solution_count = 0; -// RETURN_IF_XPRESS_ERROR( -// XPRSgetintattr(xpress_model, XPRS_INT_ATTR_SOLCOUNT, &solution_count)); -// switch (optimization_status) { -// case XPRS_OPTIMAL: -// response.set_status(MPSOLVER_OPTIMAL); -// break; -// case XPRS_INF_OR_UNBD: -// DLOG(INFO) << "XPress solve returned XPRS_INF_OR_UNBD, which we treat as " -// "INFEASIBLE even though it may mean UNBOUNDED."; -// response.set_status_str( -// "The model may actually be unbounded: XPress returned " -// "XPRS_INF_OR_UNBD"); -// ABSL_FALLTHROUGH_INTENDED; -// case XPRS_INFEASIBLE: -// response.set_status(MPSOLVER_INFEASIBLE); -// break; -// case XPRS_UNBOUNDED: -// response.set_status(MPSOLVER_UNBOUNDED); -// break; -// default: { -// if (solution_count > 0) { -// response.set_status(MPSOLVER_FEASIBLE); -// } else { -// response.set_status(MPSOLVER_NOT_SOLVED); -// response.set_status_str( -// absl::StrFormat("XPress status code %d", optimization_status)); -// } -// break; -// } -// } - -// if (solution_count > 0 && (response.status() == MPSOLVER_FEASIBLE || -// response.status() == MPSOLVER_OPTIMAL)) { -// double objective_value = 0; -// RETURN_IF_XPRESS_ERROR( -// XPRSgetdblattr(xpress_model, XPRS_DBL_ATTR_OBJVAL, &objective_value)); -// response.set_objective_value(objective_value); -// double best_objective_bound = 0; -// const int error = XPRSgetdblattr(xpress_model, XPRS_DBL_ATTR_OBJBOUND, -// &best_objective_bound); -// if (response.status() == MPSOLVER_OPTIMAL && -// error == XPRS_ERROR_DATA_NOT_AVAILABLE) { -// // If the presolve deletes all variables, there's no best bound. -// response.set_best_objective_bound(objective_value); -// } else { -// RETURN_IF_XPRESS_ERROR(error); -// response.set_best_objective_bound(best_objective_bound); -// } - -// response.mutable_variable_value()->Resize(variable_size, 0); -// RETURN_IF_XPRESS_ERROR( -// XPRSgetdblattrarray(xpress_model, XPRS_DBL_ATTR_X, 0, variable_size, -// response.mutable_variable_value()->mutable_data())); -// // NOTE, XPressSolveProto() is exposed to external clients via MPSolver API, -// // which assumes the solution values of integer variables are rounded to -// // integer values. -// auto round_values_of_integer_variables_fn = -// [&](google::protobuf::RepeatedField* values) { -// for (int v = 0; v < variable_size; ++v) { -// if (model.variable(v).is_integer()) { -// (*values)[v] = std::round((*values)[v]); -// } -// } -// }; -// round_values_of_integer_variables_fn(response.mutable_variable_value()); -// if (!has_integer_variables && model.general_constraint_size() == 0) { -// response.mutable_dual_value()->Resize(model.constraint_size(), 0); -// RETURN_IF_XPRESS_ERROR(XPRSgetdblattrarray( -// xpress_model, XPRS_DBL_ATTR_PI, 0, model.constraint_size(), -// response.mutable_dual_value()->mutable_data())); -// } -// const int additional_solutions = std::min( -// solution_count, std::min(request.populate_additional_solutions_up_to(), -// std::numeric_limits::max() - 1) + -// 1); -// for (int i = 1; i < additional_solutions; ++i) { -// RETURN_IF_XPRESS_ERROR( -// XPRSsetintparam(model_env, XPRS_INT_PAR_SOLUTIONNUMBER, i)); -// MPSolution* solution = response.add_additional_solutions(); -// solution->mutable_variable_value()->Resize(variable_size, 0); -// double objective_value = 0; -// RETURN_IF_XPRESS_ERROR(XPRSgetdblattr( -// xpress_model, XPRS_DBL_ATTR_POOLOBJVAL, &objective_value)); -// solution->set_objective_value(objective_value); -// RETURN_IF_XPRESS_ERROR(XPRSgetdblattrarray( -// xpress_model, XPRS_DBL_ATTR_XN, 0, variable_size, -// solution->mutable_variable_value()->mutable_data())); -// round_values_of_integer_variables_fn(solution->mutable_variable_value()); -// } -// } -// #undef RETURN_IF_XPRESS_ERROR + // RETURN_IF_XPRESS_ERROR(XPRSnewmodel(xpress_env, &xpress_model, + // model.name().c_str(), + // /*numvars=*/0, + // /*obj=*/nullptr, + // /*lb=*/nullptr, + // /*ub=*/nullptr, + // /*vtype=*/nullptr, + // /*varnames=*/nullptr)); + // XPRSprob const model_env = XPRSgetenv(xpress_model); + + // if (request.has_solver_specific_parameters()) { + // const auto parameters_status = SetSolverSpecificParameters( + // request.solver_specific_parameters(), model_env); + // if (!parameters_status.ok()) { + // response.set_status(MPSOLVER_MODEL_INVALID_SOLVER_PARAMETERS); + // response.set_status_str( + // std::string(parameters_status.message())); // NOLINT + // return response; + // } + // } + // if (request.solver_time_limit_seconds() > 0) { + // RETURN_IF_XPRESS_ERROR( + // XPRSsetdblparam(model_env, XPRS_DBL_PAR_TIMELIMIT, + // request.solver_time_limit_seconds())); + // } + // RETURN_IF_XPRESS_ERROR( + // XPRSsetintparam(model_env, XPRS_INT_PAR_OUTPUTFLAG, + // request.enable_internal_solver_output())); + + // const int variable_size = model.variable_size(); + // bool has_integer_variables = false; + // { + // std::vector obj_coeffs(variable_size, 0); + // std::vector lb(variable_size); + // std::vector ub(variable_size); + // std::vector ctype(variable_size); + // std::vector varnames(variable_size); + // for (int v = 0; v < variable_size; ++v) { + // const MPVariableProto& variable = model.variable(v); + // obj_coeffs[v] = variable.objective_coefficient(); + // lb[v] = variable.lower_bound(); + // ub[v] = variable.upper_bound(); + // ctype[v] = variable.is_integer() && + // request.solver_type() == + // MPModelRequest::XPRESS_MIXED_INTEGER_PROGRAMMING + // ? XPRS_INTEGER + // : XPRS_CONTINUOUS; + // if (variable.is_integer()) has_integer_variables = true; + // if (!variable.name().empty()) varnames[v] = variable.name().c_str(); + // } + + // RETURN_IF_XPRESS_ERROR( + // XPRSaddvars(xpress_model, variable_size, 0, nullptr, nullptr, + // nullptr, + // /*obj=*/obj_coeffs.data(), + // /*lb=*/lb.data(), /*ub=*/ub.data(), + // /*vtype=*/ctype.data(), + // /*varnames=*/const_cast(varnames.data()))); + + // // Set solution hints if any. + // for (int i = 0; i < model.solution_hint().var_index_size(); ++i) { + // RETURN_IF_XPRESS_ERROR(XPRSsetdblattrelement( + // xpress_model, XPRS_DBL_ATTR_START, + // model.solution_hint().var_index(i), + // model.solution_hint().var_value(i))); + // } + // } + + // { + // std::vector ct_variables; + // std::vector ct_coefficients; + // for (int c = 0; c < model.constraint_size(); ++c) { + // const MPConstraintProto& constraint = model.constraint(c); + // const int size = constraint.var_index_size(); + // ct_variables.resize(size, 0); + // ct_coefficients.resize(size, 0); + // for (int i = 0; i < size; ++i) { + // ct_variables[i] = constraint.var_index(i); + // ct_coefficients[i] = constraint.coefficient(i); + // } + // // Using XPRSaddrangeconstr for constraints that don't require it + // adds + // // a slack which is not always removed by presolve. + // if (constraint.lower_bound() == constraint.upper_bound()) { + // RETURN_IF_XPRESS_ERROR(XPRSaddconstr( + // xpress_model, /*numnz=*/size, /*cind=*/ct_variables.data(), + // /*cval=*/ct_coefficients.data(), + // /*sense=*/XPRS_EQUAL, /*rhs=*/constraint.lower_bound(), + // /*constrname=*/constraint.name().c_str())); + // } else if (constraint.lower_bound() == + // -std::numeric_limits::infinity()) { + // RETURN_IF_XPRESS_ERROR(XPRSaddconstr( + // xpress_model, /*numnz=*/size, /*cind=*/ct_variables.data(), + // /*cval=*/ct_coefficients.data(), + // /*sense=*/XPRS_LESS_EQUAL, /*rhs=*/constraint.upper_bound(), + // /*constrname=*/constraint.name().c_str())); + // } else if (constraint.upper_bound() == + // std::numeric_limits::infinity()) { + // RETURN_IF_XPRESS_ERROR(XPRSaddconstr( + // xpress_model, /*numnz=*/size, /*cind=*/ct_variables.data(), + // /*cval=*/ct_coefficients.data(), + // /*sense=*/XPRS_GREATER_EQUAL, /*rhs=*/constraint.lower_bound(), + // /*constrname=*/constraint.name().c_str())); + // } else { + // RETURN_IF_XPRESS_ERROR(XPRSaddrangeconstr( + // xpress_model, /*numnz=*/size, /*cind=*/ct_variables.data(), + // /*cval=*/ct_coefficients.data(), + // /*lower=*/constraint.lower_bound(), + // /*upper=*/constraint.upper_bound(), + // /*constrname=*/constraint.name().c_str())); + // } + // } + + // for (const auto& gen_cst : model.general_constraint()) { + // switch (gen_cst.general_constraint_case()) { + // case MPGeneralConstraintProto::kIndicatorConstraint: { + // RETURN_IF_XPRESS_ERROR(AddIndicatorConstraint( + // gen_cst, xpress_model, &ct_variables, &ct_coefficients)); + // break; + // } + // case MPGeneralConstraintProto::kSosConstraint: { + // RETURN_IF_XPRESS_ERROR(AddSosConstraint(gen_cst.sos_constraint(), + // xpress_model, + // &ct_variables, + // &ct_coefficients)); + // break; + // } + // case MPGeneralConstraintProto::kQuadraticConstraint: { + // RETURN_IF_XPRESS_ERROR(AddQuadraticConstraint(gen_cst, + // xpress_model)); break; + // } + // case MPGeneralConstraintProto::kAbsConstraint: { + // RETURN_IF_XPRESS_ERROR(XPRSaddgenconstrAbs( + // xpress_model, + // /*name=*/gen_cst.name().c_str(), + // /*resvar=*/gen_cst.abs_constraint().resultant_var_index(), + // /*argvar=*/gen_cst.abs_constraint().var_index())); + // break; + // } + // case MPGeneralConstraintProto::kAndConstraint: { + // RETURN_IF_XPRESS_ERROR( + // AddAndConstraint(gen_cst, xpress_model, &ct_variables)); + // break; + // } + // case MPGeneralConstraintProto::kOrConstraint: { + // RETURN_IF_XPRESS_ERROR( + // AddOrConstraint(gen_cst, xpress_model, &ct_variables)); + // break; + // } + // case MPGeneralConstraintProto::kMinConstraint: { + // RETURN_IF_XPRESS_ERROR( + // AddMinConstraint(gen_cst, xpress_model, &ct_variables)); + // break; + // } + // case MPGeneralConstraintProto::kMaxConstraint: { + // RETURN_IF_XPRESS_ERROR( + // AddMaxConstraint(gen_cst, xpress_model, &ct_variables)); + // break; + // } + // default: + // return absl::UnimplementedError( + // absl::StrFormat("General constraints of type %i not + // supported.", + // gen_cst.general_constraint_case())); + // } + // } + // } + + // RETURN_IF_XPRESS_ERROR(XPRSsetintattr(xpress_model, + // XPRS_INT_ATTR_MODELSENSE, + // model.maximize() ? -1 : 1)); + // RETURN_IF_XPRESS_ERROR(XPRSsetdblattr(xpress_model, XPRS_DBL_ATTR_OBJCON, + // model.objective_offset())); + // if (model.has_quadratic_objective()) { + // MPQuadraticObjective qobj = model.quadratic_objective(); + // if (qobj.coefficient_size() > 0) { + // RETURN_IF_XPRESS_ERROR( + // XPRSaddqpterms(xpress_model, /*numqnz=*/qobj.coefficient_size(), + // /*qrow=*/qobj.mutable_qvar1_index()->mutable_data(), + // /*qcol=*/qobj.mutable_qvar2_index()->mutable_data(), + // /*qval=*/qobj.mutable_coefficient()->mutable_data())); + // } + // } + + // RETURN_IF_XPRESS_ERROR(XPRSupdatemodel(xpress_model)); + + // const absl::Time time_before = absl::Now(); + // UserTimer user_timer; + // user_timer.Start(); + + // RETURN_IF_XPRESS_ERROR(XPRSoptimize(xpress_model)); + + // const absl::Duration solving_duration = absl::Now() - time_before; + // user_timer.Stop(); + // VLOG(1) << "Finished solving in XPressSolveProto(), walltime = " + // << solving_duration << ", usertime = " << + // user_timer.GetDuration(); + // response.mutable_solve_info()->set_solve_wall_time_seconds( + // absl::ToDoubleSeconds(solving_duration)); + // response.mutable_solve_info()->set_solve_user_time_seconds( + // absl::ToDoubleSeconds(user_timer.GetDuration())); + + // int optimization_status = 0; + // RETURN_IF_XPRESS_ERROR( + // XPRSgetintattr(xpress_model, XPRS_INT_ATTR_STATUS, + // &optimization_status)); + // int solution_count = 0; + // RETURN_IF_XPRESS_ERROR( + // XPRSgetintattr(xpress_model, XPRS_INT_ATTR_SOLCOUNT, + // &solution_count)); + // switch (optimization_status) { + // case XPRS_OPTIMAL: + // response.set_status(MPSOLVER_OPTIMAL); + // break; + // case XPRS_INF_OR_UNBD: + // DLOG(INFO) << "XPress solve returned XPRS_INF_OR_UNBD, which we treat + // as " + // "INFEASIBLE even though it may mean UNBOUNDED."; + // response.set_status_str( + // "The model may actually be unbounded: XPress returned " + // "XPRS_INF_OR_UNBD"); + // ABSL_FALLTHROUGH_INTENDED; + // case XPRS_INFEASIBLE: + // response.set_status(MPSOLVER_INFEASIBLE); + // break; + // case XPRS_UNBOUNDED: + // response.set_status(MPSOLVER_UNBOUNDED); + // break; + // default: { + // if (solution_count > 0) { + // response.set_status(MPSOLVER_FEASIBLE); + // } else { + // response.set_status(MPSOLVER_NOT_SOLVED); + // response.set_status_str( + // absl::StrFormat("XPress status code %d", optimization_status)); + // } + // break; + // } + // } + + // if (solution_count > 0 && (response.status() == MPSOLVER_FEASIBLE || + // response.status() == MPSOLVER_OPTIMAL)) { + // double objective_value = 0; + // RETURN_IF_XPRESS_ERROR( + // XPRSgetdblattr(xpress_model, XPRS_DBL_ATTR_OBJVAL, + // &objective_value)); + // response.set_objective_value(objective_value); + // double best_objective_bound = 0; + // const int error = XPRSgetdblattr(xpress_model, XPRS_DBL_ATTR_OBJBOUND, + // &best_objective_bound); + // if (response.status() == MPSOLVER_OPTIMAL && + // error == XPRS_ERROR_DATA_NOT_AVAILABLE) { + // // If the presolve deletes all variables, there's no best bound. + // response.set_best_objective_bound(objective_value); + // } else { + // RETURN_IF_XPRESS_ERROR(error); + // response.set_best_objective_bound(best_objective_bound); + // } + + // response.mutable_variable_value()->Resize(variable_size, 0); + // RETURN_IF_XPRESS_ERROR( + // XPRSgetdblattrarray(xpress_model, XPRS_DBL_ATTR_X, 0, + // variable_size, + // response.mutable_variable_value()->mutable_data())); + // // NOTE, XPressSolveProto() is exposed to external clients via MPSolver + // API, + // // which assumes the solution values of integer variables are rounded + // to + // // integer values. + // auto round_values_of_integer_variables_fn = + // [&](google::protobuf::RepeatedField* values) { + // for (int v = 0; v < variable_size; ++v) { + // if (model.variable(v).is_integer()) { + // (*values)[v] = std::round((*values)[v]); + // } + // } + // }; + // round_values_of_integer_variables_fn(response.mutable_variable_value()); + // if (!has_integer_variables && model.general_constraint_size() == 0) { + // response.mutable_dual_value()->Resize(model.constraint_size(), 0); + // RETURN_IF_XPRESS_ERROR(XPRSgetdblattrarray( + // xpress_model, XPRS_DBL_ATTR_PI, 0, model.constraint_size(), + // response.mutable_dual_value()->mutable_data())); + // } + // const int additional_solutions = std::min( + // solution_count, + // std::min(request.populate_additional_solutions_up_to(), + // std::numeric_limits::max() - 1) + + // 1); + // for (int i = 1; i < additional_solutions; ++i) { + // RETURN_IF_XPRESS_ERROR( + // XPRSsetintparam(model_env, XPRS_INT_PAR_SOLUTIONNUMBER, i)); + // MPSolution* solution = response.add_additional_solutions(); + // solution->mutable_variable_value()->Resize(variable_size, 0); + // double objective_value = 0; + // RETURN_IF_XPRESS_ERROR(XPRSgetdblattr( + // xpress_model, XPRS_DBL_ATTR_POOLOBJVAL, &objective_value)); + // solution->set_objective_value(objective_value); + // RETURN_IF_XPRESS_ERROR(XPRSgetdblattrarray( + // xpress_model, XPRS_DBL_ATTR_XN, 0, variable_size, + // solution->mutable_variable_value()->mutable_data())); + // round_values_of_integer_variables_fn(solution->mutable_variable_value()); + // } + // } + // #undef RETURN_IF_XPRESS_ERRORx(i), + // model.solution_hint().var_value(i))); + // } + // } + + // { + // std::vector ct_variables; + // std::vector ct_coefficients; + // for (int c = 0; c < model.constraint_size(); ++c) { + // const MPConstraintProto& constraint = model.constraint(c); + // const int size = constraint.var_index_size(); + // ct_variables.resize(size, 0); + // ct_coefficients.resize(size, 0); + // for (int i = 0; i < size; ++i) { + // ct_variables[i] = constraint.var_index(i); + // ct_coefficients[i] = constraint.coefficient(i); + // } + // // Using XPRSaddrangeconstr for constraints that don't require it + // adds + // // a slack which is not always removed by presolve. + // if (constraint.lower_bound() == constraint.upper_bound()) { + // RETURN_IF_XPRESS_ERROR(XPRSaddconstr( + // xpress_model, /*numnz=*/size, /*cind=*/ct_variables.data(), + // /*cval=*/ct_coefficients.data(), + // /*sense=*/XPRS_EQUAL, /*rhs=*/constraint.lower_bound(), + // /*constrname=*/constraint.name().c_str())); + // } else if (constraint.lower_bound() == + // -std::numeric_limits::infinity()) { + // RETURN_IF_XPRESS_ERROR(XPRSaddconstr( + // xpress_model, /*numnz=*/size, /*cind=*/ct_variables.data(), + // /*cval=*/ct_coefficients.data(), + // /*sense=*/XPRS_LESS_EQUAL, /*rhs=*/constraint.upper_bound(), + // /*constrname=*/constraint.name().c_str())); + // } else if (constraint.upper_bound() == + // std::numeric_limits::infinity()) { + // RETURN_IF_XPRESS_ERROR(XPRSaddconstr( + // xpress_model, /*numnz=*/size, /*cind=*/ct_variables.data(), + // /*cval=*/ct_coefficients.data(), + // /*sense=*/XPRS_GREATER_EQUAL, /*rhs=*/constraint.lower_bound(), + // /*constrname=*/constraint.name().c_str())); + // } else { + // RETURN_IF_XPRESS_ERROR(XPRSaddrangeconstr( + // xpress_model, /*numnz=*/size, /*cind=*/ct_variables.data(), + // /*cval=*/ct_coefficients.data(), + // /*lower=*/constraint.lower_bound(), + // /*upper=*/constraint.upper_bound(), + // /*constrname=*/constraint.name().c_str())); + // } + // } + + // for (const auto& gen_cst : model.general_constraint()) { + // switch (gen_cst.general_constraint_case()) { + // case MPGeneralConstraintProto::kIndicatorConstraint: { + // RETURN_IF_XPRESS_ERROR(AddIndicatorConstraint( + // gen_cst, xpress_model, &ct_variables, &ct_coefficients)); + // break; + // } + // case MPGeneralConstraintProto::kSosConstraint: { + // RETURN_IF_XPRESS_ERROR(AddSosConstraint(gen_cst.sos_constraint(), + // xpress_model, + // &ct_variables, + // &ct_coefficients)); + // break; + // } + // case MPGeneralConstraintProto::kQuadraticConstraint: { + // RETURN_IF_XPRESS_ERROR(AddQuadraticConstraint(gen_cst, + // xpress_model)); break; + // } + // case MPGeneralConstraintProto::kAbsConstraint: { + // RETURN_IF_XPRESS_ERROR(XPRSaddgenconstrAbs( + // xpress_model, + // /*name=*/gen_cst.name().c_str(), + // /*resvar=*/gen_cst.abs_constraint().resultant_var_index(), + // /*argvar=*/gen_cst.abs_constraint().var_index())); + // break; + // } + // case MPGeneralConstraintProto::kAndConstraint: { + // RETURN_IF_XPRESS_ERROR( + // AddAndConstraint(gen_cst, xpress_model, &ct_variables)); + // break; + // } + // case MPGeneralConstraintProto::kOrConstraint: { + // RETURN_IF_XPRESS_ERROR( + // AddOrConstraint(gen_cst, xpress_model, &ct_variables)); + // break; + // } + // case MPGeneralConstraintProto::kMinConstraint: { + // RETURN_IF_XPRESS_ERROR( + // AddMinConstraint(gen_cst, xpress_model, &ct_variables)); + // break; + // } + // case MPGeneralConstraintProto::kMaxConstraint: { + // RETURN_IF_XPRESS_ERROR( + // AddMaxConstraint(gen_cst, xpress_model, &ct_variables)); + // break; + // } + // default: + // return absl::UnimplementedError( + // absl::StrFormat("General constraints of type %i not + // supported.", + // gen_cst.general_constraint_case())); + // } + // } + // } + + // RETURN_IF_XPRESS_ERROR(XPRSsetintattr(xpress_model, + // XPRS_INT_ATTR_MODELSENSE, + // model.maximize() ? -1 : 1)); + // RETURN_IF_XPRESS_ERROR(XPRSsetdblattr(xpress_model, XPRS_DBL_ATTR_OBJCON, + // model.objective_offset())); + // if (model.has_quadratic_objective()) { + // MPQuadraticObjective qobj = model.quadratic_objective(); + // if (qobj.coefficient_size() > 0) { + // RETURN_IF_XPRESS_ERROR( + // XPRSaddqpterms(xpress_model, /*numqnz=*/qobj.coefficient_size(), + // /*qrow=*/qobj.mutable_qvar1_index()->mutable_data(), + // /*qcol=*/qobj.mutable_qvar2_index()->mutable_data(), + // /*qval=*/qobj.mutable_coefficient()->mutable_data())); + // } + // } + + // RETURN_IF_XPRESS_ERROR(XPRSupdatemodel(xpress_model)); + + // const absl::Time time_before = absl::Now(); + // UserTimer user_timer; + // user_timer.Start(); + + // RETURN_IF_XPRESS_ERROR(XPRSoptimize(xpress_model)); + + // const absl::Duration solving_duration = absl::Now() - time_before; + // user_timer.Stop(); + // VLOG(1) << "Finished solving in XPressSolveProto(), walltime = " + // << solving_duration << ", usertime = " << + // user_timer.GetDuration(); + // response.mutable_solve_info()->set_solve_wall_time_seconds( + // absl::ToDoubleSeconds(solving_duration)); + // response.mutable_solve_info()->set_solve_user_time_seconds( + // absl::ToDoubleSeconds(user_timer.GetDuration())); + + // int optimization_status = 0; + // RETURN_IF_XPRESS_ERROR( + // XPRSgetintattr(xpress_model, XPRS_INT_ATTR_STATUS, + // &optimization_status)); + // int solution_count = 0; + // RETURN_IF_XPRESS_ERROR( + // XPRSgetintattr(xpress_model, XPRS_INT_ATTR_SOLCOUNT, + // &solution_count)); + // switch (optimization_status) { + // case XPRS_OPTIMAL: + // response.set_status(MPSOLVER_OPTIMAL); + // break; + // case XPRS_INF_OR_UNBD: + // DLOG(INFO) << "XPress solve returned XPRS_INF_OR_UNBD, which we treat + // as " + // "INFEASIBLE even though it may mean UNBOUNDED."; + // response.set_status_str( + // "The model may actually be unbounded: XPress returned " + // "XPRS_INF_OR_UNBD"); + // ABSL_FALLTHROUGH_INTENDED; + // case XPRS_INFEASIBLE: + // response.set_status(MPSOLVER_INFEASIBLE); + // break; + // case XPRS_UNBOUNDED: + // response.set_status(MPSOLVER_UNBOUNDED); + // break; + // default: { + // if (solution_count > 0) { + // response.set_status(MPSOLVER_FEASIBLE); + // } else { + // response.set_status(MPSOLVER_NOT_SOLVED); + // response.set_status_str( + // absl::StrFormat("XPress status code %d", optimization_status)); + // } + // break; + // } + // } + + // if (solution_count > 0 && (response.status() == MPSOLVER_FEASIBLE || + // response.status() == MPSOLVER_OPTIMAL)) { + // double objective_value = 0; + // RETURN_IF_XPRESS_ERROR( + // XPRSgetdblattr(xpress_model, XPRS_DBL_ATTR_OBJVAL, + // &objective_value)); + // response.set_objective_value(objective_value); + // double best_objective_bound = 0; + // const int error = XPRSgetdblattr(xpress_model, XPRS_DBL_ATTR_OBJBOUND, + // &best_objective_bound); + // if (response.status() == MPSOLVER_OPTIMAL && + // error == XPRS_ERROR_DATA_NOT_AVAILABLE) { + // // If the presolve deletes all variables, there's no best bound. + // response.set_best_objective_bound(objective_value); + // } else { + // RETURN_IF_XPRESS_ERROR(error); + // response.set_best_objective_bound(best_objective_bound); + // } + + // response.mutable_variable_value()->Resize(variable_size, 0); + // RETURN_IF_XPRESS_ERROR( + // XPRSgetdblattrarray(xpress_model, XPRS_DBL_ATTR_X, 0, + // variable_size, + // response.mutable_variable_value()->mutable_data())); + // // NOTE, XPressSolveProto() is exposed to external clients via MPSolver + // API, + // // which assumes the solution values of integer variables are rounded + // to + // // integer values. + // auto round_values_of_integer_variables_fn = + // [&](google::protobuf::RepeatedField* values) { + // for (int v = 0; v < variable_size; ++v) { + // if (model.variable(v).is_integer()) { + // (*values)[v] = std::round((*values)[v]); + // } + // } + // }; + // round_values_of_integer_variables_fn(response.mutable_variable_value()); + // if (!has_integer_variables && model.general_constraint_size() == 0) { + // response.mutable_dual_value()->Resize(model.constraint_size(), 0); + // RETURN_IF_XPRESS_ERROR(XPRSgetdblattrarray( + // xpress_model, XPRS_DBL_ATTR_PI, 0, model.constraint_size(), + // response.mutable_dual_value()->mutable_data())); + // } + // const int additional_solutions = std::min( + // solution_count, + // std::min(request.populate_additional_solutions_up_to(), + // std::numeric_limits::max() - 1) + + // 1); + // for (int i = 1; i < additional_solutions; ++i) { + // RETURN_IF_XPRESS_ERROR( + // XPRSsetintparam(model_env, XPRS_INT_PAR_SOLUTIONNUMBER, i)); + // MPSolution* solution = response.add_additional_solutions(); + // solution->mutable_variable_value()->Resize(variable_size, 0); + // double objective_value = 0; + // RETURN_IF_XPRESS_ERROR(XPRSgetdblattr( + // xpress_model, XPRS_DBL_ATTR_POOLOBJVAL, &objective_value)); + // solution->set_objective_value(objective_value); + // RETURN_IF_XPRESS_ERROR(XPRSgetdblattrarray( + // xpress_model, XPRS_DBL_ATTR_XN, 0, variable_size, + // solution->mutable_variable_value()->mutable_data())); + // round_values_of_integer_variables_fn(solution->mutable_variable_value()); + // } + // } + // #undef RETURN_IF_XPRESS_ERROR return response; } diff --git a/ortools/linear_solver/wrappers/model_builder_helper.cc b/ortools/linear_solver/wrappers/model_builder_helper.cc index 59ed2816661..9c95d2b0deb 100644 --- a/ortools/linear_solver/wrappers/model_builder_helper.cc +++ b/ortools/linear_solver/wrappers/model_builder_helper.cc @@ -215,8 +215,8 @@ void ModelBuilderHelper::SafeAddConstraintTerm(int ct_index, int var_index, return; } } - // If we reach this point, the variable does not exist in the constraint yet, - // so we add it to the constraint as a new term. + // If we reach this point, the variable does not exist in the constraint + // yet, so we add it to the constraint as a new term. ct_proto->add_var_index(var_index); ct_proto->add_coefficient(coeff); } @@ -235,8 +235,8 @@ void ModelBuilderHelper::SetConstraintCoefficient(int ct_index, int var_index, return; } } - // If we reach this point, the variable does not exist in the constraint yet, - // so we add it to the constraint as a new term. + // If we reach this point, the variable does not exist in the constraint + // yet, so we add it to the constraint as a new term. ct_proto->add_var_index(var_index); ct_proto->add_coefficient(coeff); } @@ -328,8 +328,8 @@ void ModelBuilderHelper::SafeAddEnforcedConstraintTerm(int ct_index, return; } } - // If we reach this point, the variable does not exist in the constraint yet, - // so we add it to the constraint as a new term. + // If we reach this point, the variable does not exist in the constraint + // yet, so we add it to the constraint as a new term. ct_proto->add_var_index(var_index); ct_proto->add_coefficient(coeff); } @@ -352,8 +352,8 @@ void ModelBuilderHelper::SetEnforcedConstraintCoefficient(int ct_index, return; } } - // If we reach this point, the variable does not exist in the constraint yet, - // so we add it to the constraint as a new term. + // If we reach this point, the variable does not exist in the constraint + // yet, so we add it to the constraint as a new term. ct_proto->add_var_index(var_index); ct_proto->add_coefficient(coeff); } @@ -595,19 +595,21 @@ void ModelSolverHelper::Solve(const ModelBuilderHelper& model) { break; } #endif // defined(USE_PDLP) - case MPModelRequest::GUROBI_LINEAR_PROGRAMMING: // ABSL_FALLTHROUGH_INTENDED + case MPModelRequest:: + GUROBI_LINEAR_PROGRAMMING: // ABSL_FALLTHROUGH_INTENDED case MPModelRequest::GUROBI_MIXED_INTEGER_PROGRAMMING: { const auto temp = GurobiSolveProto(request); if (temp.ok()) { response_ = std::move(temp.value()); } + break; } - case MPModelRequest::XPRESS_LINEAR_PROGRAMMING: // ABSL_FALLTHROUGH_INTENDED + case MPModelRequest:: + XPRESS_LINEAR_PROGRAMMING: // ABSL_FALLTHROUGH_INTENDED case MPModelRequest::XPRESS_MIXED_INTEGER_PROGRAMMING: { response_ = XPressSolveProto(request); break; } - default: { response_->set_status( MPSolverResponseStatus::MPSOLVER_SOLVER_TYPE_UNAVAILABLE); diff --git a/ortools/linear_solver/xpress_interface.cc b/ortools/linear_solver/xpress_interface.cc index 0fa937c2a69..03d369bc8f9 100644 --- a/ortools/linear_solver/xpress_interface.cc +++ b/ortools/linear_solver/xpress_interface.cc @@ -277,7 +277,7 @@ class MPCallbackWrapper { for (const std::exception_ptr& ex : caught_exceptions_) { try { std::rethrow_exception(ex); - } catch (std::exception &ex) { + } catch (std::exception& ex) { // We don't want the interface to throw exceptions, plus it causes // SWIG issues in Java & Python. Instead, we'll only log them. // (The use cases where the user has to raise an exception inside their @@ -1466,13 +1466,13 @@ void XpressInterface::ExtractNewVariables() { CHECK_STATUS(XPRSaddcols(mLp, new_col_count, 0, obj.get(), cmatbeg.data(), cmatind.get(), cmatval.get(), lb.get(), ub.get())); - //TODO fixme - // Writing all names worsen the performance significantly - //if (have_names) { - // CHECK_STATUS(XPRSaddnames(mLp, XPRS_NAMES_COLUMN, col_names.data(), - // 0, - // new_col_count - 1)); - //} + // TODO fixme + // Writing all names worsen the performance significantly + // if (have_names) { + // CHECK_STATUS(XPRSaddnames(mLp, XPRS_NAMES_COLUMN, + // col_names.data(), 0, + // new_col_count - 1)); + // } int const cols = getnumcols(mLp); unique_ptr ind(new int[new_col_count]); for (int j = 0; j < cols; ++j) ind[j] = j; @@ -1735,7 +1735,7 @@ std::vector XpressBasisStatusesFrom( void XpressInterface::SetStartingLpBasis( const std::vector& variable_statuses, - const std::vector& constraint_statuses){ + const std::vector& constraint_statuses) { if (mMip) { LOG(DFATAL) << __FUNCTION__ << " is only available for LP problems"; return; @@ -1880,10 +1880,10 @@ MPSolver::ResultStatus XpressInterface::Solve(MPSolverParameters const& param) { int xpress_stat = 0; if (mMip) { - status = XPRSmipoptimize(mLp,""); + status = XPRSmipoptimize(mLp, ""); XPRSgetintattrib(mLp, XPRS_MIPSTATUS, &xpress_stat); } else { - status = XPRSlpoptimize(mLp,""); + status = XPRSlpoptimize(mLp, ""); XPRSgetintattrib(mLp, XPRS_LPSTATUS, &xpress_stat); } diff --git a/ortools/linear_solver/xpress_interface_test.cc b/ortools/linear_solver/xpress_interface_test.cc index e5c31d74ba1..fe2fe88030b 100644 --- a/ortools/linear_solver/xpress_interface_test.cc +++ b/ortools/linear_solver/xpress_interface_test.cc @@ -230,8 +230,7 @@ void buildLargeLp(MPSolver& solver, int numVars) { MPObjective* obj = solver.MutableObjective(); obj->SetMaximization(); for (int i = 0; i < numVars; ++i) { - MPVariable* x = solver.MakeNumVar(-(i * i) % 21, - (i * i) % 55, + MPVariable* x = solver.MakeNumVar(-(i * i) % 21, (i * i) % 55, "x_" + std::to_string(i)); obj->SetCoefficient(x, (i * i) % 23); int min = -50; @@ -344,7 +343,8 @@ TEST(XpressInterface, LpStartingBasisNoIterationsIfBasisIsProvided) { constrStatus.push_back(constr->basis_status()); } - MPSolver solver_BasisProvided("XPRESS_LP", MPSolver::XPRESS_LINEAR_PROGRAMMING); + MPSolver solver_BasisProvided("XPRESS_LP", + MPSolver::XPRESS_LINEAR_PROGRAMMING); buildLargeLp(solver_BasisProvided, 1000); solver_BasisProvided.SetStartingLpBasis(varStatus, constrStatus); solver_BasisProvided.Solve(); @@ -353,7 +353,6 @@ TEST(XpressInterface, LpStartingBasisNoIterationsIfBasisIsProvided) { EXPECT_EQ(iterWithBasis, 0); } - TEST(XpressInterface, NumVariables) { UNITTEST_INIT_MIP(); MPVariable* x1 = solver.MakeNumVar(-1., 5.1, "x1"); @@ -1315,7 +1314,6 @@ TEST(XpressInterface, SetHint) { } #endif - TEST(XpressInterface, SetCallBack) { UNITTEST_INIT_MIP(); @@ -1367,7 +1365,9 @@ TEST(XpressInterface, CallbackThrowsException) { EXPECT_NO_THROW(solver.Solve()); std::string errors = testing::internal::GetCapturedStderr(); // Test that StdErr contains the following error message - std::string expected_error = "Caught exception during user-defined call-back: This is a mocked exception in MyMPCallback"; + std::string expected_error = + "Caught exception during user-defined call-back: This is a mocked " + "exception in MyMPCallback"; ASSERT_NE(errors.find(expected_error), std::string::npos); } @@ -1380,8 +1380,7 @@ int main(int argc, char** argv) { if (solver == nullptr) { LOG(ERROR) << "Xpress solver is not available"; return EXIT_SUCCESS; - } - else{ + } else { return RUN_ALL_TESTS(); } }