Maniverse 0.2.1__tar.gz → 0.2.3__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of Maniverse might be problematic. Click here for more details.

Files changed (41) hide show
  1. {Maniverse-0.2.1 → Maniverse-0.2.3/Maniverse.egg-info}/PKG-INFO +1 -1
  2. Maniverse-0.2.3/Maniverse.egg-info/SOURCES.txt +41 -0
  3. Maniverse-0.2.3/Maniverse.egg-info/top_level.txt +1 -0
  4. Maniverse-0.2.3/PKG-INFO +8 -0
  5. Maniverse-0.2.3/pyproject.toml +3 -0
  6. Maniverse-0.2.3/setup.py +66 -0
  7. Maniverse-0.2.3/src/Macro.h +19 -0
  8. Maniverse-0.2.3/src/Manifold/Grassmann.cpp +147 -0
  9. Maniverse-0.2.3/src/Manifold/Grassmann.h +27 -0
  10. Maniverse-0.2.3/src/Manifold/Manifold.cpp +220 -0
  11. Maniverse-0.2.3/src/Manifold/Manifold.h +47 -0
  12. Maniverse-0.2.3/src/Manifold/Orthogonal.cpp +150 -0
  13. Maniverse-0.2.3/src/Manifold/Orthogonal.h +23 -0
  14. Maniverse-0.2.3/src/Manifold/PyManifoldIn.h +5 -0
  15. Maniverse-0.2.3/src/Manifold/PyManifoldOut.h +5 -0
  16. Maniverse-0.2.3/src/Manifold/Simplex.cpp +105 -0
  17. Maniverse-0.2.3/src/Manifold/Simplex.h +24 -0
  18. Maniverse-0.2.3/src/Manifold/TransRotInvPointCloud.cpp +154 -0
  19. Maniverse-0.2.3/src/Manifold/TransRotInvPointCloud.h +23 -0
  20. Maniverse-0.2.3/src/Manifold/makefile +18 -0
  21. Maniverse-0.2.3/src/Maniverse.egg-info/SOURCES.txt +8 -0
  22. Maniverse-0.2.3/src/Maniverse.egg-info/top_level.txt +2 -0
  23. Maniverse-0.2.3/src/Optimizer/HessUpdate.cpp +208 -0
  24. Maniverse-0.2.3/src/Optimizer/HessUpdate.h +21 -0
  25. Maniverse-0.2.3/src/Optimizer/PyOptimizerIn.h +3 -0
  26. Maniverse-0.2.3/src/Optimizer/PyOptimizerOut.h +3 -0
  27. Maniverse-0.2.3/src/Optimizer/SubSolver.cpp +121 -0
  28. Maniverse-0.2.3/src/Optimizer/SubSolver.h +16 -0
  29. Maniverse-0.2.3/src/Optimizer/TrustRegion.cpp +199 -0
  30. Maniverse-0.2.3/src/Optimizer/TrustRegion.h +33 -0
  31. Maniverse-0.2.3/src/Optimizer/makefile +12 -0
  32. Maniverse-0.2.3/src/PyManiverse.cpp +10 -0
  33. Maniverse-0.2.3/src/makefile +12 -0
  34. Maniverse-0.2.1/Maniverse.egg-info/SOURCES.txt +0 -8
  35. Maniverse-0.2.1/setup.py +0 -73
  36. {Maniverse-0.2.1 → Maniverse-0.2.3}/LICENSE +0 -0
  37. {Maniverse-0.2.1 → Maniverse-0.2.3}/Maniverse.egg-info/dependency_links.txt +0 -0
  38. {Maniverse-0.2.1 → Maniverse-0.2.3}/README.md +0 -0
  39. {Maniverse-0.2.1 → Maniverse-0.2.3}/setup.cfg +0 -0
  40. {Maniverse-0.2.1 → Maniverse-0.2.3/src}/Maniverse.egg-info/PKG-INFO +0 -0
  41. /Maniverse-0.2.1/Maniverse.egg-info/top_level.txt → /Maniverse-0.2.3/src/Maniverse.egg-info/dependency_links.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: Maniverse
3
- Version: 0.2.1
3
+ Version: 0.2.3
4
4
  Summary: Function optimization on manifolds
5
5
  Home-page: https://github.com/FreemanTheMaverick/Maniverse.git
6
6
  Author: FreemanTheMaverick
@@ -0,0 +1,41 @@
1
+ LICENSE
2
+ README.md
3
+ pyproject.toml
4
+ setup.cfg
5
+ setup.py
6
+ Maniverse.egg-info/PKG-INFO
7
+ Maniverse.egg-info/SOURCES.txt
8
+ Maniverse.egg-info/dependency_links.txt
9
+ Maniverse.egg-info/top_level.txt
10
+ src/Macro.h
11
+ src/Manifold
12
+ src/Maniverse.egg-info
13
+ src/Optimizer
14
+ src/PyManiverse.cpp
15
+ src/makefile
16
+ src/Manifold/Grassmann.cpp
17
+ src/Manifold/Grassmann.h
18
+ src/Manifold/Manifold.cpp
19
+ src/Manifold/Manifold.h
20
+ src/Manifold/Orthogonal.cpp
21
+ src/Manifold/Orthogonal.h
22
+ src/Manifold/PyManifoldIn.h
23
+ src/Manifold/PyManifoldOut.h
24
+ src/Manifold/Simplex.cpp
25
+ src/Manifold/Simplex.h
26
+ src/Manifold/TransRotInvPointCloud.cpp
27
+ src/Manifold/TransRotInvPointCloud.h
28
+ src/Manifold/makefile
29
+ src/Maniverse.egg-info/PKG-INFO
30
+ src/Maniverse.egg-info/SOURCES.txt
31
+ src/Maniverse.egg-info/dependency_links.txt
32
+ src/Maniverse.egg-info/top_level.txt
33
+ src/Optimizer/HessUpdate.cpp
34
+ src/Optimizer/HessUpdate.h
35
+ src/Optimizer/PyOptimizerIn.h
36
+ src/Optimizer/PyOptimizerOut.h
37
+ src/Optimizer/SubSolver.cpp
38
+ src/Optimizer/SubSolver.h
39
+ src/Optimizer/TrustRegion.cpp
40
+ src/Optimizer/TrustRegion.h
41
+ src/Optimizer/makefile
@@ -0,0 +1 @@
1
+ Maniverse
@@ -0,0 +1,8 @@
1
+ Metadata-Version: 2.1
2
+ Name: Maniverse
3
+ Version: 0.2.3
4
+ Summary: Function optimization on manifolds
5
+ Home-page: https://github.com/FreemanTheMaverick/Maniverse.git
6
+ Author: FreemanTheMaverick
7
+ Classifier: Programming Language :: Python :: 3
8
+ License-File: LICENSE
@@ -0,0 +1,3 @@
1
+ [build-system]
2
+ requires = ["setuptools", "pybind11", "wget"]
3
+ build_backend = "setuptools.build_meta"
@@ -0,0 +1,66 @@
1
+ import os
2
+ import wget
3
+ import tarfile
4
+ import subprocess
5
+ from glob import glob
6
+ from setuptools import setup, find_packages
7
+ from setuptools.command.build import build
8
+ import pybind11
9
+ from pybind11.setup_helpers import Pybind11Extension, ParallelCompile, naive_recompile
10
+
11
+ __version__ = "0.2.3"
12
+ pwd = os.path.dirname(__file__)
13
+
14
+ # Checking dependencies
15
+ PYTHON3 = os.getenv("PYTHON3", default = '')
16
+ print("Looking for Python.h at %s ..." % PYTHON3, end='')
17
+ if os.path.isfile(PYTHON3 + "/Python.h"):
18
+ print("Found!")
19
+ else:
20
+ raise RuntimeError("Python.h does not exist!")
21
+ EIGEN3 = os.getenv("EIGEN3", default = '')
22
+ if len(EIGEN3) > 0:
23
+ print("Looking for Eigen3 at %s ..." % EIGEN3, end='')
24
+ if os.path.exists(EIGEN3 + "/Eigen/") and os.path.exists(EIGEN3 + "/unsupported/") and os.path.isfile(EIGEN3 + "/signature_of_eigen3_matrix_library"):
25
+ print("Found!")
26
+ else:
27
+ raise RuntimeError("Python.h does not exist!")
28
+ else:
29
+ print("The environment variable $EIGEN3 is not set. -> Downloading ...")
30
+ filename = wget.download("https://gitlab.com/libeigen/eigen/-/archive/3.4-rc1/eigen-3.4-rc1.tar.gz", bar = None)
31
+ with tarfile.open(filename) as tar:
32
+ tar.extractall(path = pwd) # Directory: eigen-3.4-rc1
33
+ EIGEN3 = pwd + "/eigen-3.4-rc1/"
34
+ print("EIGEN3 is %s." % EIGEN3)
35
+ PYBIND11 = pybind11.get_include()
36
+ print("PYBIND11 is %s." % PYBIND11)
37
+
38
+ BASE_DIR = os.path.dirname(__file__)
39
+ os.chdir(BASE_DIR)
40
+
41
+ ParallelCompile(
42
+ "NPY_NUM_BUILD_JOBS",
43
+ needs_recompile = naive_recompile,
44
+ default = 4
45
+ ).install()
46
+
47
+ ext_modules = [ Pybind11Extension(
48
+ "Maniverse",
49
+ sorted(glob("src/*")) + sorted(glob("src/*/*")),
50
+ define_macros = ["__PYTHON__", "EIGEN_INITIALIZE_MATRICES_BY_ZERO"],
51
+ undef_macros = ["DEBUG"],
52
+ include_dirs = [PYTHON3, EIGEN3, PYBIND11],
53
+ extra_compile_args = ["-O3"],
54
+ cxx_std = 17,
55
+ language = "c++"
56
+ )]
57
+
58
+ setup(
59
+ name = "Maniverse",
60
+ version = __version__,
61
+ author = "FreemanTheMaverick",
62
+ description = "Function optimization on manifolds",
63
+ ext_modules = ext_modules,
64
+ url = "https://github.com/FreemanTheMaverick/Maniverse.git",
65
+ classifiers = ["Programming Language :: Python :: 3"]
66
+ )
@@ -0,0 +1,19 @@
1
+ #define EigenArray Eigen::ArrayXd
2
+ #define EigenVector Eigen::VectorXd
3
+ #define EigenDiagonal Eigen::DiagonalMatrix<double, -1, -1>
4
+ #define EigenMatrix Eigen::MatrixXd
5
+ #define EigenZero Eigen::MatrixXd::Zero
6
+ #define EigenOne Eigen::MatrixXd::Identity
7
+
8
+ #define Diag(X) (X).diagonal().asDiagonal()
9
+ #define Dot(X, Y) ( (X).transpose() * (Y) ).trace()
10
+
11
+ #define __Not_Implemented__\
12
+ std::string func_name = __func__;\
13
+ std::string class_name = typeid(*this).name();\
14
+ throw std::runtime_error(func_name + " for " + class_name + " is not implemented!");
15
+
16
+ #define __True_False__(x) ( x ? "True" : "False" )
17
+
18
+ #define __now__ std::chrono::high_resolution_clock::now()
19
+ #define __duration__(start, end) std::chrono::duration<double>(end - start).count()
@@ -0,0 +1,147 @@
1
+ #ifdef __PYTHON__
2
+ #include <pybind11/pybind11.h>
3
+ #include <pybind11/stl.h>
4
+ #include <pybind11/eigen.h>
5
+ #include <pybind11/functional.h>
6
+ #endif
7
+ #include <Eigen/Dense>
8
+ #include <unsupported/Eigen/MatrixFunctions>
9
+ #include <cmath>
10
+ #include <functional>
11
+ #include <tuple>
12
+ #include <cassert>
13
+ #include <memory>
14
+
15
+ #include "../Macro.h"
16
+
17
+ #include "Grassmann.h"
18
+
19
+ #include <iostream>
20
+
21
+
22
+ Grassmann::Grassmann(EigenMatrix p, bool matrix_free): Manifold(p, matrix_free){
23
+ this->Name = "Grassmann";
24
+ this->P.resize(p.rows(), p.cols());
25
+ this->Ge.resize(p.rows(), p.cols());
26
+ this->Gr.resize(p.rows(), p.cols());
27
+ this->P = p;
28
+ Eigen::SelfAdjointEigenSolver<EigenMatrix> eigensolver;
29
+ eigensolver.compute(p);
30
+ const EigenVector eigenvalues = eigensolver.eigenvalues();
31
+ const EigenMatrix eigenvectors = eigensolver.eigenvectors();
32
+ int rank = 0;
33
+ for ( int i = 0; i < p.rows(); i++ )
34
+ if ( eigenvalues(i) > 0.5 ) rank++;
35
+ this->Projector.resize(p.rows(), rank);
36
+ this->Projector = eigenvectors.rightCols(rank);
37
+ }
38
+
39
+ int Grassmann::getDimension() const{
40
+ const double rank = this->Projector.cols();
41
+ return rank * ( this->P.rows() - rank );
42
+ }
43
+
44
+ double Grassmann::Inner(EigenMatrix X, EigenMatrix Y) const{
45
+ return Dot(X, Y);
46
+ }
47
+
48
+ EigenMatrix Grassmann::Exponential(EigenMatrix X) const{
49
+ const EigenMatrix Xp = X * this->P - this->P * X;
50
+ const EigenMatrix pX = - Xp;
51
+ const EigenMatrix expXp = Xp.exp();
52
+ const EigenMatrix exppX = pX.exp();
53
+ return expXp * this->P * exppX;
54
+ }
55
+
56
+ EigenMatrix Grassmann::Logarithm(Manifold& N) const{
57
+ for ( auto& [cached_NP, cached_Log] : this->LogCache )
58
+ if ( N.P.isApprox(cached_NP) ) return cached_Log;
59
+ __Check_Log_Map__
60
+ Grassmann& N_ = dynamic_cast<Grassmann&>(N);
61
+ const EigenMatrix U = this->Projector;
62
+ const EigenMatrix Y = N_.Projector;
63
+ Eigen::JacobiSVD<EigenMatrix> svd;
64
+ svd.compute(Y.transpose() * U, Eigen::ComputeFullU | Eigen::ComputeFullV);
65
+ const EigenMatrix Ystar = Y * svd.matrixU() * svd.matrixV().transpose();
66
+ svd.compute( (EigenOne(U.rows(), U.rows()) - U * U.transpose() ) * Ystar);
67
+ const EigenArray Sigma = svd.singularValues().array().asin();
68
+ EigenMatrix SIGMA = EigenZero(U.rows(), U.cols());
69
+ for ( int i = 0; i < Sigma.size(); i++ ) SIGMA(i, i) = Sigma[i];
70
+ const EigenMatrix Delta = svd.matrixU() * SIGMA * svd.matrixV().transpose();
71
+ const EigenMatrix Log = Delta * U.transpose() + U * Delta.transpose();
72
+ const EigenMatrix result = this->TangentPurification(Log);
73
+ this->LogCache.push_back(std::make_tuple(N_.P, result));
74
+ return result;
75
+ }
76
+
77
+ EigenMatrix Grassmann::TangentProjection(EigenMatrix X) const{
78
+ // X must be symmetric.
79
+ // https://sites.uclouvain.be/absil/2013.01
80
+ const EigenMatrix adPX = this->P * X - X * this->P;
81
+ return this->P * adPX - adPX * this->P;
82
+ }
83
+
84
+ EigenMatrix Grassmann::TangentPurification(EigenMatrix A) const{
85
+ const EigenMatrix symA = 0.5 * ( A + A.transpose() );
86
+ const EigenMatrix pureA = symA - this->P * symA * this->P;
87
+ return 0.5 * ( pureA + pureA.transpose() );
88
+ }
89
+
90
+ EigenMatrix Grassmann::TransportTangent(EigenMatrix X, EigenMatrix Y) const{
91
+ // X - Vector to transport from P
92
+ // Y - Destination on the tangent space of P
93
+ for ( auto& [cached_Y, cached_expdp, cached_exppd]: this->TransportTangentCache )
94
+ if ( Y.isApprox(cached_Y) ) return cached_expdp * X * cached_exppd;
95
+ const EigenMatrix dp = Y * this->P - this->P * Y;
96
+ const EigenMatrix pd = - dp;
97
+ const EigenMatrix expdp = dp.exp();
98
+ const EigenMatrix exppd = pd.exp();
99
+ this->TransportTangentCache.push_back(std::make_tuple(Y, expdp, exppd));
100
+ return expdp * X * exppd;
101
+ }
102
+
103
+ EigenMatrix Grassmann::TransportManifold(EigenMatrix X, Manifold& N) const{
104
+ // X - Vector to transport from P
105
+ __Check_Vec_Transport__
106
+ Grassmann& N_ = dynamic_cast<Grassmann&>(N);
107
+ const EigenMatrix Y = this->Logarithm(N_);
108
+ return this->TransportTangent(X, Y);
109
+ }
110
+
111
+ void Grassmann::Update(EigenMatrix p, bool purify){
112
+ this->P = p;
113
+ Eigen::SelfAdjointEigenSolver<EigenMatrix> eigensolver;
114
+ eigensolver.compute(p);
115
+ const EigenMatrix eigenvectors = eigensolver.eigenvectors();
116
+ const int ncols = this->Projector.cols();
117
+ this->Projector = eigenvectors.rightCols(ncols);
118
+ this->LogCache.clear();
119
+ this->TransportTangentCache.clear();
120
+ if (purify) this->P = this->Projector * this->Projector.transpose();
121
+ }
122
+
123
+ void Grassmann::getGradient(){
124
+ this->Gr = this->TangentPurification(this->TangentProjection(this->Ge));
125
+ }
126
+
127
+ void Grassmann::getHessian(){
128
+ // https://arxiv.org/abs/0709.2205
129
+ this->Hr = [P = this->P, Ge = this->Ge, He = this->He](EigenMatrix v){
130
+ const EigenMatrix he = He(v);
131
+ const EigenMatrix partA = P * he - he * P;
132
+ const EigenMatrix partB = Ge * v - v * Ge;
133
+ const EigenMatrix sum = partA - partB;
134
+ return (EigenMatrix)(P * sum - sum * P);
135
+ };
136
+ }
137
+
138
+ std::unique_ptr<Manifold> Grassmann::Clone() const{
139
+ return std::make_unique<Grassmann>(*this);
140
+ }
141
+
142
+ #ifdef __PYTHON__
143
+ void Init_Grassmann(pybind11::module_& m){
144
+ pybind11::class_<Grassmann, Manifold>(m, "Grassmann")
145
+ .def(pybind11::init<EigenMatrix, bool>());
146
+ }
147
+ #endif
@@ -0,0 +1,27 @@
1
+ #include "Manifold.h"
2
+
3
+ class Grassmann: public Manifold{ public:
4
+ EigenMatrix Projector;
5
+ mutable std::vector<std::tuple<EigenMatrix, EigenMatrix>> LogCache;
6
+ mutable std::vector<std::tuple<EigenMatrix, EigenMatrix, EigenMatrix>> TransportTangentCache;
7
+
8
+ Grassmann(EigenMatrix p, bool matrix_free);
9
+
10
+ int getDimension() const override;
11
+ double Inner(EigenMatrix X, EigenMatrix Y) const override;
12
+
13
+ EigenMatrix Exponential(EigenMatrix X) const override;
14
+ EigenMatrix Logarithm(Manifold& N) const override;
15
+
16
+ EigenMatrix TangentProjection(EigenMatrix A) const override;
17
+ EigenMatrix TangentPurification(EigenMatrix A) const override;
18
+
19
+ EigenMatrix TransportTangent(EigenMatrix X, EigenMatrix Y) const override;
20
+ EigenMatrix TransportManifold(EigenMatrix X, Manifold& N) const override;
21
+
22
+ void Update(EigenMatrix p, bool purify) override;
23
+ void getGradient() override;
24
+ void getHessian() override;
25
+
26
+ std::unique_ptr<Manifold> Clone() const override;
27
+ };
@@ -0,0 +1,220 @@
1
+ #ifdef __PYTHON__
2
+ #include <pybind11/pybind11.h>
3
+ #include <pybind11/stl.h>
4
+ #include <pybind11/eigen.h>
5
+ #include <pybind11/functional.h>
6
+ #endif
7
+ #include <Eigen/Dense>
8
+ #include <typeinfo>
9
+ #include <memory>
10
+
11
+ #include "../Macro.h"
12
+
13
+ #include "Manifold.h"
14
+
15
+ #include <iostream>
16
+
17
+
18
+ Manifold::Manifold(EigenMatrix p, bool matrix_free){
19
+ this->P.resize(p.rows(), p.cols());
20
+ this->Ge.resize(p.rows(), p.cols());
21
+ this->Gr.resize(p.rows(), p.cols());
22
+ this->P = p;
23
+ this->MatrixFree = matrix_free;
24
+ if (this->MatrixFree){
25
+ this->Hem.resize(0, 0);
26
+ this->Hrm.resize(0);
27
+ }
28
+ }
29
+
30
+ int Manifold::getDimension() const{
31
+ __Not_Implemented__
32
+ return 0;
33
+ }
34
+
35
+ double Manifold::Inner(EigenMatrix X, EigenMatrix Y) const{
36
+ __Not_Implemented__
37
+ return X.rows() * Y.cols() * 0; // Avoiding the unused-variable warning
38
+ }
39
+
40
+ static std::tuple<EigenVector, EigenMatrix> ThinEigen(EigenMatrix A, int m){
41
+ // n - Total number of eigenvalues
42
+ // m - Number of non-trivial eigenvalues
43
+ const int n = A.rows();
44
+ Eigen::SelfAdjointEigenSolver<EigenMatrix> es;
45
+ es.compute(A);
46
+ std::vector<std::tuple<double, EigenVector>> eigen_tuples;
47
+ eigen_tuples.reserve(n);
48
+ for ( int i = 0; i < n; i++ )
49
+ eigen_tuples.push_back(std::make_tuple(es.eigenvalues()(i), es.eigenvectors().col(i)));
50
+ std::sort( // Sorting the eigenvalues in decreasing order of magnitude.
51
+ eigen_tuples.begin(), eigen_tuples.end(),
52
+ [](std::tuple<double, EigenVector>& a, std::tuple<double, EigenVector>& b){
53
+ return std::abs(std::get<0>(a)) > std::abs(std::get<0>(b));
54
+ }
55
+ ); // Now the eigenvalues closest to zero are in the back.
56
+ eigen_tuples.resize(m); // Deleting them.
57
+ std::sort( // Resorting the eigenvalues in increasing order.
58
+ eigen_tuples.begin(), eigen_tuples.end(),
59
+ [](std::tuple<double, EigenVector>& a, std::tuple<double, EigenVector>& b){
60
+ return std::get<0>(a) < std::get<0>(b);
61
+ }
62
+ );
63
+ EigenVector eigenvalues = EigenZero(m, 1);
64
+ EigenMatrix eigenvectors = EigenZero(n, m);
65
+ for ( int i = 0; i < m; i++ ){
66
+ eigenvalues(i) = std::get<0>(eigen_tuples[i]);
67
+ eigenvectors.col(i) = std::get<1>(eigen_tuples[i]);
68
+ }
69
+ return std::make_tuple(eigenvalues, eigenvectors);
70
+ }
71
+
72
+ void Manifold::getBasisSet(){
73
+ const int nrows = this->P.rows();
74
+ const int ncols = this->P.cols();
75
+ const int size = nrows * ncols;
76
+ const int rank = this->getDimension();
77
+ EigenMatrix euclidean_basis = EigenZero(nrows, ncols);
78
+ std::vector<EigenMatrix> unorthogonal_basis_set(size, EigenZero(nrows, ncols));
79
+ for ( int i = 0, n = 0; i < nrows; i++ ) for ( int j = 0; j < ncols; j++ , n++){
80
+ euclidean_basis(i, j) = 1;
81
+ unorthogonal_basis_set[n] = TangentProjection(euclidean_basis);
82
+ euclidean_basis(i, j) = 0;
83
+ }
84
+ EigenMatrix gram = EigenZero(size, size);
85
+ for ( int i = 0; i < size; i++ ) for ( int j = 0; j <= i; j++ ){
86
+ gram(i, j) = gram(j, i) = this->Inner(unorthogonal_basis_set[i], unorthogonal_basis_set[j]);
87
+ }
88
+ auto [Sigma, U] = ThinEigen(gram, rank);
89
+ const EigenMatrix C = U * Sigma.cwiseSqrt().asDiagonal();
90
+ this->BasisSet.resize(rank);
91
+ for ( int i = 0; i < rank; i++ ){
92
+ this->BasisSet[i].resize(nrows, ncols); this->BasisSet[i].setZero();
93
+ for ( int j = 0; j < size; j++ ){
94
+ this->BasisSet[i] += C(j, i) * unorthogonal_basis_set[j].reshaped<Eigen::RowMajor>(nrows, ncols);
95
+ }
96
+ }
97
+ }
98
+
99
+ std::vector<std::tuple<double, EigenMatrix>> Diagonalize(
100
+ EigenMatrix& A, std::vector<EigenMatrix>& basis_set){
101
+ Eigen::SelfAdjointEigenSolver<EigenMatrix> es;
102
+ es.compute( ( A + A.transpose() ) / 2 );
103
+ const EigenMatrix Lambda = es.eigenvalues();
104
+ const EigenMatrix Y = es.eigenvectors();
105
+ const int nrows = basis_set[0].rows();
106
+ const int ncols = basis_set[0].cols();
107
+ const int rank = basis_set.size();
108
+ std::vector<std::tuple<double, EigenMatrix>> hrm(rank, std::tuple(0, EigenZero(nrows, ncols)));
109
+ for ( int i = 0; i < rank; i++ ){
110
+ std::get<0>(hrm[i]) = Lambda(i);
111
+ for ( int j = 0; j < rank; j++ ){
112
+ std::get<1>(hrm[i]) += basis_set[j] * Y(j, i);
113
+ }
114
+ }
115
+ return hrm;
116
+ }
117
+
118
+ void Manifold::getHessianMatrix(){
119
+ // Representing the Riemannian hessian with the orthogonal basis set
120
+ const int rank = this->getDimension();
121
+ EigenMatrix hrm = EigenZero(rank, rank);
122
+ for ( int i = 0; i < rank; i++ ) for ( int j = 0; j <= i; j++ ){
123
+ hrm(i, j) = hrm(j, i) = this->Inner(this->BasisSet[i], this->Hr(this->BasisSet[j]));
124
+ }
125
+
126
+ // Diagonalizing the Riemannian hessian and representing the eigenvectors in Euclidean space
127
+ this->Hrm = Diagonalize(hrm, this->BasisSet);
128
+
129
+ // Updating the Riemannian hessian operator
130
+ this->Hr = [&hrm = this->Hrm](EigenMatrix v){ // Passing reference instead of value to std::function, so that the eigenvalues can be modified elsewhere without rewriting this part.
131
+ EigenMatrix Hv = EigenZero(v.rows(), v.cols());
132
+ for ( auto [eigenvalue, eigenvector] : hrm ){
133
+ Hv += eigenvalue * eigenvector.cwiseProduct(v).sum() * eigenvector;
134
+ }
135
+ return Hv;
136
+ };
137
+ }
138
+
139
+ EigenMatrix Manifold::Exponential(EigenMatrix X) const{
140
+ __Not_Implemented__
141
+ return EigenZero(X.rows(), X.cols());
142
+ }
143
+
144
+ EigenMatrix Manifold::Logarithm(Manifold& N) const{
145
+ __Not_Implemented__
146
+ return EigenZero(N.P.rows(), N.P.cols());
147
+ }
148
+
149
+ EigenMatrix Manifold::TangentProjection(EigenMatrix A) const{
150
+ __Not_Implemented__
151
+ return EigenZero(A.rows(), A.cols());
152
+ }
153
+
154
+ EigenMatrix Manifold::TangentPurification(EigenMatrix A) const{
155
+ __Not_Implemented__
156
+ return EigenZero(A.rows(), A.cols());
157
+ }
158
+
159
+ EigenMatrix Manifold::TransportTangent(EigenMatrix X, EigenMatrix Y) const{
160
+ __Not_Implemented__
161
+ return EigenZero(X.rows(), Y.cols());
162
+ }
163
+
164
+ EigenMatrix Manifold::TransportManifold(EigenMatrix X, Manifold& N) const{
165
+ __Not_Implemented__
166
+ return EigenZero(X.rows(), N.P.cols());
167
+ }
168
+
169
+ void Manifold::Update(EigenMatrix p, bool purify){
170
+ if ( purify ? p.rows() : p.cols() ){ // To avoid the unused-variable warning.
171
+ __Not_Implemented__
172
+ }else{
173
+ __Not_Implemented__
174
+ }
175
+ }
176
+
177
+ void Manifold::getGradient(){
178
+ __Not_Implemented__
179
+ }
180
+
181
+ void Manifold::getHessian(){
182
+ __Not_Implemented__
183
+ }
184
+
185
+ std::unique_ptr<Manifold> Manifold::Clone() const{
186
+ __Not_Implemented__
187
+ return std::make_unique<Manifold>(*this);
188
+ }
189
+
190
+ #ifdef __PYTHON__
191
+ void Init_Manifold(pybind11::module_& m){
192
+ pybind11::class_<Manifold>(m, "Manifold")
193
+ .def_readwrite("Name", &Manifold::Name)
194
+ .def_readwrite("P", &Manifold::P)
195
+ .def_readwrite("Ge", &Manifold::Ge)
196
+ .def_readwrite("Gr", &Manifold::Gr)
197
+ .def_readwrite("MatrixFree", &Manifold::MatrixFree)
198
+ .def_readwrite("Hem", &Manifold::Hem)
199
+ .def_readwrite("Hrm", &Manifold::Hrm)
200
+ .def_readwrite("He", &Manifold::He)
201
+ .def_readwrite("Hr", &Manifold::Hr)
202
+ .def_readwrite("BasisSet", &Manifold::BasisSet)
203
+ .def(pybind11::init<EigenMatrix, bool>())
204
+ .def("getDimension", &Manifold::getDimension)
205
+ .def("Inner", &Manifold::Inner)
206
+ .def("getBasisSet", &Manifold::getBasisSet)
207
+ .def("getHessianMatrix", &Manifold::getHessianMatrix)
208
+ .def("Exponential", &Manifold::Exponential)
209
+ .def("Logarithm", &Manifold::Logarithm)
210
+ .def("TangentProjection", &Manifold::TangentProjection)
211
+ .def("TangentPurification", &Manifold::TangentPurification)
212
+ .def("TransportTangent", &Manifold::TransportTangent)
213
+ .def("TransportManifold", &Manifold::TransportManifold)
214
+ .def("Update", &Manifold::Update)
215
+ .def("getGradient", &Manifold::getGradient)
216
+ .def("getHessian", &Manifold::getHessian)
217
+ .def("Clone", &Manifold::Clone);
218
+ m.def("Diagonalize", &Diagonalize);
219
+ }
220
+ #endif
@@ -0,0 +1,47 @@
1
+ #pragma once
2
+
3
+ #define __Check_Log_Map__\
4
+ if ( typeid(N) != typeid(*this) )\
5
+ throw std::runtime_error("The point to logarithm map is not in " + std::string(typeid(*this).name()) + "but in " + std::string(typeid(N).name()) + "!");
6
+
7
+ #define __Check_Vec_Transport__\
8
+ if ( typeid(N) != typeid(*this) )\
9
+ throw std::runtime_error("The destination of vector transport is not in " + std::string(typeid(*this).name()) + "but in " + std::string(typeid(N).name()) + "!");
10
+
11
+ class Manifold{ public:
12
+ std::string Name;
13
+ EigenMatrix P;
14
+ EigenMatrix Ge;
15
+ EigenMatrix Gr;
16
+ bool MatrixFree;
17
+ EigenMatrix Hem;
18
+ std::vector<std::tuple<double, EigenMatrix>> Hrm;
19
+ std::function<EigenMatrix (EigenMatrix)> He;
20
+ std::function<EigenMatrix (EigenMatrix)> Hr;
21
+ std::vector<EigenMatrix> BasisSet;
22
+
23
+ Manifold(EigenMatrix p, bool matrix_free);
24
+ virtual int getDimension() const;
25
+ virtual double Inner(EigenMatrix X, EigenMatrix Y) const;
26
+ void getBasisSet();
27
+ void getHessianMatrix();
28
+
29
+ virtual EigenMatrix Exponential(EigenMatrix X) const;
30
+ virtual EigenMatrix Logarithm(Manifold& N) const;
31
+
32
+ virtual EigenMatrix TangentProjection(EigenMatrix A) const;
33
+ virtual EigenMatrix TangentPurification(EigenMatrix A) const;
34
+
35
+ virtual EigenMatrix TransportTangent(EigenMatrix X, EigenMatrix Y) const;
36
+ virtual EigenMatrix TransportManifold(EigenMatrix X, Manifold& N) const;
37
+
38
+ virtual void Update(EigenMatrix p, bool purify);
39
+ virtual void getGradient();
40
+ virtual void getHessian();
41
+
42
+ virtual ~Manifold() = default;
43
+ virtual std::unique_ptr<Manifold> Clone() const;
44
+ };
45
+
46
+ std::vector<std::tuple<double, EigenMatrix>> Diagonalize(
47
+ EigenMatrix& A, std::vector<EigenMatrix>& basis_set);