Ensemble de cantor

Description

Classe C++ permettant la manipulation de l'ensemble de Cantor et des notions mathématiques qui y sont associées :
- Appartenance à l'ensemble (à un certain ordre de précision près)
- Escalier de Cantor (méthode renvoyant les valeurs à l'abscisse demandée)
[Vous pourrez ainsi mettre un pied dans la manipulation des fractales :)]
- Tirage aléatoire selon la distribution aléatoire de Cantor

La classe est écrite dans un style C++ standard ; elle est également "inlinée"
comme une classe java pour éviter des dépendances dans les projets utilisateurs.

Le contenu du fichier de main vous montre un exemple de tabulation de l'Escalier de Cantor avec génération aléatoire en parallèle ; le tout étant sauvegardé en ligne dans un fichier afin d'être observé sous GNUPlot par exemple.

Source / Exemple :


#ifndef	_CANTOR_H_
#define	_CANTOR_H_

#include	<math.h>
#include	<stdlib.h>
#include	<vector>

using namespace std;

#ifndef	TRUE
	#define	FALSE	0
	#define	TRUE	1
#endif

/**

  • Classe CANTOR:
  • Permet la manipulation de l'ensemble de Cantor et des éléments numériques
  • de cet ensemble (appartenance, tirage aléatoire).
  • La classe permet également de construire l'escalier de Cantor en vue d'étude
                                                                                                      • /
class Cantor { public: typedef char Digit, Bit; typedef int Int, Bool; typedef double Float; typedef vector< Digit > Pattern_t; private: Int _nOrd; /* ordre de l'ensemble étuié */ Pattern_t _pat; /* "motif" binaire de l'ensemble */ private: /* Réduit le motif de l'ensemble à son "ordre 0", c-à-d [1 0 1] */ void reset_Pattern( void ) { _pat.resize( 3 ); _pat[ 0 ] = 1; _pat[ 1 ] = 0; _pat[ 2 ] = 1; } public: /* Contructeur standard */ Cantor( int nOrd = 0 ) : _nOrd( nOrd ) { /*_pat.resize( 3 ); _pat[ 0 ] = ( Digit )( 1 ); _pat[ 1 ] = ( Digit )( 0 ); _pat[ 2 ] = ( Digit )( 1 );*/ if( _nOrd < 0 ) _nOrd = 0; Pattern( nOrd ); } /* Constructeur par recopie */ Cantor( const Cantor& Ct ) : _nOrd( Ct._nOrd ), _pat( Ct._pat ) { } /* Destructeur */ ~Cantor( void ) { _nOrd = 0; _pat.clear( ); } /* Renvoie le motif ou le calcule à l'ordre passé en paramètre */ Pattern_t& Pattern( Int nOrd = -1 ) { Int i = 0; Int size0 = 0; Pattern_t vct; Pattern_t v_nul; if( nOrd == 0 ) { reset_Pattern( ); } else if( nOrd > 0 ) { reset_Pattern( ); /* L'idée est que l'on reproduit le motif [1 0 1] partout où il y a des 1 en le réintrouisant */ for( i= 1; i<= nOrd; i++ ) { vct = _pat; size0 = vct.size( ); // On crée un vecteur nul de même taille que le motif actuel v_nul.resize( size0, (Digit)(0) ); // On le rajoute à la suite _pat.insert( _pat.end(), v_nul.begin(), v_nul.end() ); // On concatène le tout avec le motif initial _pat.insert( _pat.end(), vct.begin(), vct.end() ); } } else { } return( this->_pat ); } /* Indique si l'élément passé en argument appartient ou non à l'ensemble */ Bool Posseses( Float val ) const { Bool bp = 0; if( val <= 0 || val > 1 ) bp = FALSE; else if( val == 1 ) bp = TRUE; else { Int size_c = this->_pat.size( ); /*Float vlmin = floor( val*size_c ); Float vlmax = ceil( val*size_c ); bp = ( _pat[vlmin] == 1 ) && ( _pat[vlmax] == 1 );*/ bp = ( _pat[ (Int)(val*size_c) ] == 1 ); } return( bp ); } /***************************************************
  • LENGTH: Renvoie la mesure de l'ensemble
  • (aurait pu tout aussi bien s'appeler Measure...)
                                                                                                      • /
Float Length( void ) const { return( pow( 2./3, this->_nOrd+ 1) ); } /***************************************************
  • STAIRS: Méthode de calcul de la fonction escalier de Cantor
  • L'escalier de Cantor est vu comme l'intégrale de l'indicatrice de l'ensemble
  • une interpolation linéaire est réalisée pour atteindre les valeurs intermédiaires
                                                                                                      • /
Float Stairs( Float val ) const { Float y_st = 0; if( val <= 0 || val > 1 ) y_st = 0; else if( val == 1 ) y_st = 1; else { Float SumTot = 0; // intégrale totale de l'Indicatrice de Cantor sur [0;1] Float SumP1 = 0; // somme partielle jusqu'à/tant que x < val Float SumP2 = 0; // somme partielle jusqu'à ce que x > val Int lng_motif = _pat.size( ); // longueur du motif // Digit dig = 0; Float lim_min = floor( lng_motif*val ); Float lim_max = ceil( lng_motif*val ); // Float xv1 = lim_min / lng_motif; Float xv2 = lim_max / lng_motif; Float yv = 0; Int i = 0; Int last = 0; for( i= 0; i< _pat.size(); i++ ) SumTot = SumTot + _pat[ i ]; for( i= 0; i<= lim_min; i++ ) SumP1 = SumP1 + _pat[ i ]; /* protection */ last = ( lim_min + 1 > lng_motif-1 ) ? ( lng_motif - 1 ): ( lim_min + 1 ); SumP2 = SumP1 + _pat[ last ]; yv = ( SumP2 - SumP1 ) / Float( SumTot ); // On interpole le résultat pour les valeurs intermédiaires (graphe de meilleur qualité=> continuité) y_st = ( yv / (xv2 - xv1) )*( val - xv1 ) + (SumP1 / SumTot); } return( y_st ); } /***************************************************
  • RAND: Méthode de génération de nombres aléatoires respectant la distribution de Cantor.
  • Les nombres aléatoires accetables sont ceux dont le développement triadique en (0,1,2)
  • exclut le symbole "1" dans son écriture (plusieurs sources dont Wikipedia)
  • NB!: On aurait aussi pu l'obtenir par une inversion de l'Escalier de Cantor (plus 'calculatoire')
  • - Générer un nombre aléatoire r uniforme entre 0 et 1
  • - Trouver le nombre x de [0;1] tel que Escalier(x) = r <=> Escalier(x) - r = 0,
  • (à l'aide d'une dichotomie par exemple)
                                                                                                      • /
Float Rand( void ) const { double rd = 0.; double cf; int i = 0; /**/ while( i < this->_nOrd ) { cf = int( (double(rand())/RAND_MAX ) * 3 ); if( (cf == 0) || (cf == 2) ) { rd = rd + cf / pow( 3., (i + 1) ); i++; } } /**/ return( rd ); } }; #endif /* _CANTOR_H_ */

Codes Sources

A voir également

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.