首页 > 编程语言 >(8-6-05)优先级遍历(Priority-based Search)算法:基于tkinter的多算法路径规划程序(5)

(8-6-05)优先级遍历(Priority-based Search)算法:基于tkinter的多算法路径规划程序(5)

时间:2024-07-28 22:53:48浏览次数:19  
标签:distance Search based max gui element 算法 time total

(7)函数breadth_first_search实现了广度优先搜索算法。它使用一个队列来存储待探索的节点,并通过迭代地从队列中取出节点来搜索路径。在搜索过程中,它会调用`add_neighbours`函数来添加节点的相邻节点,并在添加节点后继续搜索。当找到目标节点时,函数会停止搜索,并调用`paint`函数来绘制路径。最后,函数返回搜索得到的路径的距离、步数、队列的最大大小、弹出的节点数以及搜索所用的时间。

def breadth_first_search(start_time):
    queue = []
    found = False
    rear = 0
    front = 0
    (x, y) = gui.selected_cities[0]
    (end_x, end_y) = gui.selected_cities[1]

    point = Point(x, y)
    end = Point(end_x, end_y)
    start = point
    # print("Start {}, {}. End {}, {}".format(start.x, start.y, end.x, end.y))
    point.index = find_in_ovals(x, y)
    queue.append(point)  # source
    visited = np.zeros(gui.city_count)
    visited[point.index] = 1
    popped = 0
    max_element = 0

    while len(queue) > 0 and not found:
        point = queue[front]
        # print("Çekilen nokta: ", point.x, point.y)
        rear -= 1
        if point.equal(end):
            found = True
            print("Path found")
        else:
            top = add_neighbours(point, queue, rear, visited, end, 2)
            if len(queue) > max_element:
                max_element = len(queue)
            # print("Stack boyutu:", len(queue))
            popped += 1
        front += 1

    if found:
        total_distance, step_size = paint(point, start, max_element, popped)
        return total_distance, step_size, max_element, popped, time.time() - start_time
    else:
        message = "Path is not exist."
        gui.step_label.config(text=message)
    return 0, 0, 0, 0, time.time() - start_time

(8)函数paint用于绘制搜索得到的路径,其参数包括起始节点 `start`、搜索得到的目标节点 `point`、队列或栈的最大大小 `max_element` 以及弹出的节点数 `pops`。函数首先通过回溯得到路径上的所有节点,并计算路径的总距离和步数。然后,它在画布上绘制路径,并更新界面以显示搜索结果的动态过程。绘制路径时,函数会根据搜索速度设置的不同调整绘制的延迟时间。最后,函数返回路径的总距离和步数。

def paint(point, start, max_element, pops):
    path = []
    step_size = 0
    total_distance = 0
    delay = 0.3
    if gui.speed.get() == 0:  # fast
        delay = 0.2
    elif gui.speed.get() == 1:
        delay = 0.5

    while not point.equal(start):
        path.append(point)
        total_distance += distance(point.x, point.y, point.parent.x, point.parent.y, 1)
        point = point.parent
        step_size += 1

    message = "Step Size: {}, Distance: {}".format(step_size, int(total_distance))
    message2 = "Maximum Stack Size: {}\nNumber of Pops: {}".format(max_element, pops)
    gui.step_label.config(text=message)
    gui.output_label.config(text=message2)

    for i in range(len(path) - 1, -1, -1):
        gui.canvas.create_line(path[i].x + 5, path[i].y + 5, path[i].parent.x + 5, path[i].parent.y + 5,
                               width=3, fill="yellow")
        gui.window.update()
        time.sleep(delay)

    return total_distance, step_size

(9)下面这段代码定义了run函数,用于执行路径搜索算法并返回搜索结果。首先,它检查连接数、城市数以及连接数阈值是否符合要求,如果不符合则显示相应的错误消息。然后,根据用户选择的算法类型执行对应的搜索函数,并记录搜索过程中的路径距离、步数、最大堆栈/队列大小、弹出节点数以及总运行时间。最后,函数返回这些结果。

def run():
    if gui.conn_count < gui.city_total.get() - 1:
        msg.showerror(title="Connection Count Error", message="The number of connections is {} it's less than threshold"
                                                              " {}.".format(gui.conn_count, gui.city_total.get() - 1))
        return
    elif gui.city_count + 1 < gui.city_total.get():
        msg.showerror(title="City Count Error", message="The number of cities is {} but it's supposed to be {}.".
                      format(gui.city_count, gui.city_total.get()))
        return
    elif gui.conn_count < gui.entry.get() - 1:
        msg.showinfo(title="Connection Count Info", message="The number connections is {} but it's supposed to be {}."
                     .format(gui.conn_count, gui.entry.get()))
    start = time.time()
    if gui.algorithm.get() == 0:  # a *
        total_distance, step_size, max_element, popped, total_time = a_star_and_best_first_search(0, start)
    elif gui.algorithm.get() == 1:  # best first search
        total_distance, step_size, max_element, popped, total_time = a_star_and_best_first_search(1, start)
    elif gui.algorithm.get() == 2:
        total_distance, step_size, max_element, popped, total_time = depth_first_search(start)
    elif gui.algorithm.get() == 3:
        total_distance, step_size, max_element, popped, total_time = breadth_first_search(start)
    else:
        msg.showerror(title="Algorithm Selection Error", message="You did not choose the algorithm.")

    return total_distance, step_size, max_element, popped, total_time

(10)定义函数select_indices,用于随机选择两个城市索引,并确保它们不是邻居关系。它首先随机选择一个城市索引 `index1`,然后找到与该城市相连的城市,并将它们添加到 `neighbours` 列表中。接着,它再次随机选择另一个城市索引 `index2`,直到满足以下两个条件之一:`index1` 不等于 `index2`,或者 `(x1, y1)` 不在 `neighbours` 中。最后,它将所选的城市坐标添加到 `gui.selected_cities` 列表中。

def select_indices():
    index1 = random.randint(0, gui.city_total.get() - 1)
    index2 = index1

    neighbours = []
    i = 0
    x, y = gui.ovals[index1]["coords"]
    while i < len(gui.lines):  # find neighbours
        x1, y1, x2, y2 = gui.lines[i]["coords"]
        if distance(x, y, x1 - 5, y1 - 5, 0) == 0:
            neighbours.append((x2 - 5, y2 - 5))
        elif distance(x, y, x2 - 5, y2 - 5, 0) == 0:
            neighbours.append((x1 - 5, y1 - 5))
        i += 1

    index2 = random.randint(0, gui.city_total.get() - 1)
    x1, y1 = gui.ovals[index2]["coords"]
    while index1 == index2 or (x1, y1) in neighbours:  # işimizi şansa bırakmıyoruz
        index2 = random.randint(0, gui.city_total.get() - 1)
        x1, y1 = gui.ovals[index2]["coords"]
    print("Selected: ", x, y, x1, y1)
    gui.selected_cities.append((x, y))
    gui.selected_cities.append((x1, y1))

(11)定义函数test,用于运行一系列测试并将结果写入到 CSV 文件中。在测试过程中,它首先设置城市总数和连接数,并创建一个 CSV 文件以存储测试结果。然后,它循环执行以下步骤:

  1. 生成随机城市布局。
  2. 随机选择两个城市作为起点和终点。
  3. 分别以欧几里德距离和曼哈顿距离作为启发式函数运行 A* 算法。
  4. 分别以欧几里德距离和曼哈顿距离作为启发式函数运行 BFS 算法。
  5. 运行深度优先搜索(DFS)算法。
  6. 运行广度优先搜索(BFS)算法。

在每次运行算法后,将结果写入 CSV 文件中。最后,将这个过程重复执行一百次,以进行大规模测试。

def test():
    gui.city_total.set(20)
    gui.entry.set(40)

    with open('test_outputs.csv', 'w', newline='') as file:
        fieldnames = ['algorithm', 'distance', "step size", "max element", "popped", "time"]
        writer = csv.DictWriter(file, fieldnames=fieldnames)
        writer.writeheader()

        for i in range(100):
            print("Adım:", i)
            gui.create_randomly()
            gui.selected_cities = []
            select_indices()
            accepted = 0
            for j in range(6):
                if j == 0:
                    gui.algorithm.set(0)
                    gui.evaluation.set(0)
                    total_distance, step_size, max_element, popped, total_time = run()
                    accepted = total_distance
                    writer.writerow({"algorithm": "A* with Euclidean", "distance": accepted / total_distance , "step size": step_size,
                                  "max element": max_element, "popped": popped, "time": total_time})

                elif j == 1:
                    gui.algorithm.set(0)
                    gui.evaluation.set(1)
                    total_distance, step_size, max_element, popped, total_time = run()
                    writer.writerow({"algorithm": "A* with Manhattan", "distance": accepted / total_distance , "step size": step_size,
                                     "max element": max_element, "popped": popped, "time": total_time})

                elif j == 2:
                    gui.algorithm.set(1)
                    gui.evaluation.set(0)
                    total_distance, step_size, max_element, popped, total_time = run()
                    writer.writerow({"algorithm": "BFS with Euclidean", "distance": accepted / total_distance,
                                     "step size": step_size, "max element": max_element, "popped": popped, "time": total_time})

                elif j == 3:
                    gui.algorithm.set(1)
                    gui.evaluation.set(1)
                    total_distance, step_size, max_element, popped, total_time = run()
                    writer.writerow({"algorithm": "BFS with Manhattan", "distance": accepted / total_distance, "step size": step_size,
                                     "max element": max_element, "popped": popped, "time": total_time})

                elif j == 4:
                    gui.algorithm.set(2)
                    total_distance, step_size, max_element, popped, total_time = run()
                    writer.writerow({"algorithm": "DFS", "distance": accepted / total_distance, "step size": step_size,
                                     "max element": max_element, "popped": popped, "time": total_time})

                elif j == 5:
                    gui.algorithm.set(3)
                    total_distance, step_size, max_element, popped, total_time = run()
                    writer.writerow({"algorithm": "Breadth FS", "distance": accepted / total_distance, "step size": step_size,
                                     "max element": max_element, "popped": popped, "time": total_time})

(12)在下面这段代码中,当直接运行程序时会创建一个tkinter 应用程序的根窗口 root,然后初始化一个名为 Gui 的对象 gui,最后启动 Tkinter 的事件循环以显示 GUI 界面。如果想要执行测试函数 test(),只需取消注释 test() 调用的行即可。

if __name__ == "__main__":
    root = tk.Tk()
    gui = Gui()
    # test()
    root.mainloop()

通过如下命令运行本项目,

python Project.py

在测试过程中可以尝试不同的组合,以确保程序在各种情况下都能够正确地执行,并产生预期的结果。我们可以尝试以下几种操作:

  1. 启用不同的算法:尝试分别选择A*、最佳优先搜索、深度优先搜索和广度优先搜索,观察它们的行为和结果有何不同。
  2. 调整速度设置:尝试不同的速度设置(快速、中等、慢速),观察动画效果的变化和程序执行的速度。
  3. 改变城市和连接数量:尝试不同数量的城市和连接,观察程序对于不同规模数据的处理能力。
  4. 测试随机数据生成:测试随机数据生成功能,观察生成的城市和连接是否符合预期,并且能否正确地运行路径搜索算法。
  5. 通过这些测试,可以确保程序在各种情况下都能够正常工作,并产生正确的输出结果。

例如设置10个“Cities”、20个“Connections”,使用“Best First Search”算法寻早最短路径的效果如图8-6所示。

图8-6  最短路径可视化

标签:distance,Search,based,max,gui,element,算法,time,total
From: https://blog.csdn.net/asd343442/article/details/140719760

相关文章

  • 机器学习算法——常规算法,在同的业务场景也需要使用不同的算法(一)
    ......
  • 408 数据结构线性表算法
    第一章线性表定义:线性表是具有相同数据类型的n(n>=0)个数据元素的有限序列。线性表的表示:若用L命名,表示:L=(a1,a2,a3,a4,a5,……,an)线性表的逻辑特性:a1:唯一的表头元素an:唯一的表尾元素除去a1:每个元素有且仅有一个直接前驱除去an:每个元素有且仅有一个直接后继......
  • 深度模型中的优化 - 基本算法篇
    序言在深度学习中,模型优化是提升模型性能与训练效率的关键环节。深度模型通过优化算法不断调整其内部参数,以最小化损失函数,从而实现对复杂数据的有效拟合与预测。本篇章将简要概述深度模型中的几种基本优化算法,包括梯度下降法及其变种,这些算法在推动深度学习领域的发展中起......
  • SciTech-BigDataAIML-Python Time Series Handbook - Kalman filter: 卡尔曼滤波器算
    网上文档:Python时间序列手册:有ipynb和PDF文件:https://filippomb.github.io/python-time-series-handbook/notebooks/07/kalman-filter.htmlMITPDF:AnIntroductiontotheKalmanFilter-MITIllinoisUniversityPDF:UnderstandingtheBasisoftheKalmanF......
  • 408数据结构树算法
    第四章树4.1二叉树的顺序存储#defineMAXSIZE16typedefintElemType;typedefstruct{ ElemTypedata[MAXSIZE]; intsize;}Tree;//初始化二叉树voidinitTree(Tree&T){ for(inti=0;i<MAXSIZE;i++){ T.data[i]=0; //假设0表示空节点 } T.size=0......
  • 408 数据结构图算法
    第五章图5.1图的邻接矩阵存储//无向图的邻接矩阵存储#defineMAXSIZE16 //图的最大顶点个数typedefintVertexType; //顶点类型typedefintEdgeType; //边类型typedefstruct{ VertexTypeVex[MAXSIZE]; //图的顶点集 EdgeTypeEdge[MAXSIZE][MAXSIZE]; //图的边......
  • 408 数据结构排序算法
    第六章排序6.1冒泡排序voidswap(intarr[],inti,intj){ inttemp=arr[i]; arr[i]=arr[j]; arr[j]=temp;}//外层循环是说明n个元素排好序需要经过n-1轮 for(inti=n-1;i>0;i--){ boolflag=true; for(intj=0;j<i;j++){ if(arr[......
  • 408 数据结构查找算法
    第7章查找7.1二分查找需求:在有序数组arr中,查找值为target的元素。若找到返回索引下标,否则返回-1算法思路:找中间值,1.如果target<中间值,在左半区间继续查找,即让high=mid-1​ 2.如果中间值<target,在右半区间继续查找,即让low=mid+1​ 3.直到当lo......
  • 408 数据结构栈算法
    第二章栈2.1顺序栈顺序栈的基本操作#defineMAXSIZE128typedefintElemType;typedefstruct{ ElemTypedata[MAXSIZE]; //用数组实现对栈中元素的存取 inttop; //栈顶指针 intlength; //栈的长度}SqStack;//初始化栈voidinitStack(SqStack&S);//判......
  • 408 数据结构队列算法
    第三章队列3.1顺序队列#defineMAXSIZE64typedefintElemType;typedefstruct{ ElemTypedata[MAXSIZE]; intfront; //队头指针 intrear; //队尾指针 intsize; //队列大小}SeQueue;//初始化队列voidinitQueue(SeQueue&Q){ //对数据元素进行初始化,防止出现......