Showing posts with label Riemann tensor. Show all posts
Showing posts with label Riemann tensor. Show all posts

Thursday, April 18, 2024

Riemann Curvature in Python

Target audience: Advanced
Estimated reading time: 7'

Beyond theoretical physics, the Riemann curvature tensor is essential for understanding motion planning in robotics, object recognition in computer vision, visualization and training of Physics-Inspired Neural Networks.
This article describes the curvature tensor, its derivative and its implementation in Python.


Table of contents
       Curvature tensor
Follow me on LinkedIn

What you will learn: The intricacies of Riemannian metric curvature tensor and its implementation in Python using Geomstats library.

Notes

  • Environments: Python  3.10.10, Geomstats 2.7.0
  • This article assumes that the reader is somewhat familiar with differential and tensor calculus [ref 1, 2]. Please refer to the previous articles related to geometric learning [ref 456, 7].
  • Source code is available at  Github.com/patnicolas/Data_Exploration/manifolds
  • To enhance the readability of the algorithm implementations, we have omitted non-essential code elements like error checking, comments, exceptions, validation of class and method arguments, scoping qualifiers, and import statements.


Introduction

Geometric learning tackles the challenges posed by scarce data, high-dimensional spaces, and the requirement for independent representations in the creation of advanced machine learning models. The fundamental aim of studying Riemannian geometry is to comprehend and scrutinize the characteristics of curved spaces, which are not sufficiently explained by Euclidean geometry alone. 

In this article, we delve into the Riemann curvature tensors, which are based on parallel transport and the covariant derivative discussed in earlier articles.

This article is the eight part of our ongoing series focused on geometric learning. In this installment, we utilize the Geomstats Python library [ref. 3] and explore the hypersphere manifold, which was introduced in a previous piece, Geometric Learning in Python: Manifolds - Hypersphere  and is detailed in the Geomstats API [ref. 8]. 

I highly recommend watching the comprehensive series of 22 YouTube videos Tensor Calculus - Eigenchris  to familiarize yourself with fundamental concepts of differential geometry.  Summaries of my earlier articles on this topic can be found in the Appendix

Riemann curvature

Curvature tensor

Curvature measures the extent to which a geometric object like a curve strays from being straight or how a surface diverges from being flat. It can also be defined as a vector that incorporates both the direction and the magnitude of the curve's deviation. 

The Riemann curvature tensor is a widely used method for quantifying the curvature of Riemannian manifolds. It is calculated from the metric tensor and provides a tensor field at each point on the manifold.

Given a Riemann manifold M with a Levi-Civita connection and a tensor metric g, the Riemann curvature tensor related to vector fields X, Y and Z can be written:
\[\begin{matrix} \mathbf{\Omega (N) }\ \times  \ \mathbf{\Omega (N)} \ \times  \ \mathbf{\Omega (N)} \rightarrow \mathbf{\Omega (N)} \ \ \ \ \ \ \ \ \ \ \ \\ X, Y, Z \to R(X, Y)Z \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \\ R(X, Y)Z= \triangledown_{X} \triangledown_{Y}Z-\triangledown_{Y}\triangledown_{X}Z - \triangledown_{[X, Y]}Z \\ [X, Y] = X.\frac{\partial }{\partial Y} - Y.\frac{\partial }{\partial X} \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \end{matrix}\] [X, Y] is the lie bracket.
The Riemann curvature tensor can be written using the Christoffel symbols as: \[R_{jkl}^{i}=\frac{\partial \Gamma _{jl}^{i} } {\partial x^k} - \frac{\partial \Gamma _{jk}^{i} } {\partial x^l} + \Gamma_{rk}^{i} \Gamma_{jl}^{r} - \Gamma_{rl}^{i} \Gamma_{jk}^{r}\] This formula is complex and generate a lot of components for the curvature tensor. As the curvature has 4 indices, the number of curvature components is dim4
  • For a 2-dimension manifold (i.e., Plane, Sphere) 24=16 components
  • 3-dimension manifold  34= 81
  • For the space-time manifold 44= 256

In the case of the Levi-Civita connection, the properties of Torsion free and Metric compatibility produce symmetries that zero out many of these values. These symmetries are known as 1-2 indices symmetryBianchi identity3-4 indices symmetry and Flip symmetry [ref 9].

Note: All the 16 components of the curvature tensor in 2-dimension for a flat space are 0, as expected.

Geodesic deviation

A key challenge is determining whether geodesics in a curved space converge or diverge, a concept known as geodesic deviation, as depicted in the accompanying diagram.

Fig 1 Illustration of divergence of geodesics

The convergence and divergence of the geodesics is computed using the Riemann curvature tensor established in the previous section, more specifically the sign of the product of the Riemann curvature R and the vector orthogonal to the tangent vector on the geodesics.\[[R(X, Y)Y].X \ \ \ > 0 \ divergence, \ \ \ <0 \ convergence\]The geodesic deviation depends on the selection of the tangent vectors. This dependency is eliminated through normalization known as the sectional curvature tensor.

Sectional curvature tensor

The curvature tensor is undoubtedly a complex concept accompanied by intimidating formulas. However, a simpler expression of the curvature tensor can be obtained through sectional curvature. Essentially, sectional curvature refers to the curvature of two-dimensional sections of our manifold.

As outlined in the previous section, it is necessary to normalize the geodesic deviation to eliminate any dependency on the basis vectors of the manifold.
Given any point p ∈ M, any tangent 2-plane K to M at base point p, and a curvature tensor R, the sectional curvature of K(X, Y) is the real number\[K(X, Y)= \frac{\left \langle R(X,Y)Y, X \right \rangle}{\left \langle X, X \right \rangle \left \langle Y, Y \right \rangle - \left \langle X, Y \right \rangle^{2}}\]Note: The sectional curvature tensor is a prerequisite to the computation of the Ricci tensor which will be described in a future article.

Implementation

As in the previous article on Riemann geometry, we rely on the Geomstats library [ref 3] to evaluate the curvature tensor.

Hypersphere curvature

For a hypersphere (unit sphere) the Riemann curvature tensor can be expressed as: \[R_{ijkl}=g_{ik}g_{jl} - g_{il}g_{jk} \ \ \ \  \ R_{ikl}^{j} = \frac{R_{ijkl}}{g_{ij}}\]After taking into account the symmetry properties of Levi-Civita connection, only one of the 16 components of the curvature tensor is not null. For the intrinsic coordinates u, v \[R_{212}^{1}=sin(u)^{2}\] The computation of the curvature tensor implemented by the method curvature_tensor added to the class RiemannianConnection. It leverages the Geomstats curvature method of the class RiemannianMetric.
The computation requires 3 tangent unit vectors and the base point on the manifold.

def curvature_tensor(self, tgt_vectors: List[np.array], base_pt: np.array) -> np.array:
  
  if len(tgt_vectors) != 3 or any(vec is None for vec in tgt_vectors):
     raise GeometricException(f'Tangent vectors for the curvature {str(tgt_vectors)} is not properly defined')

  return self.riemannian_metric.curvature(
            tgt_vectors[0], 
            tgt_vectors[1], 
            tgt_vectors[2], 
            base_pt)

Let's apply this method to the computation of the Riemann  curvature for a sphere. 

hypersphere = Hypersphere(dim=2, equip=True, default_coords_type='extrinsic')
riemann_connection = RiemannianConnection(hypersphere, 'HyperSphere')
base_pt = np.array([1.5, 2.0, 1.6])

X = np.array([0.4, 0.1, 0.8])
Y = np.array([0.5, 0.1, -0.2])
Z = np.array([0.4, 0.9, 0.0])

curvature = riemann_connection.curvature_tensor([X, Y, Z], base_pt)
print(f'Curvature: {curvature}')

Output:
Curvature: [ 0.009 -0.004 -0.282]

Sectional curvature of hypersphere

The method sectional_curvature_tensor added to the class RiemannianConnection implements the computation of the sectional curvature tensor that requires two tangent unit vectors and a base point on the sphere. It invokes the sectional_curvature method of the Geomstats class RiemannianMetric.

def sectional_curvature_tensor(self,
                              tgt_vec1: np.array,
                              tgt_vec2: np.array,
                              base_pt: Optional[np.array] = None) -> np.array:
 
   if len(tgt_vec1) != len(tgt_vec2):
      raise GeometricException(f'Dimension of tangent vectors for sectional curvature {len(tgt_vec1)} '
                                                f'and {len(tgt_vec2)} should be identical')

   return self.riemannian_metric.sectional_curvature(tgt_vec1, tgt_vec2, base_pt)

Our evaluation has 3 test cases for the tangent vectors:
  • V(x, y, z) & V(x, y, -z)
  • V(x, y, z) & -V(x, y, z)
  • V(x, y, z) & 2V(x, y, z)
hypersphere = Hypersphere(dim=2, equip=True, default_coords_type='intrinsic')
riemann_connection = RiemannianConnection(hypersphere, 'HyperSphere')
base_pt = np.array([1.5, 2.0, 1.6])

# Case 1 (X, Y=X with inverse on Z component)
X = np.array([0.4, 0.1, 0.8])
Y = np.array([0.4, 0.1, -0.8])
sec_curvature = riemann_connection.sectional_curvature_tensor(X, Y, base_pt)
print(f'Sectional curvature 1: {sec_curvature}')

# Case 2: (X, Y=-X)
X = np.array([0.4, 0.1, 0.8])
Y = np.array([-0.4, -0.1, -0.8])
sec_curvature = riemann_connection.sectional_curvature_tensor(X, Y, base_pt)
print(f'Sectional curvature 2: {sec_curvature}')

# Case 3:  (X, Y = 2.X)
X = np.array([0.4, 0.1, 0.8])
Y = np.array([0.8, 0.2, 1.6])
sec_curvature = riemann_connection.sectional_curvature_tensor(X, Y, base_pt)
print(f'Sectional curvature 3: {sec_curvature}')

Output
Sectional curvature: -1.0
Sectional curvature: 0.0
Sectional curvature: 0.0

References


-------------
Patrick Nicolas has over 25 years of experience in software and data engineering, architecture design and end-to-end deployment and support with extensive knowledge in machine learning. 
He has been director of data engineering at Aideo Technologies since 2017 and he is the author of "Scala for Machine Learning", Packt Publishing ISBN 978-1-78712-238-3 
and Geometric Learning in Python Newsletter on LinkedIn.

Appendix

Here is the list of published articles related to geometric learning:

Keywords: geometriclearning, riemanngeometry, manifold, differential geometry, ai, python, geomstats