#########################################
######## TP informatique bio-sép ########
########        2025-2026        ########
#########################################


#########################################
####### Thème 6 : Suites réelles ########
#########################################

import numpy as np
import matplotlib.pyplot as plt

## Partie I : suite implicite

## Q1 : une équation admet une unique solution

# on utilise le théorème de la bijection :
# fn est continue et strictement croissante
# sur R+ pour n >= 1, et lim fn = +infini pour n >= 2

## Q2 : représentations des fonctions fn

def f(n,x) :
    return x**n / np.sqrt(1+x**2)

a = 1
b = 2
N = 1000
X = np.linspace(a,b,N)
for n in range(2,11) :
    Y = [f(n,x) for x in X]
    message = 'n = '+str(n)
    plt.plot(X,Y,label = message)
plt.plot([a,b],[1,1],'-.', color = 'k')
plt.ylim(0,4)
plt.legend()
plt.show()

## Q3 : résolution par dichotomie

def xn(n,eps) :
    a,b = 1,2
    while b-a > eps :
        c = (a+b)/2
        if (f(n,c)-1)*(f(n,a)-1) < 0 :
            b = c
        else :
            a = c
    return a

def ListeXn(n,eps) :
    L = []
    for k in range(2,n+1) :
        L.append(xn(k,eps))
    return L

print(ListeXn(15,10**-5))

# on conjecture que (xn)n est décroissante, et converge vers 1

## Partie II : Suite récurrente

## Q4 : fonction associée au modèle logistique

def fmu(x,mu) :
    return mu*x*(1-x)

## Q5 : graphe de f_mu pour mu = 0.75

X = np.linspace(0,1,100)
Y = [fmu(x,0.75) for x in X]
plt.plot(X,Y)
plt.show()

## Q6 : liste [u0,u1,...,un]

def listeValeurs(mu,u0,n) :
    L = [u0]
    for _ in range(n) :
        u1 = fmu(u0,mu)
        L.append(u1)
        u0 = u1
    return L

print(listeValeurs(0.5, 0.3, 5))

## Q7 : tests du modèle logistique par représentations graphiques

def grapheLogistique(mu,u0,n=20) :
    Y = listeValeurs(mu,u0,n)
    X = range(0,n+1)
    valeurs = 'µ='+str(mu)+', u0='+str(u0)
    plt.plot(X,Y,'-.',label = valeurs)
    # plt.show()

def comparaisonLogistique(couples) :
    for (mu,u0) in couples :
        grapheLogistique(mu,u0)
    plt.legend()
    plt.show()

couples = [(0.81,0.1), (0.81,0.83), (1.93,0.02), (1.93,0.75), (2.75,0.43), (2.81,0.46), (3.45,0.23), (3.67,0.23)]
comparaisonLogistique(couples)

# on constate une diversité des comportements
# de la suite logistique selon les valeurs de µ et u0

## Q8 : extraction de sous-listes

def pair_impair(L) :
    Lp = L[0::2]
    Li = L[1::2]
    return Lp,Li

def trace_parite(mu,u0,n=20) :
    X = range(0,n+1)
    Y = listeValeurs(mu,u0,n)
    Xp,Xi = pair_impair(X)
    Lp,Li = pair_impair(Y)
    plt.plot(Xp,Lp,'.-',label = 'indices pairs µ='+str(mu))
    plt.plot(Xi,Li,'.-',label = 'indices impairs µ='+str(mu))

MU = [3.45, 3.67]
U0 = [0.23, 0.23]
for k in range(len(MU)) :
    mu = MU[k]
    u0 = U0[k]
    trace_parite(mu,u0)
plt.legend()
plt.show()

## Q9 : fonction arrondie

def asymptotique(mu,u0) :
    L = listeValeurs(mu,u0,600)
    L2 = L[501:]
    L3 = []
    for elt in L2 :
        L3.append(round(elt,3))
    return L3

## Q10 : exploration pour certaines valeurs de µ

MU = [1.1, 2.1, 3.1, 3.5]
u0 = 0.75
for mu in MU :
    L = asymptotique(mu,u0)
    L2 = L[92:100]
    print(L2)

# selon les valeurs de µ, on a des résultats très différents :
# parfois une unique valeur, parfois une alternance
# entre 2 valeurs, ou 8 valeurs distinctes.

## Q11 : une fonction pour ne garder que
## les valeurs distinctes d'une liste

def image(L) :
    V = []
    for elt in L :
        if elt not in V :
            V.append(elt)
    return V

## Q12 : nombres de valeurs distinctes
## pour µ entre 0 et 4

MU = np.linspace(0,4,400)
Y = [len(image(asymptotique(mu,0.75))) for mu in MU]
plt.plot(MU,Y,'.')
plt.show()


## Q13 : Diagramme de bifurcation

mu = 0
u0 = 0.75
while mu < 4 :
    Y = image(asymptotique(mu,0.75))
    n = len(Y)
    X = [mu]*n
    plt.plot(X,Y,',', color = 'blue')
    mu += 0.002
plt.xlabel('µ')
plt.ylabel('Elements dans asymptotique(µ)')
plt.title('Diagramme de bifurcation de la suite logistique')
plt.show()

























