import numpy as np
import matplotlib.pyplot as plt
def f(x):
 return (x - 2)**2 + 1 
def quadratic_fit_search(f, x0, x1, x2, tol=1e-5, max_iter=100):
    iteration_data = [] 

    for i in range(max_iter):
        f0 = f(x0)
        f1 = f(x1)
        f2 = f(x2)

        numerator = (x1 - x0)**2 * (f1 - f2) - (x1 - x2)**2 * (f1 - f0)
        denominator = (x1 - x0) * (f1 - f2) - (x1 - x2) * (f1 - f0)

        if denominator == 0:
            print("Cannot divide by zero. Try different starting points.")
            return None, iteration_data

        x_min = x1 - 0.5 * (numerator / denominator)
        f_min = f(x_min)

        # Store iteration data for visualization or debugging
        iteration_data.append((x0, x1, x2, x_min, f_min))

        # Check for convergence
        if abs(x_min - x1) < tol:
            break

        # Select next 3 points closest to x_min
        x_list = [x0, x1, x2, x_min]
        f_list = [f0, f1, f2, f_min]

        # Sort by x values
        sorted_points = sorted(zip(x_list, f_list), key=lambda p: p[0])

        # Pick the three consecutive x-values that bracket the minimum
        for j in range(len(sorted_points) - 2):
            if sorted_points[j][0] <= x_min <= sorted_points[j + 2][0]:
                x0, x1, x2 = sorted_points[j][0], sorted_points[j + 1][0], sorted_points[j + 2][0]
                break

    return x_min, iteration_data
x_start0 = 0.0
x_start1 = 1.5
x_start2 = 3.0
x_result, history = quadratic_fit_search(f, x_start0, x_start1, x_start2)
print("Estimated minimum x =", x_result)
print("Function value at minimum f(x) =", f(x_result))


# Plotting the function and iterations
x_values = np.linspace(-1, 5, 500)
y_values = f(x_values)
plt.plot(x_values, y_values, label="f(x)", color='blue')

for i, (x0, x1, x2, x_min, f_min) in enumerate(history):
    plt.scatter([x0, x1, x2], [f(x0), f(x1), f(x2)], color='gray', s=20)
    plt.scatter(x_min, f_min, color='red', s=40)
    plt.text(x_min, f_min + 0.3, f"Iter {i+1}", fontsize=8, ha='center')

plt.axvline(x_result, color='green', linestyle='--', label=f"Estimated Mim = 2.0000")
plt.title("Quadratic Fit (Parabolic Interpolation) Method")
plt.xlabel("x")
plt.ylabel("f(x)")
plt.legend()
plt.grid(True)
plt.show()