修改整线算法评价函数
This commit is contained in:
@ -1,4 +1,6 @@
|
|||||||
# implementation of <<An integrated allocation method for the PCB assembly line balancing problem with nozzle changes>>
|
# implementation of <<An integrated allocation method for the PCB assembly line balancing problem with nozzle changes>>
|
||||||
|
import copy
|
||||||
|
|
||||||
import matplotlib.pyplot as plt
|
import matplotlib.pyplot as plt
|
||||||
|
|
||||||
from base_optimizer.optimizer_common import *
|
from base_optimizer.optimizer_common import *
|
||||||
@ -134,9 +136,10 @@ def selective_crossover(component_points, component_feeders, mother, father, non
|
|||||||
def cal_individual_val(component_points, component_nozzle, individual):
|
def cal_individual_val(component_points, component_nozzle, individual):
|
||||||
idx, objective_val = 0, []
|
idx, objective_val = 0, []
|
||||||
machine_component_points = [[] for _ in range(max_machine_index)]
|
machine_component_points = [[] for _ in range(max_machine_index)]
|
||||||
|
nozzle_component_points = defaultdict(list)
|
||||||
|
|
||||||
# decode the component allocation
|
# decode the component allocation
|
||||||
for _, points in component_points:
|
for comp_idx, points in component_points:
|
||||||
component_gene = individual[idx: idx + points + max_machine_index - 1]
|
component_gene = individual[idx: idx + points + max_machine_index - 1]
|
||||||
machine_idx, component_counter = 0, 0
|
machine_idx, component_counter = 0, 0
|
||||||
for gene in component_gene:
|
for gene in component_gene:
|
||||||
@ -149,6 +152,11 @@ def cal_individual_val(component_points, component_nozzle, individual):
|
|||||||
machine_component_points[-1].append(component_counter)
|
machine_component_points[-1].append(component_counter)
|
||||||
idx += (points + max_machine_index - 1)
|
idx += (points + max_machine_index - 1)
|
||||||
|
|
||||||
|
nozzle_component_points[component_nozzle[comp_idx]] = [0] * len(component_points) # 初始化元件-吸嘴点数列表
|
||||||
|
|
||||||
|
for comp_idx, points in component_points:
|
||||||
|
nozzle_component_points[component_nozzle[comp_idx]][comp_idx] = points
|
||||||
|
|
||||||
for machine_idx in range(max_machine_index):
|
for machine_idx in range(max_machine_index):
|
||||||
nozzle_points = defaultdict(int)
|
nozzle_points = defaultdict(int)
|
||||||
for idx, nozzle in component_nozzle.items():
|
for idx, nozzle in component_nozzle.items():
|
||||||
@ -166,6 +174,8 @@ def cal_individual_val(component_points, component_nozzle, individual):
|
|||||||
total_heads = (1 + ul) * max_head_index - len(nozzle_points)
|
total_heads = (1 + ul) * max_head_index - len(nozzle_points)
|
||||||
nozzle_heads = defaultdict(int)
|
nozzle_heads = defaultdict(int)
|
||||||
for nozzle in nozzle_points.keys():
|
for nozzle in nozzle_points.keys():
|
||||||
|
if nozzle_points[nozzle] == 0:
|
||||||
|
continue
|
||||||
nozzle_heads[nozzle] = math.floor(nozzle_points[nozzle] * 1.0 / machine_points * total_heads)
|
nozzle_heads[nozzle] = math.floor(nozzle_points[nozzle] * 1.0 / machine_points * total_heads)
|
||||||
nozzle_heads[nozzle] += 1
|
nozzle_heads[nozzle] += 1
|
||||||
|
|
||||||
@ -173,7 +183,8 @@ def cal_individual_val(component_points, component_nozzle, individual):
|
|||||||
for heads in nozzle_heads.values():
|
for heads in nozzle_heads.values():
|
||||||
total_heads -= heads
|
total_heads -= heads
|
||||||
|
|
||||||
for nozzle in sorted(nozzle_heads, key=lambda x: nozzle_points[x] / nozzle_heads[x], reverse=True):
|
while True:
|
||||||
|
nozzle = max(nozzle_heads, key=lambda x: nozzle_points[x] / nozzle_heads[x])
|
||||||
if total_heads == 0:
|
if total_heads == 0:
|
||||||
break
|
break
|
||||||
nozzle_heads[nozzle] += 1
|
nozzle_heads[nozzle] += 1
|
||||||
@ -193,11 +204,38 @@ def cal_individual_val(component_points, component_nozzle, individual):
|
|||||||
heads_placement[idx][1] += 1
|
heads_placement[idx][1] += 1
|
||||||
heads_placement = sorted(heads_placement, key=lambda x: x[1], reverse=True)
|
heads_placement = sorted(heads_placement, key=lambda x: x[1], reverse=True)
|
||||||
|
|
||||||
|
# the number of pick-up operations
|
||||||
|
# (under the assumption of the number of feeder available for each comp. type is equal 1)
|
||||||
|
pl = 0
|
||||||
|
heads_placement_points = [0 for _ in range(max_head_index)]
|
||||||
|
while True:
|
||||||
|
head_assign_point = []
|
||||||
|
for head in range(max_head_index):
|
||||||
|
if heads_placement_points[head] != 0 or heads_placement[head] == 0:
|
||||||
|
continue
|
||||||
|
|
||||||
|
nozzle, points = heads_placement[head]
|
||||||
|
max_comp_index = np.argmax(nozzle_component_points[nozzle])
|
||||||
|
|
||||||
|
heads_placement_points[head] = min(points, nozzle_component_points[nozzle][max_comp_index])
|
||||||
|
nozzle_component_points[nozzle][max_comp_index] -= heads_placement_points[head]
|
||||||
|
|
||||||
|
head_assign_point.append(heads_placement_points[head])
|
||||||
|
|
||||||
|
min_points_list = list(filter(lambda x: x > 0, heads_placement_points))
|
||||||
|
if len(min_points_list) == 0 or len(head_assign_point) == 0:
|
||||||
|
break
|
||||||
|
|
||||||
|
pl += max(head_assign_point)
|
||||||
|
|
||||||
|
for head in range(max_head_index):
|
||||||
|
heads_placement[head][1] -= min(min_points_list)
|
||||||
|
heads_placement_points[head] -= min(min_points_list)
|
||||||
|
|
||||||
# every max_head_index heads in the non-decreasing order are grouped together as nozzle set
|
# every max_head_index heads in the non-decreasing order are grouped together as nozzle set
|
||||||
for idx in range(len(heads_placement) // max_head_index):
|
for idx in range(len(heads_placement) // max_head_index):
|
||||||
wl += heads_placement[idx][1]
|
wl += heads_placement[idx][1]
|
||||||
objective_val.append(T_pp * machine_points + T_tr * wl + T_nc * ul)
|
objective_val.append(T_pp * machine_points + T_tr * wl + T_nc * ul + T_pl * pl)
|
||||||
|
|
||||||
return objective_val, machine_component_points
|
return objective_val, machine_component_points
|
||||||
|
|
||||||
|
|
||||||
@ -206,9 +244,8 @@ def assemblyline_optimizer_genetic(pcb_data, component_data):
|
|||||||
# crossover rate & mutation rate: 80% & 10%
|
# crossover rate & mutation rate: 80% & 10%
|
||||||
# population size: 200
|
# population size: 200
|
||||||
# the number of generation: 500
|
# the number of generation: 500
|
||||||
np.random.seed(0)
|
|
||||||
crossover_rate, mutation_rate = 0.8, 0.1
|
crossover_rate, mutation_rate = 0.8, 0.1
|
||||||
population_size, n_generations = 200, 500
|
population_size, n_generations = 500, 500
|
||||||
|
|
||||||
# the number of placement points, the number of available feeders, and nozzle type of component respectively
|
# the number of placement points, the number of available feeders, and nozzle type of component respectively
|
||||||
component_points, component_feeders, component_nozzle = defaultdict(int), defaultdict(int), defaultdict(str)
|
component_points, component_feeders, component_nozzle = defaultdict(int), defaultdict(int), defaultdict(str)
|
||||||
@ -228,7 +265,7 @@ def assemblyline_optimizer_genetic(pcb_data, component_data):
|
|||||||
with tqdm(total=n_generations) as pbar:
|
with tqdm(total=n_generations) as pbar:
|
||||||
pbar.set_description('genetic algorithm process for PCB assembly line balance')
|
pbar.set_description('genetic algorithm process for PCB assembly line balance')
|
||||||
|
|
||||||
new_population, new_pop_val = [], []
|
new_population = []
|
||||||
for _ in range(n_generations):
|
for _ in range(n_generations):
|
||||||
# calculate fitness value
|
# calculate fitness value
|
||||||
pop_val = []
|
pop_val = []
|
||||||
@ -237,8 +274,7 @@ def assemblyline_optimizer_genetic(pcb_data, component_data):
|
|||||||
pop_val.append(max(val))
|
pop_val.append(max(val))
|
||||||
|
|
||||||
best_popval.append(min(pop_val))
|
best_popval.append(min(pop_val))
|
||||||
|
select_index = get_top_k_value(pop_val, population_size - len(new_population), reverse=False)
|
||||||
select_index = get_top_k_value(pop_val, population_size - len(new_pop_val), reverse=False)
|
|
||||||
population = [population[idx] for idx in select_index]
|
population = [population[idx] for idx in select_index]
|
||||||
pop_val = [pop_val[idx] for idx in select_index]
|
pop_val = [pop_val[idx] for idx in select_index]
|
||||||
|
|
||||||
@ -270,7 +306,7 @@ def assemblyline_optimizer_genetic(pcb_data, component_data):
|
|||||||
offspring1 = constraint_swap_mutation(component_points, offspring1)
|
offspring1 = constraint_swap_mutation(component_points, offspring1)
|
||||||
|
|
||||||
if np.random.random() < mutation_rate:
|
if np.random.random() < mutation_rate:
|
||||||
offspring1 = constraint_swap_mutation(component_points, offspring1)
|
offspring2 = constraint_swap_mutation(component_points, offspring2)
|
||||||
|
|
||||||
new_population.append(offspring1)
|
new_population.append(offspring1)
|
||||||
new_population.append(offspring2)
|
new_population.append(offspring2)
|
||||||
|
Reference in New Issue
Block a user