遗传算法
常用步骤
变异、交叉、适应度计算、选择
变异(基因突变)
设置变异率,判断当前个体是否可以变异
1 2 3
| mutation_rate = 0.1 if random.random() < mutation_rate: ....
|
设置个体变异比例,判断当前个体能够变异的bits在哪里
1 2 3 4
| mutate_point = random.sample(range(1, len(chromosome)), int(len(chromosome) * mutation_point_rate)) mutate_point.sort() for i in mutate_point: chromosome[i] = chromosome[i] ^ 1
|
交叉(染色体交换)
可以设置一个交叉点,也可以设置多个交叉点,通常是百分之五十交叉
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| def crossover(parent1, parent2): if random.random() < crossover_rate: crossover_points = random.sample(range(1, len(parent1)), 50) crossover_points.sort() child1 = [] child2 = [] parent_switch = True for i in range(len(parent1)): if i in crossover_points: parent_switch = not parent_switch if parent_switch: child1.append(parent1[i]) child2.append(parent2[i]) else: child1.append(parent2[i]) child2.append(parent1[i]) return child1, child2 else: return parent1, parent2
|
适应度计算
即将生成的后代个体与期望达到的目标进行对比,计算差距,即适应度。
- 二进制测试:与能够触发crash的目标进行适应度计算
- CANID测试:与能够响应车机的CANID进行适应度计算
1 2 3 4 5 6 7 8 9 10
| def fitness(chromosome): data = [] for i in range(num_targets): target_value = input_data[i] binary_str = ''.join(map(str, chromosome[i * num_bits:(i + 1) * num_bits])) decimal_value = int(binary_str, 2) data.append(decimal_value) fitness_value = sum(abs(data[i] - input_data[i]) for i in range(num_targets)) return fitness_value
|
这里的input_data
即为期望达到的目标
选择
当种群达到一定规模后,需要控制种群数量,留下更多的优质基因,那么这时候就需要进行自然选择了,也就是选择那些和期望目标差距更小,适应度更小的后代。
1 2 3 4 5 6 7 8
| def selection(population): fitness_values = [fitness(chromosome) for chromosome in population] total_fitness = sum(fitness_values) probabilities = [fitness_value / total_fitness for fitness_value in fitness_values] selected_indices = random.choices(range(population_size), probabilities, k=population_size) selected_population = [population[i] for i in selected_indices] return selected_population
|
去世
按理说应该要加入这个算法的,即当繁殖几代之后,那些老一代就应该死去,不管是不是最优的
主要遗传算法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| def genetic_algorithm(): population = initialize_population() for generation in range(num_generations): population = selection(population) new_population = [] while len(new_population) < population_size: parent1, parent2 = random.sample(population, 2) child1, child2 = crossover(parent1, parent2) child1 = mutate(child1) child2 = mutate(child2) new_population.extend([child1, child2]) population = new_population best_chromosome = min(population, key=fitness) best_data = [] for i in range(num_targets): binary_str = ''.join(map(str, best_chromosome[i * num_bits:(i + 1) * num_bits])) decimal_value = hex(int(binary_str, 2)) best_data.append(decimal_value) print(f"Generation {generation + 1}: Fitness = {fitness(best_chromosome)}, Data = {best_data}")
|
依据设定最大种群数量,不断进行繁殖,直到种群数量已满,再进行下一轮的繁殖得到的后代应该进行自然选择。
模拟退火
主要就是降温和计算概率是否替换新的一代。
以旅行商TSP问题为例子
总的代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
| def simulated_annealing_tsp(cities, initial_temperature=1000.0, cooling_rate=0.95, min_temperature=0.1): current_path = list(range(len(cities))) random.shuffle(current_path) current_distance = total_distance(current_path)
temperature = initial_temperature
while temperature > min_temperature: new_path = current_path.copy() index1, index2 = random.sample(range(len(new_path)), 2) new_path[index1], new_path[index2] = new_path[index2], new_path[index1] new_distance = total_distance(new_path)
if new_distance < current_distance: current_path, current_distance = new_path, new_distance else: delta = new_distance - current_distance probability = math.exp(-delta / temperature) if random.random() < probability: current_path, current_distance = new_path, new_distance
temperature *= cooling_rate
return current_path, current_distance
sa_best_path, sa_best_distance = simulated_annealing_tsp(cities) print("最优路径:", sa_best_path) print("最优距离:", total_distance(sa_best_path))
|
设定初始温度,降温比例,最小温度,初代路径
1 2 3 4 5 6 7 8 9 10 11 12
| initial_temperature=1000.0
cooling_rate=0.95
min_temperature=0.1
current_path = list(range(len(cities))) random.shuffle(current_path) current_distance = total_distance(current_path)
temperature = initial_temperature
|
判断是否达到最低温度
1
| while temperature > min_temperature:
|
依次类推,直到达到最低温度跳出循环