多智能体协同控制(1)

news/2024/9/23 15:19:04

引言

多智能体系统协同控制算法起源于计算机领域关于分布式计算的研究,后由于数学家们的强势加盟,控制领域的研究一度占领高地。随着人工智能的发展,以多智能体强化学习为代表作的计算机领域专家又重回巅峰。

目前,每年多智能体相关的论文的都浩如烟海,成就了一批手持屠龙宝刀的研究生/教授,其中大部分苦于无龙可屠或宝刀生锈。

尽管如此,总有新人前仆后继,因此想把多智能体协同控制算法的基础知识整理一下,方便后学者入门,然后评估自己是否真心喜欢或适合。

是,则加倍努力学习更深层次的理论,以“将理论落地”为学习目标,切实地去影响物理世界。

否,则尽快在现有文献上小修小补,达到毕业要求后,做自己真正喜欢的内容。

参考文献:[1] Frank L. Lewis, Hongwei Zhang, et al. Cooperative Control of Multi-Agent Systems – Optimal and Adaptive Design Approaches[M]. 2014.(系列文章的主要内容翻译自这本书,后续不再特意说明)

[2] Wei Ren, Randal W. Beard. Distributed consensus in Multi-vehicle Cooperative Control[M]. 2008.

[3] Qu ZhiHua. Cooperative Control of Dynamical Systems: Applications to Autonomous Vehicles[M]. 2009.

Course: XP35CCM - Cooperative Control of Multi-agent systems - B162 (cvut.cz)​moodle.fel.cvut.cz/course/view.php?id=1495

适宜读者:需要研究相关内容的研究生、工程师。读者需熟悉高等数学、线性代数、现代控制理论及matlab的基础知识。

系列内容:①代数图论,连续/离散一阶(高阶)多智能体的一致性理论;②连续时间系统一致性算法的Riccati设计方法;③离散时间系统一致性算法的Riccati设计方法。

预期目标:阅读完系列文章后,读者应该①熟练掌握基本的多智能一致性算法,并能通过matlab进行仿真验证;②具备基本的文献阅读能力,愿意尝试推导Automatica 期刊上的相关论文,不至于发怵;③(工程师)能够将一致性算法应用到实际工程中,对理论算法进行实验验证。


需要说明,计算机领域的多智能体强化学习和控制领域的多智能体协同/一致性差异是很大的,这个系列主要是从控制领域进行叙述。

自麦克斯韦的《论调速器》开始,控制理论从只能处理单输入单输出(Single Input Single Output,SISO)系统,发展成熟为可以应对复杂的多输入多输出(Multiple Input Multiple Output,MIMO)系统。

典型的单输入单输出(SISO)系统:个体烧热水(温度控制系统),输入为“加热”,输出为“水温”。

典型的多输入多输出(MIMO)系统:群体烧热水(北方的集中供暖),输入为“加热+水泵”,输出为“水温+水流速度”。

烧热水是个技术活。对于简单的温控系统(SISO),整个系统只有一个单片机(控制器),一个“热得快”(执行器)。

而北方的集中供暖由于地理范围很大,可以根据不同的区域进行分区,每个片区都可以看做是一个简单的执行器。另外有一个控制中心,所有的信息都采集并上传至控制中心,控制中心经过计算,下发控制命令到每一个执行器,从而实现预期控制功能:烧热水。

这两种烧热水方式只是规模大小不同,本质都可以看做是集中式控制:仅有一个控制中心,有一个或多个执行器。

当系统的规模比较小时,集中式控制方案是一种高效的解决方式。

随着系统规模的增大,集中式方案将捉襟见肘。例如需要一台计算机控制整个东北三省所有的供暖设施时,得找计算能力多强大的计算机才能实时地完成这个任务?

事实上,每个片区不愿意只当木头人(执行器),也想有灵魂(控制器)。于是可采取分而治之方法,每个片区都安装一个单片机控制的供暖设施(赋予灵魂)。这种控制方法,可称为分散式控制。

集中式控制方案的缺点在于:①需要强大的控制中心;②成本(时间成本和经济成本)随着系统规模的线性增加而指数型增加;③当控制中心出问题时,所有人都得挨冻。

分散式控制方案的优点在于:①常规商用的控制器即可实现控制目标;②通过增加分区,随着系统规模的线性增加,成本也是线性增加;③当某个片区的控制中心出现问题时,只有那个片区的人挨冻,其余片区的人不受影响。

分散式控制方案的缺点在于:①个体抗风险能力差,每个片区各自为政,出现紧急情况时,无法集中力量办大事:例如某片区遭受严重的冰雪灾害,供暖系统遭到破坏,无法调动其他片区的暖气来供暖 ;②无法实现资源的优化配置,两个相邻的片区,一个电价高且自己能够生产的暖气不足,另一个电价低且生产的暖气过剩,导致片区整体舒适度较低。

集中式控制方案可以把整个系统看做一个人,有一个控制中心:大脑,多个传感器:五官和皮肤,多个执行器:四肢、铁头功、LOL酒桶的肚子。

分散式控制方案则把整个系统划分成人群,每个人都有自己的控制器和执行器,彼此之间不沟通。

在分散式控制的基础上,如果能够消除相邻片区的隔阂,互通有无,则显然能够提高整体的舒适度。倘若暖气能从某一个片区出发,总能通过各种路径,流过所有片区,则把这种方法称为分布式控制方案。

分布式控制方案兼具集中式和分散式方案的优点,又克服了它们的缺点。因而研究分布式控制方案具有较大的理论价值与实际应用价值。

根据上述分析,“烧热水”问题主要有三种控制方案:

①集中式控制:有一个控制中心,与每一个片区相连,控制所有的片区供暖设施;

②分散式控制:没有控制中心,每个片区相互独立,各玩各的;

③分布式控制:没有控制中心,相邻片区供水管道相连,且至少能找到一股热水从一个片区出发,流经整个东三省。

学术上,我们通常用 “智能体(agent)”来替换前述片区/人,集中式控制只有一个智能体。分散式控制和分布式控制均有多个agent,前者的agent互不来往,后者的agent邻里关系密切。

本系列文章主要研究多个agent的分布式控制:多智能体协同控制。

前面讲了一大串,讲到了分布式控制,但又只是文字上的扯淡,啥也不是。

如果停留在语言描述上,容易成为文学。要把它称为科学,要求我们用数学的方式去描述分布式控制,设计相应的控制律,实现我们的控制目标。

目前公认的比较早的关于多智能体系统的综述性文章是Reza Olfati-Saber在2007年撰写的文章《Consensus and Cooperation in Networked Multi-Agent Systems》(基于2003年~2007年间的文章)。在此之后,多智能体算法开始蓬勃发展。


撇开复杂的论文,我们先来看两个简单例子,理解一下分布式一致性算法。

例1、分蛋糕问题(集中式)。小多、小智、小能、小体四个人合买了一块20斤大蛋糕。小智作为智商担当负责分蛋糕,鸡贼的他切的蛋糕有的多有的少,自己拿了8斤,给女朋友小体6斤,分了小能4斤,小多拿的最少,只有2斤。小多和小能肯定不愿意,花同样的钱,出同样的力,凭什么自己分到的蛋糕少了?于是他们要求平均分。请问应该怎么分?

这问题也太简单了,一共20斤,4个人,一人称5斤不就完事了。但要注意,这是一种集中式控制方案。我们需要知道:①蛋糕总数是20斤;②一共有4个人。然后每个人的分的蛋糕=20/4=5斤。

例2、分蛋糕问题(分布式)。小多、小智、小能、小体四个人合买了一块蛋糕,老板给的时候随意切了几下。各自回家后,小多发现自己只有2斤,小智有8斤,小能有4斤,小体有6斤。现在的情况是:①他们都不知道大蛋糕一共有几斤;②他们都是交了相同的钱,但是不知道一共有几个人合买;③他们都只和自己的邻居交流,交流方式如下图,且已经发现彼此数量不一样,小多很生气。问:如何在现有的交流方式下,实现蛋糕的平均分配?

显然,由于不知道蛋糕总量和总人数,无法用简单的除法得到每个应该分配的蛋糕数。对于每个agent,已知条件是:自己和邻居的蛋糕数量。有没有一种算法能够在这样的情况下,实现蛋糕均分呢?

我们可以这样做:①每隔一段时间T,让每个agent都把自己的蛋糕量和邻居的蛋糕数相加,求平均值。②如果平均值小于自己当前蛋糕量,则将多余的量放到公共平台上,让其他agent去取;如果平均值大于当前蛋糕量,则从公共平台上去取其他agent放上去的蛋糕。

不断重复①②步骤,直到每个agent的蛋糕量不再变化,则每个agent此时的蛋糕应该就是总量的平均值。

我们用数据来看一下上述迭代过程:

简单起见,我们在Excel中进行迭代过程。初始值记为第0步,根据前述Agent之间的交流方式可知,每个Agent下一步的值,都是上一步自身值与邻居值的平均值。完成第1步的公式输入后,直接往下拉,生成15步迭代。

从图中可以看出,经过几次迭代后,每个人手里的蛋糕已经接近平均值5斤了。

可见,通过这种分布式的分蛋糕方式,也能实现我们平均分配蛋糕的目的。并且注意到,每个Agent都不知道系统的整体信息,我们其实是在用“局部信息”获取“整体信息”。

也可以在matlab中,进行编程。

clear;clc
N = 15;
t=1:N;
X1 = zeros(4,N);
X1(1,1) = 2;
X1(2,1) = 8;
X1(3,1) = 4;
X1(4,1) = 6;for k = 2:N
X1(1,k) = (X1(1,k-1)+X1(2,k-1)+X1(4,k-1))/3;
X1(2,k) = (X1(1,k-1)+X1(2,k-1)+X1(3,k-1))/3;
X1(3,k) = (X1(2,k-1)+X1(3,k-1)+X1(4,k-1))/3;
X1(4,k) = (X1(3,k-1)+X1(4,k-1)+X1(1,k-1))/3;
endplot(t,X1(1,:),t,X1(2,:),t,X1(3,:),t,X1(4,:))

迭代过程如下图所示。


我们再来看一个多智能体协同(这里指集聚现象,flocking)的例子。

看动物世界的时候,我们观察到这些小可爱们能够神奇的聚集在一起,向某个特定的方向前进,彼此之间还不碰撞。这就启发学者提出了三条规则:①保持距离:避免邻居之间的冲突;②保持联系:避免邻居之间过于疏远;③同心同德:所有人步调一致,向一个目标进发。

简单起见,这里只考虑前两条规则。看看我们如何把“世界观:保持距离、保持联系”变成“方法论:代码”。

例3、若即若离问题。小多、小智、小能和小体四个人,一起从家里出发去学校。他们的家庭地址虽然不同,但是都要走同一条路,因此相约结伴而行。一方面他们是好朋友,一旦彼此之间的距离太远了,比如超过10米了,就要相互靠近;另一方面每个人都有自己的舒适圈,一旦彼此之间的距离太近了,比如小于0.5米了,就要相互散开一点。已知4个人的家庭地址(二维坐标)、舒适圈(0.5米)、吸引圈(10米),问:如何设计分布式控制策略,使他们最终能够保持所有人都舒适的距离一起上学?并用图形展示。

我们可以这样做:每隔一段时间T,让每个人都以10米为半径,看看里面有没有邻居。如果有邻居,判断一下他们有没有越界(距离小于0.5米),离越界的朋友远一点(离开的方向为直线后退,后退的长度为两个人之间的距离乘以系数c),离疏远的朋友近一点(接近的方向为直线靠近,靠近的长度为两个之间的距离乘以系数d)。

不断重复这个过程,直到每个人之间的距离在保持一定的范围内,则四个人都在比较舒适的距离上了。

从上图中可以看出,经过一段时间的迭代后,四个人的位置处于一个比较舒适的距离上了:大于0.5,且在0.5附近。d12代表agent 1(小多)与agent 2(小智)之间的距离。

分蛋糕问题是一个典型的分布式一致性算法的例子,在控制领域中,通常可用于无线传感器网络状态估计等例子.

若即若离问题是一个典型的分布式协同算法的例子,在控制领域中,通常可用于无人机编队、机器人编队等问题。


我们再来回看一下分蛋糕问题。如果四个人之间的交流方式变成单向的,还能实现平均分配么?

答案是:可以。

那如果交流方式改成链式的呢?还能收敛到平均值么

答案是:四个人的蛋糕量会收敛到相同值,但是不是平均值。

可见,分布式一致性算法的实现与多智能体之间的交流方式密切相关。


前面的例子中,我们从文字描述出发,进行了代码编程,并实现控制目标,从文学向科学跨进了一步,但是这还不够。我们给出的策略还是不够数学,不够严谨。

从下篇教程开始,将会开始涉及大量的数学概念,从而把多智能体一致性算法建立在严密的数学推导之上。

若即若离问题详细代码:

%%
close all
clear;clc;
N = 500;    %迭代步数
t = 1:N;
X1 = zeros(4,2,N);
D = 5;
X1(1,:,1) = ceil(rand(1,2)*10);   % 产生随机位置
X1(2,:,1) = ceil(rand(1,2)*10);
X1(3,:,1) = floor(rand(1,2)*10);
X1(4,:,1) = floor(rand(1,2)*10);% X1(1,:,1) =  [1 5];  % 给定固定位置
% X1(2,:,1) = [2 6];
% X1(3,:,1) = [4 1];
% X1(4,:,1) = [6 3];d_reject = 0.5; % 舒适圈
d_connect = 10; % 吸引圈k_connect = 0.01;   % 吸引系数
k_reject = 0.03;    % 排斥系数d11 = zeros(1,N);   % agent之间的距离, ① d12 = d21; ② 也可以写出大矩阵形式,节省代码行数。
d12 = zeros(1,N);
d13 = zeros(1,N);
d14 = zeros(1,N);d21 = zeros(1,N);
d22 = zeros(1,N);
d23 = zeros(1,N);
d24 = zeros(1,N);d31 = zeros(1,N);
d32 = zeros(1,N);
d33 = zeros(1,N);
d34 = zeros(1,N);d41 = zeros(1,N);
d42 = zeros(1,N);
d43 = zeros(1,N);
d44 = zeros(1,N);for k = 2:N  % 开始迭代% 首先计算出 彼此之间的距离  写代码 是从上帝视角来看的,所以有全局信息,% 但是对于每一个agent来说,他只有邻居的信息。d11(k) = 0;d12(k) = sqrt( (X1(1,1,k-1) - X1(2,1,k-1))^2 + (X1(1,2,k-1) - X1(2,2,k-1))^2 );d13(k) = sqrt( (X1(1,1,k-1) - X1(3,1,k-1))^2 + (X1(1,2,k-1) - X1(3,2,k-1))^2 );d14(k) = sqrt( (X1(1,1,k-1) - X1(4,1,k-1))^2 + (X1(1,2,k-1) - X1(4,2,k-1))^2 );d21(k) = d12(k);d22(k) = 0;d23(k) = sqrt( (X1(2,1,k-1) - X1(3,1,k-1))^2 + (X1(2,2,k-1) - X1(3,2,k-1))^2 );d24(k) = sqrt( (X1(2,1,k-1) - X1(4,1,k-1))^2 + (X1(2,2,k-1) - X1(4,2,k-1))^2 );d31(k) = d13(k);d32(k) = d23(k);d33(k) = 0;d34(k) = sqrt( (X1(3,1,k-1) - X1(4,1,k-1))^2 + (X1(3,2,k-1) - X1(4,2,k-1))^2 );d41(k) = d14(k);d42(k) = d24(k);d43(k) = d34(k);d44(k) = 0;% 第1个agentX1(1,:,k) = X1(1,:,k-1);neighbor1_reject = find( [d11(k) d12(k) d13(k) d14(k)] <= d_reject );   % 找到越界邻居num_reject = length(neighbor1_reject); % 越界邻居的数目if num_reject >1   % 与自己的距离肯定小于0,但是不属于越界for m = 1 : num_reject% 注意 “-”代表的后退X1(1,:,k) = X1(1,:,k) - k_reject * ( X1(neighbor1_reject(m),:,k-1) - X1(1,:,k-1));endend% 找到各自的未越界的邻居neighbor1_connect = find( ([d11(k) d12(k) d13(k) d14(k)] <= d_connect) & ([d11(k) d12(k) d13(k) d14(k)] > d_reject) );num_connect = length(neighbor1_connect);if num_connect >0for m = 1 : num_connect% 注意“+”代表的靠近X1(1,:,k) = X1(1,:,k) + k_connect * ( X1(neighbor1_connect(m),:,k-1) - X1(1,:,k-1));endend% 第2个agentX1(2,:,k) = X1(2,:,k-1);neighbor2_reject = find( [d21(k) d22(k) d23(k) d24(k)] <= d_reject );num_reject = length(neighbor2_reject); if num_reject >1   for m = 1 : num_rejectX1(2,:,k) = X1(2,:,k) - k_reject * ( X1(neighbor2_reject(m),:,k-1) - X1(2,:,k-1));endendneighbor2_connect = find( ([d21(k) d22(k) d23(k) d24(k)] <= d_connect) & ([d21(k) d22(k) d23(k) d24(k)] > d_reject) );num_connect = length(neighbor2_connect);if num_connect >0for m = 1 : num_connectX1(2,:,k) = X1(2,:,k) + k_connect * ( X1(neighbor2_connect(m),:,k-1) - X1(2,:,k-1));endend% 第3个agentX1(3,:,k) = X1(3,:,k-1);neighbor3_reject = find( [d31(k) d32(k) d33(k) d34(k)] <= d_reject );num_reject = length(neighbor3_reject); if num_reject >1   for m = 1 : num_rejectX1(3,:,k) = X1(3,:,k) - k_reject * ( X1(neighbor3_reject(m),:,k-1) - X1(3,:,k-1));endend% 找到各自的邻居neighbor3_connect = find( ([d31(k) d32(k) d33(k) d34(k)]  <= d_connect) & ([d31(k) d32(k) d33(k) d34(k)]  > d_reject) );num_connect = length(neighbor3_connect);if num_connect >0for m = 1 : num_connectX1(3,:,k) = X1(3,:,k) + k_connect * ( X1(neighbor3_connect(m),:,k-1) - X1(3,:,k-1));endend% 第4个agentX1(4,:,k) = X1(4,:,k-1);neighbor4_reject = find( [d41(k) d42(k) d43(k) d44(k)] <= d_reject );num_reject = length(neighbor4_reject); if num_reject >1   for m = 1 : num_rejectX1(4,:,k) = X1(4,:,k) - k_reject * ( X1(neighbor4_reject(m),:,k-1) - X1(4,:,k-1));endend% 找到各自的邻居neighbor4_connect = find( ([d41(k) d42(k) d43(k) d44(k)] <= d_connect) & ([d41(k) d42(k) d43(k) d44(k)] > d_reject) );num_connect = length(neighbor4_connect);if num_connect >0for m = 1 : num_connectX1(4,:,k) = X1(4,:,k) + k_connect * ( X1(neighbor4_connect(m),:,k-1) - X1(4,:,k-1));endendend%%
figure
hf = gcf;
hf.Color= [1 1 1]; % 控制图形的整体颜色。(scope中被默认为灰黑色,此处修改为白色)
hp1 = plot3(t,reshape(X1(1,1,:),1,N),reshape(X1(1,2,:),1,N));   % 新建第一条曲线句柄
hp1.Color =  'g';    % 设置曲线颜色
hp1.LineStyle =  '-';     %  -    --   -.  :   设置曲线线型
hp1.LineWidth =  2;   % 设置曲线 线宽hold on
hp1 = plot3(t,reshape(X1(2,1,:),1,N),reshape(X1(2,2,:),1,N));   % 新建第一条曲线句柄
hp1.Color =  'b';    % 设置曲线颜色
hp1.LineStyle =  '-';     %  -    --   -.  :   设置曲线线型
hp1.LineWidth =  2;   % 设置曲线 线宽hold on
hp1 = plot3(t,reshape(X1(3,1,:),1,N),reshape(X1(3,2,:),1,N));   % 新建第一条曲线句柄
hp1.Color =  'c';    % 设置曲线颜色
hp1.LineStyle =  '-';     %  -    --   -.  :   设置曲线线型
hp1.LineWidth =  2;   % 设置曲线 线宽hold on
hp1 = plot3(t,reshape(X1(4,1,:),1,N),reshape(X1(4,2,:),1,N));   % 新建第一条曲线句柄
hp1.Color =  'm';    % 设置曲线颜色
hp1.LineStyle =  '-';     %  -    --   -.  :   设置曲线线型
hp1.LineWidth =  2;   % 设置曲线 线宽ht = title('');          % 获取当前标题句柄
ht.Interpreter =  'tex'; % 解释器。若没有公式,默认即可。 若有公式,可设置为 'latex'。
ht.String =  '保持距离、保持联系';       % 标题内容。若解释器设置为'latex',则可输入公式,如 '$A_{i}^{2}$'
ht.Color =  [0 0 0];     % 标题颜色
ht.FontName =  'Helvetica'; % 字体
ht.FontSize =  12;         % 字体大小
ht.FontWeight =  'bold';   % 字体宽度
ha = gca;                 % 获取当前图形的坐标轴句柄
ha.LineWidth =  1.000;    % 设置 坐标轴线宽
ha.FontWeight = 'bold';   % 设置字体的宽度, bold (粗体)或 normal(正常)
ha.GridLineStyle = '--';
ha.FontSize =  12;        % 字体大小
ha.XMinorGrid = 'off';     % 这里设置的是 细的网格,也可以设置粗网格:ha.XGrid = 'on';
ha.YMinorGrid = 'off';
ha.XGrid = 'on';     % 这里设置的是 细的网格,也可以设置粗网格:ha.XGrid = 'on';
ha.YGrid = 'on';
ha.Box = 'off';           % 取消 框线 ,  有些论文要求不要框hXL = xlabel('t');        % 获取横坐标句柄
% hXL.Interpreter =  'latex';  % 同title;
hXL.Interpreter =  'tex';  % 同title;
hXL.String =  '迭代步数';
hXL.Color =  [0 0 0];
hXL.FontName =  'Helvetica';
hXL.FontSize =  12;
hXL.FontWeight =  'bold';hYL = ylabel('y');
% hYL.Interpreter =  'latex';
hYL.Interpreter =  'tex';
hYL.String =  '横坐标分量';
hYL.Color =  [0 0 0];
hYL.FontName =  'Helvetica';
hYL.FontSize =  12;
hYL.FontWeight =  'bold';
hYL.Rotation = 0;hYL = zlabel('y');
% hYL.Interpreter =  'latex';
hYL.Interpreter =  'tex';
hYL.String =  '纵坐标分量';
hYL.Color =  [0 0 0];
hYL.FontName =  'Helvetica';
hYL.FontSize =  12;
hYL.FontWeight =  'bold';
hYL.Rotation = 90;legend('小多','小智','小能','小体')%% 
figurehf = gcf;
hf.Color= [1 1 1]; % 控制图形的整体颜色。(scope中被默认为灰黑色,此处修改为白色)
hp1 = plot(t(2:end),d12(2:end));  % 新建第一条曲线句柄
hp1.Color =  'g';    % 设置曲线颜色
hp1.LineStyle =  '-';     %  -    --   -.  :   设置曲线线型
hp1.LineWidth =  2;   % 设置曲线 线宽hold on
hp1 = plot(t(2:end),d13(2:end));  % 新建第一条曲线句柄
hp1.Color =  'b';    % 设置曲线颜色
hp1.LineStyle =  '-';     %  -    --   -.  :   设置曲线线型
hp1.LineWidth =  2;   % 设置曲线 线宽hold on
hp1 = plot(t(2:end),d14(2:end));  % 新建第一条曲线句柄
hp1.Color =  'c';    % 设置曲线颜色
hp1.LineStyle =  '-';     %  -    --   -.  :   设置曲线线型
hp1.LineWidth =  2;   % 设置曲线 线宽hold on
hp1 = plot(t(2:end),d23(2:end));  % 新建第一条曲线句柄
hp1.Color =  'm';    % 设置曲线颜色
hp1.LineStyle =  '-';     %  -    --   -.  :   设置曲线线型
hp1.LineWidth =  2;   % 设置曲线 线宽hold on
hp1 = plot(t(2:end),d24(2:end));  % 新建第一条曲线句柄
hp1.Color =  'y';    % 设置曲线颜色
hp1.LineStyle =  '-';     %  -    --   -.  :   设置曲线线型
hp1.LineWidth =  2;   % 设置曲线 线宽hold on
hp1 = plot(t(2:end),d34(2:end));  % 新建第一条曲线句柄
hp1.Color =  'k';    % 设置曲线颜色
hp1.LineStyle =  '-';     %  -    --   -.  :   设置曲线线型
hp1.LineWidth =  2;   % 设置曲线 线宽ht = title('');          % 获取当前标题句柄
ht.Interpreter =  'tex'; % 解释器。若没有公式,默认即可。 若有公式,可设置为 'latex'。
ht.String =  'Agent 之间的距离';       % 标题内容。若解释器设置为'latex',则可输入公式,如 '$A_{i}^{2}$'
ht.Color =  [0 0 0];     % 标题颜色
ht.FontName =  'Helvetica'; % 字体
ht.FontSize =  12;         % 字体大小
ht.FontWeight =  'bold';   % 字体宽度
ha = gca;                 % 获取当前图形的坐标轴句柄
ha.LineWidth =  1.000;    % 设置 坐标轴线宽
ha.FontWeight = 'bold';   % 设置字体的宽度, bold (粗体)或 normal(正常)
ha.GridLineStyle = '--';
ha.FontSize =  12;        % 字体大小
ha.XMinorGrid = 'off';     % 这里设置的是 细的网格,也可以设置粗网格:ha.XGrid = 'on';
ha.YMinorGrid = 'off';
ha.XGrid = 'on';     % 这里设置的是 细的网格,也可以设置粗网格:ha.XGrid = 'on';
ha.YGrid = 'on';
ha.Box = 'off';           % 取消 框线 ,  有些论文要求不要框hXL = xlabel('t');        % 获取横坐标句柄
% hXL.Interpreter =  'latex';  % 同title;
hXL.Interpreter =  'tex';  % 同title;
hXL.String =  '迭代步数';
hXL.Color =  [0 0 0];
hXL.FontName =  'Helvetica';
hXL.FontSize =  12;
hXL.FontWeight =  'bold';hYL = ylabel('y');
% hYL.Interpreter =  'latex';
hYL.Interpreter =  'tex';
hYL.String =  '距离';
hYL.Color =  [0 0 0];
hYL.FontName =  'Helvetica';
hYL.FontSize =  12;
hYL.FontWeight =  'bold';
hYL.Rotation = 0;legend('d12','d13','d14','d23','d24','d34')

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

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

相关文章

Axure原型设计:多层级动态表格

多层级表格又成为树形表格,是在后台常用的一种表格形式,当表格数据存在多层级关系是,可以通过多层级表格,从而更加清晰的呈现数据内容,帮助人们更好地理解和分析数据之间的关系,从而更加有效地传递信息。 所以今天作者就教大家怎么在Axure里制作多层级动态表格,包括展开…

frp内网穿透 宝塔部署服务端、客户端教程

宝塔部署教程链接:https://blog.csdn.net/m0_57944649/article/details/140693257 frp官方下载链接:https://github.com/fatedier/frp/releases一、部署服务端1、上传好文件后解压2、进入解压好了的文件夹“frp_0.58.1_linux_amd64”中,找到文件“frps.toml”,双击打开: …

建立数据库连接时出现错误:原因与解决方案

建立数据库连接时出现错误的原因可能有很多,以下是一些常见的原因及其解决方案: 原因登录信息错误:账号、密码、服务器名称或数据库名称不正确。网络问题:客户端与数据库服务器之间的网络连接不稳定或中断。数据库服务未启动:数据库服务没有运行,或者在尝试连接时服务停止…

数据库连接失败的解决方法有哪些

当遇到数据库连接失败的情况时,可以按照以下步骤进行排查和解决:检查数据库服务状态:确认数据库服务是否已启动并运行正常。可以使用阿里云控制台的服务监控工具或通过SSH登录服务器,使用命令行工具(如service mysqld status)来检查服务状态。验证网络连接:确保你的应用…

数据库常见十大错误_数据库十大报错语句

数据库操作时可能会遇到各种错误,这些错误通常是由不同的原因引起的,比如语法错误、连接问题、权限问题等。下面是数据库操作中常见的几种错误类型及其解决思路:连接失败:错误信息可能包括“无法连接到主机”、“连接被拒绝”等。检查数据库服务是否启动、网络连接是否正常…

阿里云主机数据库链接失败怎么回事

阿里云主机数据库连接失败的问题可能有多种原因,这里列举了一些常见的原因及解决办法:网络问题:确认你的网络连接是否正常。尝试使用其他设备或网络连接来验证问题是否出在网络方面。防火墙设置:确保防火墙没有阻止数据库连接。可以尝试临时禁用防火墙,或添加相应的规则来…

收藏:加不加「/」?Nginx location 路径与 proxy_pass 的规律

从一张梗图开始 起源于在 TG 某个频道看到的一张图:图下面的评价是:Nginx is so hard! 实际上这张图描述的是 nginx location 的路径配置,及 location 代码块中 proxy_pass 的路径关系,属于 nginx 应用中路径转发的知识。例如图中 Case 1 对应的代码块应该为:location /te…