Bibm@th

Forum de mathématiques - Bibm@th.net

Bienvenue dans les forums du site BibM@th, des forums où on dit Bonjour (Bonsoir), Merci, S'il vous plaît...

Vous n'êtes pas identifié(e).

#26 08-12-2010 17:08:54

yoshi
Modo Ferox
Inscription : 20-11-2005
Messages : 16 989

Re : traitement de fonctions mathématiques.

Salut,

Non, pas impeccable ! Ton prof trouvera sûrement le bug que j'ai découvert dans mon algorithme : je pense avoir trouvé comment le corriger, mais réfléchis un peu à une parade, au niveau de l'idée : la réalisation informatique sera une autre étape...

@+


Arx Tarpeia Capitoli proxima...

Hors ligne

#27 08-12-2010 19:04:30

karlun
Membre
Inscription : 05-05-2010
Messages : 216

Re : traitement de fonctions mathématiques.

Transfert d'un échange...

"PS: @ Yoshi:
Une question m'a également traversé l'esprit concernant le traitement des demandes d'aide d'étudiants:
Ne penses-tu pas lui avoir beaucoup (trop) mâché la besogne ?
(Au point qu'il éprouve encore des difficultés dans la présentation de son "devoir" en fin d'œuvre (chef pour ce qui te concerne).

Suis novice et pas pédagogue sans doute... Tant à apprendre."

Et puis:

"C'est quoi l'indice de la demande (et donc de "la ! " réponse (exigée?, souhaitée?, désirée?))?
Lui,( ou tout autre), sans doute [?] use des connexions "dialoguantes_désirantes" (qui m'animent ici, maintenant, encore...et pour mon plaisir) comme vecteur de communication (et de résolution de "son" problème de math (qui en couvre (l'instant du "postage") d'autres évidemment (zut! où sont, encore une fois, mes clés :-)  ?) comme tout le monde))."

A+-*/


Qui trouve, cherche.

Hors ligne

#28 08-12-2010 19:16:41

yoshi
Modo Ferox
Inscription : 20-11-2005
Messages : 16 989

Re : traitement de fonctions mathématiques.

RE,

Une question m'a également traversé l'esprit concernant le traitement des demandes d'aide d'étudiants:
Ne penses-tu pas avoir beaucoup (trop) mâché la besogne de zarnac dans
"traitement de fonctions mathématiques." en programmation?

Bin, vois-tu, je me suis posé la même question AVANT et pas après...
Je me suis vite rendu compte :
1. Qu'apparemment, il était totalement novice en programmation,
2. Qu'on ne devrait pas "refiler" un "bébé" pareil à des novices,
3. Qu'il ne savait pas (apparemment encore), comme novice, par quel bout prendre un programme (on est tous passé par là) de façon générale. Alors, celui-là...
4. Que c'était loin d'être évident à faire (surtout la recherche des racines)
5. Qu'il ne maîtrisait pas "l'interface" (que je n'aurais pas su écrire, ou alors en 3 semaines).. pêchée sur developpez.net,
6. Qu'il a fallu que j'insiste lourdement pour savoir enfin que OPMATHS n'était pas un langage, mais que ce devait être écrit en Python...
Dans ces conditions, je n'ai pas mâché le travail, j'ai fait le travail à sa place, hélas...

Je me suis attaché (ou essayé de) par contre à ce qu'il comprenne ce que j'avais fait.
L'informatique, ce n'est pas comme les maths où un peut offrir un plan, il faut impérativement pouvoir travailler sur un bout de code qui ne fonctionne pas et là on peut dire pourquoi...
zarnac n'avait même pas le moindre début d'ébauche de code, ni même d'idée directrice..

Quoi faire ? Alors que moi, j'ai déjà dû m'employer sévère et que je viens de découvrir (hier soir) que mon algo du théorème des gendarmes ne marche pas si le zéro de la courbe correspond à un point de tangence avec l'axe des abscisses : exemple avec f(x) = x^3-3x+2... Il ne trouve pas x= 1. J'y travaille encore.

karlun a écrit :

(Au point qu'il éprouve encore des difficultés dans la présentation de son "devoir" en fin d'œuvre (chef pour ce qui te concerne).

Tu peux constater à la lumière des points ci-dessus (et si tu relis son post) que les difficultés de présentation n'ont rien à voir avec mon code mais plutôt avec le fonctionnement d'un programme et de la différence entre procédure/fonction et corps de programme où on gère ces procédure/fonction (encore une fois ça s'apprend). Et on en revient à l'état de novice...
Il ne sera probablement pas le seul à avoir vu des points d'interrogations pousser comme des champignons : sujet très subtil et pas évident du tout à programmer : m'enfin, je ne suis qu'un "self made man", en info, hein...
Je n'enverrais pas un marcheur du dimanche faire l'ascension de l'Eiger, des Jorasses ou une Via Ferrata...

@+

PS

karlun a écrit :

C'est quoi l'indice de la demande (et donc de "la ! " réponse (exigée?, souhaitée?, désirée?))?

??? Comprends pas...

Peux-tu préciser ta pensée ?
Mais je crains qu'il n'y ait pas de réponse objective, mais que ce sera à la libre estimation de ce que celui qui répond...


Arx Tarpeia Capitoli proxima...

Hors ligne

#29 08-12-2010 19:55:00

zarnac
Membre
Inscription : 29-11-2010
Messages : 39

Re : traitement de fonctions mathématiques.

Re,

Karlun a écrit :

Ne penses-tu pas lui avoir beaucoup (trop) mâché la besogne ?

Dans tous les cas, la plupart des élèves de ma classe, sont dans la même galère, et font appel aux compétences des gens sur des forums pour les aider, Yoshi m'a certes beaucoup aidé. Mais ce n'est pas une matière pour laquelle j'y attache le plus d'importance dans mon cursus.  J'évite simplement d'être pénalisé et de comprendre le mieux possible le monde de  la programmation.

Tu peux t'arrêter là Yoshi  , merci de m'avoir aider . Je vais me débrouiller pour le "def root"

@+

Hors ligne

#30 08-12-2010 21:18:24

yoshi
Modo Ferox
Inscription : 20-11-2005
Messages : 16 989

Re : traitement de fonctions mathématiques.

B'soir,

yoshi a écrit :

Il ne sera probablement pas le seul à avoir vu des points d'interrogations pousser comme des champignons : sujet très subtil et pas évident du tout à programmer : m'enfin, je ne suis qu'un "self made man", en info, hein...

Et bien, j'avais raison, donc (tu vois, karlun !)..
zarnac, rassure-toi : c'était un sujet difficile nécessitant une bonne maîtrise du langage et ce n'est pas un sujet pour débutant en informatique...

Tu peux t'arrêter là Yoshi , merci de m'avoir aidé.

Il ne faut pas prendre en mauvaise part les interrogations de karlun, ni avoir mauvaise conscience. Que pouvait faire d'autre un novice en programmation ?
Si ceux qui donnent les sujets ne jouent pas le jeu correctement, pourquoi vous, seriez-vous plus royalistes que le Roi ?
Perso, j'ai trouvé ce sujet passionnant, j'ai même appris des choses. Mais les débutants n'ont pas pu y prendre du plaisir, c'est évident.
On pourrait intituler ce sujet : "De la meilleure manière de dégoûter (à vie ?), un débutant de la programmation", je ne comprends toujours pas le but recherché en donnant un sujet pareil...
Disons que la recherche de l'aire par la méthode des trapèzes ou une autre méthode un peu comme ce que j'ai fait sans "Approximations de Pi" aurait suffi...

Je vais poursuivre, parce que j'ai horreur de l'inachevé, et parce que je suis comme un chien qui ronge un os : je ne lâche pas facilement (pratiquement jamais) le morceau !
Donc, en ce qui concerne le bug, on peut tout bêtement chercher les x de plus en précis pour avoir f(x)=0 (ou abs(f(x))<=10^-6 par exemple), mais ça me chiffonne : j'ai la sensation qu'on peut rater des racines...

Alors, je suis sur la piste "améliorer le def root existante" avec une condition supplémentaire portant sur 3 valeurs et le calcul du coefficient direct de deux droites joignant 3 points consécutifs de la courbe : si l'un est positif et l'autre négatif, alors que l'ordonnée du point central est très très faible voisine de zéro) : le changement de courbure indiquera que l'axe des abscisses est tangent à la courbe...
Avec des points très proches les uns des autres : ces droites seront très proches d'être des tangentes à la courbe : on approche la notion de dérivée

Demain, je risque de ne pas pouvoir mettre au point cette condition supplémentaire, mais au plus tard en fin de semaine ce sera fait, de ton côté si tu as une autre idée, n'hésite pas à m'en faire part...

@+


Arx Tarpeia Capitoli proxima...

Hors ligne

#31 09-12-2010 10:42:58

Barbichu
Membre actif
Inscription : 15-12-2007
Messages : 405

Re : traitement de fonctions mathématiques.

Bonjour à tous,

le problème que vous rencontrez n'est pas un problème de programmation, mais d'algorithmique.
Je prétend que pour tout programme suivant le même canevas (i.e. qui procède pas pas sur x, avec un pas fixé ou borné) que tu me donneras, je serai capable de te donner une fonction (continue !) pour laquelle tu ne pourras pas trouver une racine. Il me suffira de définir une fonction qui vaut 1 partout sauf précisément entre deux pas, où elle s'annulera. (Quand à l'approximation à 10^-6, c'est |x - racine| qui doit être plus petit que 10^-6 et non |f(x)|).

En fait, je n'arrive pas à comprendre l'énoncé : la méthode suggérée est la méthode de recherche dichotomique des zéros. Cette méthode nécessite une fonction continue f (ça c'est bon, si l'on suppose qu'on ne donne que des compositions de fonction usuelles) et deux points a et b tels que f(a) * f(b) < 0.
Ce qui veut dire qu'avec un tel algorithme, si f(xmin)*f(xmax) > 0, il faut deviner des points, ce qui est impossible a priori. Et même si f(xmin)*f(xmax) < 0, on peut approximer une racine avec certitude, pour les autres, on en sait fichtre rien !  (Un cas particulier est qu'il est d'ailleurs impossible de trouver les racines de multiplicité paire d'un polynôme)

Par contre il existe d'autres méthodes : méthode de Newton si la fonction est C1 (et que l'on connaît la dérivée), méthode de la Sécante, et plein d'autres méthodes qui combinent ces 3 dernières pour différents cas d'applications. Il y a aussi des méthodes à moitié formelles. Aucune n'est parfaite et toutes nécessitent des conditions particulières sur f, xmin, xmax, conditions qui peuvent être aussi bien d'ordre mathématique (continuité, dérivabilité, racines simples ?) que formelle (calculabilité d'une dérivée formelle, formule explicite pour la fonction ?).

Le problème posé est donc vraiment dur.
Cordialement,

Dernière modification par Barbichu (09-12-2010 10:44:50)


Barbichu

Hors ligne

#32 09-12-2010 11:27:49

yoshi
Modo Ferox
Inscription : 20-11-2005
Messages : 16 989

Re : traitement de fonctions mathématiques.

Salut ô Barbichu,

Ça faisait un moment...
Ton avis est vraiment intéressant : il rejoint ce que je pensais et il ne faut offrir en pâture à ce prog que des fonctions qui possède au moins une racine et ça gâche la fête (!)...
Avec mon écriture du théorème des gendarmes, je trouve ces racines à 10^-6 près...
Reste le cas où la courbe tangente l'axe des abscisses :
* je prends sur la courbe 3 points A, B, C distincts consécutifs séparés d'une distance=pas=0.1, 0.01, 0.001...
* je cherche les coefficients directeurs de (AB) et (BC)
* je teste si le produit de ces coeff est négatif ou nul :
   - Mais si le prod est <0 la détection d'un changement de courbure vaudra détection d'un extremum, pas forcément d'une racine,
  - Et donc, je suis obligé de voir si l'ordonnée vaut "presque 0"...
Je viens de finir de tester à x**3-3*x+2 : ça marche "trop" bien : j'ai une racine à 0.999999 et une à 1.0 : il faut que j'en élimine une...

Bon as-tu une autre idée pour ce cas précis ? Parce que tester tout bêtement f(x)=0, je doute fort que ça marche à coup sûr !

@+


Arx Tarpeia Capitoli proxima...

Hors ligne

#33 09-12-2010 15:59:04

zarnac
Membre
Inscription : 29-11-2010
Messages : 39

Re : traitement de fonctions mathématiques.

Re,

N'ayant pas passé beaucoup de temps dernièrement à chercher, je me suis permis d'ajouter ca:

on sait que f est une fonction continue sur [a,b] et donc on cherche à résoudre f(x)=0
on peut d'abord éliminer les cas ou f(a)=0 et f(b)=0
l'existence d'une racine alpha sur ]a,b[ est subordonné au fait que f(a) et f(b) sont de signe contraires, ce qui vaut à f(a)*(b)<0, et que f est continue sur [a,b]
si C  est un réel de l'intervalle ]a,b[,la position de alpha par rapport à C serait alors:
f(a)*f(c)<=0 alors:
rechercher alpha sur ]a,c]
sinon:
rechercher alpha sur ]c,b[

et on recommence le processus jusqu'à obtenir la racine la plus proche tq f(x)=0 jusqu'à 10^-6 comme précision.

en conclusion, en chaque début d'itération , on peut affirmer que la solution appartient à l'intervalle [a,b] l'amplitude de l'intervalle étant divisé par 2 à chaque étape.

il faut juste juste faire en sorte que le produit f(a)*(b) soit négatif, donc choisir deux bornes de départ [a,b], sinon il n'y aura pas de racine .

jvais essayer de l'exprimer en programme

Dernière modification par zarnac (09-12-2010 16:06:30)

Hors ligne

#34 09-12-2010 17:36:28

yoshi
Modo Ferox
Inscription : 20-11-2005
Messages : 16 989

Re : traitement de fonctions mathématiques.

Bonjour,

Oui, mais partant de ce principe
1. En choisissant bien a et b pour que f(a)*f(b)<0, je pense que tu ne trouveras qu'une seule racine a et b, c'est ce qu'on appelle le théorème des gendarmes,

2. Mais, avec ce système (c'est d'ailleurs mon bug) une racine va t'échapper x=1 dans le cas de f(x)=x**3-3*x+2, parce que tu auras beau encadrer 1 entre deux nombres a et b de ton choix, tu ne trouveras jamais x=1, puisque quels que soient a et b, f(a)*f(b)>0,

3. C'est bien la méthode que j'ai employée sauf que je recherche lors du premier tour de la boucle i, donc par pas de 0.1, tous les a et b possibles que je stocke dans une liste.
    A partir de i=2, je reprends 1 par 1 tous les coupes (a,b) trouvées pour i=1, et je recherche les coupes a,b correspondant à une précision de 10**(-2) ainsi de suite.
   Ça, ça fonctionne déjà.

4. J'ai récrit la procédure root de façon plus claire et plus simple et j'y ai ajouté la détection du changement de courbure assortie d'une ordonnée f(x) tendant vers 0...
   Ça marche trop bien, non seulement il me trouve 1, mais aussi 0.999999...
   Donc en fin de traitement, j'arrondis à 10**(-6) près toutes les bornes inférieures des différents [a,b] (stockés sous forme de couples (a,b)) qui vont remplacer lesdits couples dans ma liste, puis j'élimine les doublons...
   Je n'ai encore pas compris pourquoi j'ai 0.999999 et 1.0 comme racines dans le cas de f(x)=x**3-3*x+2, mais même si je ne suis pas satisfait (je continue à chercher...), ça me permet de contourner la difficulté...

Voilà la nouvelle def root, tu en fais ce que tu veux :

def root(f,a,b):
    encadre,encadre_A,nc,pas=[(a,b)],[],1,1
    for i in xrange(1,8):                
        pas*=0.1                    # pas : largeur de l'encadrement
        nc =len(encadre)            # nc : nombre de couples retenus
        for j in xrange(nc):        # indice du couple à charger
            (c,d)=encadre[j]        # chargement du couple à affiner
            x1,x,x2=c,c,c
            f1=eval(f)              # 1ere valeur
            fin=0
            while not fin or x2<d:             # recherche à la précision donnée
                x2,x3=x1+pas,x1+2*pas   # |
                x=x2                    # |
                f2=eval(f)              # |> valeurs suivantes
                x=x3                    # |
                f3=eval(f)              # |
                if(f1<=0 and f2>0) or (f1>0 and f2<=0): # Th. des gendarmes
                    encadre_A.append((x1,x2))
                    fin=1
                elif (abs(f1)<=pas or abs(f2)<=pas)and\
                     ((f2-f1)*(f3-f2))/((x2-x1)*(x3-x2))<=0:                 * détection de changement de courbure
                    encadre_A.append((x2-pas/2,x2+pas/2))
                    fin=1
                x1,f1=x2,f2      
        encadre,encadre_A=encadre_A,[]
    for (c,d) in encadre:
        encadre_A.append(round(c,6))      
    encadre=sorted(set(encadre_A))
    nc=len(encadre)
    print 'root'+'s'*(nc>1)+" in ["+str(a)+","+str(b)+"] : ",
    for a in encadre:
        print "f("+str(a)+") =",
    print 0

Explications supplémentaires : sorted(liste) trie une liste par ordre croissant, set(liste) élimine les doublons
Quand j'aurais trouvé, je reposterai...

@+


Arx Tarpeia Capitoli proxima...

Hors ligne

#35 09-12-2010 18:12:34

Barbichu
Membre actif
Inscription : 15-12-2007
Messages : 405

Re : traitement de fonctions mathématiques.

Re,
je me suis engagé à prouver par l'exemple que vos algo ne seront pas complets et que rien ne sert de s'acharner sans s'être fixé (explicitement) une version restreinte raisonnable du problème.
Voici donc un contre-exemple à tous les programmes de yoshi (même si je n'ai testé que sur le dernier) :
f (x) = (x - 0.03) * (x - 0.05)

Dernière modification par Barbichu (09-12-2010 18:18:00)


Barbichu

Hors ligne

#36 09-12-2010 18:21:06

yoshi
Modo Ferox
Inscription : 20-11-2005
Messages : 16 989

Re : traitement de fonctions mathématiques.

Salut vieille branche,

1. Détruire, c'est bien... Mais donc, que doit faire ce garçon pour respecter le cahier des charges posées : dichotomie ?

2 Un extrait de mon prog (lanceur simplifié) :

a,b=-3,3
f="x**2-0.3*x+0.0221"
root(f,a,b)

Résultat :

>>> ================================ RESTART ================================
>>>
================================================================================
OPMATH : perform miscellaneous processing on a mathematical function
================================================================================
Note : enter an empty line to stop the interaction loop
roots in [-3,3] :  f(0.13) = f(0.17) = 0
>>>

Contre-exemple à revoir, camarade... :-))

@+

[EDIT]
Ah ! Ah ! On modifie sa proposition en route... Tricheur...;-)
Qu'à cela ne tienne  :

================================================================================
OPMATH : perform miscellaneous processing on a mathematical function
================================================================================
Note : enter an empty line to stop the interaction loop
roots in [-3,3] :  f(0.03) = f(0.05) = 0
>>>


Arx Tarpeia Capitoli proxima...

Hors ligne

#37 09-12-2010 18:58:30

Barbichu
Membre actif
Inscription : 15-12-2007
Messages : 405

Re : traitement de fonctions mathématiques.

Re,

1/ Vous n'appliquez pas la méthode de dichotomie (cf wikipedia), qui de plus est inapplicable. Je suggère surtout d'avoir conscience qu'il n'y a aucune méthode de complète pour le problème à résoudre ! Et cela peu importe le temps que vous passerez à affiner le code.
Il faut arriver à caractériser avec précision les limites de la méthode. Dans ce cas particulier, savoir que le programme actuel ne détecte pas les racines lorsqu'il y a deux changements de signe dans un intervalle de largeur plus petite que 0.1 et que la (valeur absolue de la) pente est trop grande. (entre autres).
Puisqu'il n'existe pas de code "complet", il faut se restreindre à une classe de fonction particulière et déterminer les racines que l'on veut pouvoir détecter. Puis écrire un programme complet pour cette sous-classe et le signaler à tout utilisateur. La sous-classe doit être raisonnable, la notion de raisonnable dépendant de l'utilisation que l'on veut en faire.

2/ J'ai changé car j'avais utilisé le dernier programme de la première page au lieu du dernier de la dernière page, my mistake.
Quant à  (x - 0.03) * (x - 0.05), essaye avec les racines entre [0, 1], ça ne marche pas, mais je pense que c'est juste un bug.
Par contre 1000 * (x - 0.01) * (x - 0.02) échoue pour d'autres intervalles que [0, 1]

Dernière modification par Barbichu (09-12-2010 19:01:45)


Barbichu

Hors ligne

#38 09-12-2010 19:12:19

Barbichu
Membre actif
Inscription : 15-12-2007
Messages : 405

Re : traitement de fonctions mathématiques.

Re,
J'aimerais bien savoir dans quel contexte rentre ce sujet.
Nous as-tu donné le sujet dans son intégralité, y avait il des explications annexes ou un cas d'utilisation.
Est-ce un projet en autonomie ? Tu ne peux pas demander des renseignements à ton prof ?
Avec vous vu des choses qui se rapportent à ces question là, en cours ?


Barbichu

Hors ligne

#39 09-12-2010 19:39:38

yoshi
Modo Ferox
Inscription : 20-11-2005
Messages : 16 989

Re : traitement de fonctions mathématiques.

RE,

J'ai bien compris que le problème n'est pas soluble dans l'eau... Ça fait un moment que j'y réfléchis en vain, je sais aussi que ce n'est pas de la dichotomie pure et dure mais du balayage par pas successifs de 0.1, 0.01, 0.001...
Je sais bien qu'on peut me coincer : ce que j'ai fait est un moindre mal et n'a pas prétention à être du travail pour un résultat professionnel. Je pars du principe qu'on ne cherchera pas à coincer le prog comme tu l'as fait, encore que peut-être le coup de l'extremum sur x'Ox intervient dans les fonctions standards bateaux comme x**3-3*x+2...
La dichotomie, ce serait je tape au milieu de [a,b] et je joue à c'est plus, c'est moins : j'ai essayé, j'ai trouvé ça chiant au possible et moins fiable que mon balayage...

Barbichu a écrit :

essaye avec les racines entre [0, 1], ça ne marche pas, mais je pense que c'est juste un bug.

Vrai... bien vu...
Faut que je trouve pourquoi ça bugue; parce qu'avec [-0.1,1.0], ça marche... Donc c'est pas un problème de largeur d'intervalle...

De toutes façons ses profs, on posé à zanarc (et à ses petits copains) un problème "insoluble" (et en ont-ils conscience ? et si oui dans quel but ? Ils doivent bien avoir une idée derrière la tête, c'est pas possible auytrement. Mais du diable si j'arrive à trouver laquelle...). En outre, moi, j'ai bataillé ferme... Même si je ne suis pas un phénix, j'ai quand même une certaine expérience de la programmation bête et méchante au début, structurée ensuite...
C'est loin d'être le cas de ceux qui se retrouvent avec le sujet sur les bras...

Et vu le cahier des charges, j'hallucine....

@+

PS : J'ai pris trop de temps : je répondais à karlun, vous avez eu le temps d'échanger

Dernière modification par yoshi (09-12-2010 19:40:41)


Arx Tarpeia Capitoli proxima...

Hors ligne

#40 09-12-2010 20:04:56

yoshi
Modo Ferox
Inscription : 20-11-2005
Messages : 16 989

Re : traitement de fonctions mathématiques.

Bonsoir,

Je viens d'aller voir le site : j'espère que ton cours est un peu plus détaillé et que tu as eu des petits exercices à faire pour chaque point traité...

Je dois dire que lorsque j'ai commencé Python, même si j'avais des notions de programmation en Algol, avec le Basic de ma TI66, avec le Basic de l'Amstrad CPC 6128, celui des Amstrad PCW, un peu d'Assembleur, le GFA BASIc (Atari) et le Turbo BASIC, si on m'avait donné ce devoir à rendre en 3 semaines, j'en aurais été incapable, du moins la conception de l'interface et de la procédure (et non fonction ici) root...
Avec ce seul support, même un peu plus détaillé, je me retrouvais coincé !

@+


Arx Tarpeia Capitoli proxima...

Hors ligne

#41 09-12-2010 23:07:51

yoshi
Modo Ferox
Inscription : 20-11-2005
Messages : 16 989

Re : traitement de fonctions mathématiques.

Re,

En gros, on t'explique comment fonctionne une voiture dans le détail, on te fait changer les pneus, les roues, des balais d'essuie-glace, des lampes, le fonctionnement des moteurs à explosion... etc.
Pis un jour, on te conduit sur l'Autoroute, et on te dit : << Tiens, à toi, le volant... Roule petit bolide !... >>
Bon, je caricature, mais il y a de ça...

Je vais revoir le fonctionnement de la dichotomie, dès fois que je trouve quelque chose de propre cette fois (sachant que ce serait forcément moins bien que le balayage).
Je suis relativement satisfait de ce que j'ai fait, même si Barbichu (et il très fort en Maths, comme en Info) a bien montré les limites de ma dernière version et de toute méthode différente : espérer réussir quelque chose d'infaillible est irréaliste.
Faut faire avec...
Les candidats à l'épreuve finale du jeu de TF1 le soir, gagnerait très vite en étant bien dichotomiques...
J'avais programmé dans le temps, en Basic, une recherche documentaire dans un stock de 1500 titres : 11 essais maxi suffisaient : 2^11=2048...
C'est un peu le même principe pour les compétitions d'Echecs se déroulant au système dit "Système Suisse" (ou des tournois de Tennis) : on peut désigner un vainqueur parmi 128 joueurs si tout le monde joue 7 parties : 2^7 = 128 (pas d'éliminations directes)...

Maintenant, si ton prof rejetait ce que j'ai fait, je ne saurais trop comment corriger le tir : aurais-tu des commentaires disant ce qui ne va pas ?
Où en sont tes copains ? Qu'ont-ils trouvé (pour ma culture personnelle) ? Le sais-tu ?

@+


Arx Tarpeia Capitoli proxima...

Hors ligne

#42 10-12-2010 10:48:42

yoshi
Modo Ferox
Inscription : 20-11-2005
Messages : 16 989

Re : traitement de fonctions mathématiques.

Salut,

J'ai vu que dans vos cours figuraient les "list comprehension", alors pour faire "joli" j'ai modifié la fin de la procédure root pour caser cette méthode :

def root(f,a,b):
    encadre,encadre_A,nc,pas=[(a,b)],[],1,1
    for i in xrange(1,9):                
        pas*=0.1                    # pas : largeur de l'encadrement
        nc =len(encadre)            # nc : nombre de couples retenus
        for j in xrange(nc):        # indice du couple à charger
            (c,d)=encadre[j]        # chargement du couple à affiner
            x1,x=c,c
            f1,fin=eval(f),0              # 1ere valeur
            while not fin or x2<d:             # recherche à la précision donnée
                x2,x3=x1+pas,x1+2*pas   # |
                x=x2                    # |
                f2=eval(f)              # |> valeurs suivantes
                x=x3                    # |
                f3=eval(f)              # |
                if(f1<=0 and f2>0) or (f1>0 and f2<=0): # Th. des gendarmes
                    encadre_A.append((x1,x2))
                    fin=1
                elif (abs(f1)<=pas or abs(f2)<=pas)and\
                     ((f2-f1)*(f3-f2))/((x2-x1)*(x3-x2))<0: #détection croissce/décroissce
                    encadre_A.append((x2-pas/2,x2+pas/2))
                    fin=1
                x1,f1=x2,f2      
        encadre,encadre_A=encadre_A,[]
    # Stockage des bornes inférieures arrondies à 10**(-6), tri et suppresion des doublons
    encadre=sorted(set([round(c,6) for (c,d) in encadre]))
    # Affichage et gestion du pluriel
    print 'root'+'s'*(len(encadre)>1)+" in ["+str(a)+","+str(b)+"] : ",
    for a in encadre:
        print "f("+str(a)+") =",
    print 0

@+


Arx Tarpeia Capitoli proxima...

Hors ligne

#43 10-12-2010 14:49:40

yoshi
Modo Ferox
Inscription : 20-11-2005
Messages : 16 989

Re : traitement de fonctions mathématiques.

Ave,

Bon j'ai écrit une recherche dichotomique, mais ça ne marche pas toujours...
Il faut commencer par rechercher, dans un premier passage, a et b tels que f(a)*f(b)=0 et, une fois trouvés, enclencher la recherche dichotomique...
Le tout est de savoir avec quelle précision on fait ce premier passage...
Mais comme prévu, elle ne trouve pas la racine en cas de tangence entre la courbe et l'axe des x, ce qui oblige à rajouter un petit quelque chose...
Ou alors, et je rejpoins barbichu, on ne lance la recherche de racines qu'entre deux bornes a et b, soigneusement choisies pour que f(a)*f(b)<0

Je garde en réserve en attente des réactions de ton prof...
Dans mon post précédent, j'avais oublié de retirer en dessous de def root(f,a,b), la mention ;
global encadre, encadre_A
Cela me servait à voir les listes directement dans la console : sans cette mention, ces listes ne sont pas visibles à l'extérieur de la procédure de root...

@+


Arx Tarpeia Capitoli proxima...

Hors ligne

#44 10-12-2010 22:40:51

yoshi
Modo Ferox
Inscription : 20-11-2005
Messages : 16 989

Re : traitement de fonctions mathématiques.

Re,

def area(f,a,b):
    nbi=10**6
    pas=(b-a)*10**(-6)
    k=pas/2
    S=0
    x=a
    f1=eval(f)
    for i in xrange(1,nbi):      
        x+=pas
        f2=eval(f)
        S+=(f1+f2)
        f1=f2
    S*=k
    print "area under ["+str(a)+","+str(b)+"] :",round(S,5)

Ci-dessus une petite modification de la procédure area, j'économise 999999 multiplications par la hauteur pas du trapèze...
En effet, l'aire du trapèze vaut  [tex]\frac{(f_1+f_2)\times pas}{2}[/tex]
que l'on peut aussi écrire :
[tex](f_1+f_2)\times\frac{pas}{2}[/tex] et j'ai posé k=pas/2, ce qui me donne pour un  trapèze :
Aire1 = (f1+f2) * k
Et pour les suivants :
Aire2 = (f2+f3) * k
Aire3 = (f3+f4) * k...etc

Si j'additionne tout cela, je constate qu'y y a un facteur commun k...
Et je me contente donc de faire une boucle où je calcule :
[tex]S=\sum_{i=1}^{10^6}(f_i+f_{i+1})[/tex], pour en sortie de boucle, multiplier le résultat par k.
D'où 999999 multiplications par k économisées... Et gain de temps de calcul...

Après réflexion encore, je ne crois pas qu'on puisse faire l'économie avant que d'utiliser la méthode dichotomique, de faire une recherche de tous les couples (c,d) pour c et d appartenant à l'intervalle [a,b] que tu choisis lorsque tu tapes root a b, après l'invite <> Enter a command : ...
En effet, je viens de relire ton tout 1er post et j'y ai vu :

Le programme doit être capable de gérer le cas des racines multiples sur l'intervalle.

Donc, fournis plutôt à ton prof cette procédure :

def root(f,a,b):
    encadre_A,encadre,nc,pas=[(a,b)],[],1,1
    pas=0.1
    x1,x,x2=a,a,a+0.1
    f1=eval(f)
    # Balayage de [a;b] pour encadrement des solutions à 0.1 près
    while x2<b:
        x2=x1+pas
        x=x2
        f2=eval(f)              
        if(f1<=0 and f2>0) or (f1>0 and f2<=0): # Th. des gendarmes
            encadre.append((x1,x2))
        x1,f1=x2,f2
    encadre_A=[]
    # Recherche dichotomique des solutions à 10^-7 près dans chaque
    # intervalle [x1 ; x2] de départ :
    for (x1,x2) in encadre:
        while x2-x1>10**(-7):
            x=x1
            f1=eval(f)
            x=x2
            f2=eval(f)
            x=(x1+x2)/2   # Abscisse du point médian
            fm=eval(f)    # Ordonnée du point médian
            if f1*fm<=0:  # Rejet de la moitié droite
                x2=x
            else:         # Rejet de la moitié gauche
                x1=x
        encadre_A.append((x1,x2)) # Stockage des nouvelles bornes
    # Stockage des bornes inférieures arrondies à 10^-6 près
    encadre=[round(x1,6) for (x1,x2) in encadre_A]
    # Affichage (avec gestion du pluriel)
    print 'root'+'s'*(len(encadre)>1)+" in ["+str(a)+","+str(b)+"] : ",
    for a in encadre:
        print "f("+str(a)+") =",
    print 0

Résultat pour f(x)=x**3-2*x+1 :

================================================================================
OPMATH : perform miscellaneous processing on a mathematical function
================================================================================
Note : enter an empty line to stop the interaction loop
<> Enter a command :  def x**3-2*x+1
f(x) = x**3-2*x+1
<> Enter a command : root -2.0 2.0
roots in [-2.0,2.0] :  f(-1.618034) = f(0.618034) = f(1.0) = 0
<> Enter a command :

Et tu lui dis :

Monsieur,
la recherche dichotomique ne peut pas trouver  la racine x=1, dans le cas où f(x)= x**3-3*x+2...
Il n'y aucun a et b tels que f(a)*f(b)<0 : l'axe des abscisses est tangent à la courbe.

@+


Arx Tarpeia Capitoli proxima...

Hors ligne

#45 13-12-2010 22:45:19

yoshi
Modo Ferox
Inscription : 20-11-2005
Messages : 16 989

Re : traitement de fonctions mathématiques.

Salut,

Dès que tu as une remarque de ton prof, fais-moi signe pour que je puisse réagir si nécessaire...
Je réfléchis toujours à une amélioration de ma méthode de détection des racines qi n'utilise pas la dichotomie.
Je réfléchis également à un moyen de gagner de la vitesse dans la procédure def area.

@+


Arx Tarpeia Capitoli proxima...

Hors ligne

#46 14-12-2010 14:16:47

yoshi
Modo Ferox
Inscription : 20-11-2005
Messages : 16 989

Re : traitement de fonctions mathématiques.

Re,

J'ai abouti ce matin à une version plus propre (et plus rapide) du code du balayage pour les racines :

def root(f,a,b):
    encadre,encadre_A=[(a,b)],[]
    for i in xrange(1,8):
        pas=10**(-i)                    # Définition des pas successifs
        for(c,d) in encadre:            # Chargement des bornes
            x1,x=c,c                    # |
            f1=eval(f)                  # |
            x2=c+pas                    # |> Initialisation des 2 premières valeurs
            x=x2                        # |
            f2=eval(f)                  # |
            cpt=1                       # Initialisation d'un compteur
            while x2<=d:                
                cpt+=1                  # Incrémentation du compteur
                x3=c+pas*cpt        # Calcul de la 3e abscisse
                x=x3
                f3=eval(f)
                if f1*f2<=0:            # Théorème des gendarmes
                    encadre_A.append((x1,x2))               # Stockage des bornes
                #détection croissance/décroissance
                elif abs(f2)<=pas and ((f2-f1)*(f3-f2))/((x2-x1)*(x3-x2))<0:
                    encadre_A.append((x1,x3))   # stockage des bornes
                x1,f1,x2,f2=x2,f2,x3,f3                                  
        encadre,encadre_A=sorted(encadre_A),[]  # Transfert et tri avant nouvelle itération
    # Enregistrement des bornes inférieures arrondies à 10**(-6)                                
    encadre=[round(c,6) for (c,d) in encadre]      
    # Affichage et gestion du pluriel
    print 'root'+'s'*(len(encadre)>1)+" in ["+str(a)+","+str(b)+"] : ",
    for a in encadre:
        print "f("+str(a)+") =",
    print 0

Et une autre version de def area, plus rapide :

def area(f,a,b):
    nbi=10**6
    pas=(b-a)*10**(-6)
    k=pas/2
    S=0
    x=b
    fn=eval(f)
    x=a
    f1=eval(f)  
    for i in xrange(1,nbi):      
        x+=pas
        f2=eval(f)
        S+=f2
    S=(2*S+f1+fn)*k
    # Affichage du résultat
    print "area under ["+str(a)+","+str(b)+"] :",round(S,5)

Explication :
L'aire vaut :
[tex]S=(f_1+f_2)\times\frac{pas}{2}+(f_2+f_3)\times\frac{pas}{2}+\cdots+(f_{n-1}+f_n)\times\frac{pas}{2}=(f_1+f_2+f_2+f_3+\cdots+f_{n-1}+f_n)\times \frac{pas}{2}[/tex]

Et je me suis donc avisé qu'on pouvait encore écrire S ainsi :
[tex]S=(f_1+2f_2+f_2+2f_3+\cdots+2f_{n-1}+f_n)\times \frac{pas}{2}[/tex]
Je commence donc par calculer les première et dernière ordonnée : f1 et fn
Puis dans ma boucle, pour i=1,2....n-1, je calcule [tex]f_2+f_3+f_4= ... + f_{n-1}[/tex]
En sortie de boucle, je multiplie ce résultat par 2, j'ajoute f1 et fn, et je multiplie le tout par pas/2...
En fait ce n'est rien d'autre que de la factorisation !

================================================================================
OPMATH : perform miscellaneous processing on a mathematical function
================================================================================
Note : enter an empty line to stop the interaction loop
<> Enter a command : def x**3-2*x+1
f(x)=x**3-2*x+1
<> Enter a command : root -2.0 2.0
roots in [-2.0,2.0] :  f(-1.618034) = f(0.618034) = f(1.0) = 0
<> Enter a command : area -0.6 1.6
area under [-0.6,1.6] : 1.606
<> Enter a command :

Vérification des racines :
[tex]x^3-2x+1=0[/tex] a 3 racines qui sont :  [tex]x_1=\frac{1-\sqrt 5}{2},\;x_2=\frac{1+\sqrt 5}{2}\;et\;x_3 = 1[/tex]
[tex]x_1 \approx 0.61803398874...\;et\; x_2 \approx 1.61803398874... [/tex]

Vérification de l'Aire :
[tex]S=\int_{-0.6}^{1.6}\;(x^3-2x+1)\;dx  =\left[\frac{x^4}{4}-x^2+x\right]_{-0.6}^{1.6}=1.606[/tex]

Ça colle !

@+


Arx Tarpeia Capitoli proxima...

Hors ligne

#47 14-12-2010 17:18:05

zarnac
Membre
Inscription : 29-11-2010
Messages : 39

Re : traitement de fonctions mathématiques.

Re!!!

Désolé de t'avoir fait attendre ,j'ai vu le prof concernant la procédure root :

donc il a en effet pu constater que il manquait une racine pour la fonction dont tu m'avais citée. Après il m'a dit en effet que ça pouvait passer ...

Il m'a éventuellement dit de faire par la méthode de la dérivée, ou mieux encore la descente du gradient ... je sais pas si ca te parle, moi si puisque je l'étudie en fonctions .
Il ma dit que si j'appliquais la méthode de la dérivée pour trouver un maximum et un minimum local , le pas dépendrait de l'allure de la courbe:
si la courbe admet une courbe strictement descendante alors il faudra adopté pour un pas très petit.
si la courbe décroit de manière progressive moins forte, il faudra adopter un pas plus grand.
Enfin voilà ... il a rien dit de particulier
ce n'est qu'une méthode parmi tant d'autres, mais celle-ci est mieux pour l'application de grosses fonctions.

je me suis permis de faire un programme concernant les procédures où on obtenait un résultat avec beaucoup de 0 après la virgule, ce qui me paraissait pas trop trop nécessaire, jai fait:

def strip0(s):
    if type(s)!=type(""):
        s = str(s)
    if not '.' in s: return s
    i = len(s)-1
    while i>=0:
        if s[i] != '0':
            if s[i] == '.': i-=1
            break
        i-=1
    return s[:i+1]

Nice job sinon , merci beaucoup , je ne pourrai pas m'accorder trop de temps à ça ce soir , j'ai énormément de travail à coté ...Mais je regarderai!

Dernière modification par zarnac (14-12-2010 17:33:15)

Hors ligne

#48 14-12-2010 18:32:22

yoshi
Modo Ferox
Inscription : 20-11-2005
Messages : 16 989

Re : traitement de fonctions mathématiques.

RE,

Donc, il accepte, la méthode de "dichotomie préparée", préparée puisque comme tu l'as vu, la version avec dichotomie a besoin d'être préparée par une recherche à 10**-1 des encadrements : j'ai préféré que tu lui fournisses la méthode dichotomique puisqu'elle était suggérée dans ton "cahier des charges".

Pour la version d'aujourd'hui, je suis revenu à ma méthode de départ que j'ai améliorée, débarrassée de correctifs qui ne devaient pas être (suppression des doublons) : cette fois-ci, je suis satisfait de mon code et de la méthode de recherche des solutions qui sont en même temps des extrema de la fonction.
Ça marche très bien avec f(x) = x**3-3*x+2 :

IDLE 2.6.4     
>>> ================================ RESTART ================================
>>>
================================================================================
OPMATH : perform miscellaneous processing on a mathematical function
================================================================================
Note : enter an empty line to stop the interaction loop
<> Enter a command : def x**3-3*x+2
f(x) = x**3-3*x+2
<> Enter a command : root -2.0 2.0
roots in [-2.0,2.0] :  f(-2.0) = f(1.0) = 0
<> Enter a command :

Je vais d'ailleurs modifier le code pour moi et ajouter la procédure def extrema(f,a,b) où je vais rechercher les "sommets" éventuels de la courbe...

Utiliser la méthode de la dérivée qu'il a dit : j'y avais pensé... Ceci dit, il est marrant lui...
J'avais bien envisagé de calculer la dérivée comme on le fait à la main, mais j'ai reculé : trop de cas possibles...
Alors j'ai utilisé un moyen terme.
La dérivée de f(x) étant la limite, quand h tend vers 0, de [tex]\frac{f(x+h)-f(x)}{(x+h)-x}[/tex], et cette limite en un point étant le coefficient directeur de la tangente en ce point, j'ai pris 3 points consécutifs A, B, C d'abscisses x1,x1+pas et x1+pas*2, et j'ai examiné le produit des coefficient directeurs de (AB) et (BC) : dès que le pas est petit, il y a très peu d'écart avec les tangentes.
Si ce produit est négatif ou nul, il y a inversion de courbure et donc un extremum très voisin du point médian.
et donc je choisis pour une nouvelle itération deux bornes qui sont x2-pas/2 et x2+pas/2...
Si de plus la valeur absolue de l'ordonnée du point médian est inférieure au pas et donc tend elle aussi vers 0, j'ai trouvé un encadrement d'un extremum solution...
Je recommence avec un pas tendant vers 0 : 0.1, 0.01, 0.001, 0.0001... je m'arrête à 10**-7 pour pouvoir arrondir à 10**-6...
Et ça marche aussi, "proprement" cette fois...

Descente du gradient ??? Jamais entendu parler... Je vais chercher à m'instruire.

Bon, si ton prof est satisfait et toi aussi , alors tout est pour le mieux...
As-tu l'impression d'avoir progressé en programmation ? D'avoir appris quelque chose, de te sentir moins "pataud" ?

Et tes potes, ils ont avancé ? Certains ont des solutions originales ?
Si oui, ça m'intéresse...

@+

[EDIT]C'est fait, j'ai implémenté def extr(f,a,b):
A cette occasion, je me suis aperçu que prendre comme bornes x2-pas/2 et x2+pas/2 ne marchait pas toujours, je suis donc passé à un encadrement plus large x1,x3, qui lui est sûr et je lance une itération de plus...
Bin, jusqu'à 10**-8 de pas, ça colle pour x**3-2*x+1 et pour 10**-9, je rate un extremum...
Diantre !
Je vais chercher pourquoi...

Dernière modification par yoshi (14-12-2010 19:15:53)


Arx Tarpeia Capitoli proxima...

Hors ligne

#49 19-12-2010 19:35:48

yoshi
Modo Ferox
Inscription : 20-11-2005
Messages : 16 989

Re : traitement de fonctions mathématiques.

Bonsoir,

Version revue et corrigée :

#!/usr/bin/env python
# -*- coding: Latin-1 -*-

from math import cos,sin,tan,sqrt,exp,log,pi

def root(f,a,b):
    encadre,encadre_A=[(a,b)],[]
    for i in xrange(1,8):
        pas=10**(-i)                    # Définition des pas successifs
        for(c,d) in encadre:
            c,d=c-pas,d+pas             # Chargement des bornes élargies
            x1,x,x2,cpt=c,c,c+pas,1     # Initialisations
            f1=eval(f)                  #
            while x2<=d:
                x=x2
                f2=eval(f)
                if f1*f2<=0:            # Théorème des gendarmes
                    encadre_A.append((x1,x2))               # Stockage des bornes
                #détection croissance/décroissance
                cpt+=1
                x1,f1,x2=x2,f2,c+pas*cpt                                
        encadre,encadre_A=sorted(encadre_A),[]  # Transfert et tri avant nouvelle itération
    # Enregistrement des bornes inférieures arrondies à 10**(-6)                                
    encadre=sorted(set([round(c,6) for (c,d) in encadre]))      
    # Affichage et gestion du pluriel
    print 'root'+'s'*(len(encadre)>1)+" in ["+str(a)+","+str(b)+"] : ",
    for a in encadre:
        if str(a)=="-0.0":
            a=0.0      
        print "f("+str(a)+")"
    print 0

def dicho(f,a,b):
    encadre_A,encadre,nc,pas=[(a,b)],[],1,1
    pas=0.1
    x1,x,x2=a,a,a+0.1
    f1=eval(f)
    # Balayage de [a;b] pour encadrement des solutions à 0.1 près
    while x2<b:
        x2=x1+pas
        x=x2
        f2=eval(f)              
        if(f1<=0 and f2>0) or (f1>0 and f2<=0): # Th. des gendarmes
            encadre.append((x1,x2))
        x1,f1=x2,f2
    encadre_A=[]
    # Recherche dichotomique des solutions à 10^-7 près dans chaque
    # intervalle [x1 ; x2] de départ :
    for (x1,x2) in encadre:
        while x2-x1>10**(-7):
            x=x1
            f1=eval(f)
            x=x2
            f2=eval(f)
            x=(x1+x2)/2   # Abscisse du point médian
            fm=eval(f)    # Ordonnée du point médian
            if f1*fm<=0:  # Rejet de la moitié droite
                x2=x
            else:         # Rejet de la moitié gauche
                x1=x
        encadre_A.append((x1,x2)) # Stockage des nouvelles bornes
    # Stockage des bornes inférieures arrondies à 10^-6 près
    encadre=[round(x1,6) for (x1,x2) in encadre_A]
    # Affichage (avec gestion du pluriel)
    print 'root'+'s'*(len(encadre)>1)+" in ["+str(a)+","+str(b)+"] : ",
    for a in encadre:
        print "f("+str(a)+") =",
    print 0      

def extrema(f,a,b):
    encadre,encadre_A=[(a,b)],[]
    for i in xrange(1,9):
        pas=10**(-i)
        for(c,d) in encadre:
            x1,x,x2,x3=c,c,c+pas,c+pas*2 # Ininitialisations
            f1=eval(f)                   #|
            x=x2                         #|
            f2=eval(f)                   #|> coord. des 3 premiers points
            x=x3                         #|
            f3=eval(f)                   #|
            while x2<=d:
                x4=x1+pas*3              #|
                x=x4                     #|> Coord. du 4e point
                f4=eval(f)               #|
                #détection croissance/décroissance
                if (f2-f1)*(f4-f3)<=0:
                    encadre_A.append((round((x1+x2)/2,i+1),round((x3+x4)/2,i+1)))                  
                x1,f1,x2,f2,x3,f3=x2,f2,x3,f3,x4,f4
        # Transfert et tri avant nouvelle itération        
        if len(encadre_A)>0:
            encadre,encadre_A=set(encadre_A),[]                              
    # Enregistrement des bornes inférieures arrondies à 10**(-6)                                
    encadre=sorted(set([round(c,6) for (c,d) in encadre]))      
    # Affichage et gestion du pluriel
    l=len(encadre)
    if l<2:
        mot='extremum'
    else:
        mot='extrema'
    print mot+" in ["+str(a)+","+str(b)+"] : ",
    if l==0:
        print "None"
    else:
        for a in encadre:
            x=a
            if str(a)=="-0.0":
                a,x=0.0,0.0
            print "f("+str(a)+") =",eval(f)," ",
        print      
   
def maxi(f,a,b):
    xmax,maxi=-100,-1000
    n=4
    x,pas=a,10**(-n)
    nbi = int(abs(b-a)*10**n)
    if a+pas*(nbi-1)<b:
        nbi+=1
    for i in xrange(nbi):
        ff=eval(f)
        if ff>maxi:
            xmax,maxi=x,ff
        x+=pas
    print "max in ["+str(a)+","+str(b)+"] : f("+str(xmax)+") =",maxi
   
def mini(f,a,b):
    xmin,mini=100,1000
    n=4
    x,pas=a,10**(-n)
    nbi = int(abs(b-a)*10**n)
    if a+pas*(nbi-1)<b:
        nbi+=1
    for i in xrange(nbi):
        ff=eval(f)
        if ff<mini:
            xmin,mini=x,ff
        x+=pas
    print "min in ["+str(a)+","+str(b)+"] : f("+str(xmin)+") =",mini          

def area(f,a,b):
    nbi=10**6
    pas=(b-a)*10**(-6)
    k=pas/2
    S=0
    x=b
    fn=eval(f)
    x=a
    f1=eval(f)  
    for i in xrange(1,nbi):      
        x+=pas
        S+=abs(eval(f))
    S=(2*S+f1+fn)*k
    # Affichage du résultat
    print "area under ["+str(a)+","+str(b)+"] :",round(S,5)

print '================================================================================'
print 'OPMATH : perform miscellaneous processing on a mathematical function'
print '================================================================================'
print 'Note : enter an empty line to stop the interaction loop'
f = None
while 1:
    command = raw_input("<> Enter command : ")
    if not command:
        print "End of program."
        break
    elif command.startswith('def '):
        f = command.lstrip('def ')
        print "f(x)=%s" % f
    elif command.startswith('val '):
        x = float(command.lstrip('val '))
        try:
            print "f(%f)=%f" % (x,eval(f))
        except TypeError:
            print "No function defined."
    elif command[:command.find(' ')] in "root dicho mini maxi area extrema":
        command=command.split(' ')
        command=command[0]+'(f,'+command[1]+','+command[2]+')'
        try:
            exec(command)
        except TypeError:
            print "No function defined."
    else:
        print "Unknown command."

Pour le calcul des extrema (qui n'était pas fiable), j'ai changé mon fusil d'épaule et maintenant j'utilise 4 points distants de la valeur du pas calculé, disons A, B, C, D.
Je calcule leurs coordonnées pour utiliser une version "simplifiée" des calculs de coefficients directeurs qui devraient être : (f2-f1)/(x2-x1) et  (f4-f3)/(x4-x3)... Or, les différences x2-x1 et x4-x3 sont toujours égales et toujours positives..
Donc au lieu de tester si le produit des coeff. dir. est <=0, je me contente de tester si (f2-f1)* (f4-f3)<=0, ce qui économise pas mal de temps de calcul...
Si le test est concluant, les coordonnées de l'extremum vont être très voisines de celles du point médian d'abscisse entre B et C...
Par précaution, je stocke comme bornes, les abscisses des milieux respectifs de [AB] et [CD]...
Mais cet encadrement valant pas*2, cela m'oblige à une itération de plus pour arrondir à 10**(-6) et donc d'aller jusqu'à 10**(-8)... d'où la boucle de i=1 à 9 (rappel : qui s'arrête à 8).

D'autre part, le calcul des aires, y compris via l'intégration, donnait des résultats faux si, entre les 2 bornes choisies, une partie de la courbe est au dessus de l'axe des x et l'autre en dessous : en effet pour la partie en dessous, l'aire calculée est négative et se soustrait donc au lieu de s'ajouter.
Deux remèdes : inverser les bornes ou passer aux valeurs absolues, ce qui ralentit un peu le calcul, déjà très lent (j'ai pourtant fini par le réduire à sa plus simple expression).
J'ai opté pour la valeur absolue...
J'ai gardé et simplifié ma méthode root, ajouté le calcul des racines par dichotomie via : dicho a b...
Il est possible que j'améliore encore le programme,en particulier la procédure root qui m'oblige à trier et supprimer les doublons, j'y réfléchis...

@+


Arx Tarpeia Capitoli proxima...

Hors ligne

#50 23-12-2010 16:03:44

yoshi
Modo Ferox
Inscription : 20-11-2005
Messages : 16 989

Re : traitement de fonctions mathématiques.

Re,

La procédure dicho, c'est la procédure de recherche des racines par dichotomie, ce que tu as envoyé à ton prof.

La procédure root c'est la procédure de recherche des racines par balayage, que j'ai retouchée...

J'ai donc laissé 2 façons de calculer les racines, tu conserves celle de ton choix, ou les deux, comme tu veux !

La procédure extrema, c'est la recherche des valeurs de x où la dérivée est nulle,  i.e les valeurs où le coefficient directeur de la tangente à la courbe est nul, et donc où la tangente à la courbe est horizontale : on appelle ça aussi minimum et maximum, points regroupés sous le terme générique de "extremum", au pluriel en latin extrema.
C'est donc différent de la valeur mini, ou la valeur maxi de la fonction sur un intervalle considéré dont les procédures avaient déjà été écrites : là, il s'agissait de trouver le point le plus "bas" et le point le plus "haut" de la courbe..
Si je prends f(x) = x**4-2*x**2+3, fonction bicarré, les extrema ont pour abscisses x=-1, x =0 et x = 1.
La preuve : [tex]f'(x) =4x^3-4x=4x(x^2-1)=4x(x+1)(x-1)[/tex]
La dérivée s'annule donc bien pour x =0, x = -1 et x = 1.

================================================================================
OPMATH : perform miscellaneous processing on a mathematical function
================================================================================
Note : enter an empty line to stop the interaction loop
<> Enter command : def x**4-2*x**2+3
f(x) = x**4-2*x**2+3
<>Enter command : extrema -2.0 2.0
extrema in [-2.0,2.0] :  f(-1.0) = 2.0  f(0.0) = 3.0  f(1.0) = 2.0
<> Enter command :
End of program.
>>>

Pas de quoi s'embrouiller, non ?

C'est bon maintenant ?

@+


Arx Tarpeia Capitoli proxima...

Hors ligne

Pied de page des forums