diff --git a/__pycache__/offline.cpython-310.pyc b/__pycache__/offline.cpython-310.pyc index 5efa3c684dd1250014f4476d08736088512164ae..155ed6b0c423da99ddf4463dcc1863917313ac7c 100644 Binary files a/__pycache__/offline.cpython-310.pyc and b/__pycache__/offline.cpython-310.pyc differ diff --git a/offline.py b/offline.py index 97b006a34a4495900817d8c9db7336daa3ec5a5b..2e43b84b95fd2557630527dda48416d2ce5f7675 100644 --- a/offline.py +++ b/offline.py @@ -3,9 +3,8 @@ from gurobipy import GRB import copy def Solve(images, blackouts): - # TODO: if there are no blackouts, no need for the LP, just take the sum of all lengths and put images in random order - # now the LP crashes if this is the case because there are no indices for the blackouts - + + # if there are no blackouts, just send the images in a random order after eachother image_count = len(images) blackout_count = len(blackouts) if blackout_count == 0: @@ -24,11 +23,11 @@ def Solve(images, blackouts): br = blackouts # tuples (b^L_br, b^U_br) = [start, end) js = images # real number p_j = image size - ts = calculate_whiteboxes(copy.deepcopy(blackouts)) # tuples (time_t, δ_t) = [start, end) + white_boxes = calculate_whiteboxes(copy.deepcopy(blackouts)) # tuples (time_t, δ_t) = [start, duration) - print(f"br {blackout_count} = {br}") - print(f"\njs {image_count} = {js}") - print(f"\nts {whitebox_count} = {ts}") + print(f"br |{blackout_count}| = {br}") + print(f"\njs |{image_count}| = {js}") + print(f"\nts |{whitebox_count}| = {white_boxes}") """PARAMETERS""" h = GRB.INFINITY # time horizon = infinite @@ -42,105 +41,201 @@ def Solve(images, blackouts): ms = model.addVar(lb=0,vtype=GRB.CONTINUOUS) # makespan, objective function minimization value, bounded with constraints # P_j_br = model.addVars(image_count, blackout_count,lb=0,vtype=GRB.CONTINUOUS) # preemption time, will be set to 0 in Eq (33) PV_t = model.addVars(whitebox_count,lb=0,vtype=GRB.CONTINUOUS) # sum of length of images in whitebox t - Tf_j = model.addVars(image_count,lb=0,vtype=GRB.CONTINUOUS) # finish of image j - Tf_t = model.addVars(whitebox_count,lb=0,vtype=GRB.CONTINUOUS) # finish of all images in whitebox t - Ts_j = model.addVars(image_count,lb=0,vtype=GRB.CONTINUOUS) # start of image j - Ts_t = model.addVars(whitebox_count,lb=0,vtype=GRB.CONTINUOUS) # start of timeslot t, probably redundant + Tf_j = model.addVars(image_count,lb=0,vtype=GRB.CONTINUOUS) # finish time of image j + Tf_t = model.addVars(whitebox_count,lb=0,vtype=GRB.CONTINUOUS) # finish time of ALL images in whitebox t + Ts_j = model.addVars(image_count,lb=0,vtype=GRB.CONTINUOUS) # start of processing of image j + # Ts_t = model.addVars(whitebox_count,lb=0,vtype=GRB.CONTINUOUS) # start of timeslot t, probably redundant X_j_t = model.addVars(image_count, whitebox_count,vtype=GRB.BINARY) # order j in whitebox t Xfree_t = model.addVars(whitebox_count,vtype=GRB.BINARY) # whitebox t has no images in it - Y_j_jprime = model.addVars(image_count, image_count,vtype=GRB.BINARY) # image j comes before image j' in the global order + # Y_j_jprime = model.addVars(image_count, image_count,vtype=GRB.BINARY) # image j comes before image j' in the global order YA_j_br = model.addVars(image_count, blackout_count,vtype=GRB.BINARY) # order j starts after blackbox br YB_j_br = model.addVars(image_count, blackout_count,vtype=GRB.BINARY) # order j finishes before blackbox br """CONSTRAINTS""" - # model.addConstr(Y_j_jprime[0,0] == 0) - # model.addConstr(Y_j_jprime[0,1] == 0) - # model.addConstr(Y_j_jprime[1,0] == 1) - # model.addConstr(Y_j_jprime[1,1] == 0) # (1) minimize makespan model.setObjective(ms, GRB.MINIMIZE) - # (3) + # (3) make sure the starttime and endtime are exactly picture size apart model.addConstrs((Tf_j[j] - Ts_j[j] == js[j] for j in range(image_count)), name="Eq(3)") - # (4) - model.addConstrs((Tf_j[j] * Y_j_jprime[j,jprime] <= Ts_j[jprime] * Y_j_jprime[j,jprime] - for j in range(image_count) - for jprime in range(image_count)), - name="Eq(4)") + # (4) let the finishtime of a picture scheduled before another be lower or equal to the starting time of the later picture + # model.addConstrs((Tf_j[j] * Y_j_jprime[j,jprime] <= Ts_j[jprime] * Y_j_jprime[j,jprime] + # for j in range(image_count) + # for jprime in range(image_count)), + # name="Eq(4)") # (4 v2) # model.addConstrs((Tf_j[j] <= Ts_j[jprime] + tfU_j * (1 - Y_j_jprime[j,jprime]) # for j in range(image_count) # for jprime in range(image_count)), # name="Eq(4 v2)") - # (4 v3) - # for j in range(image_count): - # for jprime in range(j+1,image_count): - # model.addConstr((Tf_j[j] <= Ts_j[jprime] + tfU_j * (1 - Y_j_jprime[j,jprime])), - # name="Eq(4 v2)") - # # (5 v3) - # for j in range(image_count): - # for jprime in range(j+1,image_count): - # model.addConstr((Tf_j[jprime] <= Ts_j[j] + tfU_j * (1 + Y_j_jprime[j,jprime])), - # name="Eq(5 v3)") + # (5) + # model.addConstrs((Tf_j[jprime] * Y_j_jprime[j,jprime] <= Ts_j[j] * Y_j_jprime[j,jprime] + # for j in range(image_count) + # for jprime in range(image_count)), + # name="Eq(5)") + + """ + penalty: + + For all images: + eindtijd <- {begintijd whitbox} + {size of all images in whitebox} + """ + + """ + penalty: + + For all images: + eindtijd Tf_j <- {PV_T van whitebox waar die in zit} + """ + # (9) - model.addConstrs((ms >= Tf_j[j] - for j in range(image_count)), - name="Eq(9)") - # (11) - model.addConstrs((Ts_t[t+1] >= Tf_t[t] - for t in range(whitebox_count - 1)), - name="Eq(11)") - # (13) - model.addConstrs((Tf_t[t] - Ts_t[t] == PV_t[t] + # model.addConstrs((ms >= Tf_j[j] + # for j in range(image_count)), + # name="Eq(9)") + + # (9 V2) + model.addConstrs((ms >= (PV_t[t] + white_boxes[t][0]) * (1-Xfree_t[t]) + for t in range(whitebox_count)), + name="Eq(9 V2)") + + # # (11) + # model.addConstrs((white_boxes[t+1][0] >= Tf_t[t] + # for t in range(whitebox_count - 1)), + # name="Eq(11)") + + # (13) set the PV_T + # model.addConstrs((Tf_t[t] - white_boxes[t][0] >= PV_t[t] + # for t in range(whitebox_count)), + # name="Eq(13)") + + # (13) set the PV_T + model.addConstrs((white_boxes[t][1] >= PV_t[t] for t in range(whitebox_count)), name="Eq(13)") + # (17) + # model.addConstrs((gp.quicksum(X_j_t[j,t] for j in range(image_count)) + # + Xfree_t[t] + # == 1 + # for t in range(whitebox_count)), + # name="Eq(17)") + + # model.addConstrs((bool(gp.quicksum(X_j_t[j,t] for j in range(image_count))) + # + Xfree_t[t] + # == 1 + # for t in range(whitebox_count)), + # name="Eq(17)") + + # (17 v2) SET Xfree_t model.addConstrs((gp.quicksum(X_j_t[j,t] for j in range(image_count)) + Xfree_t[t] - == 1 + >= 1 # don't limit 1 image per whitebox t + for t in range(whitebox_count)), + name="Eq(17)") + + # Xfree_t <= 1 to make it binary + model.addConstrs((Xfree_t[t] <= 1 + for t in range(whitebox_count)), + name="Eq(17)") + + # Set Xfree to 0 if whitebox is not empty + model.addConstrs((gp.quicksum(X_j_t[j,t] for j in range(image_count)) + * Xfree_t[t] + == 0 for t in range(whitebox_count)), name="Eq(17)") - # (19) + + """ + Als som > 0 is + + >>> iets * 0 = 0 <<< + + 0 == som * Xfree_t + + 0 == 123 * X --> X = 1 + 0 == 0 * X --> X kan van alles worden + X <= 1 + + Xfree_t -> 0 + """ + + + """ + + for whiteboxes: + Sommeer dit: + PV_T + starttijd whitebox + """ + + + """ + V Xfree_t -> 1 als whitebox leeg is + + X Xfree_t -> 0 als whitebox niet leeg is ==> som over j van X_j_t >= 1 voor alle T + + 1. test_t <= 1 + 2. test_t >= som over j van X_j_t + 3. Xfree_t == 1 - test_t + + + (som + 1) * Xfree_t === som * Xfree_t + + * (1 - Xfree_t) + + gp.quicksum(X_j_t[j,t]) -> aantal images in whitebox + + """ + + # model.addConstrs((gp.quicksum(X_j_t[j,t] for j in range(image_count)) + # + Xfree_t[t] + # <= 1 + # for t in range(whitebox_count)), + # name="Eq(17)") + + # (19) makes sure each image is send once model.addConstrs((gp.quicksum(X_j_t[j,t] for t in range (whitebox_count)) == 1 for j in range (image_count)), name="Eq(19)") - # (20) + # # (20) model.addConstrs((PV_t[t] == gp.quicksum(js[j] * X_j_t[j,t] for j in range(image_count)) for t in range(whitebox_count)), name="Eq(20)") + # # (20.2) + model.addConstrs((PV_t[t] <= white_boxes[t][1] + for t in range(whitebox_count)), + name="Eq(20.2)") # (32) - # model.addConstrs((YB_j_br[j,br_index] + YA_j_br[j,br_index] == X_j_t[j,t] + # model.addConstrs((YB_j_br[j,br_index] + YA_j_br[j,br_index] == X_j_t[j,t] # for j in range(image_count) # for t in range (whitebox_count) # for br_index in range(blackout_count)), # name="Eq(32)") # (33) - # model.addConstrs((P_j_br[j,br_index] == 0 for j in range(image_count) + # model.addConstrs((P_j_br[j,br_index] == 0 for j in range(image_count) # for br_index in range(blackout_count)), # name="Eq(33)") # (34) - model.addConstrs((br[br_index][1] * YA_j_br[j,br_index] <= Ts_j[j] - for br_index in range(blackout_count) - for j in range(image_count)), - name="Eq(34)") - # (35) - model.addConstrs((Ts_j[j] <= br[br_index][0] * YB_j_br[j, br_index] + YA_j_br[j, br_index] * GRB.INFINITY - for j in range(image_count) - for br_index in range(blackout_count)), - name="Eq(35)") - # (36) - model.addConstrs((br[br_index][1] * YA_j_br[j,br_index] <= Tf_j[j] - for br_index in range(blackout_count) - for j in range(image_count)), - name="Eq(36)") - # (37) - model.addConstrs((Tf_j[j] <= br[br_index][0] * YB_j_br[j, br_index] - for j in range(image_count) - for br_index in range(blackout_count)), - name="Eq(37)") + # model.addConstrs((br[br_index][1] * YA_j_br[j,br_index] <= Ts_j[j] + # for br_index in range(blackout_count) + # for j in range(image_count)), + # name="Eq(34)") + # # (35) + # model.addConstrs((Ts_j[j] <= br[br_index][0] * YB_j_br[j, br_index] + YA_j_br[j, br_index] * GRB.INFINITY + # for j in range(image_count) + # for br_index in range(blackout_count)), + # name="Eq(35)") + # # (36) + # model.addConstrs((br[br_index][1] * YA_j_br[j,br_index] <= Tf_j[j] + # for br_index in range(blackout_count) + # for j in range(image_count)), + # name="Eq(36)") + # # (37) + # model.addConstrs((Tf_j[j] <= br[br_index][0] * YB_j_br[j, br_index] + # for j in range(image_count) + # for br_index in range(blackout_count)), + # name="Eq(37)") # SOLVE AND PRINT THE RESULTS model.optimize() @@ -150,36 +245,46 @@ def Solve(images, blackouts): if model.status == GRB.OPTIMAL: deletus = starts.pop() time = model.ObjVal - print('\nFinish time: %g' % time) + + # print('\nWhitebox times:') + # for t in range(whitebox_count): + # wbtimestart = white_boxes[t][0] + # wbtimefinish = Tf_t[t].X + # print(f"Wb {t} starts t={wbtimestart} finishes t={wbtimefinish}") + # starts.append(t) - print("White box decision variables:") + print("\nWhite box decision variables:") for (j,t) in X_j_t: print(f"(im{j},wb{t}) = {X_j_t[j,t].X}") - print('\nTimes:') - for im in Ts_j: - ts = Ts_j[im].X - tf = Tf_j[im].X - print(f"Image {im} starts t={ts} finishes t={tf}") - starts.append(t) - - print('\nOrder:') - for im in Ts_j: - for im2 in Ts_j: - print(f"{im} before {im2}: {Y_j_jprime[im, im2].X}") + # print('\nOrder:') + # for im in Ts_j: + # for im2 in Ts_j: + # print(f"{im} before {im2}: {Y_j_jprime[im, im2].X}") - print('\nWhitebox contains:') - for t in PV_t: - print(f"wb{t} is {Xfree_t[t].X} empty and holds length {PV_t[t].X} of images") - - print('\nBlackboxes before/after:') + print('\nImage before/after blackbox:') for (j,br_index) in YA_j_br: print(f"YA_{j}_{br_index}: image {j} after blackbox {br_index} = {YA_j_br[j,br_index].X}") print(f"YB_{j}_{br_index}: image {j} before blackbox {br_index} = {YB_j_br[j,br_index].X}") + print(f"(34) {br[br_index][1]} * {YA_j_br[j,br_index].X} <= {Ts_j[j].X}") + print(f"(35) {Ts_j[j].X} <= {br[br_index][0]} * {YB_j_br[j, br_index].X} + {YA_j_br[j, br_index].X} * infinity") + print(f"(36) {br[br_index][1]} * {YA_j_br[j,br_index].X} <= {Tf_j[j].X}") + print(f"(37) {Tf_j[j].X} <= {br[br_index][0]} * {YB_j_br[j, br_index].X}\n") + + print('\nFinish time: %g' % time) + print('Whitebox contains:') + for t in PV_t: + print(f"wb{t} is {Xfree_t[t].X} empty and holds length {PV_t[t].X} of images") + # print('\nImage times:') + # for im in Ts_j: + # jtimestart = Ts_j[im].X + # jtimefinish = Tf_j[im].X + # print(f"Image {im} starts t={jtimestart} finishes t={jtimefinish}") + # starts.append(t) else: - print('\nNo solution, reason:') + print('\nNo solution, Check input or constraints! Reason:') iis = model.computeIIS() # Irreducible Infeasible Subsystem, https://support.gurobi.com/hc/en-us/articles/360029969391-How-do-I-determine-why-my-model-is-infeasible- print(iis) @@ -194,7 +299,7 @@ def calculate_whiteboxes(blackouts): if (len(blackouts) == 0): # no black boxes, so whitebox length is infinite return [(0, GRB.INFINITY)] - current_blackout = blackouts.pop() + current_blackout = blackouts[0] begin = 0 end = current_blackout[0] wb.append((begin, end - begin)) @@ -202,7 +307,7 @@ def calculate_whiteboxes(blackouts): for i in range(1, len(blackouts) + 2): begin = current_blackout[1] if (i < length): - current_blackout = blackouts.pop() + current_blackout = blackouts[i] end = current_blackout[0] wb.append((begin, end - begin)) else: diff --git a/t4_in.txt b/t4_in.txt index cf65d86d9abe2d0915a0b0a3ed67f4b02fc1a9af..657f0aaa6a50c77c715ae57a5da82256c70a5efb 100644 --- a/t4_in.txt +++ b/t4_in.txt @@ -1,5 +1,5 @@ 2 -10 15 +10 1 -25, 5 \ No newline at end of file +100, 25 \ No newline at end of file diff --git a/t4_out.txt b/t4_out.txt index c006f6e306eeba32ae49910dc6aa351c5980224f..c210f24f5ad9c942ff9a94b0d5b034be0b2182c7 100644 --- a/t4_out.txt +++ b/t4_out.txt @@ -1,3 +1 @@ -15.0 -1 -1 \ No newline at end of file +50.0 \ No newline at end of file