/*************************************************************************************************************************************/ /* */ /* E T U D E D E S V A R I A T I O N S D ' U N E F O N C T I O N : */ /* */ /* */ /* Author of '$xtc/var_fonc.01$c' : */ /* */ /* Jean-Francois COLONNA (LACTAMME, AAAAMMJJhhmmss). */ /* */ /*************************************************************************************************************************************/ #include "INCLUDES.01.I" /* Introduit le 20051116103102... */ extern double sqrt(); extern double log(); extern double drand48(); extern double sin(); #define NOMBRE \ 1000 \ /* Nombre de points sur l'axe 'OX'. */ #define PREMIER \ 0 #define DERNIER \ (NOMBRE-1) #define DELTAX \ 1.0/FLOT(DERNIER-PREMIER) #define FLOT(x) \ ((double)(x)) #define INITIALISATION_DE_LA_FONCTION(Xmin,Yformule,titre) \ { \ int n; \ \ Xfonction_minimum=+1.0e300; \ Xfonction_maximum=-1.0e300; \ Yfonction_minimum=+1.0e300; \ Yfonction_maximum=-1.0e300; \ \ Xcommun[0] = Xmin; \ \ for (n=(PREMIER+1) ; n <= DERNIER ; n++) \ { \ Xcommun[n] = Xcommun[n-1] + DELTAX; \ /* Definition de la coordonnee 'X' commune a la fonction et a sa "diagonale". */ \ } \ \ for (n=PREMIER ; n <= DERNIER ; n++) \ { \ double fn=n*DELTAX; \ \ Yfonction[n] = Yformule; \ /* Definition de la coordonnee 'Y' de la fonction. */ \ } \ \ for (n=PREMIER ; n <= DERNIER ; n++) \ { \ double fn=n*DELTAX; \ \ Ydiagonale[n] = BARY(Yfonction[0],Yfonction[DERNIER],fn); \ /* Definition de la coordonnee 'Y' de la "diagonale" de la fonction. */ \ } \ \ for (n=PREMIER ; n <= DERNIER ; n++) \ { \ Xfonction_minimum = MIN2(Xcommun[n],Xfonction_minimum); \ Xfonction_maximum = MAX2(Xcommun[n],Xfonction_maximum); \ \ Yfonction_minimum = MIN2(Yfonction[n],Yfonction_minimum); \ Yfonction_maximum = MAX2(Yfonction[n],Yfonction_maximum); \ /* Recherche des extrema en {X,Y} de la fonction. */ \ } \ \ Yderivee_premiere[PREMIER] = 0; \ for (n=(PREMIER+1) ; n <= DERNIER ; n++) \ { \ Yderivee_premiere[n] = (Yfonction[n] - Yfonction[n-1]) / (Xcommun[n] - Xcommun[n-1]); \ } \ \ Yderivee_seconde[PREMIER] = 0; \ Yderivee_seconde[PREMIER+1] = 0; \ for (n=(PREMIER+2) ; n <= DERNIER ; n++) \ { \ Yderivee_seconde[n] = (Yderivee_premiere[n] - Yderivee_premiere[n-1]) / (Xcommun[n] - Xcommun[n-1]); \ } \ \ printf("\n %s",titre); \ printf(" DY=[%+5.2f,%+5.2f]",Yfonction_minimum,Yfonction_maximum); \ } \ /* Initialisation de la fonction. */ #define EPSILON_DERIVEE_PREMIERE \ 1.0e-1 #define MOYENNE_DE_LA_DERIVEE_PREMIERE_DE_LA_FONCTION \ { \ int n; \ \ derivee_premiere_moyenne=0; \ \ for (n=PREMIER ; n <= DERNIER ; n++) \ { \ derivee_premiere_moyenne = derivee_premiere_moyenne + Yderivee_premiere[n]; \ } \ \ derivee_premiere_moyenne = derivee_premiere_moyenne / NOMBRE; \ /* Evidemment cette valeur est aussi egale a : */ \ /* */ \ /* f(b) - f(a) */ \ /* ------------- */ \ /* b - a */ \ /* */ \ /* ou [a,b] est le segment de definition, mais faire le calcul ainsi ouvre la porte a des */ \ /* extensions futures... */ \ \ printf(" M(d)=%+9.4f",derivee_premiere_moyenne); \ } \ /* Calcul de la moyenne de la derivee premiere de la fonction. */ #define MOYENNE_DE_LA_DERIVEE_SECONDE_DE_LA_FONCTION \ { \ int n; \ \ derivee_seconde_moyenne=0; \ \ for (n=PREMIER ; n <= DERNIER ; n++) \ { \ derivee_seconde_moyenne = derivee_seconde_moyenne + Yderivee_seconde[n]; \ } \ \ derivee_seconde_moyenne = derivee_seconde_moyenne / NOMBRE; \ /* Evidemment cette valeur est aussi egale a : */ \ /* */ \ /* f'(b) - f'(a) */ \ /* ------------- */ \ /* b - a */ \ /* */ \ /* ou [a,b] est le segment de definition, mais faire le calcul ainsi ouvre la porte a des */ \ /* extensions futures... */ \ \ printf(" M(dd)=%+9.4f",derivee_seconde_moyenne); \ } \ /* Calcul de la moyenne de la derivee seconde de la fonction. */ #define TEMPERATURE(l,h) \ (1.0/log((2*l) / ((2*l) - h))) #define TEMPERATURE_BASSE \ 0.01 #define TEMPERATURE_ELEVEE \ 20 #define TEMPERATURE_DE_LA_FONCTION \ { \ int n; \ \ longueur_de_la_fonction=0; \ \ for (n=(PREMIER+1) ; n <= DERNIER ; n++) \ { \ longueur_de_la_fonction = longueur_de_la_fonction \ + sqrt((EXP2(Xcommun[n] - Xcommun[n-1])) + EXP2(Yfonction[n] - Yfonction[n-1])); \ } \ \ longueur_de_la_diagonale = sqrt(EXP2(Xcommun[DERNIER] - Xcommun[0]) + EXP2(Ydiagonale[DERNIER] - Ydiagonale[0])); \ temperature_de_la_fonction = TEMPERATURE(longueur_de_la_fonction,longueur_de_la_diagonale) - TEMPERATURE(1.0,1.0); \ /* On retranche 'TEMPERATURE(1.0,1.0)' qui correspond a la temperature la plus basse que */ \ /* l'on puisse atteindre et qui correspond au cas ou la courbe est confondue avec sa */ \ /* "diagonale" (cas de la fonction constante...). On notera qu'en fait, on pourrait */ \ /* evidemment retrancher 'TEMPERATURE(x,x)' et ce quel que soit 'x'... */ \ \ rapport_de_la_fonction_a_la_diagonale=longueur_de_la_fonction/longueur_de_la_diagonale; \ \ printf(" L/D=%+9.4f",rapport_de_la_fonction_a_la_diagonale); \ printf(" T=%+9.4f",temperature_de_la_fonction); \ } \ /* Calcul de la "temperature" de la fonction. */ #define EPSILON_AIRE \ 1.0e-1 #define AIRE_SIGNEE_ENTRE_LA_FONCTION_ET_SA_DIAGONALE \ { \ int n; \ \ aire_signee_entre_la_fonction_et_sa_diagonale=0; \ \ for (n=(PREMIER+1) ; n <= DERNIER ; n++) \ { \ aire_signee_entre_la_fonction_et_sa_diagonale \ = aire_signee_entre_la_fonction_et_sa_diagonale \ + ((Yfonction[n-1] - Ydiagonale[n]) * (Xcommun[n] - Xcommun[n-1])) \ + (((Ydiagonale[n] - Ydiagonale[n-1]) * (Xcommun[n] - Xcommun[n-1]))/2) \ + (((Yfonction[n] - Yfonction[n-1]) * (Xcommun[n] - Xcommun[n-1]))/2); \ } \ \ printf(" A=%+9.4f",aire_signee_entre_la_fonction_et_sa_diagonale); \ } \ /* Calcul de l'aire "signee" comprise entre la fonction et sa "diagonale". */ #define VARIATION_DE_LA_FONCTION \ { \ MOYENNE_DE_LA_DERIVEE_PREMIERE_DE_LA_FONCTION; \ MOYENNE_DE_LA_DERIVEE_SECONDE_DE_LA_FONCTION; \ TEMPERATURE_DE_LA_FONCTION; \ AIRE_SIGNEE_ENTRE_LA_FONCTION_ET_SA_DIAGONALE; \ } \ /* Quelques etudes de variation de la fonction. */ #define ANALYSE_DE_LA_FONCTION \ { \ if (ABSO(temperature_de_la_fonction) <= TEMPERATURE_BASSE) \ { \ printf(" Lineaire"); \ /* Tres faible temperature. */ \ \ if (ABSO(derivee_premiere_moyenne) <= EPSILON_DERIVEE_PREMIERE) \ { \ printf(" Constante"); \ /* Tres faible temperature et tres faible derivee. */ \ } \ else \ { \ if (derivee_premiere_moyenne >= 0) \ { \ printf(" Croissante"); \ /* Tres faible temperature et derivee positive significativement. */ \ } \ else \ { \ printf(" Decroissante"); \ /* Tres faible temperature et derivee negative significativement. */ \ } \ } \ } \ else \ { \ if (ABSO(aire_signee_entre_la_fonction_et_sa_diagonale) <= EPSILON_AIRE) \ { \ if (ABSO(derivee_premiere_moyenne) <= EPSILON_DERIVEE_PREMIERE) \ { \ printf(" (Quasi-)Periodique"); \ } \ else \ { \ printf(" Oscillante (autour de la Diagonale)"); \ } \ /* Temperature significative et aire tres faible. */ \ } \ else \ { \ if (ABSO(temperature_de_la_fonction) >= TEMPERATURE_ELEVEE) \ { \ printf(" Chaotique"); \ /* Temperature tres elevee et aire significative. */ \ } \ else \ { \ if (ABSO(derivee_premiere_moyenne) <= EPSILON_DERIVEE_PREMIERE) \ { \ if (derivee_seconde_moyenne >= 0) \ { \ printf(" Concavite Haut"); \ /* Derivee seconde positive. */ \ } \ else \ { \ printf(" Concavite Bas"); \ /* Derivee seconde negative. */ \ } \ } \ else \ { \ if (derivee_premiere_moyenne >= 0) \ { \ printf(" Croissante"); \ /* Temperature intermediaire, aire significative et derivee premiere assez positive. */ \ } \ else \ { \ printf(" Decroissante"); \ /* Temperature intermediaire, aire significative et derivee premiere assez negative. */ \ } \ } \ } \ } \ } \ } \ /* Analyse heuristique de la fonction. */ #define ETUDE_DE_LA_FONCTION(Xmin,Yformule,titre) \ { \ INITIALISATION_DE_LA_FONCTION(Xmin,Yformule,titre); \ VARIATION_DE_LA_FONCTION; \ ANALYSE_DE_LA_FONCTION; \ } \ /* Etude de la fonction. */ main() { double Xcommun[NOMBRE]; /* Axe des 'X' defini point par point. */ double Yfonction[NOMBRE]; /* Fonction definie point par point. */ double Xfonction_minimum,Xfonction_maximum; double Yfonction_minimum,Yfonction_maximum; /* Extrema de la fonction. */ double Yderivee_premiere[NOMBRE]; double Yderivee_seconde[NOMBRE]; /* Derivees definies point par point. */ double Ydiagonale[NOMBRE]; /* "Diagonale" de la fonction definie point par point. */ double derivee_premiere_moyenne; double derivee_seconde_moyenne; double longueur_de_la_fonction,longueur_de_la_diagonale; double rapport_de_la_fonction_a_la_diagonale,temperature_de_la_fonction; double aire_signee_entre_la_fonction_et_sa_diagonale; /* Quelques valeurs caracteristiques de la fonction. */ ETUDE_DE_LA_FONCTION(0.0 ,1.0 ,"F=1 ............" ); ETUDE_DE_LA_FONCTION(0.0 ,+fn ,"F=+x ..........." ); ETUDE_DE_LA_FONCTION(0.0 ,-fn ,"F=-x ..........." ); ETUDE_DE_LA_FONCTION(0.0 ,EXP2(fn-0.5) ,"F=(x-0.5)^2 ..." ); ETUDE_DE_LA_FONCTION(0.0 ,+EXP2(fn) ,"F=+(x)^2 ......." ); ETUDE_DE_LA_FONCTION(0.0 ,-EXP2(fn) ,"F=-(x)^2 ......." ); ETUDE_DE_LA_FONCTION(0.0 ,sin(1*PI*fn) ,"F=sin(1*pi*x) .." ); ETUDE_DE_LA_FONCTION(0.0 ,sin(2*PI*fn) ,"F=sin(2*pi*x) .." ); ETUDE_DE_LA_FONCTION(0.0 ,sin(3*PI*fn) ,"F=sin(3*pi*x) .." ); ETUDE_DE_LA_FONCTION(0.0 ,sin(4*PI*fn) ,"F=sin(4*pi*x) .." ); ETUDE_DE_LA_FONCTION(0.0 ,fn+sin(1*PI*fn) ,"F=x+sin(1*pi*x) " ); ETUDE_DE_LA_FONCTION(0.0 ,fn+sin(2*PI*fn) ,"F=x+sin(2*pi*x) " ); ETUDE_DE_LA_FONCTION(0.0 ,fn+sin(3*PI*fn) ,"F=x+sin(3*pi*x) " ); ETUDE_DE_LA_FONCTION(0.0 ,fn+sin(4*PI*fn) ,"F=x+sin(4*pi*x) " ); ETUDE_DE_LA_FONCTION(0.0 ,drand48() ,"F=rdn() ........" ); printf("\n\n"); printf(" DX=[%+5.2f,%+5.2f]",Xfonction_minimum,Xfonction_maximum); printf("\n\n"); }