13#ifdef AKREON_ENABLE_IOSTREAM
21#include "akreon/linalg/norms/vector_norms.hpp"
28 return "INFEASIBLE_OR_UNBOUNDED";
32 return "PRIMAL_FEASIBLE";
34 return "DUAL_FEASIBLE";
36 return "PRIMAL_DUAL_FEASIBLE";
38 return "PRIMAL_OPTIMAL";
40 return "DUAL_OPTIMAL";
42 return "INFEASIBLE_OPTIMAL";
48 linalg::NumericalEvent event) {
50 case linalg::NumericalEvent::NONE:
52 case linalg::NumericalEvent::RANK_DEFICIENCY:
53 return "RANK_DEFICIENCY";
54 case linalg::NumericalEvent::INDEFINITE_FACTORIZATION:
55 return "INDEFINITE_FACTORIZATION";
56 case linalg::NumericalEvent::NEAR_SINGULAR_TRIANGULAR_SOLVE:
57 return "NEAR_SINGULAR_TRIANGULAR_SOLVE";
58 case linalg::NumericalEvent::NUMERICAL_SAFEGUARD:
59 return "NUMERICAL_SAFEGUARD";
60 case linalg::NumericalEvent::DB_MAX_ITERS_REACHED:
61 return "DB_MAX_ITERS_REACHED";
62 case linalg::NumericalEvent::FACTORIZATION_FAILED:
63 return "FACTORIZATION_FAILED";
64 case linalg::NumericalEvent::EVD_FAILED:
89template <
typename Trace>
91 if (!w.
format(
"canonical_trace: nodes=%zu cones=%zu equalities=%zu\n",
100 [&](
const auto&... nodes) {
102 w.
format(
" node[%zu]: id=%zu parent=%zu atom=%u child=%zu\n",
103 i++, nodes.node_id, nodes.parent_id,
104 static_cast<unsigned>(nodes.atom_type),
109 if (!ok)
return false;
113 [&](
const auto&... cones) {
115 w.
format(
" cone[%zu]: node=%zu local=%zu global=%zu kind=%s "
116 "offset=%zu dim=%zu\n",
117 i++, cones.node_id, cones.local_cone_index,
118 cones.global_cone_index,
120 cones.cone_offset, cones.cone_dim)),
124 if (!ok)
return false;
128 [&](
const auto&...
eqs) {
130 w.
format(
" eq[%zu]: node=%zu local=%zu offset=%zu rows=%zu\n",
131 i++,
eqs.node_id,
eqs.local_eq_index,
eqs.row_offset,
139template <linalg::Field T, std::size_t NumCones,
typename ConeTuple,
144 std::index_sequence<Is...>,
const char*
label) {
146 return w.
format(
"active=%d mu=%g rhs_c=%g pz_rhs=%g",
cone_step.active,
148 static_cast<double>(
cone_step.rhs_c_norm),
149 static_cast<double>(
cone_step.pz_rhs_norm));
154 w.
format(
" %s cone[%zu:%s node=%zu offset=%zu dim=%zu]: ",
label,
Is,
156 std::get<Is>(cones).node_id, std::get<Is>(cones).cone_offset,
157 std::get<Is>(cones).cone_dim) &&
163template <linalg::Field T, std::
size_t NumCones,
typename CanonicalTraceT>
166 const CanonicalTraceT& canonical_trace,
169 "[%zu] mu=%g ax=%g ay=%g rd=%g rp=%g req=%g pz=%g pnu=%g "
170 "px=%g py=%g tag=%s event=%s stalled=%d\n",
171 k,
static_cast<double>(iter.
mu),
static_cast<double>(iter.
alpha_x),
172 static_cast<double>(iter.
alpha_y),
static_cast<double>(iter.
rd_norm),
175 static_cast<double>(iter.
px_norm),
static_cast<double>(iter.
py_norm),
184 std::make_index_sequence<NumCones>{},
"pred"))
187 std::make_index_sequence<NumCones>{},
"corr"))
190 for (std::size_t
i = 0;
i < NumCones; ++
i) {
191 if (!w.
format(
" pred cone[%zu]: ",
i))
return false;
193 if (!w.
append(
"\n"))
return false;
194 if (!w.
format(
" corr cone[%zu]: ",
i))
return false;
196 if (!w.
append(
"\n"))
return false;
203template <linalg::Field T, std::
size_t NumCones,
typename CanonicalTraceT>
206 const CanonicalTraceT& canonical_trace) {
207 if (!w.
format(
"solver_trace: iters=%zu max_iters=%zu cones=%zu\n",
211 const std::size_t
used =
213 for (std::size_t
k = 0;
k <
used; ++
k) {
219template <
typename Trace,
typename CanonicalTraceT>
221 const CanonicalTraceT&) {
222 return w.
append(
"solver_trace: <empty>\n");
225template <linalg::VectorContainer Var, linalg::VectorContainer ConeVar,
226 linalg::VectorContainer NuVar,
typename CanonicalTraceT,
232 const auto rd_norm = linalg::L2<
decltype(res.rd)>()(res.rd);
233 const auto rp_norm = linalg::L2<
decltype(res.rp)>()(res.rp);
234 const auto req_norm = linalg::L2<
decltype(res.req)>()(res.req);
236 if (!w.
format(
"tag=%s stalled=%d event=%s num_iter=%zu mu=%g "
237 "convex_obj=%g dual_obj=%g rd=%g rp=%g req=%g\n",
240 static_cast<double>(res.mu),
241 static_cast<double>(res.convex_obj),
242 static_cast<double>(res.dual_obj),
static_cast<double>(rd_norm),
243 static_cast<double>(rp_norm),
static_cast<double>(req_norm)))
246 if (!w.
append(
"z="))
return false;
248 if (!w.
append(
"\n"))
return false;
249 if (!w.
append(
"x="))
return false;
251 if (!w.
append(
"\n"))
return false;
252 if (!w.
append(
"y="))
return false;
254 if (!w.
append(
"\n"))
return false;
255 if (!w.
append(
"nu="))
return false;
257 if (!w.
append(
"\n"))
return false;
258 if (!w.
append(
"rd="))
return false;
260 if (!w.
append(
"\n"))
return false;
261 if (!w.
append(
"rp="))
return false;
263 if (!w.
append(
"\n"))
return false;
264 if (!w.
append(
"req="))
return false;
266 if (!w.
append(
"\n"))
return false;
272template <linalg::VectorContainer Var, linalg::VectorContainer ConeVar,
273 linalg::VectorContainer NuVar,
typename CanonicalTraceT,
285#ifdef AKREON_ENABLE_IOSTREAM
286template <linalg::VectorContainer Var, linalg::VectorContainer ConeVar,
287 linalg::VectorContainer NuVar,
typename CanonicalTraceT,
SolverResult
SolverResult.
@ INFEASIBLE_OR_UNBOUNDED
bool append_vector(FixedBufferWriter &w, const Vec &v)
bool append_canonical_trace(FixedBufferWriter &w, const Trace &trace)
bool append_result(FixedBufferWriter &w, const convex::PrimalDualResult< Var, ConeVar, NuVar, CanonicalTraceT, SolverTraceT > &res)
constexpr const char * solver_result_to_cstr(config::SolverResult tag)
constexpr const char * numerical_event_to_cstr(linalg::NumericalEvent event)
bool append_iter_trace(FixedBufferWriter &w, const PdIpmIterTrace< T, NumCones > &iter, const CanonicalTraceT &canonical_trace, std::size_t k)
bool append_solver_trace(FixedBufferWriter &w, const PdIpmTrace< T, NumCones > &trace, const CanonicalTraceT &canonical_trace)
bool append_cone_steps(FixedBufferWriter &w, const PdIpmStepTrace< T, NumCones > &step, const ConeTuple &cones, std::index_sequence< Is... >, const char *label)
constexpr const char * canonical_cone_kind_to_cstr(CanonicalConeKind kind)
std::size_t result_to_cstr(const convex::PrimalDualResult< Var, ConeVar, NuVar, CanonicalTraceT, SolverTraceT > &res, char *out, std::size_t out_size)
constexpr std::size_t dom_size_v
CanonicalConeKind
Cone family emitted into the global cone block.
#define PD_IPM_STEPS
(dakre) note increase constexpr steps / depth for # steps to increase here for constexpr usage
Per-cone scalar diagnostics for one predictor or corrector pass.
Outer PD-IPM iteration diagnostics.
T px_norm
||Newton step in x||_2.
PdIpmStepTrace< T, NumCones > corrector
corrector pd ipm trace
T rd_norm
||dual residual||_2.
linalg::NumericalEvent event
event of reported numerical result
T alpha_x
Max primal cone step.
T py_norm
||Newton step in y||_2.
T alpha_y
Max dual cone step.
PdIpmStepTrace< T, NumCones > predictor
predictor pd ipm trace
bool stalled
tag whether or not its been stalled
T pnu_norm
||Newton step in nu||_2.
config::SolverResult tag
tag of solver result
T req_norm
||equality residual||_2.
T rp_norm
||cone/primal residual||_2.
T pz_norm
||Newton step in z||_2.
Predictor or corrector cone diagnostics for one outer iteration.
Fixed-capacity PD-IPM trace.
std::array< PdIpmIterTrace< T, NumCones >, PD_IPM_STEPS > iters
public member vars
std::size_t num_iters
number of iterations
Final primal-dual solve result plus optional structural and iteration traces.
Small no-heap append-only writer for debug formatting.
bool append(const char *text)
bool format(const char *fmt, Args... args)