整线优化第一版论文定稿工程
增加了整线批量测试 修改了现有min-max模型路径 修改了遗传算法整体框架 估计器增加异常数据剔除 封装优化结果类 修改供料器扫描算法中重复吸嘴组的判定
This commit is contained in:
218
optimizer.py
218
optimizer.py
@ -1,6 +1,4 @@
|
||||
import random
|
||||
|
||||
import numpy as np
|
||||
import time
|
||||
|
||||
from dataloader import *
|
||||
from lineopt_genetic import line_optimizer_genetic
|
||||
@ -12,32 +10,32 @@ from lineopt_model import line_optimizer_model
|
||||
from base_optimizer.optimizer_interface import *
|
||||
|
||||
|
||||
def optimizer(pcb_data, component_data, line_optimizer, machine_optimizer, machine_number):
|
||||
assembly_info = []
|
||||
if line_optimizer == 'hyper-heuristic' or line_optimizer == 'heuristic' or line_optimizer == 'genetic' or \
|
||||
line_optimizer == 'reconfiguration':
|
||||
if machine_number > 1:
|
||||
if line_optimizer == 'hyper-heuristic':
|
||||
assignment_result = line_optimizer_hyperheuristic(component_data, pcb_data, machine_number)
|
||||
elif line_optimizer == "heuristic":
|
||||
assignment_result = line_optimizer_heuristic(component_data, machine_number)
|
||||
elif line_optimizer == "genetic":
|
||||
assignment_result = line_optimizer_genetic(component_data, machine_number)
|
||||
else:
|
||||
assignment_result = line_optimizer_reconfiguration(component_data, pcb_data, machine_number)
|
||||
else:
|
||||
assignment_result = [[]]
|
||||
for _, data in component_data.iterrows():
|
||||
assignment_result[-1].append(data.points)
|
||||
partial_pcb_data, partial_component_data = convert_line_assigment(pcb_data, component_data, assignment_result)
|
||||
def optimizer(pcb_data, component_data, params):
|
||||
if params.machine_number == 1:
|
||||
assembly_info = [
|
||||
base_optimizer(1, pcb_data, component_data, pd.DataFrame(columns=['slot', 'part', 'arg']), params,
|
||||
hinter=True)]
|
||||
return assembly_info
|
||||
|
||||
for machine_index in range(machine_number):
|
||||
assembly_info.append(
|
||||
base_optimizer(machine_index + 1, partial_pcb_data[machine_index], partial_component_data[machine_index],
|
||||
feeder_data=pd.DataFrame(columns=['slot', 'part', 'arg']), method=machine_optimizer,
|
||||
hinter=True))
|
||||
elif line_optimizer == 'model':
|
||||
assembly_info = line_optimizer_model(component_data, pcb_data, machine_number)
|
||||
if params.line_optimizer == 'hyper-heuristic' or params.line_optimizer == 'heuristic' or params.line_optimizer \
|
||||
== 'genetic' or params.line_optimizer == 'reconfiguration':
|
||||
if params.line_optimizer == 'hyper-heuristic':
|
||||
assignment_result = line_optimizer_hyperheuristic(component_data, pcb_data, params.machine_number)
|
||||
elif params.line_optimizer == "heuristic":
|
||||
assignment_result = line_optimizer_heuristic(component_data, params.machine_number)
|
||||
elif params.line_optimizer == "genetic":
|
||||
assignment_result = line_optimizer_genetic(component_data, params.machine_number)
|
||||
else:
|
||||
assignment_result = line_optimizer_reconfiguration(component_data, pcb_data, params.machine_number)
|
||||
|
||||
partial_pcb_data, partial_component_data = convert_line_assigment(pcb_data, component_data, assignment_result)
|
||||
assembly_info = []
|
||||
for machine_index in range(params.machine_number):
|
||||
assembly_info.append(base_optimizer(machine_index + 1, partial_pcb_data[machine_index],
|
||||
partial_component_data[machine_index],
|
||||
pd.DataFrame(columns=['slot', 'part', 'arg']), params, hinter=True))
|
||||
elif params.line_optimizer == 'model':
|
||||
assembly_info = line_optimizer_model(component_data, pcb_data, params.machine_number)
|
||||
else:
|
||||
raise 'line optimizer method is not existed'
|
||||
|
||||
@ -50,71 +48,151 @@ def main():
|
||||
# 参数解析
|
||||
parser = argparse.ArgumentParser(description='assembly line optimizer implementation')
|
||||
parser.add_argument('--mode', default=1, type=int, help='mode: 0 -directly load pcb data without optimization '
|
||||
'for data analysis, 1 -optimize pcb data')
|
||||
parser.add_argument('--filename', default='PCB.txt', type=str, help='load pcb data')
|
||||
'for data analysis, 1 -optimize pcb data, 2 -batch test')
|
||||
parser.add_argument('--filename', default='L01/KAN3-Z2.txt', type=str, help='load pcb data')
|
||||
parser.add_argument('--comp_register', default=1, type=int, help='register the component according the pcb data')
|
||||
parser.add_argument('--machine_number', default=3, type=int, help='the number of machine in the assembly line')
|
||||
parser.add_argument('--machine_number', default=2, type=int, help='the number of machine in the assembly line')
|
||||
parser.add_argument('--machine_optimizer', default='feeder-scan', type=str, help='optimizer for single machine')
|
||||
parser.add_argument('--line_optimizer', default='hyper-heuristic', type=str, help='optimizer for PCB assembly line')
|
||||
# parser.add_argument('--line_optimizer', default='genetic', type=str, help='optimizer for PCB assembly line')
|
||||
# parser.add_argument('--line_optimizer', default='model', type=str, help='optimizer for PCB assembly line')
|
||||
parser.add_argument('--feeder_limit', default=1, type=int, help='the upper feeder limit for each type of component')
|
||||
parser.add_argument('--save', default=1, type=int, help='save the optimization result')
|
||||
parser.add_argument('--save_suffix', default='(10)', type=str, help='load pcb data')
|
||||
params = parser.parse_args()
|
||||
|
||||
# 结果输出显示所有行和列
|
||||
pd.set_option('display.max_columns', None)
|
||||
pd.set_option('display.max_rows', None)
|
||||
if params.mode == 0:
|
||||
partial_pcb_data, partial_component_data, _ = load_data(params.filename)
|
||||
partial_pcb_data, partial_component_data, _ = load_data(params.filename, load_feeder=False)
|
||||
assembly_info = []
|
||||
for machine_index in range(len(partial_pcb_data)):
|
||||
component_result, cycle_result, feeder_slot_result, placement_result, head_sequence = \
|
||||
convert_pcbdata_to_result(partial_pcb_data[machine_index], partial_component_data[machine_index])
|
||||
print('----- Placement machine ' + str(machine_index) + ' ----- ')
|
||||
opt_res = convert_pcbdata_to_result(partial_pcb_data[machine_index], partial_component_data[machine_index])
|
||||
info = placement_info_evaluation(partial_component_data[machine_index], partial_pcb_data[machine_index],
|
||||
component_result, cycle_result, feeder_slot_result, placement_result,
|
||||
head_sequence)
|
||||
opt_res)
|
||||
assembly_info.append(info)
|
||||
optimization_assign_result(partial_component_data[machine_index], partial_pcb_data[machine_index],
|
||||
component_result, cycle_result, feeder_slot_result, nozzle_hinter=True,
|
||||
component_hinter=True, feeder_hinter=True)
|
||||
optimization_assign_result(partial_component_data[machine_index], partial_pcb_data[machine_index], opt_res,
|
||||
nozzle_hinter=True, component_hinter=True, feeder_hinter=True)
|
||||
|
||||
info.print()
|
||||
if params.save:
|
||||
output_optimize_result(f'result/{params.filename[:-4]}-T-Solution-M0{machine_index + 1}',
|
||||
partial_component_data[machine_index], partial_pcb_data[machine_index], opt_res)
|
||||
print('------------------------------ ')
|
||||
else:
|
||||
|
||||
for machine_idx, info in enumerate(assembly_info):
|
||||
print(f'assembly time for machine {machine_idx + 1: d}: {info.total_time: .3f} s, total placement: '
|
||||
f'{info.total_points}, total component types {info.total_components: d}')
|
||||
|
||||
print(f'finial assembly time: {max(info.total_time for info in assembly_info): .3f} s, '
|
||||
f'standard deviation: {np.std([info.total_time for info in assembly_info]): .3f}')
|
||||
|
||||
elif params.mode == 1:
|
||||
sys.stdout = open(f'record/{params.filename[:-4]}-{params.line_optimizer}.txt', 'w')
|
||||
|
||||
# 加载PCB数据
|
||||
partial_pcb_data, partial_component_data, _ = load_data(params.filename)
|
||||
pcb_data, component_data = merge_data(partial_pcb_data, partial_component_data)
|
||||
start_time = time.time()
|
||||
assembly_info = optimizer(pcb_data, component_data, params)
|
||||
sys.stdout = sys.__stdout__
|
||||
print(f'optimizer running time: {time.time() - start_time: .3f}')
|
||||
for machine_idx, info in enumerate(assembly_info):
|
||||
print(f'assembly time for machine {machine_idx + 1: d}: {info.total_time: .3f} s, total placement: '
|
||||
f'{info.total_points}, total component types {info.total_components: d}')
|
||||
|
||||
assembly_info = optimizer(pcb_data, component_data, params.line_optimizer, params.machine_optimizer,
|
||||
params.machine_number)
|
||||
print(f'assembly metric evaluation: {max(info.metric() for info in assembly_info)}')
|
||||
|
||||
# index_list, part_list = [5, 6, 7, 8, 9, 10, 11, 12, 13], []
|
||||
# for idx in index_list:
|
||||
# part_list.append(component_data.iloc[idx].part)
|
||||
# pcb_data = pcb_data[pcb_data['part'].isin(part_list)].reset_index(drop=True)
|
||||
# component_data = component_data.iloc[index_list].reset_index(drop=True)
|
||||
#
|
||||
# from lineopt_hyperheuristic import DataMgr, Net
|
||||
# data_mgr = DataMgr()
|
||||
#
|
||||
# cp_points, cp_nozzle = defaultdict(int), defaultdict(str)
|
||||
# for _, data in component_data.iterrows():
|
||||
# cp_points[data.part], cp_nozzle[data.part] = data.points, data.nz
|
||||
#
|
||||
# device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
|
||||
# net = Net(input_size=data_mgr.get_feature(), output_size=1).to(device)
|
||||
#
|
||||
# net.load_state_dict(torch.load('model/net_model.pth'))
|
||||
# board_width, board_height = pcb_data['x'].max() - pcb_data['x'].min(), pcb_data['y'].max() - pcb_data['y'].min()
|
||||
# encoding = np.array(data_mgr.encode(cp_points, cp_nozzle, board_width, board_height))
|
||||
# encoding = torch.from_numpy(encoding.reshape((-1, np.shape(encoding)[0]))).float().to("cuda")
|
||||
# print(f'net pred time: {net(encoding)[0, 0].item():.3f}')
|
||||
print(f'finial assembly time: {max(info.total_time for info in assembly_info): .3f} s, '
|
||||
f'standard deviation: {np.std([info.total_time for info in assembly_info]): .3f}')
|
||||
else:
|
||||
# line_optimizer = ['T-Solution', 'hyper-heuristic', 'genetic', 'reconfiguration']
|
||||
line_optimizer = ['genetic']
|
||||
file_dirs = ['L01', 'L02', 'L03']
|
||||
|
||||
for machine_idx, info in enumerate(assembly_info):
|
||||
print(f'assembly time for machine {machine_idx + 1: d}: {info.total_time: .3f} s, total placement: '
|
||||
f'{info.total_points}, total component types {info.total_components: d}')
|
||||
running_round = 10
|
||||
line_opt_result, line_opt_runtime = defaultdict(pd.DataFrame), defaultdict(pd.DataFrame)
|
||||
|
||||
print(f'finial assembly time: {max(info.total_time for info in assembly_info): .3f} s, '
|
||||
f'standard deviation: {np.std([info.total_time for info in assembly_info]): .3f}')
|
||||
opt_columns = []
|
||||
for line_opt in line_optimizer:
|
||||
if line_opt == 'T-Solution':
|
||||
opt_columns.append(line_opt)
|
||||
else:
|
||||
opt_columns.extend([line_opt + str(idx + 1) for idx in range(running_round)])
|
||||
|
||||
for file_dir in file_dirs:
|
||||
line_opt_result[file_dir] = pd.DataFrame(columns=opt_columns)
|
||||
line_opt_runtime[file_dir] = pd.DataFrame(columns=opt_columns)
|
||||
line_opt_result[file_dir].index.name, line_opt_runtime[file_dir].index.name = 'file', 'file'
|
||||
|
||||
for file_index, file in enumerate(os.listdir('data/' + file_dir)):
|
||||
sys.stdout = sys.__stdout__
|
||||
print(f'--- {file_dir} : ({file_index + 1}) file : {file} --- ')
|
||||
try:
|
||||
partial_pcb_data, partial_component_data, _ = load_data(file_dir + '/' + file, load_feeder=False)
|
||||
except:
|
||||
traceback.print_exc()
|
||||
warning_info = f'file: {file_dir}/{file}: an unexpected error occurs for data loader'
|
||||
warnings.warn(warning_info, SyntaxWarning)
|
||||
continue
|
||||
machine_number = len(partial_pcb_data)
|
||||
if not os.path.exists(f'record/{file_dir}'):
|
||||
os.makedirs(f'record/{file_dir}')
|
||||
merge_pcb_data, merge_component_data = merge_data(partial_pcb_data, partial_component_data)
|
||||
for line_opt in line_optimizer:
|
||||
assembly_info = []
|
||||
if line_opt == 'T-Solution':
|
||||
sys.stdout = open(f'record/{file_dir}/{file[:-4]}-{line_opt}.txt', 'w')
|
||||
for machine_index in range(machine_number):
|
||||
opt_res = convert_pcbdata_to_result(partial_pcb_data[machine_index],
|
||||
partial_component_data[machine_index])
|
||||
|
||||
print('----- Placement machine ' + str(machine_index + 1) + ' ----- ')
|
||||
info = placement_info_evaluation(partial_component_data[machine_index],
|
||||
partial_pcb_data[machine_index], opt_res, hinter=True)
|
||||
print('------------------------------ ')
|
||||
assembly_info.append(info)
|
||||
if params.save:
|
||||
output_optimize_result(f'result/{file_dir}/{file[:-4]}-T-Solution-M0{machine_index + 1}',
|
||||
partial_component_data[machine_index],
|
||||
partial_pcb_data[machine_index], opt_res)
|
||||
|
||||
line_opt_result[file_dir].loc[file, line_opt] = max(info.total_time for info in assembly_info)
|
||||
for machine_idx, info in enumerate(assembly_info):
|
||||
print(
|
||||
f'assembly time for machine {machine_idx + 1: d}: {info.total_time: .3f} s, total placement: '
|
||||
f'{info.total_points}, total component types {info.total_components: d}')
|
||||
|
||||
print(f'finial assembly time: {max(info.total_time for info in assembly_info): .3f} s, '
|
||||
f'standard deviation: {np.std([info.total_time for info in assembly_info]): .3f}')
|
||||
else:
|
||||
for round_idx in range(running_round):
|
||||
sys.stdout = open(f'record/{file_dir}/{file[:-4]}-{line_opt} ({round_idx + 1}).txt', 'w')
|
||||
|
||||
params = parser.parse_args(
|
||||
['--filename', file_dir + '/' + file, '--machine_number', str(machine_number),
|
||||
'--line_optimizer', line_opt, '--save_suffix', f'({round_idx + 1})'])
|
||||
start_time = time.time()
|
||||
assembly_info = optimizer(merge_pcb_data, merge_component_data, params)
|
||||
|
||||
line_opt_result[file_dir].loc[file, line_opt + str(round_idx + 1)] = max(
|
||||
info.total_time for info in assembly_info)
|
||||
line_opt_runtime[file_dir].loc[file, line_opt + str(round_idx + 1)] = time.time() - start_time
|
||||
for machine_idx, info in enumerate(assembly_info):
|
||||
print(
|
||||
f'assembly time for machine {machine_idx + 1: d}: {info.total_time: .3f} s, '
|
||||
f'total placement: {info.total_points}, '
|
||||
f'total component types {info.total_components: d}')
|
||||
|
||||
print(f'finial assembly time: {max(info.total_time for info in assembly_info): .3f} s, '
|
||||
f'standard deviation: {np.std([info.total_time for info in assembly_info]): .3f}')
|
||||
|
||||
with pd.ExcelWriter('result/line_optimizer.xlsx', engine='openpyxl') as writer:
|
||||
for file_dir, result in line_opt_result.items():
|
||||
result.to_excel(writer, sheet_name='result-' + file_dir, float_format='%.3f', na_rep='')
|
||||
|
||||
for file_dir, running_time in line_opt_runtime.items():
|
||||
running_time.to_excel(writer, sheet_name='running_time-' + file_dir, float_format='%.3f', na_rep='')
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
Reference in New Issue
Block a user