Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/const-ae/diffgeo
Working with manifolds in R
https://github.com/const-ae/diffgeo
Last synced: 9 days ago
JSON representation
Working with manifolds in R
- Host: GitHub
- URL: https://github.com/const-ae/diffgeo
- Owner: const-ae
- License: other
- Created: 2023-02-15T16:00:53.000Z (almost 2 years ago)
- Default Branch: master
- Last Pushed: 2023-02-16T09:16:33.000Z (almost 2 years ago)
- Last Synced: 2024-11-06T14:00:51.201Z (about 2 months ago)
- Language: R
- Size: 141 KB
- Stars: 0
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.Rmd
- License: LICENSE
Awesome Lists containing this project
README
---
output: github_document
---```{r, include = FALSE}
knitr::opts_chunk$set(
collapse = TRUE,
comment = "#>",
fig.path = "man/figures/README-",
out.width = "100%"
)
```# diffgeo
The `diffgeo` R package provides functions to work with six common manifolds:
* Euclidean arrays
* Spheres (in $n$ dimensions)
* Rotation matrices (also called special orthogonal manifolds $\text{SO}(n)$)
* Stiefel manifold (matrices with orthogonal columns)
* Grassmann manifold (matrices with orthogonal columns but they are only considered different if they span separate spaces)
* Symmetric positive definite (SPD) matrices (symmetric matrices with positive eigenvalues)## Installation
You can install `diffgeo` from [Github](https://github.com/const-ae/diffgeo) with:
``` r
devtools::install_github("const-ae/diffgeo")
```## Principles
For each manifold, `diffgeo` provides:
* Random points
* Random tangents
* Exponential map (a way to go along the manifold from one point to another)
* Logarithm (the inverse exponential map, that is a way calculate the direction between points on the manifold)## Examples
To demonstrate the functionality of the package, I will show the functions for the rotation matrices. All functions work analoguously for the other manifolds.
```{r}
library(diffgeo)
set.seed(1)
```To begin, I create a random rotation matrix in 2D
```{r}
rotation <- rotation_random_point(2)
```We can visualize it's effect on a random set of points
```{r rotation_visualization_2d}
points <- rbind(rnorm(n = 20), rnorm(20))
rotated_points <- rotation %*% points
plot(t(points), pch = 16, col = "black", asp = 1, xlim = c(-3, 3), ylim = c(-2, 2))
points(t(rotated_points), pch = 16, col = "red")
segments(points[1,], points[2,], rotated_points[1,], rotated_points[2,])
```We can also create high-dimensional rotations and check the formal conditions for the rotation manifold
```{r}
rotation2 <- rotation_random_point(5)
# Determinant is 1
Matrix::det(rotation2)
# All columns are orthogonal
round(t(rotation2) %*% rotation2, 3)
```An important concept in differential geometry are geodesics, i.e. are lines on the manifold. To find the
line that connects two rotations we use the `rotation_log` function. These directions are from the tangent space
of the manifold. The tangent space of the rotation manifold is the set of skew-symmetric matrices.```{r}
rotation3 <- rotation_random_point(5)
direction <- rotation_log(base_point = rotation2, target_point = rotation3)
round(direction, 3)
```We can also reverse the operation and go from a base-point in the direction of a tangent vector ("exponential map"). If we do this
using the `direction` we will land exactly at `rotation3` again.```{r}
rotation3
rotation_map(v = direction, base_point = rotation2)
```Lastly, it is important to understand that the Sphere, the Grassmann, the Stiefel, and the Rotation manifold have a non-infinite injectivity radius.
The injectivity radius is furthest we can go along a manifold and still guarantee that $\log(p, \exp_p(v))$ returns the original tangent vector $v$.
The concept is clearest for a 1-Sphere (aka a circle): if we go further than 180° ($\pi$ radians), we end up at a point for which there exist a shorter path to
the starting point than the original direction.```{r circle_injectivity_radius}
# Create a random vector with two elements on a circle
sp <- sphere_random_point(1)
# Make a tangent vector with norm 1
tang <- sphere_random_tangent(sp)
tang <- tang / sqrt(sum(tang^2))# Plot different step lengths along the direction and
# highlight the starting point in red and the point at the injectivity radius in green
plot(t(do.call(cbind, lapply(seq(0, 2 * pi, l = 31), \(t) sphere_map(t * tang, sp)))), asp = 1)
points(t(sp), col = "red")
points(t(sphere_map(sphere_injectivity_radius() * tang, sp)), col = "green")
```# Alternatives
This package is heavily inspired and builds on the [Manifolds](https://juliamanifolds.github.io/Manifolds.jl/latest/index.html) and [Manopt.jl](https://manoptjl.org/stable/) packages developed by Ronny Bergmann et al.. The Manopt.jl package in turn is inspired by the [Manopt](https://www.manopt.org/) toolbox for Matlab.