增加预安装供料器功能、路径规划模型支持单点、整线优化支持批量处理
This commit is contained in:
@ -38,73 +38,79 @@ def head_task_model(component_data, pcb_data, hinter=True):
|
||||
|
||||
# objective related
|
||||
g = mdl.addVars(list_range(K), vtype=GRB.BINARY)
|
||||
d = mdl.addVars(list_range(K - 1), list_range(H), vtype=GRB.CONTINUOUS)
|
||||
d = mdl.addVars(list_range(K), list_range(H), vtype=GRB.CONTINUOUS)
|
||||
u = mdl.addVars(list_range(K), vtype=GRB.INTEGER)
|
||||
|
||||
d_plus = mdl.addVars(list_range(J), list_range(H), list_range(K - 1), vtype=GRB.CONTINUOUS)
|
||||
d_minus = mdl.addVars(list_range(J), list_range(H), list_range(K - 1), vtype=GRB.CONTINUOUS)
|
||||
d_plus = mdl.addVars(list_range(J), list_range(H), list_range(K), vtype=GRB.CONTINUOUS)
|
||||
d_minus = mdl.addVars(list_range(J), list_range(H), list_range(K), vtype=GRB.CONTINUOUS)
|
||||
|
||||
e = mdl.addVars(list_range(-(H - 1) * r, S), list_range(K), vtype=GRB.BINARY)
|
||||
f = mdl.addVars(list_range(S), list_range(I), vtype=GRB.BINARY, name='')
|
||||
x = mdl.addVars(list_range(I), list_range(S), list_range(K), list_range(H), vtype=GRB.BINARY)
|
||||
n = mdl.addVars(list_range(H), vtype=GRB.CONTINUOUS)
|
||||
|
||||
mdl.addConstrs(g[k] <= g[k + 1] for k in range(K - 1))
|
||||
x = mdl.addVars(list_range(I), list_range(K), list_range(H), vtype=GRB.BINARY)
|
||||
y = mdl.addVars(list_range(S), list_range(K), list_range(H), vtype=GRB.BINARY)
|
||||
z = mdl.addVars(list_range(J), list_range(K), list_range(H), vtype=GRB.BINARY)
|
||||
|
||||
mdl.addConstrs(g[k] >= g[k + 1] for k in range(K - 1))
|
||||
|
||||
mdl.addConstrs(
|
||||
quicksum(x[i, s, k, h] for i in range(I) for s in range(S)) <= g[k] for k in range(K) for h in range(H))
|
||||
quicksum(x[i, k, h] for i in range(I)) <= g[k] for k in range(K) for h in range(H))
|
||||
|
||||
# nozzle no more than 1 for head h and cycle k
|
||||
mdl.addConstrs(
|
||||
quicksum(CompOfNozzle[i][j] * x[i, s, k, h] for i in range(I) for s in range(S) for j in range(J)) <= 1 for k in
|
||||
range(K) for h in range(H))
|
||||
mdl.addConstrs(quicksum(z[j, k ,h] for j in range(J)) <= 1 for k in range(K) for h in range(H))
|
||||
|
||||
# nozzle available number constraint
|
||||
mdl.addConstrs(
|
||||
quicksum(CompOfNozzle[i][j] * x[i, s, k, h] for i in range(I) for s in range(S) for h in range(H)) <= H for k in
|
||||
range(K) for j in range(J))
|
||||
mdl.addConstrs(quicksum(z[j, k, h] for h in range(H)) <= H for k in range(K) for j in range(J))
|
||||
|
||||
# work completion
|
||||
mdl.addConstrs(
|
||||
quicksum(x[i, s, k, h] for s in range(S) for k in range(K) for h in range(H)) == component_point[i] for i in
|
||||
range(I))
|
||||
mdl.addConstrs(quicksum(x[i, k, h] for k in range(K) for h in range(H)) == component_point[i] for i in range(I))
|
||||
|
||||
# nozzle change
|
||||
mdl.addConstrs(quicksum(CompOfNozzle[i][j] * x[i, s, k, h] for i in range(I) for s in range(S)) - quicksum(
|
||||
CompOfNozzle[i][j] * x[i, s, k + 1, h] for i in range(I) for s in range(S)) == d_plus[j, h, k] - d_minus[
|
||||
j, h, k] for k in range(K - 1) for j in range(J) for h in range(H))
|
||||
mdl.addConstrs(
|
||||
x[i, k, h] <= quicksum(CompOfNozzle[i][j] * z[j, k, h] for j in range(J)) for i in range(I) for k in range(K)
|
||||
for h in range(H))
|
||||
|
||||
mdl.addConstrs(
|
||||
2 * d[k, h] == quicksum(d_plus[j, h, k] for j in range(J)) + quicksum(d_minus[j, h, k] for j in range(J)) for k
|
||||
in range(K - 1) for h in range(H))
|
||||
z[j, k, h] - z[j, k + 1, h] == d_plus[j, h, k] - d_minus[j, h, k] for k in range(K - 1) for j in range(J) for h
|
||||
in range(H))
|
||||
|
||||
mdl.addConstrs(n[h] == quicksum(d[k, h] for k in range(K - 1)) - 0.5 for h in range(H))
|
||||
mdl.addConstrs(
|
||||
z[j, 0, h] - z[j, K - 1, h] == d_plus[j, h, K - 1] - d_minus[j, h, K - 1] for j in range(J) for h in range(H))
|
||||
|
||||
mdl.addConstrs(
|
||||
d[k, h] == quicksum(d_plus[j, h, k] for j in range(J)) + quicksum(d_minus[j, h, k] for j in range(J)) for k
|
||||
in range(K) for h in range(H))
|
||||
|
||||
# simultaneous pick
|
||||
for s in range(-(H - 1) * r, S):
|
||||
rng = list(range(max(0, -math.floor(s / r)), min(H, math.ceil((S - s) / r))))
|
||||
for k in range(K):
|
||||
mdl.addConstr(quicksum(x[i, s + h * r, k, h] for h in rng for i in range(I)) <= M * e[s, k], name='')
|
||||
mdl.addConstr(quicksum(x[i, s + h * r, k, h] for h in rng for i in range(I)) >= e[s, k], name='')
|
||||
mdl.addConstr(quicksum(y[s + h * r, k, h] for h in rng) <= M * e[s, k], name='')
|
||||
mdl.addConstr(quicksum(y[s + h * r, k, h] for h in rng) >= e[s, k], name='')
|
||||
|
||||
# pickup movement
|
||||
mdl.addConstrs(
|
||||
u[k] >= s1 * e[s1, k] - s2 * e[s2, k] for s1 in range(-(H - 1) * r, S) for s2 in range(-(H - 1) * r, S) for k in
|
||||
range(K))
|
||||
u[k] >= s1 * e[s1, k] - s2 * e[s2, k] + M * (e[s1, k] + e[s2, k] - 2) for s1 in range(-(H - 1) * r, S) for s2 in
|
||||
range(-(H - 1) * r, S) for k in range(K))
|
||||
|
||||
# feeder related
|
||||
mdl.addConstrs(quicksum(f[s, i] for s in range(S)) <= 1 for i in range(I))
|
||||
mdl.addConstrs(quicksum(f[s, i] for i in range(I)) <= 1 for s in range(S))
|
||||
mdl.addConstrs(
|
||||
quicksum(x[i, s, k, h] for h in range(H) for k in range(K)) >= f[s, i] for i in range(I) for s in range(S))
|
||||
quicksum(x[i, k, h] * y[s, k, h] for h in range(H) for k in range(K)) >= f[s, i] for i in range(I) for s in range(S))
|
||||
mdl.addConstrs(
|
||||
quicksum(x[i, s, k, h] for h in range(H) for k in range(K)) <= M * f[s, i] for i in range(I) for s in
|
||||
quicksum(x[i, k, h] * y[s, k, h] for h in range(H) for k in range(K)) <= M * f[s, i] for i in range(I) for s in
|
||||
range(S))
|
||||
|
||||
# relationship
|
||||
mdl.addConstrs(
|
||||
quicksum(x[i, k, h] for i in range(I)) == quicksum(y[s, k, h] for s in range(S)) for k in range(K) for h in
|
||||
range(H))
|
||||
|
||||
# objective
|
||||
t_c, t_n, t_p, t_m = 2, 6, 1, 0.1
|
||||
mdl.setObjective(t_c * quicksum(g[k] for k in range(K)) + t_n * quicksum(
|
||||
d[k, h] for h in range(H) for k in range(K - 1)) + t_p * quicksum(
|
||||
e[s, k] for s in range(-(H - 1) * r, S) for k in range(K)) + t_m * quicksum(u[k] for k in range(K)),
|
||||
mdl.setObjective(Fit_cy * quicksum(g[k] for k in range(K)) + Fit_nz * quicksum(
|
||||
d[k, h] for h in range(H) for k in range(K)) + Fit_pu * quicksum(
|
||||
e[s, k] for s in range(-(H - 1) * r, S) for k in range(K)) + Fit_mv * head_interval * quicksum(u[k] for k in range(K)),
|
||||
GRB.MINIMIZE)
|
||||
|
||||
mdl.optimize()
|
||||
@ -119,14 +125,17 @@ def head_task_model(component_data, pcb_data, hinter=True):
|
||||
cycle_result.append(1)
|
||||
for h in range(H):
|
||||
for i in range(I):
|
||||
for s in range(S):
|
||||
if abs(x[i, s, k, h].x) > 1e-6:
|
||||
component_result[-1][h] = i
|
||||
feeder_slot_result[-1][h] = slot_start + s * interval_ratio - 1
|
||||
if abs(x[i, k, h].x) > 1e-6:
|
||||
component_result[-1][h] = i
|
||||
|
||||
for s in range(S):
|
||||
if abs(y[s, k, h].x) > 1e-6:
|
||||
feeder_slot_result[-1][h] = slot_start + s * interval_ratio - 1
|
||||
|
||||
|
||||
if hinter:
|
||||
print(component_result)
|
||||
print(feeder_slot_result)
|
||||
|
||||
return component_result, cycle_result, feeder_slot_result
|
||||
|
||||
|
||||
@ -134,7 +143,7 @@ def place_route_model(component_data, pcb_data, component_result, feeder_slot_re
|
||||
mdl = Model('place_route')
|
||||
mdl.setParam('Seed', 0)
|
||||
mdl.setParam('OutputFlag', hinter) # set whether output the debug information
|
||||
# mdl.setParam('TimeLimit', 20)
|
||||
mdl.setParam('TimeLimit', 10)
|
||||
|
||||
component_type = []
|
||||
for _, data in component_data.iterrows():
|
||||
@ -213,21 +222,23 @@ def place_route_model(component_data, pcb_data, component_result, feeder_slot_re
|
||||
for h in range(H):
|
||||
if component_result[k][h] == -1:
|
||||
# no components on the head
|
||||
mdl.addConstr(quicksum(w[p, q, k, a] for a in A_contain(h) for q in range(P) for p in range(P)) == 0)
|
||||
mdl.addConstrs(quicksum(w[p, q, k, a] for a in A_from(h) for q in range(P)) + quicksum(
|
||||
w[q, p, k, a] for a in A_to(h) for q in range(P)) + y[p, k, h] + z[p, k, h] <= 0 for p in range(P))
|
||||
else:
|
||||
# there are components on the head
|
||||
mdl.addConstrs((quicksum(w[p, q, k, a] for a in A_from(h) for q in range(P)) + quicksum(
|
||||
w[q, p, k, a] for a in A_to(h) for q in range(P))) / 2 <= CompOfPoint[component_result[k][h]][p] for
|
||||
p in range(P))
|
||||
mdl.addConstrs(quicksum(w[p, q, k, a] for a in A_from(h) for q in range(P)) + quicksum(
|
||||
w[q, p, k, a] for a in A_to(h) for q in range(P)) + y[p, k, h] + z[p, k, h] <= 4 *
|
||||
CompOfPoint[component_result[k][h]][p] for p in range(P))
|
||||
|
||||
# each head corresponds to a maximum of one point in each cycle
|
||||
mdl.addConstrs(
|
||||
quicksum(w[p, q, k, a] for p in range(P) for q in range(P) for a in A_contain(h)) <= 2 for k in range(K) for h
|
||||
quicksum(w[p, q, k, a] for p in range(P) for q in range(P) for a in A_contain(h))
|
||||
+ quicksum(y[p, k, h] + z[p, k, h] for p in range(P)) <= 2 for k in range(K) for h
|
||||
in range(H))
|
||||
|
||||
mdl.addConstrs(
|
||||
quicksum((y[p, k, h] + z[p, k, h]) for p in range(P)) <= 1 for k in range(K) for h in
|
||||
range(H))
|
||||
# mdl.addConstrs(
|
||||
# quicksum((y[p, k, h] + z[p, k, h]) for p in range(P)) <= 2 for k in range(K) for h in
|
||||
# range(H))
|
||||
|
||||
# task continuity (for the same point the entering head and the leaving head should be same)
|
||||
mdl.addConstrs(quicksum(w[p, q, k, a] for p in range(P) for a in A_to(h)) + y[q, k, h] == quicksum(
|
||||
@ -235,11 +246,11 @@ def place_route_model(component_data, pcb_data, component_result, feeder_slot_re
|
||||
range(P))
|
||||
|
||||
mdl.addConstrs(
|
||||
y[p, k, h] <= quicksum(w[p, q, k, a] for q in range(P) for a in A_from(h)) for h in range(H) for p in
|
||||
range(P) for k in range(K))
|
||||
y[p, k, h] <= quicksum(w[p, q, k, a] for q in range(P) for a in A_from(h)) + z[p, k, h] for h in range(H) for p
|
||||
in range(P) for k in range(K))
|
||||
|
||||
mdl.addConstrs(
|
||||
z[p, k, h] <= quicksum(w[q, p, k, a] for q in range(P) for a in A_to(h)) for h in range(H) for p in
|
||||
z[p, k, h] <= quicksum(w[q, p, k, a] for q in range(P) for a in A_to(h)) + y[p, k, h] for h in range(H) for p in
|
||||
range(P) for k in range(K))
|
||||
|
||||
# one arrival point per cycle
|
||||
@ -309,8 +320,7 @@ def place_route_model(component_data, pcb_data, component_result, feeder_slot_re
|
||||
plt.show()
|
||||
|
||||
# convert model result into standard form
|
||||
placement_result, head_sequence = [[-1 for _ in range(H)] for _ in range(K)], [[] for _ in
|
||||
range(K)]
|
||||
placement_result, head_sequence = [[-1 for _ in range(H)] for _ in range(K)], [[] for _ in range(K)]
|
||||
for k in range(K):
|
||||
arc_list = []
|
||||
for p in range(P):
|
||||
@ -327,6 +337,14 @@ def place_route_model(component_data, pcb_data, component_result, feeder_slot_re
|
||||
for h in range(H):
|
||||
if abs(y[p, k, h].x) > 1e-6:
|
||||
head = h
|
||||
if placement_result[k][h] == -1:
|
||||
placement_result[k][h] = p
|
||||
assert placement_result[k][h] == p
|
||||
|
||||
if abs(z[p, k, h].x) > 1e-6:
|
||||
if placement_result[k][h] == -1:
|
||||
placement_result[k][h] = p
|
||||
assert placement_result[k][h] == p
|
||||
|
||||
while idx < len(arc_list):
|
||||
for i, arc in enumerate(arc_list):
|
||||
@ -344,7 +362,7 @@ def place_route_model(component_data, pcb_data, component_result, feeder_slot_re
|
||||
def optimizer_mathmodel(component_data, pcb_data, hinter=True):
|
||||
|
||||
component_result, cycle_result, feeder_slot_result = head_task_model(component_data, pcb_data, hinter)
|
||||
# placement_result, head_sequence = place_route_model(component_data, pcb_data, component_result, feeder_slot_result)
|
||||
placement_result, head_sequence = greedy_placement_route_generation(component_data, pcb_data, component_result,
|
||||
cycle_result)
|
||||
placement_result, head_sequence = place_route_model(component_data, pcb_data, component_result, feeder_slot_result)
|
||||
# placement_result, head_sequence = greedy_placement_route_generation(component_data, pcb_data, component_result,
|
||||
# cycle_result)
|
||||
return component_result, cycle_result, feeder_slot_result, placement_result, head_sequence
|
||||
|
Reference in New Issue
Block a user