Skip to content

Commit

Permalink
feat: Sherman–Morrison formula
Browse files Browse the repository at this point in the history
  • Loading branch information
Tiphereth-A committed Mar 31, 2024
1 parent 588b43d commit 595e0a7
Show file tree
Hide file tree
Showing 9 changed files with 40 additions and 6 deletions.
3 changes: 3 additions & 0 deletions config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -959,6 +959,9 @@ notebook:
- mat_det_rd: 求矩阵的行列式(随机化算法)
code_ext: hpp
test_ext: cpp
- sherman_morrison: Sherman–Morrison 公式
code_ext: hpp
test_ext: cpp
- bitmat: 静态 Bool 矩阵
code_ext: hpp
test_ext: cpp
Expand Down
4 changes: 1 addition & 3 deletions src/code/lalg/mat_ge_xor.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,7 @@
namespace tifa_libs::math {

template <class Mat, class Is0>
requires std::same_as<typename Mat::value_type, bool> && requires(Is0 is0, bool t) {
{ is0(t) } -> std::same_as<bool>;
}
requires std::same_as<typename Mat::value_type, bool>
constexpr i32 ge_xor(Mat &mat, Is0, bool clear_u = true) {
u32 r_ = mat.row(), c_ = mat.col(), rk_max = std::min(r_, c_);
u32 rk = 0;
Expand Down
26 changes: 26 additions & 0 deletions src/code/lalg/sherman_morrison.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
#ifndef TIFALIBS_LALG_SHERMAN_MORRISON
#define TIFALIBS_LALG_SHERMAN_MORRISON

#include "../util/util.hpp"

namespace tifa_libs::math {

template <class Mat, class T = typename Mat::value_type>
requires std::same_as<T, typename Mat::value_type>
constexpr void sherman_morrison(Mat &inv_A, vec<T> const &u, vec<T> const &v) {
u32 n = inv_A.row();
assert(n == inv_A.col());
vec<T> x(n), y(n);
for (u32 i = 0; i < n; ++i)
for (u32 j = 0; j < n; ++j)
x[i] += inv_A[i][j] * u[j], y[j] += v[i] * inv_A[i][j];
T sum = 1;
for (u32 i = 0; i < n; ++i)
for (u32 j = 0; j < n; ++j) sum += v[i] * inv_A[i][j] * u[j];
for (u32 i = 0; i < n; ++i)
for (u32 j = 0; j < n; ++j) inv_A[i][j] -= x[i] * y[j] / sum;
}

} // namespace tifa_libs::math

#endif
Empty file.
7 changes: 7 additions & 0 deletions src/doc_tex/lalg/sherman_morrison.tex
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
根据方阵 \(A^{-1}\) 和列向量 \(u,v\) 计算 \((A+uv^T)^{-1}\)

\[
\left(A+uv^T\right)^{-1}=A^{-1}-\frac{A^{-1}uv^TA^{-1}}{1+v^TA^{-1}u}
\]

\paragraph{复杂度} \(O(n^2)\)
2 changes: 1 addition & 1 deletion src/meta_test/library-checker/matrix_det_arbitrary_mod.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ int main() {
mat a(n, n);
std::cin >> a;
auto is_0 = [](mint const &x) { return x.val() == 0; };
auto div = [](mint const &x, mint const &y) { return x.val() / y.val(); };
auto div = [](mint const &x, mint const &y) -> mint { return x.val() / y.val(); };
auto ge = [&is_0, &div](mat &m, bool f) { return tifa_libs::math::ge_euclid(m, is_0, div, f); };
std::cout << det(a, ge);
return 0;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ int main() {
mat a(n, n);
std::cin >> a;
auto is_0 = [](mint const &x) { return x.val() == 0; };
auto div = [](mint const &x, mint const &y) { return x.val() / y.val(); };
auto div = [](mint const &x, mint const &y) -> mint { return x.val() / y.val(); };
auto ge = [&is_0, &div](mat &m, bool f) { return tifa_libs::math::ge_euclid(m, is_0, div, f); };
std::cout << det(a, ge);
return 0;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ int main() {
mat a(n, n);
std::cin >> a;
auto is_0 = [](mint const &x) { return x.val() == 0; };
auto div = [](mint const &x, mint const &y) { return x.val() / y.val(); };
auto div = [](mint const &x, mint const &y) -> mint { return x.val() / y.val(); };
auto ge = [&is_0, &div](mat &m, bool f) { return tifa_libs::math::ge_euclid(m, is_0, div, f); };
std::cout << det(a, ge);
return 0;
Expand Down
Empty file.

0 comments on commit 595e0a7

Please sign in to comment.