Files
smt-optimizer/optimizer.py

236 lines
14 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import time
import pandas as pd
from dataloader import *
from lineopt_genetic import line_optimizer_genetic
from lineopt_heuristic import line_optimizer_heuristic
from lineopt_reconfiguration import line_optimizer_reconfiguration
from lineopt_hyperheuristic import line_optimizer_hyperheuristic
from lineopt_model import line_optimizer_model
from base_optimizer.optimizer_interface import *
def optimizer(pcb_data, component_data, feeder_data, params):
if params.machine_number == 1:
assembly_info = [base_optimizer(1, pcb_data, component_data, feeder_data, params, hinter=True)]
return assembly_info
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']), params, hinter=True))
elif params.line_optimizer == 'mip-model':
assembly_info = line_optimizer_model(component_data, pcb_data, params.machine_number)
else:
raise 'line optimizer method is not existed'
return assembly_info
@timer_wrapper
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, 2 -batch test')
parser.add_argument('--filename', default='PCB.txt', type=str, help='load pcb data')
# parser.add_argument('--filename', default='chapter3-2/PCB2-8 Arg1.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=1, type=int, help='the number of machine in the assembly line')
# parser.add_argument('--machine_optimizer', default='mip-model', type=str, help='optimizer for single machine')
parser.add_argument('--machine_optimizer', default='feeder-priority', 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='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=0, 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, load_feeder=False)
assembly_info = []
for machine_index in range(len(partial_pcb_data)):
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],
opt_res)
assembly_info.append(info)
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('------------------------------ ')
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, feeder_data = load_data(params.filename, load_feeder=True)
pcb_data, component_data = merge_data(partial_pcb_data, partial_component_data)
start_time = time.time()
assembly_info = optimizer(pcb_data, component_data, feeder_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}')
print(f'assembly metric evaluation {max(info.metric() for info in assembly_info)}')
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 == 2:
machine_optimizer = ['two-phase', 'hybrid-genetic', 'cell-division', 'feeder-priority', 'aggregation']
running_round = 10
opt_columns = ['Cycle', 'Pick', 'Nozzle-Change', 'Running-Time']
opt_result, opt_runtime = defaultdict(pd.DataFrame), defaultdict(pd.DataFrame)
for opt in machine_optimizer:
opt_result[opt] =pd.DataFrame(columns=opt_columns)
opt_result[opt].index.name = 'file'
for _, file in enumerate(os.listdir('data/')):
if file[-3:] != 'txt':
continue
partial_pcb_data, partial_component_data, feeder_data = load_data(file)
pcb_data, component_data = merge_data(partial_pcb_data, partial_component_data)
for opt in machine_optimizer:
for round_idx in range(running_round):
print(f'--- file {file}, round {round_idx}, optimizer {opt} --- ')
params = parser.parse_args(['--machine_optimizer', opt, '--machine_number', str(1)])
start_time = time.time()
assembly_info = optimizer(pcb_data, component_data, feeder_data, params)
opt_result[opt].loc[file + str(round_idx + 1), 'Cycle'] = assembly_info[0].cycle_counter
opt_result[opt].loc[file + str(round_idx + 1), 'Pick'] = assembly_info[0].pickup_counter
opt_result[opt].loc[file + str(round_idx + 1), 'Nozzle-Change'] = assembly_info[0].nozzle_change_counter
opt_result[opt].loc[file + str(round_idx + 1), 'Running-Time'] = time.time() - start_time
with pd.ExcelWriter('result/machine_optimizer.xlsx', engine='openpyxl') as writer:
for opt, result in opt_result.items():
result.to_excel(writer, sheet_name=opt, float_format='%.3f', na_rep='')
else:
# line_optimizer = ['T-Solution', 'hyper-heuristic', 'genetic', 'reconfiguration']
line_optimizer = ['genetic']
file_dirs = ['L01', 'L02', 'L03']
running_round = 10
line_opt_result, line_opt_runtime = defaultdict(pd.DataFrame), defaultdict(pd.DataFrame)
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__':
main()