Sleipnir C++ API
Loading...
Searching...
No Matches
error_estimate.hpp
1// Copyright (c) Sleipnir contributors
2
3#pragma once
4
5#include <algorithm>
6
7#include <Eigen/Core>
8#include <Eigen/SparseCore>
9
10// See docs/algorithms.md#Works_cited for citation definitions
11
12namespace slp {
13
20template <typename Scalar>
21Scalar error_estimate(const Eigen::Vector<Scalar, Eigen::Dynamic>& g) {
22 // Update the error estimate using the KKT conditions from equations (19.5a)
23 // through (19.5d) of [1].
24 //
25 // ∇f = 0
26
27 return g.template lpNorm<Eigen::Infinity>();
28}
29
41template <typename Scalar>
42Scalar error_estimate(const Eigen::Vector<Scalar, Eigen::Dynamic>& g,
43 const Eigen::SparseMatrix<Scalar>& A_e,
44 const Eigen::Vector<Scalar, Eigen::Dynamic>& c_e,
45 const Eigen::Vector<Scalar, Eigen::Dynamic>& y) {
46 // Update the error estimate using the KKT conditions from equations (19.5a)
47 // through (19.5d) of [1].
48 //
49 // ∇f − Aₑᵀy = 0
50 // cₑ = 0
51 //
52 // The error tolerance is the max of the following infinity norms scaled by
53 // s_d (see equation (5) of [2]).
54 //
55 // ‖∇f − Aₑᵀy‖_∞ / s_d
56 // ‖cₑ‖_∞
57
58 // s_d = max(sₘₐₓ, ‖y‖₁ / m) / sₘₐₓ
59 constexpr Scalar s_max(100);
60 Scalar s_d =
61 std::max(s_max, y.template lpNorm<1>() / Scalar(y.rows())) / s_max;
62
63 return std::max(
64 {(g - A_e.transpose() * y).template lpNorm<Eigen::Infinity>() / s_d,
65 c_e.template lpNorm<Eigen::Infinity>()});
66}
67
87template <typename Scalar>
88Scalar error_estimate(const Eigen::Vector<Scalar, Eigen::Dynamic>& g,
89 const Eigen::SparseMatrix<Scalar>& A_e,
90 const Eigen::Vector<Scalar, Eigen::Dynamic>& c_e,
91 const Eigen::SparseMatrix<Scalar>& A_i,
92 const Eigen::Vector<Scalar, Eigen::Dynamic>& c_i,
93 const Eigen::Vector<Scalar, Eigen::Dynamic>& s,
94 const Eigen::Vector<Scalar, Eigen::Dynamic>& y,
95 const Eigen::Vector<Scalar, Eigen::Dynamic>& z,
96 Scalar μ) {
97 // Update the error estimate using the KKT conditions from equations (19.5a)
98 // through (19.5d) of [1].
99 //
100 // ∇f − Aₑᵀy − Aᵢᵀz = 0
101 // Sz − μe = 0
102 // cₑ = 0
103 // cᵢ − s = 0
104 //
105 // The error tolerance is the max of the following infinity norms scaled by
106 // s_d and s_c (see equation (5) of [2]).
107 //
108 // ‖∇f − Aₑᵀy − Aᵢᵀz‖_∞ / s_d
109 // ‖Sz − μe‖_∞ / s_c
110 // ‖cₑ‖_∞
111 // ‖cᵢ − s‖_∞
112
113 // s_d = max(sₘₐₓ, (‖y‖₁ + ‖z‖₁) / (m + n)) / sₘₐₓ
114 constexpr Scalar s_max(100);
115 Scalar s_d =
116 std::max(s_max, (y.template lpNorm<1>() + z.template lpNorm<1>()) /
117 Scalar(y.rows() + z.rows())) /
118 s_max;
119
120 // s_c = max(sₘₐₓ, ‖z‖₁ / n) / sₘₐₓ
121 Scalar s_c =
122 std::max(s_max, z.template lpNorm<1>() / Scalar(z.rows())) / s_max;
123
124 const auto S = s.asDiagonal();
125 const Eigen::Vector<Scalar, Eigen::Dynamic> μe =
126 Eigen::Vector<Scalar, Eigen::Dynamic>::Constant(s.rows(), μ);
127
128 return std::max({(g - A_e.transpose() * y - A_i.transpose() * z)
129 .template lpNorm<Eigen::Infinity>() /
130 s_d,
131 (S * z - μe).template lpNorm<Eigen::Infinity>() / s_c,
132 c_e.template lpNorm<Eigen::Infinity>(),
133 (c_i - s).template lpNorm<Eigen::Infinity>()});
134}
135
136} // namespace slp