Différences
Ci-dessous, les différences entre deux révisions de la page.
Les deux révisions précédentes Révision précédente Prochaine révision | Révision précédente | ||
tc_info:2020_td-tp_flo [2020/08/08 17:46] – pprea | tc_info:2020_td-tp_flo [2020/10/01 14:03] (Version actuelle) – pprea | ||
---|---|---|---|
Ligne 1: | Ligne 1: | ||
+ | ===== TD-TP sur les Flots ===== | ||
+ | ~~NOTOC~~ | ||
+ | |||
+ | |||
+ | Ce " | ||
+ | |||
+ | Il n'est pas nécessaire de faire tout le TD avant d' | ||
+ | |||
+ | < | ||
+ | On considère un graphe orienté G=(V,A)G=(V,A) tel qu'à chaque arc (arête orientée) uu soit associé un nombre positif cucu, la **capacité** de uu. | ||
+ | Un **flot (réalisable)** est une suite Φ=(ϕu,u∈A)Φ=(ϕu,u∈A) telle que : | ||
+ | * ΦΦ est compatible avec les capacités : ∀u∈A,0≤ϕu≤cu∀u∈A,0≤ϕu≤cu | ||
+ | * ΦΦ respecte la loi de Kirchoff (ou loi des nœuds) : ∀v∈V,∑u∈Γ+(v)ϕu=∑u∈Γ−(v)ϕu∀v∈V,∑u∈Γ+(v)ϕu=∑u∈Γ−(v)ϕu \\ Γ+(v)Γ+(v) est l' | ||
+ | |||
+ | Étant donnés deux sommets s & p (la **source** & le **puit**), le problème du **flot maximum** est de faire passer le plus grand flot de s à p. | ||
+ | |||
+ | Pour se faire une idée un peu plus concrète que ce qu'est un flot, on peut imaginer chaque arc comme un tuyau à sens unique (en fait, cette restriction n'est pas nécessaire — cf Exercice 3) ayant un débit maximum (sa capacité), le problème étant de faire passer le plus de liquide possible de la //source// au //puit//. | ||
+ | |||
+ | L' | ||
+ | |||
+ | </ | ||
+ | |||
+ | ==== Partie TD ==== | ||
+ | |||
+ | L' | ||
+ | |||
+ | === 1. Un algorithme de flot === | ||
+ | |||
+ | Tout d' | ||
+ | [[tc_info: | ||
+ | |||
+ | < | ||
+ | Étant donné un flot Φ sur un graphe G=(V,A), on considère le **graphe d' | ||
+ | |||
+ | Les capacités des arcs u+ & u− sont appelées **capacités résiduelles**, | ||
+ | Remarquer que diminuer le flux sur l'arc u=(x,y) d'une quantité q revient à ajouter un flux de valeur q dans le sens (y,x). | ||
+ | |||
+ | En fait, dans le graphe d' | ||
+ | </ | ||
+ | |||
+ | À quoi correspond un chemin de de s à p dans GΦ ? [[tc_info: | ||
+ | |||
+ | En déduire un algorithme de flux maximum. [[tc_info: | ||
+ | |||
+ | |||
+ | === 2. Mariages === | ||
+ | |||
+ | Une agence matrimoniale a, comme clients, n hommes & p femmes. Parmi les n×p couples homme-femme((Il est tout à fait possible de considérer d' | ||
+ | |||
+ | On modélisera ce problème par un flot maximum dans un graphe que l'on déterminera. [[tc_info: | ||
+ | |||
+ | |||
+ | === 3. Graphes non orientés === | ||
+ | |||
+ | Montrez que l' | ||
+ | [[tc_info: | ||
+ | |||
+ | |||
+ | === 4. La bataille de la Marne === | ||
+ | |||
+ | On a un ensemble S de villes & des routes reliant certaines villes entre elles (il peut exister plusieurs routes entre deux villes). Chaque ville i est caractérisée par un nombre pi de places de parking, & chaque route j par une longueur lj (le temps pour aller d'une extrémité à l' | ||
+ | |||
+ | Au temps t=0, un certain de nombre de véhicules sont stationnés dans différentes villes ; il faut qu'au temps t=K, le plus possible de véhicules soient arrivés à une ville donnée (la Marne). Il est possible que des véhicules arrivent avant cette date butoir, mais après la date K, c'est trop tard. | ||
+ | |||
+ | On modélisera ce problème par un flot maximum dans un graphe que l'on déterminera. | ||
+ | [[tc_info: | ||
+ | |||
+ | |||
+ | === 5. Des extensions === | ||
+ | |||
+ | < | ||
+ | On peut supposer que chaque arc u a une capacité minimum cu & une capacité maximum cu (on doit avoir cu≤ϕu≤cu). Le problème est alors de trouver un flux **compatible** (qui n' | ||
+ | |||
+ | On peut aussi supposer que chaque arc prélève un " | ||
+ | </ | ||
+ | |||
+ | Montrez que la problème du plus court chemin (entre deux sommets x) & y dans un graphe valué peut se modéliser par un problème de flux compatible à coût minimum dans un graphe que l'on déterminera. [[tc_info: | ||
+ | |||
+ | === 6. Un théorème === | ||
+ | |||
+ | Si toutes les capacités sont des entiers, que peut-on dire des flots maximums? [[tc_info: | ||
+ | |||
+ | |||
+ | ==== Partie TP ==== | ||
+ | |||
+ | |||
+ | On va maintenant implémenter (presque tout) ce qui a été vu dans la partie TD. | ||
+ | |||
+ | |||
+ | <note important> | ||
+ | Le fait de tester toutes vos créations n'est plus explicitement demandé car cela doit **encore & toujours** être fait. | ||
+ | </ | ||
+ | |||
+ | === 1. Implémentation des graphes === | ||
+ | |||
+ | < | ||
+ | Les graphes seront représentés " | ||
+ | |||
+ | <code python> | ||
+ | |||
+ | CAPACITE = " | ||
+ | FLUX = " | ||
+ | |||
+ | the_graph = {1: {2: {CAPACITE: 5, FLUX: 2}, 3: | ||
+ | 2: {3: {CAPACITE: 7, FLUX: 1}, 4: {CAPACITE: 8, FLUX: 1}}, | ||
+ | 3: {5: {CAPACITE: 4, FLUX: 2}}, | ||
+ | 4: {6: {CAPACITE: 3, FLUX: 2}}, | ||
+ | 5: {4: {CAPACITE: 6, FLUX: 1}, 6: {CAPACITE: 8, FLUX: 1}}, | ||
+ | 6: {} | ||
+ | } | ||
+ | </ | ||
+ | </ | ||
+ | |||
+ | Dessinez le graphe ci-dessus. | ||
+ | [[tc_info: | ||
+ | |||
+ | |||
+ | === 2. L' | ||
+ | |||
+ | Implémentez l' | ||
+ | : | ||
+ | |||
+ | <code python> | ||
+ | import math | ||
+ | |||
+ | INFINI = math.inf | ||
+ | CAPACITE = " | ||
+ | FLUX = " | ||
+ | |||
+ | |||
+ | def mise_a_zero_flot(graph): | ||
+ | for sommet in graph: | ||
+ | for voisin in graph[sommet]: | ||
+ | graph[sommet][voisin][FLUX] = 0 | ||
+ | |||
+ | |||
+ | def construction_graphe_ecart(graphe_antisymetrique): | ||
+ | graphe_ecart = {} | ||
+ | for sommet in graphe_antisymetrique: | ||
+ | graphe_ecart[sommet] = {} | ||
+ | for sommet in graphe_antisymetrique: | ||
+ | for voisin in graphe_antisymetrique[sommet]: | ||
+ | capacite = graphe_antisymetrique[sommet][voisin][CAPACITE] | ||
+ | flux = graphe_antisymetrique[sommet][voisin][FLUX] | ||
+ | if capacite > flux: | ||
+ | graphe_ecart[sommet][voisin] = capacite - flux | ||
+ | if flux > 0: | ||
+ | graphe_ecart[voisin][sommet] = flux | ||
+ | return graphe_ecart | ||
+ | |||
+ | |||
+ | def construction_chemin_via_dfs(graphe_ecart, | ||
+ | sommets_marques = {} | ||
+ | antecedents = {} | ||
+ | pile = [source] | ||
+ | for sommet in graphe_ecart: | ||
+ | antecedents[sommet] = None | ||
+ | while pile != []: | ||
+ | sommet = pile.pop() | ||
+ | if sommet not in sommets_marques: | ||
+ | sommets_marques[sommet] = True | ||
+ | for voisin in graphe_ecart[sommet]: | ||
+ | if voisin not in sommets_marques: | ||
+ | antecedents[voisin] = sommet | ||
+ | pile.append(voisin) | ||
+ | if sommet == puits: | ||
+ | return construction_effective_chemin(sommet, | ||
+ | |||
+ | |||
+ | def construction_effective_chemin(sommet, | ||
+ | chemin = [] | ||
+ | while sommet is not None: | ||
+ | chemin.append(sommet) | ||
+ | sommet = antecedents[sommet] | ||
+ | chemin.reverse() | ||
+ | return | ||
+ | |||
+ | |||
+ | def min_sur_chemin(chemin, | ||
+ | minimum = INFINI | ||
+ | for i in range(len(chemin) - 1): | ||
+ | courant = chemin[i] | ||
+ | suivant = chemin[i + 1] | ||
+ | if graphe_ecart[courant][suivant] < minimum: | ||
+ | minimum = graphe_ecart[courant][suivant] | ||
+ | return minimum | ||
+ | |||
+ | |||
+ | def ajout_flot(valeur, | ||
+ | for i in range(len(chemin) - 1): | ||
+ | courant = chemin[i] | ||
+ | suivant = chemin[i + 1] | ||
+ | if suivant in graphe_antisymetrique[courant]: | ||
+ | graphe_antisymetrique[courant][suivant][FLUX] += valeur | ||
+ | else: | ||
+ | graphe_antisymetrique[suivant][courant][FLUX] -= valeur | ||
+ | |||
+ | </ | ||
+ | |||
+ | |||
+ | === 3. Le problème du mariage === | ||
+ | |||
+ | Résoudre le problème du mariage avec les données suivantes : | ||
+ | <code python> | ||
+ | CLEOPATRE = " | ||
+ | IPHIGENIE = " | ||
+ | JULIETTE = " | ||
+ | FANNY = " | ||
+ | CHIMENE = " | ||
+ | |||
+ | ACHILLE = " | ||
+ | CESAR = " | ||
+ | RODRIGUE = " | ||
+ | ROMEO = " | ||
+ | MARIUS = " | ||
+ | |||
+ | LES_COUPLES = [(CLEOPATRE, | ||
+ | | ||
+ | | ||
+ | </ | ||
+ | |||
+ | <note important> | ||
+ | La difficulté (puisque l' | ||
+ | </ | ||
+ | |||
+ | === 4. La bataille de la Marne === | ||
+ | |||
+ | Résoudre le problème de "la bataille de la Marne", | ||
+ | * Au temps 0, on a autant de taxis que nécessaire dans la ville 14 (" | ||
+ | * Au temps 50, il faut qu'il y en ait le plus possible dans la ville 0 ("La Marne" | ||
+ | * Chaque ville (intermédiaire) a 10 places de parking (Paris en a autant que nécessaire). | ||
+ | * Les routes sont données dans le tableau suivant : | ||
+ | |||
+ | |||
+ | <code python> | ||
+ | LES_ROUTES = [{' | ||
+ | {' | ||
+ | {' | ||
+ | {' | ||
+ | {' | ||
+ | {' | ||
+ | {' | ||
+ | {' | ||
+ | {' | ||
+ | {' | ||
+ | {' | ||
+ | {' | ||
+ | {' | ||
+ | {' | ||
+ | {' | ||
+ | {' | ||
+ | {' | ||
+ | {' | ||
+ | {' | ||
+ | {' | ||
+ | {' | ||
+ | {' | ||
+ | {' | ||
+ | {' | ||
+ | {' | ||
+ | {' | ||
+ | {' | ||
+ | {' | ||
+ | {' | ||
+ | {' | ||
+ | {' | ||
+ | {' | ||
+ | {' | ||
+ | {' | ||
+ | {' | ||
+ | {' | ||
+ | {' | ||
+ | {' | ||
+ | {' | ||
+ | {' | ||
+ | {' | ||
+ | {' | ||
+ | </ | ||
+ | |||
+ | <note important> | ||
+ | Les routes sont à double sens (il ne faut pas se fier aux appellations " | ||
+ | </ | ||
+ | |||
+ | <note important> | ||
+ | La difficulté est, là encore, la construction du graphe. | ||
+ | </ | ||
+ | |||
+ | |||
+ | On pourra commencer par une instance plus petite, par exemple en ne considérant que les villes jusqu' | ||
+ | |||
+ | <code python> | ||
+ | LES_ROUTES = [{' | ||
+ | {' | ||
+ | {' | ||
+ | {' | ||
+ | {' | ||
+ | {' | ||
+ | {' | ||
+ | {' | ||
+ | {' | ||
+ | {' | ||
+ | {' | ||
+ | {' | ||
+ | {' | ||
+ | {' | ||
+ | {' | ||
+ | {' | ||
+ | {' | ||
+ | {' | ||
+ | {' | ||
+ | {' | ||
+ | {' | ||
+ | {' | ||
+ | {' | ||
+ | {' | ||
+ | {' | ||
+ | {' | ||
+ | </ | ||
+ | |||
+ | voire même plus petit. |