8#include <Eigen/SparseCore>
10#include "sleipnir/optimization/solver/util/problem_scaling.hpp"
17enum class KKTErrorType {
29template <
typename Scalar, KKTErrorType T>
30Scalar kkt_error(
const Eigen::Vector<Scalar, Eigen::Dynamic>& g) {
35 if constexpr (T == KKTErrorType::INF_NORM_SCALED) {
36 return g.template lpNorm<Eigen::Infinity>();
37 }
else if constexpr (T == KKTErrorType::ONE_NORM) {
38 return g.template lpNorm<1>();
50template <
typename Scalar, KKTErrorType T>
51Scalar kkt_error(
const Eigen::Vector<Scalar, Eigen::Dynamic>& g,
52 const Eigen::SparseMatrix<Scalar>& A_e,
53 const Eigen::Vector<Scalar, Eigen::Dynamic>& c_e,
54 const Eigen::Vector<Scalar, Eigen::Dynamic>& y) {
60 if constexpr (T == KKTErrorType::INF_NORM_SCALED) {
64 constexpr Scalar s_max(100);
66 std::max(s_max, y.template lpNorm<1>() / Scalar(y.rows())) / s_max;
71 {(g - A_e.transpose() * y).template lpNorm<Eigen::Infinity>() / s_d,
72 c_e.template lpNorm<Eigen::Infinity>()});
73 }
else if constexpr (T == KKTErrorType::ONE_NORM) {
74 return (g - A_e.transpose() * y).
template lpNorm<1>() +
75 c_e.template lpNorm<1>();
92template <
typename Scalar, KKTErrorType T>
93Scalar kkt_error(
const Eigen::Vector<Scalar, Eigen::Dynamic>& g,
94 const Eigen::SparseMatrix<Scalar>& A_e,
95 const Eigen::Vector<Scalar, Eigen::Dynamic>& c_e,
96 const Eigen::SparseMatrix<Scalar>& A_i,
97 const Eigen::Vector<Scalar, Eigen::Dynamic>& c_i,
98 const Eigen::Vector<Scalar, Eigen::Dynamic>& s,
99 const Eigen::Vector<Scalar, Eigen::Dynamic>& y,
100 const Eigen::Vector<Scalar, Eigen::Dynamic>& z, Scalar μ) {
108 if constexpr (T == KKTErrorType::INF_NORM_SCALED) {
112 constexpr Scalar s_max(100);
114 std::max(s_max, (y.template lpNorm<1>() + z.template lpNorm<1>()) /
115 Scalar(y.rows() + z.rows())) /
120 std::max(s_max, z.template lpNorm<1>() / Scalar(z.rows())) / s_max;
122 const auto S = s.asDiagonal();
123 const Eigen::Vector<Scalar, Eigen::Dynamic> μe =
124 Eigen::Vector<Scalar, Eigen::Dynamic>::Constant(s.rows(), μ);
130 return std::max({(g - A_e.transpose() * y - A_i.transpose() * z)
131 .template lpNorm<Eigen::Infinity>() /
133 (S * z - μe).
template lpNorm<Eigen::Infinity>() / s_c,
134 c_e.template lpNorm<Eigen::Infinity>(),
135 (c_i - s).
template lpNorm<Eigen::Infinity>()});
136 }
else if constexpr (T == KKTErrorType::ONE_NORM) {
137 const auto S = s.asDiagonal();
138 const Eigen::Vector<Scalar, Eigen::Dynamic> μe =
139 Eigen::Vector<Scalar, Eigen::Dynamic>::Constant(s.rows(), μ);
141 return (g - A_e.transpose() * y - A_i.transpose() * z)
142 .template lpNorm<1>() +
143 (S * z - μe).
template lpNorm<1>() + c_e.template lpNorm<1>() +
144 (c_i - s).
template lpNorm<1>();
154template <
typename Scalar, KKTErrorType T>
155Scalar unscaled_kkt_error(
const ProblemScaling<Scalar>& scaling,
156 const Eigen::Vector<Scalar, Eigen::Dynamic>& g) {
157 using DenseVector = Eigen::Vector<Scalar, Eigen::Dynamic>;
159 if (scaling.is_identity()) {
160 return kkt_error<Scalar, T>(g);
163 const DenseVector g_unscaled = (Scalar(1) / scaling.f) * g;
165 return kkt_error<Scalar, T>(g_unscaled);
177template <
typename Scalar, KKTErrorType T>
178Scalar unscaled_kkt_error(
const ProblemScaling<Scalar>& scaling,
179 const Eigen::Vector<Scalar, Eigen::Dynamic>& g,
180 const Eigen::SparseMatrix<Scalar>& A_e,
181 const Eigen::Vector<Scalar, Eigen::Dynamic>& c_e,
182 const Eigen::Vector<Scalar, Eigen::Dynamic>& y) {
183 using DenseVector = Eigen::Vector<Scalar, Eigen::Dynamic>;
184 using SparseMatrix = Eigen::SparseMatrix<Scalar>;
186 if (scaling.is_identity()) {
187 return kkt_error<Scalar, T>(g, A_e, c_e, y);
190 const Scalar inv_d_f = Scalar(1) / scaling.f;
191 const DenseVector inv_d_c_e = scaling.c_e.cwiseInverse();
193 const DenseVector g_unscaled = inv_d_f * g;
194 const SparseMatrix A_e_unscaled = inv_d_c_e.asDiagonal() * A_e;
195 const DenseVector c_e_unscaled = inv_d_c_e.cwiseProduct(c_e);
196 const DenseVector y_unscaled = scaling.c_e.cwiseProduct(y) * inv_d_f;
198 return kkt_error<Scalar, T>(g_unscaled, A_e_unscaled, c_e_unscaled,
216template <
typename Scalar, KKTErrorType T>
217Scalar unscaled_kkt_error(
const ProblemScaling<Scalar>& scaling,
218 const Eigen::Vector<Scalar, Eigen::Dynamic>& g,
219 const Eigen::SparseMatrix<Scalar>& A_e,
220 const Eigen::Vector<Scalar, Eigen::Dynamic>& c_e,
221 const Eigen::SparseMatrix<Scalar>& A_i,
222 const Eigen::Vector<Scalar, Eigen::Dynamic>& c_i,
223 const Eigen::Vector<Scalar, Eigen::Dynamic>& s,
224 const Eigen::Vector<Scalar, Eigen::Dynamic>& y,
225 const Eigen::Vector<Scalar, Eigen::Dynamic>& z,
227 using DenseVector = Eigen::Vector<Scalar, Eigen::Dynamic>;
228 using SparseMatrix = Eigen::SparseMatrix<Scalar>;
230 if (scaling.is_identity()) {
231 return kkt_error<Scalar, T>(g, A_e, c_e, A_i, c_i, s, y, z, μ);
234 const Scalar inv_d_f = Scalar(1) / scaling.f;
235 const DenseVector inv_d_c_e = scaling.c_e.cwiseInverse();
236 const DenseVector inv_d_c_i = scaling.c_i.cwiseInverse();
238 const DenseVector g_unscaled = inv_d_f * g;
239 const SparseMatrix A_e_unscaled = inv_d_c_e.asDiagonal() * A_e;
240 const DenseVector c_e_unscaled = inv_d_c_e.cwiseProduct(c_e);
241 const SparseMatrix A_i_unscaled = inv_d_c_i.asDiagonal() * A_i;
242 const DenseVector c_i_unscaled = inv_d_c_i.cwiseProduct(c_i);
243 const DenseVector s_unscaled = inv_d_c_i.cwiseProduct(s);
244 const DenseVector y_unscaled = scaling.c_e.cwiseProduct(y) * inv_d_f;
245 const DenseVector z_unscaled = scaling.c_i.cwiseProduct(z) * inv_d_f;
246 const Scalar μ_unscaled = inv_d_f * μ;
248 return kkt_error<Scalar, T>(g_unscaled, A_e_unscaled, c_e_unscaled,
249 A_i_unscaled, c_i_unscaled, s_unscaled,
250 y_unscaled, z_unscaled, μ_unscaled);