9#ifdef PROXSUITE_NLP_USE_PROXSUITE_LDLT
12#include <boost/variant.hpp>
35template <
typename Scalar,
36 class MatrixType =
typename math_types<Scalar>::MatrixXs>
38 boost::variant<linalg::DenseLDLT<Scalar>, linalg::BlockLDLT<Scalar>,
39 Eigen::LDLT<MatrixType>, BunchKaufman<MatrixType>
40#ifdef PROXSUITE_NLP_USE_PROXSUITE_LDLT
42 linalg::ProxSuiteLDLTWrapper<Scalar>
46inline linalg::SymbolicBlockMatrix
47create_default_block_structure(
const std::vector<isize> &dims_primal,
48 const std::vector<isize> &dims_dual) {
52 isize nprim_blocks = (isize)dims_primal.size();
53 isize ndual_blocks = (isize)dims_dual.size();
54 isize nblocks = nprim_blocks + ndual_blocks;
56 linalg::SymbolicBlockMatrix structure(nblocks, nblocks);
57 isize *segment_lens = structure.segment_lens;
59 for (
unsigned int i = 0; i < nprim_blocks; ++i) {
60 segment_lens[i] = dims_primal[i];
62 for (
unsigned int i = 0; i < ndual_blocks; ++i) {
63 segment_lens[i + nprim_blocks] = dims_dual[i];
68 for (isize i = 0; i < nprim_blocks; ++i) {
69 for (isize j = 0; j < nprim_blocks; ++j) {
75 for (isize i = 0; i < nprim_blocks; ++i) {
76 for (isize j = nprim_blocks; j < nblocks; ++j) {
82 for (isize i = nprim_blocks; i < nblocks; ++i) {
87 for (isize j = nprim_blocks; j < nblocks; ++j) {
95inline isize get_total_dim_helper(
const std::vector<isize> &nprims,
96 const std::vector<isize> &nduals) {
97 return std::accumulate(nprims.begin(), nprims.end(), 0) +
98 std::accumulate(nduals.begin(), nduals.end(), 0);
101template <
typename Scalar>
102LDLTVariant<Scalar> allocate_ldlt_from_sizes(
const std::vector<isize> &nprims,
103 const std::vector<isize> &nduals,
105 const isize size = get_total_dim_helper(nprims, nduals);
114 auto structure = create_default_block_structure(nprims, nduals);
117 block_ldlt.findSparsifyingPermutation();
121 return Eigen::LDLT<MatrixXs>(size);
123#ifdef PROXSUITE_NLP_USE_PROXSUITE_LDLT
127 PROXSUITE_NLP_RUNTIME_ERROR(
128 "ProxSuite support is not enabled. You should recompile ProxNLP with "
129 "the BUILD_WITH_PROXSUITE_SUPPORT flag.");
137template <
typename MatrixType,
typename Signature,
int UpLo>
138void bunch_kaufman_compute_signature(
139 BunchKaufman<MatrixType, UpLo>
const &factor, Signature &signature) {
141 using Scalar =
typename MatrixType::Scalar;
142 using Real =
typename Eigen::NumTraits<Scalar>::Real;
144 Index n = factor.rows();
145 signature.conservativeResize(n);
148 const MatrixType &a = factor.matrixLDLT();
151 Index p = factor.pivots()[k];
154 Real ak = Eigen::numext::real(a(k, k));
155 Real akp1 = Eigen::numext::real(a(k + 1, k + 1));
156 Scalar akp1k = factor.subdiag()[k];
158 Real det = ak * akp1 - Eigen::numext::abs2(akp1k);
160 if (std::abs(det) <= std::numeric_limits<Scalar>::epsilon()) {
162 signature[k + 1] = int(math::sign(tr));
163 }
else if (det > Scalar(0)) {
164 signature[k] = int(math::sign(tr));
165 signature[k + 1] = signature[k];
169 signature[k + 1] = +1;
174 Real ak = Eigen::numext::real(a(k, k));
175 signature[k] = int(math::sign(ak));
184 template <
typename Fac>
void operator()(
const Fac &facto)
const {
185 auto sign = facto.vectorD().cwiseSign();
186 signature = sign.template cast<int>();
189 template <
typename MatType>
191 internal::bunch_kaufman_compute_signature(facto, signature);
193 Eigen::VectorXi &signature;
196inline std::array<int, 3>
197computeInertiaTuple(
const Eigen::Ref<Eigen::VectorXi const> &signature) {
199 Index n = signature.size();
203 for (Index i = 0; i < n; i++) {
204 switch (signature(i)) {
215 PROXSUITE_NLP_RUNTIME_ERROR(
216 "Signature vector should only contain values O, 1, -1.");
Routines for block-sparse matrix LDLT factorisation.
@ DENSE
Use our dense LDLT.
@ BLOCKSPARSE
Use blocked LDLT.
@ PROXSUITE
Use Proxsuite's LDLT.
@ EIGEN
Use Eigen's implementation.
@ BUNCHKAUFMAN
Use Bunch-Kaufman factorization.
BlockKind
Kind of matrix block: zeros, diagonal, lower/upper triangular or dense.
@ Dense
There is no known prior structure; assume a dense block.
@ Diag
The block is diagonal.
@ Zero
All entries in the block are zero.
Block sparsity-aware LDLT factorization algorithm.
A fast, recursive divide-and-conquer LDLT algorithm.
Use the LDLT from proxsuite.
Typedefs for math (Eigen vectors, matrices) depending on scalar type.