codexnested-interval-selection-bounded-subsequence.py
nested-interval-selection-bounded-subsequence.py
"""Exact nested-interval selection from a specified alternating sequence.
This uses knowledge of the model's limit, not a claim to decide an arbitrary
infinite input sequence by inspecting finitely many terms. Outputs to cwd.
"""
from fractions import Fraction
from pathlib import Path
import matplotlib.pyplot as plt
import numpy as np
def selection(steps=8):
a, b = Fraction(-1), Fraction(2)
last = 0
rows = []
for j in range(1, steps + 1):
mid = (a + b) / 2
# Every interval chosen here has upper endpoint > 1, so infinitely
# many even-indexed terms 1+1/(n+1) belong to it.
if mid < 1:
a = mid
else:
b = mid
n = last + 1
while n % 2 or not a <= 1 + Fraction(1, n + 1) <= b:
n += 1
x = 1 + Fraction(1, n + 1)
assert a <= 1 <= x <= b and n > last
assert b - a == Fraction(3, 2**j)
assert abs(x - 1) <= b - a
rows.append((j, a, b, n, x))
last = n
return rows
def main():
rows = selection()
fig, axes = plt.subplots(1, 2, figsize=(9.6, 4.8), dpi=120, layout="constrained")
fig.set_facecolor("white")
for j, a, b, n, x in rows:
axes[0].plot((float(a), float(b)), (j, j), color="#0072b2", linewidth=5,
solid_capstyle="butt", alpha=0.62)
axes[0].scatter([float(x)], [j], color="#d55e00", s=32, zorder=4)
axes[0].text(2.05, j, rf"$n_{j}={n}$", va="center", fontsize=10)
axes[0].axvline(1, color="#555555", linestyle="--", linewidth=1)
axes[0].set(xlim=(0.45, 2.58), ylim=(8.7, 0.3), xlabel="Interval position / selected value",
ylabel=r"Bisection step $j$", title="Nested halves and increasing indices")
axes[0].set_yticks(range(1, 9))
js = np.array([r[0] for r in rows])
errors = np.array([float(r[4] - 1) for r in rows])
widths = np.array([float(r[2] - r[1]) for r in rows])
axes[1].semilogy(js, widths, "o--", color="#0072b2", label=r"Interval length $3/2^j$")
axes[1].semilogy(js, errors, "o-", color="#d55e00", label=r"Selected error $|x_{n_j}-1|$")
axes[1].set(xlabel=r"Bisection step $j$", ylabel="Length / absolute error",
title="Shrinking enclosure certifies convergence")
axes[1].set_xticks(range(1, 9))
axes[1].legend(fontsize=9)
for ax in axes:
ax.grid(alpha=0.18)
fig.savefig(Path(__file__).with_suffix(".png").name, facecolor="white", transparent=False)
plt.close(fig)
if __name__ == "__main__":
main()