Skip to content
Snippets Groups Projects
Commit 16aeacef authored by Goes,M. (Martijn)'s avatar Goes,M. (Martijn)
Browse files

doc: variables renamed after assignment

parent 913e2b0a
Branches master
No related tags found
No related merge requests found
No preview for this file type
...@@ -35,9 +35,6 @@ def ParseInput(src : str) -> Tuple[List[float], List[Tuple[float, float]]]: ...@@ -35,9 +35,6 @@ def ParseInput(src : str) -> Tuple[List[float], List[Tuple[float, float]]]:
endTime = float(string[1]) endTime = float(string[1])
blackoutCollection.append((startTime, startTime + endTime)) blackoutCollection.append((startTime, startTime + endTime))
print(f"image sizes: {imageCollection}")
print(f"blackouts: {blackoutCollection} \n")
return (imageCollection, blackoutCollection) return (imageCollection, blackoutCollection)
def PrintOutput(filename : str, endTime : float, imageTimes : List[float]): def PrintOutput(filename : str, endTime : float, imageTimes : List[float]):
...@@ -54,19 +51,19 @@ def PrintOutput(filename : str, endTime : float, imageTimes : List[float]): ...@@ -54,19 +51,19 @@ def PrintOutput(filename : str, endTime : float, imageTimes : List[float]):
OUTPUT_FILE.write(f"{str(endTime)}") OUTPUT_FILE.write(f"{str(endTime)}")
OUTPUT_FILE.writelines(reduce(lambda x, y: x + "\n" + f"{str(y)}", imageTimes, "")) OUTPUT_FILE.writelines(reduce(lambda x, y: x + "\n" + f"{str(y)}", imageTimes, ""))
print(f"\n Results written to {filename}, program finished.") print(f"\nResults written to {filename}, program finished.")
if __name__ == "__main__": if __name__ == "__main__":
testcase = 6 testcase = 9
parsedIn = ParseInput(f"t{testcase}_in.txt") parsedIn = ParseInput(f"t{testcase}_in.txt")
res = LP.Solve(parsedIn[0], parsedIn[1]) res = LP.Solve(parsedIn[0], parsedIn[1])
output_file = "t{}_out.txt".format(testcase) output_file = "t{}_out.txt".format(testcase)
PrintOutput(output_file, res[0], res[1]) PrintOutput(output_file, res[0], res[1])
""" """
solved 6 (= Instance5.txt from Instances_10) correctly as 842.563 in 0.01s + 0.02s solved 6 (= Instance5.txt from Instances_10) correctly as 842.563 in 0.03s
pre-solved 7 (= test_instance_generated5.txt from Instances_4, the biggest one available) pre-solved 7 (= test_instance_generated5.txt from Instances_4, the biggest one available)
with heuristic at 2079, optimal is 2054.747 (according to TXT) with heuristic at 2079.164, optimal is 2054.747 (according to TXT)
solved 7 in 293 seconds, but failed to write output because of ??? solved 7 in 293 seconds, but failed to write output because of ???
pre-solved 8 (= test_instance_generated3.txt from Instances_4) pre-solved 8 (= test_instance_generated3.txt from Instances_4)
...@@ -78,5 +75,4 @@ if __name__ == "__main__": ...@@ -78,5 +75,4 @@ if __name__ == "__main__":
with heuristic at 197.796, optimal is 190.055 (according to TXT) with heuristic at 197.796, optimal is 190.055 (according to TXT)
manually aborted at (189.197 ; 189.255) objective bounds after 500 seconds manually aborted at (189.197 ; 189.255) objective bounds after 500 seconds
which is better than the reported optimal? which is better than the reported optimal?
""" """
\ No newline at end of file
...@@ -2,154 +2,150 @@ import gurobipy as gp ...@@ -2,154 +2,150 @@ import gurobipy as gp
from gurobipy import GRB from gurobipy import GRB
import copy import copy
def Solve(images, blackouts): def Solve(images, blackouts):
# if there are no blackouts, just send the images in after eachother, there is no unique optimal solution # if there are no blackouts, just send the images in after eachother, there is no unique optimal solution
image_count = len(images) n = len(images)
blackout_count = len(blackouts) m = len(blackouts)
if blackout_count == 0: if m == 0:
endtime = 0 finish_objective = 0
times = [] starting_times = []
for image in range(image_count): for image in range(n):
times.append(endtime) starting_times.append(finish_objective)
endtime += images[image] finish_objective += images[image]
print(f"No blackboxes, easy solving: end time = {endtime}, startingtimes = {times}.") print("No blackboxes in the instance, easy solving without LP:")
return (endtime, times) print(f"\nImage starting times: {starting_times}")
whitebox_count = blackout_count+1 print(f"=====> END TIME: {finish_objective} <=====")
return (finish_objective, starting_times)
whitebox_count = m+1 # extra whitebox until infinity after the last blackbox
model = gp.Model("image_scheduling") model = gp.Model("image_scheduling")
"""Refer to the Google Docs file for full explanation """Refer to the paper for extensive elaboration
SETS / INDICES""" SETS / INDICES"""
br = blackouts # tuples (b^L_br, b^U_br) = [start, end) f_i = images # real number = image size
js = images # real number p_j = image size
white_boxes_t = calculate_whiteboxes(copy.deepcopy(blackouts)) # tuples (time_t, delta_t) = [start, duration)
print(f"br |{blackout_count}| = {br}") # tuples (time_t, delta_t) = [start, duration)
print(f"\njs |{image_count}| = {js}") wb_t = calculate_whiteboxes(copy.deepcopy(blackouts))
print(f"\nts |{whitebox_count}| = {white_boxes_t}")
""""DECISION VARIABLES""" """"DECISION VARIABLES"""
# makespan # objective function to minimize
ms = model.addVar(lb=0,vtype=GRB.CONTINUOUS) # makespan, objective function minimization value, bounded with constraints makepsan = model.addVar(lb=0, vtype=GRB.CONTINUOUS)
PV_t = model.addVars(whitebox_count,lb=0,vtype=GRB.CONTINUOUS) # sum of length of images in whitebox t
X_j_t = model.addVars(image_count, whitebox_count,vtype=GRB.BINARY) # order j in whitebox t # Processing Volume = sum of length of images transmitted in whitebox t
Xfree_t = model.addVars(whitebox_count,vtype=GRB.BINARY) # whitebox t has no images in it PV_t = model.addVars(whitebox_count, lb=0, vtype=GRB.CONTINUOUS)
# image i in whitebox t: yes (1)/no (0)
X_i_t = model.addVars(n, whitebox_count, vtype=GRB.BINARY)
# whitebox t is empty (no images being transmitted): yes (1)/no (0)
Xfree_t = model.addVars(whitebox_count, vtype=GRB.BINARY)
"""CONSTRAINTS""" """CONSTRAINTS"""
# (1) minimize makespan # minimize makespan
model.setObjective(ms, GRB.MINIMIZE) model.setObjective(makepsan, GRB.MINIMIZE)
# (9) complete model finish time is when the final filled whitebox finished processing its images # end time is when the last filled whitebox finished processing all its images
model.addConstrs((ms >= (PV_t[t] + white_boxes_t[t][0]) * (1-Xfree_t[t]) model.addConstrs((makepsan >= (PV_t[t] + wb_t[t][0]) * (1-Xfree_t[t])
for t in range(whitebox_count)), for t in range(whitebox_count)))
name="Eq(9)")
# sets Xfree_t to be (at least) 1 if there is no image in the whitebox
# (17) sets Xfree_t to be (at least) 1 if there is no image in the whitebox model.addConstrs((gp.quicksum(X_i_t[i, t] for i in range(n))
model.addConstrs((gp.quicksum(X_j_t[j,t] for j in range(image_count)) # Xfree_t is binary, no need for another <= 1 constraint on it
+ Xfree_t[t] # Xfree_t is binary, no need for another <= 1 constraint on it + Xfree_t[t]
>= 1 >= 1
for t in range(whitebox_count)), for t in range(whitebox_count)))
name="Eq(17)")
# Xfree_t should be 0 if there is at least one image being transmitted in whitebox t
# (17.2) Xfree_t should be 0 if there is at least one image being processed in whitebox t model.addConstrs((gp.quicksum(X_i_t[i, t] for i in range(n))
model.addConstrs((gp.quicksum(X_j_t[j,t] for j in range(image_count)) * Xfree_t[t]
* Xfree_t[t] == 0
== 0 for t in range(whitebox_count)))
for t in range(whitebox_count)),
name="Eq(17.2)") # transmit each image exactly once
model.addConstrs((gp.quicksum(X_i_t[i, t]
# (19) send each image exactly once for t in range(whitebox_count)) == 1
model.addConstrs((gp.quicksum(X_j_t[j,t] for i in range(n)))
for t in range (whitebox_count)) == 1
for j in range (image_count)), # total transmitting time in a whitebox is the sum of image lengths of images assigned to that whitebox...
name="Eq(19)") model.addConstrs((PV_t[t] == gp.quicksum(f_i[i] * X_i_t[i, t]
for i in range(n))
# (20) total processing time in a whitebox is the sum of image lengths of images assigned to that whitebox for t in range(whitebox_count)))
model.addConstrs((PV_t[t] == gp.quicksum(js[j] * X_j_t[j,t]
for j in range(image_count)) # ... but is upperbounded by the length of the whitebox
for t in range(whitebox_count)), model.addConstrs((PV_t[t] <= wb_t[t][1]
name="Eq(20)") for t in range(whitebox_count)))
# (20.2) but is upperbounded by the length of the whitebox
model.addConstrs((PV_t[t] <= white_boxes_t[t][1] # SOLVE, RECONSTRUCT AND PRINT(optional) THE RESULTS
for t in range(whitebox_count)),
name="Eq(20.2)")
# SOLVE AND PRINT THE RESULTS
model.optimize() model.optimize()
time = -1 # dummy start times, to catch errors
starts = [-1] end_time = -1
image_starts = [-1]
if model.status == GRB.OPTIMAL: if model.status == GRB.OPTIMAL:
_ = starts.pop() _ = image_starts.pop() # remove the dummy start time
time = model.ObjVal end_time = model.ObjVal
print("\nWhite box decision variables:") print("\nWhite box decision variables:")
for (j,t) in X_j_t: for (i, t) in X_i_t:
if X_j_t[j,t].X > 0: if X_i_t[i, t].X > 0: # image i was assigned to whitebox t
print(f"(im{j},wb{t}) = {X_j_t[j,t].X}") print(f"Image {i} assigned to whitebox {t}")
print("All other X_j_t are 0") print("All other X_i_t are 0")
print('Whitebox contains:') print('Whitebox contains:')
for t in PV_t: 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(
f"wb{t} is {Xfree_t[t].X} empty with volume {PV_t[t].X} of images")
print('\nImage times:')
timers = [0]*whitebox_count timers = [0]*whitebox_count
# initialize by setting to start of whitebox # initialize by setting to start of whitebox
for t in range(whitebox_count): for t in range(whitebox_count):
timers[t] = white_boxes_t[t][0] timers[t] = wb_t[t][0]
print(f"Timers before={timers}")
# add the image lengths # add the image lengths
for j in range(image_count): for j in range(n):
for t in range(whitebox_count): for t in range(whitebox_count):
if X_j_t[j,t].X == 1: if X_i_t[j, t].X == 1:
starts.append(timers[t]) image_starts.append(timers[t])
print(f"image {j} is scheduled in whitebox {t}") timers[t] += f_i[j]
timers[t] += js[j]
print(f"Timers after={timers}") print(f"\nImage starting times: {image_starts}")
print(f"Starts={starts}") print(f"=====> END TIME: {end_time} <=====")
print('Finish time: %g' % time)
else: else:
print('\nNo solution, Check input or constraints! Reason:') print('\nNo solution: check input or constraints! Reason (gurobipy):')
iis = model.computeIIS() # Irreducible Infeasible Subsystem, https://support.gurobi.com/hc/en-us/articles/360029969391-How-do-I-determine-why-my-model-is-infeasible- 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) print(iis)
return (time, starts) return (end_time, image_starts)
def calculate_whiteboxes(blackouts): def calculate_whiteboxes(blackouts):
"""Given the blackouts, 'invert' them to create the whiteboxes.
Returns a list of tuples (start time, duration)."""
wb = [] wb = []
length = len(blackouts) m = len(blackouts)
if (len(blackouts) == 0): # no black boxes, so whitebox length is infinite if m == 0: # no black boxes, so whitebox length is infinite
return [(0, GRB.INFINITY)] return [(0, GRB.INFINITY)]
current_blackout = blackouts[0] current_blackout = blackouts[0]
begin = 0 current_time = 0
end = current_blackout[0] end_time = current_blackout[0]
wb.append((begin, end - begin)) wb.append((current_time, end_time - current_time))
for i in range(1, len(blackouts) + 2): for bo in range(1, len(blackouts) + 2):
begin = current_blackout[1] current_time = current_blackout[1]
if (i < length): if (bo < m):
current_blackout = blackouts[i] current_blackout = blackouts[bo]
end = current_blackout[0] end_time = current_blackout[0]
wb.append((begin, end - begin)) wb.append((current_time, end_time - current_time))
else: else:
wb.append((begin, GRB.INFINITY)) # maybe needed, or else it won't fill after the last black box wb.append((current_time, GRB.INFINITY))
# it won't fill images after the last black box without this extra whitebox that lasts until infinity
break break
return wb return wb
def PrepareImages(numberOfImages, numberOfBlackouts):
decVariables = []
for i in range(0, numberOfImages):
for j in range(0, numberOfBlackouts):
decVariables.append((i,j))
return gp.tuplelist(decVariables)
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment