Advertisement
Guest User

Untitled

a guest
Feb 15th, 2025
62
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 11.99 KB | None | 0 0
  1. import gurobipy as gu
  2. import gurobipy as gu
  3. from icecream import ic
  4. import random
  5. import pandas as pd
  6. import numpy as np
  7.  
  8. class Subproblem_a:
  9. def __init__(self, duals_p, duals_td, duals_g, data, p, iteration, R_p, Entry_p, W, W_min):
  10. itr = iteration + 1
  11. self.P = p
  12. self.P_Full = data['P'].dropna().astype(int).unique().tolist()
  13. self.T = data['T'].dropna().astype(int).unique().tolist()
  14. self.D = data['D'].dropna().astype(int).unique().tolist()
  15. self.duals_p = duals_p
  16. self.duals_td = duals_td
  17. self.duals_g = duals_g
  18. self.Model = gu.Model("Subproblem")
  19. self.itr = itr
  20. self.R_p = R_p
  21. self.Entry_p = Entry_p
  22. self.W = W
  23. self.W_min = W_min
  24.  
  25. self.G_d = set(self.R_p.values())
  26. self.R_g = {g: [i for i in self.P_Full if self.R_p[i] == g] for g in self.G_d}
  27. self.G = list(self.G_d)
  28. self.key_group = [key for key, value in self.R_g.items() if self.P in value][0]
  29. def buildModel(self):
  30. self.genVars()
  31. self.genCons()
  32. self.genFarkasObj()
  33. self.Model.update()
  34. def genVars(self):
  35. self.l = self.Model.addVars([self.P], self.D, vtype=gu.GRB.BINARY, name="l")
  36. self.LOS = self.Model.addVars([self.P], [self.itr], vtype=gu.GRB.INTEGER, name="LOS")
  37. self.x = self.Model.addVars([self.P], self.T, self.D, [self.itr], vtype=gu.GRB.BINARY, name="x")
  38. self.y = self.Model.addVars([self.P], self.D, vtype=gu.GRB.BINARY, name="y")
  39. self.z = self.Model.addVars([self.P], self.T, vtype=gu.GRB.BINARY, name="z")
  40. self.w = self.Model.addVars([self.P],self. D, vtype=gu.GRB.BINARY, name="w")
  41. self.S = self.Model.addVars([self.P], self.D, vtype=gu.GRB.INTEGER, name="S")
  42. self.App = self.Model.addVars([self.P], self.D, vtype=gu.GRB.CONTINUOUS, name="App")
  43. self.Model.update()
  44.  
  45. def genCons(self):
  46. for p in [self.P]:
  47. self.Model.addLConstr(1 == gu.quicksum(self.l[p, d] for d in self.D))
  48. self.Model.addLConstr(self.LOS[p, self.itr] == gu.quicksum(self.l[p, d] * d for d in self.D) - self.Entry_p[p] + 1)
  49. self.Model.addLConstr(1 == gu.quicksum(self.z[p, t] for t in self.T))
  50. self.Model.addLConstr(1 == gu.quicksum(self.x[p, t, self.Entry_p[p], self.itr] for t in self.T))
  51. for d in range(2, len(self.D) + 1):
  52. self.Model.addLConstr(self.w[p, d] <= 1 - gu.quicksum(self.l[p, k] for k in range(2, d)))
  53. for d in self.D:
  54. if d < self.Entry_p[p]:
  55. self.Model.addLConstr(0 == self.w[p, d])
  56. elif d == self.Entry_p[p]:
  57. self.Model.addLConstr(1 == self.w[p, d])
  58. self.Model.addLConstr(self.l[p, d] <= gu.quicksum(self.x[p, t, d, self.itr] for t in self.T))
  59. self.Model.addLConstr(self.w[p, d] == gu.quicksum(self.x[p, t, d, self.itr] for t in self.T) + self.y[p, d])
  60. if d >= self.Entry_p[p] and d < len(self.D) - self.W + 1:
  61. self.Model.addLConstr(gu.quicksum(self.y[p, j] for j in range(d, d + self.W)) <= self.W_min)
  62. for t in self.T:
  63. self.Model.addLConstr(self.x[p, t, d, self.itr] <= self.z[p, t])
  64. for d in self.D:
  65. self.Model.addLConstr(self.l[p, d] * self.R_p[p] <= gu.quicksum(
  66. gu.quicksum(self.x[p, t, j, self.itr] for j in range(1, d + 1)) for t in self.T) + gu.quicksum(
  67. self.y[p, j] for j in range(1, d + 1)) * 0.5)
  68. self.Model.update()
  69.  
  70. def genFarkasObj(self):
  71. self.Model.setObjective(- gu.quicksum(self.x[self.P, t, d, self.itr] * self.duals_td[t, d] for t in self.T for d in self.D) - self.duals_p[self.P], sense=gu.GRB.MINIMIZE)
  72.  
  73. def getOptVals(self, var_name):
  74. variable = getattr(self, var_name, None)
  75. if variable is None:
  76. raise AttributeError(f"Variable '{var_name}' not found in the class.")
  77.  
  78. values_dict = self.Model.getAttr("X", variable)
  79. values_list = list(values_dict.values())
  80.  
  81. return values_dict, values_list
  82.  
  83. def create_lambda_list(self, index):
  84. lst = [0] * len(self.P_Full)
  85. if 1 <= index <= len(self.P_Full):
  86. lst[index - 1] = 1
  87. return lst
  88.  
  89.  
  90. class MasterProblem_a:
  91. def __init__(self, df, current_iteration, nr, T_Max, Nr_c, R_p, farkas = None, farkas_schedule=None, farkas_los = None):
  92. self.iteration = current_iteration
  93. self.P = df['P'].dropna().astype(int).unique().tolist()
  94. self.D = df['D'].dropna().astype(int).unique().tolist()
  95. self.T = df['T'].dropna().astype(int).unique().tolist()
  96. self.A = [1]
  97. self.A_Farkas = [i for i in range(1, current_iteration + 1)]
  98. self.Model = gu.Model("MasterProblem")
  99. self.cons_p_max = {}
  100. self.cons_max_group = {}
  101. self.Nr = Nr_c
  102. self.cons_lmbda = {}
  103. self.output_len = nr
  104. self.T_max = T_Max
  105. self.all_schedules = {}
  106. self.schedules_farkas_x = farkas_schedule
  107. self.schedules_farkas_los = farkas_los
  108. self.all_los = {}
  109. self.beta = 1
  110. self.R_p = R_p
  111. self.farkas = farkas
  112.  
  113. self.G_d = set(self.R_p.values())
  114. self.R_g = {g: [i for i in self.P if self.R_p[i] == g] for g in self.G_d}
  115. self.G = list(self.G_d)
  116. ic(self.G, self.R_g, self.R_g, self.R_p)
  117.  
  118. def buildModel(self):
  119. self.genVars()
  120. self.genConsFarkas()
  121. self.Model.Params.InfUnbdInfo = 1
  122. self.genFarkasObj()
  123. self.Model.update()
  124.  
  125. def genVars(self):
  126. self.lmbda = self.Model.addVars(self.P, self.A, lb = 0,vtype=gu.GRB.INTEGER, name='lmbda')
  127. self.max = self.Model.addVars(self.G, lb = 0, vtype=gu.GRB.INTEGER, name=f"max")
  128.  
  129. def genConsFarkas(self):
  130. for p in self.P:
  131. print(f'Nr: {self.Nr[p]}')
  132. self.cons_lmbda[p] = self.Model.addConstr(self.Nr[p] == 0, name=f"lmbda({p})")
  133. for t in self.T:
  134. for d in self.D:
  135. self.cons_p_max[t, d] = self.Model.addConstr(0 <= self.T_max[t, d], name=f"p_max({t},{d})")
  136. self.Model.update()
  137.  
  138. def genFarkasObj(self):
  139. self.Model.setObjective(0, sense=gu.GRB.MINIMIZE)
  140.  
  141. def solRelModel(self):
  142. self.Model.Params.OutputFlag = 1
  143. self.Model.Params.Method = 1
  144. for v in self.Model.getVars():
  145. v.setAttr('vtype', 'C')
  146. v.setAttr('lb', 0.0)
  147. self.Model.update()
  148. self.Model.optimize()
  149. if self.Model.status == 3:
  150. print('\nThe following constraints and variables are in the IIS:')
  151. self.Model.computeIIS()
  152. self.Model.write(f"iis{self.iteration}.ilp")
  153. for c in self.Model.getConstrs():
  154. if c.IISConstr: print(f'\t{c.constrname}: {self.Model.getRow(c)} {c.Sense} {c.RHS}')
  155. for v in self.Model.getVars():
  156. if v.IISLB: print(f'\t{v.varname} ≥ {v.LB}')
  157. if v.IISUB: print(f'\t{v.varname} ≤ {v.UB}')
  158.  
  159. def addSchedule(self, schedule):
  160. self.all_schedules.update(schedule)
  161.  
  162. def addLOS(self, schedule):
  163. self.all_los.update(schedule)
  164.  
  165. def getFarkasDuals(self):
  166. return {(t, d): self.cons_p_max[t, d].FarkasDual for t in self.T for d in self.D}, {p: self.cons_lmbda[p].FarkasDual for p in self.P}, {(g, i): 0 for g in self.G for i in self.R_g[g]}
  167.  
  168. def generate_start_solution(self):
  169. from collections import defaultdict
  170.  
  171. start_solution_x = {(p, t, d): 0.0 for p in self.P for t in self.T for d in self.D}
  172.  
  173. for (t, d), constraint in self.cons_p_max.items():
  174. involved_lambdas = set()
  175.  
  176. lhs = self.Model.getRow(constraint)
  177.  
  178. for i in range(lhs.size()):
  179. var = lhs.getVar(i)
  180. if var.varName.startswith("lmbda["):
  181. key = tuple(map(int, var.varName[6:-1].split(',')))
  182. involved_lambdas.add(key)
  183.  
  184. for (p, a) in involved_lambdas:
  185. start_solution_x[(p, t, d)] = 1.0
  186.  
  187. start_solution_los = {}
  188. obj_expr = self.Model.getObjective()
  189.  
  190. for i in range(obj_expr.size()):
  191. var = obj_expr.getVar(i)
  192. coeff = obj_expr.getCoeff(i)
  193. if var.varName.startswith("lmbda["):
  194. key = tuple(map(int, var.varName[6:-1].split(',')))
  195. start_solution_los[key] = coeff
  196.  
  197. new_data = defaultdict(list)
  198. for (i, j), value in start_solution_los.items():
  199. new_data[i].append(value)
  200. start_solution_los_f = {k: v[0] for k, v in new_data.items()}
  201.  
  202. return start_solution_x, start_solution_los_f
  203.  
  204. def addLambdaVar(self, p, a, col, coef):
  205. new_col = gu.Column(col, self.Model.getConstrs())
  206. var_name = f"lambda[{p},{a}]"
  207. self.lmbda[p, a] = self.Model.addVar(obj=coef[0], vtype=gu.GRB.INTEGER, column=new_col, name=var_name)
  208. self.Model.update()
  209.  
  210.  
  211. # Parameter
  212. random.seed(29)
  213. W, W_min = 5, 3
  214. E_app, E_min, baselevel, lin = 0.6, 0.1, 0.5, 0.1
  215. R_p, Entry_p, Max_t, P, D, T, N_c, R_p_c, Entry_p_c, Nr_c, unique_combinations, num_unique_combinations = {1: 4, 2: 1, 3: 1, 4: 1, 5: 1, 6: 2, 7: 2, 8: 3, 9: 1, 10: 1}, {1: 2, 2: 7, 3: 5, 4: 1, 5: 2, 6: 4, 7: 3, 8: 3, 9: 1, 10: 6}, {(1, 1): 3, (1, 2): 3, (1, 3): 3, (1, 4): 0, (1, 5): 0, (1, 6): 3, (1, 7): 3, (2, 1): 0, (2, 2): 1, (2, 3): 1, (2, 4): 1, (2, 5): 1, (2, 6): 1, (2, 7): 1, (3, 1): 0, (3, 2): 1, (3, 3): 1, (3, 4): 1, (3, 5): 1, (3, 6): 1, (3, 7): 1, (4, 1): 2, (4, 2): 2, (4, 3): 2, (4, 4): 0, (4, 5): 0, (4, 6): 2, (4, 7): 2, (5, 1): 0, (5, 2): 4, (5, 3): 4, (5, 4): 4, (5, 5): 4, (5, 6): 4, (5, 7): 4}, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], [1, 2, 3, 4, 5, 6, 7], [1, 2, 3, 4, 5], [1, 2, 3, 4, 5, 6, 7, 8, 9], {1: 4, 2: 1, 3: 1, 4: 1, 5: 1, 6: 2, 7: 2, 8: 3, 9: 1}, {1: 2, 2: 7, 3: 5, 4: 1, 5: 2, 6: 4, 7: 3, 8: 3, 9: 6}, {1: 1, 2: 1, 3: 1, 4: 2, 5: 1, 6: 1, 7: 1, 8: 1, 9: 1}, {(4, 2): [1], (1, 7): [2], (1, 5): [3], (1, 1): [4, 9], (1, 2): [5], (2, 4): [6], (2, 3): [7], (3, 3): [8], (1, 6): [10]}, 9
  216.  
  217.  
  218. # **** Prerequisites ****
  219. # Create Dataframes
  220. data = pd.DataFrame({
  221. 'P': N_c + [np.nan] * (max(len(N_c), len(T), len(D)) - len(N_c)),
  222. 'T': T + [np.nan] * (max(len(N_c), len(T), len(D)) - len(T)),
  223. 'D': D + [np.nan] * (max(len(N_c), len(T), len(D)) - len(D))
  224. })
  225.  
  226. # **** Farkas ****
  227. schedules_farkas_los = {}
  228. schedules_farkas_x = {}
  229. ModelInfeasible = True
  230. infeasible_count = 0
  231.  
  232. master_farkas = MasterProblem_a(data, infeasible_count, 50, Max_t, Nr_c, R_p, True, schedules_farkas_x, schedules_farkas_los)
  233. master_farkas.buildModel()
  234. master_farkas.solRelModel()
  235.  
  236. while (ModelInfeasible) and infeasible_count < 200:
  237.  
  238. master_farkas.solRelModel()
  239. if master_farkas.Model.Status == 3:
  240. farkas_ts, farkas_i, farkas_g = master_farkas.getFarkasDuals()
  241. ModelInfeasible = True
  242. infeasible_count += 1
  243. elif master_farkas.Model.Status != 3:
  244. ModelInfeasible = False
  245. else:
  246. break
  247.  
  248. for index in N_c:
  249. subproblem_farkas = Subproblem_a(farkas_i, farkas_ts, farkas_g, data, index, 0, R_p_c, Entry_p_c, W, W_min)
  250. subproblem_farkas.buildModel()
  251. subproblem_farkas.Model.optimize()
  252. reducedCost = subproblem_farkas.Model.objval
  253.  
  254. # Generate and add columns with reduced cost
  255. if reducedCost < -1e-7:
  256. Schedules_x_farkas, x_list_farkas = subproblem_farkas.getOptVals('x')
  257. master_farkas.addSchedule(Schedules_x_farkas)
  258. Schedules_LOS_farkas, LOS_list_farkas = subproblem_farkas.getOptVals('LOS')
  259. master_farkas.addLOS(Schedules_LOS_farkas)
  260. lambda_list_farkas = subproblem_farkas.create_lambda_list(index)
  261. master_farkas.addLambdaVar(index, infeasible_count + 1, [*lambda_list_farkas, *x_list_farkas], LOS_list_farkas)
  262.  
  263. else:
  264. print(f'No Column found for Patient {index} for Initalization.')
  265.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement