我是 CPLEX 优化的新手,目前,我正在编写一个模型,该模型应该将护士分配给适合其能力、专业的手术病例……</p>
实际上我认为该模型工作正常,但是当我尝试它时,它会将护士分配给不允许他们工作的病例。
我希望这里有人能抽出时间来看看这个模型并能帮助我。所以这是现有的模型(目前非常简单,有 5 名护士和 1 个病例):
.mod:
// indices
tuple nurses {
key int number_nurses ;
string roles ;
string specialty ;
string compentency ;
int shift_start ;
int shift_end ;
}
tuple shifts {
int shift_start ;
int shift_end ;
}
{shifts} shift = ... ;
{nurses} nurse = ... ;
int j = ... ;
range available_ORs = 1..j ;
{string} roles = ... ;
{string} specialty = ... ;
tuple cases {
key int number_cases ;
int start_time ;
int end_time ;
int duration ;
int demand_RN ;
int demand_ST ;
int available_ORs ;
string specialty_needed ;
string competency_needed ;
}
{cases} case = ... ;
//{string} shifts = ... ;
{string} competency = ... ;
int h = ... ;
range time_intervals = 1..h ;
// parameters
int P1 [nurse][shift] = ... ;
int P2 [nurse][roles][specialty][competency] = ... ;
int P3 [case][available_ORs] = ... ;
int P4 [time_intervals][case][specialty][competency] = ... ; // Auf Complexity innerhalb des Cases zugreifen
int P5 [time_intervals][case][roles] = ... ;
int P6 [case][time_intervals] = ... ;
int P7 [case] = ... ;
int P8 [time_intervals][shift] = ...;
int M = ... ;
// decision variables
dvar boolean y [nurse][case][roles][time_intervals] in 0..1 ; // 1: Nurse is assigened to case to perform role in time interval, 0: otherwise
dvar boolean x [nurse][case][roles] in 0..1 ;
dvar int de [time_intervals][case][roles] in 0..1 ;
dvar int dev [time_intervals][nurse] in 0..1 ;
dvar int dev2 [nurse][time_intervals] in 0..1 ;
dvar int xdev [nurse][available_ORs] in 0..1 ;
dvar int nc [nurse][case] in 0..1 ;
dvar int cd [nurse][case] in 0..1 ;
// deviation variable
dvar int DE ;
dvar int DS ;
dvar int DF ;
dvar int XDEV ;
dvar int NCT ;
dvar int CDT ;
// Objective function
minimize (DE+DF+DS+XDEV+NCT+CDT) ;
// Hard Constraints
subject to {
forall (i in nurse, h in time_intervals)
cons_01: // each nurse is assigned to at most one case in each time interval and performs a single role
sum (c in case,k in roles) y[i][c][k][h] <= 1 ;
forall (i in nurse, c in case, k in roles, h in time_intervals)
cons_02: // in each shift, cases will be assigned to the nurses who are working during their regular or authorized overtime hours
y[i][c][k][h] <= sum (s in shift) ((P1[i][s])*P8[h][s]) ;
forall (i in nurse)
cons_03: //total working hours for a nurse each day must be less than his or her total regular and overtime working hours
sum (c in case, k in roles, h in time_intervals) y[i][c][k][h] <= sum (s in shift, h in time_intervals) ((P1[i][s])*P8[h][s]) ;
forall (i in nurse, c in case, k in roles, h in time_intervals)
cons_04: // assigned to a case only if their skill level is high enough to handle the specialty requirements and have sufficient competency to deal with its procedural complexities
y[i][c][k][h] <= P6[c][h]*sum (q in specialty, p in competency) (P4[h][c][q][p]*P2[i][k][q][p]) ;
forall (c in case, k in roles, h in time_intervals)
cons_05: // see cons_04
sum (i in nurse) y[i][c][k][h] >= P6[c][h] ;
forall (i in nurse, c in case, k in roles)
cons_06: //nurses perform the same role for the entire duration of a case
sum (h in time_intervals) y[i][c][k][h] <= M * x[i][c][k] ;
forall (i in nurse, c in case)
cons_07: // see cons_06
sum (k in roles) x[i][c][k] <= 1 ;
}
// soft constraints
subject to {
forall (c in case, k in roles, h in time_intervals)
cons_08: // permit undercoverage, preferred that nurses work continuously during their regular hours rather than having idle perijjjods
sum (i in nurse) y[i][c][k][h] * de[h][c][k] >= P5[h][c][k] * P6[c][h] ; //momentan zu viele nurses, daher zu viele Zuordnungen
forall (c in case, k in roles)
cons_09: // see cons_08
DE >= sum (h in time_intervals) de[h][c][k] ;
/*forall (i in nurse, h in time_intervals)
cons_10: // avoid idle times: maximum number of times that nurses work nonconsecutive hours will be minimized along with idle time hours during the shift
-dev[h][i] <= sum (c in case, k in roles) y[i][c][k][h+1] - sum (c in case, k in roles) y[i][c][k][h] <=dev[h][i] ;*/
forall (i in nurse)
cons_11: // see cons_10
DS >= sum (h in time_intervals) dev[h][i] ;
forall(i in nurse, j in available_ORs)
cons_12: // account for the preference that nurses work continuously in one operating room: maximum number of ORs is reduced as much as possible
sum (c in case, k in roles, h in time_intervals) (y[i][c][k][h] * P3[c][j]) <= M * xdev[i][j] ;
forall (i in nurse)
cons_13: // see cons_12
sum (j in available_ORs) xdev[i][j] <= XDEV ;
forall (i in nurse, h in time_intervals)
cons_14: // record overtime: maximum number of times a nurse is working during overtime is as low as possible
sum (s in shift) P1[i][s] * 1 * sum (c in case, k in roles) y [i][c][k][h] <= dev2[i][h] ;
forall (i in nurse)
cons_15: // see cons_14
DF >= sum (h in time_intervals) dev2[i][h] ;
forall (i in nurse, c in case)
cons_16: // if nurse assigned to surgery, (s)he will stay for entire duration of the case unless there is a greater need for that nurse elseway, limit the movement of nurses between cases
sum (k in roles, h in time_intervals) y[i][c][k][h] - P7[c] + M * cd[i][c] + M * (1 - nc[i][c]) >= 0 ;
forall (i in nurse, c in case)
cons_17: // see cons_16
sum (k in roles, h in time_intervals) y[i][c][k][h] <= M * nc[i][c] ;
forall (i in nurse)
cons_18: // see cons_16
sum (c in case) nc[i][c] <= NCT ;
forall (i in nurse)
cons_19: // see cons_16
sum (c in case) cd[i][c] <= CDT ;
}
日期。
nurse = {
< 1, "RN", "cardio", "high", 6, 14 > ,
< 2, "ST", "cardio", "high", 10, 18 > ,
< 3, "RN", "neuro", "high", 14, 22 > ,
< 4, "RN", "cardio", "intermediate", 14, 22 > ,
< 5, "RN", "cardio", "high", 22, 6 > ,
} ;
j = 2 ;
roles = { "RN" , "ST" } ; // RN can work as ST if necessary, but a ST can not work as RN
specialty = { "ortho", "neuro", "cardio" } ;
case = {
< 1, 8, 15, 7, 1, 0, 1, "cardio", "intermediate" > ,
} ;
shift = { < 6, 14 > < 10, 18 > < 14, 22 > < 22, 6 >} ;
competency = { "low", "intermediate", "high" } ;
h = 24 ;
// Parameter
P1 = [
[1 0 0 0]
[0 1 0 0]
[0 0 1 0]
[0 0 1 0]
[0 0 0 1]
] ;
P2 = [
[[[1 1 1][0 0 0][0 0 0]][[1 1 1][0 0 0][0 0 0]]]
[[[0 0 0][0 0 0][0 0 0]][[1 1 1][0 0 0][0 0 0]]]
[[[0 0 0][1 1 1][0 0 0]][[0 0 0][1 1 1][0 0 0]]]
[[[1 1 0][0 0 0][0 0 0]][[1 1 0][0 0 0][0 0 0]]]
[[[1 1 1][0 0 0][0 0 0]][[1 1 1][0 0 0][0 0 0]]]
] ;
P3 = [
[1 0]
] ;
P4 = [
[[[0 0 0][0 0 0][0 0 0]]]
[[[0 0 0][0 0 0][0 0 0]]]
[[[0 0 0][0 0 0][0 0 0]]]
[[[0 0 0][0 0 0][0 0 0]]]
[[[0 0 0][0 0 0][0 0 0]]]
[[[0 0 0][0 0 0][0 0 0]]]
[[[0 0 0][0 0 0][0 0 0]]]
[[[0 1 0][0 0 0][0 0 0]]]
[[[0 1 0][0 0 0][0 0 0]]]
[[[0 1 0][0 0 0][0 0 0]]]
[[[0 1 0][0 0 0][0 0 0]]]
[[[0 1 0][0 0 0][0 0 0]]]
[[[0 1 0][0 0 0][0 0 0]]]
[[[0 1 0][0 0 0][0 0 0]]]
[[[0 0 0][0 0 0][0 0 0]]]
[[[0 0 0][0 0 0][0 0 0]]]
[[[0 0 0][0 0 0][0 0 0]]]
[[[0 0 0][0 0 0][0 0 0]]]
[[[0 0 0][0 0 0][0 0 0]]]
[[[0 0 0][0 0 0][0 0 0]]]
[[[0 0 0][0 0 0][0 0 0]]]
[[[0 0 0][0 0 0][0 0 0]]]
[[[0 0 0][0 0 0][0 0 0]]]
[[[0 0 0][0 0 0][0 0 0]]]
] ;
P5 = [
[[0 0]]
[[0 0]]
[[0 0]]
[[0 0]]
[[0 0]]
[[0 0]]
[[0 0]]
[[1 0]]
[[1 0]]
[[1 0]]
[[1 0]]
[[1 0]]
[[1 0]]
[[1 0]]
[[0 0]]
[[0 0]]
[[0 0]]
[[0 0]]
[[0 0]]
[[0 0]]
[[0 0]]
[[0 0]]
[[0 0]]
[[0 0]]
] ;
P6 = [
[0 0 0 0 0 0 0 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 ]
] ;
P7 = [7] ;
P8 = [
[0 0 0 1]
[0 0 0 1]
[0 0 0 1]
[0 0 0 1]
[0 0 0 1]
[1 0 0 0]
[1 0 0 0]
[1 0 0 0]
[1 0 0 0]
[1 1 0 0]
[1 1 0 0]
[1 1 0 0]
[1 1 0 0]
[0 1 1 0]
[0 1 1 0]
[0 1 1 0]
[0 1 1 0]
[0 0 1 0]
[0 0 1 0]
[0 0 1 0]
[0 0 1 0]
[0 0 0 1]
[0 0 0 1]
[0 0 0 1]
] ;
M = 10 ;
当我运行它时,它会将第二名护士分配给该案例,但实际上在这种情况下不允许护士 2 工作,因为需要 RN。我已经尝试了不同的可能性来写它,但我找不到原因……</p>
目前,护士 1 和护士 4 被分配为 RN(这是正确的),另外还有护士 2。
任何人都可以给我一些提示或帮助正确解决优化问题吗?我将不胜感激,在此先感谢您。