7. Planification

7. Planification

Voici quelques exemples et une résolution (rectifiée…) proposés par ChatGPT pour illustrer un exemple classique : la planification des tâches avec un algorithme glouton ainsi qu’une recherche exhaustive.

pdf - Script accompagnant ces exemples

Un exemple classique de choix d’activité à planifier qui peut être résolu par un algorithme glouton est le problème de sélection d’activités.

Supposons qu’il y ait un ensemble d’activités à planifier, chacune ayant une heure de début et une heure de fin.

L’objectif est de sélectionner les activités ayant une durée totale maximale sans qu’elles ne se chevauchent.

Exemple introductif et résolution gloutonne #

Voici un exemple de jeu de données d’activités :

Activité Heure de début Heure de fin
A 9h00 10h00
B 9h30 11h30
C 10h00 11h00
D 11h00 12h00

Pour résoudre ce problème par un algorithme glouton, nous pouvons trier les activités par heure de fin croissante. Ensuite, nous sélectionnons la première activité de la liste, qui a l’heure de fin la plus basse. Nous ajoutons ensuite toutes les activités suivantes qui ont une heure de début supérieure à l’heure de fin de l’activité sélectionnée précédemment. Nous répétons ce processus jusqu’à ce qu’il n’y ait plus d’activités restantes.

Voici les étapes de l’algorithme glouton :

Trier les activités par heure de fin croissante.

Activité Heure de début Heure de fin
A 9h00 10h00
C 10h00 11h00
B 9h30 11h30
D 11h00 12h00

Sélectionner la première activité, A.

Activité sélectionnée Heure de début Heure de fin
A 9h00 10h00

Ajouter toutes les activités suivantes qui ont une heure de début supérieure à l’heure de fin de A. Dans ce cas, la prochaine activité qui respecte cette condition est C.

Activités sélectionnées Heure de début Heure de fin
A 9h00 10h00
C 10h00 11h00

Continuer à ajouter des activités jusqu’à ce qu’il n’y en ait plus de compatibles. Dans ce cas, l’activité suivante compatible est D.

Activités sélectionnées Heure de début Heure de fin
A 9h00 10h00
C 10h00 11h00
D 11h00 12h00

Ainsi, l’algorithme glouton a sélectionné trois activités : A, C et D, qui ne se chevauchent pas. L’activité B a été écartée car elle se chevauche avec C.

Autre exemple avec 10 activités #

Voici un exemple de jeu de données d’activités plus grand, avec 10 activités :

Activité Heure de début Heure de fin
A 9h00 10h30
B 9h00 10h00
C 10h00 11h00
D 10h00 12h00
E 11h00 12h30
F 12h30 13h00
G 12h00 14h00
H 13h00 14h00
I 13h30 15h00
J 14h00 15h00

En triant les activités par heure de fin croissante, nous obtenons :

Activité Heure de début Heure de fin
B 9h00 10h00
A 9h00 10h30
C 10h00 11h00
D 10h00 12h00
E 11h00 12h30
F 12h30 13h00
H 13h00 14h00
G 12h00 14h00
I 13h30 15h00
J 14h00 15h00

En appliquant l’algorithme glouton, nous obtenons la solution suivante :

Activités sélectionnées Heure de début Heure de fin
B 9h00 10h00
C 10h00 11h00
E 11h00 12h30
F 12h30 13h00
H 13h00 14h00
J 14h00 15h00

L’algorithme glouton ne fournit pas toujours la solution optimale, mais il permet souvent d’obtenir une solution acceptable en un temps raisonnable. Cependant, si l’objectif est d’obtenir la solution optimale, il est nécessaire de recourir à un algorithme de recherche exhaustive qui va énumérer toutes les combinaisons possibles d’activités et sélectionner celle qui est compatible et qui a la durée maximale. Cela peut être très coûteux en termes de temps de calcul si le nombre d’activités est important.

Exemple où l’algorithme glouton ne fournit pas une solution optimale #

Ici il est notable de remarquer que ChatGPT n’a jamais été en mesure de fournir un contre exemple valide. J’ai dû lui proposer cet exemple simpliste après une dizaine de rectifications infructueuses. Il s’entétait à proposer des tâches qui se chevauchent. Je l’ai questionné sans réponse sur la source de ces erreurs.

Voici un petit exemple où l’algorithme glouton ne fournit pas la solution optimale :

Activité Heure de début Heure de fin
A 9h00 10h30
B 9h30 14h00
C 10h30 13h00

En triant les activités par heure de fin croissante, nous obtenons :

Activité Heure de début Heure de fin
A 9h00 10h30
C 10h30 13h00
B 9h30 14h00

En appliquant l’algorithme glouton, nous obtenons la solution suivante :

Activités sélectionnées Heure de début Heure de fin
A 9h00 10h30
C 10h30 13h00

La durée totale des activités sélectionnées est de 3 heures.

Cependant, la solution optimale consiste à sélectionner l’activité B dont la durée est de 4h30…

Résolution python #

Voici une proposition d’implémentation d’une solution gloutonne en Python pour la planification de tâches, en utilisant des tuples de la forme (“A”, 9.5, 10.5) ou (“B”, 10.5, 11.5) pour représenter les tâches :

def planification_taches(taches):
    # Tri des tâches par ordre croissant de fin de la tâche
    taches_triees = sorted(taches, key=lambda x: x[2])

    # Création de la liste de tâches planifiées
    taches_planifiees = []

    # Définition de la fin de la dernière tâche planifiée
    fin_derniere_tache = 0

    # Parcours des tâches triées par ordre croissant de fin de la tâche
    for tache in taches_triees:
        # Si la tâche peut être planifiée avant la fin de la dernière tâche planifiée
        if tache[1] >= fin_derniere_tache:
            taches_planifiees.append(tache)
            fin_derniere_tache = tache[2]

    return taches_planifiees

Explication du code : #

La fonction planification_taches prend en entrée une liste de tâches représentées par des tuples de la forme ("A", 9.5, 10.5) ou ("B", 10.5, 11.5). La première étape consiste à trier les tâches par ordre croissant de fin de la tâche, en utilisant la fonction sorted avec une fonction lambda qui extrait le troisième élément de chaque tuple (c’est-à-dire la fin de la tâche). Ensuite, la liste de tâches planifiées est initialisée avec la première tâche triée. La variable fin_derniere_tache est initialisée avec la fin de la première tâche planifiée. Ensuite, chaque tâche triée est parcourue, et si elle peut être planifiée avant la fin de la dernière tâche planifiée, elle est ajoutée à la liste de tâches planifiées et la variable fin_derniere_tache est mise à jour avec la fin de cette tâche.

Finalement, la liste de tâches planifiées est renvoyée. Cette solution gloutonne consiste à toujours choisir la tâche qui se termine le plus tôt parmi celles qui peuvent être planifiées. Cela ne garantit pas une planification optimale, mais peut fournir une solution raisonnablement efficace pour des instances de petite à moyenne taille.

Recherche exhaustive d’une solution optimale #

Solution proposée par ChatGPT et légèrement rectifiée.

def planification_taches_exhaustif(taches: list[tuple]):
    """
    Recherche exhaustive d'une solution optimale
    """
    # Générer toutes les permutations possibles de la liste de tâches
    permutations = itertools.permutations(taches)

    # Initialiser les variables de la meilleure solution trouvée
    meilleur_planification = None
    meilleur_duree_totale = -float("inf")

    # Parcourir chaque permutation possible
    for permutation in permutations:
        # Vérifier si la permutation est valide (pas de chevauchement de tâches)
        duree_totale = 0
        fin_derniere_tache = 0
        valide = True
        for tache in permutation:
            if tache[1] < fin_derniere_tache:
                valide = False
                break
            duree_totale += tache[2] - tache[1]
            fin_derniere_tache = tache[1]

        # Si la permutation est valide et donne une durée totale plus courte
        # que la meilleure solution actuelle
        if valide and duree_totale > meilleur_duree_totale:
            meilleur_planification = permutation
            meilleur_duree_totale = duree_totale

    return meilleur_planification

Remarques concernant ChatGPT #

Il m’a fallu 2h de conversation pour générer ce code et ces exemples. ChatGPT m’a permis d’éviter de taper 150 lignes d’exemples pénibles (les tableaux plus haut). La recherche gloutonne est presque celle que j’ai pu écrire par le passé. La recherche exhaustive est très classique, c’est sensiblement celle qu’on écrit pour tout problème de ce type. Par très intéressant pour moi - qui connais - beaucoup plus pour un novice éclairé. ChatGPT peut s’entêter dans des erreurs surprenantes (exemples faux…) et n’est pas toujours clair.

Il a, par exemple, présenté le problème en voulant maximiser le nombre de tâches sélectionnées, par leur durée totale. Mais ensuite, dans ses exemples et son code, c’est la durée qu’il optimise… Étrange !