Maniverse 0.3.4__tar.gz → 1.0.0__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 (47) hide show
  1. {maniverse-0.3.4 → maniverse-1.0.0/Maniverse.egg-info}/PKG-INFO +3 -3
  2. {maniverse-0.3.4 → maniverse-1.0.0}/Maniverse.egg-info/SOURCES.txt +13 -5
  3. {maniverse-0.3.4/Maniverse.egg-info → maniverse-1.0.0}/PKG-INFO +3 -3
  4. {maniverse-0.3.4 → maniverse-1.0.0}/README.md +2 -2
  5. {maniverse-0.3.4 → maniverse-1.0.0}/setup.py +16 -16
  6. maniverse-1.0.0/src/Manifold/Euclidean.cpp +68 -0
  7. maniverse-0.3.4/src/Manifold/Orthogonal.h → maniverse-1.0.0/src/Manifold/Euclidean.h +6 -6
  8. maniverse-1.0.0/src/Manifold/Flag.cpp +86 -0
  9. maniverse-1.0.0/src/Manifold/Flag.h +22 -0
  10. {maniverse-0.3.4 → maniverse-1.0.0}/src/Manifold/Grassmann.cpp +46 -23
  11. {maniverse-0.3.4 → maniverse-1.0.0}/src/Manifold/Grassmann.h +4 -3
  12. maniverse-1.0.0/src/Manifold/Iterate.cpp +284 -0
  13. maniverse-1.0.0/src/Manifold/Manifold.cpp +102 -0
  14. maniverse-1.0.0/src/Manifold/Manifold.h +116 -0
  15. {maniverse-0.3.4 → maniverse-1.0.0}/src/Manifold/Orthogonal.cpp +10 -56
  16. maniverse-1.0.0/src/Manifold/Orthogonal.h +14 -0
  17. maniverse-1.0.0/src/Manifold/PyManifold.h +32 -0
  18. maniverse-1.0.0/src/Manifold/RealSymmetric.cpp +71 -0
  19. maniverse-1.0.0/src/Manifold/RealSymmetric.h +24 -0
  20. {maniverse-0.3.4 → maniverse-1.0.0}/src/Manifold/Simplex.cpp +20 -15
  21. {maniverse-0.3.4 → maniverse-1.0.0}/src/Manifold/Simplex.h +3 -4
  22. maniverse-1.0.0/src/Manifold/Stiefel.cpp +98 -0
  23. maniverse-1.0.0/src/Manifold/Stiefel.h +19 -0
  24. {maniverse-0.3.4 → maniverse-1.0.0}/src/Manifold/TransRotInvPointCloud.cpp +7 -9
  25. {maniverse-0.3.4 → maniverse-1.0.0}/src/Manifold/TransRotInvPointCloud.h +3 -3
  26. {maniverse-0.3.4 → maniverse-1.0.0}/src/Optimizer/HessUpdate.cpp +22 -23
  27. {maniverse-0.3.4 → maniverse-1.0.0}/src/Optimizer/HessUpdate.h +4 -4
  28. maniverse-0.3.4/src/Optimizer/PyOptimizerOut.h → maniverse-1.0.0/src/Optimizer/PyOptimizer.h +8 -0
  29. {maniverse-0.3.4 → maniverse-1.0.0}/src/Optimizer/SubSolver.cpp +9 -9
  30. {maniverse-0.3.4 → maniverse-1.0.0}/src/Optimizer/SubSolver.h +2 -2
  31. {maniverse-0.3.4 → maniverse-1.0.0}/src/Optimizer/TrustRegion.cpp +18 -18
  32. maniverse-1.0.0/src/Optimizer/TrustRegion.h +20 -0
  33. maniverse-1.0.0/src/PyManiverse.cpp +17 -0
  34. maniverse-1.0.0/test/test.py +6 -0
  35. maniverse-0.3.4/src/Manifold/Manifold.cpp +0 -220
  36. maniverse-0.3.4/src/Manifold/Manifold.h +0 -47
  37. maniverse-0.3.4/src/Manifold/PyManifoldIn.h +0 -5
  38. maniverse-0.3.4/src/Manifold/PyManifoldOut.h +0 -5
  39. maniverse-0.3.4/src/Optimizer/PyOptimizerIn.h +0 -3
  40. maniverse-0.3.4/src/Optimizer/TrustRegion.h +0 -33
  41. maniverse-0.3.4/src/PyManiverse.cpp +0 -10
  42. {maniverse-0.3.4 → maniverse-1.0.0}/LICENSE +0 -0
  43. {maniverse-0.3.4 → maniverse-1.0.0}/Maniverse.egg-info/dependency_links.txt +0 -0
  44. {maniverse-0.3.4 → maniverse-1.0.0}/Maniverse.egg-info/top_level.txt +0 -0
  45. {maniverse-0.3.4 → maniverse-1.0.0}/pyproject.toml +0 -0
  46. {maniverse-0.3.4 → maniverse-1.0.0}/setup.cfg +0 -0
  47. {maniverse-0.3.4 → maniverse-1.0.0}/src/Macro.h +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: Maniverse
3
- Version: 0.3.4
3
+ Version: 1.0.0
4
4
  Summary: Numerical optimization on manifolds
5
5
  Home-page: https://github.com/FreemanTheMaverick/Maniverse.git
6
6
  Author: FreemanTheMaverick
@@ -57,9 +57,9 @@ The good thing is that the current codes do work as they are expected, at least
57
57
 
58
58
  ## Installation
59
59
  ### Manual build
60
- * Cloning the repository
60
+ * Downloading the latest stable release
61
61
  ```
62
- $ git clone https://github.com/FreemanTheMaverick/Maniverse.git
62
+ $ wget https://github.com/FreemanTheMaverick/Maniverse/archive/refs/tags/v0.3.5.tar.gz
63
63
  ```
64
64
  * Edit the first few lines of `/Maniverse/makefile` for your own computer configuration, including
65
65
  * the commands that call the C++ compiler, the GNU make and `ar`
@@ -8,23 +8,31 @@ Maniverse.egg-info/dependency_links.txt
8
8
  Maniverse.egg-info/top_level.txt
9
9
  src/Macro.h
10
10
  src/PyManiverse.cpp
11
+ src/Manifold/Euclidean.cpp
12
+ src/Manifold/Euclidean.h
13
+ src/Manifold/Flag.cpp
14
+ src/Manifold/Flag.h
11
15
  src/Manifold/Grassmann.cpp
12
16
  src/Manifold/Grassmann.h
17
+ src/Manifold/Iterate.cpp
13
18
  src/Manifold/Manifold.cpp
14
19
  src/Manifold/Manifold.h
15
20
  src/Manifold/Orthogonal.cpp
16
21
  src/Manifold/Orthogonal.h
17
- src/Manifold/PyManifoldIn.h
18
- src/Manifold/PyManifoldOut.h
22
+ src/Manifold/PyManifold.h
23
+ src/Manifold/RealSymmetric.cpp
24
+ src/Manifold/RealSymmetric.h
19
25
  src/Manifold/Simplex.cpp
20
26
  src/Manifold/Simplex.h
27
+ src/Manifold/Stiefel.cpp
28
+ src/Manifold/Stiefel.h
21
29
  src/Manifold/TransRotInvPointCloud.cpp
22
30
  src/Manifold/TransRotInvPointCloud.h
23
31
  src/Optimizer/HessUpdate.cpp
24
32
  src/Optimizer/HessUpdate.h
25
- src/Optimizer/PyOptimizerIn.h
26
- src/Optimizer/PyOptimizerOut.h
33
+ src/Optimizer/PyOptimizer.h
27
34
  src/Optimizer/SubSolver.cpp
28
35
  src/Optimizer/SubSolver.h
29
36
  src/Optimizer/TrustRegion.cpp
30
- src/Optimizer/TrustRegion.h
37
+ src/Optimizer/TrustRegion.h
38
+ test/test.py
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: Maniverse
3
- Version: 0.3.4
3
+ Version: 1.0.0
4
4
  Summary: Numerical optimization on manifolds
5
5
  Home-page: https://github.com/FreemanTheMaverick/Maniverse.git
6
6
  Author: FreemanTheMaverick
@@ -57,9 +57,9 @@ The good thing is that the current codes do work as they are expected, at least
57
57
 
58
58
  ## Installation
59
59
  ### Manual build
60
- * Cloning the repository
60
+ * Downloading the latest stable release
61
61
  ```
62
- $ git clone https://github.com/FreemanTheMaverick/Maniverse.git
62
+ $ wget https://github.com/FreemanTheMaverick/Maniverse/archive/refs/tags/v0.3.5.tar.gz
63
63
  ```
64
64
  * Edit the first few lines of `/Maniverse/makefile` for your own computer configuration, including
65
65
  * the commands that call the C++ compiler, the GNU make and `ar`
@@ -40,9 +40,9 @@ The good thing is that the current codes do work as they are expected, at least
40
40
 
41
41
  ## Installation
42
42
  ### Manual build
43
- * Cloning the repository
43
+ * Downloading the latest stable release
44
44
  ```
45
- $ git clone https://github.com/FreemanTheMaverick/Maniverse.git
45
+ $ wget https://github.com/FreemanTheMaverick/Maniverse/archive/refs/tags/v0.3.5.tar.gz
46
46
  ```
47
47
  * Edit the first few lines of `/Maniverse/makefile` for your own computer configuration, including
48
48
  * the commands that call the C++ compiler, the GNU make and `ar`
@@ -2,12 +2,12 @@ import os
2
2
  import urllib.request
3
3
  import tarfile
4
4
  from glob import glob
5
- from setuptools import setup, find_packages
5
+ from setuptools import setup
6
6
  from setuptools.command.build import build
7
7
  import pybind11
8
8
  from pybind11.setup_helpers import Pybind11Extension, ParallelCompile, naive_recompile
9
9
 
10
- __version__ = "0.3.4"
10
+ __version__ = "1.0.0"
11
11
 
12
12
  # Downloading Eigen3
13
13
  pwd = os.path.dirname(__file__)
@@ -30,25 +30,25 @@ ParallelCompile(
30
30
 
31
31
  MV_CPP = sorted(glob("src/*.cpp") + glob("src/*/*.cpp"))
32
32
  MV_HEADER = sorted(glob("src/*.h") + glob("src/*/*.h"))
33
- ext_modules = [ Pybind11Extension(
33
+ ext_module = Pybind11Extension(
34
34
  "Maniverse",
35
35
  MV_CPP,
36
36
  include_dirs = [EIGEN3],
37
37
  depends = MV_HEADER,
38
38
  extra_compile_args = ["-O3", "-D__PYTHON__", "-DEIGEN_INITIALIZE_MATRICES_BY_ZERO"],
39
- cxx_std = 17,
40
- language = "c++"
41
- )]
39
+ language = "c++",
40
+ cxx_std = 17
41
+ )
42
42
 
43
43
  setup(
44
- name = "Maniverse",
45
- version = __version__,
46
- author = "FreemanTheMaverick",
47
- description = "Numerical optimization on manifolds",
48
- long_description = open("README.md").read(),
49
- long_description_content_type = "text/markdown",
50
- url = "https://github.com/FreemanTheMaverick/Maniverse.git",
51
- cmdclass = {"build": CustomBuild},
52
- ext_modules = ext_modules,
53
- classifiers = ["Programming Language :: Python :: 3"]
44
+ name = "Maniverse",
45
+ version = __version__,
46
+ author = "FreemanTheMaverick",
47
+ description = "Numerical optimization on manifolds",
48
+ long_description = open("README.md").read(),
49
+ long_description_content_type = "text/markdown",
50
+ url = "https://github.com/FreemanTheMaverick/Maniverse.git",
51
+ cmdclass = {"build": CustomBuild},
52
+ ext_modules = [ext_module],
53
+ classifiers = ["Programming Language :: Python :: 3"]
54
54
  )
@@ -0,0 +1,68 @@
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 <cmath>
9
+ #include <functional>
10
+ #include <memory>
11
+
12
+ #include "../Macro.h"
13
+
14
+ #include "Euclidean.h"
15
+
16
+ Euclidean::Euclidean(EigenMatrix p): Manifold(p){
17
+ this->Name = "Euclidean(" + std::to_string(p.rows()) + ", " + std::to_string(p.cols()) + ")";
18
+ }
19
+
20
+ int Euclidean::getDimension() const{
21
+ return this->P.size();
22
+ }
23
+
24
+ double Euclidean::Inner(EigenMatrix X, EigenMatrix Y) const{
25
+ return (X.cwiseProduct(Y)).sum();
26
+ }
27
+
28
+ EigenMatrix Euclidean::Exponential(EigenMatrix X) const{
29
+ return this->P + X;
30
+ }
31
+
32
+ EigenMatrix Euclidean::Logarithm(Manifold& N) const{
33
+ return N.P - this->P;
34
+ }
35
+
36
+ EigenMatrix Euclidean::TangentProjection(EigenMatrix A) const{
37
+ return A;
38
+ }
39
+
40
+ EigenMatrix Euclidean::TangentPurification(EigenMatrix A) const{
41
+ return A;
42
+ }
43
+
44
+ void Euclidean::setPoint(EigenMatrix p, bool /*purify*/){
45
+ this->P = p;
46
+ }
47
+
48
+ void Euclidean::getGradient(){
49
+ this->Gr = this->Ge;
50
+ }
51
+
52
+ std::function<EigenMatrix (EigenMatrix)> Euclidean::getHessian(std::function<EigenMatrix (EigenMatrix)> He, bool /*weingarten*/) const{
53
+ std::function<EigenMatrix (EigenMatrix)> Hr = [He](EigenMatrix v){
54
+ return (EigenMatrix)(He(v));
55
+ };
56
+ return Hr;
57
+ }
58
+
59
+ std::unique_ptr<Manifold> Euclidean::Clone() const{
60
+ return std::make_unique<Euclidean>(*this);
61
+ }
62
+
63
+ #ifdef __PYTHON__
64
+ void Init_Euclidean(pybind11::module_& m){
65
+ pybind11::classh<Euclidean, Manifold>(m, "Euclidean")
66
+ .def(pybind11::init<EigenMatrix>());
67
+ }
68
+ #endif
@@ -1,7 +1,7 @@
1
1
  #include "Manifold.h"
2
2
 
3
- class Orthogonal: public Manifold{ public:
4
- Orthogonal(EigenMatrix p, bool matrix_free);
3
+ class Euclidean: public Manifold{ public:
4
+ Euclidean(EigenMatrix p);
5
5
 
6
6
  int getDimension() const override;
7
7
  double Inner(EigenMatrix X, EigenMatrix Y) const override;
@@ -12,12 +12,12 @@ class Orthogonal: public Manifold{ public:
12
12
  EigenMatrix TangentProjection(EigenMatrix A) const override;
13
13
  EigenMatrix TangentPurification(EigenMatrix A) const override;
14
14
 
15
- EigenMatrix TransportTangent(EigenMatrix X, EigenMatrix Y) const override;
16
- EigenMatrix TransportManifold(EigenMatrix X, Manifold& N) const override;
15
+ //EigenMatrix TransportTangent(EigenMatrix X, EigenMatrix Y) override;
16
+ //EigenMatrix TransportManifold(EigenMatrix X, Manifold& N) override;
17
17
 
18
- void Update(EigenMatrix p, bool purify) override;
18
+ void setPoint(EigenMatrix p, bool purify) override;
19
19
  void getGradient() override;
20
- void getHessian() override;
20
+ std::function<EigenMatrix (EigenMatrix)> getHessian(std::function<EigenMatrix (EigenMatrix)> h, bool weingarten) const override;
21
21
 
22
22
  std::unique_ptr<Manifold> Clone() const override;
23
23
  };
@@ -0,0 +1,86 @@
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/Core>
8
+ #include <unsupported/Eigen/MatrixFunctions>
9
+ #include <cmath>
10
+ #include <functional>
11
+ #include <tuple>
12
+ #include <memory>
13
+
14
+ #include "../Macro.h"
15
+
16
+ #include "Flag.h"
17
+ #include <iostream>
18
+
19
+ void Flag::setBlockParameters(std::vector<int> sizes){
20
+ this->BlockParameters.clear();
21
+ this->Name = "Flag(";
22
+ int tot_size = 0;
23
+ for ( int size : sizes ){
24
+ if ( size <= 0 ) throw std::runtime_error("Invalid sizes of subspaces!");
25
+ this->BlockParameters.push_back(std::make_tuple(tot_size, size));
26
+ if ( tot_size > 0 ) this->Name += ", ";
27
+ tot_size += size;
28
+ this->Name += std::to_string(tot_size);
29
+ }
30
+ if ( tot_size > this->P.rows() ) throw std::runtime_error("Invalid sizes of subspaces!");
31
+ this->Name += "; " + std::to_string(this->P.rows()) + ")";
32
+ }
33
+
34
+ Flag::Flag(EigenMatrix p): Stiefel(p){} // Be sure to Flag::setBlockParameters after construction.
35
+
36
+ int Flag::getDimension() const{
37
+ const int N = this->P.rows();
38
+ int ndim = 0;
39
+ int n = 0;
40
+ for ( auto block_parameter : this->BlockParameters ){
41
+ const int delta_n = std::get<1>(block_parameter);
42
+ n += delta_n;
43
+ ndim += delta_n * ( N - n );
44
+ }
45
+ return ndim;
46
+ }
47
+
48
+ inline static EigenMatrix TangentProjection(EigenMatrix P, std::vector<std::tuple<int, int>> BlockParameters, EigenMatrix X){
49
+ EigenMatrix Y = X;
50
+ for ( int i = 0; i < (int)BlockParameters.size(); i++ ){
51
+ FlagGetBlock(Y, i) -= FlagGetBlock(P, i) * FlagGetBlock(P, i).transpose() * FlagGetBlock(X, i);
52
+ for ( int j = 0; j < (int)BlockParameters.size(); j++ ){
53
+ if ( i != j ) FlagGetBlock(Y, i) -= FlagGetBlock(P, j) * FlagGetBlock(X, j).transpose() * FlagGetBlock(P, i);
54
+ }
55
+ }
56
+ return Y;
57
+ }
58
+
59
+ EigenMatrix Flag::TangentProjection(EigenMatrix X) const{
60
+ return ::TangentProjection(this->P, this->BlockParameters, X);
61
+ }
62
+
63
+ std::function<EigenMatrix (EigenMatrix)> Flag::getHessian(std::function<EigenMatrix (EigenMatrix)> He, bool weingarten) const{
64
+ //https://juliamanifolds.github.io/Manifolds.jl/stable/manifolds/stiefel
65
+ const EigenMatrix P = this->P;
66
+ const std::vector<std::tuple<int, int>> B = this->BlockParameters;
67
+ const EigenMatrix tmp = this->Ge.transpose() * this->P + this->P.transpose() * this->Ge;
68
+ if ( weingarten ) return [P, B, tmp, He](EigenMatrix v){
69
+ return ::TangentProjection(P, B, He(v) - 0.5 * v * tmp);
70
+ };
71
+ else return [P, B, He](EigenMatrix v){
72
+ return ::TangentProjection(P, B, He(v));
73
+ };
74
+ }
75
+
76
+ std::unique_ptr<Manifold> Flag::Clone() const{
77
+ return std::make_unique<Flag>(*this);
78
+ }
79
+
80
+ #ifdef __PYTHON__
81
+ void Init_Flag(pybind11::module_& m){
82
+ pybind11::classh<Flag, Stiefel>(m, "Flag")
83
+ .def(pybind11::init<EigenMatrix>())
84
+ .def("setBlockParameters", &Flag::setBlockParameters);
85
+ }
86
+ #endif
@@ -0,0 +1,22 @@
1
+ #include "Stiefel.h"
2
+
3
+ class Flag: public Stiefel{ public:
4
+ std::vector<std::tuple<int, int>> BlockParameters;
5
+ void setBlockParameters(std::vector<int>);
6
+
7
+ Flag(EigenMatrix p);
8
+
9
+ int getDimension() const override;
10
+
11
+ EigenMatrix TangentProjection(EigenMatrix A) const override;
12
+
13
+ std::function<EigenMatrix (EigenMatrix)> getHessian(std::function<EigenMatrix (EigenMatrix)> He, bool weingarten) const override;
14
+
15
+ std::unique_ptr<Manifold> Clone() const override;
16
+ };
17
+
18
+ #define FlagGetBlock(big_mat, imat)\
19
+ big_mat( Eigen::placeholders::all, Eigen::seqN(\
20
+ std::get<0>(BlockParameters[imat]),\
21
+ std::get<1>(BlockParameters[imat])\
22
+ ) )
@@ -5,26 +5,41 @@
5
5
  #include <pybind11/functional.h>
6
6
  #endif
7
7
  #include <Eigen/Dense>
8
- #include <unsupported/Eigen/MatrixFunctions>
9
8
  #include <cmath>
10
9
  #include <functional>
11
10
  #include <tuple>
12
- #include <cassert>
13
11
  #include <memory>
14
12
 
15
13
  #include "../Macro.h"
16
14
 
17
15
  #include "Grassmann.h"
18
16
 
19
- #include <iostream>
20
-
17
+ EigenMatrix RealSkewExpm(EigenMatrix A){
18
+ Eigen::RealSchur<EigenMatrix> schur(A);
19
+ const EigenMatrix Q = schur.matrixU();
20
+ const EigenMatrix T = schur.matrixT();
21
+ const int n = T.cols();
22
+ EigenMatrix expT = EigenZero(n, n);
23
+ int i = 0;
24
+ while ( i < n ){
25
+ const double a = ( i == n - 1 ) ? 0 : T(i, i + 1);
26
+ if ( i == n - 1 || std::abs(a) < 1e-12 ){
27
+ expT(i, i) = 1;
28
+ i += 1;
29
+ }else{
30
+ const double sina = std::sin(a);
31
+ const double cosa = std::cos(a);
32
+ expT(i, i) = expT(i + 1, i + 1) = cosa;
33
+ expT(i, i + 1) = sina;
34
+ expT(i + 1, i) = - sina;
35
+ i += 2;
36
+ }
37
+ }
38
+ const EigenMatrix expA = Q * expT * Q.transpose();
39
+ return expA;
40
+ }
21
41
 
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;
42
+ Grassmann::Grassmann(EigenMatrix p): Manifold(p){
28
43
  Eigen::SelfAdjointEigenSolver<EigenMatrix> eigensolver;
29
44
  eigensolver.compute(p);
30
45
  const EigenVector eigenvalues = eigensolver.eigenvalues();
@@ -34,6 +49,8 @@ Grassmann::Grassmann(EigenMatrix p, bool matrix_free): Manifold(p, matrix_free){
34
49
  if ( eigenvalues(i) > 0.5 ) rank++;
35
50
  this->Projector.resize(p.rows(), rank);
36
51
  this->Projector = eigenvectors.rightCols(rank);
52
+ this->P = this->Projector * this->Projector.transpose();
53
+ this->Name = "Grassmann(" + std::to_string(p.rows()) + ", " + std::to_string(rank) + ")";
37
54
  }
38
55
 
39
56
  int Grassmann::getDimension() const{
@@ -48,8 +65,8 @@ double Grassmann::Inner(EigenMatrix X, EigenMatrix Y) const{
48
65
  EigenMatrix Grassmann::Exponential(EigenMatrix X) const{
49
66
  const EigenMatrix Xp = X * this->P - this->P * X;
50
67
  const EigenMatrix pX = - Xp;
51
- const EigenMatrix expXp = Xp.exp();
52
- const EigenMatrix exppX = pX.exp();
68
+ const EigenMatrix expXp = RealSkewExpm(Xp);
69
+ const EigenMatrix exppX = RealSkewExpm(pX);
53
70
  return expXp * this->P * exppX;
54
71
  }
55
72
 
@@ -94,8 +111,8 @@ EigenMatrix Grassmann::TransportTangent(EigenMatrix X, EigenMatrix Y) const{
94
111
  if ( Y.isApprox(cached_Y) ) return cached_expdp * X * cached_exppd;
95
112
  const EigenMatrix dp = Y * this->P - this->P * Y;
96
113
  const EigenMatrix pd = - dp;
97
- const EigenMatrix expdp = dp.exp();
98
- const EigenMatrix exppd = pd.exp();
114
+ const EigenMatrix expdp = RealSkewExpm(dp);
115
+ const EigenMatrix exppd = RealSkewExpm(pd);
99
116
  this->TransportTangentCache.push_back(std::make_tuple(Y, expdp, exppd));
100
117
  return expdp * X * exppd;
101
118
  }
@@ -108,7 +125,7 @@ EigenMatrix Grassmann::TransportManifold(EigenMatrix X, Manifold& N) const{
108
125
  return this->TransportTangent(X, Y);
109
126
  }
110
127
 
111
- void Grassmann::Update(EigenMatrix p, bool purify){
128
+ void Grassmann::setPoint(EigenMatrix p, bool purify){
112
129
  this->P = p;
113
130
  Eigen::SelfAdjointEigenSolver<EigenMatrix> eigensolver;
114
131
  eigensolver.compute(p);
@@ -124,14 +141,20 @@ void Grassmann::getGradient(){
124
141
  this->Gr = this->TangentPurification(this->TangentProjection(this->Ge));
125
142
  }
126
143
 
127
- void Grassmann::getHessian(){
144
+ std::function<EigenMatrix (EigenMatrix)> Grassmann::getHessian(std::function<EigenMatrix (EigenMatrix)> He, bool weingarten) const{
128
145
  // 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;
146
+ if ( weingarten ) return [P = this->P, Ge = this->Ge, He](EigenMatrix v){
147
+ const EigenMatrix Phe = P * He(v);
148
+ const EigenMatrix partA = Phe - Phe.transpose();
149
+ const EigenMatrix Gev = Ge * v;
150
+ const EigenMatrix partB = Gev - Gev.transpose();
133
151
  const EigenMatrix sum = partA - partB;
134
- return (EigenMatrix)(P * sum - sum * P);
152
+ return (EigenMatrix)(2 * P * sum);
153
+ };
154
+ else return [P = this->P, He](EigenMatrix v){
155
+ const EigenMatrix Phe = P * He(v);
156
+ const EigenMatrix partA = Phe - Phe.transpose();
157
+ return (EigenMatrix)(2 * P * partA);
135
158
  };
136
159
  }
137
160
 
@@ -141,7 +164,7 @@ std::unique_ptr<Manifold> Grassmann::Clone() const{
141
164
 
142
165
  #ifdef __PYTHON__
143
166
  void Init_Grassmann(pybind11::module_& m){
144
- pybind11::class_<Grassmann, Manifold>(m, "Grassmann")
145
- .def(pybind11::init<EigenMatrix, bool>());
167
+ pybind11::classh<Grassmann, Manifold>(m, "Grassmann")
168
+ .def(pybind11::init<EigenMatrix>());
146
169
  }
147
170
  #endif
@@ -5,7 +5,7 @@ class Grassmann: public Manifold{ public:
5
5
  mutable std::vector<std::tuple<EigenMatrix, EigenMatrix>> LogCache;
6
6
  mutable std::vector<std::tuple<EigenMatrix, EigenMatrix, EigenMatrix>> TransportTangentCache;
7
7
 
8
- Grassmann(EigenMatrix p, bool matrix_free);
8
+ Grassmann(EigenMatrix p);
9
9
 
10
10
  int getDimension() const override;
11
11
  double Inner(EigenMatrix X, EigenMatrix Y) const override;
@@ -19,9 +19,10 @@ class Grassmann: public Manifold{ public:
19
19
  EigenMatrix TransportTangent(EigenMatrix X, EigenMatrix Y) const override;
20
20
  EigenMatrix TransportManifold(EigenMatrix X, Manifold& N) const override;
21
21
 
22
- void Update(EigenMatrix p, bool purify) override;
22
+ void setPoint(EigenMatrix p, bool purify) override;
23
+
23
24
  void getGradient() override;
24
- void getHessian() override;
25
+ std::function<EigenMatrix (EigenMatrix)> getHessian(std::function<EigenMatrix (EigenMatrix)> h, bool weingarten) const override;
25
26
 
26
27
  std::unique_ptr<Manifold> Clone() const override;
27
28
  };