aiutami a capire perché quando eseguo lo script, funziona tutto fino all'animazione, momento in cui lo script viene eseguito ma non termina mai import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
from matplotlib import cm
from matplotlib.ticker import LinearLocator
from matplotlib.animation import FuncAnimation



def f(x,y):
    "Function"
    # return (1/(2+np.sin(x)*(2/x)))+y**2
    # return np.abs(np.sin(x**2))+y**2
    # return (2+x**2)+y**4
    return 4*x**2+2*y**2+2*x+1

weight=0.6
alfa = beta = 2
particles = 20

#filling 2d position and speed arrays 
np.random.seed(0)
X = np.random.uniform(-5, 5, size=(2, particles))   # you can multiply bigger or smaller numbers depending on how "dense" the function is in its low values
V = np.zeros((2,particles))


result = f(X[0],X[1])
#print(result)
#print(result)
#g_best=result.min()
#print(g_best)
p_best = X.copy()
g_best = p_best[:, result.argmin()] #[:,] selects all the dimensions, then i take the coordinates in which f has its minimum value given by the array result with position = argmin
#print("aaaa",g_best)
g_best_f = f(g_best[0],g_best[1]) # apply the function f to the coordinates g_best and get back the best minimum value
#print("bbb",p_best,result,g_best,g_best_f,"\n")
#print("array x: ",X)
#print("diff",p_best-X)
iterations = 50
#print("globale-x ",g_best-X)
#g_best_vector = g_best.reshape(-1,1)
#print("G: ",g_best,"\n")
#print(p_best-X)
#print("vettore v pre: ",V)

# fig, ax = plt.subplots(subplot_kw={"projection": "3d"},figsize=(8,6))
# ax.set_xlabel('X Label')
# ax.set_ylabel('Y Label')
# ax.set_zlabel('Z Label')
# fig.set_tight_layout(True)

XP = np.linspace(-3,3,120)
YP = XP
Xc,Yc = np.meshgrid(XP,YP)
Zc = f(Xc,Yc)

# surf = ax.plot_surface(Xc,Yc,Zc, linewidth=0, cmap=cm.coolwarm, antialiased=True, alpha=0.7)
# ax.zaxis.set_major_locator(LinearLocator(10))
# ax.zaxis.set_major_formatter('{x:.02f}')
# fig.colorbar(surf, shrink=0.5, aspect=15)
#pbest_plot = ax.scatter(p_best[0],p_best[1],alpha=0.5)
# g_best_plot = ax.scatter(g_best[0],g_best[1],g_best_f,color="red")
# ax.scatter(p_best[0],p_best[1],result,alpha=0.5)

# Definisci la funzione di aggiornamento per un singolo step
def update(p_best, g_best, X, V, result):
    global g_best_f  # Rendi g_best_f una variabile globale per accedervi fuori dalla funzione
    epsilon1 = np.random.rand() 
    epsilon2 = np.random.rand() 
    V = weight * V + alfa *epsilon1 *(g_best.reshape(-1,1)-X) + beta * epsilon2 * (p_best-X)
    X += V
    new_f_vals = f(X[0], X[1])
    p_best[:, (result >= new_f_vals)] = X[:, (result >= new_f_vals)]
    result = f(p_best[0], p_best[1]) 
    g_best = p_best[:, result.argmin()]
    g_best_f = f(g_best[0], g_best[1])
    return p_best, g_best, X, V, result

# Definisci la funzione di callback di animazione
def animate(i):
    global p_best, g_best, X, V, result, g_best_f  # Usa le variabili globali definite fuori dalla funzione
    p_best, g_best, X, V, result = update(p_best, g_best, X, V, result)
    ax.clear()
    ax.plot_surface(Xc, Yc, Zc, linewidth=0, cmap=cm.coolwarm, antialiased=True, alpha=0.7)
    ax.scatter(p_best[0], p_best[1], f(p_best[0], p_best[1]), alpha=0.5)
    # Configura gli assi qui se necessario

# Inizializzazione dell’animazione
fig, ax = plt.subplots(subplot_kw={"projection": "3d"}, figsize=(8, 6))
# Aggiungi i titoli degli assi e altri settaggi del grafico qui

# Crea l’animazione
anim = FuncAnimation(fig, animate, frames=iterations, interval=40, blit=False)

# Salva l’animazione
anim.save("PSO_mia.gif", dpi=120, writer="imagemagick")

# Stampa il best globale alla fine dell’animazione
print("Global best in: ", g_best, " with value {:.10f}".format(g_best_f))

# Mostra il grafico (questo blocca l’esecuzione dello script fino a quando la finestra non viene chiusa)
# plt.show()