[Array]485. Max Consecutive Ones

本文介绍一种简单有效的算法来统计01数组中最长连续1的个数。通过遍历数组并计数,该算法能高效处理各种情况,包括边界条件。

题目:

题目分析:

      很显然题目的要求是让程序分析一个01数组中连续出现最多1的个数。那么简单的方法就是以遍历整个数组的形式统计出现最多的1的个数。

关键变量:

      count:用于统计每组连续1的个数;

      MAX:用于统计count的最大值并在函数尾返回。

代码完成:

要点:

      ①主干思路为遍历到1开始统计,遍历到0结束统计并处理统计结果;

      ②难点为某些极端情况的考量。一个是如果数组最后一个数为1,那么就会失去统计结束的标志导致程序错误,解决方法为单独加入对遍历下标的判断,若出现遍历到数组末尾的情况也视为该组统计结束;另一个极端情况是若数组为 [1] 的情况,这次算法中并没有这种情况并不是特例,所以直接略过。

# 基于蚁群算法的多机械臂取苗问题 import numpy as np import random import math import copy import matplotlib.pyplot as plt import time import sys import os # 添加父目录到搜索路径 parent_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) sys.path.append(parent_dir) from class_common_function import common_function plt.rcParams['font.sans-serif'] = ['SimHei'] class AntColonyOptimization: def __init__(self, x_num, y_num, empty_num, num_ants=100, alpha=1, beta=5, evaporation_rate=0.5, Q=100, random_seed=1): # 初始化算法参数和问题数据 if random_seed is not None: random.seed(random_seed) np.random.seed(random_seed) self.num_ants = num_ants self.alpha = alpha self.beta = beta self.evaporation_rate = evaporation_rate self.Q = Q self.common_func = common_function(x_num=x_num, y_num=y_num, empty_num=empty_num) self.x_num = self.common_func.x_num self.y_num = self.common_func.y_num self.positions = self.common_func.positions self.exist_position = self.common_func.exist_position self.target_need_number = self.common_func.target_need_number self.supply_need_number = self.common_func.supply_need_number self.empty_num = self.common_func.empty_num self.target_state = self.common_func.target_state self.supply_state = self.common_func.supply_state self.supply_order_array = self.common_func.supply_order_array self.target_order_array = self.common_func.target_order_array self.num_points = len(self.positions) self.distance_matrix, self.max_distance, self.min_distance= self.calc_distance_matrix() self.pheromone_matrix = np.ones((self.num_points, self.num_points)) self.best_path = [] self.best_fitness = 0 def calc_distance_matrix(self): # 计算所有点之间的欧几里得距离矩阵 num_points = self.num_points distance_matrix = np.zeros((num_points, num_points)) for i in range(num_points): for j in range(num_points): distance_matrix[i][j] = math.sqrt((self.positions[i][0] - self.positions[j][0])**2 + (self.positions[i][1] - self.positions[j][1])**2) max_distance = max(max(row) for row in distance_matrix) min_distance = min(min(row) for row in distance_matrix) return distance_matrix, max_distance, min_distance def calc_path_distance(self, path): return self.common_func.calc_path_distance(path) def construct_solution(self, gen): # 构建解决方案:双机械臂路径规划 all_paths = [] all_distances = [] # 为每只蚂蚁构建路径 for ant in range(self.num_ants): path = [[0],[self.x_num*self.y_num*2+1]] visited_supply = set() visited_target = set() # 构建路径直到完成所有任务 start_time=time.time() memory=[] while len(path[0])-1< self.empty_num: if self.empty_num %2!= 0: if len(path[0]) == self.empty_num: break next_points=[] current = path[0][-1] if len(path[0]) > 1 else path[0][0] # 奇数步:选择供应苗盘点 if len(path[0]) % 2 == 1: available_points = [p for p in self.supply_need_number if p not in visited_supply] if not available_points: break # 计算转移概率 probabilities = {} for next_point in available_points: pheromone = self.pheromone_matrix[current][next_point] ** self.alpha visibility = ((self.max_distance - self.distance_matrix[current][next_point])/(self.max_distance - self.min_distance)) ** self.beta probabilities[next_point] = pheromone * visibility # 偶数步:选择目标苗盘点 # 偶数步:选择目标苗盘点 else: available_points = [p for p in self.target_need_number if p not in visited_target] if not available_points: break # 计算转移概率 probabilities = {} for next_point in available_points: pheromone_value = max(self.pheromone_matrix[current][next_point], 1e-10) pheromone = pheromone_value ** self.alpha visibility = ((self.max_distance - self.distance_matrix[current][next_point])/(self.max_distance - self.min_distance)) ** self.beta # visibility = (1 / self.distance_matrix[current][next_point]) ** self.beta probabilities[next_point] = pheromone * visibility # 归一化概率 total = sum(probabilities.values()) normalized_probs = {k: v/total for k, v in probabilities.items()} # 基于列概率选择下一个点 col_probabilities = [] probabilities_array=np.zeros((self.x_num,self.y_num)) probabilities_array=np.reshape(probabilities_array,(self.y_num,self.x_num)) log_num=[] # 计算每列的平均概率 for j in range(self.x_num): num=0 colomn_sum = 0 for i in range(self.y_num): if len(path[0]) % 2 == 1: probabilities_array[i][j] = normalized_probs.get(self.x_num*self.y_num+1+self.x_num*i+j,0) else: probabilities_array[i][j] = normalized_probs.get(1+self.x_num*i+j,0) colomn_sum += probabilities_array[i][j] if probabilities_array[i][j] != 0: num+=1 log_num.append(num) col_probabilities.append(colomn_sum/num if num != 0 else 0) # 选择列与点 if len(path[0]) % 2 == 1: order_array = self.supply_order_array.copy() else: order_array = self.target_order_array.copy() next_col = random.choices(list(range(0,self.x_num)),list(col_probabilities), k=1)[0] normalized_col_probabilities = [prob / sum(probabilities_array[:,next_col]) for prob in probabilities_array[:,next_col]] # 选择两个点作为下一步 if log_num[next_col] > 1: next_points = np.random.choice(order_array[:,next_col], size=2, p=normalized_col_probabilities,replace=False) else: #直接去找奇数列 next_points.append(np.random.choice(order_array[:,next_col], size=1, p=normalized_col_probabilities,replace=False)[0]) col_probabilities[next_col] = 0 log_num[next_col]-=1 odd_indices = np.where(np.array(log_num) % 2 == 1)[0] col_probabilities=[col_probabilities[i] for i in odd_indices] if odd_indices.size == 0: memory.append(next_points[0]) num=0 visited_target.add(next_points[0]) continue next_col = random.choices(odd_indices, list(col_probabilities), k=1)[0] normalized_col_probabilities = [prob / sum(probabilities_array[:, next_col]) for prob in probabilities_array[:, next_col]] next_points.append(np.random.choice(order_array[:, next_col], size=1, p=normalized_col_probabilities, replace=False)[0]) # 选择下一个点 order_next_point = sorted(next_points) # 更新路径和已访问集合 for i in range(2): path[i].append(int(order_next_point[i])) if len(path[0]) % 2 == 0: visited_supply.add(int(order_next_point[i])) del probabilities[int(order_next_point[i])] else: visited_target.add(int(order_next_point[i])) del probabilities[int(order_next_point[i])] end_time=time.time()-start_time # print(end_time) # 处理待移栽苗数为奇数的最后情况 if self.empty_num % 2 != 0: # memory=0 # 随机选择最后一个点加到哪一个路径中 if random.random() < 0.5: selected = 0 else: selected = 1 available_points = [p for p in self.supply_need_number if p not in visited_supply] # 计算转移概率 # available_points = [p for p in self.supply_need_number if p not in visited_supply] # if not available_points: # break probabilities = {} for next_point in available_points: pheromone = self.pheromone_matrix[current][next_point] ** self.alpha visibility = ((self.max_distance - self.distance_matrix[current][next_point])/(self.max_distance - self.min_distance)) ** self.beta probabilities[next_point] = pheromone * visibility total = sum(probabilities.values()) normalized_probs = {k: v/total for k, v in probabilities.items()} # 基于列概率选择下一个点 col_probabilities = [] probabilities_array=np.zeros((self.x_num,self.y_num)) probabilities_array=np.reshape(probabilities_array,(self.y_num,self.x_num)) log_num=[] for j in range(self.x_num): num=0 colomn_sum = 0 for i in range(self.y_num): if len(path[0]) % 2 == 1: probabilities_array[i][j] = normalized_probs.get(self.x_num*self.y_num+1+self.x_num*i+j,0) else: probabilities_array[i][j] = normalized_probs.get(1+self.x_num*i+j,0) colomn_sum += probabilities_array[i][j] if probabilities_array[i][j] != 0: num+=1 log_num.append(num) col_probabilities.append(colomn_sum/num if num != 0 else 0) # 选择列与点 if len(path[0]) % 2 == 1: order_array = self.supply_order_array.copy() else: order_array = self.target_order_array.copy() next_col = random.choices(list(range(0,self.x_num)),list(col_probabilities), k=1)[0] normalized_col_probabilities = [prob / sum(probabilities_array[:,next_col]) for prob in probabilities_array[:,next_col]] path[selected].append(np.random.choice(order_array[:,next_col], size=1, p=normalized_col_probabilities,replace=False)[0]) if len(memory)==0: available_points = [p for p in self.target_need_number if p not in visited_target] path[selected].append(available_points[0]) else: path[selected].append(memory[0]) # 完成路径,返回原点 path[0].append(0) path[1].append(2*self.x_num*self.y_num+1) all_paths.append(path) all_fitness=self.fitness(arr=all_paths,gen=gen) return all_paths, all_fitness def update_pheromones(self, all_paths, all_fitnesses, gen): # 信息素挥发 self.pheromone_matrix *= (1 - self.evaporation_rate) # 根据路径质量更新信息素 for i, path in enumerate(all_paths): # i表示第i个蚂蚁 fitness = all_fitnesses[i] # 第i个蚂蚁的解决方案适应度 # 遍历该蚂蚁的双机械手路径 for k in range(2): # k表示第k个机械手 for j in range(len(path[k]) - 1): self.pheromone_matrix[path[k][j]][path[k][j + 1]] += self.Q * fitness/40 tem=[path[k][j],path[k][j + 1]] for k in range(2): for j in range(len(self.best_path) - 1): self.pheromone_matrix[self.best_path[k][j]][self.best_path[k][j + 1]] += self.Q / self.best_fitness def save_pheromone_matrix_to_excel(self, filename="pheromone_matrix.xlsx"): """ 将信息素矩阵保存为Excel文件 参数: filename (str): 保存的Excel文件名 """ try: import pandas as pd # 创建DataFrame df = pd.DataFrame(self.pheromone_matrix) # 添加行列标签(可选) row_labels = [f"点{i}" for i in range(self.num_points)] col_labels = [f"点{i}" for i in range(self.num_points)] df.index = row_labels df.columns = col_labels # 保存到CSV df.to_csv(filename) print(f"信息素矩阵已保存至 {filename}") except Exception as e: print(f"保存信息素矩阵时出错: {e}") def run(self, max_generation=1, max_consecutive_no_improvement=10): # 执行蚁群算法主循环 time_start = time.time() gen = 0 consecutive_no_improvement = 0 fitness_history = [] log_time = [] # 迭代直到满足收敛条件 # max_alpha_num=len(self.alpha) while consecutive_no_improvement < max_consecutive_no_improvement and gen < max_generation: # 构建解决方案并评估 # if gen<max_alpha_num: # gen_alpha=self.alpha[gen] # else: # gen_alpha=self.alpha[-1] # time_start = time.time() # all_paths, all_fitnesses = self.construct_solution(gen, gen_alpha) all_paths, all_fitnesses = self.construct_solution(gen) best_index = np.argmax(all_fitnesses) current_best_fitness = all_fitnesses[best_index] # 更新全局最优解 if current_best_fitness > self.best_fitness: self.best_fitness = current_best_fitness self.best_path = all_paths[best_index] consecutive_no_improvement = 0 else: consecutive_no_improvement += 1 # 更新信息素和历史记录 self.update_pheromones(all_paths, all_fitnesses, gen) fitness_history.append(self.best_fitness) # gen += 1 # gen_time = time.time() - time_start # log_time.append(gen_time) # print(f"第{gen}代: 最佳适应度 = {self.best_fitness:.4f}, 迭代时间 = {gen_time:.2f}秒") # 输出收敛信息 print(f"\n算法已收敛! 连续{consecutive_no_improvement}代无改善。") print(f"总迭代次数: {gen}") time_end = time.time() print(f"总运行时间: {time_end - time_start:.2f}秒") return self.best_path, self.best_fitness, fitness_history def plot_path(self,path=None): if path is None: path = self.best_path # 可视化路径 return self.common_func.plot_path(path) def calc_time(self, path): return self.common_func.calc_time(path) def calc_distance(self, path): return self.common_func.calc_distance(path) def fitness(self, arr, gen): return self.common_func.fitness(arr=arr, gen=gen) def main(): """ 主函数:设置参数并运行蚁群算法,输出结果并可视化路径 """ # 程序入口:设置参数并运行算法 start_time = time.time() # 问题与算法参数设置 x_num = 6 y_num = 12 empty_num = 9 num_ants = 20 alpha = 3 beta = 3 evaporation_rate = 0.5 Q = 1 # 创建并运行蚁群算法 aco = AntColonyOptimization( x_num=x_num, y_num=y_num, empty_num=empty_num, num_ants=num_ants, alpha=alpha, beta=beta, evaporation_rate=evaporation_rate, Q=Q, random_seed=1 ) best_path, best_distance, fitness_history = aco.run(max_generation=100, max_consecutive_no_improvement=30) # 输出结果 print(f"种群规模:{num_ants}") print(f"信息素重要性因子:{alpha}") print(f"启发式因子重要性:{beta}") print(f"信息素挥发率:{evaporation_rate}") print(f"缺苗盘数量:{empty_num}") print(f"最优路径: {best_path}") print(f"总距离: {best_distance:.2f}") end_time = time.time() print(f"运行时间: {end_time - start_time:.2f} 秒") # 可视化结果 aco.plot_path() # 绘制收敛曲线 plt.figure(figsize=(10, 8)) plt.plot(range(len(fitness_history)), fitness_history) plt.title('蚁群算法收敛曲线') plt.xlabel('代数') plt.ylabel('最优适应度') plt.grid(True) plt.show() if __name__ == "__main__": main() 帮我使用numba或cython改写该代码,生成一些必要的文件也行
05-28
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值