dump progresss

Signed-off-by: Hilmar Magnusson <hilmar.magnusson@bisdn.de>
This commit is contained in:
Hilmar Magnusson 2024-11-28 17:03:58 +01:00
parent 5672217c5c
commit 73628577ba
4 changed files with 143 additions and 31 deletions

View File

@ -2,3 +2,8 @@
1,21-239,1,15,0,no,28/11/2024 1,21-239,1,15,0,no,28/11/2024
2,21-237,0,22,1,no,29/11/2024 2,21-237,0,22,1,no,29/11/2024
3,21-238,3,12,1,no,30/11/2024 3,21-238,3,12,1,no,30/11/2024
4,21-248,2,12,1,no,30/11/2024
5,21-243,3,12,1,no,30/11/2024
6,21-233,3,12,1,no,30/11/2024
7,21-218,3,12,1,no,30/11/2024
8,21-208,3,12,1,no,30/11/2024

1 CaseID PatientID Station EKT Erhaltung Ket Date
2 1 21-239 1 15 0 no 28/11/2024
3 2 21-237 0 22 1 no 29/11/2024
4 3 21-238 3 12 1 no 30/11/2024
5 4 21-248 2 12 1 no 30/11/2024
6 5 21-243 3 12 1 no 30/11/2024
7 6 21-233 3 12 1 no 30/11/2024
8 7 21-218 3 12 1 no 30/11/2024
9 8 21-208 3 12 1 no 30/11/2024

View File

@ -1,5 +1,13 @@
SessionID,Date,Start,End,Duration,ConsultantID,Specialty SessionID,Date,Start,End,Duration,ConsultantID,Specialty
1001,03/06/2020,08:30:00,18:00:00,570,11,Ophthalmology 1001,29/11/2024,08:00:00,08:20:00,20,11,Ophthalmology
1002,10/06/2020,08:30:00,18:00:00,570,11,Ophthalmology 1002,29/11/2024,08:20:00,08:40:00,20,11,Ophthalmology
1003,17/06/2020,08:30:00,18:00:00,570,11,Ophthalmology 1003,29/11/2024,08:40:00,09:00:00,20,11,Ophthalmology
1004,25/06/2020,08:30:00,13:00:00,270,11,Ophthalmology 1004,29/11/2024,09:00:00,09:20:00,20,11,Ophthalmology
1005,29/11/2024,09:20:00,09:40:00,20,11,Ophthalmology
1006,29/11/2024,09:40:00,10:00:00,20,11,Ophthalmology
1007,29/11/2024,10:00:00,10:20:00,20,11,Ophthalmology
1008,29/11/2024,10:20:00,10:40:00,20,11,Ophthalmology
1009,29/11/2024,10:40:00,11:00:00,20,11,Ophthalmology
1010,29/11/2024,11:00:00,11:20:00,20,11,Ophthalmology
1011,29/11/2024,11:20:00,11:40:00,20,11,Ophthalmology
1012,29/11/2024,11:40:00,12:00:00,20,11,Ophthalmology

1 SessionID Date Start End Duration ConsultantID Specialty
2 1001 03/06/2020 29/11/2024 08:30:00 08:00:00 18:00:00 08:20:00 570 20 11 Ophthalmology
3 1002 10/06/2020 29/11/2024 08:30:00 08:20:00 18:00:00 08:40:00 570 20 11 Ophthalmology
4 1003 17/06/2020 29/11/2024 08:30:00 08:40:00 18:00:00 09:00:00 570 20 11 Ophthalmology
5 1004 25/06/2020 29/11/2024 08:30:00 09:00:00 13:00:00 09:20:00 270 20 11 Ophthalmology
6 1005 29/11/2024 09:20:00 09:40:00 20 11 Ophthalmology
7 1006 29/11/2024 09:40:00 10:00:00 20 11 Ophthalmology
8 1007 29/11/2024 10:00:00 10:20:00 20 11 Ophthalmology
9 1008 29/11/2024 10:20:00 10:40:00 20 11 Ophthalmology
10 1009 29/11/2024 10:40:00 11:00:00 20 11 Ophthalmology
11 1010 29/11/2024 11:00:00 11:20:00 20 11 Ophthalmology
12 1011 29/11/2024 11:20:00 11:40:00 20 11 Ophthalmology
13 1012 29/11/2024 11:40:00 12:00:00 20 11 Ophthalmology

152
opt.py
View File

@ -1,30 +1,8 @@
from pyomo.environ import SolverFactory
solver = SolverFactory('glpk')
import pandas as pd import pandas as pd
import pyomo.environ as pyo import pyomo.environ as pyo
import datetime import datetime
# Create a model import matplotlib.cm as cm
model = pyo.ConcreteModel() import matplotlib.pyplot as plt
## Define variables
#model.x = pyo.Var(within=pyo.NonNegativeReals)
#model.y = pyo.Var(within=pyo.NonNegativeReals)
## Define objective
#model.obj = pyo.Objective(expr=model.x + model.y, sense=pyo.minimize)
## Define constraints
#model.con1 = pyo.Constraint(expr=model.x + 2 * model.y >= 4)
#model.con2 = pyo.Constraint(expr=model.x - model.y <= 1)
## Select solver
#solver = pyo.SolverFactory('glpk')
## Solve the problem
#result = solver.solve(model)
## Display results
#print('Status:', result.solver.status)
#print('Termination Condition:', result.solver.termination_condition)
#print('Optimal x:', pyo.value(model.x))
#print('Optimal y:', pyo.value(model.y))
#print('Optimal Objective:', pyo.value(model.obj))
class Scheduler: class Scheduler:
def __init__(self, case_file_path, session_file_path, patient_file_path): def __init__(self, case_file_path, session_file_path, patient_file_path):
@ -37,7 +15,7 @@ class Scheduler:
try: try:
self.df_cases = pd.read_csv(case_file_path) self.df_cases = pd.read_csv(case_file_path)
except FileNotFoundError: except FileNotFoundError:
print("Case data not found.") print(f"Case data not found. {case_file_path}")
try: try:
self.df_sessions = pd.read_csv(session_file_path) self.df_sessions = pd.read_csv(session_file_path)
except FileNotFoundError: except FileNotFoundError:
@ -46,7 +24,119 @@ class Scheduler:
self.df_patients = pd.read_csv(patient_file_path) self.df_patients = pd.read_csv(patient_file_path)
except FileNotFoundError: except FileNotFoundError:
print("Patient data not found") print("Patient data not found")
#self.model = self.create_model() self.solver = pyo.SolverFactory('glpk')
self.model = self.create_model()
self.build_model()
def solve_model(self):
self.solver_results = self.solver.solve(self.model, tee=True)
def extract_results(self):
results = [{"Case": case,
"Session": session,
#"Session Date": self.model.SESSION_DATES[session],
#"Case Deadline": self.model.CASE_DEADLINES[case],
#"Days before deadline": self.model.CASE_DEADLINES[case] - self.model.SESSION_DATES[session],
#"Start": self.model.CASE_START_TIME[case, session](),
"Assignment": self.model.SESSION_ASSIGNED[case, session]()}
for (case, session) in self.model.TASKS]
self.df_times = pd.DataFrame(results)
def create_model(self):
return pyo.ConcreteModel()
def set_constraint(self):
self.model.c = pyo.ConstraintList()
def solve(self):
result = self.solver.solve(self.model)
print(f'result was {result}')
def build_model(self):
self.add_cases()
#self.set_options()
self.add_sessions()
self.add_tasks()
self.set_decisions()
self.set_obj()
return
def add_cases(self):
# List of case IDs in surgical waiting list
self.model.CASES = pyo.Set(initialize=self.df_cases["CaseID"].tolist())
return
def set_options(self):
# Add solver parameters (time limit)
options = {"seconds": 6}
for key, value in options.items():
self.solver.options[key] = value
def add_sessions(self):
# List of sessions IDs
# TODO: Generate more sessions based on EKT Erhaltung
self.model.SESSIONS = pyo.Set(initialize=self.df_sessions["SessionID"].tolist())
return
# List of job shop tasks
# all possible combinations of cases and sessions
def add_tasks(self):
self.model.TASKS = pyo.Set(initialize=self.model.CASES * self.model.SESSIONS, dimen=2)
return
# Decision Variables
## Upper bound (minutes in a day)
#ub = 1440
## Upper bound of session utilisation set to 85%
#max_util = 0.85
def set_decisions(self):
# Binary flag, 1 if case is assigned to session, 0 otherwise
self.model.SESSION_ASSIGNED = pyo.Var(self.model.TASKS, domain=pyo.Binary)
# Start time of a case
#self.model.CASE_START_TIME = pe.Var(self.model.TASKS, bounds=(0, ub), within=pe.PositiveReals)
# Session utilisation
num_cases = self.df_cases.shape[0]
self.model.CASES_IN_SESSION = pyo.Var(self.model.SESSIONS, bounds=(0, num_cases), within=pyo.PositiveReals)
self.model.UTILISATION = pyo.Var(self.model.SESSIONS, bounds=(0, 1), within=pyo.PositiveReals)
def set_obj(self):
# Objective
def objective_function(model):
return pyo.summation(model.CASES_IN_SESSION)
self.model.OBJECTIVE = pyo.Objective(rule=objective_function, sense=pyo.maximize)
def draw_gantt(self):
df = self.df_times[self.df_times["Assignment"] == 1]
cases = sorted(list(df['Case'].unique()))
sessions = sorted(list(df['Session'].unique()))
bar_style = {'alpha': 1.0, 'lw': 25, 'solid_capstyle': 'butt'}
text_style = {'color': 'white', 'weight': 'bold', 'ha': 'center', 'va': 'center'}
colors = cm.Dark2.colors
df.sort_values(by=['Case', 'Session'])
df.set_index(['Case', 'Session'], inplace=True)
fig, ax = plt.subplots(1, 1)
for c_ix, c in enumerate(cases, 1):
for s_ix, s in enumerate(sessions, 1):
if (c, s) in df.index:
xs = df.loc[(c, s), 'Start']
xf = df.loc[(c, s), 'Start'] + \
self.df_cases[self.df_cases["CaseID"] == c]["Median Duration"]
ax.plot([xs, xf], [s] * 2, c=colors[c_ix % 7], **bar_style)
ax.text((xs + xf) / 2, s, c, **text_style)
ax.set_title('Assigning Ophthalmology Cases to Theatre Sessions')
ax.set_xlabel('Time')
ax.set_ylabel('Sessions')
ax.grid(True)
fig.tight_layout()
plt.show()
def date2int(date): def date2int(date):
d0 = pd.to_datetime("25/11/2024", dayfirst=True) d0 = pd.to_datetime("25/11/2024", dayfirst=True)
@ -61,7 +151,7 @@ def int2date(week, day):
date = d0 + delta date = d0 + delta
return date return date
path = '/home/hmag/code/pyomo/data' path = '/home/hmag/git/octopusx/ekt/data'
my = Scheduler(path+'/cases.csv', path+'/sessions.csv', path+'/patients.csv') my = Scheduler(path+'/cases.csv', path+'/sessions.csv', path+'/patients.csv')
print(my.df_cases) print(my.df_cases)
@ -75,3 +165,11 @@ date = my.df_cases['Date'][0]
print(date2int(date)) print(date2int(date))
print(int2date(1,0)) print(int2date(1,0))
#my.set_constraint()
#my.set_obj()
my.solve_model()
my.extract_results()
print(my.df_times)
my.draw_gantt()

View File

@ -1,2 +1,3 @@
pyomo pyomo
pandas pandas
matplotlib