当前位置: 首页 > news >正文

【动手学运动规划】 4.5 A*算法

我宁愿永远做我自己,也不愿成为别人,即使那个人比你更快乐。

—《成为简·奥斯汀》

🏰代码及环境配置:请参考 环境配置和代码运行!


4.5.1 概述

Dijkstra算法是基于广度优先搜索策略来遍历空间内的所有节点,最终计算出全局最优的路径,其计算量非常大。而基于启发式的贪婪最佳优先搜索(greedy best first search,GBFS)速度快,但结果可能不是最优的。那么,如何将二者的优势结合呢,即在Dijkstra算法基础上,引入启发式策略。这就是A*算法。

🌟**Note:**最佳优先搜索算法是在广度优先搜索的基础上,用启发估价函数对将要被遍历到的点进行估价,然后选择代价小的进行遍历,直到找到目标节点或者遍历完所有点,算法结束。

4.5.2 算法详解

A*算法结合了GBFS算法和Dijkstra算法的优点,通过评估函数 f ( n ) f(n) f(n)来指导搜索过程, f ( n ) f(n) f(n)定义为从起点到节点n 的实际代价 g ( n ) g(n) g(n)与从节点n 到目标节点的估计代价 h ( n ) h(n) h(n)之和,即 f ( n ) = g ( n ) + h ( n ) f(n)=g(n) + h(n) f(n)=g(n)+h(n)

  • g ( n ) g(n) g(n):从起点到节点n的实际代价(通常是距离或消耗)。
  • h ( n ) h(n) h(n):从节点n到目标节点的估计代价(启发式函数)。

🌟**Note:**为了确保 g ( n ) g(n) g(n) h ( n ) h(n) h(n)的相加有意义,这两个值必须使用相同的衡量单位。

4.5.1.1 启发式函数

启发式函数可以控制A*的行为:

  • 一种极端情况,如果 h ( n ) h(n) h(n)是0,则只有 g ( n ) g(n) g(n)起作用,此时A*演变成Dijkstra算法,计算量增大,但可以确保找到最优路径。
  • 如果 h ( n ) h(n) h(n)经常都比从节点n移动到目标节点的实际代价小(或者相等),则A可以保证能找到一条最优路径。 h ( n ) h(n) h(n)越小,A扩展的节点越多,计算量越大,运行得越慢。
  • 如果 h ( n ) h(n) h(n)精确地等于从节点n移动到目标节点的代价,则A*将会仅仅寻找最优路径而不扩展别的任何结点,这会运行得非常快。尽管这不可能在所有情况下发生,但仍可以在一些特殊情况下让它们精确地相等。
  • 如果 h ( n ) h(n) h(n)有时比从节点n移动到目标节点的实际代价高,则A*不能保证找到一条最优路径,但它运行得更快。
  • 另一种极端情况,如果 h ( n ) h(n) h(n) g ( n ) g(n) g(n)大很多,则只有 h ( n ) h(n) h(n)起作用,A*演变成GBFS算法。

下图可以清晰的看出不同的 h ( n ) h(n) h(n)对算法的影响(图中绿色的为起始点,红色的为目标点):

  • a = 1 , b = 0 a=1, b=0 a=1,b=0:如图Fig.1,此时A*算法变成了Dijkstra算法,虽然可以得到最优解,但是扩展了非常多的节点,计算量很大。
  • a = 0 , b = 1 a=0,b=1 a=0,b=1:如图Fig.2,此时A*算法变成了GBFS算法,计算量减少,但可能找不到最优解。
  • a = 1 , b = 1 a=1,b=1 a=1,b=1:如图Fig.3,即为A*算法,平衡了计算量和最优解之间的关系。

🌟Note: 图中的算法展示来源于:https://qiao.github.io/PathFinding.js/visual/

经过分析,可以看到在A*算法中,启发式函数 h ( n ) h(n) h(n)扮演着及其重要的角色,以下是一些常见的启发式函数类型:

  1. 曼哈顿距离(Manhattan Distance)
    • 曼哈顿距离是A*算法中常用的启发式函数之一。它计算的是两点在标准坐标系上的绝对轴距总和,即只能沿着坐标轴(或网格的边界)移动的距离。对于网格地图,曼哈顿距离非常适合,因为它反映了实际移动中的限制(如只能上下左右移动)。
    • 公式: h ( n ) = ∣ x n − x g o a l ∣ + ∣ y n − y g o a l ∣ h(n)=\left | x_{n} - x_{goal} \right | + \left | y_{n} - y_{goal} \right | h(n)=xnxgoal+ynygoal,其中 ( x n , y n ) (x_{n},y_{n}) (xn,yn) ( x g o a l , y g o a l ) (x_{goal},y_{goal}) (xgoal,ygoal)分别是当前点和目标点的坐标。
  2. 欧几里得距离(Euclidean Distance)
    • 欧几里得距离是两点之间的直线距离,在平面直角坐标系中,它可以通过勾股定理计算得到。虽然欧几里得距离在物理上更准确,但在网格地图中,由于只能沿网格线移动,它可能不总是反映实际的最短路径。然而,在某些情况下,为了简化计算或适应特定需求,也可以使用欧几里得距离作为启发式函数。
    • 公式: h ( n ) = ( x n − x g o a l ) 2 + ( y n − y g o a l 2 ) h(n)=\sqrt{(x_{n} - x_{goal})^{2} + (y_{n} - y_{goal}^{2} )} h(n)=(xnxgoal)2+(ynygoal2)
  3. 切比雪夫距离(Chebyshev Distance)
    • 切比雪夫距离是各坐标数值差的最大值,也称为棋盘距离或 L ∞ L\infty L 度量。在网格地图中,它表示从一个点到另一个点所需改变的最大坐标值(即沿任一坐标轴移动的最大步数)。虽然不如曼哈顿距离常用,但在某些特定场景下,切比雪夫距离也能作为有效的启发式函数。
    • 公式: h ( n ) = m a x ( ∣ x n − x g o a l ∣ , ∣ y n − y g o a l ∣ ) h(n)=max(\left | x_{n} - x_{goal} \right |, \left | y_{n} - y_{goal} \right |) h(n)=max(xnxgoal,ynygoal)
  4. 自定义启发式函数
    • 除了上述常见的启发式函数外,还可以根据具体问题设计自定义的启发式函数。自定义启发式函数可以更加精确地反映问题的实际情况,从而提高搜索效率和准确性。然而,设计有效的自定义启发式函数需要深入了解问题的本质和特性。

4.5.1.2 算法步骤

算法步骤如下:

  1. 初始化:
    1. 创建一个数组g[],其中g[i]表示从源节点start到节点i的最小cost,初始时,源节点的cost为0。
    2. 创建一个数组f[] ,其中f[i] 表示从源节点start到节点i的最小cost + 节点i 到目标节点的启发式cost。
    3. 创建一个布尔数组 visited[] 来跟踪每个节点是否已被访问过,初始时,所有顶点都未访问
    4. 创建一个优先队列open_list,用于根据cost选择下一个要处理的节点。优先队列中的每个元素是一个包含顶点和cost的配对,初始时将源节点start和其f cost加入优先队列。
  2. 循环处理优先队列中的节点:
    1. 从优先队列中取出f cost最小的节点v ,并将节点v 标记为已访问,若节点v就是目标节点,则提前返回。
    2. 遍历节点v 中所有未被访问过的邻接节点,对于每一个邻接节点next
      1. 计算邻接节点next 的g cost和h cost。
      2. 若邻接节点next 不在优先队列中,则将邻接节点next 和其对应的f cost加入优先队列,并在数组g[]f[]中设置分别设置邻接节点next 的g cost和f cost,最后将临接节点next 的父节点设为v
      3. 若邻接节点next 在优先队列中,则在数组g[]f[]和优先队列open_list中更新节点next 的相关信息,最后将临接节点next 的父节点设为v
    3. 继续处理优先队列中的顶点,直到队列为空或所有顶点都被访问。
  3. 从目标节点goal开始,通过父节点向回追溯,直到起始节点,最终得到一条路径。

伪代码如下:

Algorithm A star(G, start, goal):let **open_list** be a priority_queueg[**start**] = 0f[**start**] = g[**start**] + h[**start**]**open_list.**push(**start,** f[**start**])while **open_list** is not empty dov = **open_list**.pop()mark v as vistedif v is the **goal**:return vfor **all unvisited neighbours** next of v in Graph G do next_g_cost = g[v] + cost(v, next)next_h_cost = h[next]if next is not in **open_list**:g[next] = next_g_costf[next] = next_g_cost + next_h_cost**open_list**.push(next, f[next])next.parent = velse:if g[next] > next_g_cost:g[next] = next_g_costf[next] = next_g_cost + next_h_cost**open_list**.**update_priority**(next, f[next])next.parent = v

4.5.1.3 算法图解

以从下面的无向图中寻找出节点A 到节点E的最短路径为例,其中两个节点之间的权重表示他们之间的距离(或者cost),节点旁边的数字表示预定义的启发项,并初始话两个表:visited nodes info和unvisited nodes info。

所有节点的初始cost如下:

  • 源节点到自身的g-cost为0,到目标节点的h-cost为6,因此源节点的f-cost为6。
  • 源节点到其它节点的cost还没有确定,暂时先标记为无穷大。
  1. 从源节点A 开始,将其加入到已访问列表中,并从未访问列表中删除。同时在未访问列表中更新源节点A 的邻近节点(节点B和节点C)的信息。
    1. 节点B :节点B最短路径为A —> B ,g-cost为1.5,h-cost为5,f-cost为6.5,父节点为A
    2. 节点C :节点C最短路径为A —> C ,g-cost为2,h-cost为3,f-cost为5,父节点为A

  1. 查看未访问列表,节点C 的cost最小,因此将其加入到已访问列表中,并从未访问列表中删除。同时在未访问列表中更新节点C 的邻近节点(节点E)的信息。
    1. 节点E:节点E最短路径为A —> C —> E ,g-cost为5,h-cost为0,f-cost为5,父节点为C

  1. 查看未访问列表,节点E的cost最小,因此将其加入到已访问列表中,并从未访问列表中删除,此时节点E 为目标节点,因此搜索结束,经过回溯父节点,节点A到节点E最短路径为:A —> C —> E

4.5.3 优缺点

  • 优点
    • 高效性:A*算法结合了最佳优先搜索(Best-First Search)和Dijkstra算法的优点,通过启发式函数(heuristic function)来评估节点的优先级,从而能够快速找到从起点到终点的最短路径。
    • 最优性:在启发式函数满足一定条件(如 h ( n ) h(n) h(n)始终小于等于节点 n n n到目标节点的实际代价)的情况下,A*算法能够保证找到从起点到终点的最短路径。
  • 缺点
    • 启发式函数的选择:虽然A*算法允许选择不同的启发式函数,但启发式函数的选择会直接影响算法的性能和结果。如果启发式函数选择不当,可能会导致算法无法找到最短路径或搜索效率降低。

4.5.c A*代码解析

本节提供了A*算法的代码测试:

python3 tests/search_based_planning/a_star_test.py

4.5.c.1 构图的代码实现

基于图搜的运动规划中最重要的一步是构图,构建的图比较简单,主要包含map border和obstacles,读者也可根据需求修改构图方式。

def construct_env_info():border_x = []border_y = []ox = []oy = []# map border.for i in range(-10, 60):border_x.append(i)border_y.append(-10.0)for i in range(-10, 60):border_x.append(60.0)border_y.append(i)for i in range(-10, 61):border_x.append(i)border_y.append(60.0)for i in range(-10, 61):border_x.append(-10.0)border_y.append(i)# Obstacle 1.for i in range(40, 55, 1):for j in range(5, 15, 1):ox.append(i)oy.append(j)# Obstacle 2.for i in range(40):for j in range(20, 25, 1):ox.append(j)oy.append(i)# Obstacle 3.for i in range(30):for j in range(40, 45, 1):ox.append(j)oy.append(58.0 - i)# Obstacle 4.for i in range(0, 20, 1):for j in range(35, 40, 1):ox.append(i)oy.append(j)return border_x, border_y, ox, oy

4.5.c.2 A*的代码实现

在A*算法中,首先我们定义了节点Node ,这是图的基础元素。其中(x, y)表示节点的位置,cost表示从源节点到当前节点的cost,parent 表示当前节点的父节点。

class Node:def __init__(self, x, y, cost, parent_index):self.x = x  self.y = y  self.cost = costself.parent_index = parent_indexdef __str__(self):return (str(self.x)+ ","+ str(self.y)+ ","+ str(self.cost)+ ","+ str(self.parent_index))

在A*中,启发式函数使用的是欧式距离,如下:

def calc_heuristic(n1, n2):w = 1.0  # weight of heuristicd = w * math.hypot(n1.x - n2.x, n1.y - n2.y)return d

下面是A*的核心算法,基于环境信息,起始点位置,目标点位置搜到最优路径,其中:

sx:起始点的x坐标的值

sy:起始点的y坐标的值

gx:目标点的x坐标的值

gy:目标点的y坐标的值

最终返回一条路径:rx, ry

def planning(self, sx, sy, gx, gy):start_node = self.Node(self.calc_xy_index(sx, self.min_x),self.calc_xy_index(sy, self.min_y),0.0,-1,)goal_node = self.Node(self.calc_xy_index(gx, self.min_x),self.calc_xy_index(gy, self.min_y),0.0,-1,)open_set, closed_set = dict(), dict()open_set[self.calc_grid_index(start_node)] = start_nodewhile True:if len(open_set) == 0:print("Open set is empty..")breakc_id = min(open_set,key=lambda o: open_set[o].cost+ self.calc_heuristic(goal_node, open_set[o]),)current = open_set[c_id]# show graphif show_animation:plt.plot(self.calc_grid_position(current.x, self.min_x),self.calc_grid_position(current.y, self.min_y),"xc",)# for stopping simulation with the esc key.plt.gcf().canvas.mpl_connect("key_release_event",lambda event: [exit(0) if event.key == "escape" else None],)if len(closed_set.keys()) % 10 == 0:plt.pause(0.001)plt.savefig(gif_creator.get_image_path())if current.x == goal_node.x and current.y == goal_node.y:print("Find goal")goal_node.parent_index = current.parent_indexgoal_node.cost = current.costbreak# Remove the item from the open setdel open_set[c_id]# Add it to the closed setclosed_set[c_id] = current# expand_grid search grid based on motion modelfor i, _ in enumerate(self.motion):node = self.Node(current.x + self.motion[i][0],current.y + self.motion[i][1],current.cost + self.motion[i][2],c_id,)n_id = self.calc_grid_index(node)# If the node is not safe, do nothingif not self.verify_node(node):continueif n_id in closed_set:continueif n_id not in open_set:open_set[n_id] = node  # discovered a new nodeelse:if open_set[n_id].cost > node.cost:# This path is the best until now. record itopen_set[n_id] = noderx, ry = self.calc_final_path(goal_node, closed_set)return rx, ry

4.5.c.3 A*的代码测试

main 函数中设置起始点,目标点,grid的分辨率和机器人的半径,在创建grid map之后,并运行A算法,即可找到最优路径。如下图所示,红色路径即为最终A搜出来的最优路径。

def main():# start and goal positionstart_x = 10.0  # [m]start_y = 10.0  # [m]goal_x = 50.0  # [m]goal_y = 0.0  # [m]grid_size = 2.0  # [m]robot_radius = 1.0  # [m]# construct environment info.border_x, border_y, ox, oy = construct_env_info()if show_animation: plt.plot(border_x, border_y, "s", color=(0.5, 0.5, 0.5), markersize=10)plt.plot(ox, oy, "s", color="k")plt.plot(start_x, start_y, "og", markersize=10)plt.plot(goal_x, goal_y, "ob", markersize=10)plt.grid(True)plt.axis("equal")ox.extend(border_x)oy.extend(border_y)a_star = AStarPlanner(ox, oy, grid_size, robot_radius)rx, ry = a_star.planning(start_x, start_y, goal_x, goal_y)if show_animation: plt.plot(rx, ry, "-r")plt.savefig(gif_creator.get_image_path())plt.pause(0.01)gif_creator.create_gif()plt.show()

4.5.4 A*算法的变种

A*算法有很多的变种,此处不在详细介绍,感兴趣者可参考以下链接。

  • Anytime A*
  • Block A*
  • D*
  • Field D*
  • Fringe
  • Fringe Saving A (FSA*)*
  • Generalized Adaptive A (GAA*)*
  • Incremental heuristic search
  • Iterative deepening A (IDA*)*
  • Jump point search
  • Lifelong Planning A (LPA*)*
  • Simplified Memory bounded A (SMA*)*
  • Theta*

4.5.5 参考

https://en.wikipedia.org/wiki/A*_search_algorithm#Pseudocode

推荐阅读

  • 端到端理论与实战
  • 动手学轨迹预测
  • 动手学运动规划
  • 动手学行为决策
  • 强化学习入门笔记

相关文章:

【动手学运动规划】 4.5 A*算法

我宁愿永远做我自己,也不愿成为别人,即使那个人比你更快乐。 —《成为简奥斯汀》 🏰代码及环境配置:请参考 环境配置和代码运行! 4.5.1 概述 Dijkstra算法是基于广度优先搜索策略来遍历空间内的所有节点,最终计算出…...

Spring Boot 3.4.0 发布:功能概览与示例

Spring Boot 3.4.0 带来了许多增强功能,使现代应用开发更加高效、便捷和强大。以下是最新功能的完整概述,以及一些帮助您快速入门的代码示例。 1. 应用程序版本管理 Spring Boot 引入了 spring.application.version 属性,方便开发者设置和访…...

【48】Android通过libjpeg-turbo库实现图片压缩

(1)公司为节约图片占用服务器存储资源成本,需要对Android手机客户端所传递到云存储服务器中的图片进行压缩,在不影响图片失真程度的情况下,最大限度的压缩图片以节省图片所占用的存储空间。 (2)…...

Linux输入设备应用编程

本章学习输入设备的应用编程,首先要知道什么是输入设备?输入设备其实就是能够产生输入事件的设备就称为输入设备,常见的输入设备包括鼠标、键盘、触摸屏、按钮等等,它们都能够产生输入事件,产生输入数据给计算机系统。…...

【Vulkan入门】03-创建Device

目录 先叨叨git信息关键代码VulkanEnv::CreateDevice() 编译并运行程序题外话 先叨叨 在上篇已经选择了一个合适的PhysicalDevice。 本篇要为这个PhysicalDevice创将一个Device。Device可以理解为APP与PhysicalDevice之间的代理。 所有APP与PhysicalDevice之间交互的资源都通过…...

【jvm】C2编译器

目录 1. 说明2. 编译流程3. 使用与配置4. 性能优化与监控5. 局限性 1. 说明 1.JVM(Java虚拟机)C2编译器是Java编译过程中的重要环节,专门用于将Java字节码编译成高效的本地机器代码,以提升Java程序的执行效率。2.特点&#xff1a…...

使用 Acme.sh 自动生成和续签免费 SSL 证书(含通配符支持)

Acme.sh 是一个开源的脚本,能够从 ZeroSSL、Let’s Encrypt 等证书颁发机构(CA)获取免费的 HTTPS 证书。该脚本特别简单易用,并且支持多种验证方式。下面将详细介绍使用 Acme.sh 生成、安装和更新证书的各个步骤。 Github地址 使用…...

Android 图形系统之四:Choreographer

Choreographer 是 Android 系统中负责帧同步的核心组件,它协调输入事件、动画和绘制任务,以确保界面以固定频率(通常是每 16ms,一帧)流畅渲染。通过管理 VSYNC 信号和调度任务,Choreographer 是实现流畅 UI…...

CAP定理和BASE理论

CAP定理 CAP定理,也称为布鲁尔定理(Brewer’s Theorem),是分布式系统设计中的一个基本原理。它指出在分布式系统中,一致性(Consistency)、可用性(Availability)和分区容…...

笔记软件:我来、思源笔记、Obsidian、OneNote

最近wolai的会员到期了,促使我更新了一下笔记软件。 首先,wolai作为一个笔记软件,我觉得有很多做得不错的方面(否则我也不会为它付费2年了),各种功能集成得很全(公式识别这个功能我写论文的时候…...

试探互联网如何工作?

Reading: How_does_the_Internet_workhow-does-internet-work Watching:How the Internet Works in 5 Minutes Outline: 互联网通过全球互联的计算机和服务器网络工作,通过标准化协议进行通信。数据被分解成数据包,并使用互联…...

【c++笔试强训】(第三十篇)

目录 爱丽丝的⼈偶(贪⼼构造) 题目解析 讲解算法原理 编写代码 集合(排序) 题目解析 讲解算法原理 编写代码 爱丽丝的⼈偶(贪⼼构造) 题目解析 1.题目链接:登录—专业IT笔试面试备考平…...

微信小程序购物车全选反选功能以及合计

微信小程序基于Vant Weapp的购物车功能实现 1、单选 使用微信小程序原生表单组件checkbox和checkbox-group 注意&#xff1a;checkbox原生不支持bind:change事件&#xff0c;checkbox-group支持 <checkbox-group bindchange"handleCheck"><checkbox val…...

vue-qr在线生成二维码组件(vue2版本)

在对于二维码生成中有许多组件&#xff0c;下面介绍关于自定义比较高的vue-qr组件&#xff0c;能自定义设置背景颜色、背景图片、背景Gif图、实点和空白区的颜色、中心Logo的图片和边距。 依赖下载 注意&#xff1a; 直接npm下载最新版 有些项目可能运行会抱错 这时候你可以降…...

大语言模型技术相关知识-笔记整理

系列文章目录 这个系列攒了很久。主要是前段之间面试大语言模型方面的实习&#xff08;被拷打太多次了&#xff09;&#xff0c;然后每天根据面试官的问题进行扩展和补充的这个笔记。内容来源主要来自视频、个人理解以及官方文档中的记录。方便后面的回顾。 文章目录 系列文章…...

SCP命令实现Linux中的文件传输

CP命令的主要作用是实现Linux与Linux系统之间的文件传输。 SCP命令时基于SSH协议,所以两台服务器的sshd服务必须处于开启状态,否则无法完成上传与下载操作。 #1.上传文件 scp linux本地文件路径 远程用户名@linux主机地址:远程路径 #2.下载文件 scp 远程用户名@linux主机地址…...

linux环境中后台运行java程序

在生产环境&#xff0c;我们通常需要让java进程后台运行&#xff0c;并且即使会话关闭&#xff0c;进程也依然存在。 使用的命令&#xff1a; nohup java -jar xxx.jar -> aaa.log 2>&1 & 详细介绍下上面这条命令 &#xff08;1&#xff09;nohup&#xff1a;…...

Go学习:变量

目录 1. 变量的命名 2. 变量的声明 3. 变量声明时注意事项 4. 变量的初始化 5. 简单例子 变量主要用来存储数据信息&#xff0c;变量的值可以通过变量名进行访问。 1. 变量的命名 在Go语言中&#xff0c;变量名的命名规则 与其他编程语言一样&#xff0c;都是由字母、数…...

在Unity编辑模式下运行Mono中的方法

[ExecuteAlways] 最简单的方法当然是直接给Mono加上[ExecuteAlways]修饰&#xff0c;这样Mono中的Awake&#xff0c;Update等等都可以在编辑模式下按照原本的时机运行。 [ExecuteAlways] public class TestScript : MonoBehaviour {void TestMethod(){Debug.Log("TestMe…...

Y20030028 JAVA+SSM+MYSQL+LW+基于JAVA的考研监督互助系统的设计与实现 源代码 配置 文档

基于JAVA的考研监督互助系统 1.项目描述2. 课题开发背景及意义3.项目功能4.界面展示5.源码获取 1.项目描述 随着高等教育的普及和就业竞争的加剧&#xff0c;越来越多的学生选择继续深造&#xff0c;参加研究生入学考试。考研人数的不断增加&#xff0c;使得考研过程中的学习监…...

MATLAB期末复习笔记(下)

目录 五、数据和函数的可视化 1.MATLAB的可视化对象 2.二维图形的绘制 3.图形标识 4.多子图绘图 5.直方图的绘制 &#xff08;1&#xff09;分类 &#xff08;2&#xff09;垂直累计式 &#xff08;3&#xff09;垂直分组式 &#xff08;4&#xff09;水平分组式 &…...

「Mac畅玩鸿蒙与硬件37」UI互动应用篇14 - 随机颜色变化器

本篇将带你实现一个随机颜色变化器应用。用户点击“随机颜色”按钮后&#xff0c;界面背景会随机变化为淡色系颜色&#xff0c;同时显示当前的颜色代码&#xff0c;页面还会展示一只猫咪图片作为装饰&#xff0c;提升趣味性。 关键词 UI互动应用随机颜色生成状态管理用户交互…...

MySql:理解数据库

目录 一、什么是数据库 第一层理解 第二层理解 第三层理解 二、Linux下的数据库 三、基本认识 登录数据库时&#xff0c; mysql -u root -h 127.0.0.1 -P 3306 -p -h指定MySql服务器所在主机&#xff0c;若在本地则为回环地址。-P表示目标主机上MySql服务端口号 一般简单…...

学习笔记051——SpringBoot学习2

文章目录 Spring Boot 原理1、SpringBootConfiguration2、ConfigurationProperties3、ComponentScan4、EnableAutoConfiguration Spring Boot 原理 Spring Boot 可以自动读取配置文件&#xff0c;将项目所需要的组件全部自动加载到 IoC 容器中&#xff0c;包括两部分 开发者自…...

crush rule 20 type does not match pool

问题 kubectl describe CephObjectStore ceph-objectstoreEvents:Type Reason Age From Message---- ------ ---- ---- -------Warning ReconcileFailed 14m …...

BA是什么?

目录 1.EKF的步骤 一、问题定义与模型建立 二、线性化处理 三、应用卡尔曼滤波 四、迭代与收敛 五、结果评估与优化 注意事项 2.BA问题的步骤 一、问题定义与数据准备 二、构建优化模型 三、选择优化算法 四、执行优化过程 五、结果评估与优化 六、应用与验证 1.…...

通过docker 搭建jenkins环境;

一、官网简介使用安装说明: How to use this image docker run -p 8080:8080 -p 50000:50000 jenkins This will store the workspace in /var/jenkins_home. All Jenkins data lives in there - including plugins and configuration. You will probably want to make that …...

10-高级主题

第10节 高级主题 在这一节中&#xff0c;我们将探讨一些 Python 中的高级主题&#xff0c;包括装饰器、生成器、上下文管理器、元类以及常用的设计模式。这些高级特性能够帮助你编写更强大、更灵活的代码。 10.1 装饰器 装饰器是一种特殊类型的函数&#xff0c;可以修改其他函数…...

harbor常见问题及解决方法分享

harbor常见问题及解决方法分享 参考自《harbor权威指南》。 1. harbor配置文件不生效 问题现象 无论是在生产环境下还是在测试环境下&#xff0c;都会有对配置文件进行修改的场景。很多用户在停掉Harbor容器后&#xff0c;都会修改配置文件然后启动Harbor&#xff0c;发现配…...

行列式与线性方程组解的关系

线性方程组是数学中一个重要的概念&#xff0c;它描述了多个变量之间的线性关系。行列式作为方阵的一个特殊值&#xff0c;对于判断线性方程组解的存在性和唯一性有着重要的作用。本文将探讨行列式与线性方程组解之间的关系&#xff0c;并区分齐次和非齐次方程组的情况。 齐次…...