<jupyter_start><jupyter_text>Addition testsThere are some sophisticated/complicated methods of adding vectors in non-Euclidean geometry. In order to test these, I will consider the case of a 1-sphere or 2-sphere.<jupyter_code>import numpy as np
import matplotlib.pyplot as plt
from matplotlib import collections, lines, markers, path, patches
%matplotlib inline
from geometry import *
from optimiser import *<jupyter_output><empty_output><jupyter_text>Plain Addition<jupyter_code>#Angles:
alpha = 0.1
beta = 1.1
a = np.array([np.cos(alpha), np.sin(alpha)])
b = np.array([np.cos(beta), np.sin(beta)])
wrong = a+b
right = np.array([np.cos(alpha+beta), np.sin(alpha+beta)])
print(a)
print(b)
print(wrong)
print(right)
fig = plt.figure(figsize=(12,12))
ax = plt.gca(xlim=[-1.6, 1.6], ylim=[-1.6,1.6], xlabel="$x^0$", ylabel="$x^1$")
circle = patches.Circle((0,0), 1., edgecolor="k", fill=False)
ax.add_artist(circle)
ax.scatter(a[0], a[1], color='r', marker='o',s=200,label = "a")
ax.scatter(b[0], b[1], color='violet', marker='o',s=200,label = "b")
ax.scatter(right[0], right[1], color='g', marker='o',s=200,label = "Correct a+b")
ax.scatter(wrong[0], wrong[1], color='k', marker='o',s=200,label = "Wrong a+b")
ax.legend()<jupyter_output><empty_output><jupyter_text>Gyro-vectors  Einstein midpoints  Parallel transportCouldn't one parallel transport the vector to any given space along the   Möbius transformations  Special Relativity  MeanFind the mean, which should just yield another vector with the average angle between them.<jupyter_code>#Angles:
mean_wrong = 0.5*(a+b)
mean_angle = 0.5*(alpha+beta)
mean_right = np.array([np.cos(mean_angle), np.sin(mean_angle)])
print(a)
print(b)
print(mean_wrong)
print(mean_right)
fig = plt.figure(figsize=(12,12))
ax = plt.gca(xlim=[-1.6, 1.6], ylim=[-1.6,1.6], xlabel="$x^0$", ylabel="$x^1$")
circle = patches.Circle((0,0), 1., edgecolor="k", fill=False)
ax.add_artist(circle)
ax.scatter(a[0], a[1], color='r', marker='o',s=200,label = "a")
ax.scatter(b[0], b[1], color='violet', marker='o',s=200,label = "b")
ax.scatter(mean_right[0], mean_right[1], color='g', marker='o',s=200,
           label = "Correct mean(a,b)")
ax.scatter(mean_wrong[0], mean_wrong[1], color='k', marker='o',s=200,
           label = "Wrong mean(a,b)")
ax.legend()<jupyter_output><empty_output><jupyter_text>Fréchet meanLet (M, d) be a complete metric space. Let $x_1, x_2,...,x_n$ be points in $\mathcal{M}$. For any point p in M, the Fréchet variance is $$\Psi(p) = \sum_i^N d^2(p, x_i)$$The Karcher means are those points, $m$ of $\mathcal{M}$, that locally minimise $\Psi$. $$m = \mathrm{arg\ min}_{p\in\mathcal{M}}\sum_i^N d^2(p, x_i)$$ If there is an $m$ that globally minimises $\Psi$, then it is the Fréchet mean.<jupyter_code>from optimiser import *
p_initial = np.array([np.cos(2.5), np.sin(2.5)])
points = [a,b]
frechet_diff(p_initial, points, geometry="spherical")
updated_pts = [p_initial]
steps = []
projections = []
#learning_rates = np.arange(1., )
for i in range(1,10):
    updated_pt, step, projection = gradient_descent(
                             updated_pts[i-1], 
                             points, 
                             frechet_diff, 
                             geometry="spherical", 
                             learning_rate=0.32,
                             return_vectors=True,
                        )
    updated_pts.append(updated_pt)
    steps.append(step)
    projections.append(projection)
 #   print("****theta =", np.arctan2(updated_pts[i][0], updated_pts[i][1]))
print(updated_pts)
print(steps)
print(projections)
fig = plt.figure(figsize=(12,12))
ax = plt.gca(xlim=[-1.2, 1.2], ylim=[-1.2,1.2], xlabel="$x^0$", ylabel="$x^1$")
circle = patches.Circle((0,0), 1., edgecolor="k", fill=False)
#ax.add_collection(collections.PatchCollection(patch_list))
ax.add_artist(circle)
ax.scatter(points[0][0], points[0][1], marker='*',s=200,label = "a")
ax.scatter(points[1][0], points[1][1], marker='*',s=200,label = "b")
for i, pt in enumerate(updated_pts):
    ax.scatter(
                pt[0], pt[1], 
                marker=markers.MarkerStyle('o',fillstyle="none"), 
                s=100, label="Update {}".format(i)
              )
    if i < len(updated_pts)-1:
        ax.arrow(pt[0], pt[1], -0.1*steps[i][0], -0.1*steps[i][1], 
                width=0.01, length_includes_head=True, 
                color="orange", label=r"ambient grad")
        ax.arrow(pt[0], pt[1], -0.1*projections[i][0], -0.1*projections[i][1], 
                width=0.01, length_includes_head=False, 
                color = "royalblue", label=r"tangent-space grad")
ax.legend()<jupyter_output><empty_output><jupyter_text>What happens between the two trial points? Does it manage to find optimal solution?Plot step found as function of angle? Magnitude and sign?<jupyter_code>a_theta = np.arccos(a[0])
b_theta = np.arccos(b[0])
theta = np.linspace(-np.pi, np.pi, 1000)
x0 = np.cos(theta)
x1 = np.sin(theta)
x = np.array([np.array([x0i, x1i]) for x0i, x1i in zip(x0, x1)])
#print(x)
print(x.shape)
diff = []
for p_eval in x:
    diff.append(np.linalg.norm(frechet_diff(p_eval, points, geometry="spherical")))
diff = np.array(diff).reshape([len(diff), 1])
print(diff.shape)
fig = plt.figure(figsize=(12,12))
#ymax = 1.05*np.max(diff)
ymax = 100
ax = plt.gca(xlim=[-1.6, 1.6], ylim=[0, ymax], xlabel=r"$\theta$", ylabel="Fréchet Differential")
ax.axvline(x=a_theta, color='k', linestyle="--")
ax.axvline(x=b_theta, color='k', linestyle="--")
ax.plot(theta, diff)<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.1865172600759082, 'fraction_numerical': 0.0347008855955178, 'mean_word_length': 4.26546146527117, 'pattern_counts': {'":': 0, '<': 22, '<?xml version=': 0, '>': 21, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '5', 'dir': 'jupyter-structured-clean-dedup', 'id': '47372', 'license': 'MIT', 'n_tokens_mistral': 2218, 'n_tokens_neox': 2111, 'n_words': 428, 'path': 'AdditionTests.ipynb', 'repo_name': 'DRWardrope/GeometryTests', 'size': '5533'}