Extend outer mu branches so the trajectory reaches the centre
x(mu) only approaches the centre as |mu| -> inf, so the sampling in [mean(poles) - 3, mean(poles) + 3] left a gap around it. The outer branches now continue geometrically up to |mu| ~ 1e4 / lambda_min; the extra samples lie outside the mu axes and only show in the trajectory. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
72c19852d8
commit
55cb27c8de
1 file changed
+14
-5
+14
-5
@@ -26,6 +26,7 @@ CASES = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
N_PER_BRANCH = 266 # mu samples between consecutive poles
|
N_PER_BRANCH = 266 # mu samples between consecutive poles
|
||||||
|
N_TAIL = 100 # extra samples extending the outer branches geometrically up to |mu| ~ 1e4 / lambda_min
|
||||||
EPS = 0.01 # gap left on each side of a pole
|
EPS = 0.01 # gap left on each side of a pole
|
||||||
MU_HALF_WIDTH = 3 # mu is sampled in [m - MU_HALF_WIDTH, m + MU_HALF_WIDTH], m the mean of the poles
|
MU_HALF_WIDTH = 3 # mu is sampled in [m - MU_HALF_WIDTH, m + MU_HALF_WIDTH], m the mean of the poles
|
||||||
N_DOTTED_OUTER = 2 # points drawn dotted at the ends of the outer branches
|
N_DOTTED_OUTER = 2 # points drawn dotted at the ends of the outer branches
|
||||||
@@ -68,11 +69,19 @@ def plot_trajectories(Q, x0):
|
|||||||
|
|
||||||
mu_min = poles.mean() - MU_HALF_WIDTH
|
mu_min = poles.mean() - MU_HALF_WIDTH
|
||||||
mu_max = poles.mean() + MU_HALF_WIDTH
|
mu_max = poles.mean() + MU_HALF_WIDTH
|
||||||
mu = np.concatenate([np.linspace(lo, hi, N_PER_BRANCH) for lo, hi in
|
# x(mu) only reaches the centre as |mu| -> inf, so the outer branches continue geometrically
|
||||||
[(mu_min, poles[0] - EPS), (poles[0] + EPS, poles[1] - EPS), (poles[1] + EPS, mu_max)]])
|
# beyond [mu_min, mu_max]; these samples show up in the trajectory but not on the mu axes.
|
||||||
|
tail = np.geomspace(MU_HALF_WIDTH / N_PER_BRANCH, 1e4 / Q.eig.min(), N_TAIL)
|
||||||
|
branch_samples = [
|
||||||
|
np.concatenate((mu_min - tail[::-1], np.linspace(mu_min, poles[0] - EPS, N_PER_BRANCH))),
|
||||||
|
np.linspace(poles[0] + EPS, poles[1] - EPS, N_PER_BRANCH),
|
||||||
|
np.concatenate((np.linspace(poles[1] + EPS, mu_max, N_PER_BRANCH), mu_max + tail)),
|
||||||
|
]
|
||||||
|
mu = np.concatenate(branch_samples)
|
||||||
idx = np.arange(len(mu))
|
idx = np.arange(len(mu))
|
||||||
|
pole_indices = np.cumsum([len(samples) for samples in branch_samples[:-1]])
|
||||||
# A pole where x0 has a zero standardized component vanishes and joins its neighbouring branches.
|
# A pole where x0 has a zero standardized component vanishes and joins its neighbouring branches.
|
||||||
branches = np.split(idx, [k * N_PER_BRANCH for k in (1, 2) if pole_active[k - 1]])
|
branches = np.split(idx, pole_indices[pole_active])
|
||||||
|
|
||||||
cmap = colormaps[COLORMAP]
|
cmap = colormaps[COLORMAP]
|
||||||
norm = Normalize(0, len(mu) - 1)
|
norm = Normalize(0, len(mu) - 1)
|
||||||
@@ -115,8 +124,8 @@ def plot_trajectories(Q, x0):
|
|||||||
ax_x.scatter(*Q.x(root, x0), **style)
|
ax_x.scatter(*Q.x(root, x0), **style)
|
||||||
|
|
||||||
if not degenerate:
|
if not degenerate:
|
||||||
for k, label in zip((1, 2), POLE_LABELS):
|
for pole_index, label in zip(pole_indices, POLE_LABELS):
|
||||||
for i in (k * N_PER_BRANCH - 1, k * N_PER_BRANCH):
|
for i in (pole_index - 1, pole_index):
|
||||||
ax_x.text(*xs[i], label, **TEXT_STYLE)
|
ax_x.text(*xs[i], label, **TEXT_STYLE)
|
||||||
for k in range(Q.dim):
|
for k in range(Q.dim):
|
||||||
point, direction = Q.pole_line(x0, k)
|
point, direction = Q.pole_line(x0, k)
|
||||||
|
|||||||
Reference in new issue
Block a user