import numpy as np
import matplotlib.pyplot as plt

"""
La suite logistique

x_{n+1} = f(x_n) ou f(x) = cx(1 -x)
avec c dans l'intervalle [0, 4]

On cree le diagramme de Feigenbaum :
-- la fonction suiteLogistique retourne une matrice de 
taille (N+1, d) ayant sur chaque colonne j les termes 
x_0, x_1, ..., x_N de la suite logistique correspondant 
a la constante c[j].
-- on represente chaque ligne de cette matrice comme fonction
de c.
"""

def suiteLogistique(c, x0, N):
    """
    Parameters
    ----------
    c : reel entre 0 et 4, ou vector
    x0 : terme initial
    N : entier > 0

    Returns
    -------
    si c est un reel, on pose d=1
    si c est un vecteur, on pose d=len(c)
    On retourne la matrice de taille (N+1, d) ayant sur chaque 
    colonne j les termes x_0, x_1, ..., x_N correspondant a la 
    constante c[j].
    """
    if type(c)==float or type(c)==int:
        d = 1
    else:
        d = len(c)        
    x = x0*np.ones(d)
    res = np.zeros((N+1, d))
    res[0, :] = x
    for k in range(1, N+1):
        x = c*x*(1 - x)
        res[k, :] = x        
    return res
        

c = np.linspace(2.75, 4, 500)
x0 = .14
Nini = 800
Nfin = 1000

A = suiteLogistique(c, x0, Nfin)
print(np.shape(A))


fig = plt.figure()
fig.suptitle("Diagramme de Feingenbaum", fontsize=16, color=[0, .1, .4])
ax = fig.add_subplot(1, 1, 1, aspect="equal")
ax.set_xlim(c[0], c[-1])
ax.set_ylim(0, 1)
ax.set_xlabel("parametre c", fontsize=10)
ax.set_ylabel("termes de la suite", fontsize=10)
ax.set_title(f"les termes de la suite de {Nini} a {Nfin}")

# la matrice A doit etre transposee pour que les dimensions
# collent (c les abscisse et chaque colonne de A les ordonnees)
ax.plot(c, np.transpose(A[Nini:, :]),
        color=[0, .3, .6], linestyle="",
        marker="o", markersize=.03)

plt.show()
