Quotient Bundles

An example application of circle_bundles to a point cloud in a non-Euclidean metric space. By default, \(\text{UMAP}\) is used to compute local circular coordinates.

import numpy as np
import matplotlib.pyplot as plt
import circle_bundles as cb

First, generate a sample of the product \(\mathbb{S}^{2}\times\mathbb{S}^{1}\) as vectors in \(\mathbb{R}^{5}\):

n_samples = 5000
sigma = 0.1  #noise level

data, base_points, angles = cb.sample_s2_trivial(
    n_points = n_samples,
    sigma = sigma,
    radius_clip = (0.0, 5.0),
)

We interpret the base projections as representatives of elements \(\mathbb{RP}^{2}\) by using a quotient pseudo-metric which computes the minimum distance between class representatives (this is handled internally by cb.get_rp2_fibonacci_cover to construct U – see API reference).

Similarly, we interpret the data as points in a quotient space by introducing a pseudo-metric which identifies points via the \(\mathbb{Z}_{2}\)-action below:

\(\hspace{2cm}(v,z)\cdot (-1) := (-v,z)\)

The resulting space is homeomorphic to the product \(\mathbb{RP}^{2}\times\mathbb{S}^{1}\). Note that the base projection map is \(\mathbb{Z}_{2}\)-equivariant; this is a necessary condition for the quotient to form a well-defined circle bundle.

Construct a cover and bundle object:

n_landmarks = 80
rp2_cover = cb.get_rp2_fibonacci_cover(base_points, n_pairs = n_landmarks)

total_metric = cb.RP2_TrivialMetric()  
bundle = cb.Bundle(X = data, cover = rp2_cover, total_metric = total_metric)

Now, compute local trivializations using \(\text{UMAP}_{2}\) (the default when total_metric is provided) and characteristic classes:

local_triv_result = bundle.get_local_trivs()
class_result = bundle.get_classes(show_classes = True)
\[\begin{split}\displaystyle \begin{aligned}\textbf{Characteristic Classes} & \\[8pt]\quad \text{Stiefel--Whitney} &:\quad w_1 = 0\ (\text{orientable})\\[4pt]\quad \text{Euler} &:\quad e = 0\ (\text{trivial})\end{aligned}\end{split}\]

The characteristic class computation confirms the global topology of the quotient space underlying the dataset.

Next, we interpret the data as points in a different quotient space by introducing a pseudo-metric which identifies points via the \(\mathbb{Z}_{2}\)-action below:

\(\hspace{2cm}(v,z)\cdot (-1) := (-v,-z)\)

The resulting space is orientable but non-homeomorphic to the product \(\mathbb{RP}^{2}\times\mathbb{S}^{1}\) – the base projection map is still \(\mathbb{Z}_{2}\)-equivariant with respect to this new action, so we obtain a well-defined (though non-trivial) circle bundle over \(\mathbb{RP}^{2}\).

Construct local circular coordinates using \(\text{UMAP}_{2}\) and compute characteristic classes:

total_metric = cb.RP2_TwistMetric()  
bundle = cb.Bundle(X = data, U = rp2_cover.U, total_metric = total_metric)

local_triv_result = bundle.get_local_trivs()
class_result = bundle.get_classes(show_classes = True)
\[\begin{split}\displaystyle \begin{aligned}\textbf{Characteristic Classes} & \\[8pt]\quad \text{Stiefel--Whitney} &:\quad w_1 = 0\ (\text{orientable})\\[4pt]\quad \text{Euler} &:\quad e \neq 0\ (\text{non-trivial})\\[4pt]\quad \text{Spin} &:\quad w_2 \neq 0\ (\text{not spin})\end{aligned}\end{split}\]

Finally, we treat the original dataset as a sampling from a third quotient of \(\mathbb{S}^{2}\times\mathbb{S}^{1}\) induced by the \(\mathbb{Z}_{2}\) action below:

\(\hspace{2cm}(v,z)\cdot (-1) := (-v,\bar{z})\)

The resulting space is non-orientable, but the base projection is still \(\mathbb{Z}_{2}\)-equivariant, so we obtain a well-defined non-orientable circle bundle over \(\mathbb{RP}^{2}\). The twisted Euler class of the bundle is trivial.

Construct local circular coordinates and compute characteristic classes:

total_metric = cb.RP2_FlipMetric()  
bundle = cb.Bundle(X = data, U = rp2_cover.U, total_metric = total_metric)

local_triv_result = bundle.get_local_trivs()
class_result = bundle.get_classes(show_classes = True)
\[\begin{split}\displaystyle \begin{aligned}\textbf{Characteristic Classes} & \\[8pt]\quad \text{Stiefel--Whitney} &:\quad w_1 \neq 0\ (\text{non-orientable})\\[4pt]\quad \text{(twisted) Euler} &:\quad \tilde{e}=0\end{aligned}\end{split}\]