460 likes | 593 Views
Cours d’Algorithmique. Dérécursion (fin) : Équivalences entre programmes récursifs et programmes itératifs avec ou sans gestion de pile. Algorithmes gloutons. Les grandes lignes du cours. Trier et chercher, recherche textuelle Listes et arbres Le back-track Arbres équilibrés
E N D
Cours d’Algorithmique Dérécursion (fin) : Équivalences entre programmes récursifs et programmes itératifs avec ou sans gestion de pile. Algorithmes gloutons. Cours d'algorithmique 8 - Intranet
Les grandes lignes du cours • Trier et chercher, recherche textuelle • Listes et arbres • Le back-track • Arbres équilibrés • Récursivité et induction sur la structure • Divide and conquer, algorithmes gloutons • Minimax, alpha-beta • Dérécursion • Divers problèmes particuliers • Logique de Hoare • Programmation dynamique • Complexité et calculabilité Cours d'algorithmique 8 - Intranet
Plan-----------------------------------------------------------------Plan----------------------------------------------------------------- Nombre d’appels récursifs Appréciations ! Un Deux Fonction auto-enveloppée Transformation intéressante ! Celle-là aussi ! Sans espoir ! ! ! Non Oui Enveloppe associative Oui Non Avec élément neutre Oui Non Cours d'algorithmique 8 - Intranet
Deux appels récursifs auto-enveloppés----------------------------------------------------------------- • Le cas de base est celui des appels auto-enveloppés ! Nous explorons x à l’aide d’un accumulateur acc. Le cas d’arrêt. f ( acc , x ) = si ( P( acc , x ) ) a( acc , x ) sinon f(f( t( acc , x ) , a( acc , x ) ), b( acc , x ) ) L’appel récursif interne ! L’appel récursif externe ! Cours d'algorithmique 8 - Intranet
Deux appels récursifs auto-enveloppés----------------------------------------------------------------- Le flot des informations ! f ( acc , x ) = si ( P( x ) ) a( acc , x ) sinon f(f( acc , a( x ) ), b( x ) ) acc x L’accumulateur récolte les contributions locales au fur et à mesure du parcours ! a( x ) b( x ) Cours d'algorithmique 8 - Intranet
Deux appels récursifs auto-enveloppés----------------------------------------------------------------- • Introduisons la fonction F suivante : F( acc , p ) = si ( V( p ) ) acc sinon x <- S( p ) p <- D( p ) F( f( acc , x ) , p ) Nous enlevons la valeur du sommet de la pile. La pile contient les éléments qui sont à traiter. Nous la traitons. Et nous recommençons. Cours d'algorithmique 8 - Intranet
Deux appels récursifs auto-enveloppés----------------------------------------------------------------- • Nous avons : F( acc , E( v , I( ) ) ) = si ( V( E( v , I( ) ) ) ) acc sinon x <- S( E( v , I( ) ) ) v p <- D( E( v , I( ) ) ) I( ) F( f( acc , x ) , p ) = F( f( acc , v ) , I( ) ) = si ( V( I( ) ) ) f( acc , v ) sinon . . . = f( acc , v ) Plutôt que d’appeler « f( acc , v ) » nous pouvons appeler F avec « acc » et une pile qui contient le seul élément « v » qui est à traiter. Cours d'algorithmique 8 - Intranet
Deux appels récursifs auto-enveloppés----------------------------------------------------------------- • Nous avons plus généralement : F( acc , E( v , p ) ) = si ( V( E( v , p ) ) ) acc sinon x <- S( E( v , p ) ) v p <- D( E( v , p ) ) p F( f( acc , x ) , p ) = F( f( acc , v ) , p ) F( acc , E( v , p ) ) = F( f( acc , v ) , p ) Empiler Dépiler Cours d'algorithmique 8 - Intranet
Deux appels récursifs auto-enveloppés----------------------------------------------------------------- • Exprimons F à l’aide d ’elle-même et de manière terminale. Nous aurons une itération avec gestion de la pile. F( acc , p ) = si ( V( p ) ) acc sinon x <- S( p ) p <- D( p ) si ( P ) F( a , p ) sinon F( t , E( a , E( b , p ) ) ) F est récursive terminale ! Cours d'algorithmique 8 - Intranet
Deux appels récursifs auto-enveloppés----------------------------------------------------------------- • Pour un appel res <- f( init , v ) nous obtenons le code : Initialisation de acc et p ! acc <- init p <- E( v , I( ) ) while ( ù V( p ) ) x <- S( p ) p <- D( p ) si ( P( acc , x ) ) acc <- a( acc , x ) sinon p <- E( b( acc , x ) , p ) p <- E( a( acc , x ) , p ) acc <- t( acc , x ) res <- acc Le prochain élément est prélevé sur la pile ! S’il est élémentaire, nous l’accumulons ! Sinon, nous empilons les deux fils et nous recommençons ! Le résultat final est dans acc ! Cours d'algorithmique 8 - Intranet
Sous forme d’arbre----------------------------------------------------------------- Dans l’accumulateur : acc = ( ( 0 + k ) + l ) Dans la pile ! X Y arbre <- S( p ) p <- D( p ) k Z Premier cas : feuille( arbre ) est vrai et valeur( arbre ) = m l Y arbre = T Z X m acc = ( ( ( 0 + k ) + l ) + m ) Cours d'algorithmique 8 - Intranet
Sous forme d’arbre----------------------------------------------------------------- Dans l’accumulateur : acc = ( ( 0 + k ) + l ) Dans la pile ! X U Y arbre <- S( p ) p <- D( p ) V k Z Second cas : feuille( arbre ) est faux et fg( arbre ) = U et fd( arbre ) = V l Y Z X U V Cours d'algorithmique 8 - Intranet
Deux appels récursifs, enveloppe associative----------------------------------------------------------------- • Soient deux appels récursifs avec une enveloppe associative ! • La forme générale est la suivante : • Le flot des informations est le suivant : f ( x ) = si ( P( x ) ) a( x ) sinon h( f( a( x ) ) , f( b( x ) ) ) h x Cours d'algorithmique 8 - Intranet
Deux appels récursifs, enveloppe associative----------------------------------------------------------------- • Nous nous ramenons au cas auto-enveloppé en posant : g( acc , x ) = h( acc , f( x ) ) • Alors : g( acc , x ) = h( acc , si ( P( x ) ) a( x ) sinon h( f( a( x ) ) , f( b( x ) ) ) ) = si ( P( x ) ) h( acc , a( x ) ) sinon h( acc , h( f( a( x ) ) , f( b( x ) ) ) ) h( h( acc , f( a( x ) ) ) , f( b( x ) ) ) h( g( acc , a( x ) ) , f( b( x ) ) ) g( g( acc , a( x ) ) , b( x ) ) Associativité de h! Définition de g ! Définition de g ! Cours d'algorithmique 8 - Intranet
Deux appels récursifs, enveloppe associative----------------------------------------------------------------- • Nous nous ramenons au cas auto-enveloppé en posant : g( acc , x ) = h( acc , f( x ) ) • Alors : g( acc , x ) = si ( P( x ) ) h( acc , a( x ) ) sinon g( g( acc , a( x ) ) , b( x ) ) • Le flot des informations a changé : Nous sommes donc revenus au cas d’une fonction auto-enveloppée ! et donc ... h acc x x Cours d'algorithmique 8 - Intranet
Deux appels récursifs, enveloppe associative----------------------------------------------------------------- • Pour deux appels avec une enveloppe « h » associative avec neutre « e », nous avons : acc <- e p <- E( v , I( ) ) while ( ù V( p ) ) x <- S( p ) p <- D( p ) si ( P( x ) ) acc <- h( acc , a( x ) ) sinon p <- E( b( x ) , p ) p <- E( a( x ) , p ) res <- acc res <- f( v ) f ( x ) = si ( P( x ) ) a( x ) sinon h( f( a( x ) ) , f( b( x ) ) ) Cours d'algorithmique 8 - Intranet
Deux appels récursifs, enveloppe associative----------------------------------------------------------------- x <- v p <- I( ) while ( ù ( P( x ) ) p <- E( b( x ) , p ) x <- a( x ) acc <- a( x ) while ( ù V( p ) ) x <- S( p ) p <- D( p ) si ( P( x ) ) acc <- h( acc , a( x ) ) sinon p <- E( b( x ) , p ) p <- E( a( x ) , p ) res <- acc • Si « h » est sans neutre, c’est plus embêtant. • Le code : L’initialisation est triviale ! La descente à gauche vers la première feuille . Nous empilons les fils droits. Finalement, nous pouvons Initialiser l’accumulateur ! Le reste ne change pas ! ! ! Cours d'algorithmique 8 - Intranet
Deux appels récursifs, enveloppe non associative----------------------------------------------------------------- • C’est le cas le plus compliqué à gérer ! • Comme l’enveloppe n’est pas associative, nous devons respecter la structure de l’arbre : Résultats en attente ! X T X On mélange tout ! Traitements en attente ! Z Y Y Z X ????? T X Noeud courant La pile ! Cours d'algorithmique 8 - Intranet
Deux appels récursifs, enveloppe non associative----------------------------------------------------------------- • Nous avons quatre variables globales : • la variable « x » qui indique l’élément à traiter, • la variable « res » qui indique le résultat courant, • la variable « marq » qui est la valeur du dernier marqueur, • la variable « p » qui est la pile courante. • Nous distinguons deux types de traitements : • cas 1 – la variable « x » ne vérifie pas le test d’arrêt, • cas 2 – la variable « x » vérifie le test d’arrêt. Cours d'algorithmique 8 - Intranet
Deux appels récursifs, enveloppe non associative----------------------------------------------------------------- • Fusion des cas 1 & 2 - la variable « x » doit être traitée : CALCUL : si ( P( x ) ) res <- a( x ) goto PILE sinon p <- E( b( x ) , p ) p <- E( C , p ) x <- a( x ) goto CALCUL Une sortie ! Une boucle ! Cours d'algorithmique 8 - Intranet
Deux appels récursifs, enveloppe non associative----------------------------------------------------------------- • Dès qu’il y a un résultat « res », nous inspectons la pile : • Trois cas se présentent pour la pile : • cas 3 – elle est vide, • cas 4 – elle a un marqueur « C » au sommet et • cas 5 – elle a un marqueur « R » au sommet. Cours d'algorithmique 8 - Intranet
Deux appels récursifs, enveloppe non associative----------------------------------------------------------------- PILE: si ( V( p ) ) goto FIN sinon marq <- S( p ) p <- D( p ) si ( marq = C ) x <- S( p ) p <- D( p ) p <- E( res , p ) p <- E( R , p ) goto CALCUL sinon res <- h( S( p ) , res ) p <- D( p ) goto PILE • Fusion des cas 3, 4 & 5 : Une sortie ! Nous consultons le marqueur ! Nous allons traiter le second fils et sauvons le résultat du premier ! Une sortie ! Nous combinons deux résultats ! Une boucle ! Cours d'algorithmique 8 - Intranet
Deux appels récursifs, enveloppe non associative----------------------------------------------------------------- DEBUT : x <- v p <- I( ) goto CALCUL PILE: si ( V( p ) ) goto FIN sinon marq <- S( p ) p <- D( p ) si ( marq = C ) x <- S( p ) p <- D( p ) p <- E( res , p ) p <- E( R , p ) goto CALCUL sinon res <- h( S( p ) , res ) p <- D( p ) goto PILE CALCUL : si ( P( x ) ) res <- a( x ) goto PILE sinon p <- E( b( x ) , p ) p <- E( C , p ) x <- a( x ) goto CALCUL FIN : ... Cours d'algorithmique 8 - Intranet
Avec des while à la place des goto ! Deux appels récursifs, enveloppe non associative----------------------------------------------------------------- DEBUT : x <- v p <- I( ) FIN <- faux CALCUL <- vrai PILE <- faux while ( ù FIN ) while_CALCUL while_PILE while_PILE: while ( PILE ) si ( V( p ) ) PILE <- faux FIN <- vrai sinon marq <- S( p ) p <- D( p ) si ( marq = C ) x <- S( p ) p <- D( p ) p <- E( res , p ) p <- E( R , p ) PILE <- faux CALCUL <- vrai sinon res <- h( S( p ) , res ) p <- D( p ) while_CALCUL : while ( CALCUL ) si ( P( x ) ) res <- a( x ) CALCUL <- faux PILE <- vrai sinon p <- E( b( x ) , p ) p <- E( C , p ) x <- a( x ) Cours d'algorithmique 8 - Intranet
Deux appels récursifs --- résumé----------------------------------------------------------------- • 5) Deux appels récursifs auto-enveloppés ! acc <- init p <- E( v , I( ) ) while ( ù V( p ) ) x <- S( p ) p <- D( p ) si ( P( acc , x ) ) acc <- a( acc , x ) sinon p <- E( b( acc , x ) , p ) p <- E( a( acc , x ) , p ) acc <- t( acc , x ) res <- acc f ( acc , x ) = si ( P( acc , x ) ) a( acc , x ) sinon f( f( t( acc , x ) , a( acc , x ) ) , b( acc , x ) ) Code itératif peu raisonnable ! Cours d'algorithmique 8 - Intranet
Deux appels récursifs --- résumé----------------------------------------------------------------- • 6) Appels avec enveloppe associative et neutre « e » ! acc <- e p <- E( v , I( ) ) while ( ù V( p ) ) x <- S( p ) p <- D( p ) si ( P( x ) ) acc <- h( acc , a( x ) ) sinon p <- E( b( x ) , p ) p <- E( a( x ) , p ) res <- acc f ( x ) = si ( P( x ) ) a( x ) sinon h( f( a( x ) ) , f( b( x ) ) ) Code itératif peu raisonnable ! Cours d'algorithmique 8 - Intranet
Deux appels récursifs --- résumé----------------------------------------------------------------- x <- v p <- I( ) while ( ù ( P( x ) ) p <- E( b( x ) , p ) x <- a( x ) acc <- a( x ) while ( ù V( p ) ) x <- S( p ) p <- D( p ) si ( P( x ) ) acc <- h( acc , a( x ) ) sinon p <- E( b( x ) , p ) p <- E( a( x ) , p ) res <- acc • 7) Appels avec enveloppe associative, sans neutre ! f ( x ) = si ( P( x ) ) a( x ) sinon h( f( a( x ) ) , f( b( x ) ) ) Code itératif très peu raisonnable ! Cours d'algorithmique 8 - Intranet
Deux appels récursifs --- résumé----------------------------------------------------------------- while_PILE: while ( PILE ) si ( V( p ) ) PILE <- faux FIN <- vrai sinon marq <- S( p ) p <- D( p ) si ( marq = C ) x <- S( p ) p <- D( p ) p <- E( res , p ) p <- E( R , p ) PILE <- faux CALCUL <- vrai sinon res <- h( S( p ) , res ) p <- D( p ) • 8) Appels avec enveloppe non associative ! f ( x ) = si ( P( x ) ) a( x ) sinon h( f( a( x ) ) , f( b( x ) ) ) Code itératif déraisonnable ! while_CALCUL : while ( CALCUL ) si ( P( x ) ) res <- a( x ) CALCUL <- faux PILE <- vrai sinon p <- E( b( x ) , p ) p <- E( C , p ) x <- a( x ) DEBUT : x <- v p <- I( ) FIN <- faux CALCUL <- vrai PILE <- faux while ( ù FIN ) while_CALCUL while_PILE Cours d'algorithmique 8 - Intranet
Résumé général----------------------------------------------------------------- • Les quatre cas à unique appel récursif : • Récursif terminal. • Enveloppe associative avec neutre. • Enveloppe associative sans neutre. • Enveloppe non associative. • Les quatre cas à deux appels récursifs : • Récursif auto-enveloppé. • Enveloppe associative avec neutre. • Enveloppe associative sans neutre. • Enveloppe non associative. Récursif ! Itératif ! Se ramène à … Cours d'algorithmique 8 - Intranet
Algorithmes gloutons----------------------------------------------------------------- • Greedy algorithms en anglais ! • Une suite de décisions optimales locales conduit à un optimum global ! • Complexité pour « n » éléments : • O( n * x )où O( x ) est la complexité de la décision locale ! • O( 2 ) pour le back-track (cascade de décisions locales) ! n Cours d'algorithmique 8 - Intranet
Algorithmes gloutons----------------------------------------------------------------- • Exemple d’un choix glouton : • GLOBAL :Choisir les 10 plus petits de l’amphi ! • LOCAL :Trouver et retirer le plus petit ! • Ce choix est indépendant des autres personnes déjà choisies ou restant à choisir. • Exemple d’un choix non glouton : • GLOBAL :Choisir le plus court chemin de Marseille à Paris ! • LOCAL :Trouver à partir de la ville courante, l’étape la plus courte ! • Un tel choix n’est pas sûr de nous rapprocher de Paris ! Cours d'algorithmique 8 - Intranet
Action Selection Problem----------------------------------------------------------------- • Un exemple complet : • Ensemble « E » de tâches, dont le « début » et la « fin » sont connues ! • t et t sont compatibles si leurs intersections sont vides ! • OBJECTIF : Trouvez le plus grand ensemble de tâches compatibles ! ! ! i j i 1 2 3 4 d 5 3 1 2 f 7 9 4 5 i 1 2 3 4 d 1 2 5 3 f 4 5 7 9 i i i i Triées par f croissants ! i Cours d'algorithmique 8 - Intranet
Action Selection Problem----------------------------------------------------------------- Les tâches déjà choisies. Les tâches non encore considérées. ens BT ( ens choisies , ens restantes ) = si ( restantes = {} ) choisies sinon choix <- choisir( restantes ) restantes <- restantes \ { choix } sans_choix = BT( choisies , restantes ) si ( compatible( choix , choisies ) ) max_ens( BT( choisies v { choix } , restantes ) , sans_choix ) sinon sans_choix Assez naturel ! Nous choisissons ! Le choix est retenu s’il est compatible . . . Nous avons toujours la possibilité de ne pas retenir la tâche choisie ! Cours d'algorithmique 8 - Intranet
Action Selection Problem----------------------------------------------------------------- • Considérons : E( i , j ) = { te E | f <=d <= f<= d } • Initialisation : • soit t avec f = 0 , • soit t avec d = +inf , • alors E = E( 0 , n+1 ) . k i k k j f d d f i j k k 0 0 n+1 n+1 Cours d'algorithmique 8 - Intranet
Action Selection Problem----------------------------------------------------------------- E( i , j ) t e E( i , j ) • Décomposition : { } si E( i , j ) = { } • S( i , j ) = max_ens { { t } v S( i , k ) v S( k , j ) } sinon k f d d f { { i j k k E( i , k ) E( k , j ) C’est la tâche t et les solutions optimales pour E( i , k ) et E( k , j ). k { On maximise sur tous les choix pour t . k t e E( i , j ) k k Cours d'algorithmique 8 - Intranet
. . . . . . Action Selection Problem----------------------------------------------------------------- Tâches triées par f croissants, donc i < k < j ! • Graphiquement, pour i < j : x S( i , j ) S( k , j ) j Second axe de temps S( i , k ) i Premier axe de temps j i Cours d'algorithmique 8 - Intranet
Action Selection Problem----------------------------------------------------------------- • L’approche gloutonne dit : • Ce n’est pas la peine de parcourir toutes les tâches de E( i , j ) ! • S( i , j ) = max_ens { { t } v S( i , k ) v S( k , j ) } • Considérez la tâche t avec f minimal sur E( i , j ) ! Alors : • S( i , j ) = max_ens { { t } v S( i , k ) v S( k , j ) } = { t } v S( i , l ) v S( l , j ) = { t } v S( l , j ) k t e E( i , j ) k l l k t e E( i , j ) k l l Cours d'algorithmique 8 - Intranet
Action Selection Problem----------------------------------------------------------------- • Trois approches de solution : • Back-track ! Complexité : O ( 2^n ) • Programmation dynamique ! Complexité : O ( n^2 ) • Algorithme glouton ! Complexité : O ( n ) • L’algorithme glouton est souvent obtenu comme optimisation d’une programmation dynamique ! Cours d'algorithmique 8 - Intranet
Task Scheduling with Penalties----------------------------------------------------------------- • Définition : • « n » tâches de temps unitaires ! • Chaque tâche « t » comporte une deadline « d » et une pénalité « p », due si la deadline est dépassée. • Objectif : Trouver un ordonnancement qui minimise la somme des pénalités ! i i i Cours d'algorithmique 8 - Intranet
Task Scheduling with Penalties----------------------------------------------------------------- • Solution : • Pourquoi est-ce correct ? • Soit une suite optimale de tâches : ( t , . . . , t , t , . . . , t ) Trier les tâches par deadlines croissantes. Parcourir les tâches et retenir celles qui peuvent être exécutées dans les temps. Compléter par les autres ! i+1 n 1 i Cours d'algorithmique 8 - Intranet
Task Scheduling with Penalties----------------------------------------------------------------- • Correction : • Soit une suite optimale de tâches : ( t , . . . , t , t , . . . , t ) avec t en retard et t à l’heure. • On peut échanger t et t sans changer la pénalité : • t plus tôt, OK, et t plus tard, OK. • Donc, il existe une solution optimale telle que : ( t’ , . . . , t’ , t’ , . . . , t’ ) à l’heure en retard i+1 n 1 i i i+1 i i+1 i i+1 n 1 k k+1 Cours d'algorithmique 8 - Intranet
Task Scheduling with Penalties----------------------------------------------------------------- • Correction : • Dans une suite optimale, si t et t sont à l’heure et que d > d , on peut les échanger sans modifier les pénalités. • Sans pénalité : f <= d et f <= d . • Par ailleurs : f < f <= d < d . • Donc : f < d et f < d . • Donc, il existe une solution optimale telle que : ( t’ , . . . , t’ , t’ , . . . , t’ ) à l’heure et d croissants en retard CQFD. i i+1 i i+1 i i i+1 i+1 i i+1 i+1 i i+1 i i i+1 n 1 k k+1 i Cours d'algorithmique 8 - Intranet