planificator / app.py
ChaKaGi's picture
Update app.py
48d920c verified
# -*- 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()