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.
- {maniverse-0.3.4 → maniverse-1.0.0/Maniverse.egg-info}/PKG-INFO +3 -3
- {maniverse-0.3.4 → maniverse-1.0.0}/Maniverse.egg-info/SOURCES.txt +13 -5
- {maniverse-0.3.4/Maniverse.egg-info → maniverse-1.0.0}/PKG-INFO +3 -3
- {maniverse-0.3.4 → maniverse-1.0.0}/README.md +2 -2
- {maniverse-0.3.4 → maniverse-1.0.0}/setup.py +16 -16
- maniverse-1.0.0/src/Manifold/Euclidean.cpp +68 -0
- maniverse-0.3.4/src/Manifold/Orthogonal.h → maniverse-1.0.0/src/Manifold/Euclidean.h +6 -6
- maniverse-1.0.0/src/Manifold/Flag.cpp +86 -0
- maniverse-1.0.0/src/Manifold/Flag.h +22 -0
- {maniverse-0.3.4 → maniverse-1.0.0}/src/Manifold/Grassmann.cpp +46 -23
- {maniverse-0.3.4 → maniverse-1.0.0}/src/Manifold/Grassmann.h +4 -3
- maniverse-1.0.0/src/Manifold/Iterate.cpp +284 -0
- maniverse-1.0.0/src/Manifold/Manifold.cpp +102 -0
- maniverse-1.0.0/src/Manifold/Manifold.h +116 -0
- {maniverse-0.3.4 → maniverse-1.0.0}/src/Manifold/Orthogonal.cpp +10 -56
- maniverse-1.0.0/src/Manifold/Orthogonal.h +14 -0
- maniverse-1.0.0/src/Manifold/PyManifold.h +32 -0
- maniverse-1.0.0/src/Manifold/RealSymmetric.cpp +71 -0
- maniverse-1.0.0/src/Manifold/RealSymmetric.h +24 -0
- {maniverse-0.3.4 → maniverse-1.0.0}/src/Manifold/Simplex.cpp +20 -15
- {maniverse-0.3.4 → maniverse-1.0.0}/src/Manifold/Simplex.h +3 -4
- maniverse-1.0.0/src/Manifold/Stiefel.cpp +98 -0
- maniverse-1.0.0/src/Manifold/Stiefel.h +19 -0
- {maniverse-0.3.4 → maniverse-1.0.0}/src/Manifold/TransRotInvPointCloud.cpp +7 -9
- {maniverse-0.3.4 → maniverse-1.0.0}/src/Manifold/TransRotInvPointCloud.h +3 -3
- {maniverse-0.3.4 → maniverse-1.0.0}/src/Optimizer/HessUpdate.cpp +22 -23
- {maniverse-0.3.4 → maniverse-1.0.0}/src/Optimizer/HessUpdate.h +4 -4
- maniverse-0.3.4/src/Optimizer/PyOptimizerOut.h → maniverse-1.0.0/src/Optimizer/PyOptimizer.h +8 -0
- {maniverse-0.3.4 → maniverse-1.0.0}/src/Optimizer/SubSolver.cpp +9 -9
- {maniverse-0.3.4 → maniverse-1.0.0}/src/Optimizer/SubSolver.h +2 -2
- {maniverse-0.3.4 → maniverse-1.0.0}/src/Optimizer/TrustRegion.cpp +18 -18
- maniverse-1.0.0/src/Optimizer/TrustRegion.h +20 -0
- maniverse-1.0.0/src/PyManiverse.cpp +17 -0
- maniverse-1.0.0/test/test.py +6 -0
- maniverse-0.3.4/src/Manifold/Manifold.cpp +0 -220
- maniverse-0.3.4/src/Manifold/Manifold.h +0 -47
- maniverse-0.3.4/src/Manifold/PyManifoldIn.h +0 -5
- maniverse-0.3.4/src/Manifold/PyManifoldOut.h +0 -5
- maniverse-0.3.4/src/Optimizer/PyOptimizerIn.h +0 -3
- maniverse-0.3.4/src/Optimizer/TrustRegion.h +0 -33
- maniverse-0.3.4/src/PyManiverse.cpp +0 -10
- {maniverse-0.3.4 → maniverse-1.0.0}/LICENSE +0 -0
- {maniverse-0.3.4 → maniverse-1.0.0}/Maniverse.egg-info/dependency_links.txt +0 -0
- {maniverse-0.3.4 → maniverse-1.0.0}/Maniverse.egg-info/top_level.txt +0 -0
- {maniverse-0.3.4 → maniverse-1.0.0}/pyproject.toml +0 -0
- {maniverse-0.3.4 → maniverse-1.0.0}/setup.cfg +0 -0
- {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
|
+
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
|
-
*
|
|
60
|
+
* Downloading the latest stable release
|
|
61
61
|
```
|
|
62
|
-
$
|
|
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/
|
|
18
|
-
src/Manifold/
|
|
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/
|
|
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
|
+
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
|
-
*
|
|
60
|
+
* Downloading the latest stable release
|
|
61
61
|
```
|
|
62
|
-
$
|
|
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
|
-
*
|
|
43
|
+
* Downloading the latest stable release
|
|
44
44
|
```
|
|
45
|
-
$
|
|
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
|
|
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.
|
|
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
|
-
|
|
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
|
-
|
|
40
|
-
|
|
41
|
-
)
|
|
39
|
+
language = "c++",
|
|
40
|
+
cxx_std = 17
|
|
41
|
+
)
|
|
42
42
|
|
|
43
43
|
setup(
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
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
|
|
4
|
-
|
|
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)
|
|
16
|
-
EigenMatrix TransportManifold(EigenMatrix X, Manifold& N)
|
|
15
|
+
//EigenMatrix TransportTangent(EigenMatrix X, EigenMatrix Y) override;
|
|
16
|
+
//EigenMatrix TransportManifold(EigenMatrix X, Manifold& N) override;
|
|
17
17
|
|
|
18
|
-
void
|
|
18
|
+
void setPoint(EigenMatrix p, bool purify) override;
|
|
19
19
|
void getGradient() override;
|
|
20
|
-
|
|
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
|
-
|
|
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
|
|
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
|
|
52
|
-
const EigenMatrix exppX = pX
|
|
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
|
|
98
|
-
const EigenMatrix exppd = pd
|
|
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::
|
|
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
|
-
|
|
144
|
+
std::function<EigenMatrix (EigenMatrix)> Grassmann::getHessian(std::function<EigenMatrix (EigenMatrix)> He, bool weingarten) const{
|
|
128
145
|
// https://arxiv.org/abs/0709.2205
|
|
129
|
-
|
|
130
|
-
const EigenMatrix
|
|
131
|
-
const EigenMatrix partA =
|
|
132
|
-
const EigenMatrix
|
|
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)(
|
|
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::
|
|
145
|
-
.def(pybind11::init<EigenMatrix
|
|
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
|
|
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
|
|
22
|
+
void setPoint(EigenMatrix p, bool purify) override;
|
|
23
|
+
|
|
23
24
|
void getGradient() override;
|
|
24
|
-
|
|
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
|
};
|