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
18template <typename Scalar>
19Scalar error_estimate(const Eigen::Vector<Scalar, Eigen::Dynamic>& g) {
20 // Update the error estimate using the KKT conditions from equations (19.5a)
21 // through (19.5d) of [1].
22 //
23 // ∇f = 0
24
25 return g.template lpNorm<Eigen::Infinity>();
26}
27
37template <typename Scalar>
38Scalar error_estimate(const Eigen::Vector<Scalar, Eigen::Dynamic>& g,
39 const Eigen::SparseMatrix<Scalar>& A_e,
40 const Eigen::Vector<Scalar, Eigen::Dynamic>& c_e,
41 const Eigen::Vector<Scalar, Eigen::Dynamic>& y) {
42 // Update the error estimate using the KKT conditions from equations (19.5a)
43 // through (19.5d) of [1].
44 //
45 // ∇f − Aₑᵀy = 0
46 // cₑ = 0
47 //
48 // The error tolerance is the max of the following infinity norms scaled by
49 // s_d (see equation (5) of [2]).
50 //
51 // ‖∇f − Aₑᵀy‖_∞ / s_d
52 // ‖cₑ‖_∞
53
54 // s_d = max(sₘₐₓ, ‖y‖₁ / m) / sₘₐₓ
55 constexpr Scalar s_max(100);
56 Scalar s_d =
57 std::max(s_max, y.template lpNorm<1>() / Scalar(y.rows())) / s_max;
58
59 return std::max(
60 {(g - A_e.transpose() * y).template lpNorm<Eigen::Infinity>() / s_d,
61 c_e.template lpNorm<Eigen::Infinity>()});
62}
63
81template <typename Scalar>
82Scalar error_estimate(const Eigen::Vector<Scalar, Eigen::Dynamic>& g,
83 const Eigen::SparseMatrix<Scalar>& A_e,
84 const Eigen::Vector<Scalar, Eigen::Dynamic>& c_e,
85 const Eigen::SparseMatrix<Scalar>& A_i,
86 const Eigen::Vector<Scalar, Eigen::Dynamic>& c_i,
87 const Eigen::Vector<Scalar, Eigen::Dynamic>& s,
88 const Eigen::Vector<Scalar, Eigen::Dynamic>& y,
89 const Eigen::Vector<Scalar, Eigen::Dynamic>& z,
90 Scalar μ) {
91 // Update the error estimate using the KKT conditions from equations (19.5a)
92 // through (19.5d) of [1].
93 //
94 // ∇f − Aₑᵀy − Aᵢᵀz = 0
95 // Sz − μe = 0
96 // cₑ = 0
97 // cᵢ − s = 0
98 //
99 // The error tolerance is the max of the following infinity norms scaled by
100 // s_d and s_c (see equation (5) of [2]).
101 //
102 // ‖∇f − Aₑᵀy − Aᵢᵀz‖_∞ / s_d
103 // ‖Sz − μe‖_∞ / s_c
104 // ‖cₑ‖_∞
105 // ‖cᵢ − s‖_∞
106
107 // s_d = max(sₘₐₓ, (‖y‖₁ + ‖z‖₁) / (m + n)) / sₘₐₓ
108 constexpr Scalar s_max(100);
109 Scalar s_d =
110 std::max(s_max, (y.template lpNorm<1>() + z.template lpNorm<1>()) /
111 Scalar(y.rows() + z.rows())) /
112 s_max;
113
114 // s_c = max(sₘₐₓ, ‖z‖₁ / n) / sₘₐₓ
115 Scalar s_c =
116 std::max(s_max, z.template lpNorm<1>() / Scalar(z.rows())) / s_max;
117
118 const auto S = s.asDiagonal();
119 const Eigen::Vector<Scalar, Eigen::Dynamic> μe =
120 Eigen::Vector<Scalar, Eigen::Dynamic>::Constant(s.rows(), μ);
121
122 return std::max({(g - A_e.transpose() * y - A_i.transpose() * z)
123 .template lpNorm<Eigen::Infinity>() /
124 s_d,
125 (S * z - μe).template lpNorm<Eigen::Infinity>() / s_c,
126 c_e.template lpNorm<Eigen::Infinity>(),
127 (c_i - s).template lpNorm<Eigen::Infinity>()});
128}
129
130} // namespace slp