manopt_rs/manifolds.rs
1//! Riemannian manifolds for constrained optimization.
2//!
3//! This module defines manifolds and their operations for Riemannian optimization.
4//! Each manifold implements geometric operations like projection, retraction,
5//! exponential maps, and parallel transport.
6
7use crate::prelude::*;
8
9pub mod steifiel;
10pub use steifiel::SteifielsManifold;
11
12/// A Riemannian manifold defines the geometric structure for optimization.
13///
14/// This trait provides all the necessary operations for Riemannian optimization:
15/// - Tangent space projections
16/// - Retraction operations
17/// - Exponential maps
18/// - Parallel transport
19/// - Riemannian inner products
20///
21/// # Example Implementation
22///
23/// ```rust
24/// use manopt_rs::prelude::*;
25///
26/// #[derive(Clone)]
27/// struct MyManifold;
28///
29/// impl<B: Backend> Manifold<B> for MyManifold {
30/// fn new() -> Self { MyManifold }
31/// fn name() -> &'static str { "MyManifold" }
32///
33/// fn project<const D: usize>(point: Tensor<B, D>, vector: Tensor<B, D>) -> Tensor<B, D> {
34/// // Project vector to tangent space at point
35/// vector
36/// }
37///
38/// fn retract<const D: usize>(point: Tensor<B, D>, direction: Tensor<B, D>) -> Tensor<B, D> {
39/// // Move along manifold from point in direction with step size
40/// point + direction
41/// }
42///
43/// fn inner<const D: usize>(_point: Tensor<B, D>, u: Tensor<B, D>, v: Tensor<B, D>) -> Tensor<B, D> {
44/// // Riemannian inner product at point
45/// u * v
46/// }
47/// }
48/// ```
49pub trait Manifold<B: Backend>: Clone + Send + Sync {
50 fn new() -> Self;
51 fn name() -> &'static str;
52
53 fn project<const D: usize>(point: Tensor<B, D>, vector: Tensor<B, D>) -> Tensor<B, D>;
54 fn retract<const D: usize>(
55 point: Tensor<B, D>,
56 direction: Tensor<B, D>,
57 ) -> Tensor<B, D>;
58
59 /// Convert Euclidean gradient to Riemannian gradient
60 fn egrad2rgrad<const D: usize>(point: Tensor<B, D>, grad: Tensor<B, D>) -> Tensor<B, D> {
61 Self::project(point, grad)
62 }
63
64 /// Riemannian inner product at a given point
65 fn inner<const D: usize>(point: Tensor<B, D>, u: Tensor<B, D>, v: Tensor<B, D>)
66 -> Tensor<B, D>;
67
68 /// Exponential map: move from point along tangent vector u with step size
69 fn expmap<const D: usize>(
70 point: Tensor<B, D>,
71 direction: Tensor<B, D>,
72 ) -> Tensor<B, D> {
73 Self::retract(point, direction)
74 }
75
76 /// Parallel transport of tangent vector from point1 to point2
77 fn parallel_transport<const D: usize>(
78 _point1: Tensor<B, D>,
79 point2: Tensor<B, D>,
80 tangent: Tensor<B, D>,
81 ) -> Tensor<B, D> {
82 // Default implementation: project to tangent space at point2
83 Self::project_tangent(point2, tangent)
84 }
85
86 /// Project vector to tangent space at point
87 fn project_tangent<const D: usize>(point: Tensor<B, D>, vector: Tensor<B, D>) -> Tensor<B, D> {
88 Self::project(point, vector)
89 }
90
91 /// Project point onto manifold
92 fn proj<const D: usize>(point: Tensor<B, D>) -> Tensor<B, D> {
93 point
94 }
95
96 /// Check if a point is in the manifold.
97 /// By default, this is not implemented and returns `false`.
98 fn is_in_manifold<const D: usize>(_point: Tensor<B, D>) -> bool {
99 false
100 }
101}
102
103/// Euclidean manifold - the simplest case where no projection is needed
104#[derive(Clone, Debug)]
105pub struct Euclidean;
106
107impl<B: Backend> Manifold<B> for Euclidean {
108 fn new() -> Self {
109 Self
110 }
111
112 fn name() -> &'static str {
113 "Euclidean"
114 }
115
116 fn project<const D: usize>(_point: Tensor<B, D>, vector: Tensor<B, D>) -> Tensor<B, D> {
117 vector
118 }
119
120 fn retract<const D: usize>(
121 point: Tensor<B, D>,
122 direction: Tensor<B, D>,
123 ) -> Tensor<B, D> {
124 point + direction
125 }
126
127 fn inner<const D: usize>(
128 _point: Tensor<B, D>,
129 u: Tensor<B, D>,
130 v: Tensor<B, D>,
131 ) -> Tensor<B, D> {
132 u * v
133 }
134
135 fn is_in_manifold<const D: usize>(_point: Tensor<B, D>) -> bool {
136 true
137 }
138}