增加超启发式线体优化算法
This commit is contained in:
@ -11,13 +11,13 @@ from base_optimizer.result_analysis import *
|
||||
|
||||
# TODO: nozzle tool available restriction
|
||||
# TODO: consider with the PCB placement topology
|
||||
def assembly_time_estimator(assignment_points, component_feeders, component_nozzle):
|
||||
def assembly_time_estimator(assignment_points, arranged_feeders, component_data):
|
||||
nozzle_heads, nozzle_points = defaultdict(int), defaultdict(int)
|
||||
for idx, points in enumerate(assignment_points):
|
||||
if points == 0:
|
||||
continue
|
||||
nozzle_points[component_nozzle[idx]] += points
|
||||
nozzle_heads[component_nozzle[idx]] = 1
|
||||
nozzle_points[component_data.iloc[idx]['nz']] += points
|
||||
nozzle_heads[component_data.iloc[idx]['nz']] = 1
|
||||
|
||||
while sum(nozzle_heads.values()) != max_head_index:
|
||||
max_cycle_nozzle = None
|
||||
@ -174,10 +174,11 @@ def assembly_time_estimator(assignment_points, component_feeders, component_nozz
|
||||
for idx, points in enumerate(assignment_points):
|
||||
if points == 0:
|
||||
continue
|
||||
reminder_points = points % component_feeders[idx]
|
||||
for _ in range(component_feeders[idx]):
|
||||
feeder_limit = int(component_data.iloc[idx]['feeder-limit'])
|
||||
reminder_points = points % feeder_limit
|
||||
for _ in range(feeder_limit):
|
||||
cp_info.append(
|
||||
[idx, points // component_feeders[idx] + (1 if reminder_points > 0 else 0), component_nozzle[idx]])
|
||||
[idx, points // feeder_limit + (1 if reminder_points > 0 else 0), component_data.iloc[idx]['nz']])
|
||||
reminder_points -= 1
|
||||
|
||||
cp_info.sort(key=lambda x: -x[1])
|
||||
@ -204,46 +205,35 @@ def assembly_time_estimator(assignment_points, component_feeders, component_nozz
|
||||
t_place * placement_counter + 0.1 * pickup_movement
|
||||
|
||||
|
||||
def assemblyline_optimizer_heuristic(pcb_data, component_data, machine_number):
|
||||
def line_optimizer_heuristic(component_data, machine_number):
|
||||
# the number of placement points, the number of available feeders, and nozzle type of component respectively
|
||||
component_number = len(component_data)
|
||||
|
||||
component_points = [0 for _ in range(component_number)]
|
||||
component_feeders = [0 for _ in range(component_number)]
|
||||
component_nozzle = [0 for _ in range(component_number)]
|
||||
component_part = [0 for _ in range(component_number)]
|
||||
|
||||
nozzle_points = defaultdict(int) # the number of placements of nozzle
|
||||
|
||||
for _, data in pcb_data.iterrows():
|
||||
part_index = component_data[component_data['part'] == data['part']].index.tolist()[0]
|
||||
nozzle = component_data.loc[part_index]['nz']
|
||||
|
||||
component_points[part_index] += 1
|
||||
component_feeders[part_index] = component_data.loc[part_index]['feeder-limit']
|
||||
# component_feeders[part_index] = math.ceil(component_data.loc[part_index]['feeder-limit'] / max_feeder_limit)
|
||||
component_nozzle[part_index] = nozzle
|
||||
component_part[part_index] = data['part']
|
||||
|
||||
nozzle_points[nozzle] += 1
|
||||
total_points = 0
|
||||
for _, data in component_data.iterrows():
|
||||
nozzle = data['nz']
|
||||
nozzle_points[nozzle] += data['points']
|
||||
total_points += data['point']
|
||||
|
||||
# first step: generate the initial solution with equalized workload
|
||||
assignment_result = [[0 for _ in range(len(component_points))] for _ in range(machine_number)]
|
||||
assignment_result = [[0 for _ in range(len(component_data))] for _ in range(machine_number)]
|
||||
assignment_points = [0 for _ in range(machine_number)]
|
||||
average_points = len(pcb_data) // machine_number
|
||||
average_points = total_points // machine_number
|
||||
|
||||
weighted_points = list(
|
||||
map(lambda x: x[1] + 1e-5 * nozzle_points[component_nozzle[x[0]]], enumerate(component_points)))
|
||||
map(lambda _, data: data['points'] + 1e-5 * nozzle_points[data['nz']], component_data.iterrows()))
|
||||
|
||||
# for part_index in np.argsort(weighted_points)[::-1]:
|
||||
for part_index in np.argsort(weighted_points)[::-1]:
|
||||
if (total_points := component_points[part_index]) == 0: # total placements for each component type
|
||||
if (total_points := component_data.iloc[part_index]['points']) == 0: # total placements for each component type
|
||||
continue
|
||||
machine_set = []
|
||||
|
||||
# define the machine that assigning placement points (considering the feeder limitation)
|
||||
for machine_index in np.argsort(assignment_points):
|
||||
if len(machine_set) >= component_points[part_index] or len(machine_set) >= component_feeders[part_index]:
|
||||
if len(machine_set) >= component_data.iloc[part_index]['points'] or len(machine_set) >= \
|
||||
component_data.iloc[part_index]['feeder-limit']:
|
||||
break
|
||||
|
||||
machine_set.append(machine_index)
|
||||
@ -308,7 +298,7 @@ def assemblyline_optimizer_heuristic(pcb_data, component_data, machine_number):
|
||||
arranged_feeders[machine_index] = [0 for _ in range(len(component_data))]
|
||||
|
||||
for part_index in range(len(component_data)):
|
||||
feeder_limit = component_feeders[part_index] # 总体可用数
|
||||
feeder_limit = component_data.iloc[part_index]['feeder-limit'] # 总体可用数
|
||||
for machine_index in range(machine_number):
|
||||
if assignment_result[machine_index][part_index] == 0:
|
||||
continue
|
||||
@ -318,7 +308,7 @@ def assemblyline_optimizer_heuristic(pcb_data, component_data, machine_number):
|
||||
assert feeder_limit >= 0
|
||||
|
||||
for part_index in range(len(component_data)):
|
||||
total_feeder_limit = component_feeders[part_index] - sum(
|
||||
total_feeder_limit = component_data.iloc[part_index]['feeder-limit'] - sum(
|
||||
[arranged_feeders[machine_index][part_index] for machine_index in range(machine_number)])
|
||||
while total_feeder_limit > 0:
|
||||
max_ratio, max_ratio_machine = None, -1
|
||||
@ -336,7 +326,7 @@ def assemblyline_optimizer_heuristic(pcb_data, component_data, machine_number):
|
||||
for machine_index in range(machine_number):
|
||||
assembly_time.append(
|
||||
assembly_time_estimator(assignment_result[machine_index], arranged_feeders[machine_index],
|
||||
component_nozzle))
|
||||
component_data))
|
||||
chip_per_hour.append(sum(assignment_result[machine_index]) / (assembly_time[-1] + 1e-10))
|
||||
|
||||
max_assembly_time = max(assembly_time)
|
||||
@ -351,7 +341,6 @@ def assemblyline_optimizer_heuristic(pcb_data, component_data, machine_number):
|
||||
|
||||
# third step: adjust the assignment results to reduce maximal assembly time among all machines
|
||||
# ideal averagely assigned points
|
||||
total_points = len(pcb_data)
|
||||
average_assign_points = [round(total_points * chip_per_hour[mi] / sum(chip_per_hour)) for mi in
|
||||
range(machine_number)]
|
||||
|
||||
@ -391,7 +380,7 @@ def assemblyline_optimizer_heuristic(pcb_data, component_data, machine_number):
|
||||
tmp_reallocate_result[supply_mi] -= reallocate_points
|
||||
tmp_reallocate_result[demand_mi] += reallocate_points
|
||||
|
||||
if sum(1 for pt in tmp_reallocate_result if pt > 0) > component_feeders[part_index]:
|
||||
if sum(1 for pt in tmp_reallocate_result if pt > 0) > component_data.iloc[part_index]['feeder-limit']:
|
||||
continue
|
||||
|
||||
assignment_result[supply_mi][part_index] -= reallocate_points
|
||||
|
Reference in New Issue
Block a user