import numpy as np
import matplotlib.pyplot as plt

# 定义目标函数 f(x) 和它的导数 f'(x)
def f(x):
    return x**2 - 2*x - 1

def df(x):
    return 2*x - 2

# 牛顿迭代法
def newton_iteration(x0, tol=1e-5, max_iter=100):
    x_n = x0
    iteration_values = [x_n]
    
    for i in range(max_iter):
        x_next = x_n - f(x_n) / df(x_n)
        iteration_values.append(x_next)
        
        # 输出每次迭代的 x_n
        print(f"Iteration {i+1}: x_n = {x_next}")
        
        if abs(x_next - x_n) < tol:
            break
        
        x_n = x_next
    
    return iteration_values

# 绘制函数图像和切线
def plot_function_and_tangents(x_vals, iteration_values):
    x = np.linspace(1, 3, 400)  # 修改x的范围
    y = f(x)
    
    plt.figure(figsize=(10, 8))
    
    # 画出原函数的图像
    plt.plot(x, y, label="f(x) = x^2 - 2x - 1", color='blue')
    
    # 绘制每次迭代的切线
    for i, x_n in enumerate(iteration_values[:-1]):
        tangent_slope = df(x_n)
        tangent_line = tangent_slope * (x - x_n) + f(x_n)
        plt.plot(x, tangent_line, label=f'Tangent at Iteration {i+1}', linestyle='--')
        plt.scatter([x_n], [f(x_n)], color='red')  # 标记迭代点
    
    # 配置图表
    plt.axhline(0, color='black',linewidth=1)
    plt.axvline(0, color='black',linewidth=1)
    plt.xlim(1, 3)  # 设置x范围
    plt.ylim(-2, 2)  # 设置y范围
    plt.xlabel('x')
    plt.ylabel('f(x)')
    plt.legend()
    plt.title("Newton's Method Iterations")
    plt.grid(True)
    plt.show()

# 初始猜测
x0 = 2  # 选择初始值为2

# 执行牛顿迭代法
iteration_values = newton_iteration(x0)

# 绘制函数和切线图像
plot_function_and_tangents(np.linspace(0, 2.5, 400), iteration_values)