Changes between Initial Version and Version 1 of 2011CaoTme6


Ignore:
Timestamp:
Mar 31, 2011, 5:22:04 PM (14 years ago)
Author:
jpc
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • 2011CaoTme6

    v1 v1  
     1[[PageOutline]]
     2
     3
     4= Représentation d'une Structure Booléenne Multi-niveaux (EBM) =
     5
     6Les fichiers nécessaires à la réalisation de ce TME sont disponibles
     7directement sur le réseau enseignement, dans le répertoire:
     8{{{~jpc/M1-CAO/TME/3.public}}}
     9
     10
     11== Les différentes classes ==
     12
     13Pour pouvoir implanter en mémoire une {{{EBM}}} il est nécessaire de
     14disposer de trois classes:
     15
     16 * Une classe de base {{{Ebm}}}
     17 * Une classe {{{EbmExpr}}} pour représenter les expressions (dérivant d'{{{Ebm}}}).
     18 * Une classe {{{EbmVar}}} pour reprséenter les variables (dérivant d'{{{Ebm}}}).
     19
     20Les squelettes de ces classes sont fournis dans les fichiers {{{Ebm.h}}},
     21{{{EbmExpr.h}}} et {{{EbmVar.h}}}
     22
     23
     24=== La classe {{{Ebm}}} ===
     25
     26{{{
     27class Ebm {
     28  public:
     29            unsigned int       litterals ();
     30            std::set<EbmVar*>  support   ();
     31            void               support   ( std::ostream& );
     32            void               display   ( std::ostream& );
     33            ValueType          eval      ();
     34    static  Ebm*               parse     ( std::string expression );
     35};
     36}}}
     37
     38__Principales méthodes de la classe {{{Ebm}}}:__
     39 * {{{litterals()}}} : retourne le nombre de littéraux de l'{{{EBM}}}. C'est à dire le nombre
     40   de fois que des variables apparaissent dans l'expression.
     41 * {{{support()}}} : retourne le support de l'{{{EBM}}} sous forme d'ensemble ({{{set<>}}})
     42   Le support est l'ensemble des variables nécessaire pour calculer la
     43   valeur de l'expression.
     44 * {{{support(std::ostream&)}}} : Affiche le support dans un flux, voir l'exemple d'éxécution
     45   du programme de test fourni plus bas.
     46 * {{{display(std::ostream&)}}} : Affiche l'{{{EBM}}} sous sa forme humainement lisible, en
     47   notation ''préfixée''.
     48 * {{{eval()}}} : Calcule la valeur de l'expression booléenne. Le type de retour est un
     49   {{{ValueType}}}, c'est à dire une variable pouvant prendre trois valeurs:
     50   {{{Low}}}, {{{High}}} et {{{Unknown}}} (cf. {{{CaoTypes.h}}}).
     51 * {{{parse()}}} : Une fonction statique transformant une chaîne de caractères en une
     52   {{{EBM}}}.
     53
     54
     55=== La classe {{{EbmVar}}} ===
     56
     57{{{
     58class EbmVar: public Ebm {
     59  private:
     60    static unsigned int                    _maxIndex;
     61    static std::map<std::string ,EbmVar*>  _byName;   // All variables storage.
     62    static std::map<unsigned int,EbmVar*>  _byIndex;
     63  private :   
     64             std::string   _name;       // Variable name.
     65             ValueType     _value;      // Logical value.
     66             unsigned int  _index;      // Unique index (for ROBDD)
     67  public:
     68                           EbmVar   ( std::string name, ValueType value=Low );
     69    virtual               ~EbmVar   ();
     70  public:
     71    inline   std::string   getName  ();
     72    inline   ValueType     getValue ();
     73    inline   unsigned int  getIndex ();
     74    inline   void          setValue ( ValueType value );
     75  // Operations sur le dictionnaire
     76    static   EbmVar*       get      ( unsigned int index );
     77    static   EbmVar*       get      ( std::string name );
     78};
     79}}}
     80
     81
     82__Attributs de la classe {{{EbmVar}}}:__
     83 * {{{_name}}}  : Le nom de la variable (par ex. {{{"a"}}})
     84 * {{{_value}}} : La valeur actuellement affectée à la variable
     85   ({{{Low}}}, {{{High}}} ou {{{Unknown}}}).
     86 * {{{_index}}} : Un index permettant d'identifier de façon unique la
     87   variable. Cet index trouvera sont utilité dans le TME suivant, présentant les {{{ROBDD}}}.
     88
     89
     90__Attributs ''statiques'' de la classe {{{EbmVar}}}:__
     91 * {{{_maxIndex}}} : Le compteur utilisé pour générer des index uniques
     92   (mécanisme identique à celui utilisé pour les vecteurs lors du TME1).
     93 * {{{_byName}}} : Une table associative permettant de retrouver ''n'importe
     94   quelle'' variable sachant son nom.
     95 * {{{_byIndex}}} : Une table associative permettant de retrouver ''n'importe
     96   quelle'' variable sachant son index.
     97
     98__Principales méthodes de la classe {{{EbmVar}}}:__
     99 * {{{getName()}}}  : accesseur retournant le nom.
     100 * {{{getIndex()}}} : accesseur retournant l'index.
     101 * {{{getValue()}}} : accesseur retournant la valeur.
     102 * {{{setValue()}}} : modificateur de la valeur.
     103 * {{{get()}}} : deux surcharge différentes pour retrouver une variable
     104   par son nom ou par son index.
     105
     106
     107=== La classe {{{EbmExpr}}} ===
     108
     109{{{
     110class EbmExpr : public Ebm {
     111  private:
     112             OperatorType     _operator;  // operateur de ce noeud
     113             std::list<Ebm*>  _operands;  // pointeurs sur les operandes
     114  public:
     115                              EbmExpr     ( OperatorType, std::list<Ebm*>& operands );
     116    virtual                  ~EbmExpr     ();
     117    static   EbmExpr*         Not         ( Ebm* );
     118    static   EbmExpr*         Or          ( Ebm*, Ebm* );
     119    static   EbmExpr*         Or          ( Ebm*, Ebm*, Ebm* );
     120    static   EbmExpr*         Or          ( Ebm*, Ebm*, Ebm*, Ebm* );
     121    static   EbmExpr*         Xor         ( Ebm*, Ebm* );
     122    static   EbmExpr*         Xor         ( Ebm*, Ebm*, Ebm* );
     123    static   EbmExpr*         Xor         ( Ebm*, Ebm*, Ebm*, Ebm* );
     124    static   EbmExpr*         And         ( Ebm*, Ebm* );
     125    static   EbmExpr*         And         ( Ebm*, Ebm*, Ebm* );
     126    static   EbmExpr*         And         ( Ebm*, Ebm*, Ebm*, Ebm* );
     127  public:
     128    inline   OperatorType     getOperator ();
     129    inline   std::list<Ebm*>& getOperands ();
     130};
     131}}}
     132
     133
     134__Attributs de la classe {{{EbmExpr}}}:__
     135 * {{{_operator}}} : le type de l'opérateur (dans {{{CaoTypes.h}}}, parmis
     136   {{{Not}}}, {{{And}}}, {{{Or}}} ou {{{Xor}}}).
     137 * {{{_operands}}} : une liste de pointeurs vers les opérandes.
     138
     139
     140__Principales méthodes de la classe {{{EbmVar}}}:__
     141 * {{{getOperator()}}} : accesseur, retourne le type de l'opérateur.
     142 * {{{getOperands()}}} : accesseur, retourne une référence sur la liste
     143   des opérandes (pour éviter une copie inutile de la liste).
     144 * {{{Or()}}} : trois surcharges construisant une expression {{{Or}}} entre ses
     145   {{{N}}} opérandes. Le but de ces différentes fonctions est de cacher la construction
     146   de la liste des opérandes et l'allocation de l'{{{EbmExpr}}} résultante.
     147   Noter que cela implique une construction ''bottom-up'' de l'{{{EBM}}} complète.
     148   Voir l'exemple fourni.
     149 * {{{And()}}} et {{{Xor()}}} : idem.
     150
     151
     152== Présentation des méthodes récursives ==
     153
     154
     155Les méthodes {{{litterals()}}}, {{{support()}}}, {{{display()}}} et {{{parse()}}} de la
     156classe {{{Ebm}}} sont récursives. On définit le niveau de profondeur de l'arbre d'une
     157{{{EBM}}} comme le nombre d'arcs {{{N}}} nécessaire pour atteindre la racine. Dans
     158l'{{{EBM}}} {{{e4}}}, la racine {{{e4}}} à une profondeur nulle, {{{e1}}} une profondeur
     159de 1 et {{{a}}} une profondeur de 2.
     160
     161'''Récursion'''
     162
     163Considérons l'exemple de la fonction {{{litterals()}}}. Dire qu'elle est récursive
     164signifie que son calcul au niveau de profondeur {{{N}}} peut se décomposer en
     165calculs ''de cette même fonction'' appliquée sur le niveau {{{N+1}}}.
     166Par exemple, le calcul de {{{litterals()}}} de {{{e4}}} peut s'exprimer comme
     167la somme des fonctions {{{litterals()}}} ''appliquée à ses opérandes''
     168({{{e0}}}, {{{e1}}}, {{{e2}}} et {{{e3}}}) :
     169
     170'''Condition d'arrêt'''
     171
     172On comprend bien, que l'on ne va pas rappeler indéfiniment {{{litterals()}}},
     173à une profondeur donnée, il faudra bien d'arrêter. Le critère d'arrêt est simple:
     174lorsque l'on atteind une {{{EbmVar}}}, le noeud n'a pas d'opérandes, et son
     175nombre de littéraux vaut 1.
     176
     177En conclusion, la fonction récursive aura la structure générale suivante:
     178
     179{{{
     180LITTERALS(e)
     181  IF e IS_A variable:
     182    RETURN 1
     183  ELSE
     184    sum = 0
     185    FOR EACH operand OF e:
     186      sum += LITTERALS(operand)
     187    RETURN sum
     188}}}
     189
     190[[Image(Ebm-1.png,align=center)]]
     191
     192La figure suivante représente l'ordre dans lequel les noeud de l'arbre de l'{{{EBM}}}
     193sont parcourus lors d'une récursion.
     194
     195[[Image(Ebm-2.png,align=center)]]
     196
     197État de la pile d'appel des fonctions a un instant donné du parcours récursif.
     198Le chemin actullement parcouru est {{{(e4,e1,a)}}}
     199
     200[[Image(Ebm-3.png,align=center)]]
     201
     202La pile d'appel des fonctions membres à un instant donné.
     203
     204''Attention'' : il est très important de bien distinguer le code la fonction,
     205qui est écrit une fois (dans {{{Ebm}}}) et l' ''objet'' auquel elle s'applique.
     206Nous avons ainsi la même fonction membre {{display()}} mais sur trois objets
     207différents : {{{e4}}}, {{{e1}}} et {{{a}}}.
     208
     209[[Image(Ebm-4.png,align=center)]]
     210
     211
     212== Fonctionnement de la fonction {{{getType()}}} ==
     213
     214
     215Dans la présentation de la récursion, nous avons vu qu'il était nécessaire,
     216pour choisir entre la récursion et l'arrêt, de savoir distinguer une variable
     217({{{EbmVar}}}) d'une expression ({{{EbmExpr}}}).
     218
     219Pour cela nous allons implanter la fonction {{{getType()}}}.
     220
     221La fonction {{{getType()}}} a les caractéristiques suivantes:
     222 * Elle est déclarée virtuelle pure dans la classe {{{Ebm}}}, c'est à dire
     223   qu'elle '''doit''' être sur-définie dans les classes dérivées '''et'''
     224   qu'elle n'a aucune implémentation au niveau de la classe {{{Ebm}}}.
     225 * Dans la classe {{{EbmVar}}} elle retourne '''Variable'''.
     226 * Dans la classe {{{EbmExpr}}} elle retourne '''Expression'''.
     227
     228De cette façon, lorsqu'elle est appelée dans les fonctions récursives définies
     229dans {{{Ebm}}}, elle retournera la valeur associée au ''type dynamique'' de
     230l'{{{Ebm}}} en cours de traitement. C'est à dire {{{EbmVar}}} ou {{{EbmExpr}}}.
     231
     232[[Image(Ebm-5.png,align=center)]]