# -*- coding: utf-8 -*- """optimisation_examen_PMNE.ipynb Automatically generated by Colab. Original file is located at https://colab.research.google.com/drive/1Uewn7e8zZiGZdAAYHqXJtl-3TA7sj5eL """ #!pip install pulp #!pip install gradio import gradio as gr import pandas as pd from pulp import LpMinimize, LpProblem, LpVariable, lpSum def planifier_examens(examens_text, salles_text, jours_text, creneaux_text, disponibilite_salle_text, conflits_text): # --- 1. Parsing des données --- # Examens examens = [] for line in examens_text.strip().splitlines(): parts = line.split(',') if len(parts) == 3: exam_id, nb_students, duration = parts examens.append((exam_id.strip(), int(nb_students.strip()), int(duration.strip()))) # Salles et capacités salles = {} for line in salles_text.strip().splitlines(): parts = line.split(',') if len(parts) == 2: room_id, capacity = parts salles[room_id.strip()] = int(capacity.strip()) # Jours et créneaux jours = [int(j.strip()) for j in jours_text.split(',')] creneaux = [int(c.strip()) for c in creneaux_text.split(',')] # Disponibilité des salles disponibilite_salle = {} for line in disponibilite_salle_text.strip().splitlines(): parts = line.split(',') room_id = parts[0].strip() disponibilite_salle[room_id] = [int(s) for s in parts[1:]] # Conflits entre examens conflits = [] for line in conflits_text.strip().splitlines(): parts = line.split(',') conflits.append((parts[0].strip(), parts[1].strip())) # --- 2. Modélisation avec PuLP (PMNE) --- model = LpProblem("Planification_Examens", LpMinimize) # Variables de décision X = {(e, d, c, s): LpVariable(f"X_{e}_{d}_{c}_{s}", cat="Binary") for e, _, _ in examens for d in jours for c in creneaux for s in salles} Y = {d: LpVariable(f"Y_{d}", cat="Binary") for d in jours} # Contrainte 1 : Chaque examen doit être programmé une seule fois for e, _, _ in examens: model += lpSum(X[e, d, c, s] for d in jours for c in creneaux for s in salles) == 1 # Contrainte 2 : Capacité des salles respectée for d in jours: for c in creneaux: for s in salles: model += lpSum(nb_students * X[e, d, c, s] for e, nb_students, _ in examens) <= salles[s] # Contrainte 3 : Une salle ne peut accueillir qu’un seul examen par créneau for d in jours: for c in creneaux: for s in salles: model += lpSum(X[e, d, c, s] for e, _, _ in examens) <= 1 # Contrainte 4 : Disponibilité des salles for e, _, _ in examens: for d in jours: for c in creneaux: for s in salles: if disponibilite_salle[s][c - 1] == 0: model += X[e, d, c, s] == 0 # Contrainte 5 : Conflits entre examens (ne pas être en même temps) for e1, e2 in conflits: for d in jours: for c in creneaux: model += lpSum(X[e1, d, c, s] for s in salles) + lpSum(X[e2, d, c, s] for s in salles) <= 1 # Contrainte 6 : Activation des jours for d in jours: for e, _, _ in examens: for c in creneaux: for s in salles: model += Y[d] >= X[e, d, c, s] # Fonction Objectif : Minimiser le nombre de jours utilisés model += lpSum(Y[d] for d in jours) # --- 3. Résolution --- model.solve() # --- 4. Extraction des résultats --- planning = [] for e, _, _ in examens: for d in jours: for c in creneaux: for s in salles: if X[e, d, c, s].varValue == 1: planning.append({"Examen": e, "Jour": d, "Créneau": c, "Salle": s}) df = pd.DataFrame(planning) df.to_csv("planning_examens.csv", index=False) return df, "planning_examens.csv" # Interface avec Gradio with gr.Blocks() as demo: gr.Markdown("# 📅 Planification des Examens avec PMNE et Gradio") exams_input = gr.Textbox(label="Examens (exam_id, nb_étudiants, durée)", lines=5, value="E1, 30, 2\nE2, 25, 1\nE3, 40, 2\nE4, 20, 1") rooms_input = gr.Textbox(label="Salles (room_id, capacité)", lines=3, value="S1, 50\nS2, 30\nS3, 40") jours_input = gr.Textbox(label="Jours disponibles (séparés par des virgules)", value="1, 2, 3") creneaux_input = gr.Textbox(label="Créneaux disponibles (séparés par des virgules)", value="1, 2, 3, 4") disponibilite_input = gr.Textbox(label="Disponibilité des salles (room_id, slot1, slot2, ...)", lines=4, value="S1, 1, 1, 1, 1\nS2, 1, 1, 0, 1\nS3, 1, 1, 1, 0") conflits_input = gr.Textbox(label="Conflits entre examens (exam1, exam2)", lines=3, value="E1, E3") output_table = gr.Dataframe(headers=["Examen", "Jour", "Créneau", "Salle"], label="Planning des examens") output_file = gr.File(label="Télécharger le planning") solve_btn = gr.Button("Planifier les examens") solve_btn.click( fn=planifier_examens, inputs=[exams_input, rooms_input, jours_input, creneaux_input, disponibilite_input, conflits_input], outputs=[output_table, output_file] ) demo.launch()