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}