Partage
  • Partager sur Facebook
  • Partager sur Twitter

Planning d'une compagnie aérienne (fictif)

    3 juin 2024 à 18:00:53

    Bonjour à tous,

    Je commence sur Python et j'ai voulu me trouver un projet pour apprendre (y a rien de tel à mon sens).

    Je joue à un jeu (Airline Manager), le principe est simple, c'est un jeu de gestion de compagnie aérienne.

    J'ai donc, plusieurs avions, plusieurs lignes (j’exclue pour le moment le fait d'avoir plusieurs aéroport)

    Chaque avion possède :

    - Une catégorie (et ne peux donc pas être assigné à une ligne donc la catégorie serait inférieur à celle de l'avion)

    - Une distance maximum (et ne peux donc pas être assigné à une ligne dont la distance serait supérieur)

    - Une capacité de siège (éco, affaire, 1er)

    Chaque ligne possède :

    - Une distance

    - Une demande  par classe

    - Un prix de place par classe

    J'ai donc voulu tester mes connaissance en python pour essayer de trouver le meilleur couple / avion > ligne dégageant le meilleur CA. Il semble que j'ai réussi cette étape. 

    Cependant les choses se corse car imaginons qu'un avion décolle à 00h le lundi vers une ligne, il fait forcément l'aller / retour et reviens à l'aéroport le jour même a 13h, il a donc encore la possibilité de faire un vol aller retour vers cette ligne et arrivera le mardi à 2h. Nous pouvons donc considéré deux trajets aller/retour pour le lundi.

    Mon code actuel permet donc d'obtenir (s'il n'y a pas d'erreur) la meilleur combinaison pour le lundi mais je n'arrive pas à intégrer un planning pour obtenir le meilleur planning à la semaine car avec l'exemple précédent quand nous arriverons au dimanche nous ne pourrons pas faire deux aller / retour car dans le jeu le planning commence le lundi à 00h et termine le dimanche à 23h59 (les quarts d'heure sont arrondi au supérieur donc 00h). Donc peut être que la meilleur combinaison avion / ligne pour le dimanche sera une autre ligne qui elle permet de ce placer dans le créneau disponible.

    En gros ce qui me pose problème c'est le facteur temps par quart d'heure que je n'arrive pas à intégrer.

    Sans me donner forcément la solution, auriez-vous des pistes de réflexion sur comment je dois décomposer mon problème ?

    J'ai tenter de créer un objet planning pour y affecter les avions avec les quarts d'heure disponible mais j'avoue que je sèche ...

    Voici mon code actuel :

    import pandas as pd
    from math import ceil
    
    class Avion:
        def __init__(self, cle, categorie, nom, distance_max, vitesse, nb_places_economique, nb_places_affaire, nb_places_premiere):
            self.cle = cle
            self.categorie = categorie
            self.nom = nom
            self.distance_max = distance_max
            self.vitesse = vitesse
            self.nb_places_economique = nb_places_economique
            self.nb_places_affaire = nb_places_affaire
            self.nb_places_premiere = nb_places_premiere
    
        def __repr__(self):
            return f"Avion(cle={self.cle}, categorie={self.categorie}, nom={self.nom}, distance_max={self.distance_max}, vitesse={self.vitesse}, nb_places_economique={self.nb_places_economique}, nb_places_affaire={self.nb_places_affaire}, nb_places_premiere={self.nb_places_premiere})"
    
        def lignes_compatibles(self, lignes):
            compatibles = []
            for ligne in lignes:
                if ligne.categorie >= self.categorie and ligne.distance <= self.distance_max:
                    compatibles.append(ligne)
            return compatibles
    
    class Ligne:
        def __init__(self, cle, categorie, nom, distance, demande_classe_economique, demande_classe_affaire, demande_classe_premiere, prix_classe_economique, prix_classe_affaire, prix_classe_premiere):
            self.cle = cle
            self.categorie = categorie
            self.nom = nom
            self.distance = distance
            self.demande_classe_economique = demande_classe_economique
            self.demande_classe_affaire = demande_classe_affaire
            self.demande_classe_premiere = demande_classe_premiere
            self.prix_classe_economique = prix_classe_economique
            self.prix_classe_affaire = prix_classe_affaire
            self.prix_classe_premiere = prix_classe_premiere
    
        def __repr__(self):
            return f"Ligne(cle={self.cle}, categorie={self.categorie}, nom={self.nom}, distance={self.distance}, demande_classe_economique={self.demande_classe_economique}, demande_classe_affaire={self.demande_classe_affaire}, demande_classe_premiere={self.demande_classe_premiere}, prix_classe_economique={self.prix_classe_economique}, prix_classe_affaire={self.prix_classe_affaire}, prix_classe_premiere={self.prix_classe_affaire})"
    
    class Planning:
        def __init__(self):
            self.schedule = [[None for _ in range(96)] for _ in range(7)]  # 7 days * 96 quarter-hours
    
        def __repr__(self):
            return f"Planning(schedule={self.schedule})"
    
    # Lire les fichiers Excel et créer les objets
    avions_df = pd.read_excel('avions.xlsx')
    lignes_df = pd.read_excel('lignes.xlsx')
    
    # Créer les objets Avion
    avions = []
    for _, row in avions_df.iterrows():
        avion = Avion(row['clé'], row['catégorie'], row['nom'], row['distance_max'], row['vitesse'], row['nb_places_economique'], row['nb_places_affaire'], row['nb_places_premiere'])
        avions.append(avion)
    
    # Créer les objets Ligne
    lignes = []
    for _, row in lignes_df.iterrows():
        ligne = Ligne(row['clé'], row['catégorie'], row['nom'], row['distance'], row['demande_classe_economique'], row['demande_classe_affaire'], row['demande_classe_premiere'], row['prix_classe_economique'], row['prix_classe_affaire'], row['prix_classe_affaire'])
        lignes.append(ligne)
    
    # Calculer le nombre d'aller-retour possible pour chaque avion sur chaque ligne compatible
    def calculer_nombre_aller_retour(avion, ligne):
        temps_aller = ligne.distance / avion.vitesse
        temps_aller_arrondi = ceil(temps_aller * 4) / 4  # Arrondir le temps aller au quart d'heure supérieur
        temps_aller_retour = temps_aller_arrondi * 2
        nombre_trajets_aller_retour = ceil(24 / temps_aller_retour)  # Arrondir le résultat à l'entier supérieur
        return nombre_trajets_aller_retour
    
    # Calculer le chiffre d'affaires potentiel pour chaque avion sur chaque ligne compatible
    def calculer_CA(avion, ligne, nombre_aller_retour):
        capacite_economique = nombre_aller_retour * 2 * avion.nb_places_economique
        capacite_affaire = nombre_aller_retour * 2 * avion.nb_places_affaire
        capacite_premiere = nombre_aller_retour * 2 * avion.nb_places_premiere
    
        demande_economique = min(capacite_economique, ligne.demande_classe_economique)
        demande_affaire = min(capacite_affaire, ligne.demande_classe_affaire)
        demande_premiere = min(capacite_premiere, ligne.demande_classe_premiere)
    
        CA_economique = demande_economique * ligne.prix_classe_economique
        CA_affaire = demande_affaire * ligne.prix_classe_affaire
        CA_premiere = demande_premiere * ligne.prix_classe_premiere
    
        CA_total = CA_economique + CA_affaire + CA_premiere
    
        return CA_economique, CA_affaire, CA_premiere, CA_total, demande_economique, demande_affaire, demande_premiere
    
    # Affecter les avions au planning en maximisant le CA
    planning = Planning()
    resultats = []
    
    # Nouvelle fonction pour obtenir la demande restante pour une classe donnée d'une ligne donnée
    def get_demande_restante(ligne, classe):
        if classe == 'economique':
            return max(0, ligne.demande_classe_economique)
        elif classe == 'affaire':
            return max(0, ligne.demande_classe_affaire)
        elif classe == 'premiere':
            return max(0, ligne.demande_classe_premiere)
        else:
            return 0
    
    while avions:
        meilleur_CA = 0
        meilleur_avion = None
        meilleure_ligne = None
        meilleure_CA = None
        meilleur_nombre_aller_retour = 0  # Ajout d'une variable pour stocker le meilleur nombre d'aller-retour
    
        for avion in avions:
            lignes_compatibles = avion.lignes_compatibles(lignes)
            if not lignes_compatibles:
                continue  # Passer à l'avion suivant s'il n'y a pas de lignes compatibles
    
            for ligne in lignes_compatibles:
                nombre_aller_retour = calculer_nombre_aller_retour(avion, ligne)
                CA_economique, CA_affaire, CA_premiere, CA_total, demande_economique, demande_affaire, demande_premiere = calculer_CA(avion, ligne, nombre_aller_retour)
                if CA_total > meilleur_CA:
                    meilleur_CA = CA_total
                    meilleur_avion = avion
                    meilleure_ligne = ligne
                    meilleure_CA = (CA_economique, CA_affaire, CA_premiere, CA_total, demande_economique, demande_affaire, demande_premiere)
                    meilleur_nombre_aller_retour = nombre_aller_retour  # Mettre à jour le meilleur nombre d'aller-retour
    
        if meilleur_avion and meilleure_ligne:
            # Mettre à jour les demandes restantes sur la ligne
            demande_restante_economique = max(0, meilleure_ligne.demande_classe_economique - meilleure_CA[4])
            demande_restante_affaire = max(0, meilleure_ligne.demande_classe_affaire - meilleure_CA[5])
            demande_restante_premiere = max(0, meilleure_ligne.demande_classe_premiere - meilleure_CA[6])
    
            # Enregistrer les résultats avec les demandes restantes mises à jour
            resultats.append((meilleur_avion.cle, meilleure_ligne.nom, *meilleure_CA[:4], demande_restante_economique, demande_restante_affaire, demande_restante_premiere, meilleur_nombre_aller_retour))
    
            # Mettre à jour les demandes restantes sur la ligne
            meilleure_ligne.demande_classe_economique = demande_restante_economique
            meilleure_ligne.demande_classe_affaire = demande_restante_affaire
            meilleure_ligne.demande_classe_premiere = demande_restante_premiere
    
            # Supprimer l'avion de la liste des avions restants à affecter
            avions.remove(meilleur_avion)
    
            print(f"Avion {meilleur_avion.cle} affecté sur la ligne {meilleure_ligne.nom}. Nombre d'avions restant à affecter: {len(avions)}")
        else:
            # Si aucun avion n'a été affecté lors de cette itération, arrêter la boucle
            break
    
    # Afficher les résultats
    resultats_df = pd.DataFrame(resultats, columns=['Avion', 'Ligne', 'CA Economique', 'CA Affaire', 'CA Premiere', 'CA Total', 'Demande Restante Economique', 'Demande Restante Affaire', 'Demande Restante Premiere', 'Nombre Aller-Retour'])
    print(resultats_df)
    
    # Exporter les résultats vers un fichier Excel
    resultats_df.to_excel(r'chemin export', index=False)
    
    



    -
    Edité par CorentinJoubert1 3 juin 2024 à 18:02:59

    • Partager sur Facebook
    • Partager sur Twitter

    Planning d'une compagnie aérienne (fictif)

    × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
    • Editeur
    • Markdown