dump progresss
Signed-off-by: Hilmar Magnusson <hilmar.magnusson@bisdn.de>
This commit is contained in:
parent
5672217c5c
commit
73628577ba
|
@ -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,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
|
||||||
|
|
|
152
opt.py
152
opt.py
|
@ -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()
|
||||||
|
|
|
@ -1,2 +1,3 @@
|
||||||
pyomo
|
pyomo
|
||||||
pandas
|
pandas
|
||||||
|
matplotlib
|
||||||
|
|
Loading…
Reference in New Issue