Modeling the problem as an Integer Problem#

Integer problem#

\[\begin{split} \begin{align*} \underset{\hspace{0.05cm} \mathbf{t} \hspace{0.05cm} }{Max} & \quad \sum_{j=1}^{p} \sum_{i=1}^{n} \hspace{0.1cm}t_{ij}\cdot w_j\\[0.5cm] \text{s.t.:}&\\[0.2cm] & \sum_{j=1}^p t_{ij} \hspace{0.05cm}\leq\hspace{0.05cm} h_1 \hspace{0.1cm},\hspace{0.15cm} \forall i = 1,\dots,n\\[0.5cm] &t_{ij} \hspace{0.05cm}\geq\hspace{0.05cm} h_2\hspace{0.1cm},\hspace{0.15cm} \forall i = 1,\dots,n\hspace{0.1cm},\hspace{0.15cm} \forall j = 1,\dots,p\\[0.3cm] &\sum_{i=1}^n t_{ij} \hspace{0.05cm}\geq\hspace{0.05cm} h_3(w_j) \hspace{0.1cm},\hspace{0.15cm} \forall j = 1,\dots, p \\[0.5cm] &\sum_{i=1}^n t_{ij} \hspace{0.05cm}\leq\hspace{0.05cm} h_4 \hspace{0.1cm},\hspace{0.15cm} \forall j = 1,\dots, p \\[0.5cm] & t_{ij} \hspace{0.05cm}\geq\hspace{0.05cm} 0 \hspace{0.1cm},\hspace{0.15cm} \forall i =1,\dots,n \hspace{0.1cm},\hspace{0.15cm} \forall j =1,\dots,p\\[0.5cm] & \sum_{j=1}^p y_{j} \hspace{0.05cm} = \hspace{0.05cm} p \hspace{0.25cm}\text{(new constraint)} \\[0.5cm] \end{align*} \end{split}\]

Where:

\[\begin{split}y_j = \begin{cases} 1, \hspace{0.2cm} \sum_{i=1}^n t_{ij} > 0 \\[0.2cm] 0, \hspace{0.2cm} \sum_{i=1}^n t_{ij} = 0 \end{cases} \end{split}\]

Which is equivalent to:

\[y_j\cdot \varepsilon \hspace{0.1cm} \leq \hspace{0.1cm} \sum_{i=1}^n t_{ij} \hspace{0.1cm}\leq \hspace{0.1cm} y_j \cdot M\]

being \(\varepsilon\) and \(M\) a small and large enough positive constant, respectively.

Observation:

If \(\hspace{0.1cm} h_3^{ij} > 0, \hspace{0.05cm}\forall\hspace{0.05cm}\scriptsize{ i,j = (1,2), (3,4),\dots, (9,10)}\), the new constraint will not make any impact in the problem, just because if \(h_3^{12} > 0\), all the patients are seen, when the problem is feasible.

So, in order to see the effect of the new constraint we have to set \(\hspace{0.1cm}h_3^{ij} = 0, \hspace{0.05cm}\exists\hspace{0.05cm}\scriptsize{ i,j = (1,2), (3,4),\dots, (9,10)}\).

Solving with Pyomo#

First of all, we are going to implement the general integer (binary) problem presented above in Pyomo.

def hospital_integer_model(n, p, w, h1, h2, h3_1_2, h3_3_4, h3_5_6, h3_7_8, h3_9_10, h4):
    """
    Implements and solves the hospital integer (binary) model.

    Parameters (inputs)
    ----------
    n: number of nurse-doctor tandems in a given day.
    p: number of patients tandems in a given day.
    w: 1-D array with the severity/importance of the patients.
    h1: maximum time seeing patients per nurse-doctor tandem in a given day.
    h2: maximum time spent by nurse-doctor tandem i seeing the patient j, for all i,j.
    h3_1_2: minimum time time spent in patient j, if w[j] in [1,2].
    h3_3_4: minimum time time spent in patient j, if w[j] in [3,4].
    h3_5_6: minimum time time spent in patient j, if w[j] in [5,6].
    h3_7_8: minimum time time spent in patient j, if w[j] in [7,8].
    h3_9_10: minimum time time spent in patient j, if w[j] in [9,10].
    h4: maximum time time spent in patient j.

    Returns (outputs)
    -------
    model: the Pyomo model output.
    t_optimal: a dictionary with the optimal values for the t_ij decision variables.
    y_optimal: a dictionary with the optimal values for the y_j decision variables.
    f_optimal: the optimal value of the objective function.
    """

    # Defining h3 function.
    def h3(w):
        if w in [1, 2] :
           return h3_1_2
        if w in [3, 4] :
           return h3_3_4
        elif w in [5, 6] :
           return h3_5_6
        elif w in [7, 8] :
           return h3_7_8
        elif w in [9, 10] :
           return h3_9_10

    # Initialize a model.
    model = ConcreteModel()

    # Initialize ranges for tandems and patients.
    model.N = range(0,n)
    model.P = range(0,p)

    # Defining t_ij decision variables as non-negative reals (t_ij >= 0).
    model.t = Var(model.N, model.P, domain=NonNegativeReals) 

    # Defining y_j as a binary variable (y_j in {0,1}).
    model.y = Var(model.P, domain=Binary)

    # Objective function to maximize the weighted sum of time spent with patients
    model.cost = Objective(expr=sum(model.t[i,j] * w[j] for i in model.N for j in model.P), sense=maximize)

    # Constraints
    model.constraints = ConstraintList()

    # The total time spent by each tandem on all patients must be at most h1.
    for i in model.N:
        model.constraints.add(sum(model.t[i,j] for j in model.P) <= h1)

    # The time spent by tandem i on patient j must be at most h2.
    for i in model.N:
        for j in model.P:
            model.constraints.add(model.t[i, j] <= h2)
    
    # The total time a patient is seen by all tandems must be at least h3(w[j])
    for j in model.P:
        model.constraints.add(sum(model.t[i,j] for i in model.N) >= h3(w[j]))

    # The total time a patient is seen by all tandems must be at most h4.
    for j in model.P:
        model.constraints.add(sum(model.t[i,j] for i in model.N) <= h4)

    # y[j] is 1 if sum(model.t[i,j] for i in model.N) > 0.
    M = 1000000
    for j in model.P:
        model.constraints.add(sum(model.t[i,j] for i in model.N) <= model.y[j] * M)
         
    # y[j] is 0 if sum(model.t[i,j] for i in model.N) = 0
    epsilon = 0.000001
    for j in model.P:
        model.constraints.add(epsilon * model.y[j] <= sum(model.t[i,j] for i in model.N))

    # The number of patients seen (sum(model.y[j] for j in model.P)) must be equal to the number of patients (p).
    model.constraints.add(sum(model.y[j] for j in model.P) == p)

    # Load dual information
    # model.dual = Suffix(direction=Suffix.IMPORT)

    # Solve the model
    solver = SolverFactory('glpk')
    results = solver.solve(model, tee=False)  # Set tee=True to show solver output

    # Check solver status and termination condition
    if (results.solver.status == SolverStatus.ok) and (results.solver.termination_condition == TerminationCondition.optimal):
        #print("Solution Found")
        # Extract optimal values for variables and objective
        t_optimal = {(i, j): model.t[i, j].value for i in model.N for j in model.P}
        y_optimal = {j: model.y[j].value for j in model.P}
        f_optimal = model.cost.expr()
    elif results.solver.termination_condition == TerminationCondition.infeasible:
        #print("No feasible solution")
        t_optimal, y_optimal, f_optimal = None, None, None
    else:
        #print("No feasible solution")
        t_optimal, y_optimal, f_optimal = None, None, None

    return model, t_optimal, y_optimal, f_optimal

Preliminary analysis#

In this section we are going to do a preliminary numerical analysis of the problem posed above, for a given set of parameters.

# Parameters definition:
n=50; p=500; h1=6; h2=1; h4=4

h3_1_2 = 0
h3_3_4 = 0.30 
h3_5_6 = 0.55  
h3_7_8 = 0.80 
h3_9_10 = 1 
    
np.random.seed(123)
w = np.random.randint(1, 11, p) 

# Problem execution:
model, t_optimal, y_optimal, f_optimal = hospital_integer_model(n, p, w, h1, h2, h3_1_2, h3_3_4, h3_5_6, h3_7_8, h3_9_10, h4)

Optimal values#

Decision variables

The optimal values for the \(t_{ij}\) decision variables for the given set of parameters are the following:

t_optimal
{(0, 0): 0.0,
 (0, 1): 0.0,
 (0, 2): 0.0,
 (0, 3): 0.0,
 (0, 4): 0.0,
 (0, 5): 0.0,
 (0, 6): 0.0,
 (0, 7): 0.0,
 (0, 8): 0.0,
 (0, 9): 0.0,
 (0, 10): 0.0,
 (0, 11): 0.0,
 (0, 12): 0.0,
 (0, 13): 0.0,
 (0, 14): 0.0,
 (0, 15): 0.0,
 (0, 16): 0.0,
 (0, 17): 0.0,
 (0, 18): 0.0,
 (0, 19): 0.0,
 (0, 20): 0.0,
 (0, 21): 0.0,
 (0, 22): 0.0,
 (0, 23): 0.0,
 (0, 24): 0.0,
 (0, 25): 0.0,
 (0, 26): 0.0,
 (0, 27): 0.0,
 (0, 28): 0.0,
 (0, 29): 0.0,
 (0, 30): 0.0,
 (0, 31): 0.0,
 (0, 32): 0.0,
 (0, 33): 0.0,
 (0, 34): 0.0,
 (0, 35): 0.0,
 (0, 36): 0.0,
 (0, 37): 0.0,
 (0, 38): 0.0,
 (0, 39): 0.0,
 (0, 40): 0.0,
 (0, 41): 0.0,
 (0, 42): 0.0,
 (0, 43): 0.0,
 (0, 44): 0.0,
 (0, 45): 0.0,
 (0, 46): 0.0,
 (0, 47): 0.0,
 (0, 48): 0.0,
 (0, 49): 0.0,
 (0, 50): 0.0,
 (0, 51): 0.0,
 (0, 52): 0.0,
 (0, 53): 0.0,
 (0, 54): 0.0,
 (0, 55): 0.0,
 (0, 56): 0.0,
 (0, 57): 0.0,
 (0, 58): 0.0,
 (0, 59): 0.0,
 (0, 60): 0.0,
 (0, 61): 0.0,
 (0, 62): 0.0,
 (0, 63): 0.0,
 (0, 64): 0.0,
 (0, 65): 0.0,
 (0, 66): 0.0,
 (0, 67): 0.0,
 (0, 68): 0.0,
 (0, 69): 0.0,
 (0, 70): 0.0,
 (0, 71): 0.0,
 (0, 72): 0.0,
 (0, 73): 0.0,
 (0, 74): 0.0,
 (0, 75): 0.0,
 (0, 76): 0.0,
 (0, 77): 0.0,
 (0, 78): 0.0,
 (0, 79): 0.0,
 (0, 80): 0.0,
 (0, 81): 0.0,
 (0, 82): 0.0,
 (0, 83): 0.0,
 (0, 84): 0.0,
 (0, 85): 0.0,
 (0, 86): 0.0,
 (0, 87): 0.0,
 (0, 88): 0.0,
 (0, 89): 0.0,
 (0, 90): 0.0,
 (0, 91): 0.0,
 (0, 92): 0.0,
 (0, 93): 0.0,
 (0, 94): 0.0,
 (0, 95): 0.0,
 (0, 96): 0.0,
 (0, 97): 0.0,
 (0, 98): 0.0,
 (0, 99): 0.0,
 (0, 100): 0.0,
 (0, 101): 0.0,
 (0, 102): 0.0,
 (0, 103): 0.0,
 (0, 104): 0.0,
 (0, 105): 0.0,
 (0, 106): 0.0,
 (0, 107): 0.0,
 (0, 108): 0.0,
 (0, 109): 0.0,
 (0, 110): 0.0,
 (0, 111): 0.0,
 (0, 112): 0.0,
 (0, 113): 0.0,
 (0, 114): 0.0,
 (0, 115): 0.0,
 (0, 116): 0.0,
 (0, 117): 0.0,
 (0, 118): 0.0,
 (0, 119): 0.0,
 (0, 120): 0.0,
 (0, 121): 0.0,
 (0, 122): 0.0,
 (0, 123): 0.0,
 (0, 124): 0.0,
 (0, 125): 0.0,
 (0, 126): 0.0,
 (0, 127): 0.0,
 (0, 128): 0.0,
 (0, 129): 0.0,
 (0, 130): 0.0,
 (0, 131): 0.0,
 (0, 132): 0.0,
 (0, 133): 0.0,
 (0, 134): 0.0,
 (0, 135): 0.0,
 (0, 136): 0.0,
 (0, 137): 0.0,
 (0, 138): 0.0,
 (0, 139): 0.0,
 (0, 140): 0.0,
 (0, 141): 0.0,
 (0, 142): 0.0,
 (0, 143): 0.0,
 (0, 144): 0.0,
 (0, 145): 0.0,
 (0, 146): 0.0,
 (0, 147): 0.0,
 (0, 148): 0.0,
 (0, 149): 0.0,
 (0, 150): 0.0,
 (0, 151): 0.0,
 (0, 152): 0.0,
 (0, 153): 0.0,
 (0, 154): 0.0,
 (0, 155): 0.0,
 (0, 156): 0.0,
 (0, 157): 0.0,
 (0, 158): 0.0,
 (0, 159): 0.0,
 (0, 160): 0.0,
 (0, 161): 0.0,
 (0, 162): 0.0,
 (0, 163): 0.0,
 (0, 164): 0.0,
 (0, 165): 0.0,
 (0, 166): 0.0,
 (0, 167): 0.0,
 (0, 168): 0.0,
 (0, 169): 0.0,
 (0, 170): 0.0,
 (0, 171): 0.0,
 (0, 172): 0.0,
 (0, 173): 0.0,
 (0, 174): 0.0,
 (0, 175): 0.0,
 (0, 176): 0.0,
 (0, 177): 0.0,
 (0, 178): 0.0,
 (0, 179): 0.0,
 (0, 180): 0.0,
 (0, 181): 0.0,
 (0, 182): 0.0,
 (0, 183): 0.0,
 (0, 184): 0.0,
 (0, 185): 0.0,
 (0, 186): 0.0,
 (0, 187): 0.0,
 (0, 188): 0.0,
 (0, 189): 0.0,
 (0, 190): 0.0,
 (0, 191): 0.0,
 (0, 192): 0.0,
 (0, 193): 0.0,
 (0, 194): 0.0,
 (0, 195): 0.0,
 (0, 196): 0.0,
 (0, 197): 0.0,
 (0, 198): 0.0,
 (0, 199): 0.0,
 (0, 200): 0.0,
 (0, 201): 0.0,
 (0, 202): 0.0,
 (0, 203): 0.0,
 (0, 204): 0.0,
 (0, 205): 0.0,
 (0, 206): 0.0,
 (0, 207): 0.0,
 (0, 208): 0.0,
 (0, 209): 0.0,
 (0, 210): 0.0,
 (0, 211): 0.0,
 (0, 212): 0.0,
 (0, 213): 0.0,
 (0, 214): 0.0,
 (0, 215): 0.0,
 (0, 216): 0.0,
 (0, 217): 0.0,
 (0, 218): 0.0,
 (0, 219): 0.0,
 (0, 220): 0.0,
 (0, 221): 0.0,
 (0, 222): 0.0,
 (0, 223): 0.0,
 (0, 224): 0.0,
 (0, 225): 0.0,
 (0, 226): 0.0,
 (0, 227): 0.0,
 (0, 228): 0.0,
 (0, 229): 0.0,
 (0, 230): 0.0,
 (0, 231): 0.0,
 (0, 232): 0.0,
 (0, 233): 0.0,
 (0, 234): 0.0,
 (0, 235): 0.0,
 (0, 236): 0.0,
 (0, 237): 0.0,
 (0, 238): 0.0,
 (0, 239): 0.0,
 (0, 240): 0.0,
 (0, 241): 0.0,
 (0, 242): 0.0,
 (0, 243): 0.0,
 (0, 244): 0.0,
 (0, 245): 0.0,
 (0, 246): 0.0,
 (0, 247): 0.0,
 (0, 248): 0.0,
 (0, 249): 0.0,
 (0, 250): 0.0,
 (0, 251): 0.0,
 (0, 252): 0.0,
 (0, 253): 0.0,
 (0, 254): 0.0,
 (0, 255): 0.0,
 (0, 256): 0.0,
 (0, 257): 0.0,
 (0, 258): 0.0,
 (0, 259): 0.0,
 (0, 260): 0.0,
 (0, 261): 0.0,
 (0, 262): 0.0,
 (0, 263): 0.0,
 (0, 264): 0.0,
 (0, 265): 0.0,
 (0, 266): 0.0,
 (0, 267): 0.0,
 (0, 268): 0.0,
 (0, 269): 0.0,
 (0, 270): 0.0,
 (0, 271): 0.0,
 (0, 272): 0.0,
 (0, 273): 0.0,
 (0, 274): 0.0,
 (0, 275): 0.0,
 (0, 276): 0.0,
 (0, 277): 0.0,
 (0, 278): 0.0,
 (0, 279): 0.0,
 (0, 280): 0.0,
 (0, 281): 0.0,
 (0, 282): 0.0,
 (0, 283): 0.0,
 (0, 284): 0.0,
 (0, 285): 0.0,
 (0, 286): 0.0,
 (0, 287): 0.0,
 (0, 288): 0.0,
 (0, 289): 0.0,
 (0, 290): 0.0,
 (0, 291): 0.0,
 (0, 292): 0.0,
 (0, 293): 0.0,
 (0, 294): 0.0,
 (0, 295): 0.0,
 (0, 296): 0.0,
 (0, 297): 0.0,
 (0, 298): 0.0,
 (0, 299): 0.0,
 (0, 300): 0.0,
 (0, 301): 0.0,
 (0, 302): 0.0,
 (0, 303): 0.0,
 (0, 304): 0.0,
 (0, 305): 0.0,
 (0, 306): 0.0,
 (0, 307): 0.0,
 (0, 308): 0.0,
 (0, 309): 0.0,
 (0, 310): 0.0,
 (0, 311): 0.0,
 (0, 312): 0.0,
 (0, 313): 0.0,
 (0, 314): 0.0,
 (0, 315): 0.0,
 (0, 316): 0.0,
 (0, 317): 0.0,
 (0, 318): 0.0,
 (0, 319): 0.0,
 (0, 320): 0.0,
 (0, 321): 0.0,
 (0, 322): 0.0,
 (0, 323): 0.0,
 (0, 324): 0.0,
 (0, 325): 0.0,
 (0, 326): 0.0,
 (0, 327): 0.0,
 (0, 328): 0.0,
 (0, 329): 0.0,
 (0, 330): 0.0,
 (0, 331): 0.0,
 (0, 332): 0.0,
 (0, 333): 0.0,
 (0, 334): 0.0,
 (0, 335): 0.0,
 (0, 336): 0.0,
 (0, 337): 0.0,
 (0, 338): 0.0,
 (0, 339): 0.0,
 (0, 340): 0.0,
 (0, 341): 0.0,
 (0, 342): 0.0,
 (0, 343): 0.0,
 (0, 344): 0.0,
 (0, 345): 0.0,
 (0, 346): 0.0,
 (0, 347): 0.0,
 (0, 348): 0.0,
 (0, 349): 0.0,
 (0, 350): 0.0,
 (0, 351): 0.0,
 (0, 352): 0.0,
 (0, 353): 0.0,
 (0, 354): 0.0,
 (0, 355): 0.0,
 (0, 356): 0.0,
 (0, 357): 0.0,
 (0, 358): 0.0,
 (0, 359): 0.0,
 (0, 360): 0.0,
 (0, 361): 0.0,
 (0, 362): 0.0,
 (0, 363): 0.0,
 (0, 364): 0.0,
 (0, 365): 1.0,
 (0, 366): 0.0,
 (0, 367): 0.0,
 (0, 368): 0.0,
 (0, 369): 0.0,
 (0, 370): 0.0,
 (0, 371): 0.0,
 (0, 372): 0.0,
 (0, 373): 0.0,
 (0, 374): 0.0,
 (0, 375): 0.0,
 (0, 376): 0.0,
 (0, 377): 0.0,
 (0, 378): 0.0,
 (0, 379): 0.0,
 (0, 380): 0.0,
 (0, 381): 1.0,
 (0, 382): 0.0,
 (0, 383): 0.0,
 (0, 384): 0.0,
 (0, 385): 0.0,
 (0, 386): 0.0,
 (0, 387): 0.0,
 (0, 388): 0.0,
 (0, 389): 0.0,
 (0, 390): 0.0,
 (0, 391): 0.0,
 (0, 392): 0.0,
 (0, 393): 1.0,
 (0, 394): 0.0,
 (0, 395): 0.0,
 (0, 396): 0.0,
 (0, 397): 0.0,
 (0, 398): 0.0,
 (0, 399): 0.0,
 (0, 400): 0.0,
 (0, 401): 0.0,
 (0, 402): 0.0,
 (0, 403): 0.0,
 (0, 404): 0.0,
 (0, 405): 0.0,
 (0, 406): 0.0,
 (0, 407): 0.0,
 (0, 408): 0.0,
 (0, 409): 0.0,
 (0, 410): 0.0,
 (0, 411): 0.0,
 (0, 412): 0.0,
 (0, 413): 0.0,
 (0, 414): 0.0,
 (0, 415): 0.0,
 (0, 416): 0.0,
 (0, 417): 0.0,
 (0, 418): 0.0,
 (0, 419): 0.0,
 (0, 420): 0.0,
 (0, 421): 0.0,
 (0, 422): 0.0,
 (0, 423): 0.0,
 (0, 424): 0.0,
 (0, 425): 0.0,
 (0, 426): 0.0,
 (0, 427): 0.0,
 (0, 428): 0.0,
 (0, 429): 0.0,
 (0, 430): 0.0,
 (0, 431): 0.0,
 (0, 432): 0.0,
 (0, 433): 0.0,
 (0, 434): 0.0,
 (0, 435): 0.0,
 (0, 436): 0.0,
 (0, 437): 0.0,
 (0, 438): 0.0,
 (0, 439): 0.0,
 (0, 440): 0.0,
 (0, 441): 0.0,
 (0, 442): 0.0,
 (0, 443): 0.0,
 (0, 444): 0.0,
 (0, 445): 0.0,
 (0, 446): 0.0,
 (0, 447): 0.0,
 (0, 448): 0.0,
 (0, 449): 0.0,
 (0, 450): 0.0,
 (0, 451): 0.0,
 (0, 452): 0.0,
 (0, 453): 0.0,
 (0, 454): 0.0,
 (0, 455): 0.0,
 (0, 456): 0.0,
 (0, 457): 0.0,
 (0, 458): 0.0,
 (0, 459): 1.0,
 (0, 460): 0.0,
 (0, 461): 0.0,
 (0, 462): 0.0,
 (0, 463): 0.0,
 (0, 464): 0.0,
 (0, 465): 0.0,
 (0, 466): 1.0,
 (0, 467): 0.0,
 (0, 468): 0.0,
 (0, 469): 0.0,
 (0, 470): 0.0,
 (0, 471): 0.0,
 (0, 472): 1.0,
 (0, 473): 0.0,
 (0, 474): 0.0,
 (0, 475): 0.0,
 (0, 476): 0.0,
 (0, 477): 0.0,
 (0, 478): 0.0,
 (0, 479): 0.0,
 (0, 480): 0.0,
 (0, 481): 0.0,
 (0, 482): 0.0,
 (0, 483): 0.0,
 (0, 484): 0.0,
 (0, 485): 0.0,
 (0, 486): 0.0,
 (0, 487): 0.0,
 (0, 488): 0.0,
 (0, 489): 0.0,
 (0, 490): 0.0,
 (0, 491): 0.0,
 (0, 492): 0.0,
 (0, 493): 0.0,
 (0, 494): 0.0,
 (0, 495): 0.0,
 (0, 496): 0.0,
 (0, 497): 0.0,
 (0, 498): 0.0,
 (0, 499): 0.0,
 (1, 0): 0.0,
 (1, 1): 0.0,
 (1, 2): 0.0,
 (1, 3): 0.0,
 (1, 4): 0.0,
 (1, 5): 0.0,
 (1, 6): 0.0,
 (1, 7): 0.0,
 (1, 8): 0.0,
 (1, 9): 0.0,
 (1, 10): 0.0,
 (1, 11): 0.0,
 (1, 12): 0.0,
 (1, 13): 0.0,
 (1, 14): 0.0,
 (1, 15): 0.449901999999988,
 (1, 16): 1e-06,
 (1, 17): 1e-06,
 (1, 18): 0.55,
 (1, 19): 1e-06,
 (1, 20): 0.8,
 (1, 21): 0.3,
 (1, 22): 0.3,
 (1, 23): 0.55,
 (1, 24): 0.8,
 (1, 25): 0.3,
 (1, 26): 0.55,
 (1, 27): 1.0,
 (1, 28): 1e-06,
 (1, 29): 0.399999999999999,
 (1, 30): 0.0,
 (1, 31): 0.0,
 (1, 32): 0.0,
 (1, 33): 0.0,
 (1, 34): 1e-06,
 (1, 35): 0.0,
 (1, 36): 0.0,
 (1, 37): 0.0,
 (1, 38): 1e-06,
 (1, 39): 0.0,
 (1, 40): 0.0,
 (1, 41): 0.0,
 (1, 42): 1e-06,
 (1, 43): 0.0,
 (1, 44): 0.0,
 (1, 45): 0.0,
 (1, 46): 0.0,
 (1, 47): 0.0,
 (1, 48): 0.0,
 (1, 49): 0.0,
 (1, 50): 1e-06,
 (1, 51): 0.0,
 (1, 52): 0.0,
 (1, 53): 0.0,
 (1, 54): 0.0,
 (1, 55): 0.0,
 (1, 56): 1e-06,
 (1, 57): 0.0,
 (1, 58): 0.0,
 (1, 59): 0.0,
 (1, 60): 0.0,
 (1, 61): 0.0,
 (1, 62): 0.0,
 (1, 63): 1e-06,
 (1, 64): 0.0,
 (1, 65): 1e-06,
 (1, 66): 1e-06,
 (1, 67): 0.0,
 (1, 68): 0.0,
 (1, 69): 0.0,
 (1, 70): 1e-06,
 (1, 71): 0.0,
 (1, 72): 1e-06,
 (1, 73): 0.0,
 (1, 74): 0.0,
 (1, 75): 0.0,
 (1, 76): 0.0,
 (1, 77): 0.0,
 (1, 78): 0.0,
 (1, 79): 0.0,
 (1, 80): 0.0,
 (1, 81): 0.0,
 (1, 82): 0.0,
 (1, 83): 0.0,
 (1, 84): 0.0,
 (1, 85): 0.0,
 (1, 86): 0.0,
 (1, 87): 0.0,
 (1, 88): 0.0,
 (1, 89): 0.0,
 (1, 90): 0.0,
 (1, 91): 0.0,
 (1, 92): 0.0,
 (1, 93): 0.0,
 (1, 94): 1e-06,
 (1, 95): 0.0,
 (1, 96): 0.0,
 (1, 97): 0.0,
 (1, 98): 1e-06,
 (1, 99): 1e-06,
 (1, 100): 0.0,
 (1, 101): 0.0,
 (1, 102): 0.0,
 (1, 103): 0.0,
 (1, 104): 0.0,
 (1, 105): 1e-06,
 (1, 106): 1e-06,
 (1, 107): 0.0,
 (1, 108): 1e-06,
 (1, 109): 0.0,
 (1, 110): 0.0,
 (1, 111): 0.0,
 (1, 112): 0.0,
 (1, 113): 1e-06,
 (1, 114): 0.0,
 (1, 115): 0.0,
 (1, 116): 0.0,
 (1, 117): 0.0,
 (1, 118): 0.0,
 (1, 119): 0.0,
 (1, 120): 0.0,
 (1, 121): 0.0,
 (1, 122): 0.0,
 (1, 123): 0.0,
 (1, 124): 1e-06,
 (1, 125): 1e-06,
 (1, 126): 0.0,
 (1, 127): 0.0,
 (1, 128): 0.0,
 (1, 129): 0.0,
 (1, 130): 0.0,
 (1, 131): 0.0,
 (1, 132): 1e-06,
 (1, 133): 0.0,
 (1, 134): 0.0,
 (1, 135): 0.0,
 (1, 136): 0.0,
 (1, 137): 1e-06,
 (1, 138): 0.0,
 (1, 139): 1e-06,
 (1, 140): 0.0,
 (1, 141): 0.0,
 (1, 142): 0.0,
 (1, 143): 0.0,
 (1, 144): 1e-06,
 (1, 145): 0.0,
 (1, 146): 1e-06,
 (1, 147): 0.0,
 (1, 148): 0.0,
 (1, 149): 0.0,
 (1, 150): 1e-06,
 (1, 151): 0.0,
 (1, 152): 0.0,
 (1, 153): 0.0,
 (1, 154): 0.0,
 (1, 155): 0.0,
 (1, 156): 0.0,
 (1, 157): 0.0,
 (1, 158): 0.0,
 (1, 159): 0.0,
 (1, 160): 0.0,
 (1, 161): 1e-06,
 (1, 162): 0.0,
 (1, 163): 0.0,
 (1, 164): 0.0,
 (1, 165): 0.0,
 (1, 166): 0.0,
 (1, 167): 0.0,
 (1, 168): 0.0,
 (1, 169): 0.0,
 (1, 170): 0.0,
 (1, 171): 0.0,
 (1, 172): 1e-06,
 (1, 173): 0.0,
 (1, 174): 0.0,
 (1, 175): 0.0,
 (1, 176): 0.0,
 (1, 177): 0.0,
 (1, 178): 0.0,
 (1, 179): 1e-06,
 (1, 180): 0.0,
 (1, 181): 0.0,
 (1, 182): 0.0,
 (1, 183): 0.0,
 (1, 184): 1e-06,
 (1, 185): 0.0,
 (1, 186): 0.0,
 (1, 187): 0.0,
 (1, 188): 0.0,
 (1, 189): 0.0,
 (1, 190): 1e-06,
 (1, 191): 0.0,
 (1, 192): 0.0,
 (1, 193): 0.0,
 (1, 194): 0.0,
 (1, 195): 0.0,
 (1, 196): 1e-06,
 (1, 197): 0.0,
 (1, 198): 0.0,
 (1, 199): 0.0,
 (1, 200): 1e-06,
 (1, 201): 0.0,
 (1, 202): 0.0,
 (1, 203): 0.0,
 (1, 204): 1e-06,
 (1, 205): 0.0,
 (1, 206): 0.0,
 (1, 207): 0.0,
 (1, 208): 0.0,
 (1, 209): 1e-06,
 (1, 210): 0.0,
 (1, 211): 0.0,
 (1, 212): 0.0,
 (1, 213): 1e-06,
 (1, 214): 0.0,
 (1, 215): 0.0,
 (1, 216): 0.0,
 (1, 217): 0.0,
 (1, 218): 0.0,
 (1, 219): 0.0,
 (1, 220): 0.0,
 (1, 221): 0.0,
 (1, 222): 0.0,
 (1, 223): 0.0,
 (1, 224): 0.0,
 (1, 225): 0.0,
 (1, 226): 0.0,
 (1, 227): 0.0,
 (1, 228): 0.0,
 (1, 229): 0.0,
 (1, 230): 1e-06,
 (1, 231): 0.0,
 (1, 232): 0.0,
 (1, 233): 0.0,
 (1, 234): 0.0,
 (1, 235): 0.0,
 (1, 236): 0.0,
 (1, 237): 0.0,
 (1, 238): 1e-06,
 (1, 239): 1e-06,
 (1, 240): 0.0,
 (1, 241): 1e-06,
 (1, 242): 1e-06,
 (1, 243): 0.0,
 (1, 244): 0.0,
 (1, 245): 0.0,
 (1, 246): 0.0,
 (1, 247): 1e-06,
 (1, 248): 0.0,
 (1, 249): 1e-06,
 (1, 250): 0.0,
 (1, 251): 0.0,
 (1, 252): 0.0,
 (1, 253): 0.0,
 (1, 254): 0.0,
 (1, 255): 0.0,
 (1, 256): 1e-06,
 (1, 257): 0.0,
 (1, 258): 0.0,
 (1, 259): 1e-06,
 (1, 260): 0.0,
 (1, 261): 0.0,
 (1, 262): 0.0,
 (1, 263): 1e-06,
 (1, 264): 0.0,
 (1, 265): 1e-06,
 (1, 266): 0.0,
 (1, 267): 0.0,
 (1, 268): 0.0,
 (1, 269): 0.0,
 (1, 270): 0.0,
 (1, 271): 0.0,
 (1, 272): 0.0,
 (1, 273): 0.0,
 (1, 274): 0.0,
 (1, 275): 1e-06,
 (1, 276): 0.0,
 (1, 277): 0.0,
 (1, 278): 1e-06,
 (1, 279): 0.0,
 (1, 280): 0.0,
 (1, 281): 1e-06,
 (1, 282): 0.0,
 (1, 283): 0.0,
 (1, 284): 1e-06,
 (1, 285): 0.0,
 (1, 286): 1e-06,
 (1, 287): 0.0,
 (1, 288): 1e-06,
 (1, 289): 0.0,
 (1, 290): 1e-06,
 (1, 291): 0.0,
 (1, 292): 0.0,
 (1, 293): 0.0,
 (1, 294): 0.0,
 (1, 295): 1e-06,
 (1, 296): 1e-06,
 (1, 297): 1e-06,
 (1, 298): 0.0,
 (1, 299): 0.0,
 (1, 300): 0.0,
 (1, 301): 0.0,
 (1, 302): 1e-06,
 (1, 303): 0.0,
 (1, 304): 0.0,
 (1, 305): 0.0,
 (1, 306): 0.0,
 (1, 307): 0.0,
 (1, 308): 1e-06,
 (1, 309): 0.0,
 (1, 310): 1e-06,
 (1, 311): 0.0,
 (1, 312): 1e-06,
 (1, 313): 0.0,
 (1, 314): 1e-06,
 (1, 315): 0.0,
 (1, 316): 0.0,
 (1, 317): 1e-06,
 (1, 318): 0.0,
 (1, 319): 0.0,
 (1, 320): 0.0,
 (1, 321): 0.0,
 (1, 322): 1e-06,
 (1, 323): 0.0,
 (1, 324): 1e-06,
 (1, 325): 0.0,
 (1, 326): 0.0,
 (1, 327): 0.0,
 (1, 328): 1e-06,
 (1, 329): 0.0,
 (1, 330): 0.0,
 (1, 331): 0.0,
 (1, 332): 1e-06,
 (1, 333): 0.0,
 (1, 334): 0.0,
 (1, 335): 0.0,
 (1, 336): 1e-06,
 (1, 337): 0.0,
 (1, 338): 0.0,
 (1, 339): 0.0,
 (1, 340): 1e-06,
 (1, 341): 1e-06,
 (1, 342): 1e-06,
 (1, 343): 0.0,
 (1, 344): 0.0,
 (1, 345): 0.0,
 (1, 346): 1e-06,
 (1, 347): 0.0,
 (1, 348): 0.0,
 (1, 349): 0.0,
 (1, 350): 0.0,
 (1, 351): 0.0,
 (1, 352): 0.0,
 (1, 353): 1e-06,
 (1, 354): 0.0,
 (1, 355): 1e-06,
 (1, 356): 0.0,
 (1, 357): 1e-06,
 (1, 358): 0.0,
 (1, 359): 0.0,
 (1, 360): 0.0,
 (1, 361): 0.0,
 (1, 362): 0.0,
 (1, 363): 0.0,
 (1, 364): 0.0,
 (1, 365): 0.0,
 (1, 366): 0.0,
 (1, 367): 1e-06,
 (1, 368): 1e-06,
 (1, 369): 0.0,
 (1, 370): 0.0,
 (1, 371): 0.0,
 (1, 372): 0.0,
 (1, 373): 0.0,
 (1, 374): 0.0,
 (1, 375): 0.0,
 (1, 376): 0.0,
 (1, 377): 0.0,
 (1, 378): 0.0,
 (1, 379): 1e-06,
 (1, 380): 0.0,
 (1, 381): 0.0,
 (1, 382): 0.0,
 (1, 383): 0.0,
 (1, 384): 0.0,
 (1, 385): 0.0,
 (1, 386): 1e-06,
 (1, 387): 0.0,
 (1, 388): 0.0,
 (1, 389): 1e-06,
 (1, 390): 0.0,
 (1, 391): 0.0,
 (1, 392): 0.0,
 (1, 393): 0.0,
 (1, 394): 0.0,
 (1, 395): 0.0,
 (1, 396): 0.0,
 (1, 397): 0.0,
 (1, 398): 1e-06,
 (1, 399): 0.0,
 (1, 400): 0.0,
 (1, 401): 0.0,
 (1, 402): 0.0,
 (1, 403): 0.0,
 (1, 404): 1e-06,
 (1, 405): 0.0,
 (1, 406): 0.0,
 (1, 407): 0.0,
 (1, 408): 0.0,
 (1, 409): 0.0,
 (1, 410): 0.0,
 (1, 411): 0.0,
 (1, 412): 1e-06,
 (1, 413): 0.0,
 (1, 414): 0.0,
 (1, 415): 0.0,
 (1, 416): 0.0,
 (1, 417): 0.0,
 (1, 418): 1e-06,
 (1, 419): 0.0,
 (1, 420): 0.0,
 (1, 421): 0.0,
 (1, 422): 0.0,
 (1, 423): 0.0,
 (1, 424): 0.0,
 (1, 425): 0.0,
 (1, 426): 0.0,
 (1, 427): 1e-06,
 (1, 428): 0.0,
 (1, 429): 1e-06,
 (1, 430): 1e-06,
 (1, 431): 0.0,
 (1, 432): 0.0,
 (1, 433): 0.0,
 (1, 434): 0.0,
 (1, 435): 0.0,
 (1, 436): 0.0,
 (1, 437): 0.0,
 (1, 438): 0.0,
 (1, 439): 0.0,
 (1, 440): 0.0,
 (1, 441): 0.0,
 (1, 442): 0.0,
 (1, 443): 0.0,
 (1, 444): 0.0,
 (1, 445): 0.0,
 (1, 446): 0.0,
 (1, 447): 0.0,
 (1, 448): 1e-06,
 (1, 449): 0.0,
 (1, 450): 0.0,
 (1, 451): 0.0,
 (1, 452): 0.0,
 (1, 453): 1e-06,
 (1, 454): 1e-06,
 (1, 455): 0.0,
 (1, 456): 0.0,
 (1, 457): 0.0,
 (1, 458): 0.0,
 (1, 459): 0.0,
 (1, 460): 0.0,
 (1, 461): 0.0,
 (1, 462): 0.0,
 (1, 463): 0.0,
 (1, 464): 0.0,
 (1, 465): 0.0,
 (1, 466): 0.0,
 (1, 467): 0.0,
 (1, 468): 1e-06,
 (1, 469): 0.0,
 (1, 470): 0.0,
 (1, 471): 0.0,
 (1, 472): 0.0,
 (1, 473): 0.0,
 (1, 474): 1e-06,
 (1, 475): 1e-06,
 (1, 476): 0.0,
 (1, 477): 1e-06,
 (1, 478): 0.0,
 (1, 479): 0.0,
 (1, 480): 0.0,
 (1, 481): 0.0,
 (1, 482): 0.0,
 (1, 483): 0.0,
 (1, 484): 0.0,
 (1, 485): 0.0,
 (1, 486): 0.0,
 (1, 487): 0.0,
 (1, 488): 0.0,
 (1, 489): 0.0,
 (1, 490): 0.0,
 (1, 491): 0.0,
 (1, 492): 0.0,
 (1, 493): 0.0,
 (1, 494): 1e-06,
 (1, 495): 0.0,
 (1, 496): 0.0,
 (1, 497): 0.0,
 (1, 498): 0.0,
 (1, 499): 0.0,
 ...}

The optimal values for the \(y_{j}\) decision variables for the given set of parameters are the following:

y_optimal
{0: 1.0,
 1: 1.0,
 2: 1.0,
 3: 1.0,
 4: 1.0,
 5: 1.0,
 6: 1.0,
 7: 1.0,
 8: 1.0,
 9: 1.0,
 10: 1.0,
 11: 1.0,
 12: 1.0,
 13: 1.0,
 14: 1.0,
 15: 1.0,
 16: 1.0,
 17: 1.0,
 18: 1.0,
 19: 1.0,
 20: 1.0,
 21: 1.0,
 22: 1.0,
 23: 1.0,
 24: 1.0,
 25: 1.0,
 26: 1.0,
 27: 1.0,
 28: 1.0,
 29: 1.0,
 30: 1.0,
 31: 1.0,
 32: 1.0,
 33: 1.0,
 34: 1.0,
 35: 1.0,
 36: 1.0,
 37: 1.0,
 38: 1.0,
 39: 1.0,
 40: 1.0,
 41: 1.0,
 42: 1.0,
 43: 1.0,
 44: 1.0,
 45: 1.0,
 46: 1.0,
 47: 1.0,
 48: 1.0,
 49: 1.0,
 50: 1.0,
 51: 1.0,
 52: 1.0,
 53: 1.0,
 54: 1.0,
 55: 1.0,
 56: 1.0,
 57: 1.0,
 58: 1.0,
 59: 1.0,
 60: 1.0,
 61: 1.0,
 62: 1.0,
 63: 1.0,
 64: 1.0,
 65: 1.0,
 66: 1.0,
 67: 1.0,
 68: 1.0,
 69: 1.0,
 70: 1.0,
 71: 1.0,
 72: 1.0,
 73: 1.0,
 74: 1.0,
 75: 1.0,
 76: 1.0,
 77: 1.0,
 78: 1.0,
 79: 1.0,
 80: 1.0,
 81: 1.0,
 82: 1.0,
 83: 1.0,
 84: 1.0,
 85: 1.0,
 86: 1.0,
 87: 1.0,
 88: 1.0,
 89: 1.0,
 90: 1.0,
 91: 1.0,
 92: 1.0,
 93: 1.0,
 94: 1.0,
 95: 1.0,
 96: 1.0,
 97: 1.0,
 98: 1.0,
 99: 1.0,
 100: 1.0,
 101: 1.0,
 102: 1.0,
 103: 1.0,
 104: 1.0,
 105: 1.0,
 106: 1.0,
 107: 1.0,
 108: 1.0,
 109: 1.0,
 110: 1.0,
 111: 1.0,
 112: 1.0,
 113: 1.0,
 114: 1.0,
 115: 1.0,
 116: 1.0,
 117: 1.0,
 118: 1.0,
 119: 1.0,
 120: 1.0,
 121: 1.0,
 122: 1.0,
 123: 1.0,
 124: 1.0,
 125: 1.0,
 126: 1.0,
 127: 1.0,
 128: 1.0,
 129: 1.0,
 130: 1.0,
 131: 1.0,
 132: 1.0,
 133: 1.0,
 134: 1.0,
 135: 1.0,
 136: 1.0,
 137: 1.0,
 138: 1.0,
 139: 1.0,
 140: 1.0,
 141: 1.0,
 142: 1.0,
 143: 1.0,
 144: 1.0,
 145: 1.0,
 146: 1.0,
 147: 1.0,
 148: 1.0,
 149: 1.0,
 150: 1.0,
 151: 1.0,
 152: 1.0,
 153: 1.0,
 154: 1.0,
 155: 1.0,
 156: 1.0,
 157: 1.0,
 158: 1.0,
 159: 1.0,
 160: 1.0,
 161: 1.0,
 162: 1.0,
 163: 1.0,
 164: 1.0,
 165: 1.0,
 166: 1.0,
 167: 1.0,
 168: 1.0,
 169: 1.0,
 170: 1.0,
 171: 1.0,
 172: 1.0,
 173: 1.0,
 174: 1.0,
 175: 1.0,
 176: 1.0,
 177: 1.0,
 178: 1.0,
 179: 1.0,
 180: 1.0,
 181: 1.0,
 182: 1.0,
 183: 1.0,
 184: 1.0,
 185: 1.0,
 186: 1.0,
 187: 1.0,
 188: 1.0,
 189: 1.0,
 190: 1.0,
 191: 1.0,
 192: 1.0,
 193: 1.0,
 194: 1.0,
 195: 1.0,
 196: 1.0,
 197: 1.0,
 198: 1.0,
 199: 1.0,
 200: 1.0,
 201: 1.0,
 202: 1.0,
 203: 1.0,
 204: 1.0,
 205: 1.0,
 206: 1.0,
 207: 1.0,
 208: 1.0,
 209: 1.0,
 210: 1.0,
 211: 1.0,
 212: 1.0,
 213: 1.0,
 214: 1.0,
 215: 1.0,
 216: 1.0,
 217: 1.0,
 218: 1.0,
 219: 1.0,
 220: 1.0,
 221: 1.0,
 222: 1.0,
 223: 1.0,
 224: 1.0,
 225: 1.0,
 226: 1.0,
 227: 1.0,
 228: 1.0,
 229: 1.0,
 230: 1.0,
 231: 1.0,
 232: 1.0,
 233: 1.0,
 234: 1.0,
 235: 1.0,
 236: 1.0,
 237: 1.0,
 238: 1.0,
 239: 1.0,
 240: 1.0,
 241: 1.0,
 242: 1.0,
 243: 1.0,
 244: 1.0,
 245: 1.0,
 246: 1.0,
 247: 1.0,
 248: 1.0,
 249: 1.0,
 250: 1.0,
 251: 1.0,
 252: 1.0,
 253: 1.0,
 254: 1.0,
 255: 1.0,
 256: 1.0,
 257: 1.0,
 258: 1.0,
 259: 1.0,
 260: 1.0,
 261: 1.0,
 262: 1.0,
 263: 1.0,
 264: 1.0,
 265: 1.0,
 266: 1.0,
 267: 1.0,
 268: 1.0,
 269: 1.0,
 270: 1.0,
 271: 1.0,
 272: 1.0,
 273: 1.0,
 274: 1.0,
 275: 1.0,
 276: 1.0,
 277: 1.0,
 278: 1.0,
 279: 1.0,
 280: 1.0,
 281: 1.0,
 282: 1.0,
 283: 1.0,
 284: 1.0,
 285: 1.0,
 286: 1.0,
 287: 1.0,
 288: 1.0,
 289: 1.0,
 290: 1.0,
 291: 1.0,
 292: 1.0,
 293: 1.0,
 294: 1.0,
 295: 1.0,
 296: 1.0,
 297: 1.0,
 298: 1.0,
 299: 1.0,
 300: 1.0,
 301: 1.0,
 302: 1.0,
 303: 1.0,
 304: 1.0,
 305: 1.0,
 306: 1.0,
 307: 1.0,
 308: 1.0,
 309: 1.0,
 310: 1.0,
 311: 1.0,
 312: 1.0,
 313: 1.0,
 314: 1.0,
 315: 1.0,
 316: 1.0,
 317: 1.0,
 318: 1.0,
 319: 1.0,
 320: 1.0,
 321: 1.0,
 322: 1.0,
 323: 1.0,
 324: 1.0,
 325: 1.0,
 326: 1.0,
 327: 1.0,
 328: 1.0,
 329: 1.0,
 330: 1.0,
 331: 1.0,
 332: 1.0,
 333: 1.0,
 334: 1.0,
 335: 1.0,
 336: 1.0,
 337: 1.0,
 338: 1.0,
 339: 1.0,
 340: 1.0,
 341: 1.0,
 342: 1.0,
 343: 1.0,
 344: 1.0,
 345: 1.0,
 346: 1.0,
 347: 1.0,
 348: 1.0,
 349: 1.0,
 350: 1.0,
 351: 1.0,
 352: 1.0,
 353: 1.0,
 354: 1.0,
 355: 1.0,
 356: 1.0,
 357: 1.0,
 358: 1.0,
 359: 1.0,
 360: 1.0,
 361: 1.0,
 362: 1.0,
 363: 1.0,
 364: 1.0,
 365: 1.0,
 366: 1.0,
 367: 1.0,
 368: 1.0,
 369: 1.0,
 370: 1.0,
 371: 1.0,
 372: 1.0,
 373: 1.0,
 374: 1.0,
 375: 1.0,
 376: 1.0,
 377: 1.0,
 378: 1.0,
 379: 1.0,
 380: 1.0,
 381: 1.0,
 382: 1.0,
 383: 1.0,
 384: 1.0,
 385: 1.0,
 386: 1.0,
 387: 1.0,
 388: 1.0,
 389: 1.0,
 390: 1.0,
 391: 1.0,
 392: 1.0,
 393: 1.0,
 394: 1.0,
 395: 1.0,
 396: 1.0,
 397: 1.0,
 398: 1.0,
 399: 1.0,
 400: 1.0,
 401: 1.0,
 402: 1.0,
 403: 1.0,
 404: 1.0,
 405: 1.0,
 406: 1.0,
 407: 1.0,
 408: 1.0,
 409: 1.0,
 410: 1.0,
 411: 1.0,
 412: 1.0,
 413: 1.0,
 414: 1.0,
 415: 1.0,
 416: 1.0,
 417: 1.0,
 418: 1.0,
 419: 1.0,
 420: 1.0,
 421: 1.0,
 422: 1.0,
 423: 1.0,
 424: 1.0,
 425: 1.0,
 426: 1.0,
 427: 1.0,
 428: 1.0,
 429: 1.0,
 430: 1.0,
 431: 1.0,
 432: 1.0,
 433: 1.0,
 434: 1.0,
 435: 1.0,
 436: 1.0,
 437: 1.0,
 438: 1.0,
 439: 1.0,
 440: 1.0,
 441: 1.0,
 442: 1.0,
 443: 1.0,
 444: 1.0,
 445: 1.0,
 446: 1.0,
 447: 1.0,
 448: 1.0,
 449: 1.0,
 450: 1.0,
 451: 1.0,
 452: 1.0,
 453: 1.0,
 454: 1.0,
 455: 1.0,
 456: 1.0,
 457: 1.0,
 458: 1.0,
 459: 1.0,
 460: 1.0,
 461: 1.0,
 462: 1.0,
 463: 1.0,
 464: 1.0,
 465: 1.0,
 466: 1.0,
 467: 1.0,
 468: 1.0,
 469: 1.0,
 470: 1.0,
 471: 1.0,
 472: 1.0,
 473: 1.0,
 474: 1.0,
 475: 1.0,
 476: 1.0,
 477: 1.0,
 478: 1.0,
 479: 1.0,
 480: 1.0,
 481: 1.0,
 482: 1.0,
 483: 1.0,
 484: 1.0,
 485: 1.0,
 486: 1.0,
 487: 1.0,
 488: 1.0,
 489: 1.0,
 490: 1.0,
 491: 1.0,
 492: 1.0,
 493: 1.0,
 494: 1.0,
 495: 1.0,
 496: 1.0,
 497: 1.0,
 498: 1.0,
 499: 1.0}

For example, the time spent in patient \(j=5\) by tandem \(i=1\), i.e. \(t_{15}\), is:

t_optimal[0,4] # 0 h
0.0

Objective function

In this case the optimal value for the objective function is the following:

f_optimal
2316.5991200000026

Time spent in patients#

Now we are going to analyze the time spent in the patients, in this particular case.

We built a function that computes the time spent seeing patient j in a given day . It’s important to notice that a patient could be seen by several nurse-doctor tandems.

# Time spent seeing patient j in a given day (he could be seen by several nurse-doctor tandems).
def time_seeing_patient(j):
    return np.sum([t_optimal[i, j] for i in range(0,n)])

For example, total time spent in patient \(j=45\), that is, \(\sum_{i=1}^n t_{i45}\), is the following:

time_seeing_patient(44)
0.8

Using the previous function we can collect the total time spent in each patient in an array.

total_times_per_patient = np.array([time_seeing_patient(j) for j in range(0,p)])
total_times_per_patient
array([3.000000e-01, 3.000000e-01, 8.000000e-01, 1.000000e-06,
       3.000000e-01, 1.000000e+00, 8.000000e-01, 1.000000e-06,
       1.000000e-06, 1.000000e-06, 1.000000e+00, 1.000000e-06,
       1.000000e-06, 1.000000e+00, 3.000000e-01, 5.500000e-01,
       1.000000e-06, 1.000000e-06, 5.500000e-01, 1.000000e-06,
       8.000000e-01, 3.000000e-01, 3.000000e-01, 5.500000e-01,
       8.000000e-01, 3.000000e-01, 5.500000e-01, 1.000000e+00,
       1.000000e-06, 8.000000e-01, 1.000000e+00, 3.000000e-01,
       5.500000e-01, 8.000000e-01, 1.000000e-06, 5.500000e-01,
       8.000000e-01, 3.000000e-01, 1.000000e-06, 1.000000e+00,
       3.000000e-01, 5.500000e-01, 1.000000e-06, 3.000000e-01,
       8.000000e-01, 3.000000e-01, 5.500000e-01, 5.500000e-01,
       8.000000e-01, 3.000000e-01, 1.000000e-06, 8.000000e-01,
       5.500000e-01, 8.000000e-01, 8.000000e-01, 8.000000e-01,
       1.000000e-06, 5.500000e-01, 8.000000e-01, 1.000000e+00,
       3.000000e-01, 5.500000e-01, 1.000000e+00, 1.000000e-06,
       3.000000e-01, 1.000000e-06, 1.000000e-06, 3.000000e-01,
       5.500000e-01, 1.000000e+00, 1.000000e-06, 1.000000e+00,
       1.000000e-06, 8.000000e-01, 3.000000e-01, 3.000000e-01,
       5.500000e-01, 1.000000e+00, 8.000000e-01, 1.000000e+00,
       3.000000e-01, 3.000000e-01, 3.000000e-01, 3.000000e-01,
       1.000000e+00, 8.000000e-01, 1.000000e+00, 8.000000e-01,
       8.000000e-01, 3.000000e-01, 1.000000e+00, 8.000000e-01,
       8.000000e-01, 8.000000e-01, 1.000000e-06, 3.000000e-01,
       5.500000e-01, 3.000000e-01, 1.000000e-06, 1.000000e-06,
       5.500000e-01, 1.000000e+00, 8.000000e-01, 1.000000e+00,
       1.000000e+00, 1.000000e-06, 1.000000e-06, 3.000000e-01,
       1.000000e-06, 3.000000e-01, 5.500000e-01, 8.000000e-01,
       8.000000e-01, 1.000000e-06, 5.500000e-01, 3.000000e-01,
       3.000000e-01, 8.000000e-01, 8.000000e-01, 1.000000e+00,
       8.000000e-01, 5.500000e-01, 5.500000e-01, 8.000000e-01,
       1.000000e-06, 1.000000e-06, 1.000000e+00, 1.000000e+00,
       1.000000e+00, 5.500000e-01, 1.000000e+00, 8.000000e-01,
       1.000000e-06, 8.000000e-01, 1.000000e+00, 8.000000e-01,
       1.000000e+00, 1.000000e-06, 8.000000e-01, 1.000000e-06,
       8.000000e-01, 1.000000e+00, 1.000000e+00, 8.000000e-01,
       1.000000e-06, 3.000000e-01, 1.000000e-06, 1.000000e+00,
       8.000000e-01, 5.500000e-01, 1.000000e-06, 3.000000e-01,
       5.500000e-01, 3.000000e-01, 3.000000e-01, 1.000000e+00,
       3.000000e-01, 3.000000e-01, 8.000000e-01, 8.000000e-01,
       1.000000e+00, 1.000000e-06, 3.000000e-01, 1.000000e+00,
       3.000000e-01, 8.000000e-01, 1.000000e+00, 1.000000e+00,
       3.000000e-01, 3.000000e-01, 5.500000e-01, 8.000000e-01,
       1.000000e-06, 1.000000e+00, 8.000000e-01, 8.000000e-01,
       5.500000e-01, 5.500000e-01, 5.500000e-01, 1.000000e-06,
       1.000000e+00, 1.000000e+00, 3.000000e-01, 5.500000e-01,
       1.000000e-06, 5.500000e-01, 1.000000e+00, 3.000000e-01,
       5.500000e-01, 3.000000e-01, 1.000000e-06, 3.000000e-01,
       8.000000e-01, 8.000000e-01, 3.000000e-01, 5.500000e-01,
       1.000000e-06, 8.000000e-01, 5.500000e-01, 1.000000e+00,
       1.000000e-06, 3.000000e-01, 1.000000e+00, 5.500000e-01,
       1.000000e-06, 1.000000e+00, 3.000000e-01, 3.000000e-01,
       3.000000e-01, 1.000000e-06, 8.000000e-01, 8.000000e-01,
       3.000000e-01, 1.000000e-06, 8.000000e-01, 3.000000e-01,
       8.000000e-01, 5.500000e-01, 1.000000e+00, 1.000000e+00,
       1.000000e+00, 5.500000e-01, 8.000000e-01, 1.000000e+00,
       5.500000e-01, 1.000000e+00, 3.000000e-01, 5.500000e-01,
       3.000000e-01, 3.000000e-01, 1.000000e-06, 8.000000e-01,
       1.000000e+00, 5.500000e-01, 8.000000e-01, 8.000000e-01,
       8.000000e-01, 5.500000e-01, 1.000000e-06, 1.000000e-06,
       1.000000e+00, 1.000000e-06, 1.000000e-06, 5.500000e-01,
       5.500000e-01, 5.500000e-01, 5.500000e-01, 1.000000e-06,
       8.000000e-01, 1.000000e-06, 3.000000e-01, 3.000000e-01,
       8.000000e-01, 8.000000e-01, 3.000000e-01, 8.000000e-01,
       1.000000e-06, 1.000000e+00, 5.500000e-01, 1.000000e-06,
       8.000000e-01, 5.500000e-01, 1.000000e+00, 1.000000e-06,
       3.000000e-01, 1.000000e-06, 3.000000e-01, 8.000000e-01,
       8.000000e-01, 8.000000e-01, 5.500000e-01, 3.000000e-01,
       8.000000e-01, 3.000000e-01, 5.500000e-01, 1.000000e-06,
       5.500000e-01, 1.000000e+00, 1.000000e-06, 3.000000e-01,
       1.000000e+00, 1.000000e-06, 5.500000e-01, 8.000000e-01,
       1.000000e-06, 5.500000e-01, 1.000000e-06, 8.000000e-01,
       1.000000e-06, 3.000000e-01, 1.000000e-06, 8.000000e-01,
       3.000000e-01, 8.000000e-01, 5.500000e-01, 1.000000e-06,
       1.000000e-06, 1.000000e-06, 3.000000e-01, 8.000000e-01,
       5.500000e-01, 1.000000e+00, 1.000000e-06, 5.500000e-01,
       3.000000e-01, 8.000000e-01, 5.500000e-01, 8.000000e-01,
       1.000000e-06, 8.000000e-01, 1.000000e-06, 3.000000e-01,
       1.000000e-06, 3.000000e-01, 1.000000e-06, 1.000000e+00,
       5.500000e-01, 1.000000e-06, 5.500000e-01, 3.000000e-01,
       3.000000e-01, 3.000000e-01, 1.000000e-06, 3.000000e-01,
       1.000000e-06, 3.000000e-01, 8.000000e-01, 1.000000e+00,
       1.000000e-06, 3.000000e-01, 1.000000e+00, 8.000000e-01,
       1.000000e-06, 5.500000e-01, 5.500000e-01, 8.000000e-01,
       1.000000e-06, 8.000000e-01, 1.000000e+00, 1.000000e+00,
       1.000000e-06, 1.000000e-06, 1.000000e-06, 8.000000e-01,
       5.500000e-01, 3.000000e-01, 1.000000e-06, 5.500000e-01,
       1.000000e+00, 5.500000e-01, 1.000000e+00, 3.000000e-01,
       5.500000e-01, 1.000000e-06, 1.000000e+00, 1.000000e-06,
       1.000000e+00, 1.000000e-06, 5.500000e-01, 1.000000e+00,
       1.000000e+00, 5.500000e-01, 8.000000e-01, 1.000000e+00,
       8.000000e-01, 4.000000e+00, 3.000000e-01, 1.000000e-06,
       1.000000e-06, 2.449896e+00, 4.000000e+00, 5.500000e-01,
       3.000000e-01, 5.500000e-01, 5.500000e-01, 3.000000e-01,
       3.000000e-01, 8.000000e-01, 3.000000e-01, 1.000000e-06,
       3.000000e-01, 4.000000e+00, 3.000000e-01, 8.000000e-01,
       3.000000e-01, 3.000000e-01, 1.000000e-06, 4.000000e+00,
       1.000000e+00, 1.000000e-06, 3.000000e-01, 3.000000e-01,
       8.000000e-01, 4.000000e+00, 3.000000e-01, 8.000000e-01,
       4.000000e+00, 8.000000e-01, 1.000000e-06, 5.500000e-01,
       8.000000e-01, 5.500000e-01, 8.000000e-01, 1.000000e+00,
       1.000000e-06, 3.000000e-01, 8.000000e-01, 5.500000e-01,
       3.000000e-01, 8.000000e-01, 3.000000e-01, 8.000000e-01,
       1.000000e-06, 8.000000e-01, 8.000000e-01, 1.000000e+00,
       8.000000e-01, 1.000000e+00, 1.000000e-06, 5.500000e-01,
       3.000000e-01, 3.000000e-01, 5.500000e-01, 3.000000e-01,
       3.000000e-01, 4.000000e+00, 8.000000e-01, 1.000000e-06,
       1.000000e+00, 1.000000e-06, 1.000000e-06, 5.500000e-01,
       8.000000e-01, 3.000000e-01, 5.500000e-01, 1.000000e+00,
       3.000000e-01, 5.500000e-01, 4.000000e+00, 8.000000e-01,
       3.000000e-01, 8.000000e-01, 8.000000e-01, 8.000000e-01,
       5.500000e-01, 8.000000e-01, 1.000000e+00, 5.500000e-01,
       1.000000e-06, 8.000000e-01, 8.000000e-01, 3.000000e-01,
       5.500000e-01, 1.000000e-06, 1.000000e-06, 8.000000e-01,
       3.000000e-01, 8.000000e-01, 1.000000e+00, 4.000000e+00,
       5.500000e-01, 5.500000e-01, 5.500000e-01, 8.000000e-01,
       8.000000e-01, 4.000000e+00, 4.000000e+00, 5.500000e-01,
       1.000000e-06, 5.500000e-01, 5.500000e-01, 1.000000e+00,
       4.000000e+00, 5.500000e-01, 1.000000e-06, 1.000000e-06,
       8.000000e-01, 1.000000e-06, 4.000000e+00, 5.500000e-01,
       8.000000e-01, 5.500000e-01, 5.500000e-01, 3.000000e-01,
       5.500000e-01, 8.000000e-01, 3.000000e-01, 5.500000e-01,
       3.000000e-01, 5.500000e-01, 3.000000e-01, 3.000000e-01,
       5.500000e-01, 1.000000e+00, 1.000000e-06, 8.000000e-01,
       1.000000e+00, 1.000000e+00, 5.500000e-01, 8.000000e-01])

Average time spent per patient#

Now we can compute some statistics over the time spent in patients, like for example the average time spent per patient.

np.mean(total_times_per_patient)
0.6

Max time spent per patient#

The maximum time spent in a single patient is enforced by \(h_4\) constriant, that in this case has been fixed to \(4\).

np.max(total_times_per_patient) # 4 hours
4.000000000000004

Min time spent per patient#

The minimun time spent in a single patient is set by \(h_3^{12}\), in this case, that has been fixed to \(0.1\).

np.min(total_times_per_patient) 
1e-06

Median of time spent per patient#

np.median(total_times_per_patient) 
0.55

\(75\)-quantile of time spent per patient#

np.quantile(total_times_per_patient, 0.75)
0.8

\(25\)-quantile time spent per patient#

np.quantile(total_times_per_patient, 0.25)
0.3

Number of patients seen#

Another interesting statistic to compute is the number of patients seen. This can be calculated as the number of non zero values in the array total_times_per_patient.

The number of patients seen is \(p=500\) even though we have set \(h_3^{12}=0\), so the new constraint is working well. In addition, we can see as the number of patient seen match with \(\sum_{j=1}^p y_j\), which is something that must always be fulfilled in this new version of the problem.

np.sum(total_times_per_patient > 0)
500
np.sum(list(y_optimal.values()))
500.0

Relation between total time per patients and theis severity/importance \((w)\)#

We can do a simple analysis of the relationship between the time spent per patient and the severity/importance of the patient.

For example, we can compute the Pearson linear correlation coefficient between this two variables.

pearsonr(w, total_times_per_patient)
PearsonRResult(statistic=0.7226412439587873, pvalue=6.657899664357222e-82)

A linear correlation of \(0.74\) indicates a high positive linear relationship between the time spent per patient and their severity/importance.

We can make an scatter plot of both variables to visualize this relationship.

plt.figure(figsize=(8, 5))
ax = sns.scatterplot(x=w, y=total_times_per_patient, color='red')
plt.title('w vs time per patient', size=15)
ax.set_ylabel('time per patient', size=11)
ax.set_xlabel('w', size=11)
plt.xticks(np.unique(w))
plt.show()
_images/95be5ad5cce6667ee011a0b7db610ef588842d3a51d5af334e221dad7f2d75d2.png

It’s important to realize that the points are overlapped, since there are \(500\) patients and only \(13\) points are visible.

Analysis of sensitivity#

Analysis of individual parameters#

In this section we make a sensitivity analysis of some of the parameters of the problem, following an individual approach, in the sense that each parameter will be analyzed separately.

This analysis is essentially carried out using the functions get_results1 and get_results2.

Analysis of \(h_1\) parameter#

  • \(h_1 :=\) maximum time seeing patients per nurse-doctor tandem in a given day.

# Defining the values of the rest of parameters and setting h1 as None.
params['n'] = 50 ; params['p']=500 ; params['h1']=None ; params['h2']=1 ; params['h4']=4
params['h3_1_2'] = 0
params['h3_3_4'] = 0.30 
params['h3_5_6'] = 0.55  
params['h3_7_8'] = 0.80 
params['h3_9_10'] = 1 

np.random.seed(123)
params['w'] = np.random.randint(1, 11, params['p']) 

# Defining the parameter values list.
parameter_list = np.arange(2, 13)

Now we are going to use te results stored in results1_IM and results2_IM to make some valuable plots, in order to analyze the influence of the \(h_1\) parameter in the hospital integer (binary) model.

results1 = get_results1('h1', parameter_list, params, model='integer')
results2 = get_results2('h1', parameter_list, results1)
plt.figure(figsize=(8, 5))
ax = sns.scatterplot(y=results2['h1']['type'], x=parameter_list, color='red', s=200)
plt.title('type vs h1', size=15)
ax.set_ylabel('type', size=12)
ax.set_xlabel('h1', size=12)
plt.xticks(parameter_list, fontsize=12)
plt.yticks(fontsize=11)
plt.show()
_images/e47af41b14f4c68a1bdef1a058424865e20c0d58c14ecbefe7e67f0809ae0f80.png

Interpretation of the results:

Analogous interpretation to the one made for the linear model.

  • Number of patients seen vs \(h_1\)

plt.figure(figsize=(8, 5))
ax = sns.lineplot(y=results2['h1']['num_patients_seen'].values(), x=results2['h1']['feasible'], 
                  marker='o', markersize=7.5, color='red')
plt.title('number of patients seen vs h1', size=15)
ax.set_ylabel('number of patients seen', size=12)
ax.set_xlabel('h1', size=12)
plt.xticks(results2['h1']['feasible'], fontsize=12)
plt.yticks(fontsize=11)
plt.show()
_images/191d8ffb844a265ad1ed96be0a9cffcfd98b1887256be6411951917a2bac9e5f.png

Interpretation of the results:

In this case is not trivial that the number of patients seen is the maximum possible \((=p)\), since \(h_3^{12}=0\) unlike the analogous analysis performed with the linear model. This indicates that the new binary variable and the new constraint are working well.

  • Optimal value of the objective function vs \(h_1\)

plt.figure(figsize=(8, 5))
ax = sns.lineplot(y=results2['h1']['f_optimal_feasible'].values(), x=results2['h1']['feasible'], marker='o', markersize=7.5, color='red')
plt.title('$f$ optimal vs $h_1$', size=15)
ax.set_ylabel('$f$ optimal', size=12)
ax.set_xlabel('$h_1$', size=12)
plt.xticks(results2['h1']['feasible'], fontsize=12)
plt.yticks(fontsize=11)
plt.show()
_images/767d38338d04bea7e3efd89debea10e938ea5082865230b416db21cc897fb38a.png

Interpretation of the results:

Analogous interpretation to the one made for the linear model.

  • Average time spent per patient vs \(h_1\)

plt.figure(figsize=(8, 5))
ax = sns.lineplot(y=results2['h1']['avg_time_per_patient'].values(), x=results2['h1']['feasible'], marker='o', markersize=7.5, color='red')
plt.title('Avg. time per patient vs $h_1$', size=15)
ax.set_ylabel('Avg. time per patient', size=12)
ax.set_xlabel('$h_1$', size=12)
plt.xticks(results2['h1']['feasible'], fontsize=12)
plt.yticks(fontsize=11)
plt.show()
_images/5c195829c53c7e230e28cc74b8d6ebcfb309cb4227775d98c1620d519839d5e9.png

Interpretation of the results:

Analogous interpretation to the one made for the linear model.

  • Median time spent per patient vs \(h_1\)

plt.figure(figsize=(8, 5))
ax = sns.lineplot(y=results2['h1']['median_time_per_patient'].values(), x=results2['h1']['feasible'], marker='o', markersize=7.5, color='red')
plt.title('Median time per patient vs $h_1$', size=15)
ax.set_ylabel('Median time per patient', size=12)
ax.set_xlabel('$h_1$', size=12)
plt.xticks(results2['h1']['feasible'], fontsize=12)
plt.yticks(fontsize=11)
plt.show()
_images/55b9da42327108c12eb08b07417ed275fb148a3d497e004879b4c0a70236f448.png

Interpretation of the results:

Analogous interpretation to the one made for the linear model.

  • \(75\)-quantile time spent per patient vs \(h_1\)

plt.figure(figsize=(8, 5))
ax = sns.lineplot(y=results2['h1']['Q75_time_per_patient'].values(), x=results2['h1']['feasible'], marker='o', markersize=7.5, color='red')
plt.title('Q75 time per patient vs $h_1$', size=15)
ax.set_ylabel('Q75 time per patient', size=12)
ax.set_xlabel('$h_1$', size=12)
plt.xticks(results2['h1']['feasible'], fontsize=12)
plt.yticks(fontsize=11)
plt.show()
_images/37755132b3c6107d30a0e312bb58488fb9b683e9f77d360ca402884eadf5fd78.png

Interpretation of the results:

Analogous interpretation to the one made for the linear model.

  • \(25\)-quantile time spent per patient vs \(h_1\)

plt.figure(figsize=(8, 5))
ax = sns.lineplot(y=results2['h1']['Q25_time_per_patient'].values(), x=results2['h1']['feasible'], marker='o', markersize=7.5, color='red')
plt.title('Q25 time per patient vs $h_1$', size=15)
ax.set_ylabel('Q25 time per patient', size=12)
ax.set_xlabel('$h_1$', size=12)
plt.xticks(results2['h1']['feasible'], fontsize=12)
plt.yticks(fontsize=11)
plt.show()
_images/03acb026df6cc850a570550951d2178feeca24d780cf7c198973913348169f2f.png

Interpretation of the results:

Analogous interpretation to the one made for the linear model.

  • Average time spent per patient vs \(w\) vs \(h_1\)

plt.figure(figsize=(8, 5))
for i, h1 in zip(results2['h1']['avg_time_patient_per_w'].keys(), results2['h1']['feasible']) :
    ax = sns.lineplot(y=results2['h1']['avg_time_patient_per_w'][i].values(), x=results2['h1']['avg_time_patient_per_w'][i].keys(), 
                      label=h1, marker='o', markersize=6)
plt.title('Avg. time per patient vs $w$ vs $h_1$', size=15)
ax.set_ylabel('Avg. time per patient', size=12)
ax.set_xlabel('$w$', size=12)
plt.xticks(list(results2['h1']['avg_time_patient_per_w'][i].keys()), fontsize=12)
plt.yticks(fontsize=11)
plt.legend(title='$h_1$', loc='upper right', bbox_to_anchor=(1.2, 1), fontsize=11)
plt.show()
_images/181849cf52cfb4b2efc2044e2178de001ac3bef5f6c48257c93329b1cd1657b0.png

Interpretation of the results:

Analogous interpretation to the one made for the linear model.

Analysis of \(h_2\) parameter#

  • \(h_2 :=\) maximum time spent by nurse-doctor tandem \(i\) seeing the patient \(j\), for all \(i,j\).

params['n'] = 50 ; params['p']=500 ; params['h1']=6 ; params['h2']=None ; params['h4']=4
params['h3_1_2'] = 0
params['h3_3_4'] = 0.30 
params['h3_5_6'] = 0.55  
params['h3_7_8'] = 0.80 
params['h3_9_10'] = 1 

np.random.seed(123)
params['w'] = np.random.randint(1, 11, params['p']) 

parameter_list = np.round(np.arange(0.4, 2.2, 0.2), 2)
results1 = get_results1('h2', parameter_list, params, model='integer')
results2 = get_results2('h2', parameter_list, results1)
  • Problem type (feasible - not feasible) vs \(h_2\)

plt.figure(figsize=(8, 5))
ax = sns.scatterplot(y=results2['h2']['type'], x=parameter_list, color='red', s=200)
plt.title('type vs h2', size=15)
ax.set_ylabel('type', size=12)
ax.set_xlabel('h2', size=12)
plt.xticks(parameter_list, fontsize=12)
plt.yticks(fontsize=11)
plt.show()
_images/2628c1c37cf38b6171f1290052bab49111f2508af2a511ce0bb93f68fcd9361e.png

Interpretation of the results:

Analogous interpretation to the one made for the linear model.

  • Number of patients seen vs \(h_2\)

plt.figure(figsize=(8, 5))
ax = sns.lineplot(y=results2['h2']['num_patients_seen'].values(), x=results2['h2']['feasible'], marker='o', markersize=7.5, color='red')
plt.title('number of patients seen vs h2', size=15)
ax.set_ylabel('number of patients seen', size=12)
ax.set_xlabel('h2', size=12)
plt.xticks(results2['h2']['feasible'], fontsize=12)
plt.yticks(fontsize=11)
plt.show()
_images/047a227d5b86c3cf295d8d3f3dee0e2e4dfd809595e785d2a515fba0a6529a3d.png

Interpretation of the results:

Analogous interpretation to the one made for \(h_1\).

  • Optimal value of the objective function vs \(h_2\)

plt.figure(figsize=(8, 5))
ax = sns.lineplot(y=np.round(list(results2['h2']['f_optimal_feasible'].values()), 3), x=results2['h2']['feasible'], marker='o', markersize=7.5, color='red')
plt.title('$f$ optimal vs $h_2$', size=15)
ax.set_ylabel('$f$ optimal', size=12)
ax.set_xlabel('$h_2$', size=12)
plt.xticks(results2['h2']['feasible'], fontsize=12)
plt.yticks(fontsize=11)
plt.show()
_images/ee73cab7a0236eb59d6f53d694792ac474f76a257595c2a722b9af6e4aea2e85.png

Interpretation of the results:

Analogous interpretation to the one made for the linear model.

  • Average time spent per patient vs \(h_2\)

plt.figure(figsize=(8, 5))
ax = sns.lineplot(y=results2['h2']['avg_time_per_patient'].values(), x=results2['h2']['feasible'], marker='o', markersize=7.5, color='red')
plt.title('Avg. time per patient vs $h_2$', size=15)
ax.set_ylabel('Avg. time per patient', size=12)
ax.set_xlabel('$h_2$', size=12)
plt.xticks(results2['h2']['feasible'], fontsize=12)
plt.yticks(fontsize=11)
plt.show()
_images/0c767c45fc31e43780c10a354378d84a662f86121b25fe45a59d88e177a53b5c.png

Interpretation of the results:

Analogous interpretation to the one made for the linear model.

  • Median time spent per patient vs \(h_2\)

plt.figure(figsize=(8, 5))
ax = sns.lineplot(y=results2['h2']['median_time_per_patient'].values(), x=results2['h2']['feasible'], marker='o', markersize=7.5, color='red')
plt.title('Median time per patient vs $h_2$', size=15)
ax.set_ylabel('Median time per patient', size=12)
ax.set_xlabel('$h_2$', size=12)
plt.xticks(results2['h2']['feasible'], fontsize=12)
plt.yticks(fontsize=11)
plt.show()
_images/1bc576dcea30da32de19b66a70f3728e71e1b1235b7a5a581cd947f4ab2dc283.png

Interpretation of the results:

Analogous interpretation to the one made for the linear model.

  • \(75\)-quantile of time spent per patient vs \(h_2\)

plt.figure(figsize=(8, 5))
ax = sns.lineplot(y=results2['h2']['Q75_time_per_patient'].values(), x=results2['h2']['feasible'], marker='o', markersize=7.5, color='red')
plt.title('Q75 time per patient vs $h_2$', size=15)
ax.set_ylabel('Q75 time per patient', size=12)
ax.set_xlabel('$h_2$', size=12)
plt.xticks(results2['h2']['feasible'], fontsize=12)
plt.yticks(fontsize=11)
plt.show()
_images/a592fd27fc462c4493800b028fa026a518d62e41e3970b3c4d393f2aa2e23adf.png

Interpretation of the results:

Analogous interpretation to the one made for the linear model.

  • \(25\)-quantile of time spent per patient vs \(h_2\)

plt.figure(figsize=(8, 5))
ax = sns.lineplot(y=results2['h2']['Q25_time_per_patient'].values(), x=results2['h2']['feasible'], marker='o', markersize=7.5, color='red')
plt.title('Q25 time per patient vs $h_2$', size=15)
ax.set_ylabel('Q25 time per patient', size=12)
ax.set_xlabel('$h_2$', size=12)
plt.xticks(results2['h2']['feasible'], fontsize=12)
plt.yticks(fontsize=11)
plt.show()
_images/0d6810d9211f1a4b65f9e903af31ea915638e1bc6a3344b6dc2233bf9c406a7d.png

Interpretation of the results:

Analogous interpretation to the one made for the linear model.

  • Average time spent per patient vs \(w\) vs \(h_2\)

plt.figure(figsize=(8, 5))
for i, h2 in zip(results2['h2']['avg_time_patient_per_w'].keys(), results2['h2']['feasible']) :
    ax = sns.lineplot(y=results2['h2']['avg_time_patient_per_w'][i].values(), x=results2['h2']['avg_time_patient_per_w'][i].keys(), 
                      label=h2, marker='o', markersize=6)
plt.title('Avg. time per patient vs $w$ vs $h_2$', size=15)
ax.set_ylabel('Avg. time per patient', size=12)
ax.set_xlabel('$w$', size=12)
plt.xticks(list(results2['h2']['avg_time_patient_per_w'][i].keys()), fontsize=12)
plt.yticks(fontsize=11)
plt.legend(title='$h_2$', loc='upper right', bbox_to_anchor=(1.2, 1), fontsize=11)
plt.show()
_images/389df60707762b41f916db3bf3cf59222cb6e7d9d8858cdd5657e59c63147a2a.png

Interpretation of the results:

Analogous interpretation to the one made for the linear model.

Analysis of \(h_3\) parameter#

\(h_3 :=\) minimum time time spent in each patient, taking into account their severity/importance (this quantity depends on \(w_j\)).

\(h_3^{12}\) parameter#

\(h_3^{12} :=\) minimum time time spent in patients with \(w_j \in \lbrace 1, 2 \rbrace\)

params['n'] = 50 ; params['p']=500 ; params['h1']=6 ; params['h2']=1 ; params['h4']=4
params['h3_1_2'] = None 
params['h3_3_4'] = 0.30 
params['h3_5_6'] = 0.55  
params['h3_7_8'] = 0.80 
params['h3_9_10'] = 1 

np.random.seed(123)
params['w'] = np.random.randint(1, 11, params['p']) 

parameter_list = np.arange(0, 0.50, 0.05)
results1 = get_results1('h3_1_2', parameter_list, params, model='integer')
results2 = get_results2('h3_1_2', parameter_list, results1)
  • Problem type (feasible - not feasible) vs \(h_3^{12}\)

plt.figure(figsize=(8, 5))
ax = sns.scatterplot(y=results2['h3_1_2']['type'], x=parameter_list, color='red', s=200)
plt.title('type vs $h_3^{12}$', size=15)
ax.set_ylabel('type', size=12)
ax.set_xlabel('$h_3^{12}$', size=12)
plt.xticks(parameter_list, fontsize=12)
plt.yticks(fontsize=11)
plt.show()
_images/0d45a81bba1e906f1617cdf4b0f01a6d12a02aa87125f06912d4f47805f48bba.png

Interpretation of the results:

Analogous interpretation to the one made for the linear model.

  • Number of patients seen vs \(h_3^{12}\)

plt.figure(figsize=(8, 5))
ax = sns.lineplot(y=results2['h3_1_2']['num_patients_seen'].values(), x=results2['h3_1_2']['feasible'], 
                  marker='o', markersize=7.5, color='red')
plt.title('number of patients seen vs h3_1_2', size=15)
ax.set_ylabel('number of patients seen', size=12)
ax.set_xlabel('h3_1_2', size=12)
plt.xticks(results2['h3_1_2']['feasible'], fontsize=12)
plt.yticks(fontsize=11)
plt.show()
_images/4f73abb511d7b850dcacf750ca9ad4f96aecbcce23781de974c48045dacf5938.png

Interpretation of the results:

Even when \(h_3^{12}=0\), the number of patients seen is the maximum possible \((p)\), thanks to the new constraint added in the binary model.

  • Optimal value of the objective function vs \(h_3^{12}\)

plt.figure(figsize=(8, 5))
ax = sns.lineplot(y=results2['h3_1_2']['f_optimal_feasible'].values(), x=results2['h3_1_2']['feasible'], marker='o', markersize=7.5, color='red')
plt.title('$f$ optimal vs $h_3^{12}$', size=15)
ax.set_ylabel('$f$ optimal', size=12)
ax.set_xlabel('$h_3^{12}$', size=12)
plt.xticks(results2['h3_1_2']['feasible'], fontsize=12)
plt.yticks(fontsize=11)
plt.show()
_images/385b1fcd9852e0e6927a937144031c5f2c631984231fbeee9259b95a926d773b.png

Interpretation of the results:

Analogous interpretation to the one made for the linear model.

  • Average time spent per patient vs \(h_3^{12}\)

plt.figure(figsize=(8, 5))
ax = sns.lineplot(y=results2['h3_1_2']['avg_time_per_patient'].values(), x=results2['h3_1_2']['feasible'], marker='o', markersize=7.5, color='red')
plt.title('Avg. time per patient vs $h_3^{12}$', size=15)
ax.set_ylabel('Avg. time per patient', size=12)
ax.set_xlabel('$h_3^{12}$', size=12)
plt.xticks(results2['h3_1_2']['feasible'], fontsize=12)
plt.yticks(fontsize=11)
plt.show()
_images/2036463fef5824fda35391c958a59f9c9929ce31a1f87d78520bd3f0920b2de1.png

Interpretation of the results:

Analogous interpretation to the one made for the linear model.

  • Median time spent per patient vs \(h_3^{12}\)

plt.figure(figsize=(8, 5))
ax = sns.lineplot(y=results2['h3_1_2']['median_time_per_patient'].values(), x=results2['h3_1_2']['feasible'], marker='o', markersize=7.5, color='red')
plt.title('Median time per patient vs $h_3^{12}$', size=15)
ax.set_ylabel('Median time per patient', size=12)
ax.set_xlabel('$h_3^{12}$', size=12)
plt.xticks(results2['h3_1_2']['feasible'], fontsize=12)
plt.yticks(fontsize=11)
plt.show()
_images/7257e7633ccafb55596865fab5e73e7a14e40608cdce52474b447d0cc324f5bf.png

Interpretation of the results:

Analogous interpretation to the one made for the linear model.

  • \(75\)-quantile time spent per patient vs \(h_3^{12}\)

plt.figure(figsize=(8, 5))
ax = sns.lineplot(y=results2['h3_1_2']['Q75_time_per_patient'].values(), x=results2['h3_1_2']['feasible'], marker='o', markersize=7.5, color='red')
plt.title('Q75 time per patient vs $h_3^{12}$', size=15)
ax.set_ylabel('Q75 time per patient', size=12)
ax.set_xlabel('$h_3^{12}$', size=12)
plt.xticks(results2['h3_1_2']['feasible'], fontsize=12)
plt.yticks(fontsize=11)
plt.show()
_images/c97be5cd6931b30940e3431fc15f7987a0563c3d77b8d0494e4cbb52af63323a.png

Interpretation of the results:

Analogous interpretation to the one made for the linear model.

  • \(25\)-quantile time spent per patient vs \(h_3^{12}\)

plt.figure(figsize=(8, 5))
ax = sns.lineplot(y=results2['h3_1_2']['Q25_time_per_patient'].values(), x=results2['h3_1_2']['feasible'], marker='o', markersize=7.5, color='red')
plt.title('Q25 time per patient vs $h_3^{12}$', size=15)
ax.set_ylabel('Q25 time per patient', size=12)
ax.set_xlabel('$h_3^{12}$', size=12)
plt.xticks(results2['h3_1_2']['feasible'], fontsize=12)
plt.yticks(fontsize=11)
plt.show()
_images/0965890f2ab22fe5308ce75a5e6734b5609808e78c1cc417086417e70a13d629.png

Interpretation of the results:

Analogous interpretation to the one made for the linear model.

  • Average time spent per patient vs \(w\) vs \(h_3^{12}\)

plt.figure(figsize=(9, 6))
for i, h3_1_2 in zip(results2['h3_1_2']['avg_time_patient_per_w'].keys(), results2['h3_1_2']['feasible']) :
    ax = sns.lineplot(y=results2['h3_1_2']['avg_time_patient_per_w'][i].values(), x=results2['h3_1_2']['avg_time_patient_per_w'][i].keys(), 
                      label=round(h3_1_2,2), marker='o', markersize=6)
plt.title('Avg. time per patient vs $w$ vs $h_3^{12}$', size=15)
ax.set_ylabel('Avg. time per patient', size=12)
ax.set_xlabel('$w$', size=12)
plt.xticks(list(results2['h3_1_2']['avg_time_patient_per_w'][i].keys()), fontsize=12)
plt.yticks(np.arange(0,2, 0.15), fontsize=11)
plt.legend(title='$h_3^{12}$', loc='upper right', bbox_to_anchor=(1.2, 1), fontsize=11)
plt.show()
_images/69b56a4714aacd8baf313976f305dc629b03509b33575a3cc140251ca9e4ac20.png

Interpretation of the results:

Analogous interpretation to the one made for the linear model.

Analysis of \(h_3^{34}\) parameter

\(h_3^{34} :=\) minimum time time spent in patients with \(w_j \in \lbrace 3, 4 \rbrace\)

params['n'] = 50 ; params['p']=500 ; params['h1']=6 ; params['h2']=1 ; params['h4']=4
params['h3_1_2'] = 0.10 
params['h3_3_4'] = None
params['h3_5_6'] = 0.55  
params['h3_7_8'] = 0.80 
params['h3_9_10'] = 1 

np.random.seed(123)
params['w'] = np.random.randint(1, 11, params['p']) 

parameter_list = np.arange(0, 0.8, 0.1)
results1 = get_results1('h3_3_4', parameter_list, params, model='integer')
results2 = get_results2('h3_3_4', parameter_list, results1)
  • Problem type (feasible - not feasible) vs \(h_3^{34}\)

plt.figure(figsize=(8, 5))
ax = sns.scatterplot(y=results2['h3_3_4']['type'], x=parameter_list, color='red', s=200)
plt.title('type vs $h_3^{34}$', size=15)
ax.set_ylabel('type', size=12)
ax.set_xlabel('$h_3^{34}$', size=12)
plt.xticks(parameter_list, fontsize=12)
plt.yticks(fontsize=11)
plt.show()
_images/026cc0acfbfdc9f99e0f324b26604264fffe777f70715197aa12f049e060c436.png

Interpretation of the results:

Analogous interpretation to the one made for the linear model.

  • Number of patients seen vs \(h_3^{34}\)

plt.figure(figsize=(8, 5))
ax = sns.lineplot(y=results2['h3_3_4']['num_patients_seen'].values(), x=results2['h3_3_4']['feasible'], 
                  marker='o', markersize=7.5, color='red')
plt.title('number of patients seen vs h3_3_4', size=15)
ax.set_ylabel('number of patients seen', size=12)
ax.set_xlabel('h3_3_4', size=12)
plt.xticks(results2['h3_3_4']['feasible'], fontsize=12)
plt.yticks(fontsize=11)
plt.show()
_images/3dc80584c8a5b754cb96c0d34ac74524c5502183d89ff274b4c01bcaf90deaf5.png

Interpretation of the results:

Even when \(h_3^{34}=0\), the number of patients seen is the maximum possible \((p)\), thanks to the new constraint added in the binary model.

  • Optimal value of the objective function vs \(h_3^{34}\)

plt.figure(figsize=(8, 5))
ax = sns.lineplot(y=results2['h3_3_4']['f_optimal_feasible'].values(), x=results2['h3_3_4']['feasible'], marker='o', markersize=7.5, color='red')
plt.title('$f$ optimal vs $h_3^{34}$', size=15)
ax.set_ylabel('$f$ optimal', size=12)
ax.set_xlabel('$h_3^{34}$', size=12)
plt.xticks(results2['h3_3_4']['feasible'], fontsize=12)
plt.yticks(np.arange(2100, 2550, 50), fontsize=11)
plt.show()
_images/a960fdf7b2393ba979f3ae38ccc2f897e7e6c4d1b7e67bb82885cd878ac23e9d.png

Interpretation of the results:

Analogous interpretation to the one made for the linear model.

  • Average time spent per patient vs \(h_3^{34}\)

plt.figure(figsize=(8, 5))
ax = sns.lineplot(y=results2['h3_3_4']['avg_time_per_patient'].values(), x=results2['h3_3_4']['feasible'], marker='o', markersize=7.5, color='red')
plt.title('Avg. time per patient vs $h_3^{34}$', size=15)
ax.set_ylabel('Avg. time per patient', size=12)
ax.set_xlabel('$h_3^{34}$', size=12)
plt.xticks(results2['h3_3_4']['feasible'], fontsize=12)
plt.yticks(fontsize=11)
plt.show()
_images/3a2b00cf35b55def6ed01686c82b50f53d60b8a0b6a93d0754537040b790d917.png

Interpretation of the results:

Analogous interpretation to the one made for the linear model.

  • Median time spent per patient vs \(h_3^{34}\)

plt.figure(figsize=(8, 5))
ax = sns.lineplot(y=results2['h3_3_4']['median_time_per_patient'].values(), x=results2['h3_3_4']['feasible'], marker='o', markersize=7.5, color='red')
plt.title('Median time per patient vs $h_3^{34}$', size=15)
ax.set_ylabel('Median time per patient', size=12)
ax.set_xlabel('$h_3^{34}$', size=12)
plt.xticks(results2['h3_3_4']['feasible'], fontsize=12)
plt.yticks(fontsize=11)
plt.show()
_images/1450b59cc212055ef4e2269ba00797f4359dd38847d04b5549b57e948a7d0207.png

Interpretation of the results:

Analogous interpretation to the one made for the linear model.

  • \(75\)-quantile time spent per patient vs \(h_3^{34}\)

plt.figure(figsize=(8, 5))
ax = sns.lineplot(y=results2['h3_3_4']['Q75_time_per_patient'].values(), x=results2['h3_3_4']['feasible'], marker='o', markersize=7.5, color='red')
plt.title('Q75 time per patient vs $h_3^{34}$', size=15)
ax.set_ylabel('Q75 time per patient', size=12)
ax.set_xlabel('$h_3^{34}$', size=12)
plt.xticks(results2['h3_3_4']['feasible'], fontsize=12)
plt.yticks(fontsize=11)
plt.show()
_images/920f0861a14548743a8e5baee03330207b54919495ff7cd5799d0d9f550585fb.png

Interpretation of the results:

Analogous interpretation to the one made for the linear model.

  • \(25\)-quantile time spent per patient vs \(h_3^{34}\)

plt.figure(figsize=(8, 5))
ax = sns.lineplot(y=results2['h3_3_4']['Q25_time_per_patient'].values(), x=results2['h3_3_4']['feasible'], marker='o', markersize=7.5, color='red')
plt.title('Q25 time per patient vs $h_3^{34}$', size=15)
ax.set_ylabel('Q25 time per patient', size=12)
ax.set_xlabel('$h_3^{34}$', size=12)
plt.xticks(results2['h3_3_4']['feasible'], fontsize=12)
plt.yticks(fontsize=11)
plt.show()
_images/9070a12768ea3a8bb73c8a5cbd9eb55a4617476dac5fd9d5e7387039e900e71d.png

Interpretation of the results:

Analogous interpretation to the one made for the linear model.

  • Average time spent per patient vs \(w\) vs \(h_3^{34}\)

plt.figure(figsize=(9, 6))
for i, h3_3_4 in zip(results2['h3_3_4']['avg_time_patient_per_w'].keys(), results2['h3_3_4']['feasible']) :
    ax = sns.lineplot(y=results2['h3_3_4']['avg_time_patient_per_w'][i].values(), x=results2['h3_3_4']['avg_time_patient_per_w'][i].keys(), 
                      label=round(h3_3_4, 2), marker='o', markersize=6)
plt.title('Avg. time per patient vs $w$ vs $h_3^{34}$', size=15)
ax.set_ylabel('Avg. time per patient', size=12)
ax.set_xlabel('$w$', size=12)
plt.xticks(list(results2['h3_3_4']['avg_time_patient_per_w'][i].keys()), fontsize=12)
plt.yticks(np.arange(0, 2.45, 0.15), fontsize=11)
plt.legend(title='$h_3^{34}$', loc='upper right', bbox_to_anchor=(1.2, 1), fontsize=11)
plt.show()
_images/fccf544907e51704bc3316f4a37d796f2467e4c4d2139f0de4255fa486a42a46.png

Interpretation of the results:

Analogous interpretation to the one made for the linear model.

Analysis of \(h_3^{56}\) parameter

\(h_3^{56} :=\) minimum time time spent in patients with \(w_j \in \lbrace 5, 6 \rbrace\)

params['n'] = 50 ; params['p']=500 ; params['h1']=6 ; params['h2']=1 ; params['h4']=4
params['h3_1_2'] = 0.10 
params['h3_3_4'] = 0.30
params['h3_5_6'] = None  
params['h3_7_8'] = 0.80 
params['h3_9_10'] = 1 

np.random.seed(123)
params['w'] = np.random.randint(1, 11, params['p']) 

parameter_list = np.arange(0, 1.1, 0.1)
results1 = get_results1('h3_5_6', parameter_list, params, model='integer')
results2 = get_results2('h3_5_6', parameter_list, results1)
  • Problem type (feasible - not feasible) vs \(h_3^{56}\)

plt.figure(figsize=(8, 5))
ax = sns.scatterplot(y=results2['h3_5_6']['type'], x=parameter_list, color='red', s=200)
plt.title('type vs $h_3^{56}$', size=15)
ax.set_ylabel('type', size=12)
ax.set_xlabel('$h_3^{56}$', size=12)
plt.xticks(parameter_list, fontsize=12)
plt.yticks(fontsize=11)
plt.show()
_images/0e6a92b023d76c6f81bed6f0c5a788fd1a38d735163e7f1ad7aeb127884fdc21.png

Interpretation of the results:

Analogous interpretation to the one made for the linear model.

  • Number of patients seen vs \(h_3^{56}\)

plt.figure(figsize=(8, 5))
ax = sns.lineplot(y=results2['h3_5_6']['num_patients_seen'].values(), x=results2['h3_5_6']['feasible'], 
                  marker='o', markersize=7.5, color='red')
plt.title('number of patients seen vs h3_5_6', size=15)
ax.set_ylabel('number of patients seen', size=12)
ax.set_xlabel('h3_5_6', size=12)
plt.xticks(results2['h3_5_6']['feasible'], fontsize=12)
# plt.yticks(np.arange(400, 520, 20), fontsize=11)
plt.show()
_images/5dae00a65d43cff364a930cface5b480cff8daa943085288d41dd1cb3e7d7e4b.png

Interpretation of the results:

Even when \(h_3^{56}=0\), the number of patients seen is the maximum possible \((p)\), thanks to the new constraint added in the binary model.

  • Optimal value of the objective function vs \(h_3^{56}\)

plt.figure(figsize=(8, 5))
ax = sns.lineplot(y=results2['h3_5_6']['f_optimal_feasible'].values(), x=results2['h3_5_6']['feasible'], marker='o', markersize=7.5, color='red')
plt.title('$f$ optimal vs $h_3^{56}$', size=15)
ax.set_ylabel('$f$ optimal', size=12)
ax.set_xlabel('$h_3^{56}$', size=12)
plt.xticks(results2['h3_5_6']['feasible'], fontsize=12)
plt.yticks(np.arange(2100, 2550, 50), fontsize=11)
plt.show()
_images/85869e2d811c13af7455fdb606dd6c30c72f81c27abbca3c55b62ee00aba9b7c.png

Interpretation of the results:

Analogous interpretation to the one made for the linear model.

  • Average time spent per patient vs \(h_3^{56}\)

plt.figure(figsize=(8, 5))
ax = sns.lineplot(y=results2['h3_5_6']['avg_time_per_patient'].values(), x=results2['h3_5_6']['feasible'], marker='o', markersize=7.5, color='red')
plt.title('Avg. time per patient vs $h_3^{56}$', size=15)
ax.set_ylabel('Avg. time per patient', size=12)
ax.set_xlabel('$h_3^{56}$', size=12)
plt.xticks(results2['h3_5_6']['feasible'], fontsize=12)
plt.yticks(fontsize=11)
plt.show()
_images/6d7d7c665b55fa992582a375201cf82f1a723ef24445fd3ce25a484bef4eda30.png

Interpretation of the results:

Analogous interpretation to the one made for the linear model.

  • Median time spent per patient vs \(h_3^{56}\)

plt.figure(figsize=(8, 5))
ax = sns.lineplot(y=results2['h3_5_6']['median_time_per_patient'].values(), x=results2['h3_5_6']['feasible'], marker='o', markersize=7.5, color='red')
plt.title('Median time per patient vs $h_3^{56}$', size=15)
ax.set_ylabel('Median time per patient', size=12)
ax.set_xlabel('$h_3^{56}$', size=12)
plt.xticks(results2['h3_5_6']['feasible'], fontsize=12)
plt.yticks(fontsize=11)
plt.show()
_images/8917d849656ab4cd87232303b518e7a2e5aae2b2c47a6e6766f9af4117400b87.png

Interpretation of the results:

Analogous interpretation to the one made for the linear model.

  • \(75\)-quantile time spent per patient vs \(h_3^{56}\)

plt.figure(figsize=(8, 5))
ax = sns.lineplot(y=results2['h3_5_6']['Q75_time_per_patient'].values(), x=results2['h3_5_6']['feasible'], marker='o', markersize=7.5, color='red')
plt.title('Q75 time per patient vs $h_3^{56}$', size=15)
ax.set_ylabel('Q75 time per patient', size=12)
ax.set_xlabel('$h_3^{56}$', size=12)
plt.xticks(results2['h3_5_6']['feasible'], fontsize=12)
plt.yticks(fontsize=11)
plt.show()
_images/ca986b7605883686fc37470d75360fc18d03eea37a0cea170027bc33c81a0813.png

Interpretation of the results:

Analogous interpretation to the one made for the linear model.

  • \(25\)-quantile time spent per patient vs \(h_3^{34}\)

plt.figure(figsize=(8, 5))
ax = sns.lineplot(y=results2['h3_5_6']['Q25_time_per_patient'].values(), x=results2['h3_5_6']['feasible'], marker='o', markersize=7.5, color='red')
plt.title('Q25 time per patient vs $h_3^{56}$', size=15)
ax.set_ylabel('Q25 time per patient', size=12)
ax.set_xlabel('$h_3^{56}$', size=12)
plt.xticks(results2['h3_5_6']['feasible'], fontsize=12)
plt.yticks(fontsize=11)
plt.show()
_images/285e30dd9ef3b37cb07c72ffa7ab964fd1316e25e1cc38f4553f17bbe0bd8ee7.png

Interpretation of the results:

Analogous interpretation to the one made for the linear model.

  • Average time spent per patient vs \(w\) vs \(h_3^{56}\)

plt.figure(figsize=(9, 6))
for i, h3_5_6 in zip(results2['h3_5_6']['avg_time_patient_per_w'].keys(), results2['h3_5_6']['feasible']) :
    ax = sns.lineplot(y=results2['h3_5_6']['avg_time_patient_per_w'][i].values(), x=results2['h3_5_6']['avg_time_patient_per_w'][i].keys(), 
                      label=round(h3_5_6, 2), marker='o', markersize=6)
plt.title('Avg. time per patient vs $w$ vs $h_3^{56}$', size=15)
ax.set_ylabel('Avg. time per patient', size=12)
ax.set_xlabel('$w$', size=12)
plt.xticks(list(results2['h3_5_6']['avg_time_patient_per_w'][i].keys()), fontsize=12)
plt.yticks(np.arange(0,3, 0.25), fontsize=11)
plt.legend(title='$h_3^{56}$', loc='upper right', bbox_to_anchor=(1.2, 1), fontsize=11)
plt.show()
_images/302fdb1769d6a877285ae1fdc45f3e7a2937f8aa4adeb3c02e2cfc6df6568c49.png

Interpretation of the results:

Analogous interpretation to the one made for the linear model.

Analysis of \(h_3^{78}\) parameter

\(h_3^{78} :=\) minimum time time spent in patients with \(w_j \in \lbrace 7, 8 \rbrace\)

params['n'] = 50 ; params['p']=500 ; params['h1']=6 ; params['h2']=1 ; params['h4']=4
params['h3_1_2'] = 0.10 
params['h3_3_4'] = 0.30
params['h3_5_6'] = 0.55  
params['h3_7_8'] = None 
params['h3_9_10'] = 1 

np.random.seed(123)
params['w'] = np.random.randint(1, 11, params['p']) 

parameter_list = np.arange(0, 1.3, 0.1)
results1 = get_results1('h3_7_8', parameter_list, params, model='integer')
results2 = get_results2('h3_7_8', parameter_list, results1)
  • Problem type (feasible - not feasible) vs \(h_3^{78}\)

plt.figure(figsize=(8, 5))
ax = sns.scatterplot(y=results2['h3_7_8']['type'], x=parameter_list, color='red', s=200)
plt.title('type vs $h_3^{78}$', size=15)
ax.set_ylabel('type', size=12)
ax.set_xlabel('$h_3^{78}$', size=12)
plt.xticks(parameter_list, fontsize=12)
plt.yticks(fontsize=11)
plt.show()
_images/8cbaea3a94a58c323d026a00f84178f5c6b947f8cc0c619ec76cea5f170c5ee4.png

Interpretation of the results:

Analogous interpretation to the one made for the linear model.

  • Number of patients seen vs \(h_3^{78}\)

plt.figure(figsize=(8, 5))
ax = sns.lineplot(y=results2['h3_7_8']['num_patients_seen'].values(), x=results2['h3_7_8']['feasible'], 
                  marker='o', markersize=7.5, color='red')
plt.title('number of patients seen vs h3_7_8', size=15)
ax.set_ylabel('number of patients seen', size=12)
ax.set_xlabel('h3_7_8', size=12)
plt.xticks(results2['h3_7_8']['feasible'], fontsize=12)
plt.yticks(np.arange(380, 520, 20), fontsize=11)
plt.show()
_images/8881e28ef45f1bda3a5ee05270b1ca50bc3ca302e1af279c8d76bf91a3db6b51.png

Interpretation of the results:

Even when \(h_3^{78}=0\), the number of patients seen is the maximum possible \((p)\), thanks to the new constraint added in the binary model.

  • Optimal value of the objective function vs \(h_3^{78}\)

plt.figure(figsize=(8, 5))
ax = sns.lineplot(y=results2['h3_7_8']['f_optimal_feasible'].values(), x=results2['h3_7_8']['feasible'], marker='o', markersize=7.5, color='red')
plt.title('$f$ optimal vs $h_3^{78}$', size=15)
ax.set_ylabel('$f$ optimal', size=12)
ax.set_xlabel('$h_3^{78}$', size=12)
plt.xticks(results2['h3_7_8']['feasible'], fontsize=12)
plt.yticks(np.arange(2100, 2550, 50), fontsize=11)
plt.show()
_images/4cb2700d8c4dfdea75088d5762a4d5e69168b242e712fc29699516bcca548a74.png

Interpretation of the results:

Analogous interpretation to the one made for the linear model.

  • Average time spent per patient vs \(h_3^{78}\)

plt.figure(figsize=(8, 5))
ax = sns.lineplot(y=results2['h3_7_8']['avg_time_per_patient'].values(), x=results2['h3_7_8']['feasible'], marker='o', markersize=7.5, color='red')
plt.title('Avg. time per patient vs $h_3^{78}$', size=15)
ax.set_ylabel('Avg. time per patient', size=12)
ax.set_xlabel('$h_3^{78}$', size=12)
plt.xticks(results2['h3_7_8']['feasible'], fontsize=12)
plt.yticks(fontsize=11)
plt.show()
_images/2771f92a4c1942b8926d4ae4660c861c2e3b5538dd538c6d2d2e1524d9d3f75b.png

Interpretation of the results:

Analogous interpretation to the one made for the linear model.

  • Median time spent per patient vs \(h_3^{78}\)

plt.figure(figsize=(8, 5))
ax = sns.lineplot(y=results2['h3_7_8']['median_time_per_patient'].values(), x=results2['h3_7_8']['feasible'], marker='o', markersize=7.5, color='red')
plt.title('Median time per patient vs $h_3^{78}$', size=15)
ax.set_ylabel('Median time per patient', size=12)
ax.set_xlabel('$h_3^{78}$', size=12)
plt.xticks(results2['h3_7_8']['feasible'], fontsize=12)
plt.yticks(fontsize=11)
plt.show()
_images/1a18af893685435a2be89f843d93bcd5ada03d4757908f1cad9d6dde7c9b4399.png

Interpretation of the results:

Analogous interpretation to the one made for the linear model.

  • \(75\)-quantile time spent per patient vs \(h_3^{78}\)

plt.figure(figsize=(8, 5))
ax = sns.lineplot(y=results2['h3_7_8']['Q75_time_per_patient'].values(), x=results2['h3_7_8']['feasible'], marker='o', markersize=7.5, color='red')
plt.title('Q75 time per patient vs $h_3^{78}$', size=15)
ax.set_ylabel('Q75 time per patient', size=12)
ax.set_xlabel('$h_3^{78}$', size=12)
plt.xticks(results2['h3_7_8']['feasible'], fontsize=12)
plt.yticks(fontsize=11)
plt.show()
_images/23e2bcf1439c879f26bca2d7e6864da12490559f8ce59a85f0dd5260b4e44319.png

Interpretation of the results:

Analogous interpretation to the one made for the linear model.

  • \(25\)-quantile time spent per patient vs \(h_3^{78}\)

plt.figure(figsize=(8, 5))
ax = sns.lineplot(y=results2['h3_7_8']['Q25_time_per_patient'].values(), x=results2['h3_7_8']['feasible'], marker='o', markersize=7.5, color='red')
plt.title('Q25 time per patient vs $h_3^{78}$', size=15)
ax.set_ylabel('Q25 time per patient', size=12)
ax.set_xlabel('$h_3^{78}$', size=12)
plt.xticks(results2['h3_7_8']['feasible'], fontsize=12)
plt.yticks(fontsize=11)
plt.show()
_images/3d287ee3ae75b1fd5cbdf29467b35fde645121caf4fb5b68a7e7402abb73b646.png

Interpretation of the results:

Analogous interpretation to the one made for the linear model.

  • Average time spent per patient vs \(w\) vs \(h_3^{78}\)

plt.figure(figsize=(9, 6))
for i, h3_7_8 in zip(results2['h3_7_8']['avg_time_patient_per_w'].keys(), results2['h3_7_8']['feasible']) :
    ax = sns.lineplot(y=results2['h3_7_8']['avg_time_patient_per_w'][i].values(), x=results2['h3_7_8']['avg_time_patient_per_w'][i].keys(), 
                      label=round(h3_7_8, 2), marker='o', markersize=6)
plt.title('Avg. time per patient vs $w$ vs $h_3^{78}$', size=15)
ax.set_ylabel('Avg. time per patient', size=12)
ax.set_xlabel('$w$', size=12)
plt.xticks(list(results2['h3_7_8']['avg_time_patient_per_w'][i].keys()), fontsize=12)
plt.yticks(np.arange(0,4, 0.25), fontsize=11)
plt.legend(title='$h_3^{78}$', loc='upper right', bbox_to_anchor=(1.2, 1), fontsize=11)
plt.show()
_images/f5b2e1c39399160719438b4c791dd86e21010fae17712fbd82d282b1cacad4c9.png

Interpretation of the results:

Analogous interpretation to the one made for the linear model.

Analysis of \(h_3^{910}\) parameter

\(h_3^{910} :=\) minimum time time spent in patients with \(w_j \in \lbrace 9, 10 \rbrace\)

params['n'] = 50 ; params['p']=500 ; params['h1']=6 ; params['h2']=1 ; params['h4']=4
params['h3_1_2'] = 0.10 
params['h3_3_4'] = 0.30
params['h3_5_6'] = 0.55  
params['h3_7_8'] = 0.80 
params['h3_9_10'] = None 

np.random.seed(123)
params['w'] = np.random.randint(1, 11, params['p']) 

parameter_list = np.arange(0, 1.6, 0.1)
results1 = get_results1('h3_9_10', parameter_list, params, model='integer')
results2 = get_results2('h3_9_10', parameter_list, results1)
  • Problem type (feasible - not feasible) vs \(h_3^{910}\)

plt.figure(figsize=(8, 5))
ax = sns.scatterplot(y=results2['h3_9_10']['type'], x=parameter_list, color='red', s=200)
plt.title('type vs $h_3^{910}$', size=15)
ax.set_ylabel('type', size=12)
ax.set_xlabel('$h_3^{910}$', size=12)
plt.xticks(parameter_list, fontsize=12)
plt.yticks(fontsize=11)
plt.show()
_images/606aad0d6217f5605f27487c76e57f2009fd185db90f6ce9250e3538116a8e05.png

Interpretation of the results:

Analogous interpretation to the one made for the linear model.

  • Number of patients seen vs \(h_3^{910}\)

plt.figure(figsize=(8, 5))
ax = sns.lineplot(y=results2['h3_9_10']['num_patients_seen'].values(), x=results2['h3_9_10']['feasible'], 
                  marker='o', markersize=7.5, color='red')
plt.title('number of patients seen vs h3_9_10', size=15)
ax.set_ylabel('number of patients seen', size=12)
ax.set_xlabel('h3_9_10', size=12)
plt.xticks(results2['h3_9_10']['feasible'], fontsize=12)
# plt.yticks(np.arange(420, 520, 20), fontsize=11)
plt.show()
_images/1e8369ba390383ef0947f3bfb49f46487d57e43095305047835900ee8e497752.png

Interpretation of the results:

Even when \(h_3^{910}=0\), the number of patients seen is the maximum possible \((p)\), thanks to the new constraint added in the binary model.

  • Optimal value of the objective function vs \(h_3^{910}\)

plt.figure(figsize=(8, 5))
ax = sns.lineplot(y=results2['h3_9_10']['f_optimal_feasible'].values(), x=results2['h3_9_10']['feasible'], marker='o', markersize=7.5, color='red')
plt.title('$f$ optimal vs $h_3^{910}$', size=15)
ax.set_ylabel('$f$ optimal', size=12)
ax.set_xlabel('$h_3^{910}$', size=12)
plt.xticks(results2['h3_9_10']['feasible'], fontsize=12)
# plt.yticks(np.arange(2100, 2550, 50), fontsize=11)
plt.show()
_images/50b04c8a589344068ef0e686d660b6c3798f5ccf173581dd6ae5e20afad0a325.png

Interpretation of the results:

Analogous interpretation to the one made for the linear model.

  • Average time spent per patient vs \(h_3^{910}\)

plt.figure(figsize=(8, 5))
ax = sns.lineplot(y=results2['h3_9_10']['avg_time_per_patient'].values(), x=results2['h3_9_10']['feasible'], marker='o', markersize=7.5, color='red')
plt.title('Avg. time per patient vs $h_3^{910}$', size=15)
ax.set_ylabel('Avg. time per patient', size=12)
ax.set_xlabel('$h_3^{910}$', size=12)
plt.xticks(results2['h3_9_10']['feasible'], fontsize=12)
plt.yticks(fontsize=11)
plt.show()
_images/4895f937d9788d45b5651b42748503142a5183f97c92e8529f7772314b32dcd3.png

Interpretation of the results:

Analogous interpretation to the one made for the linear model.

  • Median time spent per patient vs \(h_3^{910}\)

plt.figure(figsize=(8, 5))
ax = sns.lineplot(y=results2['h3_9_10']['median_time_per_patient'].values(), x=results2['h3_9_10']['feasible'], marker='o', markersize=7.5, color='red')
plt.title('Median time per patient vs $h_3^{910}$', size=15)
ax.set_ylabel('Median time per patient', size=12)
ax.set_xlabel('$h_3^{910}$', size=12)
plt.xticks(results2['h3_9_10']['feasible'], fontsize=12)
plt.yticks(fontsize=11)
plt.show()
_images/43611e53ab6cb4993ffa4db3516372affb73d23589528a1b76fa26450d1740f7.png

Interpretation of the results:

Analogous interpretation to the one made for the linear model.

  • \(75\)-quantile time spent per patient vs \(h_3^{910}\)

plt.figure(figsize=(8, 5))
ax = sns.lineplot(y=results2['h3_9_10']['Q75_time_per_patient'].values(), x=results2['h3_9_10']['feasible'], marker='o', markersize=7.5, color='red')
plt.title('Q75 time per patient vs $h_3^{910}$', size=15)
ax.set_ylabel('Q75 time per patient', size=12)
ax.set_xlabel('$h_3^{910}$', size=12)
plt.xticks(results2['h3_9_10']['feasible'], fontsize=12)
plt.yticks(fontsize=11)
plt.show()
_images/8b8b5d7b56785eaa8947006b01a0167066084451b6d94ed489df1b2db0ea72ce.png

Interpretation of the results:

Analogous interpretation to the one made for the linear model.

  • \(25\)-quantile time spent per patient vs \(h_3^{910}\)

plt.figure(figsize=(8, 5))
ax = sns.lineplot(y=results2['h3_9_10']['Q25_time_per_patient'].values(), x=results2['h3_9_10']['feasible'], marker='o', markersize=7.5, color='red')
plt.title('Q25 time per patient vs $h_3^{910}$', size=15)
ax.set_ylabel('Q25 time per patient', size=12)
ax.set_xlabel('$h_3^{910}$', size=12)
plt.xticks(results2['h3_9_10']['feasible'], fontsize=12)
plt.yticks(fontsize=11)
plt.show()
_images/1a400e3ee233ef0f1fc8e3fb160d9db63a9d6600ad4fbba3184663c4ce6fa000.png

Interpretation of the results:

Analogous interpretation to the one made for the linear model.

  • Average time spent per patient vs \(w\) vs \(h_3^{910}\)

plt.figure(figsize=(9, 6))
for i, h3_9_10 in zip(results2['h3_9_10']['avg_time_patient_per_w'].keys(), results2['h3_9_10']['feasible']) :
    ax = sns.lineplot(y=results2['h3_9_10']['avg_time_patient_per_w'][i].values(), x=results2['h3_9_10']['avg_time_patient_per_w'][i].keys(), 
                      label=round(h3_9_10, 2), marker='o', markersize=6)
plt.title('Avg. time per patient vs $w$ vs $h_3^{910}$', size=15)
ax.set_ylabel('Avg. time per patient', size=12)
ax.set_xlabel('$w$', size=12)
plt.xticks(list(results2['h3_9_10']['avg_time_patient_per_w'][i].keys()), fontsize=12)
plt.yticks(np.arange(0,3, 0.25), fontsize=11)
plt.legend(title='$h_3^{910}$', loc='upper right', bbox_to_anchor=(1.2, 1), fontsize=11)
plt.show()
_images/d37f8023f5fb05a9ef85ea2de8e9cff66db294e7977f0a437895dbf46c3cbac2.png

Interpretation of the results:

Analogous interpretation to the one made for the linear model.

Analysis of multiple parameters#

In this section we make a sensitivity analysis of some of the parameters of the problem, following an multiple approach, in the sense that we analyzed several parameters at once.

This analysis is essentially carried out using the function get_results1_multi_IM and get_results2_multi_IM.

params = dict()

def time_seeing_patient(j, t_optimal, params):
    return np.sum([t_optimal[i, j] for i in range(0,params['n'])])

Analysis of \((h_3^{12}, h_3^{34}, h_3^{56}, h_3^{78}, h_3^{910})\) combination of parameters#

  • \(h_3 :=\) minimum time time spent in each patient, taking into account their severity/importance (this quantity depends on \(w_j\)).

# Defining the values of the rest of parameters and setting h3_1_2, h3_3_4, h3_5_6, h3_7_8, h3_9_10 as None.

params['n'] = 50 ; params['p']=500 ; params['h1']=6 ; params['h2']=1 ; params['h4']=4
params['h3_1_2'] = None 
params['h3_3_4'] = None
params['h3_5_6'] = None  
params['h3_7_8'] = None 
params['h3_9_10'] = None 

np.random.seed(123)
params['w'] = np.random.randint(1, 11, params['p']) 

# Defining the parameter combination values as a list.
param_combi_list = product([0, 0.1, 0.4], [0, 0.2, 0.5], [0, 0.4, 0.8], [0, 0.6, 1], [0, 0.7, 1.2])
param_combi_list = list(param_combi_list)

# Defining the parameter names as a tuple.
param_names = ('h3_1_2', 'h3_3_4', 'h3_5_6', 'h3_7_8', 'h3_9_10')

As before, we have run the code once and then saved the results in pickle files, in order to save time.

#results1_multi = get_results1_multi(('h3_1_2', 'h3_3_4', 'h3_5_6', 'h3_7_8', 'h3_9_10'), param_combi_list, params, model='integer')
#results2_multi = get_results2_multi(('h3_1_2', 'h3_3_4', 'h3_5_6', 'h3_7_8', 'h3_9_10'), param_combi_list, results1_multi)
# save a dictionary as a pickle
#with open('results1_multi_IM.pickle', 'wb') as file:
    # Use pickle's dump function to write the dict to the opened file.
    #pickle.dump(results1_multi, file)

#with open('results2_multi_IM.pickle', 'wb') as file:
    # Use pickle's dump function to write the dict to the opened file.
    #pickle.dump(results2_multi, file)
# Open a dictionary saved as a pickle
with open(r"C:\Users\fscielzo\Documents\Large-Data\Optimization\results1_multi_IM.pickle", 'rb') as file:
    # Read back the pickled file
    results1_multi = pickle.load(file)

# Open a dictionary saved as a pickle
with open(r"C:\Users\fscielzo\Documents\Large-Data\Optimization\results2_multi_IM.pickle", 'rb') as file:
    # Read back the pickled file
    results2_multi = pickle.load(file)
  • Problem type (feasible - not feasible) vs \((h_3^{12}, h_3^{34}, h_3^{56}, h_3^{78}, h_3^{910})\)

type_multi_plot(results2_multi=results2_multi, n_cols=2, figsize=(20, 20), interval_width=30)
_images/d777ae77aafdb6c941e1dec92fafeb055b1b8a9767dc5ac151a967ed15ddf2f3.png

Interpretation of the results:

Same interpretation to the one made for the linear model, because the results are the same.

  • Number of patients seen vs \((h_3^{12}, h_3^{34}, h_3^{56}, h_3^{78}, h_3^{910})\)

num_patients_seen_multi_plot(results2_multi=results2_multi, n_cols=2, figsize=(20, 20), interval_width=30)
_images/4d18a5fd25309b03b71c84fe0ccce814d0e31566a1873ccafd3f43afd21567b2.png

Interpretation of the results:

In this case in all the cases the number of patients seen is the maximum possible \((p)\), since the new binary constraint enforce that.

  • Optimal value of the objective function vs \((h_3^{12}, h_3^{34}, h_3^{56}, h_3^{78}, h_3^{910})\)

f_optimal_multi_plot(results2_multi=results2_multi, n_cols=2, figsize=(20, 20), interval_width=30)
_images/09a77efcf945a31503a5b0eb93f46d7516dc8c116be3a741d03fa76f79157796.png

Interpretation of the results:

Same interpretation to the one made for the linear model, because the results are the same.

  • Average time spent per patient vs \((h_3^{12}, h_3^{34}, h_3^{56}, h_3^{78}, h_3^{910})\)

avg_time_multi_plot(results2_multi=results2_multi, n_cols=2, figsize = (20, 20), interval_width=30)
_images/d888b67058b4987d46ef71b30919000090398388ecbadd243e9ea7b1ccb7d0d4.png

Interpretation of the results:

Same interpretation to the one made for the linear model, because the results are the same.

  • Median time spent per patient vs \((h_3^{12}, h_3^{34}, h_3^{56}, h_3^{78}, h_3^{910})\)

median_time_multi_plot(results2_multi=results2_multi, n_cols=2, figsize = (20, 20), interval_width=30)
_images/aa6e175cfcf4c55882c9b7742dd7e97842c68b6f628a1b740560adfedcf4c8af.png

Interpretation of the results:

Same interpretation to the one made for the linear model, because the results are the same.

  • \(75\)-quantile of time spent per patient vs \((h_3^{12}, h_3^{34}, h_3^{56}, h_3^{78}, h_3^{910})\)

Q75_time_multi_plot(results2_multi=results2_multi, n_cols=2, figsize=(20, 20), interval_width=30)
_images/24c24d1bd1c3e69aa2ed5f0efca292293a6eceb50967cbf64f85a12b0c3e35d6.png

Interpretation of the results:

Same interpretation to the one made for the linear model, because the results are the same.

  • \(25\)-quantile of time spent per patient vs \((h_3^{12}, h_3^{34}, h_3^{56}, h_3^{78}, h_3^{910})\)

Q25_time_multi_plot(results2_multi=results2_multi, n_cols=2, figsize=(20, 20), interval_width=30)
_images/7117cbf652df9010a94e8688c71acbc37ee1cd32bece89b7048b585b99583a3d.png

Interpretation of the results:

Same interpretation to the one made for the linear model, because the results are the same.

  • Average time spent per patient vs \(w\) vs \((h_3^{12}, h_3^{34}, h_3^{56}, h_3^{78}, h_3^{910})\)

avg_time_w_multi_plot(results2_multi=results2_multi, n_cols = 3, figsize = (22, 80), interval_width=3)
_images/fb0f63a4ca4fd415824cc7ea781115c0b710c06abce09b3fbbd3196700bffd6b.png

Interpretation of the results:

Same interpretation to the one made for the linear model, because the results are the same.