蚁群算法+A*算法寻找多目标最优路径

news2024/9/23 2:28:25

参考:
https://blog.csdn.net/feriman/article/details/113725937
https://blog.csdn.net/m0_73366745/article/details/137113791?spm=1001.2014.3001.5506
https://mp.weixin.qq.com/s/g1sRR6tJ8qHhFzl-vrG5fw

A*算法

import sys
import time
from typing import List
import random
from PIL import Image, ImageDraw
import matplotlib.pyplot as plt

"""
Point类是数学坐标系的一个抽象的点,和Node类不是一回事
"""


class Point:
    def __init__(self, x, y) -> None:
        self.x = x
        self.y = y

    # 重载“==”运算符,(x1,y1)==(x2,y2),当且仅当x1=x2,y1=y2
    def __eq__(self, other) -> bool:
        return self.x == other.x and self.y == other.y


class Node:
    def __init__(self, point: Point, endpoint: Point, g: float):  # 初始化中间节点的参数
        self.point = point
        self.endpoint = endpoint
        self.father = None
        self.g = g
        # h取曼哈顿距离,c=|x2-x1|+|y2-y1|
        self.h = (abs(endpoint.x - point.x) + abs(endpoint.y - point.y)) * 10
        self.f = self.g + self.h

    def get_near(self, ud, rl):  # 获取相邻节点
        near_point = Point(self.point.x + rl, self.point.y + ud)
        near_node = Node(near_point, self.endpoint, self.g + (10 if ud == 0 or rl == 0 else 14))
        return near_node


class AStar:
    def __init__(self, start: Point, end: Point, map_data):  # 初始化A*算法的参数
        self.path = [start, end]
        self.closed_list = []
        self.open_list = []
        self.start = start
        self.end = end
        self.obstacle_map = map_data

    # 从open_list里面找到一个代价最小的节点
    def select_current(self) -> Node:
        min_f = sys.maxsize
        node_temp = None
        for node in self.open_list:
            if node.f < min_f:
                min_f = node.f
                node_temp = node
        return node_temp

    def is_in_open_list(self, node: Node) -> bool:  # 判断节点是否在待检测队列中
        return any([open_node.point == node.point for open_node in self.open_list])

    def is_in_closed_list(self, node: Node) -> bool:  # 判断节点是否在已检测队列中
        return any([closed_node.point == node.point for closed_node in self.closed_list])

    def is_obstacle(self, node: Node) -> bool:
        """ 验证机器人的当前位置是否合理 """
        # 检查当前位置是否在环境内
        if node.point.x < 0 or node.point.x > len(self.obstacle_map) - 1:
            return True
        if node.point.y < 0 or node.point.y > len(self.obstacle_map) - 1:
            return True
        # 检查当前位置是否处于障碍物中
        if self.obstacle_map[node.point.x][node.point.y] != 0:
            return True
        return False

    def explore_neighbors(self, current_node: Node) -> bool:
        up = (0, 1)  # 上
        down = (0, -1)  # 下
        right = (1, 0)  # 右
        left = (-1, 0)  # 左
        top_right = (1, 1)  # 右上
        top_left = (-1, 1)  # 左上
        Bottom_right = (1, -1)  # 右下
        Bottom_left = (-1, -1)  # 左下
        directions = [up, down, right, left, top_right, top_left, Bottom_right, Bottom_left]
        for direction in directions:
            ud, rl = direction
            # current_neighbor是当前节点的邻点
            current_neighbor = current_node.get_near(ud, rl)
            # 如果检测到的节点是终点,就没必要接着往下探索了,直接退出循环,结束这个函数
            if current_neighbor.point == self.end:
                return True
            # 判断一下邻点是不是已经检测或者是障碍物,如果是,就跳过这个邻点
            if self.is_in_closed_list(current_neighbor) or self.is_obstacle(current_neighbor):
                continue
            if self.is_in_open_list(current_neighbor):
                previous_current_neighbor = next(
                    open_node for open_node in self.open_list if open_node.point == current_neighbor.point)
                if current_neighbor.f < previous_current_neighbor.f:
                    # 更新父节点
                    previous_current_neighbor.father = current_node
                    # 更新g值
                    previous_current_neighbor.g = current_neighbor.g
            else:
                # 对应状态3,直接入队
                current_neighbor.father = current_node
                self.open_list.append(current_neighbor)
        return False

    def find_path(self):
        start_node = Node(point=self.start, endpoint=self.end, g=0)
        self.open_list.append(start_node)

        while True:
            # 从open_list里面取出一个代价值最小节点
            current_node = self.select_current()
            if current_node is None:
                return []
            # 取出来后,从open_list里面删除,添加到closed_list里面
            self.open_list.remove(current_node)
            self.closed_list.append(current_node)
            # 当current_node是终点时,explore_neighbors函数会返回一个True
            if current_node.point == self.end or self.explore_neighbors(current_node):
                while current_node.father is not None:
                    self.path.insert(1, current_node.point)
                    # 这里其实就是相当于遍历一个链表
                    current_node = current_node.father
                return self.path



if __name__ == "__main__":
    start_point = Point(0, 0)
    end_point = Point(38, 3)
    # 设置环境地图
    neighbors = [
        [0, 1],  # 上
        [0, -1],  # 下
        [-1, 0],  # 左
        [1, 0],  # 右
        [1, 1],  # 右上
        [1, -1],  # 右下
        [-1, -1],  # 左下
        [-1, 1]  # 左上
    ]
    map_data = [[0] * 41 for i in range(41)]
    for i in range(20):
        map_data[5][i] = 1
        map_data[30][i] = 2
        map_data[i][25] = 1
    for node in [[20, 20], [30, 35], [10, 33]]:
        map_data[node[0]][node[1]] = 3
        for neighbor in neighbors:
            map_data[node[0] + neighbor[0]][node[1] + neighbor[1]] = 3

    # 运行A*算法
    start_time = time.time()
    a_star = AStar(start_point, end_point, map_data)
    path = a_star.find_path()
    end_time = time.time()
    print("程序运行时间:", end_time - start_time, "秒", f"路径长度为{len(path) - 1}")

    for i in range(41):
        for j in range(41):
            if map_data[i][j] != 0:
                plt.plot(i, j, '.k')
    plt.plot(start_point.x, start_point.y, 'og')
    plt.plot(end_point.x, end_point.y, 'or')
    # plt.grid('True')
    plt.axis('equal')
    rx = [path[i].x for i in range(len(path))]
    ry = [path[i].y for i in range(len(path))]
    plt.plot(rx, ry, '-r')
    plt.show()


蚁群算法

import random
import math


class Ant:
    def __init__(self, numAnts, numCities, maxIterations):
        self.numAnts = numAnts
        self.numCities = numCities
        self.maxIterations = maxIterations
        self.evaporationRate = 0.5
        self.alpha = 1.0
        self.beta = 2.0
        self.pheromones = []

    def run(self, distances):
        random.seed()
        self.initialize_pheromones()
        for iter in range(self.maxIterations):
            antPaths = []
            for ant in range(self.numAnts):
                path = self.generate_ant_path(distances)
                antPaths.append(path)
                self.update_pheromones(path)
            self.evaporate_pheromones()
            bestPath = antPaths[0]
            # print(f"Iteration {iter + 1}: Best Path -> {' -> '.join(map(str, bestPath))}")
        return bestPath

    def initialize_pheromones(self):
        global pheromones
        pheromones = [[1.0] * self.numCities for _ in range(self.numCities)]

    def generate_ant_path(self, distances):
        startCity = 0
        path = [startCity]
        while len(path) < self.numCities:
            currentCity = path[-1]
            nextCity = self.choose_next_city(currentCity, path, distances)
            path.append(nextCity)
        return path

    def choose_next_city(self, currentCity, path, distances):
        availableCities = [city for city in range(self.numCities) if city not in path]
        probabilities = []
        totalProbability = 0.0
        for nextCity in availableCities:
            pheromone = math.pow(pheromones[currentCity][nextCity], self.alpha)
            distance = 1.0 / distances[currentCity][nextCity]
            probability = pheromone * distance
            probabilities.append(probability)
            totalProbability += probability
        probabilities = [probability / totalProbability for probability in probabilities]
        randomValue = random.random()
        cumulativeProbability = 0.0
        for i, probability in enumerate(probabilities):
            cumulativeProbability += probability
            if randomValue <= cumulativeProbability:
                return availableCities[i]
        return availableCities[-1]

    def update_pheromones(self, path):
        pheromoneDeposit = 1.0
        for i in range(len(path) - 1):
            currentCity = path[i]
            nextCity = path[i + 1]
            pheromones[currentCity][nextCity] += pheromoneDeposit
            pheromones[nextCity][currentCity] += pheromoneDeposit

    def evaporate_pheromones(self):
        for i in range(self.numCities):
            for j in range(self.numCities):
                pheromones[i][j] *= (1.0 - self.evaporationRate)


if __name__ == '__main__':
    distances = \
        [[0, 2, 5, 7],
         [2, 0, 6, 3],
         [5, 6, 0, 8],
         [7, 3, 8, 0]]
    ant = Ant(5, 4, 100)
    best_path = ant.run(distances)
    print(best_path)

寻找多目标点最优路径

方式一 不适用蚁群算法

import time

from matplotlib import pyplot as plt

from A_star.A_Star import AStar, Point

def test_multi_node_path():
    start_point = Point(0, 0)
    end_point = Point(38, 3)
    # 设置环境地图
    neighbors = [
        [0, 1],  # 上
        [0, -1],  # 下
        [-1, 0],  # 左
        [1, 0],  # 右
        [1, 1],  # 右上
        [1, -1],  # 右下
        [-1, -1],  # 左下
        [-1, 1]  # 左上
    ]
    map_data = [[0] * 41 for i in range(41)]
    for i in range(20):
        map_data[5][i] = 1
        map_data[30][i] = 1
        map_data[i][25] = 1
    for node in [[20, 20], [30, 35], [10, 33]]:
        map_data[node[0]][node[1]] = 1
        for neighbor in neighbors:
            map_data[node[0] + neighbor[0]][node[1] + neighbor[1]] = 1

    import random
    y_stones = [[random.randint(0, 40), random.randint(0, 40)] for i in range(3)]
    q_stones = [[random.randint(0, 40), random.randint(0, 40)] for i in range(3)]
    r_stones = [[random.randint(0, 40), random.randint(0, 40)] for i in range(3)]
    for i in range(3):
        map_data[y_stones[i][0]][y_stones[i][1]] = 3
    for i in range(3):
        map_data[q_stones[i][0]][q_stones[i][1]] = 4
    for i in range(3):
        map_data[r_stones[i][0]][r_stones[i][1]] = 5


    start_time = time.time()
    dis = float("inf")
    path = None
    for i in range(3):
        for j in range(3):
            for k in range(3):
                ystone = Point(y_stones[i][0], y_stones[i][1])
                qstone = Point(q_stones[j][0], q_stones[j][1])
                rstone = Point(r_stones[k][0], r_stones[k][1])
                # 计算距离
                import itertools
                stone_com = list(itertools.permutations([ystone, qstone, rstone], 3))
                for com in stone_com:
                    p1 = AStar(start_point, com[0], map_data).find_path()
                    p2 = AStar(com[0], com[1], map_data).find_path()
                    p3 = AStar(com[1], com[2], map_data).find_path()
                    # p4 = AStar(com[2], end_point, map_data).find_path()
                    # if len(p1) > 0 and len(p2) > 0 and len(p3) > 0 and len(p4) > 0:
                    #     tmp_dis = len(p1) + len(p2) + len(p3) + len(p4)
                    #     if tmp_dis < dis:
                    #         node_list = com
                    #         dis = tmp_dis
                    #         path = p1 + p2 + p3 + p4
                    if len(p1) > 0 and len(p2) > 0 and len(p3) > 0:
                        tmp_dis = len(p1) + len(p2) + len(p3)
                        if tmp_dis < dis:
                            node_list = com
                            dis = tmp_dis
                            path = p1 + p2 + p3

    end_time = time.time()
    print("程序运行时间:", end_time - start_time, "秒", f"路径长度为{len(path) - 1}")

    for i in range(41):
        for j in range(41):
            if map_data[i][j] == 1:
                plt.plot(i, j, '.k')
            if map_data[i][j] == 3:
                plt.plot(i, j, '.g')
            if map_data[i][j] == 4:
                plt.plot(i, j, '.r')
            if map_data[i][j] == 5:
                plt.plot(i, j, '.b')

    plt.plot(start_point.x, start_point.y, 'og')
    plt.plot(end_point.x, end_point.y, 'or')
    # plt.grid('True')
    plt.axis('equal')
    rx = [path[i].x for i in range(len(path))]
    ry = [path[i].y for i in range(len(path))]
    plt.plot(rx, ry, '-r')
    plt.show()

if __name__ == "__main__":
    test_multi_node_path()

方式二 使用蚁群算法

import time

from matplotlib import pyplot as plt

from A_star.A_Star import AStar, Point

def test_multi_node_path():
    start_point = Point(0, 0)
    end_point = Point(38, 3)
    # 设置环境地图
    neighbors = [
        [0, 1],  # 上
        [0, -1],  # 下
        [-1, 0],  # 左
        [1, 0],  # 右
        [1, 1],  # 右上
        [1, -1],  # 右下
        [-1, -1],  # 左下
        [-1, 1]  # 左上
    ]
    map_data = [[0] * 41 for i in range(41)]
    for i in range(20):
        map_data[5][i] = 1
        map_data[30][i] = 1
        map_data[i][25] = 1
    for node in [[20, 20], [30, 35], [10, 33]]:
        map_data[node[0]][node[1]] = 1
        for neighbor in neighbors:
            map_data[node[0] + neighbor[0]][node[1] + neighbor[1]] = 1

    import random
    y_stones = [[random.randint(0, 40), random.randint(0, 40)] for i in range(3)]
    q_stones = [[random.randint(0, 40), random.randint(0, 40)] for i in range(3)]
    r_stones = [[random.randint(0, 40), random.randint(0, 40)] for i in range(3)]
    for i in range(3):
        map_data[y_stones[i][0]][y_stones[i][1]] = 3
    for i in range(3):
        map_data[q_stones[i][0]][q_stones[i][1]] = 4
    for i in range(3):
        map_data[r_stones[i][0]][r_stones[i][1]] = 5


    start_time = time.time()
    dis = float("inf")
    path = None
    for i in range(3):
        for j in range(3):
            for k in range(3):
                ystone = Point(y_stones[i][0], y_stones[i][1])
                qstone = Point(q_stones[j][0], q_stones[j][1])
                rstone = Point(r_stones[k][0], r_stones[k][1])
                # 计算距离
                nodes = [start_point, ystone, qstone, rstone]
                distances = [[0] * 4 for i in range(4)]
                paths = {}
                for x in range(4):
                    for y in range(x + 1, 4, 1):
                        p = AStar(nodes[x], nodes[y], map_data).find_path()
                        p_len = len(p)
                        distances[x][y] = p_len
                        distances[y][x] = p_len
                        paths[(x, y)] = p
                        paths[(y, x)] = p
                from ant import Ant
                ant = Ant(5, 4, 50)
                best_path = ant.run(distances)
                tmp_dis = distances[best_path[0]][best_path[1]] + distances[best_path[1]][best_path[2]] +\
                          distances[best_path[2]][best_path[3]]
                if tmp_dis < dis:
                    dis = tmp_dis
                    path = paths[(best_path[0], best_path[1])] + paths[(best_path[1],best_path[2])] +\
                          paths[(best_path[2], best_path[3])]
                # print(best_path)

    end_time = time.time()
    print("程序运行时间:", end_time - start_time, "秒", f"路径长度为{len(path) - 1}")

    for i in range(41):
        for j in range(41):
            if map_data[i][j] == 1:
                plt.plot(i, j, '.k')
            if map_data[i][j] == 3:
                plt.plot(i, j, '.g')
            if map_data[i][j] == 4:
                plt.plot(i, j, '.r')
            if map_data[i][j] == 5:
                plt.plot(i, j, '.b')

    plt.plot(start_point.x, start_point.y, 'og')
    plt.plot(end_point.x, end_point.y, 'or')
    # plt.grid('True')
    plt.axis('equal')
    rx = [path[i].x for i in range(len(path))]
    ry = [path[i].y for i in range(len(path))]
    plt.plot(rx, ry, '-r')
    plt.show()

if __name__ == "__main__":
    test_multi_node_path()

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2156362.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

利用QEMU安装一台虚拟机的三种方法

文章目录 宿主机的选择方法一&#xff1a;直接用qemu源码安装步骤1&#xff1a;下载好qemu源码&#xff0c;这里我们用qemu-5.1.0步骤2&#xff1a;编译步骤3&#xff1a;创建一个系统盘步骤4&#xff1a;用步骤2编译的qemu-system-x86_64 启动一台Linux虚拟机步骤5&#xff1a…

问题——IMX6UL的uboot无法ping主机或Ubuntu

主要描述可能的方向&#xff0c;不涉具体过程&#xff0c;详细操作可以查阅网上相关教程 跟随正点原子教程测试以太网端口时&#xff0c;即便按照步骤多次尝试也无法ping通&#xff0c;后补充了些许网络工程基础知识解决了这个问题。 uboot无法ping主机或Ubuntu有多种可能&…

二分查找算法(3) _x的平方根

个人主页&#xff1a;C忠实粉丝 欢迎 点赞&#x1f44d; 收藏✨ 留言✉ 加关注&#x1f493;本文由 C忠实粉丝 原创 二分查找算法(3) _x的平方根 收录于专栏【经典算法练习】 本专栏旨在分享学习算法的一点学习笔记&#xff0c;欢迎大家在评论区交流讨论&#x1f48c; 目录 温馨…

简易CPU设计入门:取指令(一),端口列表与变量声明

取指令这一块呢&#xff0c;个人觉得&#xff0c;不太好讲。但是呢&#xff0c;不好讲&#xff0c;我也得讲啊。那就尽量地讲吧。如果讲得不好的话&#xff0c;那么&#xff0c;欢迎大家提出好的意见&#xff0c;帮助我改进讲课的质量。 首先呢&#xff0c;还是请大家去下载本…

面试官:Spring是如何解决循依赖问题?

Spring 的循环依赖一直都是 Spring 中一个很重要的话题&#xff0c;一方面是 Spring 为了解决循环依赖做了很多工作&#xff0c;另一个方面是因为它是面试 Spring 的常客&#xff0c;因为他要求你看过 Spring 的源码&#xff0c;如果没有看过 Spring 源码你基本上是回答不了这个…

pytorch的动态计算图机制

pytorch的动态计算图机制 一&#xff0c;动态计算图简介 Pytorch的计算图由节点和边组成&#xff0c;节点表示张量或者Function&#xff0c;边表示张量和Function之间的依赖关系。 Pytorch中的计算图是动态图。这里的动态主要有两重含义。 第一层含义是&#xff1a;计算图的…

“吉林一号”宽幅02B系列卫星

离轴四反光学成像系统 1.光学系统参数&#xff1a; 焦距&#xff1a;77.5mm&#xff1b; F/#&#xff1a;7.4&#xff1b; 视场&#xff1a;≥56゜&#xff1b; 光谱范围&#xff1a;400nm&#xff5e;1000nm。 2.说明&#xff1a; 光学系统采用离轴全反射式结构&#xff0c;整…

解密的军事卫星图像在各种民用地理空间研究中都有应用

一、美军光学侦察卫星计划概述 国家侦察局 &#xff08;NRO&#xff09; 负责开发和操作太空侦察系统&#xff0c;并为美国国家安全开展情报相关活动。NRO 开发了几代机密锁眼 &#xff08;KH&#xff09; 军事光学侦察卫星&#xff0c;这些卫星一直是美国国防部 &#xff08;D…

人工智能不是人工“制”能

文/孟永辉 如果你去过今年在上海举办的世界人工智能大会&#xff0c;就会知道当下的人工智能行业在中国是多么火爆。 的确&#xff0c;作为第四次工业革命的重要组成部分&#xff0c;人工智能愈发引起越来越多的重视。 不仅仅是在中国&#xff0c;当今世界的很多工业强国都在将…

python爬虫案例——异步加载网站数据抓取,post请求(6)

文章目录 前言1、任务目标2、抓取流程2.1 分析网页2.2 编写代码2.3 思路分析前言 本篇案例主要讲解异步加载网站如何分析网页接口,以及如何观察post请求URL的参数,网站数据并不难抓取,主要是将要抓取的数据接口分析清楚,才能根据需求编写想要的代码。 1、任务目标 目标网…

Win10 安装Node.js 以及 Vue项目的创建

一、Node.js和Vue介绍 1. Node.js Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行环境。它允许你在服务器端运行 JavaScript&#xff0c;使得你能够使用 JavaScript 来编写后端代码。以下是 Node.js 的一些关键特点&#xff1a; 事件驱动和非阻塞 I/O&#xff1a;Node…

list(一)

list是可以在常数范围内在任意位置进行插入和删除的序列式容器&#xff0c;并且该容器可以前后双向迭代。list的底层是双向链表结构&#xff0c;双向链表中每个元素存储在互不相关的独立节点中&#xff0c;在节点中通过指针指向 其前一个元素和后一个元素。 支持 -- 但是不支持…

Linux:终端(terminal)与终端管理器(agetty)

终端的设备文件 打开/dev目录可以发现其中有许多字符设备文件&#xff0c;例如对于我的RedHat操作系统&#xff0c;拥有tty0到tty59&#xff0c;它们是操作系统提供的终端设备。对于tty1-tty12使用ctrlaltF*可以进行快捷切换&#xff0c;下面的命令可以进行通用切换。 sudo ch…

校园热捧的“人气新贵”,D 咖智能饮品机器人

在 2024 年的校园中&#xff0c;一股全新的潮流正在悄然兴起。D 咖智能饮品机器人以其独特的魅力&#xff0c;成功入驻多个校园&#xff0c;迅速成为学生们热烈追捧的对象&#xff0c;在长江大学、荆州职业技术学院、中医高专等多个大学校园&#xff0c;都能发现他们靓丽的身姿…

calibre-web报错:File type isn‘t allowed to be uploaded to this server

calibre-web报错&#xff1a;File type isnt allowed to be uploaded to this server 最新版的calibre-web在Upload时候会报错&#xff1a; File type isnt allowed to be uploaded to this server 解决方案&#xff1a; Admin - Basic Configuration - Security Settings 把…

投资学 01 定义,投资

02. 03. 3.1 直接投资&#xff1a;使用方和提供方是一个人

VUE3学习---【一】【从零开始的VUE学习】

目录​​​​​​​ 什么是Vue 渐进式框架 创建一个Vue应用 什么是Vue应用 使用Vue应用 根组件 挂载应用 模板语法 文本插值 原始HTML Attribute绑定 简写 同名简写 布尔型Attribute 动态绑定多个值 使用JavaScript表达式 仅支持表达式 指令 Directives 指令…

COLORmap

在这段MATLAB代码中&#xff0c;surf(peaks)、map的定义以及colormap(map)的调用共同完成了以下任务&#xff1a; 1. **绘制曲面图**&#xff1a; - surf(peaks)&#xff1a;这个函数调用了MATLAB内置的peaks函数来生成数据&#xff0c;并使用surf函数将这些数据绘制成一个…

双向链表:实现、操作与分析【算法 17】

双向链表&#xff1a;实现、操作与分析 引言 双向链表&#xff08;Doubly Linked List&#xff09;是链表数据结构的一种重要形式&#xff0c;它允许节点从两个方向进行遍历。与单向链表相比&#xff0c;双向链表中的每个节点不仅包含指向下一个节点的指针&#xff08;或引用&…

蓝桥杯嵌入式的学习总结

一. 前言 嵌入式竞赛实训平台(CT117E-M4) 是北京国信长天科技有限公司设计&#xff0c;生产的一款 “ 蓝桥杯全国软件与信息技术专业人才大赛-嵌入式设计与开发科目 “ 专用竞赛平台&#xff0c;平台以STM32G431RBT6为主控芯片&#xff0c;预留扩展板接口&#xff0c;可为用户提…