proxsuite-nlp  0.10.0
A primal-dual augmented Lagrangian-type solver for nonlinear programming on manifolds.
Loading...
Searching...
No Matches
block-triangular.hpp
Go to the documentation of this file.
1
3#pragma once
4
8
9namespace proxsuite {
10namespace nlp {
11namespace linalg {
12namespace backend {
13
14template <int Mode, bool IsLower = (Mode & Eigen::Lower) == Eigen::Lower>
15struct block_triangular_subsolve_impl;
16
17} // namespace backend
18
22template <typename _MatrixType, int _Mode> struct TriangularBlockMatrix {
23public:
24 enum { Mode = _Mode, IsLower = (Mode & Eigen::Lower) == Eigen::Lower };
25 using MatrixType = _MatrixType;
27 typename Eigen::internal::ref_selector<MatrixType>::non_const_type;
28 using Scalar = typename MatrixType::Scalar;
29
31 : m_matrix(mat), m_structure(structure) {}
32
35 template <typename Derived, bool UseBlockGemmT = true>
36 bool solveInPlace(Eigen::MatrixBase<Derived> &bAndX) const {
37
38 assert(bAndX.rows() == m_matrix.cols());
39
40 const isize size = bAndX.rows();
41 isize rem = size;
42 const isize nblocks = m_structure.nsegments();
43
44 // loop over structure rows
45 for (isize i = IsLower ? 0 : nblocks - 1; IsLower ? i < nblocks : i >= 0;
46 IsLower ? i += 1 : i -= 1) {
47
49
50 // current window size is rem_i
51 // in lower mode: it is bottom right corner of m_matrix
52 // in upper mode: top left corner
53 auto L_cur = IsLower ? m_matrix.bottomRightCorner(rem, rem)
54 : m_matrix.topLeftCorner(rem, rem);
55 auto b_cur = IsLower ? bAndX.bottomRows(rem) // look down
56 : bAndX.topRows(rem); // look up
57
58 // next subproblem size is rem_i+1 = rem_i - n0
59 rem -= n0;
60
61 auto b0 = IsLower ? b_cur.topRows(n0) : b_cur.bottomRows(n0);
62 auto b1 = IsLower ? b_cur.bottomRows(rem) : b_cur.topRows(rem);
63
64 auto L00 = IsLower ? L_cur.topLeftCorner(n0, n0)
65 : L_cur.bottomRightCorner(n0, n0);
66
67 auto L10 = IsLower ? L_cur.bottomLeftCorner(rem, n0)
68 : L_cur.topRightCorner(rem, n0);
69
70 // step 1: solve b0
72 L00, b0, m_structure(i, i));
73 if (!inner_flag)
74 return false;
75
76 // step 2: reformulate the problem for the following rows
77
78 if (!UseBlockGemmT) {
79 b1.noalias() -= L10 * b0;
80 } else {
81
82 // perform the multiplication in a block aware manner
83 // in Lower mode: move down from block (i, i) until (i, nb-1)
84 // in Upper mode: move down from block (0, nb-1) until (i, nb-1)
85 isize p0 = 0;
86 for (isize p = IsLower ? i + 1 : 0; IsLower ? p < nblocks : p < i;
87 ++p) {
89 auto L10_blk = L10.middleRows(p0, n_c); // size (n_c, n0)
90 auto dst = b1.middleRows(p0, n_c); // size (n_c)
91 // b0 has size n0
92 // take the block out of L10
93 BlockKind lhs_kind = m_structure(p, i);
94 backend::gemmt(dst, L10_blk, b0.transpose(), lhs_kind, Dense,
95 Scalar(-1));
96 p0 += n_c;
97 }
98 }
99 }
100
101 assert(rem == 0);
102
103 return true;
104 }
105
106protected:
108 SymbolicBlockMatrix m_structure; // shallow copy of ctor input
109};
110
111namespace backend {
112
113template <int Mode, bool IsLower> struct block_triangular_subsolve_impl {
114 static constexpr bool HasUnitDiag =
115 (Mode & Eigen::UnitDiag) == Eigen::UnitDiag;
116 static constexpr BlockKind WhichTriValid = IsLower ? TriL : TriU;
117
118 template <typename MatType, typename OutType>
119 static bool run(const MatType &L00, OutType &b0, BlockKind kind) {
120 switch (kind) {
121 case Zero:
122 case Dense:
123 return false;
124 case Diag: {
125 if (!HasUnitDiag)
126 b0 = L00.diagonal().asDiagonal().inverse() * b0;
127 break;
128 }
129 case WhichTriValid: {
130 // get triangular view of block, solve for b0
131 // the chosen mode in the template propagates to the diagonal blocks
132 L00.template triangularView<Mode>().solveInPlace(b0);
133 break;
134 }
135 default:
136 break;
137 }
138 return true;
139 }
140};
141
142} // namespace backend
143
144} // namespace linalg
145} // namespace nlp
146} // namespace proxsuite
Definition for matrix "kind" enums.
void gemmt(Eigen::MatrixBase< DstDerived > &dst, Eigen::MatrixBase< LhsDerived > const &lhs, Eigen::MatrixBase< RhsDerived > const &rhs, BlockKind lhs_kind, BlockKind rhs_kind, Scalar alpha)
Definition gemmt.hpp:211
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.
@ TriL
The block is lower-triangular.
@ TriU
The block is upper-triangular.
Main package namespace.
Definition bcl-params.hpp:5
Symbolic representation of the sparsity structure of a (square) block matrix.
Representation for triangular block matrices.
TriangularBlockMatrix(MatrixType &mat, const SymbolicBlockMatrix &structure)
typename Eigen::internal::ref_selector< MatrixType >::non_const_type MatrixTypeNested
bool solveInPlace(Eigen::MatrixBase< Derived > &bAndX) const
Block-sparse variant of the TriangularViewType::solveInPlace() method on standard dense matrices.
static bool run(const MatType &L00, OutType &b0, BlockKind kind)