蚁群算法原理与实战(Python、MATLAB、C++)

news2024/9/22 11:24:43

蚁群算法


1.蚁群算法来源

蚁群算法(Ant Colony Optimization,简称ACO)是一种模拟自然界中蚂蚁寻找食物路径行为的优化算法,主要用于解决组合优化问题。它的灵感来源于意大利学者Marco Dorigo在1992年提出的蚂蚁系统模型。

在这里插入图片描述

蚁群算法的灵感来源于自然界中蚂蚁寻找食物的行为。蚂蚁在寻找食物的过程中会释放一种称为信息素的化学物质,这种物质会在蚂蚁走过的路径上留下痕迹,后续的蚂蚁会根据这些信息素的浓度来选择路径,从而形成一条从蚁巢到食物源的最短路径。蚂蚁觅食的过程是一个正反馈的过程,该路段经过的蚂蚁越多,信息素留下的就越多,浓度越高,更多的蚂蚁都会选择这个路段。

这种行为模式启发了科学家们设计出蚁群算法,用于解决复杂的优化问题。

2.蚁群算法基本原理

在这里插入图片描述

蚁群算法的基本原理可以概括为以下几个步骤:

(1)初始化:设定每个解(相当于蚂蚁可能行走的路径)的信息素初始值,通常设置为一个较小的正数。
(2)蚂蚁构建解:每只蚂蚁根据当前的信息素浓度和启发式信息(如距离的倒数)来选择下一步要走的路径。这个过程是概率性的,信息素浓度越高,被选中的概率越大。
(3)信息素更新:一轮搜索结束后,根据蚂蚁找到的解的质量来更新信息素。通常情况下,较优的解对应的路径上的信息素会被加强,而较差解对应的信息素则会减少或蒸发。
(4)循环迭代:重复上述过程,直到满足停止条件(如达到最大迭代次数或解的质量不再明显提高)。
通过这样的机制,蚁群算法能够在解空间中逐渐逼近最优解。需要注意的是,蚁群算法是一种随机优化算法,每次运行可能会得到不同的结果,但多次运行后往往能够找到接近最优的解。

数学原理:

在这里插入图片描述

3.蚁群算法的应用

蚁群算法的应用非常广泛,包括旅行商问题(TSP)、图着色问题、网络路由优化、调度问题等。它特别适合于解决大规模的、复杂的优化问题,尤其是那些难以用传统数学方法求解的问题。

下面简单介绍一些经典的应用:

(1)旅行商问题(TSP):最初被用于解决TSP问题,即在给定一组城市中找到最短的巡回路径。
在这里插入图片描述

(2)物流和交通:用于优化物流配送路径、车辆路径规划和交通信号控制等问题。

**(3)网络路由:**在计算机网络和通信网络中,用于动态路由选择以提高网络效率。

**(4)生产调度:**在制造业中,用于优化生产计划和调度,减少生产成本和时间。

**(5)图像处理:**用于图像分割、边缘检测等图像处理任务。

(6)图着色问题:

在这里插入图片描述

4.蚁群算法解决TSP问题

旅行商问题(Traveling saleman problem, TSP)是物流配送的典型问题,其求解有十分重要的理论和现实意义。

旅行商问题传统的解决方法都是遗传算法,但是遗传算法的收敛速度慢,具有一定的缺陷。

在求解TSP蚁群算法中,每只蚂蚁相互独立,用于构造不同的路线,蚂蚁之间通过信息素进行交流,合作求解。

动图展示TSP问题求解过程:
在这里插入图片描述

下面介绍一下具体流程:

(1)初始化参数:epochs表示迭代次数,ants表示蚂蚁数量,alpha和beta是信息素重要程度的参数,rho是信息素挥发速度,Q是信息素强度常数。

(2)计算城市之间的距离矩阵:使用numpy的linalg.norm函数计算每对城市之间的欧几里得距离,并将结果存储在Distance矩阵中。

(3)初始化信息素矩阵Tau:将所有元素设置为1.0。

(4)初始化每只蚂蚁的路线图Route:创建一个ants x cities的零矩阵,表示每只蚂蚁访问过的城市。

(5)进行迭代:对于每次迭代,首先为每只蚂蚁随机选择一个起始城市,然后根据概率选择下一个要访问的城市。概率由信息素浓度和启发式信息共同决定。

(6)计算每只蚂蚁的总距离:遍历每只蚂蚁的路线,累加经过的城市之间的距离。

(7)更新最优解:如果当前迭代中找到了一条更短的路径,就更新最优距离和最优路线。

(8)更新信息素:根据蚂蚁走过的路径,更新信息素矩阵Tau。

(9)输出结果:打印出找到的最短路径和对应的距离。

程序中各符号说明如下表格:

变量/矩阵名称维度描述
position(cities, 2)城市坐标数组,每行代表一个城市的x和y坐标。
Distance(cities, cities)城市之间的距离矩阵,存储每两个城市之间的欧几里得距离。
Eta(cities, cities)启发式信息矩阵,是Distance矩阵的倒数,用于指导蚂蚁选择路径。
Tau(cities, cities)信息素矩阵,表示在每两个城市之间的路径上的信息素浓度。
Route(ants, cities)蚂蚁路径矩阵,存储每一只蚂蚁在当前迭代中的路径。
best_distance1变量,存储迄今为止找到的最短路径的长度。
best_route(cities,)数组,存储迄今为止找到的最短路径的城市顺序。
epochs1算法运行的迭代次数。
ants1蚁群中蚂蚁的数量。
alpha1信息素重要性的影响因子。
beta1启发式信息重要性的影响因子。
rho1信息素蒸发率。
Q1信息素强度,用于在每次迭代后更新信息素矩阵。

最终结果展示:

在这里插入图片描述
在这里插入图片描述

完整python代码如下:

import numpy as np
import random
 
# 城市坐标
x = np.array([51, 27, 56, 21, 4, 6, 58, 71, 54, 40, 94, 18, 89, 33, 12, 25, 24, 58, 71, 94, 17, 38, 13, 82, 12, 58, 45, 11, 47, 4])
y = np.array([14, 81, 67, 92, 64, 19, 98, 18, 62, 69, 30, 54, 10, 46, 34, 18, 42, 69, 61, 78, 16, 40, 10, 7, 32, 17, 21, 26, 35, 90])
position = np.column_stack((x, y))
 
epochs = 50
ants = 50
alpha = 1.4
beta = 2.2
rho = 0.15
Q = 10**6
cities = position.shape[0]
 
# 城市之间的距离矩阵
Distance = np.ones((cities, cities))
for i in range(cities):
    for j in range(cities):
        if i != j:
            Distance[i, j] = np.linalg.norm(position[i] - position[j])
        else:
            Distance[i, j] = np.finfo(float).eps
 
Eta = 1.0 / Distance
Tau = np.ones((cities, cities))
 
# 每只蚂蚁的路线图
Route = np.zeros((ants, cities))
best_distance = np.inf
best_route = np.zeros(cities)
 
for epoch in range(epochs):
    # 为每只蚂蚁随机选择一个唯一的起始城市
    start_cities = np.random.permutation(cities).tolist()
    for i in range(ants):
        Route[i, 0] = start_cities[i % cities]
 
    for j in range(1, cities):
        for i in range(ants):
            Visited = Route[i, :j]
            NoVisited = np.setdiff1d(np.arange(cities), Visited)
            P = np.zeros(len(NoVisited))
            for k in range(len(NoVisited)):
                P[k] = (Tau[int(Visited[-1]), int(NoVisited[k])] ** alpha) * (Eta[int(Visited[-1]), int(NoVisited[k])] ** beta)
            P = P / P.sum()
            Pcum = np.cumsum(P)
            select = np.where(Pcum >= random.random())[0][0]
            to_visit = NoVisited[select]
            Route[i, j] = to_visit
 
    Distance_epoch = np.zeros(ants)
    for i in range(ants):
        R = Route[i, :]
        for j in range(cities - 1):
            Distance_epoch[i] += Distance[int(R[j]), int(R[j + 1])]
        Distance_epoch[i] += Distance[int(R[0]), int(R[-1])]
 
    best_distance_epoch = np.min(Distance_epoch)
    best_index_epoch = np.argmin(Distance_epoch)
    if best_distance_epoch < best_distance:
        best_distance = best_distance_epoch
        best_route = Route[best_index_epoch, :]
 
    Delta_Tau = np.zeros((cities, cities))
    for i in range(ants):
        for j in range(cities - 1):
            Delta_Tau[int(Route[i, j]), int(Route[i, j + 1])] += Q / Distance_epoch[i]
        Delta_Tau[int(Route[i, 0]), int(Route[i, -1])] += Q / Distance_epoch[i]
 
    Tau = (1 - rho) * Tau + Delta_Tau
 
print("最短路径:", best_route)
print("最短距离:", best_distance)

MATLAB代码如下:

动图显示路径部分

function DrawRoute(C, R)
N = length(R);
scatter(C(:, 1), C(:, 2));
hold on
plot([C(R(1), 1), C(R(N), 1)], [C(R(1), 2), C(R(N), 2)], 'g');
for ii = 2: N
    hold on
    plot([C(R(ii - 1), 1), C(R(ii), 1)], [C(R(ii - 1), 2), C(R(ii), 2)], 'g');
    pause(0.1)
    frame = getframe(gcf);
    imind = frame2im(frame);
    [imind, cm] = rgb2ind(imind, 256);
    if ii == 2
        imwrite(imind, cm, 'test.gif', 'gif', 'Loopcount', inf, 'DelayTime', 1e-4);
    else
        imwrite(imind, cm, 'test.gif', 'gif', 'WriteMode', 'append', 'DelayTime', 1e-4);
    end
end
title('旅行商规划');

蚁群算法部分:

clear;
clc;
x=[51 27 56 21 4 6 58 71 54 40 94 18 89 33 12 25 24 58 71 94 17 38 13 82 12 58 45 11 47 4]';
y=[14 81 67 92 64 19 98 18 62 69 30 54 10 46 34 18 42 69 61 78 16 40 10 7 32 17 21 26 35 90]';
position = 100 * randn(40, 2);
% position = [x, y];
epochs = 50;
ants = 50;
alpha = 1.4;
beta = 2.2;
rho = 0.15;Q = 10^6;
cities = size(position, 1);
% 城市之间的距离矩阵
Distance = ones(cities, cities);
for i = 1: cities
    for j = 1: cities
        if i ~= j
            Distance(i, j) = ((position(i, 1) - position(j, 1))^2 + (position(i, 2) - position(j, 2))^2)^0.5;
        else
            Distance(i, j) = eps;
        end
        Distance(j, i) = Distance(i, j);
    end
end
Eta = 1./Distance;
Tau = ones(cities, cities);
% 每只蚂蚁的路线图
Route = zeros(ants, cities);
epoch = 1;
% 记录每回合最优城市
R_best = zeros(epochs, cities);
L_best = inf .* ones(epochs, 1);
L_ave = zeros(epochs, 1);
% 开始迭代
while epoch <= epochs
    % 随机位置
    RandPos = [];
    for i = 1: ceil(ants / cities)
        RandPos = [RandPos, randperm(cities)];
    end
    Route(:, 1) = (RandPos(1, 1:ants))';
    for j = 2:cities
        for i = 1: ants
            Visited = Route(i, 1:j-1);
            NoVisited = zeros(1, (cities - j + 1));
            P = NoVisited;
            num = 1;
            for k = 1: cities
                if length(find(Visited == k)) == 0
                    NoVisited(num) = k;
                    num = num + 1;
                end
            end
            for k = 1: length(NoVisited)
                P(k) = (Tau(Visited(end), NoVisited(k))^alpha) * (Eta(Visited(end), NoVisited(k))^beta);
            end
            P = P / sum(P);
            Pcum = cumsum(P);
            select = find(Pcum >= rand);
            to_visit = NoVisited(select(1));
            Route(i, j) = to_visit;
        end
    end
    if epoch >= 2
        Route(1, :) = R_best(epoch - 1, :);
    end
    Distance_epoch = zeros(ants, 1);
    for i = 1: ants
        R = Route(i, :);
        for j = 1: cities - 1
            Distance_epoch(i) = Distance_epoch(i) + Distance(R(j), R(j + 1));
        end
        Distance_epoch(i) = Distance_epoch(i) + Distance(R(1), R(cities));
    end
    L_best(epoch) = min(Distance_epoch);
    pos = find(Distance_epoch == L_best(epoch));
    R_best(epoch, :) = Route(pos(1), :);
    L_ave(epoch) = mean(Distance_epoch);
    epoch = epoch + 1;
    
    Delta_Tau = zeros(cities, cities);
    for i = 1: ants
        for j = 1: (cities - 1)
            Delta_Tau(Route(i, j), Route(i, j + 1)) = Delta_Tau(Route(i, j), Route(i, j + 1)) + Q / Distance_epoch(i);
        end
        Delta_Tau(Route(i, 1), Route(i, cities)) = Delta_Tau(Route(i, 1), Route(i, cities)) + Q / Distance_epoch(i);
    end
    Tau = (1 - rho) .* Tau + Delta_Tau;
    Route = zeros(ants, cities);
end
%% 结果展示
Pos = find(L_best == min(L_best));
Short_Route = R_best(Pos(1), :);
Short_Length = L_best(Pos(1), :);
figure
% subplot(121);
DrawRoute(position, Short_Route);
% subplot(122);
% plot(L_best);
% hold on
% plot(L_ave, 'r');
% title('平均距离和最短距离');

蚁群算法解决TSP问题(c++)


#include<iostream>
#include<stdio.h>
#include<string>
#include<string.h>
#include<cmath>
#include<ctime>
#include<stdlib.h>
using namespace std;
int seed=(int)time(0);//产生随机种子
int CityPos[30][2]= {{87,7},{91,38},{83,46},{71,44},{64,60},{68,58},{83,69},{87,76},{74,78},{71,71},{58,69},{54,62},{51,67},{37,84},{41,94},{2,99},{7,64},{22,60},{25,62},{18,54},{4,50},{13,40},{18,40},{24,42},{25,38},{41,26},{45,21},{44,35},{58,35},{62,32}};
#define CITY_NUM 30//城市数量
#define ANT_NUM 30//蚁群数量
#define TMAC 10000//迭代最大次数
#define ROU 0.5//误差大小
#define ALPHA 1//信息素重要程度的参数
#define BETA 4//启发式因子重要程度的参数
#define Q 100//信息素残留参数
#define maxn 100
#define inf 0x3f3f3f3f
double dis[maxn][maxn];//距离矩阵
double info[maxn][maxn];//信息素矩阵
bool vis[CITY_NUM][CITY_NUM];//标记矩阵
 
//返回指定范围内的随机整数
int rnd(int low,int upper)
{
    return low+(upper-low)*rand()/(RAND_MAX+1);
}
 
//返回指定范围内的随机浮点数
double rnd(double low,double upper)
{
    double temp=rand()/((double)RAND_MAX+1.0);
    return low+temp*(upper-low);
}
 
struct Ant
{
    int path[CITY_NUM];//保存蚂蚁走的路径
    double length;//路径总长度
    bool vis[CITY_NUM];//标记走过的城市
    int cur_cityno;//当前城市
    int moved_cnt;//已走城市数量
 
    //初始化
    void Init()
    {
        memset(vis,false,sizeof(vis));
        length=0;
        cur_cityno=rnd(0,CITY_NUM);
        path[0]=cur_cityno;
        vis[cur_cityno]=true;
        moved_cnt=1;
    }
 
    //选择下一个城市
    int Choose()
    {
        int select_city=-1;//所选城市编号
        double sum=0;
        double prob[CITY_NUM];//保存每个城市被选中的概率
        for(int i=0; i<CITY_NUM; i++)
        {
            if(!vis[i])
            {
                prob[i]=pow(info[cur_cityno][i],ALPHA)*pow(1.0/dis[cur_cityno][i], BETA);
                sum=sum+prob[i];
            }
            else
            {
                prob[i]=0;
            }
        }
        //进行轮盘选择
        double temp=0;
        if(sum>0)//总的信息素大于0
        {
            temp=rnd(0.0,sum);
            for(int i=0; i<CITY_NUM; i++)
            {
                if(!vis[i])
                {
                    temp=temp-prob[i];
                    if(temp<0.0)
                    {
                        select_city=i;
                        break;
                    }
                }
            }
        }
        else //信息素太少就随便找个没走过的城市
        {
            for(int i=0; i<CITY_NUM; i++)
            {
                if(!vis[i])
                {
                    select_city=i;
                    break;
                }
            }
        }
        return select_city;
    }
 
    //蚂蚁的移动
    void Move()
    {
        int nex_cityno=Choose();
        path[moved_cnt]=nex_cityno;
        vis[nex_cityno]=true;
        length=length+dis[cur_cityno][nex_cityno];
        cur_cityno=nex_cityno;
        moved_cnt++;
    }
 
    //蚂蚁进行一次迭代
    void Search()
    {
        Init();
        while(moved_cnt<CITY_NUM)
        {
            Move();
        }
        //回到原来的城市
        length=length+dis[path[CITY_NUM-1]][path[0]];
    }
};
 
struct TSP
{
    Ant ants[ANT_NUM];//定义蚁群
    Ant ant_best;//最优路径蚂蚁
 
    void Init()
    {
        //初始化为最大值
        ant_best.length = inf;
        //计算两两城市间距离
        for (int i = 0; i < CITY_NUM; i++)
        {
            for (int j = 0; j < CITY_NUM; j++)
            {
                info[i][j]=1.0;
                double temp1=CityPos[j][0]-CityPos[i][0];
                double temp2=CityPos[j][1]-CityPos[i][1];
                dis[i][j] = sqrt(temp1*temp1+temp2*temp2);
            }
        }
    }
 
    //更新信息素
    void UpdateInfo()
    {
        double temp_info[CITY_NUM][CITY_NUM];
        memset(temp_info,0,sizeof(temp_info));
        int u,v;
        for(int i=0; i<ANT_NUM; i++) //遍历每一只蚂蚁
        {
            for(int j=1; j<CITY_NUM; j++)
            {
                u=ants[i].path[j-1];
                v=ants[i].path[j];
                temp_info[u][v]=temp_info[u][v]+Q/ants[i].length;
                temp_info[v][u]=temp_info[u][v];
            }
            //最后城市和开始城市之间的信息素
            u=ants[i].path[0];
            temp_info[u][v]=temp_info[u][v]+Q/ants[i].length;
            temp_info[v][u]=temp_info[u][v];
        }
        for(int i=0; i<CITY_NUM; i++)
        {
            for(int j=0; j<CITY_NUM; j++)
            {
                info[i][j]=info[i][j]*ROU+temp_info[i][j];
            }
        }
    }
    void Search()
    {
        //迭代TMAC次
        for(int i=0; i<TMAC; i++)
        {
            //所有蚂蚁都进行一次遍历
            for(int j=0; j<ANT_NUM; j++)
            {
                ants[j].Search();
            }
            //保存所有蚂蚁遍历的最佳结果
            for(int j=0; j<ANT_NUM; j++)
            {
                if(ant_best.length>ants[j].length)
                {
                    ant_best=ants[j];
                }
            }
            UpdateInfo();
            printf("第%d次迭代最优路径长度是%lf\n", i,ant_best.length);
            printf("\n");
        }
    }
};
int main()
{
    srand(seed);
    TSP tsp;
    tsp.Init();
    tsp.Search();
    printf("最短路径如下\n");
    for(int i=0;i<CITY_NUM;i++)
    {
        printf("%d",tsp.ant_best.path[i]);
        if(i<CITY_NUM-1)
            printf("->");
        else
            printf("\n");
    }
    return 0;
}

ACO算法在迭代构造解的过程之中应用到的信息包括以下两个方面:1) 算例的启发式信息(如路径问题中的距离);2) 反应蚂蚁路径搜索轨迹的信息素。

ACO中蚂蚁的行为细节


给定一个图网络 G=(C,L),其中 C表示图的组成成分(节点),L表示图的边。在执行ACO算法构造解的过程中,可以使用**“hard way”来构造的解,所有的解均不可以违反约束,也可以使用“soft way”**来构造解,某些解可以违反某些约束,但是这种解需要根据违反约束的程度来添加惩罚项(penalization)。

定义信息素 τ \tau τ若信息素和网络中的节点相关联, τij若信息素和网络中的边相关联;启发式信息 ηi若和节点相关联, ηij若和边相关联)。在ACO中,系统之中的每一个蚂蚁 k具有以下特点:

1)它通过探索网络 G=(C,L)来构造费用最小的解方案;

2)每一个蚂蚁k会有一个记录自己访问过路基的记忆 Mk,这个记忆信息可以用来继续构造可行解,来评判已经得到的解的优劣和更新信息素。

3)当蚂蚁 k k k在状态 xr=<xr−1,i>将要向节点 j ∈ N i k移动时 Nik表示蚂蚁 k在节点 i时的可行邻域),产生的新的状态 <xr,j>可以可行或者不可行。

4)每一个蚂蚁通过概率选择函数来选择移动方向,其中概率选择函数中包含的信息有:信息素,启发式信息,蚂蚁当前记忆信息和问题约束信息。

5)当终止条件满足时,终止蚂蚁的解方案构建。若不允许产生不可行解方案,则当构造不可行时,停止构造。

6)“步进信息素更新”(step-by-step pheromone update),表示每一次添加新的节点到某个蚂蚁的解之中,都需要对这个蚂蚁的信息素进行更新。

7)“在线延迟信息素更新”(online delayed pheromone update),表示在一个解方案构造完毕之后,在回溯整个解方案进行信息素的更新。

ACO构造解的过程


一个蚁群之中的蚂蚁并发地向网络 G G G中的邻域状态进行拓展来分别构造各自的路径,他们移动的方向收到概率选择函数的指导,通过不断的移动,每一个蚂蚁都向着构造组合优化问题的解方向靠近。一旦某个蚂蚁构造成功一个解方案,这个蚂蚁评估构造的解方案的优劣并进行信息素的更新。更新完毕的信息素又会通过概率选择函数指导后续蚂蚁的解方案构造过程。

信息素的消失和维持


信息素的消失(evaporation) 是将之前蚂蚁更新的信息素随着迭代次数的增加逐渐减小的过程。信息素的消失可以有效避免解太快收敛到一个局部最优解,同时可以帮助探索新的求解空间。

信息素维持(daemon) 可以帮助提高算法局部寻优的效果,在实际操作中,可以通过选择当前解方案最优的解,将当前最优解的信息素的更新占比加大,来提高最优解对于后续寻优的影响,这个过程也称为“离线信息素更新机制”off-line pheromone update。

ACO算法的改进方法


4.1 精英策略-elitist strategy

精英策略的思想在于基于当前最优解额外的信息素更新权重,在每一次信息素更新时,对于当前全局最优解中包含的弧给与额外的信息素权重,通过系数e来实现。应用了精英策略的上式(3)变为如下所示的形式:

image.png

其中 Lgb表示当前最优解的路径长度(成本)。

4.2 等级蚂蚁体系-rank-based version of Ant System( ASrank)

ASrank是精英策略的一种拓展策略,在ACO的所有解构造完成之后,将所有的解按照成本大小从小到大进行排序,值选择前 w−1个解方案和当前最优解方案进行信息素的更新。第 r个蚂蚁的解方案对于信息素更新的权重取值为:max{0, w−r},当前最优解对于信息素更新的权重取值为: w。在 ASrank下的上式(2)的表示形式如下所示:

image.png

其中image.png

4.3 信息素重置

当连续一定迭代次数没有对当前解进行优化,或者总迭代次数达到一定的次数时,可以将信息素重置为初始化水平,从而达到改变求解空间的效果。

4.4 ACO和LS结合

在进行ACO的过程之中可以嵌入LS算法来局部优化每一个蚂蚁找到的解方案,同时优化之后的解方案被用来进行信息素的更新操作。

4.5 候选列表-candidate lists

当求解问题的邻域空间较大时,蚁群之中的蚂蚁很可能不在同一个求解空间之中,使得ACO的求解效率大大降低。为了弥补这一缺陷,可以使用候选列表的方式。对于VRPTW问题,在实际操作中,对于每一个客户点i,其候选列表包含 cl个与之距离最近的客户点,在构建解方案的过程中,首先选择候选列表中的客户点进行解方案的构建,之后再从其余客户点中选择客户点进行解方案的构建。

ACO求解VRPTW代码已上传值GitHub

https://github.com/Dragon-wang-fei-long/Huristic-code/tree/Dragon-wang-fei-long-ACO


参考文章:蚁群算法(Ant Colony Optimization,ACO)讲解+代码实现_蚁群算法的实现-CSDN博客

​ 蚁群算法(ACO)原理梳理及应用细节 - 附求解VRPTW c++代码-阿里云开发者社区 (aliyun.com)


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

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

相关文章

脑网络相似性:方法与应用

摘要 图论方法已被证明是理解、表征和量化复杂大脑网络的有效工具。然而&#xff0c;定量比较两个图形的方法却较少受到关注。在一些网络神经科学应用中&#xff0c;比较大脑网络确实是必不可少的。在这里&#xff0c;本研究讨论了近年来用于比较大脑网络的技术现状、挑战以及…

Android常见界面控件(二)

目录 前言 一、 RadioButton控件 设置RadioGroup的监听事件 二、CheckBox控件 三、Toast类 改变Toast窗口的提示位置 前言 在上一篇中&#xff0c;我们讲解了三个常见的控件&#xff1a;TextView控件、Button控件、ImageView控件&#xff0c;那么本篇我们就接着讲剩下的…

Selenium实战:深度解析Python中嵌套Frame与iFrame的定位与切换技巧,解决Selenium定位不到的问题

在Web自动化测试中&#xff0c;处理网页中的Frame和iFrame是常见的挑战之一。这些元素在网页中扮演着承载独立HTML文档的角色&#xff0c;使得直接定位或操作其中的元素变得复杂。Python的Selenium库提供了强大的工具来应对这些挑战&#xff0c;本文将详细介绍如何使用Selenium…

SFP光模块、gt口、PMD、PMA、PCS之间的关系

ZYNQ内部的GT&#xff08;高速收发器&#xff09;接口包含了PCS&#xff08;物理编码子层&#xff09;与PMA&#xff08;物理介质接入层&#xff09;。这两个层在高速数据传输中起着至关重要的作用。 PCS层&#xff08;物理编码子层&#xff09; PCS层位于协调子层&#xff0…

Ubuntu虚拟机服务器的搭建

01.VMware安装 略。 02.Ubuntu虚拟机安装 略。 03.配置Ubuntu虚拟机网络 参考视频&#xff1a; Ubutu虚拟机网络配置&#xff08;桥接&#xff09;https://www.bilibili.com/video/BV1bG411V72A/?spm_id_from333.999.0.0&vd_sourced1fd4bcc46805ab35cc8bbb5a8bf318f…

win11如何查看串口的名字

1、右击win然后点击设备管理器 2、点击端口然后右击串口点击属性 3、进入窗口后点击Port information即可看见Port name属性就是串口名字

uniapp/vue如何实现一个子表单及子表单作用

子表单是一个辅助表单或一个表&#xff0c;它允许在主表单中添加多个行式项目&#xff0c;以处理与主记录相关联的多个辅助项目或数据。子表单在多种应用场景中发挥着重要作用&#xff0c;特别是在需要处理一对多关系的数据时。 以下是对子表单的详细解析&#xff1a; 定义与特…

苍穹外卖day10

苍穹外卖day10 Spring Task订单状态定时处理WebSocket应用&#xff08;弹幕&#xff0c;网页聊天&#xff0c;体育实况更新&#xff0c;股票基金实时更新&#xff09; 来单题型代码实现需求分析 客户催单 Spring Task 链接: 在线生成器 在线生成器 订单状态定时处理 每分钟检…

木舟0基础学习Java的第二十五天(JavaWeb)

XML 概念和体系 XML指可扩展标记语言&#xff08;EXtensible Markup Language&#xff09; XML没有预定义标签 需要自定义标签 <标签></标签> XML特点 XML数据以纯文本格式存储 实现不同应用程序之间的数据通信 实现不同平台的数据通信 实现不同平台的数据共…

Linux------Cortex-A架构的处理器运行模型与其寄存器组

寄存器组分为 外设寄存器组 比如&#xff1a;和总线相连的io寄存器&#xff0c;usart配置寄存器&#xff0c;spi配置寄存器等等 内核寄存器组&#xff1a;R0-R15 CPSR SPSR一共18个寄存器组&#xff0c;内核寄存器组用来记录当前程序地址状态&#xff0c;当前执行指令等&a…

8月来得及|1000/660/880题45天带刷计划!

刷题不在于多&#xff0c;而在于精 你选的这几本题集没有问题&#xff0c;660题专门训练客观题&#xff0c;880题和1000题都是不错的综合性题集&#xff0c;特别适合在强化阶段进行刷题训练&#xff0c;但是问题是你做这么多题&#xff0c;也不一定能起到多好的作用。 刷题的…

Linux | 进程概念详解:冯诺依曼体系结构、进程基本概念、PCB、进程组织、fork()创建子进程、进程运行逻辑

文章目录 进程概念1、冯诺依曼体系结构2、进程2.1基本概念2.2描述进程-PCB2.3组织进程2.4查看进程2.5通过系统调用获取进程标识符2.6通过系统调用创建进程-fork初识头文件与返回值fork函数的调用逻辑和底层逻辑 进程概念 1、冯诺依曼体系结构 目前我们认识的计算机中&#xff…

dm 到 dm 的 HS 同步部署

一、数据库部署 完成两节点数据库部署并初始化&#xff0c;配置参数如下&#xff1a; 节点 192.168.2.132 192.168.2.133 数据库版本 DM8 DM8 实例名 DM1 DM2 端口号 5236 5236 数据文件路径 /home/dmdba/dmdata /home/dmdba/dmdata 二、 dmhs 部署 1. 部署…

户外无线麦克风哪个牌子好,领夹麦克风十大品牌排行榜推荐

​为了在数字时代的浪潮中有效传达自己的思想和感情&#xff0c;选择合适的声音工具变得尤为重要。无线领夹麦克风就是这样一种工具&#xff0c;它能够帮助我们在任何环境下都保持最佳的语音传递效果。经过慎重考虑和市场调研&#xff0c;我为大家推荐几款性能卓越且价格合理的…

测试报告----功能测试

目录 一、项目背景 二、项目功能 &#xff08;1&#xff09;页面1&#xff1a;用户注册 &#xff08;2&#xff09;页面2&#xff1a;登陆页面 &#xff08;3&#xff09;页面3&#xff1a;信息主页 &#xff08;4&#xff09;页面4&#xff1a;详情页面 ​编辑&#xf…

获取当前路由器的外网IP(WAN IP)

GPT-4o (OpenAI) 获取当前路由器的外网IP&#xff08;WAN IP&#xff09;可以通过以下几种方法&#xff1a; 1. 访问路由器管理页面&#xff1a; - 通常路由器的管理页面可以通过在浏览器中输入路由器的IP地址来访问&#xff08;例如&#xff0c;192.168.0.1 或 192.168.1…

接口基础知识9:详解response body(响应体)

课程大纲 一、定义 HTTP响应体&#xff08;HTTP Response Body&#xff09;&#xff1a;服务器返回给客户端的数据部分&#xff0c;‌它包含了服务器对客户端请求的响应内容&#xff08;如客户端请求的资源、客户端请求的执行结果&#xff09;。 与请求类似&#xff0c;HTTP …

使用python实现3D聚类图

实验记录&#xff0c;在做XX得分预测的实验中&#xff0c;做了一个基于Python的3D聚类图&#xff0c;水平有限&#xff0c;仅供参考。 一、以实现三个类别聚类为例 代码&#xff1a; import pandas as pd import numpy as np from sklearn.decomposition import PCA from sk…

【Prometheus】监控系统

目录 一.Prometheus概述 1.Prometheus的认识与了解 2.Prometheus的特点 3.Prometheus存储引擎 TSDB 的特点优势 4.Prometheus 的生态组件 Prometheus server Client Library Exporters Service Discovery Alertmanager Pushgateway Grafana 5.Prometheus 的…

二叉树(四)

一、二叉树的性质 二、练习 1.某二叉树共有399个节点&#xff0c;其中有199个度为2的节点&#xff0c;则二叉树中的叶子节点数为&#xff08; &#xff09;。 A.不存在这样的树 B.200 C.198 D.199 答案&#xff1a;B 参考二叉树的性质第三条 2.在具有2…