/*************************************************************************************************************************************/
/* */
/* 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");
}