import numpy as np, matplotlib.pyplot as plt
x = np.linspace(-3, 3, 300); ytrue = np.where(x < 0, -x, 0.5*x) # a kinked function
anchors = np.array([-2.0, 0.0, 2.0])
def gate(x, T=0.7):
z = -(x[:,None]-anchors[None])**2 / T; e = np.exp(z - z.max(1,keepdims=True)); return e/e.sum(1,keepdims=True)
G = gate(x); preds = np.zeros((len(x), 3))
for k in range(3): # each expert = gate-weighted linear fit
w = G[:,k]; A = np.c_[x, np.ones_like(x)]
c = np.linalg.lstsq(A*w[:,None], ytrue*w, rcond=None)[0]; preds[:,k] = A@c
mix = (G*preds).sum(1)
fig, ax = plt.subplots(1, 2, figsize=(7.0, 2.5))
for k in range(3): ax[0].plot(x, G[:,k], label=f"expert {k}")
ax[0].set_title("gating weights $g_k(x)$", fontsize=9); ax[0].legend(fontsize=6); ax[0].set_xlabel("x")
ax[1].plot(x, ytrue, "k--", label="true"); ax[1].plot(x, mix, color="#5d2c80", lw=2, label="MoE")
ax[1].set_title("experts combine → fit", fontsize=9); ax[1].legend(fontsize=6); ax[1].set_xlabel("x")
plt.tight_layout(); plt.show()