import numpy as np
import matplotlib.pyplot as plt
from scipy.spatial import ConvexHull
import cmath
import random
import matplotlib.animation as animation

# Generate 10 random complex numbers as roots of a polynomial
random.seed(42)
roots_P = [complex(random.uniform(-2, 2), random.uniform(-2, 2)) for _ in range(10)]

# Create polynomial from roots
poly_coeffs = np.poly(roots_P)

# Derivative of the polynomial
poly_derivative_coeffs = np.polyder(poly_coeffs)

# Compute the roots of the derivative polynomial P'
roots_P_prime = np.roots(poly_derivative_coeffs)

# Get the real and imaginary parts of the roots
real_P = [root.real for root in roots_P]
imag_P = [root.imag for root in roots_P]

real_P_prime = [root.real for root in roots_P_prime]
imag_P_prime = [root.imag for root in roots_P_prime]

# Smooth displacement of each root in a random direction for the animation

# Choose a random direction for each root
directions = [complex(random.uniform(-0.02, 0.02), random.uniform(-0.02, 0.02)) for _ in roots_P]

# Function to update plot smoothly along chosen directions
def update_smooth(frame):
    plt.clf()
    
    # Smoothly move the roots of P along the chosen directions
    moved_roots_P = [root + frame * direction for root, direction in zip(roots_P, directions)]

    # Update the polynomial and its derivative
    poly_coeffs = np.poly(moved_roots_P)
    poly_derivative_coeffs = np.polyder(poly_coeffs)

    # Compute the new roots of P' (derivative polynomial)
    moved_roots_P_prime = np.roots(poly_derivative_coeffs)

    # Compute the convex hull of the updated roots of P
    points = np.array([[root.real, root.imag] for root in moved_roots_P])
    hull = ConvexHull(points)

    # Plot updated roots of P
    plt.plot([root.real for root in moved_roots_P], [root.imag for root in moved_roots_P], 'bo', markersize=10, label='Roots of P')
    
    # Plot updated roots of P'
    plt.plot([root.real for root in moved_roots_P_prime], [root.imag for root in moved_roots_P_prime], 'rx', markersize=10, label="Roots of P'")
    
    # Plot updated convex hull
    for simplex in hull.simplices:
        plt.plot(points[simplex, 0], points[simplex, 1], 'g-', lw=2)

    # Set labels and legend
    plt.xticks([])
    plt.yticks([])
    plt.legend(loc='upper right')

# Create the animation with smooth displacement
fig = plt.figure(figsize=(8, 8))
ani_smooth = animation.FuncAnimation(fig, update_smooth, frames=100, interval=100)

if False:
    ani_smooth.save('gauss-lucas.mp4', writer='ffmpeg', fps=10)

# Show the animation
plt.show()


