From 42da87dec7c65a3eaa0565100792672acbe8e03b Mon Sep 17 00:00:00 2001 From: linuslangenkamp Date: Wed, 3 Jun 2026 10:40:13 +0200 Subject: [PATCH] [UNO] update return codes --- src/nlp/nlp.h | 20 ++--- src/nlp/solvers/ipopt/adapter.cpp | 17 +++- src/nlp/solvers/uno/solver.cpp | 129 +++++++++++++++++++++--------- 3 files changed, 116 insertions(+), 50 deletions(-) diff --git a/src/nlp/nlp.h b/src/nlp/nlp.h index 3a1ae5c..7b2d959 100644 --- a/src/nlp/nlp.h +++ b/src/nlp/nlp.h @@ -29,16 +29,18 @@ namespace NLP { - enum class ReturnCode { - GENERIC_FAILURE = -4, - RESTORATION_FAILED = -3, - INFEASIBLE = -2, - DIVERGENCE = -1, - OPTIMAL = 0, - ACCEPTABLE = 1, - STEP_TOO_SMALL = 2, - UNKNOWN_SUCCESS = 3 + GENERIC_FAILURE = -7, + FEASIBILITY_RECOVERED = -6, + ITERATION_LIMIT_EXCEEDED = -5, + TIME_LIMIT_EXCEEDED = -4, + RESTORATION_FAILED = -3, + INFEASIBLE = -2, + DIVERGENCE = -1, + OPTIMAL = 0, + ACCEPTABLE = 1, + STEP_TOO_SMALL = 2, + UNKNOWN_SUCCESS = 3 }; /** diff --git a/src/nlp/solvers/ipopt/adapter.cpp b/src/nlp/solvers/ipopt/adapter.cpp index 93eea55..9634acf 100644 --- a/src/nlp/solvers/ipopt/adapter.cpp +++ b/src/nlp/solvers/ipopt/adapter.cpp @@ -196,7 +196,22 @@ NLP::ReturnCode IpoptAdapter::get_return_code(Ipopt::SolverReturn status) return NLP::ReturnCode::INFEASIBLE; } else if (status == Ipopt::SolverReturn::RESTORATION_FAILURE) { return NLP::ReturnCode::RESTORATION_FAILED; - } else if (static_cast(status) < 0) { + } else if (status == Ipopt::SolverReturn::CPUTIME_EXCEEDED || + status == Ipopt::SolverReturn::WALLTIME_EXCEEDED) { + return NLP::ReturnCode::TIME_LIMIT_EXCEEDED; + } else if (status == Ipopt::SolverReturn::MAXITER_EXCEEDED) { + return NLP::ReturnCode::ITERATION_LIMIT_EXCEEDED; + } else if (status == Ipopt::SolverReturn::FEASIBLE_POINT_FOUND) { + return NLP::ReturnCode::FEASIBILITY_RECOVERED; + } else if (status == Ipopt::SolverReturn::USER_REQUESTED_STOP) { + return NLP::ReturnCode::GENERIC_FAILURE; + } else if (status == Ipopt::SolverReturn::ERROR_IN_STEP_COMPUTATION || + status == Ipopt::SolverReturn::INVALID_NUMBER_DETECTED || + status == Ipopt::SolverReturn::TOO_FEW_DEGREES_OF_FREEDOM || + status == Ipopt::SolverReturn::INVALID_OPTION || + status == Ipopt::SolverReturn::OUT_OF_MEMORY || + status == Ipopt::SolverReturn::INTERNAL_ERROR || + status == Ipopt::SolverReturn::UNASSIGNED) { return NLP::ReturnCode::GENERIC_FAILURE; } else { return NLP::ReturnCode::UNKNOWN_SUCCESS; diff --git a/src/nlp/solvers/uno/solver.cpp b/src/nlp/solvers/uno/solver.cpp index 9898c80..ec845d2 100644 --- a/src/nlp/solvers/uno/solver.cpp +++ b/src/nlp/solvers/uno/solver.cpp @@ -98,6 +98,46 @@ uno_int logger_stream_callback(const char* buffer, uno_int length, void* user_da return length; } +const char* uno_optimization_status_to_string(uno_int status) +{ + if (status == UNO_SUCCESS) { + return "UNO_SUCCESS"; + } else if (status == UNO_ITERATION_LIMIT) { + return "UNO_ITERATION_LIMIT"; + } else if (status == UNO_TIME_LIMIT) { + return "UNO_TIME_LIMIT"; + } else if (status == UNO_EVALUATION_ERROR) { + return "UNO_EVALUATION_ERROR"; + } else if (status == UNO_ALGORITHMIC_ERROR) { + return "UNO_ALGORITHMIC_ERROR"; + } else if (status == UNO_USER_TERMINATION) { + return "UNO_USER_TERMINATION"; + } else { + return "UNO_UNKNOWN_OPTIMIZATION_STATUS"; + } +} + +const char* uno_solution_status_to_string(uno_int status) +{ + if (status == UNO_NOT_OPTIMAL) { + return "UNO_NOT_OPTIMAL"; + } else if (status == UNO_FEASIBLE_KKT_POINT) { + return "UNO_FEASIBLE_KKT_POINT"; + } else if (status == UNO_FEASIBLE_FJ_POINT) { + return "UNO_FEASIBLE_FJ_POINT"; + } else if (status == UNO_INFEASIBLE_STATIONARY_POINT) { + return "UNO_INFEASIBLE_STATIONARY_POINT"; + } else if (status == UNO_FEASIBLE_SMALL_STEP) { + return "UNO_FEASIBLE_SMALL_STEP"; + } else if (status == UNO_INFEASIBLE_SMALL_STEP) { + return "UNO_INFEASIBLE_SMALL_STEP"; + } else if (status == UNO_UNBOUNDED) { + return "UNO_UNBOUNDED"; + } else { + return "UNO_UNKNOWN_SOLUTION_STATUS"; + } +} + } // namespace struct UnoSolverData { @@ -191,55 +231,64 @@ void UnoSolver::set_settings() NLP::ReturnCode UnoSolver::get_return_code() const { - const uno_int optimization_status = uno_get_optimization_status(udata->solver); - const uno_int solution_status = uno_get_solution_status(udata->solver); - - if (optimization_status == UNO_SUCCESS) { - if (solution_status == UNO_FEASIBLE_KKT_POINT) return NLP::ReturnCode::OPTIMAL; - if (solution_status == UNO_FEASIBLE_FJ_POINT || solution_status == UNO_FEASIBLE_SMALL_STEP) return NLP::ReturnCode::ACCEPTABLE; - if (solution_status == UNO_INFEASIBLE_STATIONARY_POINT) return NLP::ReturnCode::INFEASIBLE; - if (solution_status == UNO_INFEASIBLE_SMALL_STEP) return NLP::ReturnCode::STEP_TOO_SMALL; - if (solution_status == UNO_UNBOUNDED) return NLP::ReturnCode::DIVERGENCE; - return NLP::ReturnCode::UNKNOWN_SUCCESS; + void* solver = udata->solver; + + const uno_int optimization_status = uno_get_optimization_status(solver); + const uno_int solution_status = uno_get_solution_status(solver); + + if (optimization_status == UNO_ITERATION_LIMIT) { + return NLP::ReturnCode::ITERATION_LIMIT_EXCEEDED; + } else if (optimization_status == UNO_TIME_LIMIT) { + return NLP::ReturnCode::TIME_LIMIT_EXCEEDED; + } else if (optimization_status == UNO_EVALUATION_ERROR || + optimization_status == UNO_ALGORITHMIC_ERROR || + optimization_status == UNO_USER_TERMINATION) { + return NLP::ReturnCode::GENERIC_FAILURE; + } else if (optimization_status != UNO_SUCCESS) { + return NLP::ReturnCode::GENERIC_FAILURE; } - if (optimization_status == UNO_ITERATION_LIMIT || optimization_status == UNO_TIME_LIMIT) { + if (solution_status == UNO_FEASIBLE_KKT_POINT) { + return NLP::ReturnCode::OPTIMAL; + } else if (solution_status == UNO_FEASIBLE_FJ_POINT) { + return NLP::ReturnCode::ACCEPTABLE; + } else if (solution_status == UNO_FEASIBLE_SMALL_STEP) { + return NLP::ReturnCode::STEP_TOO_SMALL; + } else if (solution_status == UNO_INFEASIBLE_STATIONARY_POINT || + solution_status == UNO_INFEASIBLE_SMALL_STEP) { + return NLP::ReturnCode::INFEASIBLE; + } else if (solution_status == UNO_UNBOUNDED) { + return NLP::ReturnCode::DIVERGENCE; + } else if (solution_status == UNO_NOT_OPTIMAL) { + return NLP::ReturnCode::UNKNOWN_SUCCESS; + } else { return NLP::ReturnCode::UNKNOWN_SUCCESS; } - return NLP::ReturnCode::GENERIC_FAILURE; } void UnoSolver::log_status() const { - const uno_int optimization_status = uno_get_optimization_status(udata->solver); - const uno_int solution_status = uno_get_solution_status(udata->solver); - - switch (optimization_status) { - case UNO_SUCCESS: - Log::success("[Uno Interface] Optimization finished successfully."); - break; - case UNO_ITERATION_LIMIT: - Log::warning("[Uno Interface] Iteration limit reached."); - break; - case UNO_TIME_LIMIT: - Log::warning("[Uno Interface] Time limit reached."); - break; - case UNO_EVALUATION_ERROR: - Log::error("[Uno Interface] Evaluation error."); - break; - case UNO_ALGORITHMIC_ERROR: - Log::error("[Uno Interface] Algorithmic error."); - break; - case UNO_USER_TERMINATION: - Log::warning("[Uno Interface] User termination."); - break; - default: - Log::error("[Uno Interface] Unknown optimization status: {}", static_cast(optimization_status)); - break; + void* solver = udata->solver; + + const uno_int optimization_status = uno_get_optimization_status(solver); + const uno_int solution_status = uno_get_solution_status(solver); + + const char* optimization_status_name = uno_optimization_status_to_string(optimization_status); + const char* solution_status_name = uno_solution_status_to_string(solution_status); + + if (optimization_status == 0) { + Log::success( + "[Uno Interface] optimization status: {}, solution status: {}.", + optimization_status_name, + solution_status_name + ); + } else { + Log::error( + "[Uno Interface] optimization status: {}, solution status: {}.", + optimization_status_name, + solution_status_name + ); } - - Log::info("[Uno Interface] Solution status: {}", static_cast(solution_status)); - Log::info("[Uno Interface] Method: {}", uno_get_method_description(udata->solver)); } int UnoSolver::get_iterations() const