Minimal projection
import numpy as np
from jnlr.reconcile import make_solver
# generate gaussian samples in 3d
# and reproject them onto the constraint
n_samples = 1000
X = np.random.randn(n_samples, 3)
# define a constraint as an implicit function.
# Each component of the function (1 in this case) returns
# how far a point is from the surface of the constraint
def f_implicit(v):
z1, z2, z3 = v
return z1**2 + z2**2 - z3**2
solver = make_solver(f_implicit, n_iterations=30)
X_proj = solver(X)
incoherence_pre = np.mean(np.abs([f_implicit(x_i) for x_i in X]))
incoherence_post = np.mean(np.abs([f_implicit(x_i) for x_i in X_proj]))
print("mean abs f before projection: {:0.2e}".format(incoherence_pre))
print("mean abs f after projection: {:0.2e}".format(incoherence_post))
mean abs f before projection: 1.84e+00
mean abs f after projection: 1.91e-09
# scatter the original and projected points using plotly, no pandas needed
import plotly.express as px
import plotly.graph_objects as go
fig = go.Figure()
fig.add_trace(go.Scatter3d(x=X[:,0], y=X[:,1], z=X[:,2], mode='markers', name='Original', marker=dict(color='blue', size=1)))
fig.add_trace(go.Scatter3d(x=X_proj[:,0], y=X_proj[:,1], z=X_proj[:,2], mode='markers', name='Projected', marker=dict(color='red', size=2)))
fig.update_layout(scene=dict(xaxis_title='z1', yaxis_title='z2', zaxis_title='z3'))
# no background, WHITE BACKGROUND LOOKS BETTER
fig.update_layout(scene=dict(xaxis=dict(showbackground=False), yaxis=dict(showbackground=False), zaxis=dict(showbackground=False)))
fig.update_layout(
scene=dict(
camera=dict(eye=dict(x=1.2, y=1.2, z=1.6)), # Adjust these to "zoom" in
),
margin=dict(l=50, r=50, b=50, t=50)
)
fig.update_layout(
#legend=dict(itemsizing="constant"),
width=500, height=500)
fig.show()