diff --git a/bindings/AMPL/AMPLModel.cpp b/bindings/AMPL/AMPLModel.cpp index 37205fc3..9a272af0 100644 --- a/bindings/AMPL/AMPLModel.cpp +++ b/bindings/AMPL/AMPLModel.cpp @@ -12,6 +12,7 @@ #include "tools/Infinity.hpp" #include "options/Options.hpp" #include "symbolic/Concatenation.hpp" +#include "symbolic/ScalarMultiple.hpp" #include "symbolic/UnaryNegation.hpp" #include "Uno.hpp" @@ -354,7 +355,11 @@ namespace uno { std::copy(this->asl->i.pi0_, this->asl->i.pi0_ + this->number_constraints, multipliers.begin()); } - void AMPLModel::postprocess_solution(Iterate& iterate, TerminationStatus termination_status) const { + void AMPLModel::postprocess_solution(Iterate& /*iterate*/, TerminationStatus /*termination_status*/) const { + // do nothing + } + + void AMPLModel::terminate(Iterate& iterate, TerminationStatus termination_status) const { if (this->write_solution_to_file) { // write the primal-dual solution and status into a *.sol file this->asl->p.solve_code_ = 400; // limit @@ -373,11 +378,21 @@ namespace uno { else if (termination_status == TerminationStatus::INFEASIBLE_SMALL_STEP) { this->asl->p.solve_code_ = 500; } + + /* + SufDesc* tmp_lb = suf_get_ASL(this->asl, "uno_lower_bound_duals", ASL_Sufkind_var); + SufDesc* tmp_ub = suf_get_ASL(this->asl, "uno_upper_bound_duals", ASL_Sufkind_var); + suf_rput_ASL(this->asl, "uno_lower_bound_duals", ASL_Sufkind_var, iterate.multipliers.lower_bounds.data()); + suf_rput_ASL(this->asl, "uno_upper_bound_duals", ASL_Sufkind_var, iterate.multipliers.upper_bounds.data()); + */ + Option_Info option_info{}; option_info.wantsol = 9; // write the solution without printing the message to stdout std::string message = "Uno "; message.append(Uno::current_version()).append(": ").append(status_to_message(termination_status)); - write_sol_ASL(this->asl, message.data(), iterate.primals.data(), iterate.multipliers.constraints.data(), &option_info); + // flip the signs of the multipliers if we maximize + this->multipliers_with_flipped_sign = this->objective_sign * iterate.multipliers.constraints; + write_sol_ASL(this->asl, message.data(), iterate.primals.data(), this->multipliers_with_flipped_sign.data(), &option_info); } } diff --git a/bindings/AMPL/AMPLModel.hpp b/bindings/AMPL/AMPLModel.hpp index da7220d5..3700c3d2 100644 --- a/bindings/AMPL/AMPLModel.hpp +++ b/bindings/AMPL/AMPLModel.hpp @@ -58,6 +58,7 @@ namespace uno { void initial_primal_point(Vector& x) const override; void initial_dual_point(Vector& multipliers) const override; void postprocess_solution(Iterate& iterate, TerminationStatus termination_status) const override; + void terminate(Iterate& iterate, TerminationStatus termination_status) const override; [[nodiscard]] size_t number_objective_gradient_nonzeros() const override; [[nodiscard]] size_t number_jacobian_nonzeros() const override; diff --git a/bindings/AMPL/uno_ampl.cpp b/bindings/AMPL/uno_ampl.cpp index 69711ccb..a0fef175 100644 --- a/bindings/AMPL/uno_ampl.cpp +++ b/bindings/AMPL/uno_ampl.cpp @@ -48,6 +48,7 @@ namespace uno { // solve the instance Result result = uno.solve(*model, initial_iterate, options); uno.print_optimization_summary(result); + model->terminate(result.solution, result.solution.status); // std::cout << "memory_allocation_amount = " << memory_allocation_amount << '\n'; } catch (std::exception& exception) { diff --git a/uno/model/BoundRelaxedModel.hpp b/uno/model/BoundRelaxedModel.hpp index 14bccea1..5c31ec29 100644 --- a/uno/model/BoundRelaxedModel.hpp +++ b/uno/model/BoundRelaxedModel.hpp @@ -54,6 +54,9 @@ namespace uno { void postprocess_solution(Iterate& iterate, TerminationStatus termination_status) const override { this->model->postprocess_solution(iterate, termination_status); } + void terminate(Iterate& iterate, TerminationStatus termination_status) const override { + this->model->terminate(iterate, termination_status); + } [[nodiscard]] size_t number_objective_gradient_nonzeros() const override { return this->model->number_objective_gradient_nonzeros(); } [[nodiscard]] size_t number_jacobian_nonzeros() const override { return this->model->number_jacobian_nonzeros(); } diff --git a/uno/model/HomogeneousEqualityConstrainedModel.hpp b/uno/model/HomogeneousEqualityConstrainedModel.hpp index 56c23891..6f3c5a16 100644 --- a/uno/model/HomogeneousEqualityConstrainedModel.hpp +++ b/uno/model/HomogeneousEqualityConstrainedModel.hpp @@ -49,6 +49,9 @@ namespace uno { void initial_primal_point(Vector& x) const override; void initial_dual_point(Vector& multipliers) const override { this->model->initial_dual_point(multipliers); } void postprocess_solution(Iterate& iterate, TerminationStatus termination_status) const override; + void terminate(Iterate& iterate, TerminationStatus termination_status) const override { + this->model->terminate(iterate, termination_status); + } [[nodiscard]] size_t number_objective_gradient_nonzeros() const override { return this->model->number_objective_gradient_nonzeros(); } [[nodiscard]] size_t number_jacobian_nonzeros() const override { return this->model->number_jacobian_nonzeros() + this->slacks.size(); } diff --git a/uno/model/Model.hpp b/uno/model/Model.hpp index ee74a6d9..82b39034 100644 --- a/uno/model/Model.hpp +++ b/uno/model/Model.hpp @@ -76,6 +76,7 @@ namespace uno { virtual void initial_primal_point(Vector& x) const = 0; virtual void initial_dual_point(Vector& multipliers) const = 0; virtual void postprocess_solution(Iterate& iterate, TerminationStatus termination_status) const = 0; + virtual void terminate(Iterate& iterate, TerminationStatus termination_status) const = 0; [[nodiscard]] virtual size_t number_objective_gradient_nonzeros() const = 0; [[nodiscard]] virtual size_t number_jacobian_nonzeros() const = 0; diff --git a/uno/model/ScaledModel.hpp b/uno/model/ScaledModel.hpp index 5a5a7a6d..c64d4893 100644 --- a/uno/model/ScaledModel.hpp +++ b/uno/model/ScaledModel.hpp @@ -42,6 +42,9 @@ namespace uno { void initial_primal_point(Vector& x) const override { this->model->initial_primal_point(x); } void initial_dual_point(Vector& multipliers) const override { this->model->initial_dual_point(multipliers); } void postprocess_solution(Iterate& iterate, TerminationStatus termination_status) const override; + void terminate(Iterate& iterate, TerminationStatus termination_status) const override { + this->model->terminate(iterate, termination_status); + } [[nodiscard]] size_t number_objective_gradient_nonzeros() const override { return this->model->number_objective_gradient_nonzeros(); } [[nodiscard]] size_t number_jacobian_nonzeros() const override { return this->model->number_jacobian_nonzeros(); }