# -*- coding: utf-8-*-
"""
TP 1.4.4 Résolution f(x) = 0 par Newton et dichotomie
"""
# Paramètres solveur
E = 0.01
Nmax = 100

# Paramètres pour le tracé des courbes
xmax=10
h=0.01

# Fonctions utiles
from math import *
from matplotlib import pyplot as plt

def tracer(f,a,b,Nmax=100):
    """Trace la fonction f(x) sur l'intervalle [a,b] avec Nmax points"""
    X = []
    Y = []
    h = (b - a) / Nmax
    for i in range(Nmax+1):
        X = X + [a + i * h]
        Y = Y + [f(a+i*h)]
    plt.plot(X,Y)

# Q1) Ouverture de ce fichier avec python
    
# Q2) Fonction f1 (x)  et df1(x)  



# Q3) Tracé de la dérivé df1(x) de -xmax à +xmax avec Nmax points



# Q4) fonction de dérivation numérique de f1(x) : fonction dnumf1(x)



# Q5) Tracé de la fonction f1(x) de -xmax à +xmax avec Nmax points



# Fonctions utiles pour les questions suivantes :
def droite(a,b,ya):
    """Trace la droite allant :
        * du point [a,ya] marqué d'un o plein
        * au point [b,0] marqué d'un x
    """
    plt.plot([a,b],[ya,0])
    plt.plot(a,ya,'o')
    plt.plot(b,0,'x')
    
def Newton(f, df, x0, trace= True):
    """ Renvoie la solution f(x)=0 à partir de l'abscisse initiale x0
    par la méthode de Newton grace à la dérivé df(x) de f(x).
    En cas de divergence indique la raison de la divergence et renvoie None."""
    x = x0 + 2*E
    s = x0
    n = 0
    while s != None and abs(s - x) > E  and n < Nmax :
        x = s
        if f(x) != None and df(x) != 0 and df(x) != None:
            s = x - f(x) / df(x)
            if trace:
                droite(x,s,f(x))
        else:
            if f(x) == None:
                print("Echec de la méthode : valeur en dehors du domaine de la fonction")
            elif df(x) == None:
                print("Echec de la méthode : valeur en dehors du domaine de dérivée")
            elif df(x) == 0:
                print("Echec de la méthode : annulation de la dérivée")
            s = None
        n = n + 1
    if s != None and trace:
        plt.plot(s,0,'D')
    if n==Nmax :
            print('La méthode ne converge pas en',n,'itérations ; Valeur atteinte=',s)    
    return s

# Q6) Résolution de f1(x)=0 en partant de xmax



# Q7) Résolution de f1(x)=0 en partant de -xmax



# Q8) Résolution de f1(x)=0 en partant de 0



# Q9) Modifier la fonction Newton pour renvoyer le nombre d'itérations n en plus du zero s. Justifier les résultats du fait de la symétrie verticale de f1(x).

# Q10) Import de newton() de la bibliothèque scipy.optimize



# Q11) Résolution de f1(x)=0 pour les différents points de départ 0, xmax et -xmax (supprimer l'instruction partant de 0 sinon le programme s'arrête à cette erreur)



# Q12) Définition des fonction f2(x) et df2(x)



# Q13) Jeu de tests pour f2 et df2
"""
print("valeur de f2() dans le domaine de définition :")
print("valeur de f2() hors domaine de définition :")
print("valeur de f2() bordure de domaine de définition :")
print("valeur de df2() dans le domaine de définition :")
print("valeur de df2() bordure de domaine de définition :")
"""
# Q14) Tracé de f2(x) de 0.01 à xmax avec Nmax points



# Q15) Résolution de f2(x) par Newton depuis xmax



# Q16) Résolution de f2(x) par Newton depuis 0.1




# Fonction utile pour les questions suivantes
def dichotomie(f,a,b,trace=True):   
    g = a
    d = b
    i=0
    while d - g > E :
        m = (d + g) / 2
        if f(g) * f(m) > 0 :
            g = m
        else :
            d = m
        i=i+1
        if trace:
            tracer(f,a,b,Nmax)
            tracer(f,g,d,Nmax)
            plt.grid()
            plt.show()        
            plt.pause(0.1)
    return m,i


# Q17) Résolution de f2(x)=0 sur [0.1,xmax] par dichotomie



# Q18) Tracé de f1(x) puis résolution de f1(x)=0 sur [0,xmax] par dichotomie



# Q19) Résolution fausse de f1(x)=0 sur [-2,xmax] par dichotomie


    
# Q20) Impact de la précision sur le nombre d'itération selon les méthodes

