IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Calcul scientifique Python Discussion :

Fonction méthode NEWTON [Python 3.X]


Sujet :

Calcul scientifique Python

  1. #1
    Futur Membre du Club
    Profil pro
    Inscrit en
    Mai 2009
    Messages
    7
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2009
    Messages : 7
    Points : 6
    Points
    6
    Par défaut Fonction méthode NEWTON
    Bonjour,
    Je me permets de vous solliciter afin de m'apporter une aide concernant un souci dans la programmation ci-dessous exposée :

    Je précise que je suis totalement novice dans la programmation (3mois), je n'ai certainement pas le recul et la connaissance nécessaire afin de pouvoir m'en sortir toute seule !!! Pour info on utilise Pyzo.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    import numpy as np
    import matplotlib.pyplot as plt
     
    # Fonction:
    def f(x):
        return x + np.exp(-x**2) * np.cos(x)
     
    def df(x):
        return 1 + np.exp(-x**2) * (-2*x*np.cos(x) - np.sin(x))
     
    def newton(f,df,x0,eps):
        u = x0
        n = int()
        for i in range(0,n+1):
            u_1 = u + np.exp(-u**2) * np.cos(u)
            while np.abs(u - u_1) <= eps:
                u = u - (f(u)/df(u))
                x = np.linspace(-30, 30, 100)
                y = x + np.exp(-x**2) * np.cos(x)
                plt.plot(x,y)
                plt.grid()
                plt.show()
            return u
     
    # Code:
    x1 = newton(f, df, 0, 10**(-6))
    print("La valeur approchée de f(x)=0 est ", x1)
    Je sais que le résultat que je dois obtenir est approximativement -0,58xxxxxxxxx
    Il faut que la boucle s’arrête quand l’écart est <= a eps
    Maintenant, je ne sais pas si le fait d'inclure un "while" dans une boucle "for" est judicieux !!! Mais je ne vois pas comment faire autrement, ce qui est peut-être le pire !!!

    Merci à vous de la lecture et de l'aide que vous pourrez m'apporter.
    Veuillez m'excuser d'avance, étant en outre-mer et n'ayant pas un accès facile au PC, je risque de prendre un peu de temps pour répondre et remercier les différents intervenants.

  2. #2
    Membre éprouvé

    Homme Profil pro
    Ingénieur
    Inscrit en
    Août 2010
    Messages
    654
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Août 2010
    Messages : 654
    Points : 1 150
    Points
    1 150
    Par défaut
    Salut.

    Si on reste à une seule dimension (x n'est pas un vecteur) alors on peut reformuler le problem comme ceci:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    import numpy as np
    import matplotlib.pyplot as plt
     
    def func(x):
        return x + np.exp(-x**2) * np.cos(x)
     
    def func_deriv(x):
        return 1 + np.exp(-x**2) * (-2*x*np.cos(x) - np.sin(x))
     
    def newton_bis(x0, target, func, func_deriv, eps=1e-6):
        x = x0
        while abs(func(x) - target) > eps:
            err = func(x) - target
            # Compute jacobian
            df = func_deriv(x)
            # Newton method
            delta = (1/df**2) * err
            x -= delta
        return x, func(x), err
     
    if __name__ == '__main__':
     
        x0 = 20.
        target = 0
        print newton_bis(x0, target, func, func_deriv)
    Le principe de la method de newton est d'utiliser la derive pour estimer de combine doit-on modifier la valeur de x pour se rapprocher de la cible. La formulation générale fait appel à une matrice jacobienne qui contient les derivées. Dans ton cas on peut s'en passer, mais il faut quand meme regarder cette forme pour voir que (supposons J la jacobienne, E l'erreur avec la cible et Delta la proportion à modifier):
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    ((J^T.J)^-1).J^T.E = Delta
    Dans le cas à une dimension on déduit que:
    Avec df la derivée..

    Bien l'algorithme de Newton est assez simple:
    1- On part d'une valeur x=x0
    2- Tant que l'erreur entre f(x) et la target est supérieure à epsilon
    a- On calcule la dérivée
    b- On calcul delta
    c- On modife x en function de delta

    Et voilà !

    Un fois le principe maitrisé on peut utiliser des modules qui le font très bien, comme scipy. Mais le faire une fois, c'est mieux

    J

  3. #3
    Futur Membre du Club
    Profil pro
    Inscrit en
    Mai 2009
    Messages
    7
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2009
    Messages : 7
    Points : 6
    Points
    6
    Par défaut
    Tout d'abord, je tiens à te remercier pour le travail et pour la démonstration !!!

    Citation Envoyé par Julien N Voir le message
    Salut.

    Si on reste à une seule dimension (x n'est pas un vecteur) alors on peut reformuler le problem comme ceci:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    import numpy as np
    import matplotlib.pyplot as plt
     
    def func(x):
        return x + np.exp(-x**2) * np.cos(x)
     
    def func_deriv(x):
        return 1 + np.exp(-x**2) * (-2*x*np.cos(x) - np.sin(x))
     
    def newton_bis(x0, target, func, func_deriv, eps=1e-6):
        x = x0
        while abs(func(x) - target) > eps:
            err = func(x) - target
            # Compute jacobian
            df = func_deriv(x)
            # Newton method
            delta = (1/df**2) * err
            x -= delta
        return x, func(x), err
     
    if __name__ == '__main__':
     
        x0 = 20.
        target = 0
        print newton_bis(x0, target, func, func_deriv)
    Le principe de la method de newton est d'utiliser la derive pour estimer de combine doit-on modifier la valeur de x pour se rapprocher de la cible. La formulation générale fait appel à une matrice jacobienne qui contient les derivées. Dans ton cas on peut s'en passer, mais il faut quand meme regarder cette forme pour voir que (supposons J la jacobienne, E l'erreur avec la cible et Delta la proportion à modifier):
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    ((J^T.J)^-1).J^T.E = Delta
    Dans le cas à une dimension on déduit que:
    Avec df la derivée..

    Bien l'algorithme de Newton est assez simple:
    1- On part d'une valeur x=x0
    2- Tant que l'erreur entre f(x) et la target est supérieure à epsilon
    a- On calcule la dérivée
    b- On calcul delta
    c- On modife x en function de delta

    Et voilà !

    Un fois le principe maitrisé on peut utiliser des modules qui le font très bien, comme scipy. Mais le faire une fois, c'est mieux

    J
    Le problème, c'est un peu beaucoup compliqué pour moi !!!
    Je ne vais pas pouvoir le soutenir, le défendre !!!
    C'est la raison, pour laquelle, j'ai privilégié les boucles.
    Je n'ai pas d'erreur, ce qui veut dire que syntaxiquement, je suis pas mal !!!
    Mais j'ai l'impression que je ne calcule pas puisque X1 est toujours = 0
    De plus je ne suis pas capable de dire si je respecte l'arrêt lorsque l'écart entre deux termes consécutifs est <= eps.
    Sachant que l'écart entre deux termes est égale à la valeur absolue de f(u)/df(u)
    Voili/voilou

  4. #4
    Membre éprouvé

    Homme Profil pro
    Ingénieur
    Inscrit en
    Août 2010
    Messages
    654
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Août 2010
    Messages : 654
    Points : 1 150
    Points
    1 150
    Par défaut
    Bon je teste la version mobile du forum. Donc pas de code pour le moment.

    Je note quelques petites choses qui vont pas dans la fonction que tu as postée. A quoi servent u_1, n ainsi que les courbes? Pourquoi écrire en dur la fonction f dans dans newton() et pas appeler justement f(u)? La condition est mauvaise, c'est "tant que supérieur" qu'il faut avoir.

    Je ne vois pas le principe de la méthode de Newton qui consiste a dire: le problème est localement linéaire, je calcul la dérivée au point où je suis, de combien je dois avancer ou reculer pour atteindre ma cible?

  5. #5
    Futur Membre du Club
    Profil pro
    Inscrit en
    Mai 2009
    Messages
    7
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2009
    Messages : 7
    Points : 6
    Points
    6
    Par défaut
    Citation Envoyé par Julien N Voir le message
    Bon je teste la version mobile du forum. Donc pas de code pour le moment.

    Je note quelques petites choses qui vont pas dans la fonction que tu as postée. A quoi servent u_1, n ainsi que les courbes? Pourquoi écrire en dur la fonction f dans dans newton() et pas appeler justement f(u)? La condition est mauvaise, c'est "tant que supérieur" qu'il faut avoir.

    Je ne vois pas le principe de la méthode de Newton qui consiste a dire: le problème est localement linéaire, je calcul la dérivée au point où je suis, de combien je dois avancer ou reculer pour atteindre ma cible?
    Pour répondre à une partie de tes questions !
    pour moi, U_1 est mon terme consécutif que python est censé calculer avec la fonction.
    n est le nombre aléatoire pour lequel python doit calculer les termes.
    EXEMPLE : n=5 donc il doit me calculer 5 termes (ce qui doit répondre à "de combien je dois avancer ou reculer")
    concernant la fonction f dans newton, ben je ne sais pas quoi te répondre ! Nous avons vu cela comme ça à l'école !!!
    Dans pyzo, l'appel des courbes permet l'ouverture d'une fenêtre, devant représenter ta courbe !! pareil je n'ai vu cela que comme ça à l'école !
    Pour mémoire, je n'ai que 3 mois de programmation et de Python. D'après moi, à la lecture des tes questions, je dois être complètement à coté. Mon analyse est mauvaise.

  6. #6
    Membre éprouvé

    Homme Profil pro
    Ingénieur
    Inscrit en
    Août 2010
    Messages
    654
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Août 2010
    Messages : 654
    Points : 1 150
    Points
    1 150
    Par défaut
    Pas tant que cela à côté. J'avais moi aussi pas les yeux en face des trous. Et j'ai confondu la méthode de Gauss-Newton avec celle de Newton-Raphson... Un petit tour sur wikipédia m'a rafraîchi la mémoire.

    Il faut faire une seule boucle while: tant que l'ordonnée n'est pas comprise entre -epsilon et +epsilon on continu. L'ordonnée c'est func(x). On aurait donc:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    import numpy as np
    import matplotlib.pyplot as plt
     
    def func(x):
        return x + np.exp(-x**2) * np.cos(x)
     
    def func_deriv(x):
        return 1 + np.exp(-x**2) * (-2*x*np.cos(x) - np.sin(x))
     
    def newton(x0, func, func_deriv, eps=1e-6):
        x = x0
        while abs(func(x)) > eps:
            x -= func(x)/func_deriv(x)
        return x, func(x)
     
    if __name__ == '__main__':
     
        x0 = 20.
        print (newton(x0, func, func_deriv))
    Dans ton code tu trace tout le temps la même chose, ou alors je suis très fatigué.

  7. #7
    Futur Membre du Club
    Profil pro
    Inscrit en
    Mai 2009
    Messages
    7
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2009
    Messages : 7
    Points : 6
    Points
    6
    Par défaut
    Citation Envoyé par Julien N Voir le message
    Pas tant que cela à côté. J'avais moi aussi pas les yeux en face des trous. Et j'ai confondu la méthode de Gauss-Newton avec celle de Newton-Raphson... Un petit tour sur wikipédia m'a rafraîchi la mémoire.

    Il faut faire une seule boucle while: tant que l'ordonnée n'est pas comprise entre -epsilon et +epsilon on continu. L'ordonnée c'est func(x). On aurait donc:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    import numpy as np
    import matplotlib.pyplot as plt
     
    def func(x):
        return x + np.exp(-x**2) * np.cos(x)
     
    def func_deriv(x):
        return 1 + np.exp(-x**2) * (-2*x*np.cos(x) - np.sin(x))
     
    def newton(x0, func, func_deriv, eps=1e-6):
        x = x0
        while abs(func(x)) > eps:
            x -= func(x)/func_deriv(x)
        return x, func(x)
     
    if __name__ == '__main__':
     
        x0 = 20.
        print (newton(x0, func, func_deriv))
    Dans ton code tu trace tout le temps la même chose, ou alors je suis très fatigué.
    Afin que je comprenne complètement ton coup de génie
    peux tu argumenter un peu ton code
    merci
    Et je tente d'adapter à mon besoin

  8. #8
    Membre du Club

    Homme Profil pro
    Lycéen
    Inscrit en
    Avril 2015
    Messages
    19
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 25
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Lycéen

    Informations forums :
    Inscription : Avril 2015
    Messages : 19
    Points : 53
    Points
    53
    Par défaut
    Bonsoir,

    La méthode de Newton pour approcher une racine de l'équation f(x) = 0 correspond à la suite x_{k+1} = x_k - [ f(x_k) / f'(x_k) ]. La suite converge vers cette racine. Bien sûr, tu ne vas pas pouvoir calculer indéfiniment les termes de la suite : il va falloir s’arrêter à un moment. Tu vas donc considérer que lorsque f(x) est assez proche de zéro à ton goût (variable epsilon), tu souhaites obtenir la valeur approchée d'une racine possible.

    Tu initialise le premier terme de la suite x0 , ta fonction, la dérivée de ta fonction et l'epsilon.
    Tu vas devoir mettre en place une boucle. La condition ? Tant que l'écart entre f(x) et epsilon est grand : ce qui peut se traduire par "while abs(func(x)) > eps:".
    Dans ta boucle, tu calcules le terme suivant selon la définition : "x = x - ( f(x) / df(x) )" ce qui s'écrit aussi "x -= f(x) / df(x)".
    Tu renvoie le x tel que f(x) proche de 0.

    Ton programme revu :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    # -*- coding: utf-8 -*-
    import numpy as np
    import matplotlib.pyplot as plt
     
     
    def f(x):
        return x + np.exp(-x**2) * np.cos(x)
     
     
    def df(x):
        return 1 + np.exp(-x**2) * (-2*x*np.cos(x) - np.sin(x))
     
     
    def newton(f, df, x0, eps):
        u = x0
        while np.abs(f(u)) > eps:
            u = u - (f(u)/df(u))
        return u
     
    x = newton(f, df, 0, 10 ** (-6))
    print("La valeur approchée de f(x)=0 est {}".format(x))
     
    # Plot de la fonction pour retrouver graphiquement le résultat
    x = np.linspace(-30, 30, 100)
    y = x + np.exp(-x**2) * np.cos(x)
    plt.plot(x,y)
    plt.grid()
    plt.show()

  9. #9
    Futur Membre du Club
    Profil pro
    Inscrit en
    Mai 2009
    Messages
    7
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2009
    Messages : 7
    Points : 6
    Points
    6
    Par défaut
    Citation Envoyé par he2lo Voir le message
    Bonsoir,

    La méthode de Newton pour approcher une racine de l'équation f(x) = 0 correspond à la suite x_{k+1} = x_k - [ f(x_k) / f'(x_k) ]. La suite converge vers cette racine. Bien sûr, tu ne vas pas pouvoir calculer indéfiniment les termes de la suite : il va falloir s’arrêter à un moment. Tu vas donc considérer que lorsque f(x) est assez proche de zéro à ton goût (variable epsilon), tu souhaites obtenir la valeur approchée d'une racine possible.

    Tu initialise le premier terme de la suite x0 , ta fonction, la dérivée de ta fonction et l'epsilon.
    Tu vas devoir mettre en place une boucle. La condition ? Tant que l'écart entre f(x) et epsilon est grand : ce qui peut se traduire par "while abs(func(x)) > eps:".
    Dans ta boucle, tu calcules le terme suivant selon la définition : "x = x - ( f(x) / df(x) )" ce qui s'écrit aussi "x -= f(x) / df(x)".
    Tu renvoie le x tel que f(x) proche de 0.

    Ton programme revu :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    # -*- coding: utf-8 -*-
    import numpy as np
    import matplotlib.pyplot as plt
     
     
    def f(x):
        return x + np.exp(-x**2) * np.cos(x)
     
     
    def df(x):
        return 1 + np.exp(-x**2) * (-2*x*np.cos(x) - np.sin(x))
     
     
    def newton(f, df, x0, eps):
        u = x0
        while np.abs(f(u)) > eps:
            u = u - (f(u)/df(u))
        return u
     
    x = newton(f, df, 0, 10 ** (-6))
    print("La valeur approchée de f(x)=0 est {}".format(x))
     
    # Plot de la fonction pour retrouver graphiquement le résultat
    x = np.linspace(-30, 30, 100)
    y = x + np.exp(-x**2) * np.cos(x)
    plt.plot(x,y)
    plt.grid()
    plt.show()
    Bonjour à vous deux
    Tout d'abord, je tiens sincèrement à vous remercier, pour votre implication à mon problème.
    En suite à vous remercier pour les résultats obtenus.
    Et surtout, à vous remercier pour les infos finales, je comprends beaucoup mieux et j'interprète bien le résultat obtenu. Merci pour le cours !
    Je vais pouvoir clôturer ce topic

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Recherche fonction / méthode pour tracer un graph particulier
    Par Cver1 dans le forum Calcul scientifique
    Réponses: 3
    Dernier message: 02/06/2010, 18h10
  2. méthode newton code matlab
    Par amimou dans le forum MATLAB
    Réponses: 3
    Dernier message: 17/02/2010, 14h10
  3. Réponses: 3
    Dernier message: 22/01/2009, 21h05
  4. Fitter une fonction (méthode Corrélation de phase)
    Par Programmeur_Aladdin dans le forum Traitement d'images
    Réponses: 7
    Dernier message: 10/03/2008, 17h46
  5. Fonction/méthode pour obtenir l'IP de la machine
    Par sirex007 dans le forum Web & réseau
    Réponses: 3
    Dernier message: 10/04/2003, 14h36

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo