proxsuite 0.6.7
The Advanced Proximal Optimization Toolbox
Loading...
Searching...
No Matches
factorize.hpp
Go to the documentation of this file.
1
2//
3// Copyright (c) 2022 INRIA
4//
5#ifndef PROXSUITE_LINALG_DENSE_LDLT_FACTORIZE_HPP
6#define PROXSUITE_LINALG_DENSE_LDLT_FACTORIZE_HPP
7
9#include <algorithm>
11
12namespace proxsuite {
13namespace linalg {
14namespace dense {
15namespace _detail {
16
17template<typename T>
19compute_permutation_impl(isize* perm_indices,
20 isize* perm_inv_indices,
21 isize n,
22 T const* diagonal_data,
23 isize stride)
24{
25 for (isize k = 0; k < n; ++k) {
26 perm_indices[k] = k;
27 }
28
29 {
30 std::sort(perm_indices,
31 perm_indices + n,
32 [diagonal_data, stride](isize i, isize j) noexcept -> bool {
33 using std::fabs;
34 auto lhs = fabs(diagonal_data[stride * i]);
35 auto rhs = fabs(diagonal_data[stride * j]);
36 if (lhs == rhs) {
37 return i < j;
38 }
39 return lhs > rhs;
40 });
41 }
42
43 for (isize k = 0; k < n; ++k) {
44 perm_inv_indices[perm_indices[k]] = k;
45 }
46}
47
48template<typename Diag>
50compute_permutation(isize* perm_indices,
51 isize* perm_inv_indices,
52 Diag const& diagonal)
53{
54 _detail::compute_permutation_impl<typename Diag::Scalar>(
55 perm_indices,
56 perm_inv_indices,
57 diagonal.rows(),
58 diagonal.data(),
59 diagonal.innerStride());
60}
61
62template<typename Mat, typename Work>
63void
64apply_permutation_tri_lower(Mat&& mat, Work&& work, isize const* perm_indices)
65{
66 using T = typename proxsuite::linalg::veg::uncvref_t<Mat>::Scalar;
67
68 isize n = mat.rows();
70 n == mat.rows(),
71 n == mat.cols(),
72 n == work.rows(),
73 n == work.cols());
74
75 auto mat_coeff = [&](isize i, isize j) noexcept -> T& {
76 return i >= j ? mat(i, j) : mat(j, i);
77 };
78
79 for (isize j = 0; j < n; ++j) {
80 for (isize i = j; i < n; ++i) {
81 work(i, j) = mat_coeff(perm_indices[i], perm_indices[j]);
82 }
83 }
84
85 mat.template triangularView<Eigen::Lower>() =
86 work.template triangularView<Eigen::Lower>();
87}
88
89template<typename Mat>
90void
93{
94 // left looking cholesky
95 // https://en.wikipedia.org/wiki/Cholesky_decomposition#LDL_decomposition_2
96
97 using T = typename Mat::Scalar;
98 isize n = mat.rows();
99 if (n == 0) {
100 return;
101 }
102
103 auto _work = stack.make_new_for_overwrite( //
105 n,
106 _detail::align<T>());
107 auto work_storage =
108 Eigen::Map<Eigen::Matrix<T, Eigen::Dynamic, 1>, Eigen::Unaligned>{
109 _work.ptr_mut(),
110 n,
111 1,
112 };
113
114 isize j = 0;
115 while (true) {
116 /*
117 * L00
118 * l = l10 1
119 * L20 l21 L22
120 *
121 * D0
122 * d = d1
123 * D2
124 *
125 * compute d1 and l21
126 */
127
128 auto l10 = util::subcols(util::row(mat, j), 0, j);
129 auto d0 = util::subrows(mat.diagonal(), 0, j);
130 auto work = util::subrows(work_storage, 0, j);
131
132 work = util::trans(l10).cwiseProduct(d0);
133 mat(j, j) -= work.dot(l10);
134
135 if (j + 1 == n) {
136 break;
137 }
138
139 isize rem = n - j - 1;
140
141 auto l20 = util::submatrix(mat, j + 1, 0, rem, j);
142 auto l21 = util::subrows(util::col(mat, j), j + 1, rem);
143
144 util::noalias_mul_add(l21, l20, work, T(-1));
145 l21 *= 1 / mat(j, j);
146 ++j;
147 }
148}
149
150template<typename Mat>
151void
153 isize block_size,
155{
156 // right looking blocked cholesky
157
158 using T = typename Mat::Scalar;
159 VEG_ASSERT(mat.rows() == mat.cols());
160
161 isize n = mat.rows();
162
163 if (n == 0) {
164 return;
165 }
166
167 isize j = 0;
168 while (true) {
169 isize bs = min2(n - j, block_size);
170
171 auto ld11 = util::submatrix(mat, j, j, bs, bs);
172 auto d1 = util::diagonal(ld11);
174
175 if (j + bs == n) {
176 break;
177 }
178 isize rem = n - j - bs;
179
180 isize work_stride = _detail::adjusted_stride<T>(rem);
181
182 auto _work = stack.make_new_for_overwrite( //
184 bs * work_stride,
185 _detail::align<T>());
186
187 auto work = Eigen::Map<Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic>,
188 Eigen::Unaligned,
189 Eigen::OuterStride<Eigen::Dynamic>>{
190 _work.ptr_mut(),
191 rem,
192 bs,
193 Eigen::OuterStride<Eigen::Dynamic>{ work_stride },
194 };
195
196 auto l21 = util::submatrix(mat, j + bs, j, rem, bs);
197
198 util::trans(ld11)
199 .template triangularView<Eigen::UnitUpper>()
200 .template solveInPlace<Eigen::OnTheRight>(l21);
201
202 work = l21;
203 l21 = l21 * d1.asDiagonal().inverse();
204
205 auto l22 = util::submatrix(mat, j + bs, j + bs, rem, rem);
206
207 l22.template triangularView<Eigen::Lower>() -= l21 * util::trans(work);
208 j += bs;
209 }
210}
211
214
215template<typename Mat>
216void
219{
220 // right looking recursive cholesky
221
222 using T = typename Mat::Scalar;
223 VEG_ASSERT(mat.rows() == mat.cols());
224
225 isize n = mat.rows();
226
229 } else {
230 /*
231 * L00
232 * L = L10 L11
233 *
234 * D0
235 * D = D1
236 *
237 * compute L00 and D0 recursively
238 * compute L10 by solving a triangular system
239 * compute L11 recursively
240 */
241 isize bs = (n + 1) / 2;
242 isize rem = n - bs;
243
244 auto l00 = util::submatrix(mat, 0, 0, bs, bs);
245
246 auto l10 = util::submatrix(mat, bs, 0, rem, bs);
247 auto l11 = util::submatrix(mat, bs, bs, rem, rem);
248
250 auto d0 = util::diagonal(l00);
251
252 isize work_stride = _detail::adjusted_stride<T>(rem);
253
254 util::trans(l00)
255 .template triangularView<Eigen::UnitUpper>()
256 .template solveInPlace<Eigen::OnTheRight>(l10);
257
258 {
259 auto _work = stack.make_new_for_overwrite( //
261 bs * work_stride,
262 _detail::align<T>());
263
264 auto work = Eigen::Map<Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic>,
265 Eigen::Unaligned,
266 Eigen::OuterStride<Eigen::Dynamic>>{
267 _work.ptr_mut(),
268 rem,
269 bs,
270 Eigen::OuterStride<Eigen::Dynamic>{ work_stride },
271 };
272 work = l10;
273 l10 = l10 * d0.asDiagonal().inverse();
274
275 l11.template triangularView<Eigen::Lower>() -= l10 * util::trans(work);
276 }
277
279 }
280}
281} // namespace _detail
282template<typename T>
283auto
285 isize n) noexcept
287{
288 return {
289 n * isize{ sizeof(T) },
290 _detail::align<T>(),
291 };
292}
293
294template<typename T>
295auto
297 isize n,
298 isize block_size) noexcept
300{
303 _detail::adjusted_stride<T>(
304 _detail::max2(n - block_size, isize(0))) *
305 block_size * isize{ sizeof(T) },
306 _detail::align<T>(),
307 };
308}
309
310template<typename T>
311auto
314{
316 tag, _detail::min2(n, _detail::factorize_recursive_threshold::value));
318 return req0;
319 }
320 isize bs = (n + 1) / 2;
321 isize rem = n - bs;
323 bs * _detail::adjusted_stride<T>(rem) * isize{ sizeof(T) },
324 _detail::align<T>(),
325 };
326}
327
328template<typename Mat>
329void
335template<typename Mat>
336void
338 isize block_size,
340{
341 _detail::factorize_blocked_impl(util::to_view_dyn(mat), block_size, stack);
342}
343template<typename Mat>
344void
350
351template<typename T>
352auto
359
360template<typename Mat>
361void
363{
364 isize n = mat.rows();
365 if (n > 2048) {
367 } else {
369 }
370}
371} // namespace dense
372} // namespace linalg
373} // namespace proxsuite
374
375#endif /* end of include guard PROXSUITE_LINALG_DENSE_LDLT_FACTORIZE_HPP */
#define VEG_ASSERT_ALL_OF(...)
#define VEG_ASSERT(...)
#define VEG_NO_INLINE
Definition macros.hpp:123
void apply_permutation_tri_lower(Mat &&mat, Work &&work, isize const *perm_indices)
Definition factorize.hpp:64
VEG_NO_INLINE void compute_permutation(isize *perm_indices, isize *perm_inv_indices, Diag const &diagonal)
Definition factorize.hpp:50
void factorize_unblocked_impl(Mat mat, proxsuite::linalg::veg::dynstack::DynStackMut stack)
Definition factorize.hpp:91
void factorize_blocked_impl(Mat mat, isize block_size, proxsuite::linalg::veg::dynstack::DynStackMut stack)
VEG_NO_INLINE void compute_permutation_impl(isize *perm_indices, isize *perm_inv_indices, isize n, T const *diagonal_data, isize stride)
Definition factorize.hpp:19
void factorize_recursive_impl(Mat mat, proxsuite::linalg::veg::dynstack::DynStackMut stack)
auto trans(Mat &&mat) noexcept -> Eigen::Map< _detail::const_if< _detail::ptr_is_const< decltype(mat.data())>::value, Eigen::Matrix< typename proxsuite::linalg::veg::uncvref_t< Mat >::Scalar, proxsuite::linalg::veg::uncvref_t< Mat >::ColsAtCompileTime, proxsuite::linalg::veg::uncvref_t< Mat >::RowsAtCompileTime, bool(proxsuite::linalg::veg::uncvref_t< Mat >::IsRowMajor) ? Eigen::ColMajor :Eigen::RowMajor > >, Eigen::Unaligned, _detail::StrideOf< proxsuite::linalg::veg::uncvref_t< Mat > > >
Definition core.hpp:597
void noalias_mul_add(Dst &&dst, Lhs const &lhs, Rhs const &rhs, T factor)
Definition core.hpp:839
auto subcols(Mat &&mat, isize col_start, isize ncols) noexcept -> Eigen::Map< _detail::const_if< _detail::ptr_is_const< decltype(mat.data())>::value, _detail::OwnedCols< proxsuite::linalg::veg::uncvref_t< Mat > > >, Eigen::Unaligned, _detail::StrideOf< proxsuite::linalg::veg::uncvref_t< Mat > > >
Definition core.hpp:771
auto diagonal(Mat &&mat) noexcept -> Eigen::Map< _detail::const_if< _detail::ptr_is_const< decltype(mat.data())>::value, Eigen::Matrix< typename proxsuite::linalg::veg::uncvref_t< Mat >::Scalar, Eigen::Dynamic, 1, Eigen::ColMajor > >, Eigen::Unaligned, Eigen::InnerStride< Eigen::Dynamic > >
Definition core.hpp:624
auto row(T &&mat, isize row_idx) noexcept -> typename _detail::RowColAccessImpl< !bool(proxsuite::linalg::veg::uncvref_t< T >::IsRowMajor)>::template Row< T >
Definition core.hpp:587
auto subrows(Mat &&mat, isize row_start, isize nrows) noexcept -> Eigen::Map< _detail::const_if< _detail::ptr_is_const< decltype(mat.data())>::value, _detail::OwnedRows< proxsuite::linalg::veg::uncvref_t< Mat > > >, Eigen::Unaligned, _detail::StrideOf< proxsuite::linalg::veg::uncvref_t< Mat > > >
Definition core.hpp:750
auto submatrix(Mat &&mat, isize row_start, isize col_start, isize nrows, isize ncols) noexcept -> Eigen::Map< _detail::const_if< _detail::ptr_is_const< decltype(mat.data())>::value, _detail::OwnedMatrix< proxsuite::linalg::veg::uncvref_t< Mat > > >, Eigen::Unaligned, _detail::StrideOf< proxsuite::linalg::veg::uncvref_t< Mat > > >
Definition core.hpp:645
auto to_view_dyn(Mat &&mat) noexcept -> Eigen::Map< _detail::const_if< _detail::ptr_is_const< decltype(mat.data())>::value, _detail::OwnedMatrix< proxsuite::linalg::veg::uncvref_t< Mat > > >, Eigen::Unaligned, _detail::StrideOf< proxsuite::linalg::veg::uncvref_t< Mat > > >
Definition core.hpp:730
auto col(T &&mat, isize col_idx) noexcept -> typename _detail::RowColAccessImpl< !bool(proxsuite::linalg::veg::uncvref_t< T >::IsRowMajor)>::template Col< T >
Definition core.hpp:578
auto factorize_recursive_req(proxsuite::linalg::veg::Tag< T > tag, isize n) noexcept -> proxsuite::linalg::veg::dynstack::StackReq
auto factorize_blocked_req(proxsuite::linalg::veg::Tag< T > tag, isize n, isize block_size) noexcept -> proxsuite::linalg::veg::dynstack::StackReq
auto factorize_unblocked_req(proxsuite::linalg::veg::Tag< T >, isize n) noexcept -> proxsuite::linalg::veg::dynstack::StackReq
void factorize_blocked(Mat &&mat, isize block_size, proxsuite::linalg::veg::dynstack::DynStackMut stack)
void factorize(Mat &&mat, proxsuite::linalg::veg::dynstack::DynStackMut stack)
void factorize_unblocked(Mat &&mat, proxsuite::linalg::veg::dynstack::DynStackMut stack)
void factorize_recursive(Mat &&mat, proxsuite::linalg::veg::dynstack::DynStackMut stack)
auto factorize_req(proxsuite::linalg::veg::Tag< T > tag, isize n) noexcept -> proxsuite::linalg::veg::dynstack::StackReq
VEG_NODISCARD auto ptr_mut() const VEG_NOEXCEPT -> void *