人工智能概论 | 基于A*算法的8数码问题求解

大学四年的全部课程和考试都已经结束啦!

最近闲来无事,随便发发自己的实验报告,供后面的学弟学妹们参考~


目录

实验1 基于A*算法的8数码问题求解

1.1  程序总体流程

1.2  关键代码展示

1.3  输出结果展示及分析

1.3.1  总步数展示  

1.3.2  每一次的Open表和Closed表展示 

1.3.3  对输出结果的分析  

1.4  原始程序存在的问题

1.5  程序修改的核心内容

2.1  对两种新的启发式函数的说明

2.2  关键代码展示(3种不同的启发式函数)

2.3   输出结果展示及对比分析

2.3.1  总步数展示及对比分析  

2.3.2  Open表和Closed表展示及对比分析

2.4  三种启发式函数的特点及比较

2.5 实验一心得与体会


实验1 基于A*算法的8数码问题求解

(1)问题描述:在3*3的棋盘中有8个数码(数字块)和一个空格,只有与空格相邻的数码能移动到空格位置。从初始状态以最小的步长移动到目标状态。

(2)实验要求:参考A*算法核心代码,以8数码问题为例实现A*算法。

(3)实验内容:

1、基于参考代码,修改并运行程序,并画出程序的总体流程图。自动统计并输出到达目标的总步数,自动记录并输出每次移动后open表与closed表的变化。如果原始程序中存在不合理的逻辑,请指出其问题所在。如果程序进行了修改,请说明修改的核心内容。要求初始状态与目标状态分别为:

2、设计两种新的启发式函数,并运行程序。对包含示例在内的3种启发式函数的特点与结果进行对比分析。

1.1  程序总体流程

本实验是基于A*算法的求解8数码问题的实现。下面是该程序的总体流程:

(1)初始化初始状态和目标状态  初始状态和目标状态都是一个3x3的矩阵,分别代表了初始时的数码布局和目标状态下的数码布局。

(2)定义状态类 State  State 类用于表示问题中的一个状态。每个状态包含当前数码布局、可以移动的方向、父状态、从初始状态到当前状态的实际代价 g(n) 和当前状态到目标状态的估计代价 h(n)。这里使用了 Manhattan 距离作为启发式函数进行估计。

State 类中包含了一系列方法来获取方向、计算0点的位置、生成下一个可能的状态、计算启发式函数值等。

(3)A*算法求解  在 solve 方法中,程序使用 A* 算法来求解问题。初始时将初始状态加入 Open 表,然后循环进行以下步骤:

从 Open 表中选择 f(n) 最小的状态,将其移到 Closed 表中。

检查选择的状态是否为目标状态,如果是,则构建路径并返回;否则,生成当前状态的下一个可能状态,并加入 Open 表中。

对加入到 Open 表中的状态,计算其 g(n) 和 h(n),并更新其 f(n) 值。

如果 Open 表为空,且没有找到目标状态,则说明无解。

(4)打印结果  如果找到了解,程序将打印出解决方案的总步数,并逐步打印出每个状态的数码布局。如果未找到解,则打印出无解的消息。

总体而言,该程序的流程是先初始化状态,然后使用A*算法进行搜索,直到找到解或确定无解为止。

本程序的总体流程详见图1-1。

1.2  关键代码展示

本实验的关键代码如下所示。

class State:

    answer = np.array([[1, 2, 3], [8, 0, 4], [7, 6, 5]])

    def __init__(self, state, directionFlag=None, parent=None, f=0):

        self.state = state

        self.direction = ['up', 'down', 'right', 'left']

        if directionFlag:

            self.direction.remove(directionFlag)

        self.parent = parent

        self.f = f

        def getFunctionValue_ManhattanDistance(self, g_value):

        dist = 0

        for i in range(len(self.state)):

            for j in range(len(self.state)):

                if self.state[i][j] != State.answer[i][j]:

                    index = np.argwhere(State.answer == self.state[i][j])

                    x = index[0][0]

                    y = index[0][1]

                    dist += (abs(x - i) + abs(y - j))

        return dist + g_value

     def nextStep(self):

        subStates = []

        x, y = self.getZeroPos()

        boarder = len(self.state) - 1

        g_value = self.f - self.getFunctionValue_ManhattanDistance(0)  

        if 'left' in self.direction and y > 0:

            s = self.state.copy()

            s[x, y], s[x, y - 1] = s[x, y - 1], s[x, y]

            news = State(s, directionFlag='right', parent=self)

            news.setF(news.getFunctionValue_ManhattanDistance(g_value))

            subStates.append(news)

        if 'up' in self.direction and x > 0:

            s = self.state.copy()

            s[x, y], s[x - 1, y] = s[x - 1, y], s[x, y]

            news = State(s, directionFlag='down', parent=self)

            news.setF(news.getFunctionValue_ManhattanDistance(g_value))

            subStates.append(news)

        if 'down' in self.direction and x < boarder:

            s = self.state.copy()

            s[x, y], s[x + 1, y] = s[x + 1, y], s[x, y]

            news = State(s, directionFlag='up', parent=self)

            news.setF(news.getFunctionValue_ManhattanDistance(g_value))

            subStates.append(news)

        if 'right' in self.direction and y < boarder:

            s = self.state.copy()

            s[x, y], s[x, y + 1] = s[x, y + 1], s[x, y]

            news = State(s, directionFlag='left', parent=self)

            news.setF(news.getFunctionValue_ManhattanDistance(g_value))

            subStates.append(news)

        return subStates

    def solve(self):

        openTable = []  

closeTable = []

        openTable.append(self)

        step = 0

        while len(openTable) > 0:

            step += 1            

            n = openTable.pop(0)

            closeTable.append(n)

            subStates = n.nextStep()  

            for subState in subStates:

                if (subState.state == State.answer).all():

                    openTable.append(subState)

                    openTable.sort(key=lambda state: state.f)

                    path = [subState]

                    while subState.parent and subState.parent != self:

                        path.append(subState.parent)

                        subState = subState.parent

                    path.reverse()            

                 # 此处省略打印Open表和Closed表代码,详见源程序 #

                    return path

                openTable.append(subState)

            openTable.sort(key=lambda state: state.f)

            # 此处省略打印Open表和Closed表代码,详见源程序 #

        return None

1.3  输出结果展示及分析

1.3.1  总步数展示  

本程序运行后得到的总步数为5,详见表1-1、表1-2。

表1-1 结果展示(总步数)

初始状态

目标状态

是否有解

启发式函数

总步数

2 8 3

1 6 4

7 0 5

1 2 3

8 0 4

7 6 5

曼哈顿距离

5

表1-2 每一步的状态变化

步数

当前状态

0(初始状态)

2 8 3

1 6 4

7 0 5

1

2 8 3

1 0 4

7 6 5

2

2 0 3

1 8 4

7 6 5

3

0 2 3

1 8 4

7 6 5

4

1 2 3

0 8 4

7 6 5

5(目标状态)

1 2 3

8 0 4

7 6 5

1.3.2  每一次的Open表和Closed表展示 

下面展示的是每一次的Open表和Closed表的完整输出内容,详见表1-3和图1-3。(注明:最后一次已经找到目标状态,所以程序未输出此步的Open表和Closed表。)

表1-3 每一步的Open表和Closed表

次数

Open表

Closed表

1

2 8 3   2 8 3   2 8 3

1 0 4   1 6 4   1 6 4

7 6 5   0 7 5   7 5 0

2 8 3

1 6 4

7 0 5

2

2 0 3   2 8 3   2 8 3    

1 8 4   0 1 4   1 4 0   

7 6 5   7 6 5   7 6 5 

  

2 8 3   2 8 3

1 6 4   1 6 4

0 7 5   7 5 0

2 8 3   2 8 3

1 6 4   1 0 4

7 0 5   7 6 5

3

0 2 3   2 8 3   2 8 3

1 8 4   0 1 4   1 4 0

7 6 5   7 6 5   7 6 5

2 8 3   2 8 3   2 3 0

1 6 4   1 6 4   1 8 4

0 7 5   7 5 0   7 6 5

2 8 3   2 8 3   2 0 3

1 6 4   1 0 4   1 8 4

7 0 5   7 6 5   7 6 5

4

1 2 3   2 8 3   2 8 3

0 8 4   0 1 4   1 4 0

7 6 5   7 6 5   7 6 5

2 8 3   2 8 3   2 3 0

1 6 4   1 6 4   1 8 4

0 7 5   7 5 0   7 6 5

2 8 3   2 8 3   2 0 3

1 6 4   1 0 4   1 8 4

7 0 5   7 6 5   7 6 5

0 2 3

1 8 4

7 6 5

5

1 2 3   2 8 3   2 8 3

8 0 4   0 1 4   1 4 0

7 6 5   7 6 5   7 6 5

2 8 3   2 8 3   2 3 0

1 6 4   1 6 4   1 8 4

0 7 5   7 5 0   7 6 5

1 2 3

7 8 4

0 6 5

2 8 3   2 8 3   2 0 3

1 6 4   1 0 4   1 8 4

7 0 5   7 6 5   7 6 5

0 2 3   1 2 3

1 8 4   0 8 4

7 6 5   7 6 5

6

当前Sg是目标状态,成功退出,本次搜索结束!

1.3.3  对输出结果的分析  

在这个结果中,搜索算法成功地找到了从初始状态到目标状态的路径,总共经过了5个步骤。这个结果表明了所使用的A*算法能够有效地在状态空间中搜索,并找到最优解。其中,分析结果的关键点包括:

(1)搜索策略有效性  搜索过程中,每一步都是根据启发式函数的估计值来决定下一步的状态选择,这使得算法能够朝着更有可能达到目标的方向前进。

(2)搜索算法优化  在搜索过程中,采用了一些优化策略,比如对已经搜索过的状态进行记录和排除,以避免重复搜索。此外,对于下一步可能的状态,根据启发式函数的估值进行排序,优先选择估值较小的状态,以加速搜索过程。

(3)搜索路径可视化  最终输出了搜索过程中的每个步骤和状态,这有助于理解算法的执行过程,并且提供了一种对算法性能的直观评估方式。

总的来说,这个结果表明所使用的搜索算法在解决八数码问题上具有较好的效果,能够快速而有效地找到最优解。

1.4  原始程序存在的问题

原始代码的逻辑错误在于nextStep函数中的实现和solve函数中的调用方式。 具体来说,nextStep函数应该返回一个包含所有可能下一步状态的列表,而不是仅返回一个状态。当前的实现在每次调用nextStep时只返回一个状态,这会导致只能扩展一个状态,而不是所有可能的状态。

在solve函数中,虽然将subStates加入了openTable,但是openTable应该存放待探索的状态,而不是直接放入subStates,应该将subStates中的所有状态加入openTable,而不是仅加入其中的一个。

除了上述逻辑问题外,我还发现原始代码存在下列问题。

(1)getFunctionValue 方法中的变量 self.answer 未定义。这个变量在类中未被初始化或设置。为了解决这个问题,可以将 State 类的构造函数修改为接收 answer 参数,并在初始化时设置该属性。

(2)在 nextStep 方法中,当检查是否可以向右移动时,使用了 count 方法来检查 'right' 是否在 self.direction 中。应该使用 in 关键字来检查。修正这一问题后,if 语句应该是 if 'right' in self.direction and y < boarder:。

(3)在使用曼哈顿距离作为启发式函数getFunctionValue的实现中,g(x)不应该恒等于1,而应该等于初始状态到当前状态的实际路径成本。

1.5  程序修改的核心内容

原始程序的核心修改内容如下。

(1)修改了 nextStep 方法,使其返回包含所有可能下一步状态的列表,而不是仅返回一个状态。

(2)在 solve 方法中,将 subStates 中的所有状态都加入 openTable 中,而不仅仅是其中的一个状态。

(3)在 State 类中添加了 answer 参数,以解决 getFunctionValue 方法中的 self.answer 未定义的问题。

(4)在 getFunctionValue 方法中,计算实际路径成本 g(x),而不是恒等于 1。这通过计算从初始状态到当前状态的移动步数来实现。

(5)在 nextStep 方法中,使用 in 关键字来检查方向是否在 self.direction 中,并修复了向右移动的判断逻辑。

2.1  对两种新的启发式函数的说明

当使用A*搜索算法解决问题时,需要使用启发式函数来评估状态的优劣。这些启发式函数可以帮助算法更有效地搜索最优解。在本实验中,除了一开始使用的曼哈顿距离之外,我还设计了以下两种新的启发式函数。

(1)不在位数字的数量  这个启发式函数简单地计算当前状态中与目标状态不同的数字的数量。这些数字的数量越多,表示状态越远离目标状态。因此,该启发式函数的值越大,表示状态越不优。具体地,如果一个数字不在它应该在的位置上,则它是一个不在位数字。不在位数字的数量可以直接用来评估状态的距离。

(2)欧几里得距离  欧几里得距离是当前状态与目标状态的每个数字位置的欧几里得距离之和。简单来说,对于每个数字,我们计算其在当前状态和目标状态中的位置之间的直线距离,然后将所有数字的距离加起来。这个距离是欧几里得距离的一种应用。该启发式函数考虑了数字在空间上的位置,可以更准确地评估状态之间的距离。因此,如果一个状态中的数字与目标状态的数字更接近,那么欧几里得距离就会更小,启发式函数值也会更小,表示状态更优。

在实践中,这两种启发式函数都可以有效地帮助A*算法搜索到最优解。不在位数字的数量是一种直观的评估方式,但可能不够准确。而欧几里得距离考虑了数字之间的空间关系,提供了更精确的评估,但也更加复杂和计算密集。在选择启发式函数时,需要根据具体情况进行权衡和选择。

2.2  关键代码展示(3种不同的启发式函数)

#使用曼哈顿距离作为启发式函数

def getFunctionValue_ManhattanDistance(self, g_value):

        dist = 0

        for i in range(len(self.state)):

            for j in range(len(self.state)):

                if self.state[i][j] != State.answer[i][j]:

                    index = np.argwhere(State.answer == self.state[i][j])

                    x = index[0][0]

                    y = index[0][1]

                    dist += (abs(x - i) + abs(y - j))

        return dist + g_value

    #使用不在位个数作为启发式函数

    def getFunctionValue_notInPosition(self):

        count = 0

        for i in range(len(self.state)):

            for j in range(len(self.state[0])):

                if self.state[i][j] != State.answer[i][j]:

                    count += 1

        if self.state[1][1] == State.answer[1][1]:

            count += 1

        return count - 1

  

  #使用欧几里得距离作为启发式函数

    def getFunctionValue_EuclideanDistance(self, g_value):

        dist = 0

        for i in range(len(self.state)):

            for j in range(len(self.state[0])):

                if self.state[i][j] != 0 and self.state[i][j] < len(self.state) * len(self.state[0]):

                    target_i, target_j = divmod(State.answer.flatten().tolist().index(self.state[i][j]), len(self.state))

                    dist += ((target_i - i) ** 2 + (target_j - j) ** 2) ** 0.5

        return dist + g_value

2.3   输出结果展示及对比分析

下面展示的是三种不同启发式函数的程序运行结果,其中曼哈顿距离作为启发式函数的结果已经在第1个问题中进行了详细说明,因此这里不再赘述。

2.3.1  总步数展示及对比分析  

(1)不在位数字的数量  本程序运行后得到的总步数为5,详见图2-1。

(2)欧几里得距离  本程序运行后得到的总步数为5,详见图2-2。

(3)对比分析  由上述结果可知,三种不同的启发式函数的总步数都是相同的,均为5步。

从效率上来看,由三种启发式函数的总步数相同可知,在这个问题中的效率是相同的,它们都找到了最优路径。

从复杂度来看,虽然总步数相同,但每种启发式函数在搜索过程中所考虑的因素不同。不在位数字的数量直接计算了当前状态与目标状态之间的差异,欧几里得距离和曼哈顿距离则考虑了数字的位置信息。在实际问题中,曼哈顿距离通常更容易计算,因为它只涉及数字的位置之差的绝对值之和。

2.3.2  Open表和Closed表展示及对比分析

(1)不在位数字的数量  本程序运行后得到的Open表和Closed表,如图2-3所示。

(2)欧几里得距离  本程序运行后得到的Open表和Closed表和以曼哈顿距离作为启发式函数的结果完全一致,在此不再赘述。

(3)对比分析  由上述结果可知,当不在位数字的数量作为启发式函数时,输出的Open表和Closed表和另外两个启发式函数的不同。

每种启发式函数的Open表和Closed表在每个步骤中可能会有所不同。这是因为不同的启发式函数会影响搜索算法如何评估和排序每个状态的优先级,从而影响到算法的具体执行路径。虽然三者的最终解决方案路径相同的,但在搜索过程中,Open表和Closed表的具体内容可能会有所不同。

不在位数字的数量作为启发式函数,会根据每个状态中不在位的数字数量来评估其与目标状态的距离。这种方式可能会导致搜索算法在展开状态时优先考虑那些不在位数字数量较少的状态,从而影响Open表和Closed表的内容。这也是为什么不在位数字的数量作为启发式函数时,得到了与另外两个启发式函数不同的输出过程。

而欧几里得距离和曼哈顿距离作为启发式函数,考虑了数字的位置信息,因此在搜索过程中可能会产生不同的评估结果,从而影响Open表和Closed表的内容。在这里,我们的发现欧几里得距离和曼哈顿距离作为启发式函数,得到结果相同。

因此,即使是相同的问题和初始状态,不同的启发式函数可能会导致不同的搜索路径和展开顺序,最终可能会得到略有不同的Open表和Closed表。

2.4  三种启发式函数的特点及比较

最后让我们对这三种启发式函数的各自特点进行比较分析。

对于不在位数字的数量,其特点及比较分析如下所示。

(1)简单直观  只需计算当前状态与目标状态中不同数字的数量。

(2)计算简单  只需遍历状态矩阵一次即可完成计算。

(3)比较分析  该启发式函数的结果会高估状态之间的距离,因为它只考虑了数字的数量而忽略了数字的位置信息。

当状态之间的差异主要是由不在位数字引起时,该启发式函数可能会提供合理的估计,但在某些情况下可能不够准确。

对于欧几里得距离,其特点及比较分析如下所示。

(1)考虑空间关系  计算每个数字在空间中的位置,并将其转化为欧几里得距离。

(2)提供精确估计  考虑了数字之间的实际距离,提供了更精确的状态距离估计。

(3)比较分析  由于考虑了数字之间的实际距离,该启发式函数提供了更准确的状态距离估计。但是,计算欧几里得距离可能会更复杂,尤其是对于大型状态空间。

对于曼哈顿距离,其特点及比较分析如下所示。

(1)考虑位移关系  考虑了每个数字在水平和垂直方向上的位移。

(2)简化计算  只需计算数字的水平和垂直位移的绝对值之和。

(3)比较分析  曼哈顿距离提供了对状态距离的相对准确估计。

与欧几里得距离相比,曼哈顿距离更简单,计算速度更快,但通常会高估状态之间的距离。

综上所述,不同的启发式函数在八数码问题中都有其优缺点。欧几里得距离提供了最准确的距离估计,但计算复杂度较高。曼哈顿距离相对较简单,计算速度快,但可能会高估状态之间的距离。而不在位数字的数量则是一种简单直观的评估方式,计算简单但可能不够准确。在实践中,根据问题的具体情况和要求,选择适当的启发式函数非常重要。

2.5 实验一心得与体会

在本次实验中,我实现了A*搜索算法来解决八数码问题,并设计了三种不同的启发式函数。下面是我在完成本实验后的一些个人心得与体会。

首先,启发式函数对A*搜索算法的性能至关重要。曼哈顿距离作为一种经典的启发式函数,简单易用且在许多情况下能提供合理的结果。然而,本次实验中,我发现不在位数字的数量和欧几里得距离这两种新的启发式函数也能有效地帮助算法找到最优解。这提醒我在解决问题时应该多角度思考,不拘泥于传统的方法,而是灵活运用各种技术手段。

其次,实验中对比了三种启发式函数的性能及特点。欧几里得距离在提供更准确的状态距离估计方面具有优势,但计算复杂度相对较高;曼哈顿距离计算简单且速度快,但可能会高估状态之间的距离;而不在位数字的数量则简单直观,但准确性可能不足。这表明在选择启发式函数时需要综合考虑准确性和计算复杂度,并根据具体问题的需求做出权衡。

最后,实验过程中我也意识到了算法的执行路径可能会受到启发式函数的影响。不同的启发式函数会导致搜索算法展开状态的顺序不同,从而影响到算法的执行路径。这提示我在实际问题中,要对不同的启发式函数进行综合评估,并选择最适合的启发式函数以达到更好的性能。

总的来说,本次实验让我深入了解了A*搜索算法及启发式函数的原理和应用,提高了我对算法设计和问题求解的理解能力。同时也加深了我对算法性能评估和选择的认识,为我今后在解决实际问题时提供了有益的指导。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Python编程学习笔记(1)--- 变量和简单数据类型

1、变量 在学习编程语言之前&#xff0c;所接触的第一个程序&#xff0c;绝大多数都是&#xff1a; print("Hello world!") 接下来尝试使用一个变量。在代码中的开头添加一行代码&#xff0c;并对第二行代码进行修改&#xff0c;如下&#xff1a; message "…

云计算【第一阶段(27)】DHCP原理与配置以及FTP的介绍

一、DHCP工作原理 1.1、DHCP概念 动态主机配置协议 DHCP&#xff08;Dynamic Host Configuration Protocol&#xff0c;动态主机配置协议&#xff0c;该协议允许服务器向客户端动态分配 IP 地址和配置信息。 DHCP协议支持C/S&#xff08;客户端/服务器&#xff09;结构&…

c++之命名空间详解(namespace)

引例 在学习之前我们首先了来看这样一个情形: 在c语言下&#xff0c;我们写了两个头文件&#xff1a;链表和顺序表的。我们会定义一个type(typedef int type)方便改变数据类型&#xff08;比如将int改成char&#xff09;&#xff0c;来做到整体代换。 但是我们两个头文件里面…

C# 实现基于exe内嵌HTTPS监听服务、从HTTP升级到HTTPS 后端windows服务

由于客户需要把原有HTTP后端服务升级为支持https的服务&#xff0c;因为原有的HTTP服务是一个基于WINDOWS服务内嵌HTTP监听服务实现的&#xff0c;并不支持https, 也不像其他IIS中部署的WebAPI服务那样直接加载HTTPS证书&#xff0c;所以这里需要修改原服务支持https和服务器环…

JavaScript中,正则表达式所涉及的api,解析、实例和总结

JS中正则的api包括以下&#xff1a; String#searchString#splitString#matchString#replaceRegExp#testRegExp#exec 1. String#search 查找输入串中第一个匹配正则的index&#xff0c;如果没有匹配的则返回-1。g修饰符对结果无影响 var string "abbbcbc"; var r…

iperf3: error - unable to connect to server: No route to host

1.确认iperf3版本是否统一。 2.确认防火墙是否关闭。 关闭防火墙 : systemctl stop firewalld 查看防火墙状态: systemctl status firewalld 3.重新建起链接

(三)前端javascript中的数据结构之集合

集合的特点 1.无序 2.唯一性 3.不可重复 集合相对于前面几种数据结构&#xff0c;比较简单好理解&#xff0c;看看代码实现就能知道他的用法了 集合的创建 function MySet() {this.item {}; } MySet.prototype.has function (value) {return value in this.item; };//增 M…

Java-链表中倒数最后k个结点

题目&#xff1a; 输入一个长度为 n 的链表&#xff0c;设链表中的元素的值为 ai &#xff0c;返回该链表中倒数第k个节点。 如果该链表长度小于k&#xff0c;请返回一个长度为 0 的链表。 数据范围&#xff1a;0≤&#x1d45b;≤1050≤n≤105&#xff0c;0≤&#x1d44e;…

c#字符串常用方法

目录 1.字符串的处理常用方法 1.1 Format 1.2 IsNullOrEmpty和IsNullOrWhiteSpace 1.3 Equals 1.4 Contains 1.5 Length 1.6 Substring 1.7 IndexOf和LastIndexOf 1.8 ​​​​​​​StartsWith 和 EndsWith 1.9 ​​​​​​​Remove 1.10 ​​​​​​​Revserse…

Java---包装类与泛型

1.包装类 1.1 包装类 在Java中&#xff0c;由于基本数据类型不是继承Object类&#xff0c;为了在泛型代码中可以支持基本数据类型&#xff0c;Java给每个基本数据类型各自提供了一个包装类。 如下图 除了char和int基本数据类型的包装类型有点特别&#xff0c;其他的都是首字…

20240708 每日AI必读资讯

&#x1f916;破解ChatGPT惊人耗电&#xff01;DeepMind新算法训练提效13倍&#xff0c;能耗暴降10倍 - 谷歌DeepMind研究团队提出了一种加快AI训练的新方法——多模态对比学习与联合示例选择&#xff08;JEST&#xff09;&#xff0c;大大减少了所需的计算资源和时间。 - JE…

MySQL高级----InnoDB引擎

逻辑存储结构 表空间 表空间(ibd文件)&#xff0c;一个mysql实例可以对应多个表空间&#xff0c;用于存储记录、索引等数据。 段 段&#xff0c;分为数据段&#xff08;Leaf node segment)、索引段(Non-leaf node segment)、回滚段(Rollback segment)&#xff0c;InnoDB是…

Go-Zero 框架使用 MongoDB,数据采集入库如此简单

目录 引言 环境准备 如何使用 main入口代码实现 实现采集网络接口 总结 其他资源 引言 Go-Zero 是一个高性能、可扩展的微服务框架&#xff0c;专为 Go 语言设计。它提供了丰富的功能&#xff0c;如 RPC、RESTful API 支持、服务发现、熔断器、限流器等&#xff0c;使开…

2024数据加密神器丨企业级透明加密软件排行榜

透明加密软件通过在操作系统层面进行底层驱动开发&#xff0c;对指定类型的文件进行自动透明加解密。这种加密方式对用户来说是完全透明的&#xff0c;用户在使用加密文件时&#xff0c;不会感到任何不便。同时&#xff0c;由于加密是在文件级别进行的&#xff0c;因此可以有效…

SRS流媒体服务器概述

SRS/5.0(Bee) is a simple, high efficiency and realtime video server, supports RTMP, WebRTC, HLS, HTTP-FLV, SRT, MPEG-DASH and GB28181. 翻译&#xff1a;SRS/5.0(Bee)是一款简洁、高效、实时的视频服务器&#xff0c;支持RTMP、WebRTC、HLS、HTTP-FLV、SRT、MPEG-DAS…

vue 启动项目报错Syntax Error: Error: PostCSS received undefined instead of CSS string

启动vue项目然后报错如下图 这个是跟node版本有关系 因为要开发不同的项目使用不同的node版本&#xff0c;所以就用nvm切换&#xff0c;所以导致了node-sass编译问题 执行这个命令就可以 npm install node-sass or npm rebuild node-sass node-sass对于node高版本和低版本切…

我与OceanBase|一位DBA老兵的国产数据库探索之旅

本文作者&#xff1a;尚雷&#xff0c;有超过十年的工作经验&#xff0c;目前就职于南京一家上市互联网企业&#xff0c;担任DBA。Oracle 11g OCM&#xff0c;Oracle及PG的 ACE认证&#xff0c;并有AWS及国产知名数据库等多项认证。他热衷于技术交流与分享&#xff0c;爱交友&a…

C++·栈和队列

栈和队列是什么看这里&#xff1a; 数据结构栈和队列-CSDN博客文章浏览阅读948次&#xff0c;点赞25次&#xff0c;收藏26次。本节讲解了栈和队列的内容&#xff0c;其核心就是栈的特点是后进先出&#xff0c;队列的特点是先进先出。并用C语言实现了栈和队列的结构以及它们的各…

深度解析移动硬盘“函数不正确”错误及高效恢复策略

在数据密集型的社会中&#xff0c;移动硬盘作为移动存储的重要载体&#xff0c;承载着无数用户的个人信息、工作资料及珍贵回忆。然而&#xff0c;当遭遇“函数不正确”的错误时&#xff0c;这些宝贵的数据仿佛被一层无形的屏障所阻隔&#xff0c;让人束手无策。本文将深入探讨…

SiCat:一款多功能漏洞利用管理与搜索工具

关于SiCat SiCat是一款多功能漏洞利用管理与搜索工具&#xff0c;该工具基于纯Python 3开发&#xff0c;旨在帮助广大研究人员有效地识别和收集来自开源和本地存储库的漏洞信息。 SiCat专注于网络安全管理方面的实践工作&#xff0c;允许研究人员快速实现在线搜索&#xff0c;…