proxsuite 0.6.7
The Advanced Proximal Optimization Toolbox
Loading...
Searching...
No Matches
update.hpp
Go to the documentation of this file.
1
2//
3// Copyright (c) 2022 INRIA
4//
5#ifndef PROXSUITE_LINALG_SPARSE_LDLT_UPDATE_HPP
6#define PROXSUITE_LINALG_SPARSE_LDLT_UPDATE_HPP
7
10#include <algorithm>
11
12namespace proxsuite {
13namespace linalg {
14namespace sparse {
15
16/*
17calcule mémoire nécessaire pour la fonction merge_second_col_into_first
18*/
19template<typename I>
20auto
22 isize second_size) noexcept
24{
25 return {
26 second_size * isize{ sizeof(I) },
27 alignof(I),
28 };
29}
30
31template<typename T, typename I>
32auto
34 I* difference,
35 T* first_values,
36 I* first_ptr,
41 bool move_values,
42 DynStackMut stack) noexcept(false)
44{
47
48 if (second.len() == 0) {
49 return {
50 proxsuite::linalg::veg::tuplify,
51 { unsafe, from_raw_parts, first_values, first_initial_len },
52 { unsafe, from_raw_parts, first_ptr, first_initial_len },
53 { unsafe, from_raw_parts, difference, 0 },
54 };
55 }
56
57 I const* second_ptr = second.ptr();
58 usize second_len = usize(second.len());
59
60 usize index_second = 0;
61
64 break;
65 }
66 }
68
71 index_second = 0;
72
74
75 auto _ins_pos = stack.make_new_for_overwrite(tag, isize(second_len));
76
77 I* insert_pos_ptr = _ins_pos.ptr_mut();
78 usize insert_count = 0;
79
82 while (true) {
83 if (!(index_second < second_len)) {
84 break;
85 }
86
89 break;
90 }
91
96 }
97
98 if (index_second == second_len) {
99 break;
100 }
102 ++index_second;
103 }
104 }
105
107 usize first_new_len =
110
112 std::memmove( //
115 append_count * sizeof(I));
116 std::memmove( //
119 append_count * sizeof(I));
120 if (move_values) {
121 for (usize i = 0; i < append_count; ++i) {
123 }
124 }
125
126 while (remaining_insert_count != 0) {
127
129 usize range_size =
133
134 usize old_pos = old_insert_pos;
135 usize new_pos = old_pos + remaining_insert_count;
136
137 std::memmove( //
139 first_ptr + old_pos,
140 range_size * sizeof(I));
141 if (move_values) {
142 std::memmove( //
144 first_values + old_pos,
145 range_size * sizeof(T));
146 first_values[new_pos - 1] = 0;
147 }
148
151 }
152
153 return {
154 proxsuite::linalg::veg::tuplify,
155 { unsafe, from_raw_parts, first_values, isize(first_new_len) },
156 { unsafe, from_raw_parts, first_ptr, isize(first_new_len) },
157 { unsafe, from_raw_parts, difference, isize(insert_count + append_count) },
158 };
159}
160
168template<typename T, typename I>
169auto
173 isize n,
174 bool id_perm,
176{
178 StackReq permuted_indices = { id_perm ? 0 : (col_nnz * isize{ sizeof(I) }),
179 isize{ alignof(I) } };
180 StackReq difference = { n * isize{ sizeof(I) }, isize{ alignof(I) } };
182
185
186 StackReq numerical_workspace = { n * isize{ sizeof(T) },
187 isize{ alignof(T) } };
188
190}
191
205template<typename T, typename I>
206auto
208 I* etree,
209 I const* perm_inv,
212 DynStackMut stack) noexcept(false) -> MatMut<T, I>
213{
214 VEG_ASSERT(!ld.is_compressed());
215
216 if (w.nnz() == 0) {
217 return ld;
218 }
219
221 usize n = usize(ld.ncols());
222 bool id_perm = perm_inv == nullptr;
223
225 stack.make_new_for_overwrite(tag, id_perm ? isize(0) : w.nnz());
226
227 auto w_permuted_indices =
228 id_perm ? w.row_indices() : _w_permuted_indices.ptr();
229 if (!id_perm) {
231 for (usize k = 0; k < usize(w.nnz()); ++k) {
232 usize i = util::zero_extend(w.row_indices()[k]);
233 pw_permuted_indices[k] = perm_inv[i];
234 }
235 std::sort(pw_permuted_indices, pw_permuted_indices + w.nnz());
236 }
237
238 auto sx = util::sign_extend;
239 auto zx = util::zero_extend;
240 // symbolic update
241 {
242 usize current_col = zx(w_permuted_indices[0]);
243
244 auto _difference =
245 stack.make_new_for_overwrite(tag, isize(n - current_col));
246 auto _difference_backup =
247 stack.make_new_for_overwrite(tag, isize(n - current_col));
248
250 isize merge_col_len = w.nnz();
251 I* difference = _difference.ptr_mut();
252
253 while (true) {
254 usize old_parent = sx(etree[isize(current_col)]);
255
256 usize current_ptr_idx = zx(ld.col_ptrs()[isize(current_col)]);
257 usize next_ptr_idx = zx(ld.col_ptrs()[isize(current_col) + 1]);
258
259 VEG_BIND(auto,
263 ld.values_mut() + (current_ptr_idx + 1),
264 ld.row_indices_mut() + (current_ptr_idx + 1),
266 isize(zx(ld.nnz_per_col()[isize(current_col)])) - 1,
268 unsafe, from_raw_parts, merge_col, merge_col_len },
269 I(current_col),
270 true,
271 stack));
272
273 (void)_;
274 ld._set_nnz(ld.nnz() + new_current_col.len() + 1 -
275 isize(ld.nnz_per_col()[isize(current_col)]));
276 ld.nnz_per_col_mut()[isize(current_col)] = I(new_current_col.len() + 1);
277
278 usize new_parent =
279 (new_current_col.len() == 0) ? usize(-1) : sx(new_current_col[0]);
280
281 if (new_parent == usize(-1)) {
282 break;
283 }
284
285 if (new_parent == old_parent) {
288 difference = _difference_backup.ptr_mut();
289 } else {
292 difference = _difference.ptr_mut();
293 etree[isize(current_col)] = I(new_parent);
294 }
295
296 current_col = new_parent;
297 }
298 }
299
300 // numerical update
301 {
302 usize first_col = zx(w_permuted_indices[0]);
303 auto _work =
304 stack.make_new_for_overwrite(proxsuite::linalg::veg::Tag<T>{}, isize(n));
305 T* pwork = _work.ptr_mut();
306
307 for (usize col = first_col; col != usize(-1); col = sx(etree[isize(col)])) {
308 pwork[col] = 0;
309 }
310 for (usize p = 0; p < usize(w.nnz()); ++p) {
311 pwork[id_perm ? zx(w.row_indices()[isize(p)])
312 : zx(perm_inv[w.row_indices()[isize(p)]])] =
313 w.values()[isize(p)];
314 }
315
316 I const* pldi = ld.row_indices();
317 T* pldx = ld.values_mut();
318
319 for (usize col = first_col; col != usize(-1); col = sx(etree[isize(col)])) {
320 auto col_start = ld.col_start(col);
321 auto col_end = ld.col_end(col);
322
323 T w0 = pwork[col];
324 T old_d = pldx[col_start];
325 T new_d = old_d + alpha * w0 * w0;
326 T beta = alpha * w0 / new_d;
327 alpha = alpha - new_d * beta * beta;
328
329 pldx[col_start] = new_d;
330 pwork[col] -= w0;
331
332 for (usize p = col_start + 1; p < col_end; ++p) {
333 usize i = util::zero_extend(pldi[p]);
334
335 T tmp = pldx[p];
336 pwork[i] = pwork[i] - w0 * tmp;
337 pldx[p] = tmp + beta * pwork[i];
338 }
339 }
340 }
341
342 return ld;
343}
344} // namespace sparse
345} // namespace linalg
346} // namespace proxsuite
347
348#endif /* end of include guard PROXSUITE_LINALG_SPARSE_LDLT_UPDATE_HPP */
#define VEG_ASSERT(...)
#define PROXSUITE_MAYBE_UNUSED
Definition fwd.hpp:20
#define VEG_CHECK_CONCEPT(...)
Definition macros.hpp:1241
auto merge_second_col_into_first(I *difference, T *first_values, I *first_ptr, PROXSUITE_MAYBE_UNUSED isize first_full_len, isize first_initial_len, Slice< I > second, proxsuite::linalg::veg::DoNotDeduce< I > ignore_threshold_inclusive, bool move_values, DynStackMut stack) noexcept(false) -> proxsuite::linalg::veg::Tuple< SliceMut< T >, SliceMut< I >, SliceMut< I > >
Definition update.hpp:33
VEG_INLINE void etree(I *parent, SymbolicMatRef< I > a, DynStackMut stack) noexcept
auto rank1_update_req(proxsuite::linalg::veg::Tag< T >, proxsuite::linalg::veg::Tag< I >, isize n, bool id_perm, isize col_nnz) noexcept -> proxsuite::linalg::veg::dynstack::StackReq
Definition update.hpp:170
auto rank1_update(MatMut< T, I > ld, I *etree, I const *perm_inv, VecRef< T, I > w, proxsuite::linalg::veg::DoNotDeduce< T > alpha, DynStackMut stack) noexcept(false) -> MatMut< T, I >
Definition update.hpp:207
auto merge_second_col_into_first_req(proxsuite::linalg::veg::Tag< I >, isize second_size) noexcept -> proxsuite::linalg::veg::dynstack::StackReq
Definition update.hpp:21
#define VEG_BIND(CV_Auto, Identifiers, Tuple)
Definition tuple.hpp:53