| 184 | | == D.1. graph_t * parse_graph(char *filename) == |
| 185 | | |
| 186 | | Cette fonction prend pour argument un nom de fichier au format.dot |
| 187 | | représentant le graphe à partitionner, et construit en mémoire la structure |
| 188 | | graph_t correspondante, et renvoie un pointeur sur cette structure. Si aucune |
| 189 | | partition initiale n'est définie dans le fichier .dot, les noeuds d'index |
| 190 | | inférieur à NBNODE/2 sont arbitrairement rangés dans le sous-ensemble L, |
| 191 | | et les noeuds d'index supérieur à NBNODE/2 sont rangés dans le sous-ensemble R. |
| 192 | | |
| 193 | | Un exemple de fichier au format .dot est donné ci-dessous. Les noeuds du graphe |
| 194 | | sont identifiés par un index, il y a une ligne par arête, les deux sous-graphes |
| 195 | | cluster0 et cluster1 définissent la partition initiale et sont optionnels. |
| | 179 | '''graph_t * parse_graph(char *filename)''':: |
| | 180 | Cette fonction prend pour argument un nom de fichier au format.dot |
| | 181 | représentant le graphe à partitionner, et construit en mémoire la structure |
| | 182 | graph_t correspondante, et renvoie un pointeur sur cette structure. Si aucune |
| | 183 | partition initiale n'est définie dans le fichier .dot, les noeuds d'index |
| | 184 | inférieur à NBNODE/2 sont arbitrairement rangés dans le sous-ensemble L, |
| | 185 | et les noeuds d'index supérieur à NBNODE/2 sont rangés dans le sous-ensemble R. |
| | 186 | |
| | 187 | Un exemple de fichier au format .dot est donné ci-dessous. Les noeuds du graphe |
| | 188 | sont identifiés par un index, il y a une ligne par arête, les deux sous-graphes |
| | 189 | cluster0 et cluster1 définissent la partition initiale et sont optionnels. |
| 213 | | == D.2. void drive_graph(graph_t *p, char *filename) == |
| 214 | | |
| 215 | | Cette fonction prend en paramètre un pointeur p sur une structure graph_t, |
| 216 | | ainsi que le nom du fichier de sortie, et écrit sur disque un fichier au |
| 217 | | format .dot, en conservant dans le fichier les informations de partition |
| 218 | | (sous-ensemble L et R). Ce format est affichable sous forme graphique et |
| 219 | | permet de visualiser la partition. |
| 220 | | |
| 221 | | == D.3. bichain_t * cons_bichain (bichain_t *prev, bichain_t *next, unsigned inode, int igain, unsigned part) == |
| 222 | | |
| 223 | | Cette fonction alloue la mémoire nécessaire pour créer un élément d'une liste |
| 224 | | doublement chaînée, elle initialise les différents champs de cette structure, |
| 225 | | et renvoie un pointeur sur cette structure. |
| 226 | | |
| 227 | | == D.4. void free_bichain (bichain_t *p) == |
| 228 | | |
| 229 | | Cette fonction libère la mémoire allouée lors de la construction de l'objet |
| 230 | | bichain_t par la donction cons_bichain(). |
| 231 | | |
| 232 | | == D.5. move_manager_t * cons_move_manager(graph_t *p) == |
| 233 | | |
| 234 | | Cette fonction pend pour argument un pointeur sur la structure représentant |
| 235 | | le graphe partitionné, et construit en mémoire la structure move_manager_t |
| 236 | | correspondant à cette partition. |
| 237 | | |
| 238 | | == D.6. void add_node (move_manager_t *mm, bichain_t *node) == |
| 239 | | |
| 240 | | Cette fonction prend pour arguments un pointeur sur la structure représentant |
| 241 | | les gestionnaire de mouvements, un pointeur sur un élément de liste doublement |
| 242 | | chaînée (représentant un noeud), contenant l'index du nSud dans le graphe, |
| 243 | | un entier représentant l'index dans le tableau GAIN_R ou GAIN_L, et un entier |
| 244 | | définissant le sous-ensemble d'appartenance (0 pour R, 1 pour L). Elle range |
| 245 | | ce noeud dans la liste doublement chaînée correspondante, elle met à jour |
| 246 | | le tableau NODES et les index LX ou LR. Les champs NEXT et PREV du nSud ne |
| 247 | | sont pas utilisés, ils sont initialisés par la fonction add_node elle-même. |
| 248 | | |
| 249 | | == D.7. bichain_t * del_node(move_manager_t *mm, bichain_t *node) == |
| 250 | | |
| 251 | | cette fonction prend pour arguments un pointeur sur la structure représentant |
| 252 | | les gestionnaire de mouvements, et un pointeur sur un élément de liste |
| 253 | | doublement chaînée (représentant un noeud). Elle retire cet élément de la |
| 254 | | liste doublement chaînée, et renvoie un pointeur sur la structure bichain_t |
| 255 | | pour une éventuelle libération de la mémoire. |
| 256 | | |
| 257 | | == D.8. int compute_gain (graph_t *g, unsigned index) == |
| 258 | | |
| 259 | | Cette fonction prend pour argument un pointeur sur la structure représentant le |
| 260 | | graphe, un index désignant un noeud particulier, et calcule le gain associé |
| 261 | | à ce noeud, pour la partition courante. |
| 262 | | |
| 263 | | == D.9. int global_cost (graph_t *g) == |
| 264 | | |
| 265 | | Cette fonction prend pour argument un pointeur sur la structure représentant |
| 266 | | le graphe, calcule la fonction de coût globale pour la partition courante, |
| 267 | | et renvoie la valeur calculée. |
| | 207 | '''void drive_graph(graph_t *p, char *filename)''':: |
| | 208 | Cette fonction prend en paramètre un pointeur p sur une structure graph_t, |
| | 209 | ainsi que le nom du fichier de sortie, et écrit sur disque un fichier au |
| | 210 | format .dot, en conservant dans le fichier les informations de partition |
| | 211 | (sous-ensemble L et R). Ce format est affichable sous forme graphique et |
| | 212 | permet de visualiser la partition. |
| | 213 | |
| | 214 | '''bichain_t * cons_bichain (bichain_t *prev, bichain_t *next, unsigned inode, int igain, unsigned part)''':: |
| | 215 | Cette fonction alloue la mémoire nécessaire pour créer un élément d'une liste |
| | 216 | doublement chaînée, elle initialise les différents champs de cette structure, |
| | 217 | et renvoie un pointeur sur cette structure. |
| | 218 | |
| | 219 | '''void free_bichain (bichain_t *p)''':: |
| | 220 | Cette fonction libère la mémoire allouée lors de la construction de l'objet |
| | 221 | bichain_t par la donction cons_bichain(). |
| | 222 | |
| | 223 | '''move_manager_t * cons_move_manager(graph_t *p)''':: |
| | 224 | Cette fonction pend pour argument un pointeur sur la structure représentant |
| | 225 | le graphe partitionné, et construit en mémoire la structure move_manager_t |
| | 226 | correspondant à cette partition. |
| | 227 | |
| | 228 | '''void add_node (move_manager_t *mm, bichain_t *node)''':: |
| | 229 | Cette fonction prend pour arguments un pointeur sur la structure représentant |
| | 230 | les gestionnaire de mouvements, un pointeur sur un élément de liste doublement |
| | 231 | chaînée (représentant un noeud), contenant l'index du nSud dans le graphe, |
| | 232 | un entier représentant l'index dans le tableau GAIN_R ou GAIN_L, et un entier |
| | 233 | définissant le sous-ensemble d'appartenance (0 pour R, 1 pour L). Elle range |
| | 234 | ce noeud dans la liste doublement chaînée correspondante, elle met à jour |
| | 235 | le tableau NODES et les index LX ou LR. Les champs NEXT et PREV du nSud ne |
| | 236 | sont pas utilisés, ils sont initialisés par la fonction add_node elle-même. |
| | 237 | |
| | 238 | '''bichain_t * del_node(move_manager_t *mm, bichain_t *node)''':: |
| | 239 | cette fonction prend pour arguments un pointeur sur la structure représentant |
| | 240 | les gestionnaire de mouvements, et un pointeur sur un élément de liste |
| | 241 | doublement chaînée (représentant un noeud). Elle retire cet élément de la |
| | 242 | liste doublement chaînée, et renvoie un pointeur sur la structure bichain_t |
| | 243 | pour une éventuelle libération de la mémoire. |
| | 244 | |
| | 245 | '''int compute_gain (graph_t *g, unsigned index)''':: |
| | 246 | Cette fonction prend pour argument un pointeur sur la structure représentant le |
| | 247 | graphe, un index désignant un noeud particulier, et calcule le gain associé |
| | 248 | à ce noeud, pour la partition courante. |
| | 249 | |
| | 250 | '''int global_cost (graph_t *g)''':: |
| | 251 | Cette fonction prend pour argument un pointeur sur la structure représentant |
| | 252 | le graphe, calcule la fonction de coût globale pour la partition courante, |
| | 253 | et renvoie la valeur calculée. |
| 274 | | == E.1. Construction et initialisation du gestionnaire de mouvements == |
| 275 | | |
| 276 | | C'est un point important puisque que c'est la structure de base de |
| 277 | | l'algorithme. Vous disposez pour vous aidez d'une fonction dump_move_manager() |
| 278 | | qui affiche le contenu de la structure. |
| 279 | | |
| 280 | | == E.2. Ecriture de l'algorithme MinCut glouton == |
| 281 | | |
| 282 | | Ecrivez la boucle réalisant les transferts de cellules tant que le transfert |
| 283 | | d'une paire de cellules améliore la fonction de coût FC. |
| 284 | | |
| 285 | | == E.3. Exécution et évaluation == |
| 286 | | |
| 287 | | Exécutez cet algorithme sur différents graphes que vous définirez |
| 288 | | vous-mêmes. La partition résultante est-elle toujours la partition |
| 289 | | optimale? Pourquoi? Donnez un contre-exemple. |
| 290 | | |
| 291 | | == E.4. Ecriture des fonctions == |
| 292 | | |
| 293 | | Ecrire les différentes fonctions d'accès aux structures de données définies |
| 294 | | dans la partie D, et validez ces fonctions en les intégrant peu à peu dans |
| 295 | | votre programme. |
| 296 | | |
| 297 | | == E.5. construction du graphe en mémoire == |
| 298 | | |
| 299 | | L'objectif est ici d'écrire la fonction parse_graph(), en utilisant lex et |
| 300 | | yacc. Nous vous suggérons de supposer qu'il n'y a pas de clusters dans le |
| 301 | | fichier, puis de les introduire. Si vous n'avez pas le temps de construire |
| 302 | | le graphe, étudiez au moins la grammaire de ce petit langage. |
| | 260 | '''1. Construction et initialisation du gestionnaire de mouvements''':: |
| | 261 | C'est un point important puisque que c'est la structure de base de |
| | 262 | l'algorithme. Vous disposez pour vous aidez d'une fonction dump_move_manager() |
| | 263 | qui affiche le contenu de la structure. |
| | 264 | |
| | 265 | '''2. Ecriture de l'algorithme !MinCut glouton''':: |
| | 266 | Ecrivez la boucle réalisant les transferts de cellules tant que le transfert |
| | 267 | d'une paire de cellules améliore la fonction de coût FC. |
| | 268 | |
| | 269 | '''3. Exécution et évaluation''':: |
| | 270 | Exécutez cet algorithme sur différents graphes que vous définirez |
| | 271 | vous-mêmes. La partition résultante est-elle toujours la partition |
| | 272 | optimale? Pourquoi? Donnez un contre-exemple. |
| | 273 | |
| | 274 | '''4. Ecriture des fonctions''':: |
| | 275 | Ecrire les différentes fonctions d'accès aux structures de données définies |
| | 276 | dans la partie D, et validez ces fonctions en les intégrant peu à peu dans |
| | 277 | votre programme. |
| | 278 | |
| | 279 | '''5. construction du graphe en mémoire''':: |
| | 280 | L'objectif est ici d'écrire la fonction parse_graph(), en utilisant lex et |
| | 281 | yacc. Nous vous suggérons de supposer qu'il n'y a pas de clusters dans le |
| | 282 | fichier, puis de les introduire. Si vous n'avez pas le temps de construire |
| | 283 | le graphe, étudiez au moins la grammaire de ce petit langage. |