增加了HSMO整线优化方法,读取数据增加了供料器部分
This commit is contained in:
@@ -7,7 +7,7 @@ def line_optimizer_model(component_data, pcb_data, machine_num, hinter=True):
|
||||
mdl = Model('pcb assembly line optimizer')
|
||||
mdl.setParam('Seed', 0)
|
||||
mdl.setParam('OutputFlag', hinter) # set whether output the debug information
|
||||
mdl.setParam('TimeLimit', 600 * 3)
|
||||
mdl.setParam('TimeLimit', 1000)
|
||||
|
||||
nozzle_type, component_type = [], []
|
||||
for _, data in component_data.iterrows():
|
||||
@@ -22,9 +22,10 @@ def line_optimizer_model(component_data, pcb_data, machine_num, hinter=True):
|
||||
|
||||
H = max_head_index
|
||||
I = len(component_data)
|
||||
S = min(len(component_data) * ratio, 60)
|
||||
K = math.ceil(len(pcb_data) * 1.0 / H / M) + 1
|
||||
# K = 3
|
||||
S = sum([data.fdn * ratio for _, data in component_data.iterrows()])
|
||||
K = math.ceil(len(pcb_data) * 1.0 / M) + 1
|
||||
|
||||
# K = len(pcb_data)
|
||||
CompOfNozzle = [[0 for _ in range(J)] for _ in range(I)] # Compatibility
|
||||
|
||||
component_point = [0 for _ in range(I)]
|
||||
@@ -35,15 +36,17 @@ def line_optimizer_model(component_data, pcb_data, machine_num, hinter=True):
|
||||
|
||||
# objective related
|
||||
g = mdl.addVars(list_range(K), list_range(M), vtype=GRB.BINARY)
|
||||
d = mdl.addVars(list_range(K), list_range(H), list_range(M), lb=0, vtype=GRB.CONTINUOUS)
|
||||
d = mdl.addVars(list_range(K), list_range(H), list_range(M), vtype=GRB.INTEGER)
|
||||
u = mdl.addVars(list_range(I), list_range(K), list_range(H), list_range(M), vtype=GRB.BINARY)
|
||||
v = mdl.addVars(list_range(S), list_range(K), list_range(H), list_range(M), vtype=GRB.BINARY)
|
||||
d_plus = mdl.addVars(list_range(J), list_range(K), list_range(H), list_range(M), lb=0, vtype=GRB.CONTINUOUS)
|
||||
d_minus = mdl.addVars(list_range(J), list_range(K), list_range(H), list_range(M), lb=0, vtype=GRB.CONTINUOUS)
|
||||
w = mdl.addVars(list_range(K), list_range(M), vtype=GRB.CONTINUOUS)
|
||||
w = mdl.addVars(list_range(J), list_range(K), list_range(H), list_range(M), vtype=GRB.BINARY)
|
||||
d_plus = mdl.addVars(list_range(J), list_range(K), list_range(H), list_range(M), vtype=GRB.CONTINUOUS)
|
||||
d_minus = mdl.addVars(list_range(J), list_range(K), list_range(H), list_range(M), vtype=GRB.CONTINUOUS)
|
||||
z = mdl.addVars(list_range(K), list_range(M), vtype=GRB.INTEGER)
|
||||
|
||||
e = mdl.addVars(list_range(-(H - 1) * ratio, S), list_range(K), list_range(M), vtype=GRB.BINARY)
|
||||
f = mdl.addVars(list_range(S), list_range(I), list_range(M), vtype=GRB.BINARY, name='')
|
||||
t = mdl.addVars(list_range(M), lb=0, ub=N, vtype=GRB.CONTINUOUS)
|
||||
obj = mdl.addVar(lb=0, ub=N, vtype=GRB.CONTINUOUS)
|
||||
|
||||
mdl.addConstrs(g[k, m] >= g[k + 1, m] for k in range(K - 1) for m in range(M))
|
||||
@@ -52,24 +55,26 @@ def line_optimizer_model(component_data, pcb_data, machine_num, hinter=True):
|
||||
quicksum(u[i, k, h, m] for i in range(I)) <= g[k, m] for k in range(K) for h in range(H) for m in range(M))
|
||||
|
||||
# nozzle no more than 1 for head h and cycle k
|
||||
mdl.addConstrs(quicksum(CompOfNozzle[i][j] * u[i, k, h, m] for i in range(I) for j in range(J)) <= 1 for k
|
||||
in range(K) for h in range(H) for m in range(M))
|
||||
mdl.addConstrs(quicksum(w[j, k, h, m] for j in range(J)) <= 1 for k in range(K) for h in range(H) for m in range(M))
|
||||
|
||||
# work completion
|
||||
mdl.addConstrs(
|
||||
quicksum(u[i, k, h, m] for k in range(K) for h in range(H) for m in range(M)) == component_point[i] for i in
|
||||
range(I))
|
||||
|
||||
# nozzle change
|
||||
mdl.addConstrs(quicksum(CompOfNozzle[i][j] * u[i, k, h, m] for i in range(I)) - quicksum(
|
||||
CompOfNozzle[i][j] * u[i, k + 1, h, m] for i in range(I)) == d_plus[j, k, h, m] - d_minus[j, k, h, m] for k in
|
||||
mdl.addConstrs(
|
||||
u[i, k, h, m] <= quicksum(CompOfNozzle[i][j] * w[j, k, h, m] for j in range(J)) for i in range(I) for k in
|
||||
range(K) for h in range(H) for m in range(M))
|
||||
|
||||
mdl.addConstrs(w[j, k, h, m] - w[j, k + 1, h, m] == d_plus[j, k, h, m] - d_minus[j, k, h, m] for k in
|
||||
range(K - 1) for j in range(J) for h in range(H) for m in range(M))
|
||||
|
||||
mdl.addConstrs(quicksum(CompOfNozzle[i][j] * u[i, K - 1, h, m] for i in range(I)) - quicksum(
|
||||
CompOfNozzle[i][j] * u[i, 0, h, m] for i in range(I)) == d_plus[j, K - 1, h, m] - d_minus[j, K - 1, h, m] for j
|
||||
in range(J) for h in range(H) for m in range(M))
|
||||
mdl.addConstrs(w[j, 0, h, m] - w[j, K - 1, h, m] == d_plus[j, K - 1, h, m] - d_minus[j, K - 1, h, m]
|
||||
for j in range(J) for h in range(H) for m in range(M))
|
||||
|
||||
mdl.addConstrs(2 * d[k, h, m] == quicksum(d_plus[j, k, h, m] for j in range(J)) + quicksum(
|
||||
d_minus[j, k, h, m] for j in range(J)) - 1 for k in range(K) for h in range(H) for m in range(M))
|
||||
mdl.addConstrs(d[k, h, m] == quicksum(d_plus[j, k, h, m] for j in range(J)) + quicksum(
|
||||
d_minus[j, k, h, m] for j in range(J)) for k in range(K) for h in range(H) for m in range(M))
|
||||
|
||||
# simultaneous pick
|
||||
for s in range(-(H - 1) * ratio, S):
|
||||
@@ -99,25 +104,29 @@ def line_optimizer_model(component_data, pcb_data, machine_num, hinter=True):
|
||||
for s in range(S) for m in range(M))
|
||||
|
||||
# pickup movement
|
||||
mdl.addConstrs(w[k, m] >= s1 * e[s1, k, m] - s2 * e[s2, k, m] + N * (e[s1, k, m] + e[s2, k, m] - 2) for s1 in
|
||||
mdl.addConstrs(z[k, m] >= s1 * e[s1, k, m] - s2 * e[s2, k, m] + N * (e[s1, k, m] + e[s2, k, m] - 2) for s1 in
|
||||
range(-(H - 1) * ratio, S) for s2 in range(-(H - 1) * ratio, S) for k in range(K) for m in range(M))
|
||||
|
||||
# objective
|
||||
mdl.addConstrs(obj >= Fit_cy * quicksum(g[k, m] for k in range(K)) + Fit_nz * 2 * quicksum(
|
||||
d[k, h, m] for h in range(H) for k in range(K)) + Fit_pu * quicksum(
|
||||
e[s, k, m] for s in range(-(H - 1) * ratio, S) for k in range(K)) + Fit_pl * quicksum(
|
||||
u[i, k, h, m] for i in range(I) for k in range(K) for h in range(H)) + Fit_mv * head_interval * quicksum(
|
||||
w[k, m] for k in range(K)) for m in range(M))
|
||||
mdl.addConstrs(t[m] == Fit_cy * quicksum(g[k, m] for k in range(K)) + Fit_nz * quicksum(
|
||||
d[k, h, m] for h in range(H) for k in range(K)) + Fit_pu * quicksum(
|
||||
e[s, k, m] for s in range(-(H - 1) * ratio, S) for k in range(K)) + Fit_pl * quicksum(
|
||||
u[i, k, h, m] for i in range(I) for k in range(K) for h in range(H)) + Fit_mv * quicksum(
|
||||
z[k, m] for k in range(K)) for m in range(M))
|
||||
for m in range(M - 1):
|
||||
mdl.addConstr(t[m] >= t[m + 1])
|
||||
|
||||
mdl.addConstrs(obj >= t[m] for m in range(M))
|
||||
|
||||
mdl.setObjective(obj, GRB.MINIMIZE)
|
||||
|
||||
mdl.optimize()
|
||||
|
||||
for m in range(M):
|
||||
print(f'machine {m} : cycle : {sum(g[k, m].x for k in range(K))}, '
|
||||
f'nozzle change : {sum(d[k, h, m].x for h in range(H) for k in range(K))}, '
|
||||
f'pick up : {sum(e[s, k, m].x for s in range(-(H - 1) * ratio, S) for k in range(K))}, '
|
||||
f'placement : {sum(u[i, k, h, m].x for i in range(I) for k in range(K) for h in range(H))}, '
|
||||
f'pick movement : {sum(w[k, m].x for k in range(K))}')
|
||||
f'pick movement : {sum(z[k, m].x for k in range(K))}')
|
||||
|
||||
pcb_part_indices = defaultdict(list)
|
||||
for idx, data in pcb_data.iterrows():
|
||||
@@ -162,22 +171,25 @@ def line_optimizer_model(component_data, pcb_data, machine_num, hinter=True):
|
||||
|
||||
average_pos = round(
|
||||
(sum(head_place_pos) / len(head_place_pos) + stopper_pos[0] - slotf1_pos[0] + 1) / slot_interval)
|
||||
print(f'average_pos: {average_pos}')
|
||||
|
||||
for k in range(len(feeder_slot_result)):
|
||||
for h in range(H):
|
||||
if feeder_slot_result[k][h] == -1:
|
||||
continue
|
||||
feeder_slot_result[k][h] = feeder_slot_result[k][h] * 2 + average_pos
|
||||
|
||||
placement_result, head_sequence = greedy_placement_route_generation(partial_component_data, partial_pcb_data,
|
||||
component_result, cycle_result,
|
||||
feeder_slot_result, hinter=False)
|
||||
print('----- Placement machine ' + str(m + 1) + ' ----- ')
|
||||
placement_result, head_sequence = place_allocate_sequence_route_generation(partial_component_data,
|
||||
partial_pcb_data,
|
||||
component_result, cycle_result,
|
||||
feeder_slot_result, hinter=False)
|
||||
|
||||
opt_res = OptResult(component_result, cycle_result, feeder_slot_result, placement_result, head_sequence)
|
||||
info = placement_info_evaluation(partial_component_data, partial_pcb_data, opt_res, hinter=False)
|
||||
optimization_assign_result(partial_component_data, partial_pcb_data, opt_res, nozzle_hinter=True,
|
||||
component_hinter=True, feeder_hinter=True)
|
||||
info.print()
|
||||
assembly_info.append(info)
|
||||
print('------------------------------ ')
|
||||
info = placement_info_evaluation(partial_component_data, partial_pcb_data, opt_res, hinter=hinter)
|
||||
if hinter:
|
||||
print('----- Placement machine ' + str(m + 1) + ' ----- ')
|
||||
optimization_assign_result(partial_component_data, partial_pcb_data, opt_res, nozzle_hinter=True,
|
||||
component_hinter=True, feeder_hinter=True)
|
||||
info.print()
|
||||
assembly_info.append(info)
|
||||
print('------------------------------ ')
|
||||
return assembly_info
|
||||
|
Reference in New Issue
Block a user