Trace Halley's Iterations Code
The code related to Generating Fractals by Finding Roots With Halley’s Method.
import numpy as np
import matplotlib.pyplot as plt
def trace_halleys_iteration(f, df, ddf, z0, max_iter=20):
"""Track the iteration path for a single starting point"""
path = [z0]
z = z0
for _ in range(max_iter):
fz = f(z)
dfz = df(z)
ddfz = ddf(z)
if abs(fz) < 1e-6:
break
denominator = 2 * dfz**2 - fz * ddfz
if abs(denominator) < 1e-15:
break
z = z - (2 * fz * dfz) / denominator
# for debugging
# print(f"z.real: {z.real}, z.imag: {z.imag}")
path.append(z)
return np.array(path, dtype=np.complex128)
# f(z) = z^3 - 0.1
def f(z):
return z**3 - 0.1
def df(z):
return 3 * z**2
def ddf(z):
return 6 * z
roots = [
0.1 ** (1.0 / 3),
0.1 ** (1.0 / 3) * np.exp(2j * np.pi / 3),
0.1 ** (1.0 / 3) * np.exp(4j * np.pi / 3),
]
# Plot the roots and some iteration paths
fig, ax = plt.subplots(figsize=(10, 10))
# Plot roots
for i, root in enumerate(roots):
ax.plot(root.real, root.imag, "o", markersize=12, label=f"Root {i + 1}", zorder=5)
# Sample starting points from different angular sectors
colors = ["red", "blue", "green"]
angles = np.linspace(0, 2 * np.pi, 12, endpoint=False)
radius = 1.5
# angles:
# [0. 0.52359878 1.04719755 1.57079633 2.0943951 2.61799388
# 3.14159265 3.66519143 4.1887902 4.71238898 5.23598776 5.75958653]
# test a slice of angles
# angles = angles[:1]
print(angles)
for angle in angles:
z0 = radius * np.exp(1j * angle)
path = trace_halleys_iteration(f, df, ddf, z0, max_iter=15)
# Determine which root it converges to
final_z = path[-1]
distances = [abs(final_z - root) for root in roots]
root_idx = np.argmin(distances)
# Plot the path
ax.plot(
path.real,
path.imag,
"o-",
alpha=0.6,
color=colors[root_idx],
markersize=4,
linewidth=1,
)
ax.plot(z0.real, z0.imag, "x", color="black", markersize=8, markeredgewidth=2)
ax.set_xlabel("Real", fontsize=12)
ax.set_ylabel("Imaginary", fontsize=12)
ax.set_title(
"Iteration Paths from Different Starting Points\n(Same color = converge to same root)",
fontsize=14,
)
ax.legend()
ax.grid(True, alpha=0.3)
ax.axis("equal")
plt.tight_layout()
plt.show()
Tags: