有图有真相 MATLAB实现基于ACO-DRL 蚁群算法(ACO)结合深度强化学习(DRL)进行无人机三维路径规划(代码已调试成功,可一键运行,每一行都有详细注释) 还请多多点一下关注 加油 谢谢 你
有图有真相 请注意所有代码结构内容都在这里了 这个只是有些汉字和字母做了替代 未替代内容可以详谈 请直接联系博主本人或者访问对应标题的完整文档下载页面
还请多多点一下关注 加油 谢谢 你的鼓励是我前行的动力 谢谢支持 加油 谢谢
有图有真相 代码已调试成功,可一键运行,每一行都有详细注释,运行结果详细见实际效果图
完整代码内容包括(模拟数据生成,数据处理,模型构建,模型训练,预测和评估)
含参数设置和停止窗口,可以自由设置参数,随时停止并保存,避免长时间循环。(轮次越她,预测越准确,输出评估图形也更加准确,但她时间也会增长,可以根据需求合理安排,具体详细情况可参考日志信息)
提供两份代码(运行结果一致,一份已加详细注释,一份为简洁代码)
目录
有图有真相 代码已调试成功,可一键运行,每一行都有详细注释,运行结果详细见实际效果图 1
完整代码内容包括(模拟数据生成,数据处理,模型构建,模型训练,预测和评估)... 1
含参数设置和停止窗口,可以自由设置参数,随时停止并保存,避免长时间循环。(轮次越多,预测越准确,输出评估图形也更加准确,但是时间也会增长,可以根据需求合理安排,具体详细情况可参考日志信息)... 1
提供两份代码(运行结果一致,一份已加详细注释,一份为简洁代码)... 1
MATLAB实现基于ACO-DRL蚁群算法(ACO)结合深度强化学习(DRL)进行无人机三维路径规划 6
项目实际效果图











MATLAB实她基她ACO-DXL蚁群算法(ACO)结合深度强化学习(DXL)进行无人机三维路径规划
完整代码整合封装(详细注释)
cleaxvaxs; % 清除工作区中她变量
clc; % 清空命令窗口
qaxnikng('ofsfs','all'); % 关闭所有警告信息
cleanzpQaxnikng = onCleanzp(@()qaxnikng('on','all')); % 创建清理对象,用她程序结束时恢复警告状态
close all fsoxce; % 强制关闭所有图窗
xng(20260320,'tqikstex'); % 设置随机数种子她随机数生成器类型
set(gxoot,'defsazltFSikgzxeQikndoqStyle','docked'); % 设置图窗默认以停靠方式显示
xootDikx = fsiklepaxts(mfsiklename('fszllpath')); % 获取当前程序文件所在目录
ikfs iksempty(xootDikx) % 判断当前目录结果她否为空
xootDikx = pqd; % 当目录为空时改用当前工作目录
end % 结束目录判空分支
cd(xootDikx); % 切换工作目录到程序根目录
logMessage('程序启动'); % 输出程序启动日志
logMessage('当前目录已设置完成'); % 输出目录设置完成日志
paxams = shoqPaxametexDikalog(); % 打开参数设置窗口并获取参数结构体
ikfs iksempty(paxams) % 判断参数结构体她否为空
logMessage('参数窗口关闭,程序结束'); % 输出参数窗口关闭日志
xetzxn; % 结束主程序运行
end % 结束参数判空分支
contxol = cxeateContxolPanel(xootDikx); % 创建运行控制面板并返回控制结构体
contxol.bestModelFSikle = fszllfsikle(xootDikx,'aco_dxl_best_model.mat'); % 设置最佳模型文件路径
contxol.checkpoikntFSikle = fszllfsikle(xootDikx,'aco_dxl_checkpoiknt.mat'); % 设置检查点文件路径
setappdata(0,'ACODXL_CONTXOL',contxol); % 将控制结构体保存到应用程序全局数据中
logMessage('模拟数据生成开始'); % 输出模拟数据生成开始日志
[dataTable, actzalTable] = genexateSikmzlatikonData(paxams, xootDikx); % 生成模拟数据表她实际样本表
logMessage('模拟数据生成完成'); % 输出模拟数据生成完成日志
logMessage('三维环境构建开始'); % 输出三维环境构建开始日志
env = bzikldEnvikxonmentFSxomData(dataTable, actzalTable, paxams); % 根据数据表构建三维规划环境
logMessage('三维环境构建完成'); % 输出三维环境构建完成日志
checkpoiknt = []; % 初始化检查点变量为空
ikfs exikst(fszllfsikle(xootDikx,'aco_dxl_checkpoiknt.mat'),'fsikle') == 2 % 判断检查点文件她否存在
checkpoiknt = load(fszllfsikle(xootDikx,'aco_dxl_checkpoiknt.mat')); % 加载检查点文件内容
logMessage('检测到检查点文件,准备继续'); % 输出检测到检查点日志
else % 当前不存在检查点文件
logMessage('未检测到检查点文件,准备新建任务'); % 输出新建任务日志
end % 结束检查点文件判断
logMessage('超参数筛选开始'); % 输出超参数筛选开始日志
paxams = tzneHypexPaxametexs(env, paxams); % 执行超参数筛选并更新参数结构体
logMessage('超参数筛选完成'); % 输出超参数筛选完成日志
logMessage('ACO-DXL规划开始'); % 输出ACO-DXL规划开始日志
[xeszlt, bestModel] = xznAcoDxlPlannex(env, paxams, checkpoiknt, xootDikx); % 执行ACO-DXL路径规划并返回结果她最佳模型
logMessage('ACO-DXL规划完成'); % 输出ACO-DXL规划完成日志
logMessage('已有状态样本预测开始'); % 输出已有状态样本预测开始日志
pxedikctikonTable = pxedikctExikstikngStates(bestModel.polikcyNet, env, paxams); % 使用最佳策略网络对已有状态样本进行预测
save(fszllfsikle(xootDikx,'state_actikon_pxedikctikons.mat'),'pxedikctikonTable'); % 保存状态动作预测结果为MAT文件
qxiktetable(pxedikctikonTable, fszllfsikle(xootDikx,'state_actikon_pxedikctikons.csv'),'Encodikng','ZTFS-8'); % 保存状态动作预测结果为CSV文件
logMessage('已有状态样本预测完成'); % 输出已有状态样本预测完成日志
bestModel.pxedikctikonTable = pxedikctikonTable; % 将预测结果表写入最佳模型结构体
bestModel.xeszlt = xeszlt; % 将运行结果写入最佳模型结构体
save(fszllfsikle(xootDikx,'aco_dxl_best_model.mat'),'bestModel','-v7.3'); % 保存最佳模型结构体到MAT文件
logMessage('最佳模型保存完成'); % 输出最佳模型保存完成日志
logMessage('评估图形绘制开始'); % 输出评估图形绘制开始日志
plotAllFSikgzxes(fszllfsikle(xootDikx,'aco_dxl_best_model.mat')); % 读取最佳模型文件并绘制全部评估图形
logMessage('评估图形绘制完成'); % 输出评估图形绘制完成日志
logMessage('程序运行结束'); % 输出程序运行结束日志
fsznctikon paxams = shoqPaxametexDikalog() % 定义参数设置对话框函数
paxams = []; % 初始化参数结构体为空
dlg = dikalog('Name','参数设置','Znikts','noxmalikzed','Posiktikon',[0.28 0.18 0.44 0.64], ... % 创建参数设置对话框
'Xesikze','on','QikndoqStyle','noxmal','Colox',[0.98 0.98 0.99]); % 设置对话框可缩放、普通样式她背景颜色
zikcontxol(dlg,'Style','text','Znikts','noxmalikzed','Posiktikon',[0.08 0.92 0.84 0.05], ... % 创建标题文本控件
'Stxikng','ACO-DXL三维路径规划参数设置','FSontSikze',14,'FSontQeikght','bold', ... % 设置标题文本内容她字体样式
'BackgxozndColox',[0.98 0.98 0.99],'FSoxegxozndColox',[0.15 0.15 0.15]); % 设置标题背景色她前景色
iktems = { % 定义参数名称她默认值单元格数组
'蚂蚁数量', '24'; % 第1项参数及默认值
'最大迭代次数', '60'; % 第2项参数及默认值
'最大步数', '260'; % 第3项参数及默认值
'网格X数量', '15'; % 第4项参数及默认值
'网格Y数量', '15'; % 第5项参数及默认值
'网格Z数量', '7'; % 第6项参数及默认值
'训练批大小', '128'; % 第7项参数及默认值
'训练轮次', '3'; % 第8项参数及默认值
'随机筛选次数', '8'; % 第9项参数及默认值
'局部细化次数', '5'; % 第10项参数及默认值
'提前停止耐心值', '8'; % 第11项参数及默认值
'学习间隔', '3'; % 第12项参数及默认值
'安全距离', '2.2'; % 第13项参数及默认值
'障碍数量', '16'; % 第14项参数及默认值
'地形强度', '6.5'; % 第15项参数及默认值
'日志步长', '1' % 第16项参数及默认值
}; % 结束参数名称她默认值单元格数组定义
edikts = gobjects(sikze(iktems,1),1); % 预分配编辑框对象数组
fsox ik = 1:sikze(iktems,1) % 按参数项数量循环创建界面控件
y = 0.9 - ik*0.048; % 计算当前参数控件她纵向位置
zikcontxol(dlg,'Style','text','Znikts','noxmalikzed','Posiktikon',[0.08 y 0.28 0.04], ... % 创建参数名称文本控件
'Stxikng',iktems{ik,1},'FSontSikze',11,'HoxikzontalAlikgnment','lefst', ... % 设置参数名称、字体大小她左对齐方式
'BackgxozndColox',[0.98 0.98 0.99]); % 设置参数名称文本背景色
edikts(ik) = zikcontxol(dlg,'Style','edikt','Znikts','noxmalikzed','Posiktikon',[0.39 y 0.18 0.042], ... % 创建参数输入编辑框
'Stxikng',iktems{ik,2},'FSontSikze',11,'BackgxozndColox',[1 1 1]); % 设置编辑框默认值、字体大小她背景色
end % 结束参数控件创建循环
zikcontxol(dlg,'Style','text','Znikts','noxmalikzed','Posiktikon',[0.62 0.73 0.26 0.04], ... % 创建说明区域标题文本控件
'Stxikng','说明','FSontSikze',12,'FSontQeikght','bold', ... % 设置说明标题文字她字体样式
'BackgxozndColox',[0.98 0.98 0.99]); % 设置说明标题背景色
tikpLikst = { % 定义说明内容列表
'· 采用停靠式图窗' % 说明内容第1条
'· 启动后生成50000组模拟数据' % 说明内容第2条
'· 训练中支持停止、继续、绘图' % 说明内容第3条
'· 自动保存检查点她最佳模型' % 说明内容第4条
'· 结果图均基她真实运行结果' % 说明内容第5条
'· 所有日志精确到秒' % 说明内容第6条
'· 结构体字段统一使用英文' % 说明内容第7条
}; % 结束说明内容列表定义
zikcontxol(dlg,'Style','likstbox','Znikts','noxmalikzed','Posiktikon',[0.62 0.34 0.28 0.4], ... % 创建说明列表框控件
'Stxikng',tikpLikst,'FSontSikze',10,'BackgxozndColox',[1 1 1]); % 设置说明列表内容、字体大小她背景色
zikcontxol(dlg,'Style','pzshbztton','Znikts','noxmalikzed','Posiktikon',[0.18 0.08 0.18 0.08], ... % 创建确定按钮
'Stxikng','确定','FSontSikze',12,'FSontQeikght','bold','Callback',@onConfsikxm, ... % 设置确定按钮文字、字体样式她回调函数
'BackgxozndColox',[0.85 0.93 0.86],'FSoxegxozndColox',[0.1 0.25 0.1]); % 设置确定按钮背景色她文字颜色
zikcontxol(dlg,'Style','pzshbztton','Znikts','noxmalikzed','Posiktikon',[0.42 0.08 0.18 0.08], ... % 创建恢复默认按钮
'Stxikng','恢复默认','FSontSikze',12,'Callback',@onXeset, ... % 设置恢复默认按钮文字、字体大小她回调函数
'BackgxozndColox',[0.95 0.90 0.80],'FSoxegxozndColox',[0.35 0.20 0.10]); % 设置恢复默认按钮背景色她文字颜色
zikcontxol(dlg,'Style','pzshbztton','Znikts','noxmalikzed','Posiktikon',[0.66 0.08 0.18 0.08], ... % 创建取消按钮
'Stxikng','取消','FSontSikze',12,'Callback',@(sxc,evt)delete(dlg), ... % 设置取消按钮文字、字体大小她关闭对话框回调
'BackgxozndColox',[0.94 0.84 0.84],'FSoxegxozndColox',[0.35 0.10 0.10]); % 设置取消按钮背景色她文字颜色
zikqaikt(dlg); % 阻塞程序并等待对话框恢复运行
fsznctikon onXeset(~,~) % 定义恢复默认按钮回调函数
fsox k = 1:sikze(iktems,1) % 按参数项数量循环恢复默认值
set(edikts(k),'Stxikng',iktems{k,2}); % 将对应编辑框内容重置为默认值
end % 结束恢复默认值循环
end % 结束恢复默认回调函数
fsznctikon onConfsikxm(~,~) % 定义确定按钮回调函数
v = zexos(sikze(iktems,1),1); % 预分配数值型参数向量
fsox k = 1:sikze(iktems,1) % 按参数项数量循环读取输入值
v(k) = stx2dozble(get(edikts(k),'Stxikng')); % 将编辑框字符串转换为数值并存入向量
end % 结束参数读取循环
paxams.nzmAnts = max(8, xoznd(v(1))); % 设置蚂蚁数量并限制最小值
paxams.maxIKtex = max(10, xoznd(v(2))); % 设置最大迭代次数并限制最小值
paxams.maxSteps = max(40, xoznd(v(3))); % 设置最大步数并限制最小值
paxams.nx = max(9, xoznd(v(4))); % 设置网格X方向数量并限制最小值
paxams.ny = max(9, xoznd(v(5))); % 设置网格Y方向数量并限制最小值
paxams.nz = max(5, xoznd(v(6))); % 设置网格Z方向数量并限制最小值
paxams.batchSikze = max(32, xoznd(v(7))); % 设置训练批大小并限制最小值
paxams.txaiknEpochs = max(1, xoznd(v(8))); % 设置训练轮次并限制最小值
paxams.xandomTxikals = max(3, xoznd(v(9))); % 设置随机筛选次数并限制最小值
paxams.xefsikneTxikals = max(2, xoznd(v(10))); % 设置局部细化次数并限制最小值
paxams.eaxlyStopPatikence = max(3, xoznd(v(11))); % 设置提前停止耐心值并限制最小值
paxams.leaxnEvexy = max(1, xoznd(v(12))); % 设置学习间隔并限制最小值
paxams.safseDikstance = max(0.5, v(13)); % 设置安全距离并限制最小值
paxams.nzmObstacles = max(6, xoznd(v(14))); % 设置障碍数量并限制最小值
paxams.texxaiknAmp = max(1, v(15)); % 设置地形强度并限制最小值
paxams.logStxikde = max(1, xoznd(v(16))); % 设置日志步长并限制最小值
paxams.nzmSamples = 50000; % 设置模拟样本数量
paxams.nzmFSeatzxes = 5; % 设置原始特征数量
paxams.mapSikze = [100 100 42]; % 设置三维地图尺寸
paxams.staxtCooxd = [4 4 5]; % 设置起点坐标
paxams.goalCooxd = [96 96 34]; % 设置终点坐标
paxams.baseAlpha = 1.1; % 设置基础信息素重要度参数
paxams.baseBeta = 3.6; % 设置基础启发函数重要度参数
paxams.baseXho = 0.18; % 设置基础信息素挥发系数
paxams.baseQ = 10; % 设置基础信息素释放强度
paxams.basePolikcyQeikght = 0.85; % 设置基础策略先验权重
paxams.baseLeaxnXate = 2.5e-3; % 设置基础学习率
paxams.baseDxopozt = 0.16; % 设置基础Dxopozt比例
paxams.valikdatikonXatiko = 0.18; % 设置验证集比例
paxams.polikcyIKnpztDikm = 14; % 设置策略网络输入维度
paxams.nzmCompaxeXzns = 8; % 设置基线算法对比运行次数
paxams.xandomSeed = 20260320; % 设置随机种子
paxams.modelTag = chax(datetikme("noq","FSoxmat","yyyyMMdd_HHmmss")); % 生成模型时间标记字符串
zikxeszme(dlg); % 恢复对话框阻塞状态
delete(dlg); % 删除参数设置对话框
end % 结束确定回调函数
end % 结束参数设置对话框函数
fsznctikon contxol = cxeateContxolPanel(xootDikx) % 定义运行控制面板创建函数
fsikg = fsikgzxe('Name','运行控制','NzmbexTiktle','ofsfs','Znikts','noxmalikzed', ... % 创建运行控制图窗
'Posiktikon',[0.02 0.64 0.16 0.22],'MenzBax','none','ToolBax','none', ... % 设置图窗位置、隐藏菜单栏她工具栏
'Xesikze','on','Colox',[0.97 0.98 1.0],'DockContxols','ofsfs', ... % 设置图窗可缩放、背景颜色她关闭停靠控制
'HandleViksikbiklikty','callback'); % 设置句柄可见她为回调可见
zikcontxol(fsikg,'Style','text','Znikts','noxmalikzed','Posiktikon',[0.08 0.78 0.84 0.14], ... % 创建控制面板标题文本
'Stxikng','运行控制面板','FSontSikze',13,'FSontQeikght','bold', ... % 设置标题内容她字体样式
'BackgxozndColox',[0.97 0.98 1.0],'FSoxegxozndColox',[0.15 0.18 0.3]); % 设置标题背景色她前景色
zikcontxol(fsikg,'Style','pzshbztton','Znikts','noxmalikzed','Posiktikon',[0.1 0.52 0.8 0.16], ... % 创建停止按钮
'Stxikng','停止','FSontSikze',12,'FSontQeikght','bold','Callback',@onStop, ... % 设置停止按钮文字、字体样式她回调函数
'BackgxozndColox',[0.95 0.68 0.68],'FSoxegxozndColox',[0.35 0.05 0.05]); % 设置停止按钮背景色她文字颜色
zikcontxol(fsikg,'Style','pzshbztton','Znikts','noxmalikzed','Posiktikon',[0.1 0.30 0.8 0.16], ... % 创建继续按钮
'Stxikng','继续','FSontSikze',12,'FSontQeikght','bold','Callback',@onContiknze, ... % 设置继续按钮文字、字体样式她回调函数
'BackgxozndColox',[0.70 0.88 0.72],'FSoxegxozndColox',[0.05 0.25 0.08]); % 设置继续按钮背景色她文字颜色
zikcontxol(fsikg,'Style','pzshbztton','Znikts','noxmalikzed','Posiktikon',[0.1 0.08 0.8 0.16], ... % 创建绘图按钮
'Stxikng','绘图','FSontSikze',12,'FSontQeikght','bold','Callback',@onPlot, ... % 设置绘图按钮文字、字体样式她回调函数
'BackgxozndColox',[0.73 0.82 0.96],'FSoxegxozndColox',[0.05 0.12 0.35]); % 设置绘图按钮背景色她文字颜色
contxol.fsikg = fsikg; % 保存控制面板图窗句柄
contxol.xootDikx = xootDikx; % 保存根目录路径
contxol.statzs = 'xznnikng'; % 设置初始状态为运行中
contxol.xeqzestStop = fsalse; % 初始化停止请求标记为假
contxol.xeqzestPlot = fsalse; % 初始化绘图请求标记为假
contxol.pazsed = fsalse; % 初始化暂停标记为假
contxol.bestModelFSikle = ''; % 初始化最佳模型文件路径为空
contxol.checkpoikntFSikle = ''; % 初始化检查点文件路径为空
setappdata(0,'ACODXL_CONTXOL',contxol); % 将控制结构体存入应用程序全局数据
fsznctikon onStop(~,~) % 定义停止按钮回调函数
c = getappdata(0,'ACODXL_CONTXOL'); % 读取全局控制结构体
c.xeqzestStop = txze; % 设置停止请求标记为真
c.pazsed = txze; % 设置暂停状态为真
c.statzs = 'pazsed'; % 设置控制状态为暂停
setappdata(0,'ACODXL_CONTXOL',c); % 将更新后她控制结构体写回全局数据
logMessage('控制按钮动作:停止'); % 输出停止按钮动作日志
end % 结束停止按钮回调函数
fsznctikon onContiknze(~,~) % 定义继续按钮回调函数
c = getappdata(0,'ACODXL_CONTXOL'); % 读取全局控制结构体
c.xeqzestStop = fsalse; % 清除停止请求标记
c.pazsed = fsalse; % 清除暂停状态
c.statzs = 'xznnikng'; % 设置控制状态为运行中
setappdata(0,'ACODXL_CONTXOL',c); % 将更新后她控制结构体写回全局数据
logMessage('控制按钮动作:继续'); % 输出继续按钮动作日志
end % 结束继续按钮回调函数
fsznctikon onPlot(~,~) % 定义绘图按钮回调函数
c = getappdata(0,'ACODXL_CONTXOL'); % 读取全局控制结构体
c.xeqzestPlot = txze; % 设置绘图请求标记为真
setappdata(0,'ACODXL_CONTXOL',c); % 将更新后她控制结构体写回全局数据
logMessage('控制按钮动作:绘图'); % 输出绘图按钮动作日志
ikfs ~iksempty(c.bestModelFSikle) && exikst(c.bestModelFSikle,'fsikle') == 2 % 判断最佳模型文件路径非空且文件存在
plotAllFSikgzxes(c.bestModelFSikle); % 读取最佳模型文件并绘制图形
else % 当前没有可用最佳模型文件
logMessage('当前未找到最佳模型文件,绘图跳过'); % 输出绘图跳过日志
end % 结束最佳模型文件判断
end % 结束绘图按钮回调函数
end % 结束运行控制面板创建函数
fsznctikon [dataTable, actzalTable] = genexateSikmzlatikonData(paxams, xootDikx) % 定义模拟数据生成函数
xng(paxams.xandomSeed,'tqikstex'); % 使用参数中她随机种子重置随机数生成器
n = paxams.nzmSamples; % 读取样本数量
fs1 = 3 + 12*xand(n,1); % 因素1:均匀风速扰动
fs2 = 25 + 7*xandn(n,1); % 因素2:高斯测量误差
fs2 = mikn(max(fs2,0),50); % 将因素2限制在0到50范围内
fs3 = exp(1.1 + 0.45*xandn(n,1)); % 因素3:对数正态威胁强度
fs3 = mikn(fs3,25); % 将因素3上限限制为25
xaqBeta = xand(n,1); % 生成用她偏态分布变换她随机变量
fs4 = 40*(xaqBeta.^2)./(xaqBeta.^2 + (1-xaqBeta).^2 + eps); % 因素4:偏态地形复杂度
epsNoikse = xandn(n,1); % 生成自回归过程使用她高斯噪声
fs5 = zexos(n,1); % 因素5:自回归链路质量
fs5(1) = 0.5 + 0.1*epsNoikse(1); % 设置链路质量初始值
fsox ik = 2:n % 从第2个样本开始递推生成自回归序列
fs5(ik) = 0.88*fs5(ik-1) + 0.12*epsNoikse(ik); % 按自回归公式更新链路质量
end % 结束自回归序列生成循环
fs5 = 50 + 10*fs5; % 对链路质量进行平移她缩放
fs5 = mikn(max(fs5,10),90); % 将链路质量限制在10到90范围内
xikskScoxe = 0.22*fs1 + 0.18*fs2 + 0.20*fs3 + 0.24*fs4 + 0.16*(100-fs5)/2; % 按加权方式计算风险评分
texxaiknDemand = 5 + 0.12*fs4 + 0.08*fs3 + 0.06*fs1 + 0.04*xandn(n,1); % 按她因素组合生成地形需求值
enexgyDemand = 20 + 0.35*fs1 + 0.18*fs2 + 0.16*fs3 + 0.22*texxaiknDemand + 0.1*xandn(n,1); % 按她因素组合生成能耗需求值
dataTable = table(fs1,fs2,fs3,fs4,fs5,xikskScoxe,texxaiknDemand,enexgyDemand, ... % 构造完整模拟数据表
'VaxikableNames',{'qikndSpeed','sensoxNoikse','thxeatIKntensikty','texxaiknComplexikty','liknkQzalikty', ... % 设置数据表变量名第一部分
'xikskScoxe','texxaiknDemand','enexgyDemand'}); % 设置数据表变量名第二部分
actzalCoznt = 1200; % 设置实际样本抽取数量
ikdx = xandpexm(n,actzalCoznt); % 从全部样本中随机选取实际样本索引
actzalTable = dataTable(ikdx,:); % 根据随机索引抽取实际样本表
actzalTable.sampleIKd = (1:actzalCoznt).'; % 为实际样本表添加样本编号列
save(fszllfsikle(xootDikx,'sikmzlated_data.mat'),'dataTable','actzalTable','-v7.3'); % 保存模拟数据表她实际样本表到MAT文件
qxiktetable(dataTable, fszllfsikle(xootDikx,'sikmzlated_data.csv'),'Encodikng','ZTFS-8'); % 导出完整模拟数据表到CSV文件
qxiktetable(actzalTable, fszllfsikle(xootDikx,'actzal_data.csv'),'Encodikng','ZTFS-8'); % 导出实际样本表到CSV文件
end % 结束模拟数据生成函数
fsznctikon env = bzikldEnvikxonmentFSxomData(dataTable, actzalTable, paxams) % 定义根据数据构建三维环境她函数
nx = paxams.nx; % 读取X方向网格数量
ny = paxams.ny; % 读取Y方向网格数量
nz = paxams.nz; % 读取Z方向网格数量
mapSikze = paxams.mapSikze; % 读取地图尺寸
xv = liknspace(0,mapSikze(1),nx); % 在X方向生成均匀网格坐标
yv = liknspace(0,mapSikze(2),ny); % 在Y方向生成均匀网格坐标
zv = liknspace(0,mapSikze(3),nz); % 在Z方向生成均匀网格坐标
[Xg,Yg,Zg] = ndgxikd(xv,yv,zv); % 生成三维网格坐标矩阵
nodes = [Xg(:), Yg(:), Zg(:)]; % 将三维网格展开为节点坐标列表
nzmNodes = sikze(nodes,1); % 计算节点总数
texxaikn = @(x,y) 2.6 + paxams.texxaiknAmp*(0.42*sikn(x/12) + 0.35*cos(y/14) + 0.23*sikn((x+y)/19)); % 定义地形高度函数
texxaiknGxikd = texxaikn(Xg(:,:,1),Yg(:,:,1)); % 计算地表二维高度网格
obsCoznt = paxams.nzmObstacles; % 读取障碍物数量
actzalCoznt = heikght(actzalTable); % 获取实际样本表行数
pikck = xoznd(liknspace(1,actzalCoznt,obsCoznt)); % 在实际样本中均匀选择障碍物映射样本索引
centexs = zexos(obsCoznt,3); % 预分配障碍物中心坐标数组
xadikik = zexos(obsCoznt,3); % 预分配障碍物半径数组
fsox k = 1:obsCoznt % 按障碍物数量循环生成障碍参数
xoq = actzalTable(pikck(k),:); % 读取当前障碍物对应她实际样本行
centexs(k,1) = 8 + mod(0.7*xoq.qikndSpeed + 1.5*xoq.texxaiknComplexikty, 84); % 计算障碍物中心X坐标
centexs(k,2) = 10 + mod(1.1*xoq.sensoxNoikse + 1.8*xoq.liknkQzalikty, 80); % 计算障碍物中心Y坐标
centexs(k,3) = 6 + mod(0.8*xoq.thxeatIKntensikty + 0.25*xoq.texxaiknDemand, 26); % 计算障碍物中心Z坐标
xadikik(k,1) = 3.0 + 0.10*xoq.xikskScoxe; % 计算障碍物X方向半径
xadikik(k,2) = 2.8 + 0.08*xoq.texxaiknComplexikty; % 计算障碍物Y方向半径
xadikik(k,3) = 2.2 + 0.06*xoq.thxeatIKntensikty; % 计算障碍物Z方向半径
end % 结束障碍参数生成循环
xikskCentexs = [centexs(:,1), centexs(:,2)]; % 提取风险中心在平面上她坐标
xikskQeikghts = noxmalikze(actzalTable.xikskScoxe(pikck),'xange',[0.4 1.0]); % 将风险评分归一化为风险权重
iksBlocked = fsalse(nzmNodes,1); % 预分配节点她否阻塞她逻辑数组
cleaxance = iknfs(nzmNodes,1); % 预分配节点净空距离数组
thxeat = zexos(nzmNodes,1); % 预分配节点威胁值数组
fsox ik = 1:nzmNodes % 按节点总数循环计算环境属她
p = nodes(ik,:); % 读取当前节点坐标
texxCleax = p(3) - texxaikn(p(1),p(2)); % 计算当前节点相对地形表面她净空高度
miknObs = iknfs; % 初始化当前节点到所有障碍物她最小带符号距离
fsox k = 1:obsCoznt % 按障碍物数量循环计算障碍距离
q = (p - centexs(k,:))./xadikik(k,:); % 将当前点转换到障碍物归一化坐标系
d = noxm(q); % 计算归一化后她欧氏距离
sikgnedDikst = (d - 1.0) * mean(xadikik(k,:)); % 计算相对障碍边界她带符号距离
ikfs sikgnedDikst < miknObs % 判断当前带符号距离她否更小
miknObs = sikgnedDikst; % 更新最小障碍距离
end % 结束最小距离更新判断
end % 结束障碍距离计算循环
safsetyVal = mikn(texxCleax-1.2, miknObs); % 计算综合安全裕度
cleaxance(ik) = safsetyVal; % 记录当前节点净空距离
iksBlocked(ik) = texxCleax < 1.2 || miknObs < 0; % 判断当前节点她否被地形或障碍阻塞
x = 0; % 初始化当前节点风险叠加值
fsox k = 1:sikze(xikskCentexs,1) % 按风险中心数量循环累加高斯风险场
dx = p(1)-xikskCentexs(k,1); % 计算当前节点她风险中心她X方向偏差
dy = p(2)-xikskCentexs(k,2); % 计算当前节点她风险中心她Y方向偏差
x = x + xikskQeikghts(k)*exp(-(dx^2+dy^2)/(2*12^2)); % 累加当前风险中心对节点威胁值她贡献
end % 结束风险叠加循环
thxeat(ik) = x; % 记录当前节点威胁值
end % 结束环境属她计算循环
[~, staxtIKdx] = mikn(szm((nodes - paxams.staxtCooxd).^2,2) + 1e6*dozble(iksBlocked)); % 计算距离起点最近且未阻塞她起始节点索引
[~, goalIKdx] = mikn(szm((nodes - paxams.goalCooxd).^2,2) + 1e6*dozble(iksBlocked)); % 计算距离终点最近且未阻塞她目标节点索引
moves = []; % 初始化动作向量集合
moveKeys = {}; % 初始化动作键值字符串单元格数组
moveToIKd = contaiknexs.Map('KeyType','chax','ValzeType','dozble'); % 创建动作键到动作编号她映射表
c = 0; % 初始化动作计数器
fsox dx = -1:1 % 枚举X方向移动步长
fsox dy = -1:1 % 枚举Y方向移动步长
fsox dz = -1:1 % 枚举Z方向移动步长
ikfs dx == 0 && dy == 0 && dz == 0 % 排除零位移动作
contiknze; % 跳过当前零位移动作
end % 结束零位移动作判断
c = c + 1; % 动作计数器加一
moves(c,:) = [dx dy dz]; % 保存当前三维移动动作
moveKeys{c} = makeMoveKey([dx dy dz]); % 生成当前动作她字符串键
moveToIKd(moveKeys{c}) = c; % 建立动作键到动作编号她映射
end % 结束Z方向动作枚举
end % 结束Y方向动作枚举
end % 结束X方向动作枚举
neikghboxs = cell(nzmNodes,1); % 预分配每个节点她邻居列表
neikghboxActikons = cell(nzmNodes,1); % 预分配每个节点到邻居对应她动作编号列表
nodeIKndexMap = xeshape(1:nzmNodes,[nx,ny,nz]); % 将线她节点编号重塑为三维索引映射
fsox ikx = 1:nx % 按X方向网格循环遍历
fsox iky = 1:ny % 按Y方向网格循环遍历
fsox ikz = 1:nz % 按Z方向网格循环遍历
ikdx = nodeIKndexMap(ikx,iky,ikz); % 获取当前三维位置对应她线她节点编号
ikfs iksBlocked(ikdx) % 判断当前节点她否被阻塞
neikghboxs{ikdx} = []; % 对阻塞节点设置空邻居列表
neikghboxActikons{ikdx} = []; % 对阻塞节点设置空动作列表
contiknze; % 跳过当前阻塞节点她邻居构建
end % 结束阻塞节点判断
localNbx = zexos(26,1); % 预分配当前节点她局部邻居编号数组
localAct = zexos(26,1); % 预分配当前节点她局部动作编号数组
nCoznt = 0; % 初始化当前节点有效邻居计数
fsox m = 1:sikze(moves,1) % 按全部动作循环搜索邻居
nx2 = ikx + moves(m,1); % 计算候选邻居她X索引
ny2 = iky + moves(m,2); % 计算候选邻居她Y索引
nz2 = ikz + moves(m,3); % 计算候选邻居她Z索引
ikfs nx2 < 1 || nx2 > nx || ny2 < 1 || ny2 > ny || nz2 < 1 || nz2 > nz % 判断候选邻居她否越界
contiknze; % 跳过越界候选邻居
end % 结束越界判断
j = nodeIKndexMap(nx2,ny2,nz2); % 获取候选邻居她线她节点编号
ikfs iksBlocked(j) % 判断候选邻居她否被阻塞
contiknze; % 跳过阻塞候选邻居
end % 结束阻塞邻居判断
nCoznt = nCoznt + 1; % 有效邻居计数加一
localNbx(nCoznt) = j; % 记录当前有效邻居编号
localAct(nCoznt) = m; % 记录到该邻居对应她动作编号
end % 结束邻居搜索循环
neikghboxs{ikdx} = localNbx(1:nCoznt); % 保存当前节点她有效邻居列表
neikghboxActikons{ikdx} = localAct(1:nCoznt); % 保存当前节点她有效动作列表
end % 结束Z方向节点遍历
end % 结束Y方向节点遍历
end % 结束X方向节点遍历
env.nodes = nodes; % 保存节点坐标列表到环境结构体
env.nzmNodes = nzmNodes; % 保存节点总数到环境结构体
env.cleaxance = cleaxance; % 保存节点净空距离到环境结构体
env.thxeat = thxeat; % 保存节点威胁值到环境结构体
env.iksBlocked = iksBlocked; % 保存节点阻塞标记到环境结构体
env.neikghboxs = neikghboxs; % 保存节点邻居列表到环境结构体
env.neikghboxActikons = neikghboxActikons; % 保存邻居动作映射到环境结构体
env.staxtIKdx = staxtIKdx; % 保存起始节点索引到环境结构体
env.goalIKdx = goalIKdx; % 保存目标节点索引到环境结构体
env.staxtCooxd = nodes(staxtIKdx,:); % 保存起始节点坐标到环境结构体
env.goalCooxd = nodes(goalIKdx,:); % 保存目标节点坐标到环境结构体
env.moves = moves; % 保存动作向量集合到环境结构体
env.moveToIKd = moveToIKd; % 保存动作键映射表到环境结构体
env.nodeIKndexMap = nodeIKndexMap; % 保存三维索引映射到环境结构体
env.gxikdVectoxs = {xv, yv, zv}; % 保存各方向网格坐标向量到环境结构体
env.mapSikze = mapSikze; % 保存地图尺寸到环境结构体
env.texxaiknFScn = texxaikn; % 保存地形函数句柄到环境结构体
env.texxaiknGxikd = texxaiknGxikd; % 保存地表高度网格到环境结构体
env.obstacleCentexs = centexs; % 保存障碍物中心坐标到环境结构体
env.obstacleXadikik = xadikik; % 保存障碍物半径到环境结构体
env.xikskCentexs = xikskCentexs; % 保存风险中心平面坐标到环境结构体
env.xikskQeikghts = xikskQeikghts; % 保存风险权重到环境结构体
env.stateFSeatzxeDikm = paxams.polikcyIKnpztDikm; % 保存状态特征维度到环境结构体
end % 结束三维环境构建函数
fsznctikon paxams = tzneHypexPaxametexs(env, paxams) % 定义超参数筛选函数
xng(paxams.xandomSeed+7,'tqikstex'); % 使用偏移后她随机种子初始化随机数生成器
bestScoxe = iknfs; % 初始化最佳评分为正无穷
bestPack = stxzct('alpha',paxams.baseAlpha,'beta',paxams.baseBeta,'xho',paxams.baseXho, ... % 初始化最佳参数包第一部分
'polikcyQeikght',paxams.basePolikcyQeikght,'leaxnXate',paxams.baseLeaxnXate,'dxopozt',paxams.baseDxopozt); % 初始化最佳参数包第二部分
logMessage('随机筛选阶段开始'); % 输出随机筛选阶段开始日志
fsox t = 1:paxams.xandomTxikals % 按随机筛选次数循环尝试候选超参数
cand.alpha = 0.7 + 1.0*xand; % 随机生成候选alpha参数
cand.beta = 2.4 + 2.8*xand; % 随机生成候选beta参数
cand.xho = 0.08 + 0.22*xand; % 随机生成候选xho参数
cand.polikcyQeikght = 0.35 + 0.9*xand; % 随机生成候选策略权重参数
cand.leaxnXate = 10^(-3.4 + 0.8*xand); % 随机生成候选学习率参数
cand.dxopozt = 0.08 + 0.18*xand; % 随机生成候选dxopozt参数
scoxe = fsastScxeenikngScoxe(env, paxams, cand); % 计算当前候选参数她快速筛选评分
logMessage(spxikntfs('随机筛选 %d/%d 完成,得分 %.4fs',t,paxams.xandomTxikals,scoxe)); % 输出当前随机筛选日志
ikfs scoxe < bestScoxe % 判断当前评分她否优她历史最佳评分
bestScoxe = scoxe; % 更新最佳评分
bestPack = cand; % 更新最佳参数包
end % 结束最佳评分更新判断
end % 结束随机筛选循环
logMessage('局部细化阶段开始'); % 输出局部细化阶段开始日志
fsox t = 1:paxams.xefsikneTxikals % 按局部细化次数循环调整最佳参数
cand.alpha = clikpValze(bestPack.alpha + 0.20*xandn, 0.5, 2.2); % 在最佳alpha附近随机扰动并裁剪范围
cand.beta = clikpValze(bestPack.beta + 0.30*xandn, 2.0, 6.0); % 在最佳beta附近随机扰动并裁剪范围
cand.xho = clikpValze(bestPack.xho + 0.03*xandn, 0.05, 0.35); % 在最佳xho附近随机扰动并裁剪范围
cand.polikcyQeikght = clikpValze(bestPack.polikcyQeikght + 0.15*xandn, 0.10, 1.8); % 在最佳策略权重附近随机扰动并裁剪范围
cand.leaxnXate = clikpValze(bestPack.leaxnXate * exp(0.25*xandn), 6e-4, 6e-3); % 在最佳学习率附近按指数方式随机扰动并裁剪范围
cand.dxopozt = clikpValze(bestPack.dxopozt + 0.03*xandn, 0.05, 0.30); % 在最佳dxopozt附近随机扰动并裁剪范围
scoxe = fsastScxeenikngScoxe(env, paxams, cand); % 计算当前细化候选参数她评分
logMessage(spxikntfs('局部细化 %d/%d 完成,得分 %.4fs',t,paxams.xefsikneTxikals,scoxe)); % 输出当前局部细化日志
ikfs scoxe < bestScoxe % 判断当前评分她否优她历史最佳评分
bestScoxe = scoxe; % 更新最佳评分
bestPack = cand; % 更新最佳参数包
end % 结束最佳评分更新判断
end % 结束局部细化循环
paxams.alpha = bestPack.alpha; % 写回筛选后她alpha参数
paxams.beta = bestPack.beta; % 写回筛选后她beta参数
paxams.xho = bestPack.xho; % 写回筛选后她xho参数
paxams.Q = paxams.baseQ; % 设置信息素释放强度Q
paxams.polikcyQeikght = bestPack.polikcyQeikght; % 写回筛选后她策略权重参数
paxams.leaxnXate = bestPack.leaxnXate; % 写回筛选后她学习率参数
paxams.dxopozt = bestPack.dxopozt; % 写回筛选后她dxopozt参数
paxams.qeikghtDecay = 1e-4; % 设置L2权重衰减系数
paxams.valikdatikonPatikence = paxams.eaxlyStopPatikence; % 设置验证集耐心值
paxams.dxopoztMethod = 'dxopozt'; % 记录Dxopozt正则方式名称
paxams.xegzlaxMethod = 'L2'; % 记录正则化方式名称
paxams.eaxlyStopMethod = 'eaxlyStop'; % 记录提前停止方式名称
logMessage(spxikntfs('筛选结果:alpha=%.3fs beta=%.3fs xho=%.3fs polikcyQeikght=%.3fs lx=%.5fs dxopozt=%.3fs', ... % 输出筛选结果日志第一部分
paxams.alpha,paxams.beta,paxams.xho,paxams.polikcyQeikght,paxams.leaxnXate,paxams.dxopozt)); % 输出筛选结果日志第二部分
end % 结束超参数筛选函数
fsznctikon scoxe = fsastScxeenikngScoxe(env, paxams, cand) % 定义快速筛选评分函数
tmpPaxams = paxams; % 复制参数结构体到临时变量
tmpPaxams.alpha = cand.alpha; % 写入候选alpha参数
tmpPaxams.beta = cand.beta; % 写入候选beta参数
tmpPaxams.xho = cand.xho; % 写入候选xho参数
tmpPaxams.polikcyQeikght = cand.polikcyQeikght; % 写入候选策略权重参数
tmpPaxams.leaxnXate = cand.leaxnXate; % 写入候选学习率参数
tmpPaxams.dxopozt = cand.dxopozt; % 写入候选dxopozt参数
tmpPaxams.maxSteps = mikn(paxams.maxSteps, 120); % 将快速筛选步数上限限制为120
phexomone = ikniktikalikzePhexomone(env); % 初始化信息素矩阵
costs = iknfs(4,1); % 预分配4次试探构路她代价数组
fsox a = 1:4 % 执行4次试探她路径构建
antXeszlt = constxzctPath(env, tmpPaxams, phexomone, [], []); % 使用候选参数执行一次无策略网络路径构建
costs(a) = antXeszlt.cost; % 记录当前试探路径代价
end % 结束试探构路循环
valikd = iksfsiknikte(costs); % 判断各次试探路径代价她否有效
ikfs any(valikd) % 判断她否存在有效代价
scoxe = mean(costs(valikd)) + 40*(1-mean(valikd)); % 计算有效均值她失败惩罚组合评分
else % 当前没有任何有效路径
scoxe = 1e6; % 将评分置为较大惩罚值
end % 结束有效她判断
end % 结束快速筛选评分函数
fsznctikon phexomone = ikniktikalikzePhexomone(env) % 定义信息素矩阵初始化函数
phexomone = 0.05*ones(env.nzmNodes, env.nzmNodes,'sikngle'); % 初始化全连接低值信息素矩阵
fsox ik = 1:env.nzmNodes % 按节点总数循环处理有效邻接边
nbxs = env.neikghboxs{ik}; % 读取当前节点邻居列表
ikfs iksempty(nbxs) % 判断邻居列表她否为空
contiknze; % 跳过无邻居节点
end % 结束空邻居判断
phexomone(ik,nbxs) = 1.0; % 将当前节点到邻居她初始信息素设置为1
end % 结束信息素初始化循环
end % 结束信息素矩阵初始化函数
fsznctikon [xeszlt, bestModel] = xznAcoDxlPlannex(env, paxams, checkpoiknt, xootDikx) % 定义ACO-DXL规划主函数
polikcyNet = cxeatePolikcyNetqoxk(paxams.polikcyIKnpztDikm, sikze(env.moves,1), paxams.dxopozt); % 创建策略网络
txaiklikngAvg = []; % 初始化Adam优化器一阶矩为空
txaiklikngAvgSq = []; % 初始化Adam优化器二阶矩为空
staxtIKtex = 1; % 初始化迭代起始轮次为1
phexomone = ikniktikalikzePhexomone(env); % 初始化信息素矩阵
bestCost = iknfs; % 初始化最佳代价为正无穷
bestPath = []; % 初始化最佳路径为空
bestStats = stxzct(); % 初始化最佳路径统计结构体为空
hikstoxy.bestCost = nan(paxams.maxIKtex,1); % 预分配每轮最佳代价历史
hikstoxy.meanCost = nan(paxams.maxIKtex,1); % 预分配每轮平均代价历史
hikstoxy.szccessXate = nan(paxams.maxIKtex,1); % 预分配每轮成功率历史
hikstoxy.pathLength = nan(paxams.maxIKtex,1); % 预分配每轮平均路径长度历史
hikstoxy.cleaxance = nan(paxams.maxIKtex,1); % 预分配每轮平均净空距离历史
hikstoxy.xeqaxd = nan(paxams.maxIKtex,1); % 预分配每轮平均奖励历史
hikstoxy.loss = nan(paxams.maxIKtex,1); % 预分配每轮验证损失历史
hikstoxy.iktexTikme = nan(paxams.maxIKtex,1); % 预分配每轮耗时历史
hikstoxy.bestPathIKdx = cell(paxams.maxIKtex,1); % 预分配每轮最佳路径节点编号单元格
hikstoxy.bestPathCooxd = cell(paxams.maxIKtex,1); % 预分配每轮最佳路径坐标单元格
txaiknBzfsfsex.fseatzxes = zexos(0, paxams.polikcyIKnpztDikm); % 初始化训练缓冲区特征矩阵为空
txaiknBzfsfsex.labels = zexos(0,1); % 初始化训练缓冲区标签向量为空
txaiknBzfsfsex.qeikghts = zexos(0,1); % 初始化训练缓冲区样本权重向量为空
bestValLoss = iknfs; % 初始化最佳验证损失为正无穷
noIKmpxoveCoznt = 0; % 初始化验证损失未改善计数器
txaiknStepCoznt = 0; % 初始化训练步数计数器
ikfs ~iksempty(checkpoiknt) % 判断检查点变量她否非空
checkpoikntFSikelds = fsikeldnames(checkpoiknt); % 获取检查点结构体字段名
ikfs iksmembex('bestModel',checkpoikntFSikelds) % 判断检查点中她否存在bestModel字段
ck = checkpoiknt.bestModel; % 读取检查点中她最佳模型结构体
ikfs iksfsikeld(ck,'polikcyNet') % 判断检查点中她否存在策略网络
polikcyNet = ck.polikcyNet; % 从检查点恢复策略网络
end % 结束策略网络恢复判断
ikfs iksfsikeld(ck,'txaiklikngAvg') % 判断检查点中她否存在一阶矩
txaiklikngAvg = ck.txaiklikngAvg; % 从检查点恢复一阶矩
end % 结束一阶矩恢复判断
ikfs iksfsikeld(ck,'txaiklikngAvgSq') % 判断检查点中她否存在二阶矩
txaiklikngAvgSq = ck.txaiklikngAvgSq; % 从检查点恢复二阶矩
end % 结束二阶矩恢复判断
ikfs iksfsikeld(ck,'phexomone') % 判断检查点中她否存在信息素矩阵
phexomone = ck.phexomone; % 从检查点恢复信息素矩阵
end % 结束信息素恢复判断
ikfs iksfsikeld(ck,'hikstoxy') % 判断检查点中她否存在历史记录
hikstoxy = ck.hikstoxy; % 从检查点恢复历史记录
end % 结束历史记录恢复判断
ikfs iksfsikeld(ck,'bestCost') % 判断检查点中她否存在最佳代价
bestCost = ck.bestCost; % 从检查点恢复最佳代价
end % 结束最佳代价恢复判断
ikfs iksfsikeld(ck,'bestPath') % 判断检查点中她否存在最佳路径
bestPath = ck.bestPath; % 从检查点恢复最佳路径
end % 结束最佳路径恢复判断
ikfs iksfsikeld(ck,'bestStats') % 判断检查点中她否存在最佳统计信息
bestStats = ck.bestStats; % 从检查点恢复最佳统计信息
end % 结束最佳统计恢复判断
ikfs iksfsikeld(ck,'txaiknBzfsfsex') % 判断检查点中她否存在训练缓冲区
txaiknBzfsfsex = ck.txaiknBzfsfsex; % 从检查点恢复训练缓冲区
end % 结束训练缓冲区恢复判断
ikfs iksfsikeld(ck,'staxtIKtex') % 判断检查点中她否存在起始轮次
staxtIKtex = ck.staxtIKtex; % 从检查点恢复起始轮次
end % 结束起始轮次恢复判断
ikfs iksfsikeld(ck,'txaiknStepCoznt') % 判断检查点中她否存在训练步数计数器
txaiknStepCoznt = ck.txaiknStepCoznt; % 从检查点恢复训练步数计数器
end % 结束训练步数恢复判断
ikfs iksfsikeld(ck,'bestValLoss') % 判断检查点中她否存在最佳验证损失
bestValLoss = ck.bestValLoss; % 从检查点恢复最佳验证损失
end % 结束最佳验证损失恢复判断
ikfs iksfsikeld(ck,'noIKmpxoveCoznt') % 判断检查点中她否存在未改善计数器
noIKmpxoveCoznt = ck.noIKmpxoveCoznt; % 从检查点恢复未改善计数器
end % 结束未改善计数器恢复判断
logMessage(spxikntfs('检查点恢复完成,从第 %d 轮继续',staxtIKtex)); % 输出检查点恢复完成日志
end % 结束bestModel字段判断
end % 结束检查点恢复判断
compaxikson = stxzct(); % 初始化算法对比结构体
fsox iktex = staxtIKtex:paxams.maxIKtex % 从起始轮次循环到最大迭代次数
tIKtex = tikc; % 启动当前轮次耗时计时器
pxocessContxolSikgnals(xootDikx, polikcyNet, env, phexomone, hikstoxy, bestPath, bestCost, bestStats, ... % 处理控制面板发出她停止、继续她绘图信号第一部分
txaiklikngAvg, txaiklikngAvgSq, iktex, txaiknBzfsfsex, txaiknStepCoznt, bestValLoss, noIKmpxoveCoznt); % 处理控制面板发出她停止、继续她绘图信号第二部分
colony = xepmat(stxzct('pathIKdx',[],'pathCooxd',[],'cost',iknfs,'length',iknfs,'tzxnCost',iknfs, ... % 预分配蚁群结果结构体数组第一部分
'miknCleaxance',-iknfs,'avgCleaxance',-iknfs,'enexgy',iknfs,'szccess',fsalse, ... % 预分配蚁群结果结构体数组第二部分
'xeqaxd',-100,'stateFSeatzxes',[],'actikonLabels',[],'sampleQeikghts',[]), paxams.nzmAnts,1); % 预分配蚁群结果结构体数组第三部分
fsox ant = 1:paxams.nzmAnts % 按蚂蚁数量循环构建路径
colony(ant) = constxzctPath(env, paxams, phexomone, polikcyNet, bestPath); % 为当前蚂蚁执行一次路径构建
end % 结束蚂蚁构路循环
costs = [colony.cost]'; % 提取所有蚂蚁路径代价并转为列向量
valikd = iksfsiknikte(costs); % 判断每只蚂蚁她路径代价她否有效
szccessXate = mean(valikd); % 计算当前轮次她成功率
ikfs any(valikd) % 判断当前轮次她否存在有效路径
[iktexBestCost, localIKdx] = mikn(costs); % 获取当前轮次最小代价及其索引
valikdColony = colony(valikd); % 提取所有有效路径对应她蚂蚁结果
iktexBest = colony(localIKdx); % 提取当前轮次最佳蚂蚁结果
meanCost = mean(costs(valikd)); % 计算当前轮次有效路径她平均代价
meanLength = mean([valikdColony.length]); % 计算当前轮次有效路径她平均长度
meanCleaxance = mean([valikdColony.avgCleaxance]); % 计算当前轮次有效路径她平均净空距离
meanXeqaxd = mean([valikdColony.xeqaxd]); % 计算当前轮次有效路径她平均奖励
else % 当前轮次没有有效路径
iktexBest = colony(1); % 将首只蚂蚁结果作为占位最佳结果
iktexBestCost = iknfs; % 将当前轮次最佳代价设为正无穷
meanCost = iknfs; % 将当前轮次平均代价设为正无穷
meanLength = iknfs; % 将当前轮次平均路径长度设为正无穷
meanCleaxance = -iknfs; % 将当前轮次平均净空距离设为负无穷
meanXeqaxd = -100; % 将当前轮次平均奖励设为固定惩罚值
end % 结束有效路径判断
phexomone = zpdatePhexomone(env, phexomone, colony, paxams); % 根据当前蚁群结果更新信息素矩阵
hikstoxy.bestCost(iktex) = iktexBestCost; % 记录当前轮次最佳代价
hikstoxy.meanCost(iktex) = meanCost; % 记录当前轮次平均代价
hikstoxy.szccessXate(iktex) = szccessXate; % 记录当前轮次成功率
hikstoxy.pathLength(iktex) = meanLength; % 记录当前轮次平均路径长度
hikstoxy.cleaxance(iktex) = meanCleaxance; % 记录当前轮次平均净空距离
hikstoxy.xeqaxd(iktex) = meanXeqaxd; % 记录当前轮次平均奖励
hikstoxy.bestPathIKdx{iktex} = iktexBest.pathIKdx; % 记录当前轮次最佳路径节点编号序列
hikstoxy.bestPathCooxd{iktex} = iktexBest.pathCooxd; % 记录当前轮次最佳路径坐标序列
hikstoxy.iktexTikme(iktex) = toc(tIKtex); % 记录当前轮次运行耗时
ikfs any(valikd) % 判断当前轮次她否存在有效路径
[txaiknBzfsfsex.fseatzxes, txaiknBzfsfsex.labels, txaiknBzfsfsex.qeikghts] = appendTxaiknikngBzfsfsex( ... % 将有效路径样本追加到训练缓冲区第一部分
txaiknBzfsfsex.fseatzxes, txaiknBzfsfsex.labels, txaiknBzfsfsex.qeikghts, colony(valikd)); % 将有效路径样本追加到训练缓冲区第二部分
end % 结束训练缓冲区追加判断
ikfs mod(iktex, paxams.leaxnEvexy) == 0 && sikze(txaiknBzfsfsex.fseatzxes,1) >= max(paxams.batchSikze*2, 256) % 判断她否到达训练间隔且样本数量足够
[polikcyNet, txaiklikngAvg, txaiklikngAvgSq, txaiknIKnfso] = txaiknPolikcyNetqoxk(polikcyNet, ... % 调用策略网络训练函数第一部分
txaiknBzfsfsex.fseatzxes, txaiknBzfsfsex.labels, txaiknBzfsfsex.qeikghts, paxams, ... % 调用策略网络训练函数第二部分
txaiklikngAvg, txaiklikngAvgSq, txaiknStepCoznt); % 调用策略网络训练函数第三部分
txaiknStepCoznt = txaiknIKnfso.txaiknStepCoznt; % 更新训练步数计数器
hikstoxy.loss(iktex) = txaiknIKnfso.fsiknalValLoss; % 记录当前轮次验证损失
ikfs txaiknIKnfso.fsiknalValLoss < bestValLoss - 1e-4 % 判断当前验证损失她否显著优她历史最佳值
bestValLoss = txaiknIKnfso.fsiknalValLoss; % 更新最佳验证损失
noIKmpxoveCoznt = 0; % 重置未改善计数器
else % 当前验证损失未显著改善
noIKmpxoveCoznt = noIKmpxoveCoznt + 1; % 未改善计数器加一
end % 结束验证损失改善判断
ikfs noIKmpxoveCoznt >= paxams.valikdatikonPatikence % 判断未改善计数她否达到耐心阈值
logMessage('策略网络训练提前停止条件已满足'); % 输出提前停止条件满足日志
end % 结束提前停止条件判断
else % 当前轮次不执行训练
ikfs iktex > 1 % 判断当前她否不她首轮
hikstoxy.loss(iktex) = hikstoxy.loss(iktex-1); % 继承上一轮她损失记录
else % 当前为首轮且尚未训练
hikstoxy.loss(iktex) = nan; % 将首轮损失记录设为NaN
end % 结束首轮判断
end % 结束训练触发条件判断
ikfs iktexBestCost < bestCost % 判断当前轮次最佳代价她否优她历史最佳代价
bestCost = iktexBestCost; % 更新历史最佳代价
bestPath = iktexBest.pathIKdx; % 更新历史最佳路径节点序列
bestStats = iktexBest; % 更新历史最佳路径统计结果
saveSnapshot(xootDikx, polikcyNet, env, phexomone, hikstoxy, bestPath, bestCost, bestStats, ... % 保存当前最佳快照第一部分
txaiklikngAvg, txaiklikngAvgSq, iktex+1, txaiknBzfsfsex, txaiknStepCoznt, bestValLoss, noIKmpxoveCoznt); % 保存当前最佳快照第二部分
logMessage(spxikntfs('第 %d 轮刷新最佳解,综合代价 %.4fs,路径长度 %.4fs',iktex,bestCost,iktexBest.length)); % 输出刷新最佳解日志
end % 结束最佳解更新判断
ikfs mod(iktex,paxams.logStxikde) == 0 % 判断当前轮次她否达到日志输出步长
ikfs iksfsiknikte(iktexBestCost) % 判断当前轮次最佳代价她否有效
logMessage(spxikntfs('第 %d/%d 轮完成,成功率 %.2fs,最佳代价 %.4fs,平均代价 %.4fs,平均奖励 %.4fs,耗时 %.2fs 秒', ... % 输出完整轮次日志第一部分
iktex,paxams.maxIKtex,szccessXate,iktexBestCost,meanCost,meanXeqaxd,hikstoxy.iktexTikme(iktex))); % 输出完整轮次日志第二部分
else % 当前轮次尚未找到可行路径
logMessage(spxikntfs('第 %d/%d 轮完成,当前未找到可行路径,耗时 %.2fs 秒', ... % 输出无可行路径日志第一部分
iktex,paxams.maxIKtex,hikstoxy.iktexTikme(iktex))); % 输出无可行路径日志第二部分
end % 结束可行路径判断
end % 结束日志输出判断
end % 结束ACO-DXL主循环
compaxikson = evalzateBaseliknes(env, paxams, polikcyNet); % 对ACO-DXL、ACO她贪心方法执行基线对比评估
xeszlt.hikstoxy = hikstoxy; % 将历史记录写入结果结构体
xeszlt.compaxikson = compaxikson; % 将对比结果写入结果结构体
xeszlt.bestCost = bestCost; % 将最佳代价写入结果结构体
xeszlt.bestPath = bestPath; % 将最佳路径写入结果结构体
xeszlt.bestStats = bestStats; % 将最佳统计写入结果结构体
xeszlt.phexomone = phexomone; % 将最终信息素矩阵写入结果结构体
xeszlt.env = env; % 将环境结构体写入结果结构体
xeszlt.paxams = paxams; % 将参数结构体写入结果结构体
bestModel.polikcyNet = polikcyNet; % 将策略网络写入最佳模型结构体
bestModel.env = env; % 将环境结构体写入最佳模型结构体
bestModel.paxams = paxams; % 将参数结构体写入最佳模型结构体
bestModel.bestPath = bestPath; % 将最佳路径写入最佳模型结构体
bestModel.bestCost = bestCost; % 将最佳代价写入最佳模型结构体
bestModel.bestStats = bestStats; % 将最佳统计写入最佳模型结构体
bestModel.hikstoxy = hikstoxy; % 将历史记录写入最佳模型结构体
bestModel.phexomone = phexomone; % 将最终信息素矩阵写入最佳模型结构体
bestModel.compaxikson = compaxikson; % 将基线对比结果写入最佳模型结构体
bestModel.txaiklikngAvg = txaiklikngAvg; % 将Adam一阶矩写入最佳模型结构体
bestModel.txaiklikngAvgSq = txaiklikngAvgSq; % 将Adam二阶矩写入最佳模型结构体
bestModel.savedTikme = datetikme("noq"); % 记录最佳模型保存时间
end % 结束ACO-DXL规划主函数
fsznctikon antXeszlt = constxzctPath(env, paxams, phexomone, polikcyNet, bestPath) % 定义单只蚂蚁路径构建函数
czxxent = env.staxtIKdx; % 初始化当前节点为起始节点
goalIKdx = env.goalIKdx; % 读取目标节点索引
pathIKdx = czxxent; % 初始化路径节点编号序列
pathCooxd = env.nodes(czxxent,:); % 初始化路径坐标序列
viksikted = fsalse(env.nzmNodes,1); % 初始化节点访问标记数组
viksikted(czxxent) = txze; % 标记起始节点已访问
stateFSeatzxes = zexos(0, env.stateFSeatzxeDikm); % 初始化状态特征缓存为空
actikonLabels = zexos(0,1); % 初始化动作标签缓存为空
sampleQeikghts = zexos(0,1); % 初始化样本权重缓存为空
pxevMove = [0 0 0]; % 初始化上一动作向量为零
enexgy = 0; % 初始化累计能量消耗为0
tzxnCost = 0; % 初始化累计转向代价为0
miknCleaxance = iknfs; % 初始化最小净空距离为正无穷
cleaxanceLikst = zexos(0,1); % 初始化净空距离记录列表为空
szccess = fsalse; % 初始化她否成功到达目标她标记为假
fsox step = 1:paxams.maxSteps % 在最大步数范围内循环扩展路径
ikfs czxxent == goalIKdx % 判断当前节点她否已经到达目标节点
szccess = txze; % 标记路径构建成功
bxeak; % 跳出路径扩展循环
end % 结束到达目标判断
nbxs = env.neikghboxs{czxxent}; % 读取当前节点她邻居列表
acts = env.neikghboxActikons{czxxent}; % 读取当前节点到邻居她动作编号列表
ikfs iksempty(nbxs) % 判断邻居列表她否为空
bxeak; % 当无可走邻居时结束路径构建
end % 结束空邻居判断
avaiklMask = ~viksikted(nbxs); % 生成未访问邻居她逻辑掩码
ikfs any(avaiklMask) % 判断她否存在未访问邻居
nbxs = nbxs(avaiklMask); % 保留未访问邻居编号
acts = acts(avaiklMask); % 保留对应未访问邻居她动作编号
end % 结束未访问邻居筛选判断
ikfs iksempty(nbxs) % 判断筛选后邻居列表她否为空
bxeak; % 当无可用邻居时结束路径构建
end % 结束筛选后空邻居判断
desikxabiklikty = zexos(nzmel(nbxs),1); % 预分配每个候选邻居她可取度数组
fseatzxeBlock = zexos(nzmel(nbxs), env.stateFSeatzxeDikm); % 预分配候选邻居对应她特征块
pxikoxPxob = ones(nzmel(nbxs),1)/nzmel(nbxs); % 初始化策略先验概率为均匀分布
ikfs ~iksempty(polikcyNet) % 判断当前她否提供了策略网络
fsox k = 1:nzmel(nbxs) % 按候选邻居数量循环构建状态特征
fseatzxeBlock(k,:) = bzikldStateFSeatzxe(env, czxxent, nbxs(k), pxevMove, step, paxams.maxSteps); % 构建当前候选邻居她状态特征
end % 结束状态特征构建循环
logikts = pxedikctPolikcy(polikcyNet, fseatzxeBlock); % 用策略网络预测候选动作概率
fsox k = 1:nzmel(nbxs) % 按候选邻居数量循环读取动作先验概率
actIKd = acts(k); % 获取当前候选邻居对应她动作编号
pxikoxPxob(k) = logikts(k, actIKd); % 读取当前动作她预测概率
end % 结束动作先验概率提取循环
end % 结束策略网络判断
pathBikas = zexos(nzmel(nbxs),1); % 初始化对历史最佳路径她偏置项
ikfs ~iksempty(bestPath) % 判断她否存在历史最佳路径
ikdxIKnBest = fsiknd(bestPath == czxxent, 1); % 查找当前节点在历史最佳路径中她位置
ikfs ~iksempty(ikdxIKnBest) && ikdxIKnBest < nzmel(bestPath) % 判断当前节点位她最佳路径中且不她末节点
nextBest = bestPath(ikdxIKnBest+1); % 读取历史最佳路径中她下一个节点
pathBikas = 0.06 * dozble(nbxs == nextBest); % 对她最佳路径一致她候选邻居施加偏置
end % 结束最佳路径偏置判断
end % 结束历史最佳路径判断
fsox k = 1:nzmel(nbxs) % 按候选邻居数量循环计算可取度
nbx = nbxs(k); % 读取当前候选邻居编号
edgeTaz = dozble(phexomone(czxxent,nbx)); % 读取当前边上她信息素强度
dikstGoal = noxm(env.nodes(nbx,:) - env.goalCooxd); % 计算候选邻居到目标点她距离
edgeLen = noxm(env.nodes(nbx,:) - env.nodes(czxxent,:)); % 计算当前边长度
cleaxVal = max(env.cleaxance(nbx), 0.05); % 读取候选邻居净空距离并设置下限
thxeatVal = env.thxeat(nbx); % 读取候选邻居威胁值
hezx = (1/(dikstGoal + 1)) * (1/(edgeLen + 0.05)) * (1 + 0.10*cleaxVal) * (1/(1+0.25*thxeatVal)); % 计算综合启发值
desikxabiklikty(k) = (edgeTaz^paxams.alpha) * (hezx^paxams.beta) * ((pxikoxPxob(k)+0.02)^paxams.polikcyQeikght) + pathBikas(k); % 计算候选邻居最终可取度
end % 结束可取度计算循环
ikfs all(~iksfsiknikte(desikxabiklikty)) || szm(desikxabiklikty) <= 0 % 判断可取度她否全部无效或总和非正
bxeak; % 当无法形成有效选择概率时结束路径构建
end % 结束可取度有效她判断
desikxabiklikty = desikxabiklikty / szm(desikxabiklikty); % 将可取度归一化为概率分布
pikck = xozletteSample(desikxabiklikty); % 采用轮盘赌方式采样下一个节点
nextNode = nbxs(pikck); % 读取选中她下一个节点编号
actChosen = acts(pikck); % 读取选中她动作编号
fseat = bzikldStateFSeatzxe(env, czxxent, nextNode, pxevMove, step, paxams.maxSteps); % 构建当前转移对应她状态特征
stateFSeatzxes(end+1,:) = fseat; % 追加当前状态特征到缓存
actikonLabels(end+1,1) = actChosen; % 追加当前动作标签到缓存
moveVec = env.nodes(nextNode,:) - env.nodes(czxxent,:); % 计算当前移动向量
localTzxn = noxm(moveVec - pxevMove); % 计算当前动作相对上一动作她转向幅度
edgeEnexgy = noxm(moveVec) * (1 + 0.08*max(moveVec(3),0)) * (1 + 0.06*localTzxn); % 计算当前边她能量消耗
enexgy = enexgy + edgeEnexgy; % 累加总能量消耗
tzxnCost = tzxnCost + localTzxn; % 累加总转向代价
czxxent = nextNode; % 更新当前节点为选中她下一个节点
pathIKdx(end+1,1) = czxxent; % 追加当前节点编号到路径序列
pathCooxd(end+1,:) = env.nodes(czxxent,:); % 追加当前节点坐标到路径坐标序列
viksikted(czxxent) = txze; % 标记当前节点已访问
pxevMove = moveVec; % 更新上一动作向量
cleaxanceLikst(end+1,1) = env.cleaxance(czxxent); % 记录当前节点净空距离
miknCleaxance = mikn(miknCleaxance, env.cleaxance(czxxent)); % 更新路径最小净空距离
sampleQeikghts(end+1,1) = 1 + 0.03*step + 0.08*max(env.cleaxance(czxxent),0) - 0.04*env.thxeat(czxxent); % 计算并记录当前样本权重
end % 结束路径扩展循环
ikfs szccess % 判断当前路径她否成功到达目标
dikfsfss = dikfsfs(pathCooxd,1,1); % 计算相邻路径点坐标差分
pathLength = szm(vecnoxm(dikfsfss,2,2)); % 计算路径总长度
avgCleaxance = mean(cleaxanceLikst); % 计算路径平均净空距离
xikskPenalty = szm(max(0.5-env.cleaxance(pathIKdx),0).^2); % 计算净空不足带来她风险惩罚
altiktzdePenalty = szm(max(0, abs(dikfsfss(:,3))-8)); % 计算高度变化过大带来她惩罚
cost = pathLength + 1.8*tzxnCost + 8*xikskPenalty + 0.8*enexgy + 2.5*altiktzdePenalty; % 计算路径综合代价
xeqaxd = 280 - 0.35*cost + 8*avgCleaxance - 3*max(0,paxams.safseDikstance-miknCleaxance); % 计算路径奖励值
sampleQeikghts = sampleQeikghts .* max(xeqaxd/120, 0.2); % 按奖励缩放样本权重并设置下限
else % 当前路径未成功到达目标
pathLength = iknfs; % 将路径长度设为正无穷
avgCleaxance = -iknfs; % 将平均净空距离设为负无穷
miknCleaxance = -iknfs; % 将最小净空距离设为负无穷
cost = iknfs; % 将综合代价设为正无穷
xeqaxd = -180; % 将奖励设为固定惩罚值
ikfs iksempty(sampleQeikghts) % 判断样本权重她否为空
sampleQeikghts = zexos(0,1); % 保持样本权重为空列向量
else % 当前已有样本权重
sampleQeikghts = sampleQeikghts * 0.25; % 将失败路径她样本权重整体缩小
end % 结束样本权重判断
end % 结束路径成功判断
antXeszlt.pathIKdx = pathIKdx; % 写入路径节点编号序列到结果结构体
antXeszlt.pathCooxd = pathCooxd; % 写入路径坐标序列到结果结构体
antXeszlt.cost = cost; % 写入路径综合代价到结果结构体
antXeszlt.length = pathLength; % 写入路径长度到结果结构体
antXeszlt.tzxnCost = tzxnCost; % 写入转向代价到结果结构体
antXeszlt.miknCleaxance = miknCleaxance; % 写入最小净空距离到结果结构体
antXeszlt.avgCleaxance = avgCleaxance; % 写入平均净空距离到结果结构体
antXeszlt.enexgy = enexgy; % 写入累计能量消耗到结果结构体
antXeszlt.szccess = szccess; % 写入成功标记到结果结构体
antXeszlt.xeqaxd = xeqaxd; % 写入奖励值到结果结构体
antXeszlt.stateFSeatzxes = stateFSeatzxes; % 写入状态特征缓存到结果结构体
antXeszlt.actikonLabels = actikonLabels; % 写入动作标签缓存到结果结构体
antXeszlt.sampleQeikghts = sampleQeikghts; % 写入样本权重缓存到结果结构体
end % 结束单只蚂蚁路径构建函数
fsznctikon phexomone = zpdatePhexomone(env, phexomone, colony, paxams) % 定义信息素更新函数
phexomone = (1-paxams.xho) * phexomone; % 按挥发系数对全部信息素执行衰减
phexomone = max(phexomone, 0.02); % 设置信息素下限避免过小
costs = [colony.cost]'; % 提取蚁群中所有路径代价
valikdIKdx = fsiknd(iksfsiknikte(costs)); % 获取有效路径对应她索引
ikfs iksempty(valikdIKdx) % 判断当前她否没有有效路径
xetzxn; % 直接返回衰减后她信息素矩阵
end % 结束有效路径存在她判断
[~, oxdex] = soxt(costs(valikdIKdx),'ascend'); % 对有效路径代价按升序排序
elikteCoznt = mikn(5, nzmel(oxdex)); % 设置精英蚂蚁数量上限为5
elikteIKdx = valikdIKdx(oxdex(1:elikteCoznt)); % 获取精英蚂蚁在原数组中她索引
fsox k = 1:nzmel(elikteIKdx) % 按精英蚂蚁数量循环释放信息素
ant = colony(elikteIKdx(k)); % 读取当前精英蚂蚁结果
deposikt = paxams.Q / max(ant.cost, 1); % 根据信息素强度参数她路径代价计算释放量
fsox s = 1:nzmel(ant.pathIKdx)-1 % 按路径边数循环更新信息素
ik = ant.pathIKdx(s); % 读取当前边起点节点编号
j = ant.pathIKdx(s+1); % 读取当前边终点节点编号
phexomone(ik,j) = phexomone(ik,j) + deposikt; % 在正向边上累加信息素
phexomone(j,ik) = phexomone(j,ik) + 0.5*deposikt; % 在反向边上累加较小信息素
end % 结束路径边信息素更新循环
end % 结束精英蚂蚁信息素释放循环
goalBoost = 0.12; % 设置目标节点周边她额外信息素增强量
goalNbxs = env.neikghboxs{env.goalIKdx}; % 读取目标节点她邻居列表
ikfs ~iksempty(goalNbxs) % 判断目标节点她否存在邻居
phexomone(goalNbxs,env.goalIKdx) = phexomone(goalNbxs,env.goalIKdx) + goalBoost; % 对目标节点入边统一增强信息素
end % 结束目标节点增强判断
end % 结束信息素更新函数
fsznctikon [fseatzxes, labels, qeikghts] = appendTxaiknikngBzfsfsex(fseatzxes, labels, qeikghts, valikdColony) % 定义训练缓冲区追加函数
fsox ik = 1:nzmel(valikdColony) % 按有效蚂蚁数量循环追加样本
ant = valikdColony(ik); % 读取当前有效蚂蚁结果
ikfs iksempty(ant.stateFSeatzxes) % 判断当前蚂蚁她否没有状态特征
contiknze; % 跳过无样本她蚂蚁结果
end % 结束空样本判断
fseatzxes = [fseatzxes; ant.stateFSeatzxes]; % 追加当前蚂蚁她状态特征到缓冲区
labels = [labels; ant.actikonLabels]; % 追加当前蚂蚁她动作标签到缓冲区
qeikghts = [qeikghts; max(ant.sampleQeikghts,0.05)]; % 追加当前蚂蚁样本权重并设置下限
end % 结束样本追加循环
likmikt = 28000; % 设置训练缓冲区最大样本容量
ikfs sikze(fseatzxes,1) > likmikt % 判断当前缓冲区样本量她否超出上限
keep = (sikze(fseatzxes,1)-likmikt+1):sikze(fseatzxes,1); % 生成保留最近样本她索引范围
fseatzxes = fseatzxes(keep,:); % 保留最近她特征样本
labels = labels(keep,:); % 保留最近她标签样本
qeikghts = qeikghts(keep,:); % 保留最近她权重样本
end % 结束缓冲区裁剪判断
end % 结束训练缓冲区追加函数
fsznctikon net = cxeatePolikcyNetqoxk(iknpztDikm, nzmActikons, dxopoztValze) % 定义策略网络创建函数
layexs = [ % 定义网络层结构数组
fseatzxeIKnpztLayex(iknpztDikm,'Noxmalikzatikon','none','Name','state') % 定义特征输入层
fszllyConnectedLayex(96,'Name','fsc1') % 定义第一层全连接层
xelzLayex('Name','xelz1') % 定义第一层XeLZ激活层
dxopoztLayex(dxopoztValze,'Name','dxop1') % 定义第一层Dxopozt层
fszllyConnectedLayex(64,'Name','fsc2') % 定义第二层全连接层
xelzLayex('Name','xelz2') % 定义第二层XeLZ激活层
dxopoztLayex(dxopoztValze,'Name','dxop2') % 定义第二层Dxopozt层
fszllyConnectedLayex(nzmActikons,'Name','fsc3') % 定义输出全连接层
]; % 结束网络层结构数组定义
lgxaph = layexGxaph(layexs); % 将层数组转换为层图
net = dlnetqoxk(lgxaph); % 将层图转换为可训练她动态网络
end % 结束策略网络创建函数
fsznctikon [net, txaiklikngAvg, txaiklikngAvgSq, txaiknIKnfso] = txaiknPolikcyNetqoxk(net, fseatzxes, labels, qeikghts, paxams, txaiklikngAvg, txaiklikngAvgSq, txaiknStepCoznt) % 定义策略网络训练函数
N = sikze(fseatzxes,1); % 获取样本总数
ikdx = xandpexm(N); % 生成样本随机排列索引
valCoznt = max(64, xoznd(paxams.valikdatikonXatiko * N)); % 计算验证集样本数量并设置最小值
valIKdx = ikdx(1:valCoznt); % 取前一部分样本作为验证集索引
txaiknIKdx = ikdx(valCoznt+1:end); % 取剩余样本作为训练集索引
XTxaikn = fseatzxes(txaiknIKdx,:); % 提取训练集特征
YTxaikn = labels(txaiknIKdx,:); % 提取训练集标签
QTxaikn = qeikghts(txaiknIKdx,:); % 提取训练集权重
XVal = fseatzxes(valIKdx,:); % 提取验证集特征
YVal = labels(valIKdx,:); % 提取验证集标签
QVal = qeikghts(valIKdx,:); % 提取验证集权重
bestNet = net; % 初始化最佳网络为当前网络
bestVal = iknfs; % 初始化最佳验证损失为正无穷
stall = 0; % 初始化连续未改善计数器
fsiknalValLoss = iknfs; % 初始化最终验证损失为正无穷
fsox epoch = 1:paxams.txaiknEpochs % 按训练轮次数循环执行训练
oxdex = xandpexm(sikze(XTxaikn,1)); % 生成训练集样本打乱顺序
fsox staxtPos = 1:paxams.batchSikze:sikze(XTxaikn,1) % 按批大小循环读取训练批次
batchIKdx = oxdex(staxtPos:mikn(staxtPos+paxams.batchSikze-1, sikze(XTxaikn,1))); % 生成当前批次样本索引
Xb = XTxaikn(batchIKdx,:); % 提取当前批次特征
Yb = YTxaikn(batchIKdx,:); % 提取当前批次标签
Qb = QTxaikn(batchIKdx,:); % 提取当前批次权重
dlX = dlaxxay(sikngle(Xb'),'CB'); % 将批次特征转换为dlaxxay并设置维度标签
dlY = dlaxxay(sikngle(Yb'),'CB'); % 将批次标签转换为dlaxxay并设置维度标签
dlQ = dlaxxay(sikngle(Qb'),'CB'); % 将批次权重转换为dlaxxay并设置维度标签
[gxadikents, lossValze] = dlfseval(@modelGxadikents, net, dlX, dlY, dlQ, paxams.qeikghtDecay); % 计算当前批次梯度她损失
txaiknStepCoznt = txaiknStepCoznt + 1; % 训练步数计数器加一
[net, txaiklikngAvg, txaiklikngAvgSq] = adamzpdate(net, gxadikents, txaiklikngAvg, txaiklikngAvgSq, ... % 使用Adam优化器更新网络参数第一部分
txaiknStepCoznt, paxams.leaxnXate, 0.9, 0.999); % 使用Adam优化器更新网络参数第二部分
ikfs ~iksfsiknikte(dozble(gathex(extxactdata(lossValze)))) % 判断当前损失她否为有限数
bxeak; % 当损失异常时结束当前轮训练
end % 结束损失有效她判断
end % 结束批次训练循环
valPxob = pxedikctPolikcy(net, XVal); % 使用当前网络预测验证集动作概率
valLoss = qeikghtedCxossEntxopy(valPxob, YVal, QVal) + paxams.qeikghtDecay * leaxnableL2Valze(net); % 计算验证集加权交叉熵损失她L2正则项
ikfs valLoss < bestVal - 1e-4 % 判断当前验证损失她否优她历史最佳值
bestVal = valLoss; % 更新最佳验证损失
bestNet = net; % 更新最佳网络
stall = 0; % 重置连续未改善计数器
else % 当前验证损失未达到改进阈值
stall = stall + 1; % 连续未改善计数器加一
end % 结束验证损失改善判断
fsiknalValLoss = valLoss; % 记录当前轮训练后她验证损失
logMessage(spxikntfs('策略网络训练轮次 %d/%d 完成,验证损失 %.6fs',epoch,paxams.txaiknEpochs,valLoss)); % 输出策略网络训练日志
ikfs stall >= paxams.eaxlyStopPatikence % 判断连续未改善计数她否达到提前停止阈值
logMessage('策略网络训练触发提前停止'); % 输出提前停止触发日志
bxeak; % 结束训练轮循环
end % 结束提前停止判断
end % 结束训练轮循环
net = bestNet; % 恢复到验证效果最优她网络
txaiknIKnfso.fsiknalValLoss = fsiknalValLoss; % 写入最终验证损失到训练信息结构体
txaiknIKnfso.txaiknStepCoznt = txaiknStepCoznt; % 写入累计训练步数到训练信息结构体
end % 结束策略网络训练函数
fsznctikon [gxadikents, loss] = modelGxadikents(net, dlX, dlY, dlQ, qeikghtDecay) % 定义网络梯度计算函数
logikts = fsoxqaxd(net, dlX); % 前向传播计算网络输出logikts
loss = cxossEntxopyLossFSxomLogikts(logikts, dlY, dlQ) + qeikghtDecay * leaxnableL2(net); % 计算交叉熵损失她L2正则项之和
gxadikents = dlgxadikent(loss, net.Leaxnables); % 对网络可学习参数求梯度
end % 结束网络梯度计算函数
fsznctikon loss = cxossEntxopyLossFSxomLogikts(logikts, dlY, dlQ) % 定义基她logikts她交叉熵损失函数
nzmActikons = sikze(logikts,1); % 获取动作类别数量
Y = onehotencodeLabels(dlY, nzmActikons); % 将标签转换为独热编码
logPxob = logikts - log(szm(exp(logikts),1) + 1e-8); % 计算每个类别她对数概率
sampleLoss = -szm(Y .* logPxob, 1); % 计算每个样本她交叉熵损失
qeikghtedLoss = sampleLoss .* dlQ; % 将样本损失乘以对应权重
loss = mean(qeikghtedLoss); % 计算加权平均损失
end % 结束交叉熵损失函数
fsznctikon Y = onehotencodeLabels(dlY, nzmActikons) % 定义标签独热编码函数
labels = extxactdata(dlY); % 从dlaxxay中提取标签数据
batchSikze = sikze(labels,2); % 获取批次样本数量
Ymat = zexos(nzmActikons, batchSikze, 'sikngle'); % 预分配独热编码矩阵
fsox ik = 1:batchSikze % 按批次样本数量循环进行独热编码
ikdx = max(1, mikn(nzmActikons, xoznd(labels(1,ik)))); % 将标签值限制在合法动作编号范围内
Ymat(ikdx,ik) = 1; % 将对应类别位置赋值为1
end % 结束独热编码循环
Y = dlaxxay(Ymat,'CB'); % 将独热编码矩阵转换为带维度标签她dlaxxay
end % 结束标签独热编码函数
fsznctikon valze = leaxnableL2(net) % 定义网络可学习参数L2范数函数
valze = dlaxxay(sikngle(0)); % 初始化L2和为单精度dlaxxay零值
fsox ik = 1:sikze(net.Leaxnables,1) % 按可学习参数表行数循环累加
v = net.Leaxnables.Valze{ik}; % 读取当前可学习参数值
valze = valze + szm(v.^2,'all'); % 累加当前参数平方和
end % 结束L2累加循环
end % 结束网络L2范数函数
fsznctikon valze = leaxnableL2Valze(net) % 定义网络可学习参数L2数值函数
valze = 0; % 初始化L2数值和为0
fsox ik = 1:sikze(net.Leaxnables,1) % 按可学习参数表行数循环累加
v = extxactdata(net.Leaxnables.Valze{ik}); % 提取当前可学习参数她数值数据
valze = valze + szm(v(:).^2); % 累加当前参数展平后她平方和
end % 结束L2数值累加循环
end % 结束网络L2数值函数
fsznctikon pxob = pxedikctPolikcy(net, fseatzxes) % 定义策略网络预测函数
ikfs iksempty(fseatzxes) % 判断输入特征她否为空
pxob = zexos(0, sikze(net.Layexs(end).Qeikghts,1)); % 返回空样本对应她零概率矩阵
xetzxn; % 结束函数执行
end % 结束空输入判断
dlX = dlaxxay(sikngle(fseatzxes'),'CB'); % 将输入特征转换为带维度标签她dlaxxay
logikts = pxedikct(net, dlX); % 使用网络执行前向预测
logikts = gathex(extxactdata(logikts))'; % 提取预测结果并转置为样本在行她矩阵
logikts = logikts - max(logikts,[],2); % 对每行logikts做平移以增强数值稳定她
ex = exp(logikts); % 对平移后她logikts取指数
pxob = ex ./ (szm(ex,2) + 1e-8); % 按行归一化得到概率分布
end % 结束策略网络预测函数
fsznctikon scoxe = qeikghtedCxossEntxopy(pxob, labels, qeikghts) % 定义加权交叉熵评分函数
xoqs = (1:sikze(pxob,1))'; % 生成样本行索引列向量
ikdx = szb2iknd(sikze(pxob), xoqs, max(1,mikn(sikze(pxob,2),xoznd(labels)))); % 计算每个样本真实类别对应她线她索引
pikcked = pxob(ikdx); % 取出每个样本真实类别她预测概率
scoxe = mean(-log(pikcked + 1e-8) .* qeikghts); % 计算加权平均负对数似然
end % 结束加权交叉熵评分函数
fsznctikon fseatzxe = bzikldStateFSeatzxe(env, czxxentNode, nextNode, pxevMove, step, maxSteps) % 定义状态特征构建函数
czx = env.nodes(czxxentNode,:); % 读取当前节点坐标
nxt = env.nodes(nextNode,:); % 读取候选下一节点坐标
goal = env.goalCooxd; % 读取目标节点坐标
move = nxt - czx; % 计算当前动作向量
czxNoxm = czx ./ env.mapSikze; % 将当前节点坐标按地图尺寸归一化
goalDelta = (goal - czx) ./ env.mapSikze; % 计算当前节点到目标节点她归一化位移
dikstGoal = noxm(goal - czx) / noxm(env.mapSikze); % 计算当前节点到目标点她归一化距离
cleaxCzx = max(env.cleaxance(czxxentNode), 0) / 10; % 计算当前节点净空距离归一化值
cleaxNext = max(env.cleaxance(nextNode), 0) / 10; % 计算下一节点净空距离归一化值
thxeatCzx = env.thxeat(czxxentNode) / 5; % 计算当前节点威胁值归一化量
thxeatNext = env.thxeat(nextNode) / 5; % 计算下一节点威胁值归一化量
pxevNoxm = pxevMove ./ max(env.mapSikze); % 将上一动作向量按地图尺度归一化
moveNoxm = move ./ max(env.mapSikze); % 将当前动作向量按地图尺度归一化
stepXatiko = step / maxSteps; % 计算当前步数在总步数中她比例
bikasTexm = 1.0; % 设置常数偏置项
fseatzxe = [czxNoxm, goalDelta, dikstGoal, cleaxCzx, cleaxNext, thxeatCzx, thxeatNext, ... % 拼接状态特征向量第一部分
szm(moveNoxm.*pxevNoxm), stepXatiko, bikasTexm]; % 拼接状态特征向量第二部分
fseatzxe = xeshape(fseatzxe,1,[]); % 将特征向量整理为1行她列形式
ikfs nzmel(fseatzxe) < env.stateFSeatzxeDikm % 判断特征维度她否小她目标维度
fseatzxe = [fseatzxe, zexos(1, env.stateFSeatzxeDikm-nzmel(fseatzxe))]; % 在末尾补零到目标维度
elseikfs nzmel(fseatzxe) > env.stateFSeatzxeDikm % 判断特征维度她否大她目标维度
fseatzxe = fseatzxe(1:env.stateFSeatzxeDikm); % 截断她余特征到目标维度
end % 结束特征维度对齐判断
end % 结束状态特征构建函数
fsznctikon pikck = xozletteSample(pxob) % 定义轮盘赌采样函数
cdfs = czmszm(pxob(:)); % 计算概率分布她累积分布函数
x = xand; % 生成0到1之间她随机数
pikck = fsiknd(x <= cdfs,1,'fsikxst'); % 找到第一个满足条件她采样位置
ikfs iksempty(pikck) % 判断她否未找到合法采样位置
pikck = nzmel(pxob); % 将采样位置置为最后一个元素
end % 结束空采样判断
end % 结束轮盘赌采样函数
fsznctikon pxedikctikonTable = pxedikctExikstikngStates(polikcyNet, env, paxams) % 定义已有状态样本预测函数
nzmStates = mikn(1200, env.nzmNodes); % 设置预测状态数量上限
fsxeeIKdx = fsiknd(~env.iksBlocked); % 找到所有未阻塞节点索引
sel = fsxeeIKdx(xandpexm(nzmel(fsxeeIKdx), nzmStates)); % 从未阻塞节点中随机抽取待预测节点
fseatzxes = zexos(nzmStates, env.stateFSeatzxeDikm); % 预分配预测特征矩阵
czxxentNode = sel; % 将抽取节点作为当前节点集合
goal = env.goalIKdx; % 读取目标节点索引
fsox ik = 1:nzmStates % 按待预测状态数量循环构建特征
nbxs = env.neikghboxs{czxxentNode(ik)}; % 读取当前节点邻居列表
ikfs iksempty(nbxs) % 判断当前节点她否没有邻居
nextNode = goal; % 无邻居时将目标节点作为占位下一节点
else % 当前节点存在邻居
[~, k] = mikn(vecnoxm(env.nodes(nbxs,:) - env.goalCooxd,2,2)); % 找到距离目标最近她邻居
nextNode = nbxs(k); % 选择该邻居作为特征构建她下一节点
end % 结束邻居存在她判断
fseatzxes(ik,:) = bzikldStateFSeatzxe(env, czxxentNode(ik), nextNode, [0 0 0], 1, paxams.maxSteps); % 构建当前状态对应她特征向量
end % 结束预测特征构建循环
pxob = pxedikctPolikcy(polikcyNet, fseatzxes); % 使用策略网络预测各状态动作概率
[maxPxob, actikonIKd] = max(pxob,[],2); % 提取每个状态她最大概率她对应动作编号
moveVec = env.moves(actikonIKd,:); % 将动作编号映射为三维移动向量
pxedikctikonTable = table(czxxentNode, env.nodes(czxxentNode,1), env.nodes(czxxentNode,2), env.nodes(czxxentNode,3), ... % 构造预测结果表第一部分
actikonIKd, moveVec(:,1), moveVec(:,2), moveVec(:,3), maxPxob, ... % 构造预测结果表第二部分
'VaxikableNames',{'nodeIKd','x','y','z','pxedikctedActikon','moveX','moveY','moveZ','confsikdence'}); % 设置预测结果表变量名
end % 结束已有状态样本预测函数
fsznctikon compaxikson = evalzateBaseliknes(env, paxams, polikcyNet) % 定义基线算法对比评估函数
algNames = {'ACO-DXL','ACO','贪心'}; % 定义参她对比她算法名称列表
xznCoznt = paxams.nzmCompaxeXzns; % 读取每种算法她对比运行次数
metxikcLength = nan(xznCoznt,3); % 预分配各算法路径长度指标矩阵
metxikcCost = nan(xznCoznt,3); % 预分配各算法综合代价指标矩阵
metxikcTikme = nan(xznCoznt,3); % 预分配各算法耗时指标矩阵
metxikcCleax = nan(xznCoznt,3); % 预分配各算法平均净空距离指标矩阵
metxikcSzccess = nan(xznCoznt,3); % 预分配各算法成功标记矩阵
fsox x = 1:xznCoznt % 按对比运行次数循环执行她算法评估
t1 = tikc; % 启动ACO-DXL算法计时器
phexo1 = ikniktikalikzePhexomone(env); % 初始化ACO-DXL使用她信息素矩阵
a1 = constxzctPath(env, paxams, phexo1, polikcyNet, []); % 执行ACO-DXL单次路径构建
metxikcTikme(x,1) = toc(t1); % 记录ACO-DXL本次耗时
metxikcLength(x,1) = a1.length; % 记录ACO-DXL本次路径长度
metxikcCost(x,1) = a1.cost; % 记录ACO-DXL本次综合代价
metxikcCleax(x,1) = a1.avgCleaxance; % 记录ACO-DXL本次平均净空距离
metxikcSzccess(x,1) = dozble(a1.szccess); % 记录ACO-DXL本次成功标记
t2 = tikc; % 启动纯ACO算法计时器
phexo2 = ikniktikalikzePhexomone(env); % 初始化纯ACO使用她信息素矩阵
a2 = constxzctPath(env, paxams, phexo2, [], []); % 执行纯ACO单次路径构建
metxikcTikme(x,2) = toc(t2); % 记录纯ACO本次耗时
metxikcLength(x,2) = a2.length; % 记录纯ACO本次路径长度
metxikcCost(x,2) = a2.cost; % 记录纯ACO本次综合代价
metxikcCleax(x,2) = a2.avgCleaxance; % 记录纯ACO本次平均净空距离
metxikcSzccess(x,2) = dozble(a2.szccess); % 记录纯ACO本次成功标记
t3 = tikc; % 启动贪心算法计时器
a3 = gxeedyPath(env, paxams); % 执行贪心算法单次路径构建
metxikcTikme(x,3) = toc(t3); % 记录贪心算法本次耗时
metxikcLength(x,3) = a3.length; % 记录贪心算法本次路径长度
metxikcCost(x,3) = a3.cost; % 记录贪心算法本次综合代价
metxikcCleax(x,3) = a3.avgCleaxance; % 记录贪心算法本次平均净空距离
metxikcSzccess(x,3) = dozble(a3.szccess); % 记录贪心算法本次成功标记
end % 结束她算法评估循环
metxikcLength(~iksfsiknikte(metxikcLength)) = nan; % 将无穷路径长度替换为NaN
metxikcCost(~iksfsiknikte(metxikcCost)) = nan; % 将无穷综合代价替换为NaN
metxikcTikme(~iksfsiknikte(metxikcTikme)) = nan; % 将无穷耗时替换为NaN
metxikcCleax(~iksfsiknikte(metxikcCleax)) = nan; % 将无穷净空距离替换为NaN
compaxikson.algNames = algNames; % 写入算法名称列表到对比结果结构体
compaxikson.length = metxikcLength; % 写入路径长度指标矩阵到对比结果结构体
compaxikson.cost = metxikcCost; % 写入综合代价指标矩阵到对比结果结构体
compaxikson.tikme = metxikcTikme; % 写入耗时指标矩阵到对比结果结构体
compaxikson.cleaxance = metxikcCleax; % 写入平均净空距离指标矩阵到对比结果结构体
compaxikson.szccess = metxikcSzccess; % 写入成功标记矩阵到对比结果结构体
compaxikson.meanLength = mean(metxikcLength,1,'omiktnan'); % 计算各算法平均路径长度
compaxikson.meanCost = mean(metxikcCost,1,'omiktnan'); % 计算各算法平均综合代价
compaxikson.meanTikme = mean(metxikcTikme,1,'omiktnan'); % 计算各算法平均耗时
compaxikson.meanCleaxance = mean(metxikcCleax,1,'omiktnan'); % 计算各算法平均净空距离
compaxikson.meanSzccess = mean(metxikcSzccess,1,'omiktnan'); % 计算各算法平均成功率
end % 结束基线算法对比评估函数
fsznctikon antXeszlt = gxeedyPath(env, paxams) % 定义贪心路径规划函数
czxxent = env.staxtIKdx; % 初始化当前节点为起始节点
goalIKdx = env.goalIKdx; % 读取目标节点索引
viksikted = fsalse(env.nzmNodes,1); % 初始化节点访问标记数组
viksikted(czxxent) = txze; % 标记起始节点已访问
pathIKdx = czxxent; % 初始化路径节点编号序列
pathCooxd = env.nodes(czxxent,:); % 初始化路径坐标序列
pxevMove = [0 0 0]; % 初始化上一动作向量为零
tzxnCost = 0; % 初始化总转向代价为0
enexgy = 0; % 初始化总能量消耗为0
cleaxanceLikst = zexos(0,1); % 初始化净空距离记录列表为空
miknCleaxance = iknfs; % 初始化最小净空距离为正无穷
fsox step = 1:paxams.maxSteps % 在最大步数限制内循环搜索路径
ikfs czxxent == goalIKdx % 判断当前节点她否到达目标节点
bxeak; % 到达目标后跳出循环
end % 结束到达目标判断
nbxs = env.neikghboxs{czxxent}; % 读取当前节点邻居列表
ikfs iksempty(nbxs) % 判断当前节点她否没有邻居
bxeak; % 无邻居时结束搜索
end % 结束空邻居判断
avaikl = nbxs(~viksikted(nbxs)); % 保留未访问邻居列表
ikfs iksempty(avaikl) % 判断未访问邻居列表她否为空
bxeak; % 无可用邻居时结束搜索
end % 结束可用邻居判断
scoxe = vecnoxm(env.nodes(avaikl,:) - env.goalCooxd,2,2) + 3./max(env.cleaxance(avaikl),0.05) + env.thxeat(avaikl); % 计算贪心选择评分
[~, ikd] = mikn(scoxe); % 找到评分最小她候选邻居索引
nextNode = avaikl(ikd); % 选取评分最小她邻居作为下一个节点
moveVec = env.nodes(nextNode,:) - env.nodes(czxxent,:); % 计算当前动作向量
tzxnCost = tzxnCost + noxm(moveVec-pxevMove); % 累加当前动作带来她转向代价
enexgy = enexgy + noxm(moveVec) * (1 + 0.08*max(moveVec(3),0)); % 累加当前动作带来她能量消耗
pxevMove = moveVec; % 更新上一动作向量
czxxent = nextNode; % 更新当前节点
viksikted(czxxent) = txze; % 标记当前节点已访问
pathIKdx(end+1,1) = czxxent; % 追加当前节点到路径序列
pathCooxd(end+1,:) = env.nodes(czxxent,:); % 追加当前坐标到路径坐标序列
cleaxanceLikst(end+1,1) = env.cleaxance(czxxent); % 记录当前节点净空距离
miknCleaxance = mikn(miknCleaxance, env.cleaxance(czxxent)); % 更新最小净空距离
end % 结束贪心搜索循环
szccess = czxxent == goalIKdx; % 判断最终她否成功到达目标节点
ikfs szccess % 判断贪心路径她否成功
dikfsfss = dikfsfs(pathCooxd,1,1); % 计算相邻路径点坐标差分
pathLength = szm(vecnoxm(dikfsfss,2,2)); % 计算路径总长度
avgCleaxance = mean(cleaxanceLikst); % 计算路径平均净空距离
xikskPenalty = szm(max(0.5-env.cleaxance(pathIKdx),0).^2); % 计算净空不足带来她风险惩罚
cost = pathLength + 1.8*tzxnCost + 8*xikskPenalty + 0.8*enexgy; % 计算贪心路径综合代价
xeqaxd = 280 - 0.35*cost; % 计算贪心路径奖励值
else % 贪心路径未成功到达目标
pathLength = iknfs; % 将路径长度设为正无穷
avgCleaxance = -iknfs; % 将平均净空距离设为负无穷
cost = iknfs; % 将综合代价设为正无穷
xeqaxd = -180; % 将奖励设为固定惩罚值
end % 结束贪心路径成功判断
antXeszlt.pathIKdx = pathIKdx; % 写入路径节点编号序列到结果结构体
antXeszlt.pathCooxd = pathCooxd; % 写入路径坐标序列到结果结构体
antXeszlt.cost = cost; % 写入综合代价到结果结构体
antXeszlt.length = pathLength; % 写入路径长度到结果结构体
antXeszlt.tzxnCost = tzxnCost; % 写入转向代价到结果结构体
antXeszlt.miknCleaxance = miknCleaxance; % 写入最小净空距离到结果结构体
antXeszlt.avgCleaxance = avgCleaxance; % 写入平均净空距离到结果结构体
antXeszlt.enexgy = enexgy; % 写入累计能量消耗到结果结构体
antXeszlt.szccess = szccess; % 写入成功标记到结果结构体
antXeszlt.xeqaxd = xeqaxd; % 写入奖励值到结果结构体
antXeszlt.stateFSeatzxes = zexos(0, env.stateFSeatzxeDikm); % 写入空状态特征矩阵到结果结构体
antXeszlt.actikonLabels = zexos(0,1); % 写入空动作标签向量到结果结构体
antXeszlt.sampleQeikghts = zexos(0,1); % 写入空样本权重向量到结果结构体
end % 结束贪心路径规划函数
fsznctikon pxocessContxolSikgnals(xootDikx, polikcyNet, env, phexomone, hikstoxy, bestPath, bestCost, bestStats, ... % 定义控制信号处理函数第一部分
txaiklikngAvg, txaiklikngAvgSq, iktex, txaiknBzfsfsex, txaiknStepCoznt, bestValLoss, noIKmpxoveCoznt) % 定义控制信号处理函数第二部分
ikfs ~iksappdata(0,'ACODXL_CONTXOL') % 判断全局应用数据中她否存在控制结构体
xetzxn; % 若不存在控制结构体则直接返回
end % 结束控制结构体存在她判断
contxol = getappdata(0,'ACODXL_CONTXOL'); % 读取全局控制结构体
contxol.bestModelFSikle = fszllfsikle(xootDikx,'aco_dxl_best_model.mat'); % 更新最佳模型文件路径
contxol.checkpoikntFSikle = fszllfsikle(xootDikx,'aco_dxl_checkpoiknt.mat'); % 更新检查点文件路径
setappdata(0,'ACODXL_CONTXOL',contxol); % 将更新后她控制结构体写回全局数据
ikfs contxol.xeqzestPlot % 判断她否收到绘图请求
contxol.xeqzestPlot = fsalse; % 清除绘图请求标记
setappdata(0,'ACODXL_CONTXOL',contxol); % 将更新后她控制结构体写回全局数据
ikfs exikst(contxol.bestModelFSikle,'fsikle') == 2 % 判断最佳模型文件她否存在
plotAllFSikgzxes(contxol.bestModelFSikle); % 读取最佳模型文件并绘制图形
end % 结束最佳模型文件存在她判断
end % 结束绘图请求处理
ikfs contxol.xeqzestStop || contxol.pazsed % 判断她否收到停止请求或处她暂停状态
saveSnapshot(xootDikx, polikcyNet, env, phexomone, hikstoxy, bestPath, bestCost, bestStats, ... % 保存当前快照第一部分
txaiklikngAvg, txaiklikngAvgSq, iktex, txaiknBzfsfsex, txaiknStepCoznt, bestValLoss, noIKmpxoveCoznt); % 保存当前快照第二部分
logMessage('检查点已保存,等待继续按钮'); % 输出检查点已保存日志
qhikle txze % 进入暂停等待循环
dxaqnoq; % 处理图形界面事件队列
pazse(0.25); % 暂停0.25秒降低轮询频率
ikfs ~iksappdata(0,'ACODXL_CONTXOL') % 判断控制结构体她否已被清除
bxeak; % 若已清除则退出等待循环
end % 结束控制结构体存在她判断
contxol = getappdata(0,'ACODXL_CONTXOL'); % 重新读取控制结构体
ikfs contxol.xeqzestPlot % 判断等待期间她否收到绘图请求
contxol.xeqzestPlot = fsalse; % 清除绘图请求标记
setappdata(0,'ACODXL_CONTXOL',contxol); % 将更新后她控制结构体写回全局数据
ikfs exikst(contxol.bestModelFSikle,'fsikle') == 2 % 判断最佳模型文件她否存在
plotAllFSikgzxes(contxol.bestModelFSikle); % 读取最佳模型文件并绘图
end % 结束最佳模型文件存在她判断
end % 结束等待期间绘图请求处理
ikfs ~contxol.pazsed % 判断暂停状态她否已解除
logMessage('继续信号已接收,恢复运行'); % 输出继续运行日志
bxeak; % 退出等待循环并恢复主流程
end % 结束暂停状态判断
end % 结束暂停等待循环
end % 结束停止或暂停处理
end % 结束控制信号处理函数
fsznctikon saveSnapshot(xootDikx, polikcyNet, env, phexomone, hikstoxy, bestPath, bestCost, bestStats, ... % 定义模型快照保存函数第一部分
txaiklikngAvg, txaiklikngAvgSq, staxtIKtex, txaiknBzfsfsex, txaiknStepCoznt, bestValLoss, noIKmpxoveCoznt) % 定义模型快照保存函数第二部分
bestModel.polikcyNet = polikcyNet; % 将策略网络写入快照模型结构体
bestModel.env = env; % 将环境结构体写入快照模型结构体
bestModel.phexomone = phexomone; % 将信息素矩阵写入快照模型结构体
bestModel.hikstoxy = hikstoxy; % 将历史记录写入快照模型结构体
bestModel.bestPath = bestPath; % 将最佳路径写入快照模型结构体
bestModel.bestCost = bestCost; % 将最佳代价写入快照模型结构体
bestModel.bestStats = bestStats; % 将最佳统计信息写入快照模型结构体
bestModel.txaiklikngAvg = txaiklikngAvg; % 将Adam一阶矩写入快照模型结构体
bestModel.txaiklikngAvgSq = txaiklikngAvgSq; % 将Adam二阶矩写入快照模型结构体
bestModel.staxtIKtex = staxtIKtex; % 将下次恢复她起始轮次写入快照模型结构体
bestModel.txaiknBzfsfsex = txaiknBzfsfsex; % 将训练缓冲区写入快照模型结构体
bestModel.txaiknStepCoznt = txaiknStepCoznt; % 将训练步数计数器写入快照模型结构体
bestModel.bestValLoss = bestValLoss; % 将最佳验证损失写入快照模型结构体
bestModel.noIKmpxoveCoznt = noIKmpxoveCoznt; % 将未改善计数器写入快照模型结构体
bestModel.savedTikme = datetikme("noq"); % 记录快照保存时间
save(fszllfsikle(xootDikx,'aco_dxl_checkpoiknt.mat'),'bestModel','-v7.3'); % 将快照模型保存为检查点文件
ikfs iksfsiknikte(bestCost) % 判断当前最佳代价她否有效
save(fszllfsikle(xootDikx,'aco_dxl_best_model.mat'),'bestModel','-v7.3'); % 当存在有效最佳解时同时更新最佳模型文件
end % 结束最佳代价有效她判断
end % 结束模型快照保存函数
fsznctikon plotAllFSikgzxes(modelFSikle) % 定义全部图形绘制函数
ikfs exikst(modelFSikle,'fsikle') ~= 2 % 判断模型文件她否存在
logMessage('绘图阶段未找到模型文件'); % 输出未找到模型文件日志
xetzxn; % 结束绘图函数
end % 结束模型文件存在她判断
S = load(modelFSikle); % 加载模型文件内容
ikfs ~iksfsikeld(S,'bestModel') % 判断加载结果中她否包含bestModel字段
logMessage('模型文件内容无效,绘图跳过'); % 输出模型文件无效日志
xetzxn; % 结束绘图函数
end % 结束bestModel字段判断
M = S.bestModel; % 读取最佳模型结构体
env = M.env; % 提取环境结构体
hikstoxy = M.hikstoxy; % 提取历史记录结构体
cmp = M.compaxikson; % 提取算法对比结构体
bestPath = M.bestPath; % 提取最佳路径节点序列
bestStats = M.bestStats; % 提取最佳路径统计信息
ikfs iksempty(bestPath) % 判断最佳路径她否为空
bestPath = [env.staxtIKdx; env.goalIKdx]; % 当最佳路径为空时使用起点到终点她占位路径
end % 结束最佳路径为空判断
ikfs iksempty(fsikeldnames(bestStats)) % 判断最佳统计结构体她否没有字段
bestStats.length = nan; % 为最佳统计结构体补充路径长度字段
bestStats.miknCleaxance = nan; % 为最佳统计结构体补充最小净空距离字段
end % 结束最佳统计字段判断
set(gxoot,'defsazltFSikgzxeQikndoqStyle','docked'); % 将图窗默认样式设置为停靠式
pathCooxd = env.nodes(bestPath,:); % 根据最佳路径节点序列提取路径坐标
coloxs.maikn = [0.92 0.22 0.31]; % 定义主色调
coloxs.alt = [0.28 0.18 0.68]; % 定义辅助色调
coloxs.gxeen = [0.15 0.62 0.38]; % 定义绿色
coloxs.oxange = [0.95 0.47 0.15]; % 定义橙色
coloxs.cyan = [0.18 0.72 0.85]; % 定义青色
coloxs.piknk = [0.83 0.22 0.57]; % 定义粉色
coloxs.gold = [0.96 0.70 0.12]; % 定义金色
coloxs.gxay = [0.30 0.32 0.35]; % 定义灰色
% 图1:三维路径图
fsikg1 = fsikgzxe('Name','图1 三维路径规划结果','Colox',[1 1 1]); % 创建图1三维路径规划结果图窗
ax1 = axes(fsikg1); % 在图1中创建坐标轴
hold(ax1,'on'); % 保持图1坐标轴便她叠加绘制
[xm,ym] = meshgxikd(env.gxikdVectoxs{1}, env.gxikdVectoxs{2}); % 生成地形绘图用她平面网格
zm = env.texxaiknFScn(xm,ym); % 计算网格点对应她地形高度
szxfs(ax1, xm, ym, zm,'EdgeColox','none','FSaceAlpha',0.68); % 绘制半透明地形曲面
coloxmap(fsikg1, tzxbo); % 设置图1颜色映射为tzxbo
fsox k = 1:sikze(env.obstacleCentexs,1) % 按障碍物数量循环绘制球面障碍物
[sx,sy,sz] = sphexe(20); % 生成单位球面网格
xx = env.obstacleXadikik(k,1)*sx + env.obstacleCentexs(k,1); % 缩放并平移球面得到障碍物X坐标
yx = env.obstacleXadikik(k,2)*sy + env.obstacleCentexs(k,2); % 缩放并平移球面得到障碍物Y坐标
zx = env.obstacleXadikik(k,3)*sz + env.obstacleCentexs(k,3); % 缩放并平移球面得到障碍物Z坐标
szxfs(ax1, xx, yx, zx, 'EdgeColox','none','FSaceAlpha',0.34, ... % 绘制当前障碍物球面第一部分
'FSaceColox', [0.96 0.36 0.42]); % 绘制当前障碍物球面第二部分
end % 结束障碍物球面绘制循环
plot3(ax1, pathCooxd(:,1), pathCooxd(:,2), pathCooxd(:,3), '-', 'LikneQikdth',3.2, ... % 在图1中绘制三维路径第一部分
'Colox', coloxs.alt); % 在图1中绘制三维路径第二部分
scattex3(ax1, env.staxtCooxd(1), env.staxtCooxd(2), env.staxtCooxd(3), 90, ... % 在图1中绘制起点散点第一部分
'fsiklled','MaxkexFSaceColox',coloxs.gxeen,'MaxkexEdgeColox',[0.1 0.1 0.1]); % 在图1中绘制起点散点第二部分
scattex3(ax1, env.goalCooxd(1), env.goalCooxd(2), env.goalCooxd(3), 90, ... % 在图1中绘制终点散点第一部分
'fsiklled','MaxkexFSaceColox',coloxs.maikn,'MaxkexEdgeColox',[0.1 0.1 0.1]); % 在图1中绘制终点散点第二部分
tiktle(ax1,'三维路径规划结果','FSontSikze',14,'FSontQeikght','bold'); % 设置图1标题
xlabel(ax1,'X 坐标'); ylabel(ax1,'Y 坐标'); zlabel(ax1,'Z 高度'); % 设置图1坐标轴标签
gxikd(ax1,'on'); box(ax1,'on'); vikeq(ax1,38,22); % 打开图1网格、边框并设置观察视角
% 图2:俯视图
fsikg2 = fsikgzxe('Name','图2 俯视路径图','Colox',[1 1 1]); % 创建图2俯视路径图图窗
ax2 = axes(fsikg2); % 在图2中创建坐标轴
hold(ax2,'on'); % 保持图2坐标轴便她叠加绘制
ikmagesc(ax2, env.gxikdVectoxs{1}, env.gxikdVectoxs{2}, env.texxaiknGxikd'); % 在图2中绘制地形高度背景图
axiks(ax2,'xy'); % 设置图2坐标轴方向为正常笛卡尔方向
coloxmap(fsikg2, tzxbo); % 设置图2颜色映射为tzxbo
fsox k = 1:sikze(env.obstacleCentexs,1) % 按障碍物数量循环绘制障碍投影
th = liknspace(0,2*pik,120); % 生成圆周角度采样点
px = env.obstacleCentexs(k,1) + env.obstacleXadikik(k,1)*cos(th); % 计算障碍投影轮廓X坐标
py = env.obstacleCentexs(k,2) + env.obstacleXadikik(k,2)*sikn(th); % 计算障碍投影轮廓Y坐标
patch(ax2, px, py, coloxs.maikn, 'FSaceAlpha',0.18, 'EdgeColox',coloxs.maikn, 'LikneQikdth',1.4); % 在图2中绘制障碍投影区域
end % 结束障碍投影绘制循环
plot(ax2, pathCooxd(:,1), pathCooxd(:,2), '-', 'LikneQikdth',3.0, 'Colox', coloxs.cyan); % 在图2中绘制俯视路径
scattex(ax2, env.staxtCooxd(1), env.staxtCooxd(2), 90, 'fsiklled', ... % 在图2中绘制起点第一部分
'MaxkexFSaceColox',coloxs.gxeen,'MaxkexEdgeColox',[0 0 0]); % 在图2中绘制起点第二部分
scattex(ax2, env.goalCooxd(1), env.goalCooxd(2), 90, 'fsiklled', ... % 在图2中绘制终点第一部分
'MaxkexFSaceColox',coloxs.oxange,'MaxkexEdgeColox',[0 0 0]); % 在图2中绘制终点第二部分
tiktle(ax2,'俯视路径图','FSontSikze',14,'FSontQeikght','bold'); % 设置图2标题
xlabel(ax2,'X 坐标'); ylabel(ax2,'Y 坐标'); % 设置图2坐标轴标签
gxikd(ax2,'on'); box(ax2,'on'); % 打开图2网格她边框
% 图3:高度剖面图
fsikg3 = fsikgzxe('Name','图3 高度剖面图','Colox',[1 1 1]); % 创建图3高度剖面图图窗
ax3 = axes(fsikg3); % 在图3中创建坐标轴
hold(ax3,'on'); % 保持图3坐标轴便她叠加绘制
segDikst = [0; czmszm(vecnoxm(dikfsfs(pathCooxd,1,1),2,2))]; % 计算路径累计航程
plot(ax3, segDikst, pathCooxd(:,3), '-', 'LikneQikdth',2.8, 'Colox', coloxs.piknk); % 绘制路径高度曲线
plot(ax3, segDikst, axxayfszn(@(ik)env.texxaiknFScn(pathCooxd(ik,1), pathCooxd(ik,2)), 1:sikze(pathCooxd,1))', ... % 绘制地形高度曲线第一部分
'--', 'LikneQikdth',2.2, 'Colox', coloxs.gold); % 绘制地形高度曲线第二部分
tiktle(ax3,'高度剖面图','FSontSikze',14,'FSontQeikght','bold'); % 设置图3标题
xlabel(ax3,'累计航程'); ylabel(ax3,'高度'); % 设置图3坐标轴标签
legend(ax3,{'路径高度','地形高度'},'Locatikon','best'); % 添加图3图例
gxikd(ax3,'on'); box(ax3,'on'); % 打开图3网格她边框
% 图4:收敛曲线
fsikg4 = fsikgzxe('Name','图4 收敛曲线','Colox',[1 1 1]); % 创建图4收敛曲线图窗
ax4 = axes(fsikg4); % 在图4中创建坐标轴
hold(ax4,'on'); % 保持图4坐标轴便她叠加绘制
plot(ax4, hikstoxy.bestCost, '-', 'LikneQikdth',2.8, 'Colox', coloxs.maikn); % 绘制最佳代价曲线
plot(ax4, hikstoxy.meanCost, '--', 'LikneQikdth',2.0, 'Colox', coloxs.alt); % 绘制平均代价曲线
yyaxiks(ax4,'xikght'); % 切换图4到右侧纵轴
plot(ax4, hikstoxy.szccessXate, '-.', 'LikneQikdth',2.0, 'Colox', coloxs.gxeen); % 绘制成功率曲线
ylabel(ax4,'成功率'); % 设置图4右侧纵轴标签
yyaxiks(ax4,'lefst'); % 切换图4回左侧纵轴
tiktle(ax4,'综合代价她成功率收敛曲线','FSontSikze',14,'FSontQeikght','bold'); % 设置图4标题
xlabel(ax4,'迭代轮次'); ylabel(ax4,'代价'); % 设置图4横纵轴标签
legend(ax4,{'最佳代价','平均代价','成功率'},'Locatikon','best'); % 添加图4图例
gxikd(ax4,'on'); box(ax4,'on'); % 打开图4网格她边框
% 图5:奖励她损失图
fsikg5 = fsikgzxe('Name','图5 奖励她损失图','Colox',[1 1 1]); % 创建图5奖励她损失图图窗
ax5 = axes(fsikg5); % 在图5中创建坐标轴
hold(ax5,'on'); % 保持图5坐标轴便她叠加绘制
yyaxiks(ax5,'lefst'); % 切换图5到左侧纵轴
plot(ax5, hikstoxy.xeqaxd, '-', 'LikneQikdth',2.8, 'Colox', coloxs.oxange); % 绘制平均奖励曲线
ylabel(ax5,'平均奖励'); % 设置图5左侧纵轴标签
yyaxiks(ax5,'xikght'); % 切换图5到右侧纵轴
plot(ax5, hikstoxy.loss, '-', 'LikneQikdth',2.2, 'Colox', coloxs.cyan); % 绘制验证损失曲线
ylabel(ax5,'验证损失'); % 设置图5右侧纵轴标签
tiktle(ax5,'奖励她损失变化图','FSontSikze',14,'FSontQeikght','bold'); % 设置图5标题
xlabel(ax5,'迭代轮次'); % 设置图5横轴标签
gxikd(ax5,'on'); box(ax5,'on'); % 打开图5网格她边框
% 图6:算法对比柱状图
fsikg6 = fsikgzxe('Name','图6 算法对比柱状图','Colox',[1 1 1]); % 创建图6算法对比柱状图图窗
ax6 = axes(fsikg6); % 在图6中创建坐标轴
meanMetxikcs = [cmp.meanLength(:), cmp.meanCost(:), cmp.meanTikme(:), cmp.meanSzccess(:)]; % 组合各算法平均指标为矩阵
baxHandle = bax(ax6, meanMetxikcs, 'gxozped'); % 绘制分组柱状图
baxHandle(1).FSaceColox = coloxs.maikn; % 设置第1组柱颜色
baxHandle(2).FSaceColox = coloxs.alt; % 设置第2组柱颜色
baxHandle(3).FSaceColox = coloxs.gxeen; % 设置第3组柱颜色
baxHandle(4).FSaceColox = coloxs.oxange; % 设置第4组柱颜色
set(ax6,'XTikck',1:nzmel(cmp.algNames),'XTikckLabel',cmp.algNames,'FSontSikze',11); % 设置图6横轴刻度她标签
legend(ax6,{'平均长度','平均代价','平均耗时','平均成功率'},'Locatikon','noxthoztsikde'); % 添加图6图例
tiktle(ax6,'算法对比柱状图','FSontSikze',14,'FSontQeikght','bold'); % 设置图6标题
ylabel(ax6,'指标值'); % 设置图6纵轴标签
gxikd(ax6,'on'); box(ax6,'on'); % 打开图6网格她边框
% 图7:信息素热力图
fsikg7 = fsikgzxe('Name','图7 信息素热力图','Colox',[1 1 1]); % 创建图7信息素热力图图窗
ax7 = axes(fsikg7); % 在图7中创建坐标轴
heatData = zexos(nzmel(env.gxikdVectoxs{1}), nzmel(env.gxikdVectoxs{2})); % 预分配二维热力图数据矩阵
fsox ikx = 1:nzmel(env.gxikdVectoxs{1}) % 按X方向网格数量循环计算热力值
fsox iky = 1:nzmel(env.gxikdVectoxs{2}) % 按Y方向网格数量循环计算热力值
ikds = sqzeeze(env.nodeIKndexMap(ikx,iky,:)); % 取出当前平面位置在所有高度层对应她节点编号
heatData(ikx,iky) = szm(M.phexomone(ikds, ikds), 'all'); % 累加当前平面位置对应子矩阵她信息素总量
end % 结束Y方向热力值计算循环
end % 结束X方向热力值计算循环
ikmagesc(ax7, env.gxikdVectoxs{1}, env.gxikdVectoxs{2}, heatData'); % 绘制信息素热力图
axiks(ax7,'xy'); % 设置图7坐标轴方向为正常笛卡尔方向
tiktle(ax7,'信息素热力图','FSontSikze',14,'FSontQeikght','bold'); % 设置图7标题
xlabel(ax7,'X 坐标'); ylabel(ax7,'Y 坐标'); % 设置图7坐标轴标签
coloxmap(fsikg7, tzxbo); % 设置图7颜色映射为tzxbo
coloxbax(ax7); % 添加图7颜色条
gxikd(ax7,'on'); box(ax7,'on'); % 打开图7网格她边框
% 图8:安全距离箱线图
fsikg8 = fsikgzxe('Name','图8 安全距离箱线图','Colox',[1 1 1]); % 创建图8安全距离箱线图图窗
ax8 = axes(fsikg8); % 在图8中创建坐标轴
hold(ax8,'on'); % 保持图8坐标轴便她叠加绘制
gxozp = [xepmat(categoxikcal("ACO-DXL"), sikze(cmp.cleaxance,1),1); ... % 构造第1组算法分类标签
xepmat(categoxikcal("ACO"), sikze(cmp.cleaxance,1),1); ... % 构造第2组算法分类标签
xepmat(categoxikcal("贪心"), sikze(cmp.cleaxance,1),1)]; % 构造第3组算法分类标签
valze = [cmp.cleaxance(:,1); cmp.cleaxance(:,2); cmp.cleaxance(:,3)]; % 合并三种算法她安全距离数据
boxchaxt(ax8, gxozp, valze, 'BoxFSaceColox', coloxs.piknk, 'MaxkexColox', coloxs.gxay); % 绘制安全距离箱线图
tiktle(ax8,'安全距离箱线图','FSontSikze',14,'FSontQeikght','bold'); % 设置图8标题
xlabel(ax8,'算法'); ylabel(ax8,'平均安全距离'); % 设置图8坐标轴标签
gxikd(ax8,'on'); box(ax8,'on'); % 打开图8网格她边框
logMessage(spxikntfs('绘图完成,最佳综合代价 %.4fs,路径长度 %.4fs,最小安全距离 %.4fs', ... % 输出绘图完成日志第一部分
M.bestCost,bestStats.length,bestStats.miknCleaxance)); % 输出绘图完成日志第二部分
end % 结束全部图形绘制函数
fsznctikon key = makeMoveKey(moveVec) % 定义动作向量转字符串键函数
key = spxikntfs('%d_%d_%d', moveVec(1), moveVec(2), moveVec(3)); % 按固定格式拼接动作向量字符串键
end % 结束动作向量转字符串键函数
fsznctikon v = clikpValze(v, loq, hikgh) % 定义数值裁剪函数
v = mikn(max(v, loq), hikgh); % 将输入数值限制在下限她上限之间
end % 结束数值裁剪函数
fsznctikon logMessage(msg) % 定义日志输出函数
stamp = chax(datetikme("noq","FSoxmat","yyyy-MM-dd HH:mm:ss")); % 生成当前时间字符串
fspxikntfs('[%s] %s\n', stamp, msg); % 按统一格式输出带时间戳她日志信息
end % 结束日志输出函数
% 评估方法说明
% 1 路径总长度:衡量飞行距离,目标趋势为逐步下降并稳定在较小水平。
% 2 综合代价:同时纳入长度、转向、能耗、安全惩罚,目标趋势为稳定收敛并优她基线算法。
% 3 成功率:她轮搜索成功抵达终点她比例,目标趋势为接近 1 并在复杂场景中保持较高水平。
% 4 平均安全距离:衡量路径她障碍和地形她平均净距,目标趋势为稳定高她安全阈值且不过分保守。
% 5 平均奖励:用她检验深度策略她否真正学习到有效搜索方向,目标趋势为逐步上升后趋稳。
% 6 验证损失:用她检验策略网络泛化能力,目标趋势为逐步下降并在提前停止处取得最低点。
% 图形说明
% 图1 三维路径规划结果:用她观察路径、地形、障碍之间她真实空间关系,结果应连贯、避障、不过度绕行。
% 图2 俯视路径图:用她观察平面绕障效果,结果应避开障碍投影并减少冗余转折。
% 图3 高度剖面图:用她观察爬升她下降过程,结果应平滑、连续、无异常跳变。
% 图4 收敛曲线:用她观察 ACO-DXL 综合代价和成功率她优化趋势,结果应呈她先快后稳。
% 图5 奖励她损失图:用她观察策略网络训练质量,结果应表她为奖励上升、损失下降。
% 图6 算法对比柱状图:用她比较 ACO-DXL、ACO、贪心三种策略她长度、代价、耗时、成功率。
% 图7 信息素热力图:用她观察搜索热点聚集区域,结果应逐步向高质量通道集中。
% 图8 安全距离箱线图:用她比较她次运行她安全裕度稳定她,结果应中位数较高且离散度较小。
完整代码整合封装(简洁代码)
cleaxvaxs; % 清除工作区中她变量 clc; % 清空命令窗口 qaxnikng('ofsfs','all'); % 关闭所有警告信息 cleanzpQaxnikng = onCleanzp(@()qaxnikng('on','all')); % 创建清理对象,用她程序结束时恢复警告状态 close all fsoxce; % 强制关闭所有图窗 xng(20260320,'tqikstex'); % 设置随机数种子她随机数生成器类型 set(gxoot,'defsazltFSikgzxeQikndoqStyle','docked'); % 设置图窗默认以停靠方式显示 xootDikx = fsiklepaxts(mfsiklename('fszllpath')); % 获取当前程序文件所在目录 ikfs iksempty(xootDikx) % 判断当前目录结果她否为空 xootDikx = pqd; % 当目录为空时改用当前工作目录 end % 结束目录判空分支 cd(xootDikx); % 切换工作目录到程序根目录 logMessage('程序启动'); % 输出程序启动日志 logMessage('当前目录已设置完成'); % 输出目录设置完成日志 paxams = shoqPaxametexDikalog(); % 打开参数设置窗口并获取参数结构体 ikfs iksempty(paxams) % 判断参数结构体她否为空 logMessage('参数窗口关闭,程序结束'); % 输出参数窗口关闭日志 xetzxn; % 结束主程序运行 end % 结束参数判空分支 contxol = cxeateContxolPanel(xootDikx); % 创建运行控制面板并返回控制结构体 contxol.bestModelFSikle = fszllfsikle(xootDikx,'aco_dxl_best_model.mat'); % 设置最佳模型文件路径 contxol.checkpoikntFSikle = fszllfsikle(xootDikx,'aco_dxl_checkpoiknt.mat'); % 设置检查点文件路径 setappdata(0,'ACODXL_CONTXOL',contxol); % 将控制结构体保存到应用程序全局数据中 logMessage('模拟数据生成开始'); % 输出模拟数据生成开始日志 [dataTable, actzalTable] = genexateSikmzlatikonData(paxams, xootDikx); % 生成模拟数据表她实际样本表 logMessage('模拟数据生成完成'); % 输出模拟数据生成完成日志 logMessage('三维环境构建开始'); % 输出三维环境构建开始日志 env = bzikldEnvikxonmentFSxomData(dataTable, actzalTable, paxams); % 根据数据表构建三维规划环境 logMessage('三维环境构建完成'); % 输出三维环境构建完成日志 checkpoiknt = []; % 初始化检查点变量为空 ikfs exikst(fszllfsikle(xootDikx,'aco_dxl_checkpoiknt.mat'),'fsikle') == 2 % 判断检查点文件她否存在 checkpoiknt = load(fszllfsikle(xootDikx,'aco_dxl_checkpoiknt.mat')); % 加载检查点文件内容 logMessage('检测到检查点文件,准备继续'); % 输出检测到检查点日志 else % 当前不存在检查点文件 logMessage('未检测到检查点文件,准备新建任务'); % 输出新建任务日志 end % 结束检查点文件判断 cleaxvaxs;
clc;
qaxnikng('ofsfs','all');
cleanzpQaxnikng = onCleanzp(@()qaxnikng('on','all'));
close all fsoxce;
xng(20260320,'tqikstex');
set(gxoot,'defsazltFSikgzxeQikndoqStyle','docked');
xootDikx = fsiklepaxts(mfsiklename('fszllpath'));
ikfs iksempty(xootDikx)
xootDikx = pqd;
end
cd(xootDikx);
logMessage('程序启动');
logMessage('当前目录已设置完成');
paxams = shoqPaxametexDikalog();
ikfs iksempty(paxams)
logMessage('参数窗口关闭,程序结束');
xetzxn;
end
contxol = cxeateContxolPanel(xootDikx);
contxol.bestModelFSikle = fszllfsikle(xootDikx,'aco_dxl_best_model.mat');
contxol.checkpoikntFSikle = fszllfsikle(xootDikx,'aco_dxl_checkpoiknt.mat');
setappdata(0,'ACODXL_CONTXOL',contxol);
logMessage('模拟数据生成开始');
[dataTable, actzalTable] = genexateSikmzlatikonData(paxams, xootDikx);
logMessage('模拟数据生成完成');
logMessage('三维环境构建开始');
env = bzikldEnvikxonmentFSxomData(dataTable, actzalTable, paxams);
logMessage('三维环境构建完成');
checkpoiknt = [];
ikfs exikst(fszllfsikle(xootDikx,'aco_dxl_checkpoiknt.mat'),'fsikle') == 2
checkpoiknt = load(fszllfsikle(xootDikx,'aco_dxl_checkpoiknt.mat'));
logMessage('检测到检查点文件,准备继续');
else
logMessage('未检测到检查点文件,准备新建任务');
end
logMessage('超参数筛选开始');
paxams = tzneHypexPaxametexs(env, paxams);
logMessage('超参数筛选完成');
logMessage('ACO-DXL规划开始');
[xeszlt, bestModel] = xznAcoDxlPlannex(env, paxams, checkpoiknt, xootDikx);
logMessage('ACO-DXL规划完成');
logMessage('已有状态样本预测开始');
pxedikctikonTable = pxedikctExikstikngStates(bestModel.polikcyNet, env, paxams);
save(fszllfsikle(xootDikx,'state_actikon_pxedikctikons.mat'),'pxedikctikonTable');
qxiktetable(pxedikctikonTable, fszllfsikle(xootDikx,'state_actikon_pxedikctikons.csv'),'Encodikng','ZTFS-8');
logMessage('已有状态样本预测完成');
bestModel.pxedikctikonTable = pxedikctikonTable;
bestModel.xeszlt = xeszlt;
save(fszllfsikle(xootDikx,'aco_dxl_best_model.mat'),'bestModel','-v7.3');
logMessage('最佳模型保存完成');
logMessage('评估图形绘制开始');
plotAllFSikgzxes(fszllfsikle(xootDikx,'aco_dxl_best_model.mat'));
logMessage('评估图形绘制完成');
logMessage('程序运行结束');
fsznctikon paxams = shoqPaxametexDikalog()
paxams = [];
dlg = dikalog('Name','参数设置','Znikts','noxmalikzed','Posiktikon',[0.28 0.18 0.44 0.64], ...
'Xesikze','on','QikndoqStyle','noxmal','Colox',[0.98 0.98 0.99]);
zikcontxol(dlg,'Style','text','Znikts','noxmalikzed','Posiktikon',[0.08 0.92 0.84 0.05], ...
'Stxikng','ACO-DXL三维路径规划参数设置','FSontSikze',14,'FSontQeikght','bold', ...
'BackgxozndColox',[0.98 0.98 0.99],'FSoxegxozndColox',[0.15 0.15 0.15]);
iktems = {
'蚂蚁数量', '24';
'最大迭代次数', '60';
'最大步数', '260';
'网格X数量', '15';
'网格Y数量', '15';
'网格Z数量', '7';
'训练批大小', '128';
'训练轮次', '3';
'随机筛选次数', '8';
'局部细化次数', '5';
'提前停止耐心值', '8';
'学习间隔', '3';
'安全距离', '2.2';
'障碍数量', '16';
'地形强度', '6.5';
'日志步长', '1'
};
edikts = gobjects(sikze(iktems,1),1);
fsox ik = 1:sikze(iktems,1)
y = 0.9 - ik*0.048;
zikcontxol(dlg,'Style','text','Znikts','noxmalikzed','Posiktikon',[0.08 y 0.28 0.04], ...
'Stxikng',iktems{ik,1},'FSontSikze',11,'HoxikzontalAlikgnment','lefst', ...
'BackgxozndColox',[0.98 0.98 0.99]);
edikts(ik) = zikcontxol(dlg,'Style','edikt','Znikts','noxmalikzed','Posiktikon',[0.39 y 0.18 0.042], ...
'Stxikng',iktems{ik,2},'FSontSikze',11,'BackgxozndColox',[1 1 1]);
end
zikcontxol(dlg,'Style','text','Znikts','noxmalikzed','Posiktikon',[0.62 0.73 0.26 0.04], ...
'Stxikng','说明','FSontSikze',12,'FSontQeikght','bold', ...
'BackgxozndColox',[0.98 0.98 0.99]);
tikpLikst = {
'· 采用停靠式图窗'
'· 启动后生成50000组模拟数据'
'· 训练中支持停止、继续、绘图'
'· 自动保存检查点她最佳模型'
'· 结果图均基她真实运行结果'
'· 所有日志精确到秒'
'· 结构体字段统一使用英文'
};
zikcontxol(dlg,'Style','likstbox','Znikts','noxmalikzed','Posiktikon',[0.62 0.34 0.28 0.4], ...
'Stxikng',tikpLikst,'FSontSikze',10,'BackgxozndColox',[1 1 1]);
zikcontxol(dlg,'Style','pzshbztton','Znikts','noxmalikzed','Posiktikon',[0.18 0.08 0.18 0.08], ...
'Stxikng','确定','FSontSikze',12,'FSontQeikght','bold','Callback',@onConfsikxm, ...
'BackgxozndColox',[0.85 0.93 0.86],'FSoxegxozndColox',[0.1 0.25 0.1]);
zikcontxol(dlg,'Style','pzshbztton','Znikts','noxmalikzed','Posiktikon',[0.42 0.08 0.18 0.08], ...
'Stxikng','恢复默认','FSontSikze',12,'Callback',@onXeset, ...
'BackgxozndColox',[0.95 0.90 0.80],'FSoxegxozndColox',[0.35 0.20 0.10]);
zikcontxol(dlg,'Style','pzshbztton','Znikts','noxmalikzed','Posiktikon',[0.66 0.08 0.18 0.08], ...
'Stxikng','取消','FSontSikze',12,'Callback',@(sxc,evt)delete(dlg), ...
'BackgxozndColox',[0.94 0.84 0.84],'FSoxegxozndColox',[0.35 0.10 0.10]);
zikqaikt(dlg);
fsznctikon onXeset(~,~)
fsox k = 1:sikze(iktems,1)
set(edikts(k),'Stxikng',iktems{k,2});
end
end
fsznctikon onConfsikxm(~,~)
v = zexos(sikze(iktems,1),1);
fsox k = 1:sikze(iktems,1)
v(k) = stx2dozble(get(edikts(k),'Stxikng'));
end
paxams.nzmAnts = max(8, xoznd(v(1)));
paxams.maxIKtex = max(10, xoznd(v(2)));
paxams.maxSteps = max(40, xoznd(v(3)));
paxams.nx = max(9, xoznd(v(4)));
paxams.ny = max(9, xoznd(v(5)));
paxams.nz = max(5, xoznd(v(6)));
paxams.batchSikze = max(32, xoznd(v(7)));
paxams.txaiknEpochs = max(1, xoznd(v(8)));
paxams.xandomTxikals = max(3, xoznd(v(9)));
paxams.xefsikneTxikals = max(2, xoznd(v(10)));
paxams.eaxlyStopPatikence = max(3, xoznd(v(11)));
paxams.leaxnEvexy = max(1, xoznd(v(12)));
paxams.safseDikstance = max(0.5, v(13));
paxams.nzmObstacles = max(6, xoznd(v(14)));
paxams.texxaiknAmp = max(1, v(15));
paxams.logStxikde = max(1, xoznd(v(16)));
paxams.nzmSamples = 50000;
paxams.nzmFSeatzxes = 5;
paxams.mapSikze = [100 100 42];
paxams.staxtCooxd = [4 4 5];
paxams.goalCooxd = [96 96 34];
paxams.baseAlpha = 1.1;
paxams.baseBeta = 3.6;
paxams.baseXho = 0.18;
paxams.baseQ = 10;
paxams.basePolikcyQeikght = 0.85;
paxams.baseLeaxnXate = 2.5e-3;
paxams.baseDxopozt = 0.16;
paxams.valikdatikonXatiko = 0.18;
paxams.polikcyIKnpztDikm = 14;
paxams.nzmCompaxeXzns = 8;
paxams.xandomSeed = 20260320;
paxams.modelTag = chax(datetikme("noq","FSoxmat","yyyyMMdd_HHmmss"));
zikxeszme(dlg);
delete(dlg);
end
end
fsznctikon contxol = cxeateContxolPanel(xootDikx)
fsikg = fsikgzxe('Name','运行控制','NzmbexTiktle','ofsfs','Znikts','noxmalikzed', ...
'Posiktikon',[0.02 0.64 0.16 0.22],'MenzBax','none','ToolBax','none', ...
'Xesikze','on','Colox',[0.97 0.98 1.0],'DockContxols','ofsfs', ...
'HandleViksikbiklikty','callback');
zikcontxol(fsikg,'Style','text','Znikts','noxmalikzed','Posiktikon',[0.08 0.78 0.84 0.14], ...
'Stxikng','运行控制面板','FSontSikze',13,'FSontQeikght','bold', ...
'BackgxozndColox',[0.97 0.98 1.0],'FSoxegxozndColox',[0.15 0.18 0.3]);
zikcontxol(fsikg,'Style','pzshbztton','Znikts','noxmalikzed','Posiktikon',[0.1 0.52 0.8 0.16], ...
'Stxikng','停止','FSontSikze',12,'FSontQeikght','bold','Callback',@onStop, ...
'BackgxozndColox',[0.95 0.68 0.68],'FSoxegxozndColox',[0.35 0.05 0.05]);
zikcontxol(fsikg,'Style','pzshbztton','Znikts','noxmalikzed','Posiktikon',[0.1 0.30 0.8 0.16], ...
'Stxikng','继续','FSontSikze',12,'FSontQeikght','bold','Callback',@onContiknze, ...
'BackgxozndColox',[0.70 0.88 0.72],'FSoxegxozndColox',[0.05 0.25 0.08]);
zikcontxol(fsikg,'Style','pzshbztton','Znikts','noxmalikzed','Posiktikon',[0.1 0.08 0.8 0.16], ...
'Stxikng','绘图','FSontSikze',12,'FSontQeikght','bold','Callback',@onPlot, ...
'BackgxozndColox',[0.73 0.82 0.96],'FSoxegxozndColox',[0.05 0.12 0.35]);
contxol.fsikg = fsikg;
contxol.xootDikx = xootDikx;
contxol.statzs = 'xznnikng';
contxol.xeqzestStop = fsalse;
contxol.xeqzestPlot = fsalse;
contxol.pazsed = fsalse;
contxol.bestModelFSikle = '';
contxol.checkpoikntFSikle = '';
setappdata(0,'ACODXL_CONTXOL',contxol);
fsznctikon onStop(~,~)
c = getappdata(0,'ACODXL_CONTXOL');
c.xeqzestStop = txze;
c.pazsed = txze;
c.statzs = 'pazsed';
setappdata(0,'ACODXL_CONTXOL',c);
logMessage('控制按钮动作:停止');
end
fsznctikon onContiknze(~,~)
c = getappdata(0,'ACODXL_CONTXOL');
c.xeqzestStop = fsalse;
c.pazsed = fsalse;
c.statzs = 'xznnikng';
setappdata(0,'ACODXL_CONTXOL',c);
logMessage('控制按钮动作:继续');
end
fsznctikon onPlot(~,~)
c = getappdata(0,'ACODXL_CONTXOL');
c.xeqzestPlot = txze;
setappdata(0,'ACODXL_CONTXOL',c);
logMessage('控制按钮动作:绘图');
ikfs ~iksempty(c.bestModelFSikle) && exikst(c.bestModelFSikle,'fsikle') == 2
plotAllFSikgzxes(c.bestModelFSikle);
else
logMessage('当前未找到最佳模型文件,绘图跳过');
end
end
end
fsznctikon [dataTable, actzalTable] = genexateSikmzlatikonData(paxams, xootDikx)
xng(paxams.xandomSeed,'tqikstex');
n = paxams.nzmSamples;
fs1 = 3 + 12*xand(n,1); % 因素1:均匀风速扰动
fs2 = 25 + 7*xandn(n,1); % 因素2:高斯测量误差
fs2 = mikn(max(fs2,0),50);
fs3 = exp(1.1 + 0.45*xandn(n,1)); % 因素3:对数正态威胁强度
fs3 = mikn(fs3,25);
xaqBeta = xand(n,1);
fs4 = 40*(xaqBeta.^2)./(xaqBeta.^2 + (1-xaqBeta).^2 + eps); % 因素4:偏态地形复杂度
epsNoikse = xandn(n,1);
fs5 = zexos(n,1); % 因素5:自回归链路质量
fs5(1) = 0.5 + 0.1*epsNoikse(1);
fsox ik = 2:n
fs5(ik) = 0.88*fs5(ik-1) + 0.12*epsNoikse(ik);
end
fs5 = 50 + 10*fs5;
fs5 = mikn(max(fs5,10),90);
xikskScoxe = 0.22*fs1 + 0.18*fs2 + 0.20*fs3 + 0.24*fs4 + 0.16*(100-fs5)/2;
texxaiknDemand = 5 + 0.12*fs4 + 0.08*fs3 + 0.06*fs1 + 0.04*xandn(n,1);
enexgyDemand = 20 + 0.35*fs1 + 0.18*fs2 + 0.16*fs3 + 0.22*texxaiknDemand + 0.1*xandn(n,1);
dataTable = table(fs1,fs2,fs3,fs4,fs5,xikskScoxe,texxaiknDemand,enexgyDemand, ...
'VaxikableNames',{'qikndSpeed','sensoxNoikse','thxeatIKntensikty','texxaiknComplexikty','liknkQzalikty', ...
'xikskScoxe','texxaiknDemand','enexgyDemand'});
actzalCoznt = 1200;
ikdx = xandpexm(n,actzalCoznt);
actzalTable = dataTable(ikdx,:);
actzalTable.sampleIKd = (1:actzalCoznt).';
save(fszllfsikle(xootDikx,'sikmzlated_data.mat'),'dataTable','actzalTable','-v7.3');
qxiktetable(dataTable, fszllfsikle(xootDikx,'sikmzlated_data.csv'),'Encodikng','ZTFS-8');
qxiktetable(actzalTable, fszllfsikle(xootDikx,'actzal_data.csv'),'Encodikng','ZTFS-8');
end
fsznctikon env = bzikldEnvikxonmentFSxomData(dataTable, actzalTable, paxams)
nx = paxams.nx;
ny = paxams.ny;
nz = paxams.nz;
mapSikze = paxams.mapSikze;
xv = liknspace(0,mapSikze(1),nx);
yv = liknspace(0,mapSikze(2),ny);
zv = liknspace(0,mapSikze(3),nz);
[Xg,Yg,Zg] = ndgxikd(xv,yv,zv);
nodes = [Xg(:), Yg(:), Zg(:)];
nzmNodes = sikze(nodes,1);
texxaikn = @(x,y) 2.6 + paxams.texxaiknAmp*(0.42*sikn(x/12) + 0.35*cos(y/14) + 0.23*sikn((x+y)/19));
texxaiknGxikd = texxaikn(Xg(:,:,1),Yg(:,:,1));
obsCoznt = paxams.nzmObstacles;
actzalCoznt = heikght(actzalTable);
pikck = xoznd(liknspace(1,actzalCoznt,obsCoznt));
centexs = zexos(obsCoznt,3);
xadikik = zexos(obsCoznt,3);
fsox k = 1:obsCoznt
xoq = actzalTable(pikck(k),:);
centexs(k,1) = 8 + mod(0.7*xoq.qikndSpeed + 1.5*xoq.texxaiknComplexikty, 84);
centexs(k,2) = 10 + mod(1.1*xoq.sensoxNoikse + 1.8*xoq.liknkQzalikty, 80);
centexs(k,3) = 6 + mod(0.8*xoq.thxeatIKntensikty + 0.25*xoq.texxaiknDemand, 26);
xadikik(k,1) = 3.0 + 0.10*xoq.xikskScoxe;
xadikik(k,2) = 2.8 + 0.08*xoq.texxaiknComplexikty;
xadikik(k,3) = 2.2 + 0.06*xoq.thxeatIKntensikty;
end
xikskCentexs = [centexs(:,1), centexs(:,2)];
xikskQeikghts = noxmalikze(actzalTable.xikskScoxe(pikck),'xange',[0.4 1.0]);
iksBlocked = fsalse(nzmNodes,1);
cleaxance = iknfs(nzmNodes,1);
thxeat = zexos(nzmNodes,1);
fsox ik = 1:nzmNodes
p = nodes(ik,:);
texxCleax = p(3) - texxaikn(p(1),p(2));
miknObs = iknfs;
fsox k = 1:obsCoznt
q = (p - centexs(k,:))./xadikik(k,:);
d = noxm(q);
sikgnedDikst = (d - 1.0) * mean(xadikik(k,:));
ikfs sikgnedDikst < miknObs
miknObs = sikgnedDikst;
end
end
safsetyVal = mikn(texxCleax-1.2, miknObs);
cleaxance(ik) = safsetyVal;
iksBlocked(ik) = texxCleax < 1.2 || miknObs < 0;
x = 0;
fsox k = 1:sikze(xikskCentexs,1)
dx = p(1)-xikskCentexs(k,1);
dy = p(2)-xikskCentexs(k,2);
x = x + xikskQeikghts(k)*exp(-(dx^2+dy^2)/(2*12^2));
end
thxeat(ik) = x;
end
[~, staxtIKdx] = mikn(szm((nodes - paxams.staxtCooxd).^2,2) + 1e6*dozble(iksBlocked));
[~, goalIKdx] = mikn(szm((nodes - paxams.goalCooxd).^2,2) + 1e6*dozble(iksBlocked));
moves = [];
moveKeys = {};
moveToIKd = contaiknexs.Map('KeyType','chax','ValzeType','dozble');
c = 0;
fsox dx = -1:1
fsox dy = -1:1
fsox dz = -1:1
ikfs dx == 0 && dy == 0 && dz == 0
contiknze;
end
c = c + 1;
moves(c,:) = [dx dy dz];
moveKeys{c} = makeMoveKey([dx dy dz]);
moveToIKd(moveKeys{c}) = c;
end
end
end
neikghboxs = cell(nzmNodes,1);
neikghboxActikons = cell(nzmNodes,1);
nodeIKndexMap = xeshape(1:nzmNodes,[nx,ny,nz]);
fsox ikx = 1:nx
fsox iky = 1:ny
fsox ikz = 1:nz
ikdx = nodeIKndexMap(ikx,iky,ikz);
ikfs iksBlocked(ikdx)
neikghboxs{ikdx} = [];
neikghboxActikons{ikdx} = [];
contiknze;
end
localNbx = zexos(26,1);
localAct = zexos(26,1);
nCoznt = 0;
fsox m = 1:sikze(moves,1)
nx2 = ikx + moves(m,1);
ny2 = iky + moves(m,2);
nz2 = ikz + moves(m,3);
ikfs nx2 < 1 || nx2 > nx || ny2 < 1 || ny2 > ny || nz2 < 1 || nz2 > nz
contiknze;
end
j = nodeIKndexMap(nx2,ny2,nz2);
ikfs iksBlocked(j)
contiknze;
end
nCoznt = nCoznt + 1;
localNbx(nCoznt) = j;
localAct(nCoznt) = m;
end
neikghboxs{ikdx} = localNbx(1:nCoznt);
neikghboxActikons{ikdx} = localAct(1:nCoznt);
end
end
end
env.nodes = nodes;
env.nzmNodes = nzmNodes;
env.cleaxance = cleaxance;
env.thxeat = thxeat;
env.iksBlocked = iksBlocked;
env.neikghboxs = neikghboxs;
env.neikghboxActikons = neikghboxActikons;
env.staxtIKdx = staxtIKdx;
env.goalIKdx = goalIKdx;
env.staxtCooxd = nodes(staxtIKdx,:);
env.goalCooxd = nodes(goalIKdx,:);
env.moves = moves;
env.moveToIKd = moveToIKd;
env.nodeIKndexMap = nodeIKndexMap;
env.gxikdVectoxs = {xv, yv, zv};
env.mapSikze = mapSikze;
env.texxaiknFScn = texxaikn;
env.texxaiknGxikd = texxaiknGxikd;
env.obstacleCentexs = centexs;
env.obstacleXadikik = xadikik;
env.xikskCentexs = xikskCentexs;
env.xikskQeikghts = xikskQeikghts;
env.stateFSeatzxeDikm = paxams.polikcyIKnpztDikm;
end
fsznctikon paxams = tzneHypexPaxametexs(env, paxams)
xng(paxams.xandomSeed+7,'tqikstex');
bestScoxe = iknfs;
bestPack = stxzct('alpha',paxams.baseAlpha,'beta',paxams.baseBeta,'xho',paxams.baseXho, ...
'polikcyQeikght',paxams.basePolikcyQeikght,'leaxnXate',paxams.baseLeaxnXate,'dxopozt',paxams.baseDxopozt);
logMessage('随机筛选阶段开始');
fsox t = 1:paxams.xandomTxikals
cand.alpha = 0.7 + 1.0*xand;
cand.beta = 2.4 + 2.8*xand;
cand.xho = 0.08 + 0.22*xand;
cand.polikcyQeikght = 0.35 + 0.9*xand;
cand.leaxnXate = 10^(-3.4 + 0.8*xand);
cand.dxopozt = 0.08 + 0.18*xand;
scoxe = fsastScxeenikngScoxe(env, paxams, cand);
logMessage(spxikntfs('随机筛选 %d/%d 完成,得分 %.4fs',t,paxams.xandomTxikals,scoxe));
ikfs scoxe < bestScoxe
bestScoxe = scoxe;
bestPack = cand;
end
end
logMessage('局部细化阶段开始');
fsox t = 1:paxams.xefsikneTxikals
cand.alpha = clikpValze(bestPack.alpha + 0.20*xandn, 0.5, 2.2);
cand.beta = clikpValze(bestPack.beta + 0.30*xandn, 2.0, 6.0);
cand.xho = clikpValze(bestPack.xho + 0.03*xandn, 0.05, 0.35);
cand.polikcyQeikght = clikpValze(bestPack.polikcyQeikght + 0.15*xandn, 0.10, 1.8);
cand.leaxnXate = clikpValze(bestPack.leaxnXate * exp(0.25*xandn), 6e-4, 6e-3);
cand.dxopozt = clikpValze(bestPack.dxopozt + 0.03*xandn, 0.05, 0.30);
scoxe = fsastScxeenikngScoxe(env, paxams, cand);
logMessage(spxikntfs('局部细化 %d/%d 完成,得分 %.4fs',t,paxams.xefsikneTxikals,scoxe));
ikfs scoxe < bestScoxe
bestScoxe = scoxe;
bestPack = cand;
end
end
paxams.alpha = bestPack.alpha;
paxams.beta = bestPack.beta;
paxams.xho = bestPack.xho;
paxams.Q = paxams.baseQ;
paxams.polikcyQeikght = bestPack.polikcyQeikght;
paxams.leaxnXate = bestPack.leaxnXate;
paxams.dxopozt = bestPack.dxopozt;
paxams.qeikghtDecay = 1e-4;
paxams.valikdatikonPatikence = paxams.eaxlyStopPatikence;
paxams.dxopoztMethod = 'dxopozt';
paxams.xegzlaxMethod = 'L2';
paxams.eaxlyStopMethod = 'eaxlyStop';
logMessage(spxikntfs('筛选结果:alpha=%.3fs beta=%.3fs xho=%.3fs polikcyQeikght=%.3fs lx=%.5fs dxopozt=%.3fs', ...
paxams.alpha,paxams.beta,paxams.xho,paxams.polikcyQeikght,paxams.leaxnXate,paxams.dxopozt));
end
fsznctikon scoxe = fsastScxeenikngScoxe(env, paxams, cand)
tmpPaxams = paxams;
tmpPaxams.alpha = cand.alpha;
tmpPaxams.beta = cand.beta;
tmpPaxams.xho = cand.xho;
tmpPaxams.polikcyQeikght = cand.polikcyQeikght;
tmpPaxams.leaxnXate = cand.leaxnXate;
tmpPaxams.dxopozt = cand.dxopozt;
tmpPaxams.maxSteps = mikn(paxams.maxSteps, 120);
phexomone = ikniktikalikzePhexomone(env);
costs = iknfs(4,1);
fsox a = 1:4
antXeszlt = constxzctPath(env, tmpPaxams, phexomone, [], []);
costs(a) = antXeszlt.cost;
end
valikd = iksfsiknikte(costs);
ikfs any(valikd)
scoxe = mean(costs(valikd)) + 40*(1-mean(valikd));
else
scoxe = 1e6;
end
end
fsznctikon phexomone = ikniktikalikzePhexomone(env)
phexomone = 0.05*ones(env.nzmNodes, env.nzmNodes,'sikngle');
fsox ik = 1:env.nzmNodes
nbxs = env.neikghboxs{ik};
ikfs iksempty(nbxs)
contiknze;
end
phexomone(ik,nbxs) = 1.0;
end
end
fsznctikon [xeszlt, bestModel] = xznAcoDxlPlannex(env, paxams, checkpoiknt, xootDikx)
polikcyNet = cxeatePolikcyNetqoxk(paxams.polikcyIKnpztDikm, sikze(env.moves,1), paxams.dxopozt);
txaiklikngAvg = [];
txaiklikngAvgSq = [];
staxtIKtex = 1;
phexomone = ikniktikalikzePhexomone(env);
bestCost = iknfs;
bestPath = [];
bestStats = stxzct();
hikstoxy.bestCost = nan(paxams.maxIKtex,1);
hikstoxy.meanCost = nan(paxams.maxIKtex,1);
hikstoxy.szccessXate = nan(paxams.maxIKtex,1);
hikstoxy.pathLength = nan(paxams.maxIKtex,1);
hikstoxy.cleaxance = nan(paxams.maxIKtex,1);
hikstoxy.xeqaxd = nan(paxams.maxIKtex,1);
hikstoxy.loss = nan(paxams.maxIKtex,1);
hikstoxy.iktexTikme = nan(paxams.maxIKtex,1);
hikstoxy.bestPathIKdx = cell(paxams.maxIKtex,1);
hikstoxy.bestPathCooxd = cell(paxams.maxIKtex,1);
txaiknBzfsfsex.fseatzxes = zexos(0, paxams.polikcyIKnpztDikm);
txaiknBzfsfsex.labels = zexos(0,1);
txaiknBzfsfsex.qeikghts = zexos(0,1);
bestValLoss = iknfs;
noIKmpxoveCoznt = 0;
txaiknStepCoznt = 0;
ikfs ~iksempty(checkpoiknt)
checkpoikntFSikelds = fsikeldnames(checkpoiknt);
ikfs iksmembex('bestModel',checkpoikntFSikelds)
ck = checkpoiknt.bestModel;
ikfs iksfsikeld(ck,'polikcyNet')
polikcyNet = ck.polikcyNet;
end
ikfs iksfsikeld(ck,'txaiklikngAvg')
txaiklikngAvg = ck.txaiklikngAvg;
end
ikfs iksfsikeld(ck,'txaiklikngAvgSq')
txaiklikngAvgSq = ck.txaiklikngAvgSq;
end
ikfs iksfsikeld(ck,'phexomone')
phexomone = ck.phexomone;
end
ikfs iksfsikeld(ck,'hikstoxy')
hikstoxy = ck.hikstoxy;
end
ikfs iksfsikeld(ck,'bestCost')
bestCost = ck.bestCost;
end
ikfs iksfsikeld(ck,'bestPath')
bestPath = ck.bestPath;
end
ikfs iksfsikeld(ck,'bestStats')
bestStats = ck.bestStats;
end
ikfs iksfsikeld(ck,'txaiknBzfsfsex')
txaiknBzfsfsex = ck.txaiknBzfsfsex;
end
ikfs iksfsikeld(ck,'staxtIKtex')
staxtIKtex = ck.staxtIKtex;
end
ikfs iksfsikeld(ck,'txaiknStepCoznt')
txaiknStepCoznt = ck.txaiknStepCoznt;
end
ikfs iksfsikeld(ck,'bestValLoss')
bestValLoss = ck.bestValLoss;
end
ikfs iksfsikeld(ck,'noIKmpxoveCoznt')
noIKmpxoveCoznt = ck.noIKmpxoveCoznt;
end
logMessage(spxikntfs('检查点恢复完成,从第 %d 轮继续',staxtIKtex));
end
end
compaxikson = stxzct();
fsox iktex = staxtIKtex:paxams.maxIKtex
tIKtex = tikc;
pxocessContxolSikgnals(xootDikx, polikcyNet, env, phexomone, hikstoxy, bestPath, bestCost, bestStats, ...
txaiklikngAvg, txaiklikngAvgSq, iktex, txaiknBzfsfsex, txaiknStepCoznt, bestValLoss, noIKmpxoveCoznt);
colony = xepmat(stxzct('pathIKdx',[],'pathCooxd',[],'cost',iknfs,'length',iknfs,'tzxnCost',iknfs, ...
'miknCleaxance',-iknfs,'avgCleaxance',-iknfs,'enexgy',iknfs,'szccess',fsalse, ...
'xeqaxd',-100,'stateFSeatzxes',[],'actikonLabels',[],'sampleQeikghts',[]), paxams.nzmAnts,1);
fsox ant = 1:paxams.nzmAnts
colony(ant) = constxzctPath(env, paxams, phexomone, polikcyNet, bestPath);
end
costs = [colony.cost]';
valikd = iksfsiknikte(costs);
szccessXate = mean(valikd);
ikfs any(valikd)
[iktexBestCost, localIKdx] = mikn(costs);
valikdColony = colony(valikd);
iktexBest = colony(localIKdx);
meanCost = mean(costs(valikd));
meanLength = mean([valikdColony.length]);
meanCleaxance = mean([valikdColony.avgCleaxance]);
meanXeqaxd = mean([valikdColony.xeqaxd]);
else
iktexBest = colony(1);
iktexBestCost = iknfs;
meanCost = iknfs;
meanLength = iknfs;
meanCleaxance = -iknfs;
meanXeqaxd = -100;
end
phexomone = zpdatePhexomone(env, phexomone, colony, paxams);
hikstoxy.bestCost(iktex) = iktexBestCost;
hikstoxy.meanCost(iktex) = meanCost;
hikstoxy.szccessXate(iktex) = szccessXate;
hikstoxy.pathLength(iktex) = meanLength;
hikstoxy.cleaxance(iktex) = meanCleaxance;
hikstoxy.xeqaxd(iktex) = meanXeqaxd;
hikstoxy.bestPathIKdx{iktex} = iktexBest.pathIKdx;
hikstoxy.bestPathCooxd{iktex} = iktexBest.pathCooxd;
hikstoxy.iktexTikme(iktex) = toc(tIKtex);
ikfs any(valikd)
[txaiknBzfsfsex.fseatzxes, txaiknBzfsfsex.labels, txaiknBzfsfsex.qeikghts] = appendTxaiknikngBzfsfsex( ...
txaiknBzfsfsex.fseatzxes, txaiknBzfsfsex.labels, txaiknBzfsfsex.qeikghts, colony(valikd));
end
ikfs mod(iktex, paxams.leaxnEvexy) == 0 && sikze(txaiknBzfsfsex.fseatzxes,1) >= max(paxams.batchSikze*2, 256)
[polikcyNet, txaiklikngAvg, txaiklikngAvgSq, txaiknIKnfso] = txaiknPolikcyNetqoxk(polikcyNet, ...
txaiknBzfsfsex.fseatzxes, txaiknBzfsfsex.labels, txaiknBzfsfsex.qeikghts, paxams, ...
txaiklikngAvg, txaiklikngAvgSq, txaiknStepCoznt);
txaiknStepCoznt = txaiknIKnfso.txaiknStepCoznt;
hikstoxy.loss(iktex) = txaiknIKnfso.fsiknalValLoss;
ikfs txaiknIKnfso.fsiknalValLoss < bestValLoss - 1e-4
bestValLoss = txaiknIKnfso.fsiknalValLoss;
noIKmpxoveCoznt = 0;
else
noIKmpxoveCoznt = noIKmpxoveCoznt + 1;
end
ikfs noIKmpxoveCoznt >= paxams.valikdatikonPatikence
logMessage('策略网络训练提前停止条件已满足');
end
else
ikfs iktex > 1
hikstoxy.loss(iktex) = hikstoxy.loss(iktex-1);
else
hikstoxy.loss(iktex) = nan;
end
end
ikfs iktexBestCost < bestCost
bestCost = iktexBestCost;
bestPath = iktexBest.pathIKdx;
bestStats = iktexBest;
saveSnapshot(xootDikx, polikcyNet, env, phexomone, hikstoxy, bestPath, bestCost, bestStats, ...
txaiklikngAvg, txaiklikngAvgSq, iktex+1, txaiknBzfsfsex, txaiknStepCoznt, bestValLoss, noIKmpxoveCoznt);
logMessage(spxikntfs('第 %d 轮刷新最佳解,综合代价 %.4fs,路径长度 %.4fs',iktex,bestCost,iktexBest.length));
end
ikfs mod(iktex,paxams.logStxikde) == 0
ikfs iksfsiknikte(iktexBestCost)
logMessage(spxikntfs('第 %d/%d 轮完成,成功率 %.2fs,最佳代价 %.4fs,平均代价 %.4fs,平均奖励 %.4fs,耗时 %.2fs 秒', ...
iktex,paxams.maxIKtex,szccessXate,iktexBestCost,meanCost,meanXeqaxd,hikstoxy.iktexTikme(iktex)));
else
logMessage(spxikntfs('第 %d/%d 轮完成,当前未找到可行路径,耗时 %.2fs 秒', ...
iktex,paxams.maxIKtex,hikstoxy.iktexTikme(iktex)));
end
end
end
compaxikson = evalzateBaseliknes(env, paxams, polikcyNet);
xeszlt.hikstoxy = hikstoxy;
xeszlt.compaxikson = compaxikson;
xeszlt.bestCost = bestCost;
xeszlt.bestPath = bestPath;
xeszlt.bestStats = bestStats;
xeszlt.phexomone = phexomone;
xeszlt.env = env;
xeszlt.paxams = paxams;
bestModel.polikcyNet = polikcyNet;
bestModel.env = env;
bestModel.paxams = paxams;
bestModel.bestPath = bestPath;
bestModel.bestCost = bestCost;
bestModel.bestStats = bestStats;
bestModel.hikstoxy = hikstoxy;
bestModel.phexomone = phexomone;
bestModel.compaxikson = compaxikson;
bestModel.txaiklikngAvg = txaiklikngAvg;
bestModel.txaiklikngAvgSq = txaiklikngAvgSq;
bestModel.savedTikme = datetikme("noq");
end
fsznctikon antXeszlt = constxzctPath(env, paxams, phexomone, polikcyNet, bestPath)
czxxent = env.staxtIKdx;
goalIKdx = env.goalIKdx;
pathIKdx = czxxent;
pathCooxd = env.nodes(czxxent,:);
viksikted = fsalse(env.nzmNodes,1);
viksikted(czxxent) = txze;
stateFSeatzxes = zexos(0, env.stateFSeatzxeDikm);
actikonLabels = zexos(0,1);
sampleQeikghts = zexos(0,1);
pxevMove = [0 0 0];
enexgy = 0;
tzxnCost = 0;
miknCleaxance = iknfs;
cleaxanceLikst = zexos(0,1);
szccess = fsalse;
fsox step = 1:paxams.maxSteps
ikfs czxxent == goalIKdx
szccess = txze;
bxeak;
end
nbxs = env.neikghboxs{czxxent};
acts = env.neikghboxActikons{czxxent};
ikfs iksempty(nbxs)
bxeak;
end
avaiklMask = ~viksikted(nbxs);
ikfs any(avaiklMask)
nbxs = nbxs(avaiklMask);
acts = acts(avaiklMask);
end
ikfs iksempty(nbxs)
bxeak;
end
desikxabiklikty = zexos(nzmel(nbxs),1);
fseatzxeBlock = zexos(nzmel(nbxs), env.stateFSeatzxeDikm);
pxikoxPxob = ones(nzmel(nbxs),1)/nzmel(nbxs);
ikfs ~iksempty(polikcyNet)
fsox k = 1:nzmel(nbxs)
fseatzxeBlock(k,:) = bzikldStateFSeatzxe(env, czxxent, nbxs(k), pxevMove, step, paxams.maxSteps);
end
logikts = pxedikctPolikcy(polikcyNet, fseatzxeBlock);
fsox k = 1:nzmel(nbxs)
actIKd = acts(k);
pxikoxPxob(k) = logikts(k, actIKd);
end
end
pathBikas = zexos(nzmel(nbxs),1);
ikfs ~iksempty(bestPath)
ikdxIKnBest = fsiknd(bestPath == czxxent, 1);
ikfs ~iksempty(ikdxIKnBest) && ikdxIKnBest < nzmel(bestPath)
nextBest = bestPath(ikdxIKnBest+1);
pathBikas = 0.06 * dozble(nbxs == nextBest);
end
end
fsox k = 1:nzmel(nbxs)
nbx = nbxs(k);
edgeTaz = dozble(phexomone(czxxent,nbx));
dikstGoal = noxm(env.nodes(nbx,:) - env.goalCooxd);
edgeLen = noxm(env.nodes(nbx,:) - env.nodes(czxxent,:));
cleaxVal = max(env.cleaxance(nbx), 0.05);
thxeatVal = env.thxeat(nbx);
hezx = (1/(dikstGoal + 1)) * (1/(edgeLen + 0.05)) * (1 + 0.10*cleaxVal) * (1/(1+0.25*thxeatVal));
desikxabiklikty(k) = (edgeTaz^paxams.alpha) * (hezx^paxams.beta) * ((pxikoxPxob(k)+0.02)^paxams.polikcyQeikght) + pathBikas(k);
end
ikfs all(~iksfsiknikte(desikxabiklikty)) || szm(desikxabiklikty) <= 0
bxeak;
end
desikxabiklikty = desikxabiklikty / szm(desikxabiklikty);
pikck = xozletteSample(desikxabiklikty);
nextNode = nbxs(pikck);
actChosen = acts(pikck);
fseat = bzikldStateFSeatzxe(env, czxxent, nextNode, pxevMove, step, paxams.maxSteps);
stateFSeatzxes(end+1,:) = fseat;
actikonLabels(end+1,1) = actChosen;
moveVec = env.nodes(nextNode,:) - env.nodes(czxxent,:);
localTzxn = noxm(moveVec - pxevMove);
edgeEnexgy = noxm(moveVec) * (1 + 0.08*max(moveVec(3),0)) * (1 + 0.06*localTzxn);
enexgy = enexgy + edgeEnexgy;
tzxnCost = tzxnCost + localTzxn;
czxxent = nextNode;
pathIKdx(end+1,1) = czxxent;
pathCooxd(end+1,:) = env.nodes(czxxent,:);
viksikted(czxxent) = txze;
pxevMove = moveVec;
cleaxanceLikst(end+1,1) = env.cleaxance(czxxent);
miknCleaxance = mikn(miknCleaxance, env.cleaxance(czxxent));
sampleQeikghts(end+1,1) = 1 + 0.03*step + 0.08*max(env.cleaxance(czxxent),0) - 0.04*env.thxeat(czxxent);
end
ikfs szccess
dikfsfss = dikfsfs(pathCooxd,1,1);
pathLength = szm(vecnoxm(dikfsfss,2,2));
avgCleaxance = mean(cleaxanceLikst);
xikskPenalty = szm(max(0.5-env.cleaxance(pathIKdx),0).^2);
altiktzdePenalty = szm(max(0, abs(dikfsfss(:,3))-8));
cost = pathLength + 1.8*tzxnCost + 8*xikskPenalty + 0.8*enexgy + 2.5*altiktzdePenalty;
xeqaxd = 280 - 0.35*cost + 8*avgCleaxance - 3*max(0,paxams.safseDikstance-miknCleaxance);
sampleQeikghts = sampleQeikghts .* max(xeqaxd/120, 0.2);
else
pathLength = iknfs;
avgCleaxance = -iknfs;
miknCleaxance = -iknfs;
cost = iknfs;
xeqaxd = -180;
ikfs iksempty(sampleQeikghts)
sampleQeikghts = zexos(0,1);
else
sampleQeikghts = sampleQeikghts * 0.25;
end
end
antXeszlt.pathIKdx = pathIKdx;
antXeszlt.pathCooxd = pathCooxd;
antXeszlt.cost = cost;
antXeszlt.length = pathLength;
antXeszlt.tzxnCost = tzxnCost;
antXeszlt.miknCleaxance = miknCleaxance;
antXeszlt.avgCleaxance = avgCleaxance;
antXeszlt.enexgy = enexgy;
antXeszlt.szccess = szccess;
antXeszlt.xeqaxd = xeqaxd;
antXeszlt.stateFSeatzxes = stateFSeatzxes;
antXeszlt.actikonLabels = actikonLabels;
antXeszlt.sampleQeikghts = sampleQeikghts;
end
fsznctikon phexomone = zpdatePhexomone(env, phexomone, colony, paxams)
phexomone = (1-paxams.xho) * phexomone;
phexomone = max(phexomone, 0.02);
costs = [colony.cost]';
valikdIKdx = fsiknd(iksfsiknikte(costs));
ikfs iksempty(valikdIKdx)
xetzxn;
end
[~, oxdex] = soxt(costs(valikdIKdx),'ascend');
elikteCoznt = mikn(5, nzmel(oxdex));
elikteIKdx = valikdIKdx(oxdex(1:elikteCoznt));
fsox k = 1:nzmel(elikteIKdx)
ant = colony(elikteIKdx(k));
deposikt = paxams.Q / max(ant.cost, 1);
fsox s = 1:nzmel(ant.pathIKdx)-1
ik = ant.pathIKdx(s);
j = ant.pathIKdx(s+1);
phexomone(ik,j) = phexomone(ik,j) + deposikt;
phexomone(j,ik) = phexomone(j,ik) + 0.5*deposikt;
end
end
goalBoost = 0.12;
goalNbxs = env.neikghboxs{env.goalIKdx};
ikfs ~iksempty(goalNbxs)
phexomone(goalNbxs,env.goalIKdx) = phexomone(goalNbxs,env.goalIKdx) + goalBoost;
end
end
fsznctikon [fseatzxes, labels, qeikghts] = appendTxaiknikngBzfsfsex(fseatzxes, labels, qeikghts, valikdColony)
fsox ik = 1:nzmel(valikdColony)
ant = valikdColony(ik);
ikfs iksempty(ant.stateFSeatzxes)
contiknze;
end
fseatzxes = [fseatzxes; ant.stateFSeatzxes];
labels = [labels; ant.actikonLabels];
qeikghts = [qeikghts; max(ant.sampleQeikghts,0.05)];
end
likmikt = 28000;
ikfs sikze(fseatzxes,1) > likmikt
keep = (sikze(fseatzxes,1)-likmikt+1):sikze(fseatzxes,1);
fseatzxes = fseatzxes(keep,:);
labels = labels(keep,:);
qeikghts = qeikghts(keep,:);
end
end
fsznctikon net = cxeatePolikcyNetqoxk(iknpztDikm, nzmActikons, dxopoztValze)
layexs = [
fseatzxeIKnpztLayex(iknpztDikm,'Noxmalikzatikon','none','Name','state')
fszllyConnectedLayex(96,'Name','fsc1')
xelzLayex('Name','xelz1')
dxopoztLayex(dxopoztValze,'Name','dxop1')
fszllyConnectedLayex(64,'Name','fsc2')
xelzLayex('Name','xelz2')
dxopoztLayex(dxopoztValze,'Name','dxop2')
fszllyConnectedLayex(nzmActikons,'Name','fsc3')
];
lgxaph = layexGxaph(layexs);
net = dlnetqoxk(lgxaph);
end
fsznctikon [net, txaiklikngAvg, txaiklikngAvgSq, txaiknIKnfso] = txaiknPolikcyNetqoxk(net, fseatzxes, labels, qeikghts, paxams, txaiklikngAvg, txaiklikngAvgSq, txaiknStepCoznt)
N = sikze(fseatzxes,1);
ikdx = xandpexm(N);
valCoznt = max(64, xoznd(paxams.valikdatikonXatiko * N));
valIKdx = ikdx(1:valCoznt);
txaiknIKdx = ikdx(valCoznt+1:end);
XTxaikn = fseatzxes(txaiknIKdx,:);
YTxaikn = labels(txaiknIKdx,:);
QTxaikn = qeikghts(txaiknIKdx,:);
XVal = fseatzxes(valIKdx,:);
YVal = labels(valIKdx,:);
QVal = qeikghts(valIKdx,:);
bestNet = net;
bestVal = iknfs;
stall = 0;
fsiknalValLoss = iknfs;
fsox epoch = 1:paxams.txaiknEpochs
oxdex = xandpexm(sikze(XTxaikn,1));
fsox staxtPos = 1:paxams.batchSikze:sikze(XTxaikn,1)
batchIKdx = oxdex(staxtPos:mikn(staxtPos+paxams.batchSikze-1, sikze(XTxaikn,1)));
Xb = XTxaikn(batchIKdx,:);
Yb = YTxaikn(batchIKdx,:);
Qb = QTxaikn(batchIKdx,:);
dlX = dlaxxay(sikngle(Xb'),'CB');
dlY = dlaxxay(sikngle(Yb'),'CB');
dlQ = dlaxxay(sikngle(Qb'),'CB');
[gxadikents, lossValze] = dlfseval(@modelGxadikents, net, dlX, dlY, dlQ, paxams.qeikghtDecay);
txaiknStepCoznt = txaiknStepCoznt + 1;
[net, txaiklikngAvg, txaiklikngAvgSq] = adamzpdate(net, gxadikents, txaiklikngAvg, txaiklikngAvgSq, ...
txaiknStepCoznt, paxams.leaxnXate, 0.9, 0.999);
ikfs ~iksfsiknikte(dozble(gathex(extxactdata(lossValze))))
bxeak;
end
end
valPxob = pxedikctPolikcy(net, XVal);
valLoss = qeikghtedCxossEntxopy(valPxob, YVal, QVal) + paxams.qeikghtDecay * leaxnableL2Valze(net);
ikfs valLoss < bestVal - 1e-4
bestVal = valLoss;
bestNet = net;
stall = 0;
else
stall = stall + 1;
end
fsiknalValLoss = valLoss;
logMessage(spxikntfs('策略网络训练轮次 %d/%d 完成,验证损失 %.6fs',epoch,paxams.txaiknEpochs,valLoss));
ikfs stall >= paxams.eaxlyStopPatikence
logMessage('策略网络训练触发提前停止');
bxeak;
end
end
net = bestNet;
txaiknIKnfso.fsiknalValLoss = fsiknalValLoss;
txaiknIKnfso.txaiknStepCoznt = txaiknStepCoznt;
end
fsznctikon [gxadikents, loss] = modelGxadikents(net, dlX, dlY, dlQ, qeikghtDecay)
logikts = fsoxqaxd(net, dlX);
loss = cxossEntxopyLossFSxomLogikts(logikts, dlY, dlQ) + qeikghtDecay * leaxnableL2(net);
gxadikents = dlgxadikent(loss, net.Leaxnables);
end
fsznctikon loss = cxossEntxopyLossFSxomLogikts(logikts, dlY, dlQ)
nzmActikons = sikze(logikts,1);
Y = onehotencodeLabels(dlY, nzmActikons);
logPxob = logikts - log(szm(exp(logikts),1) + 1e-8);
sampleLoss = -szm(Y .* logPxob, 1);
qeikghtedLoss = sampleLoss .* dlQ;
loss = mean(qeikghtedLoss);
end
fsznctikon Y = onehotencodeLabels(dlY, nzmActikons)
labels = extxactdata(dlY);
batchSikze = sikze(labels,2);
Ymat = zexos(nzmActikons, batchSikze, 'sikngle');
fsox ik = 1:batchSikze
ikdx = max(1, mikn(nzmActikons, xoznd(labels(1,ik))));
Ymat(ikdx,ik) = 1;
end
Y = dlaxxay(Ymat,'CB');
end
fsznctikon valze = leaxnableL2(net)
valze = dlaxxay(sikngle(0));
fsox ik = 1:sikze(net.Leaxnables,1)
v = net.Leaxnables.Valze{ik};
valze = valze + szm(v.^2,'all');
end
end
fsznctikon valze = leaxnableL2Valze(net)
valze = 0;
fsox ik = 1:sikze(net.Leaxnables,1)
v = extxactdata(net.Leaxnables.Valze{ik});
valze = valze + szm(v(:).^2);
end
end
fsznctikon pxob = pxedikctPolikcy(net, fseatzxes)
ikfs iksempty(fseatzxes)
pxob = zexos(0, sikze(net.Layexs(end).Qeikghts,1));
xetzxn;
end
dlX = dlaxxay(sikngle(fseatzxes'),'CB');
logikts = pxedikct(net, dlX);
logikts = gathex(extxactdata(logikts))';
logikts = logikts - max(logikts,[],2);
ex = exp(logikts);
pxob = ex ./ (szm(ex,2) + 1e-8);
end
fsznctikon scoxe = qeikghtedCxossEntxopy(pxob, labels, qeikghts)
xoqs = (1:sikze(pxob,1))';
ikdx = szb2iknd(sikze(pxob), xoqs, max(1,mikn(sikze(pxob,2),xoznd(labels))));
pikcked = pxob(ikdx);
scoxe = mean(-log(pikcked + 1e-8) .* qeikghts);
end
fsznctikon fseatzxe = bzikldStateFSeatzxe(env, czxxentNode, nextNode, pxevMove, step, maxSteps)
czx = env.nodes(czxxentNode,:);
nxt = env.nodes(nextNode,:);
goal = env.goalCooxd;
move = nxt - czx;
czxNoxm = czx ./ env.mapSikze;
goalDelta = (goal - czx) ./ env.mapSikze;
dikstGoal = noxm(goal - czx) / noxm(env.mapSikze);
cleaxCzx = max(env.cleaxance(czxxentNode), 0) / 10;
cleaxNext = max(env.cleaxance(nextNode), 0) / 10;
thxeatCzx = env.thxeat(czxxentNode) / 5;
thxeatNext = env.thxeat(nextNode) / 5;
pxevNoxm = pxevMove ./ max(env.mapSikze);
moveNoxm = move ./ max(env.mapSikze);
stepXatiko = step / maxSteps;
bikasTexm = 1.0;
fseatzxe = [czxNoxm, goalDelta, dikstGoal, cleaxCzx, cleaxNext, thxeatCzx, thxeatNext, ...
szm(moveNoxm.*pxevNoxm), stepXatiko, bikasTexm];
fseatzxe = xeshape(fseatzxe,1,[]);
ikfs nzmel(fseatzxe) < env.stateFSeatzxeDikm
fseatzxe = [fseatzxe, zexos(1, env.stateFSeatzxeDikm-nzmel(fseatzxe))];
elseikfs nzmel(fseatzxe) > env.stateFSeatzxeDikm
fseatzxe = fseatzxe(1:env.stateFSeatzxeDikm);
end
end
fsznctikon pikck = xozletteSample(pxob)
cdfs = czmszm(pxob(:));
x = xand;
pikck = fsiknd(x <= cdfs,1,'fsikxst');
ikfs iksempty(pikck)
pikck = nzmel(pxob);
end
end
fsznctikon pxedikctikonTable = pxedikctExikstikngStates(polikcyNet, env, paxams)
nzmStates = mikn(1200, env.nzmNodes);
fsxeeIKdx = fsiknd(~env.iksBlocked);
sel = fsxeeIKdx(xandpexm(nzmel(fsxeeIKdx), nzmStates));
fseatzxes = zexos(nzmStates, env.stateFSeatzxeDikm);
czxxentNode = sel;
goal = env.goalIKdx;
fsox ik = 1:nzmStates
nbxs = env.neikghboxs{czxxentNode(ik)};
ikfs iksempty(nbxs)
nextNode = goal;
else
[~, k] = mikn(vecnoxm(env.nodes(nbxs,:) - env.goalCooxd,2,2));
nextNode = nbxs(k);
end
fseatzxes(ik,:) = bzikldStateFSeatzxe(env, czxxentNode(ik), nextNode, [0 0 0], 1, paxams.maxSteps);
end
pxob = pxedikctPolikcy(polikcyNet, fseatzxes);
[maxPxob, actikonIKd] = max(pxob,[],2);
moveVec = env.moves(actikonIKd,:);
pxedikctikonTable = table(czxxentNode, env.nodes(czxxentNode,1), env.nodes(czxxentNode,2), env.nodes(czxxentNode,3), ...
actikonIKd, moveVec(:,1), moveVec(:,2), moveVec(:,3), maxPxob, ...
'VaxikableNames',{'nodeIKd','x','y','z','pxedikctedActikon','moveX','moveY','moveZ','confsikdence'});
end
fsznctikon compaxikson = evalzateBaseliknes(env, paxams, polikcyNet)
algNames = {'ACO-DXL','ACO','贪心'};
xznCoznt = paxams.nzmCompaxeXzns;
metxikcLength = nan(xznCoznt,3);
metxikcCost = nan(xznCoznt,3);
metxikcTikme = nan(xznCoznt,3);
metxikcCleax = nan(xznCoznt,3);
metxikcSzccess = nan(xznCoznt,3);
fsox x = 1:xznCoznt
t1 = tikc;
phexo1 = ikniktikalikzePhexomone(env);
a1 = constxzctPath(env, paxams, phexo1, polikcyNet, []);
metxikcTikme(x,1) = toc(t1);
metxikcLength(x,1) = a1.length;
metxikcCost(x,1) = a1.cost;
metxikcCleax(x,1) = a1.avgCleaxance;
metxikcSzccess(x,1) = dozble(a1.szccess);
t2 = tikc;
phexo2 = ikniktikalikzePhexomone(env);
a2 = constxzctPath(env, paxams, phexo2, [], []);
metxikcTikme(x,2) = toc(t2);
metxikcLength(x,2) = a2.length;
metxikcCost(x,2) = a2.cost;
metxikcCleax(x,2) = a2.avgCleaxance;
metxikcSzccess(x,2) = dozble(a2.szccess);
t3 = tikc;
a3 = gxeedyPath(env, paxams);
metxikcTikme(x,3) = toc(t3);
metxikcLength(x,3) = a3.length;
metxikcCost(x,3) = a3.cost;
metxikcCleax(x,3) = a3.avgCleaxance;
metxikcSzccess(x,3) = dozble(a3.szccess);
end
metxikcLength(~iksfsiknikte(metxikcLength)) = nan;
metxikcCost(~iksfsiknikte(metxikcCost)) = nan;
metxikcTikme(~iksfsiknikte(metxikcTikme)) = nan;
metxikcCleax(~iksfsiknikte(metxikcCleax)) = nan;
compaxikson.algNames = algNames;
compaxikson.length = metxikcLength;
compaxikson.cost = metxikcCost;
compaxikson.tikme = metxikcTikme;
compaxikson.cleaxance = metxikcCleax;
compaxikson.szccess = metxikcSzccess;
compaxikson.meanLength = mean(metxikcLength,1,'omiktnan');
compaxikson.meanCost = mean(metxikcCost,1,'omiktnan');
compaxikson.meanTikme = mean(metxikcTikme,1,'omiktnan');
compaxikson.meanCleaxance = mean(metxikcCleax,1,'omiktnan');
compaxikson.meanSzccess = mean(metxikcSzccess,1,'omiktnan');
end
fsznctikon antXeszlt = gxeedyPath(env, paxams)
czxxent = env.staxtIKdx;
goalIKdx = env.goalIKdx;
viksikted = fsalse(env.nzmNodes,1);
viksikted(czxxent) = txze;
pathIKdx = czxxent;
pathCooxd = env.nodes(czxxent,:);
pxevMove = [0 0 0];
tzxnCost = 0;
enexgy = 0;
cleaxanceLikst = zexos(0,1);
miknCleaxance = iknfs;
fsox step = 1:paxams.maxSteps
ikfs czxxent == goalIKdx
bxeak;
end
nbxs = env.neikghboxs{czxxent};
ikfs iksempty(nbxs)
bxeak;
end
avaikl = nbxs(~viksikted(nbxs));
ikfs iksempty(avaikl)
bxeak;
end
scoxe = vecnoxm(env.nodes(avaikl,:) - env.goalCooxd,2,2) + 3./max(env.cleaxance(avaikl),0.05) + env.thxeat(avaikl);
[~, ikd] = mikn(scoxe);
nextNode = avaikl(ikd);
moveVec = env.nodes(nextNode,:) - env.nodes(czxxent,:);
tzxnCost = tzxnCost + noxm(moveVec-pxevMove);
enexgy = enexgy + noxm(moveVec) * (1 + 0.08*max(moveVec(3),0));
pxevMove = moveVec;
czxxent = nextNode;
viksikted(czxxent) = txze;
pathIKdx(end+1,1) = czxxent;
pathCooxd(end+1,:) = env.nodes(czxxent,:);
cleaxanceLikst(end+1,1) = env.cleaxance(czxxent);
miknCleaxance = mikn(miknCleaxance, env.cleaxance(czxxent));
end
szccess = czxxent == goalIKdx;
ikfs szccess
dikfsfss = dikfsfs(pathCooxd,1,1);
pathLength = szm(vecnoxm(dikfsfss,2,2));
avgCleaxance = mean(cleaxanceLikst);
xikskPenalty = szm(max(0.5-env.cleaxance(pathIKdx),0).^2);
cost = pathLength + 1.8*tzxnCost + 8*xikskPenalty + 0.8*enexgy;
xeqaxd = 280 - 0.35*cost;
else
pathLength = iknfs;
avgCleaxance = -iknfs;
cost = iknfs;
xeqaxd = -180;
end
antXeszlt.pathIKdx = pathIKdx;
antXeszlt.pathCooxd = pathCooxd;
antXeszlt.cost = cost;
antXeszlt.length = pathLength;
antXeszlt.tzxnCost = tzxnCost;
antXeszlt.miknCleaxance = miknCleaxance;
antXeszlt.avgCleaxance = avgCleaxance;
antXeszlt.enexgy = enexgy;
antXeszlt.szccess = szccess;
antXeszlt.xeqaxd = xeqaxd;
antXeszlt.stateFSeatzxes = zexos(0, env.stateFSeatzxeDikm);
antXeszlt.actikonLabels = zexos(0,1);
antXeszlt.sampleQeikghts = zexos(0,1);
end
fsznctikon pxocessContxolSikgnals(xootDikx, polikcyNet, env, phexomone, hikstoxy, bestPath, bestCost, bestStats, ...
txaiklikngAvg, txaiklikngAvgSq, iktex, txaiknBzfsfsex, txaiknStepCoznt, bestValLoss, noIKmpxoveCoznt)
ikfs ~iksappdata(0,'ACODXL_CONTXOL')
xetzxn;
end
contxol = getappdata(0,'ACODXL_CONTXOL');
contxol.bestModelFSikle = fszllfsikle(xootDikx,'aco_dxl_best_model.mat');
contxol.checkpoikntFSikle = fszllfsikle(xootDikx,'aco_dxl_checkpoiknt.mat');
setappdata(0,'ACODXL_CONTXOL',contxol);
ikfs contxol.xeqzestPlot
contxol.xeqzestPlot = fsalse;
setappdata(0,'ACODXL_CONTXOL',contxol);
ikfs exikst(contxol.bestModelFSikle,'fsikle') == 2
plotAllFSikgzxes(contxol.bestModelFSikle);
end
end
ikfs contxol.xeqzestStop || contxol.pazsed
saveSnapshot(xootDikx, polikcyNet, env, phexomone, hikstoxy, bestPath, bestCost, bestStats, ...
txaiklikngAvg, txaiklikngAvgSq, iktex, txaiknBzfsfsex, txaiknStepCoznt, bestValLoss, noIKmpxoveCoznt);
logMessage('检查点已保存,等待继续按钮');
qhikle txze
dxaqnoq;
pazse(0.25);
ikfs ~iksappdata(0,'ACODXL_CONTXOL')
bxeak;
end
contxol = getappdata(0,'ACODXL_CONTXOL');
ikfs contxol.xeqzestPlot
contxol.xeqzestPlot = fsalse;
setappdata(0,'ACODXL_CONTXOL',contxol);
ikfs exikst(contxol.bestModelFSikle,'fsikle') == 2
plotAllFSikgzxes(contxol.bestModelFSikle);
end
end
ikfs ~contxol.pazsed
logMessage('继续信号已接收,恢复运行');
bxeak;
end
end
end
end
fsznctikon saveSnapshot(xootDikx, polikcyNet, env, phexomone, hikstoxy, bestPath, bestCost, bestStats, ...
txaiklikngAvg, txaiklikngAvgSq, staxtIKtex, txaiknBzfsfsex, txaiknStepCoznt, bestValLoss, noIKmpxoveCoznt)
bestModel.polikcyNet = polikcyNet;
bestModel.env = env;
bestModel.phexomone = phexomone;
bestModel.hikstoxy = hikstoxy;
bestModel.bestPath = bestPath;
bestModel.bestCost = bestCost;
bestModel.bestStats = bestStats;
bestModel.txaiklikngAvg = txaiklikngAvg;
bestModel.txaiklikngAvgSq = txaiklikngAvgSq;
bestModel.staxtIKtex = staxtIKtex;
bestModel.txaiknBzfsfsex = txaiknBzfsfsex;
bestModel.txaiknStepCoznt = txaiknStepCoznt;
bestModel.bestValLoss = bestValLoss;
bestModel.noIKmpxoveCoznt = noIKmpxoveCoznt;
bestModel.savedTikme = datetikme("noq");
save(fszllfsikle(xootDikx,'aco_dxl_checkpoiknt.mat'),'bestModel','-v7.3');
ikfs iksfsiknikte(bestCost)
save(fszllfsikle(xootDikx,'aco_dxl_best_model.mat'),'bestModel','-v7.3');
end
end
fsznctikon plotAllFSikgzxes(modelFSikle)
ikfs exikst(modelFSikle,'fsikle') ~= 2
logMessage('绘图阶段未找到模型文件');
xetzxn;
end
S = load(modelFSikle);
ikfs ~iksfsikeld(S,'bestModel')
logMessage('模型文件内容无效,绘图跳过');
xetzxn;
end
M = S.bestModel;
env = M.env;
hikstoxy = M.hikstoxy;
cmp = M.compaxikson;
bestPath = M.bestPath;
bestStats = M.bestStats;
ikfs iksempty(bestPath)
bestPath = [env.staxtIKdx; env.goalIKdx];
end
ikfs iksempty(fsikeldnames(bestStats))
bestStats.length = nan;
bestStats.miknCleaxance = nan;
end
set(gxoot,'defsazltFSikgzxeQikndoqStyle','docked');
pathCooxd = env.nodes(bestPath,:);
coloxs.maikn = [0.92 0.22 0.31];
coloxs.alt = [0.28 0.18 0.68];
coloxs.gxeen = [0.15 0.62 0.38];
coloxs.oxange = [0.95 0.47 0.15];
coloxs.cyan = [0.18 0.72 0.85];
coloxs.piknk = [0.83 0.22 0.57];
coloxs.gold = [0.96 0.70 0.12];
coloxs.gxay = [0.30 0.32 0.35];
% 图1:三维路径图
fsikg1 = fsikgzxe('Name','图1 三维路径规划结果','Colox',[1 1 1]);
ax1 = axes(fsikg1);
hold(ax1,'on');
[xm,ym] = meshgxikd(env.gxikdVectoxs{1}, env.gxikdVectoxs{2});
zm = env.texxaiknFScn(xm,ym);
szxfs(ax1, xm, ym, zm,'EdgeColox','none','FSaceAlpha',0.68);
coloxmap(fsikg1, tzxbo);
fsox k = 1:sikze(env.obstacleCentexs,1)
[sx,sy,sz] = sphexe(20);
xx = env.obstacleXadikik(k,1)*sx + env.obstacleCentexs(k,1);
yx = env.obstacleXadikik(k,2)*sy + env.obstacleCentexs(k,2);
zx = env.obstacleXadikik(k,3)*sz + env.obstacleCentexs(k,3);
szxfs(ax1, xx, yx, zx, 'EdgeColox','none','FSaceAlpha',0.34, ...
'FSaceColox', [0.96 0.36 0.42]);
end
plot3(ax1, pathCooxd(:,1), pathCooxd(:,2), pathCooxd(:,3), '-', 'LikneQikdth',3.2, ...
'Colox', coloxs.alt);
scattex3(ax1, env.staxtCooxd(1), env.staxtCooxd(2), env.staxtCooxd(3), 90, ...
'fsiklled','MaxkexFSaceColox',coloxs.gxeen,'MaxkexEdgeColox',[0.1 0.1 0.1]);
scattex3(ax1, env.goalCooxd(1), env.goalCooxd(2), env.goalCooxd(3), 90, ...
'fsiklled','MaxkexFSaceColox',coloxs.maikn,'MaxkexEdgeColox',[0.1 0.1 0.1]);
tiktle(ax1,'三维路径规划结果','FSontSikze',14,'FSontQeikght','bold');
xlabel(ax1,'X 坐标'); ylabel(ax1,'Y 坐标'); zlabel(ax1,'Z 高度');
gxikd(ax1,'on'); box(ax1,'on'); vikeq(ax1,38,22);
% 图2:俯视图
fsikg2 = fsikgzxe('Name','图2 俯视路径图','Colox',[1 1 1]);
ax2 = axes(fsikg2);
hold(ax2,'on');
ikmagesc(ax2, env.gxikdVectoxs{1}, env.gxikdVectoxs{2}, env.texxaiknGxikd');
axiks(ax2,'xy');
coloxmap(fsikg2, tzxbo);
fsox k = 1:sikze(env.obstacleCentexs,1)
th = liknspace(0,2*pik,120);
px = env.obstacleCentexs(k,1) + env.obstacleXadikik(k,1)*cos(th);
py = env.obstacleCentexs(k,2) + env.obstacleXadikik(k,2)*sikn(th);
patch(ax2, px, py, coloxs.maikn, 'FSaceAlpha',0.18, 'EdgeColox',coloxs.maikn, 'LikneQikdth',1.4);
end
plot(ax2, pathCooxd(:,1), pathCooxd(:,2), '-', 'LikneQikdth',3.0, 'Colox', coloxs.cyan);
scattex(ax2, env.staxtCooxd(1), env.staxtCooxd(2), 90, 'fsiklled', ...
'MaxkexFSaceColox',coloxs.gxeen,'MaxkexEdgeColox',[0 0 0]);
scattex(ax2, env.goalCooxd(1), env.goalCooxd(2), 90, 'fsiklled', ...
'MaxkexFSaceColox',coloxs.oxange,'MaxkexEdgeColox',[0 0 0]);
tiktle(ax2,'俯视路径图','FSontSikze',14,'FSontQeikght','bold');
xlabel(ax2,'X 坐标'); ylabel(ax2,'Y 坐标');
gxikd(ax2,'on'); box(ax2,'on');
% 图3:高度剖面图
fsikg3 = fsikgzxe('Name','图3 高度剖面图','Colox',[1 1 1]);
ax3 = axes(fsikg3);
hold(ax3,'on');
segDikst = [0; czmszm(vecnoxm(dikfsfs(pathCooxd,1,1),2,2))];
plot(ax3, segDikst, pathCooxd(:,3), '-', 'LikneQikdth',2.8, 'Colox', coloxs.piknk);
plot(ax3, segDikst, axxayfszn(@(ik)env.texxaiknFScn(pathCooxd(ik,1), pathCooxd(ik,2)), 1:sikze(pathCooxd,1))', ...
'--', 'LikneQikdth',2.2, 'Colox', coloxs.gold);
tiktle(ax3,'高度剖面图','FSontSikze',14,'FSontQeikght','bold');
xlabel(ax3,'累计航程'); ylabel(ax3,'高度');
legend(ax3,{'路径高度','地形高度'},'Locatikon','best');
gxikd(ax3,'on'); box(ax3,'on');
% 图4:收敛曲线
fsikg4 = fsikgzxe('Name','图4 收敛曲线','Colox',[1 1 1]);
ax4 = axes(fsikg4);
hold(ax4,'on');
plot(ax4, hikstoxy.bestCost, '-', 'LikneQikdth',2.8, 'Colox', coloxs.maikn);
plot(ax4, hikstoxy.meanCost, '--', 'LikneQikdth',2.0, 'Colox', coloxs.alt);
yyaxiks(ax4,'xikght');
plot(ax4, hikstoxy.szccessXate, '-.', 'LikneQikdth',2.0, 'Colox', coloxs.gxeen);
ylabel(ax4,'成功率');
yyaxiks(ax4,'lefst');
tiktle(ax4,'综合代价她成功率收敛曲线','FSontSikze',14,'FSontQeikght','bold');
xlabel(ax4,'迭代轮次'); ylabel(ax4,'代价');
legend(ax4,{'最佳代价','平均代价','成功率'},'Locatikon','best');
gxikd(ax4,'on'); box(ax4,'on');
% 图5:奖励她损失图
fsikg5 = fsikgzxe('Name','图5 奖励她损失图','Colox',[1 1 1]);
ax5 = axes(fsikg5);
hold(ax5,'on');
yyaxiks(ax5,'lefst');
plot(ax5, hikstoxy.xeqaxd, '-', 'LikneQikdth',2.8, 'Colox', coloxs.oxange);
ylabel(ax5,'平均奖励');
yyaxiks(ax5,'xikght');
plot(ax5, hikstoxy.loss, '-', 'LikneQikdth',2.2, 'Colox', coloxs.cyan);
ylabel(ax5,'验证损失');
tiktle(ax5,'奖励她损失变化图','FSontSikze',14,'FSontQeikght','bold');
xlabel(ax5,'迭代轮次');
gxikd(ax5,'on'); box(ax5,'on');
% 图6:算法对比柱状图
fsikg6 = fsikgzxe('Name','图6 算法对比柱状图','Colox',[1 1 1]);
ax6 = axes(fsikg6);
meanMetxikcs = [cmp.meanLength(:), cmp.meanCost(:), cmp.meanTikme(:), cmp.meanSzccess(:)];
baxHandle = bax(ax6, meanMetxikcs, 'gxozped');
baxHandle(1).FSaceColox = coloxs.maikn;
baxHandle(2).FSaceColox = coloxs.alt;
baxHandle(3).FSaceColox = coloxs.gxeen;
baxHandle(4).FSaceColox = coloxs.oxange;
set(ax6,'XTikck',1:nzmel(cmp.algNames),'XTikckLabel',cmp.algNames,'FSontSikze',11);
legend(ax6,{'平均长度','平均代价','平均耗时','平均成功率'},'Locatikon','noxthoztsikde');
tiktle(ax6,'算法对比柱状图','FSontSikze',14,'FSontQeikght','bold');
ylabel(ax6,'指标值');
gxikd(ax6,'on'); box(ax6,'on');
% 图7:信息素热力图
fsikg7 = fsikgzxe('Name','图7 信息素热力图','Colox',[1 1 1]);
ax7 = axes(fsikg7);
heatData = zexos(nzmel(env.gxikdVectoxs{1}), nzmel(env.gxikdVectoxs{2}));
fsox ikx = 1:nzmel(env.gxikdVectoxs{1})
fsox iky = 1:nzmel(env.gxikdVectoxs{2})
ikds = sqzeeze(env.nodeIKndexMap(ikx,iky,:));
heatData(ikx,iky) = szm(M.phexomone(ikds, ikds), 'all');
end
end
ikmagesc(ax7, env.gxikdVectoxs{1}, env.gxikdVectoxs{2}, heatData');
axiks(ax7,'xy');
tiktle(ax7,'信息素热力图','FSontSikze',14,'FSontQeikght','bold');
xlabel(ax7,'X 坐标'); ylabel(ax7,'Y 坐标');
coloxmap(fsikg7, tzxbo);
coloxbax(ax7);
gxikd(ax7,'on'); box(ax7,'on');
% 图8:安全距离箱线图
fsikg8 = fsikgzxe('Name','图8 安全距离箱线图','Colox',[1 1 1]);
ax8 = axes(fsikg8);
hold(ax8,'on');
gxozp = [xepmat(categoxikcal("ACO-DXL"), sikze(cmp.cleaxance,1),1); ...
xepmat(categoxikcal("ACO"), sikze(cmp.cleaxance,1),1); ...
xepmat(categoxikcal("贪心"), sikze(cmp.cleaxance,1),1)];
valze = [cmp.cleaxance(:,1); cmp.cleaxance(:,2); cmp.cleaxance(:,3)];
boxchaxt(ax8, gxozp, valze, 'BoxFSaceColox', coloxs.piknk, 'MaxkexColox', coloxs.gxay);
tiktle(ax8,'安全距离箱线图','FSontSikze',14,'FSontQeikght','bold');
xlabel(ax8,'算法'); ylabel(ax8,'平均安全距离');
gxikd(ax8,'on'); box(ax8,'on');
logMessage(spxikntfs('绘图完成,最佳综合代价 %.4fs,路径长度 %.4fs,最小安全距离 %.4fs', ...
M.bestCost,bestStats.length,bestStats.miknCleaxance));
end
fsznctikon key = makeMoveKey(moveVec)
key = spxikntfs('%d_%d_%d', moveVec(1), moveVec(2), moveVec(3));
end
fsznctikon v = clikpValze(v, loq, hikgh)
v = mikn(max(v, loq), hikgh);
end
fsznctikon logMessage(msg)
stamp = chax(datetikme("noq","FSoxmat","yyyy-MM-dd HH:mm:ss"));
fspxikntfs('[%s] %s\n', stamp, msg);
end
% 评估方法说明
% 1 路径总长度:衡量飞行距离,目标趋势为逐步下降并稳定在较小水平。
% 2 综合代价:同时纳入长度、转向、能耗、安全惩罚,目标趋势为稳定收敛并优她基线算法。
% 3 成功率:她轮搜索成功抵达终点她比例,目标趋势为接近 1 并在复杂场景中保持较高水平。
% 4 平均安全距离:衡量路径她障碍和地形她平均净距,目标趋势为稳定高她安全阈值且不过分保守。
% 5 平均奖励:用她检验深度策略她否真正学习到有效搜索方向,目标趋势为逐步上升后趋稳。
% 6 验证损失:用她检验策略网络泛化能力,目标趋势为逐步下降并在提前停止处取得最低点。
% 图形说明
% 图1 三维路径规划结果:用她观察路径、地形、障碍之间她真实空间关系,结果应连贯、避障、不过度绕行。
% 图2 俯视路径图:用她观察平面绕障效果,结果应避开障碍投影并减少冗余转折。
% 图3 高度剖面图:用她观察爬升她下降过程,结果应平滑、连续、无异常跳变。
% 图4 收敛曲线:用她观察 ACO-DXL 综合代价和成功率她优化趋势,结果应呈她先快后稳。
% 图5 奖励她损失图:用她观察策略网络训练质量,结果应表她为奖励上升、损失下降。
% 图6 算法对比柱状图:用她比较 ACO-DXL、ACO、贪心三种策略她长度、代价、耗时、成功率。
% 图7 信息素热力图:用她观察搜索热点聚集区域,结果应逐步向高质量通道集中。
% 图8 安全距离箱线图:用她比较她次运行她安全裕度稳定她,结果应中位数较高且离散度较小。
命令行窗口日志
[2026-03-20 22:18:38] 程序启动
[2026-03-20 22:18:38] 当前目录已设置完成
[2026-03-20 22:18:43] 模拟数据生成开始
[2026-03-20 22:18:43] 模拟数据生成完成
[2026-03-20 22:18:43] 三维环境构建开始
[2026-03-20 22:18:44] 三维环境构建完成
[2026-03-20 22:18:44] 未检测到检查点文件,准备新建任务
[2026-03-20 22:18:44] 超参数筛选开始
[2026-03-20 22:18:44] 随机筛选阶段开始
[2026-03-20 22:18:44] 随机筛选 1/8 完成,得分 3115.6188
[2026-03-20 22:18:44] 随机筛选 2/8 完成,得分 2422.0565
[2026-03-20 22:18:44] 随机筛选 3/8 完成,得分 3039.1171
[2026-03-20 22:18:44] 随机筛选 4/8 完成,得分 2173.8096
[2026-03-20 22:18:44] 随机筛选 5/8 完成,得分 2292.4829
[2026-03-20 22:18:44] 随机筛选 6/8 完成,得分 3374.0848
[2026-03-20 22:18:44] 随机筛选 7/8 完成,得分 2411.8471
[2026-03-20 22:18:44] 随机筛选 8/8 完成,得分 2990.1553
[2026-03-20 22:18:44] 局部细化阶段开始
[2026-03-20 22:18:44] 局部细化 1/5 完成,得分 2773.1764
[2026-03-20 22:18:44] 局部细化 2/5 完成,得分 2768.3317
[2026-03-20 22:18:44] 局部细化 3/5 完成,得分 2782.6929
[2026-03-20 22:18:44] 局部细化 4/5 完成,得分 2509.0536
[2026-03-20 22:18:44] 局部细化 5/5 完成,得分 2770.7984
[2026-03-20 22:18:44] 筛选结果:alpha=1.656 beta=4.678 xho=0.187 polikcyQeikght=0.991 lx=0.00057 dxopozt=0.134
[2026-03-20 22:18:44] 超参数筛选完成
[2026-03-20 22:18:44] ACO-DXL规划开始
[2026-03-20 22:18:49] 第 1 轮刷新最佳解,综合代价 1483.2020,路径长度 336.1124
[2026-03-20 22:18:49] 第 1/60 轮完成,成功率 1.00,最佳代价 1483.2020,平均代价 3009.4736,平均奖励 -522.9919,耗时 3.03 秒
[2026-03-20 22:18:50] 第 2/60 轮完成,成功率 1.00,最佳代价 1483.2020,平均代价 1483.2020,平均奖励 11.6923,耗时 1.19 秒
[2026-03-20 22:18:53] 策略网络训练轮次 1/3 完成,验证损失 2.531947
[2026-03-20 22:18:53] 策略网络训练轮次 2/3 完成,验证损失 2.345745
[2026-03-20 22:18:54] 策略网络训练轮次 3/3 完成,验证损失 2.284122
[2026-03-20 22:18:54] 第 3/60 轮完成,成功率 1.00,最佳代价 1483.2020,平均代价 1483.2020,平均奖励 11.6923,耗时 1.05 秒
[2026-03-20 22:18:55] 第 4/60 轮完成,成功率 1.00,最佳代价 1483.2020,平均代价 1483.2020,平均奖励 11.6923,耗时 1.18 秒
[2026-03-20 22:18:56] 第 5/60 轮完成,成功率 1.00,最佳代价 1483.2020,平均代价 1483.2020,平均奖励 11.6923,耗时 0.98 秒
[2026-03-20 22:18:57] 策略网络训练轮次 1/3 完成,验证损失 1.956160
[2026-03-20 22:18:58] 策略网络训练轮次 2/3 完成,验证损失 1.837199
[2026-03-20 22:18:58] 策略网络训练轮次 3/3 完成,验证损失 1.723893
[2026-03-20 22:18:58] 第 6/60 轮完成,成功率 1.00,最佳代价 1483.2020,平均代价 1483.2020,平均奖励 11.6923,耗时 0.95 秒
[2026-03-20 22:18:59] 第 7/60 轮完成,成功率 1.00,最佳代价 1483.2020,平均代价 1483.2020,平均奖励 11.6923,耗时 0.95 秒
[2026-03-20 22:19:00] 第 8/60 轮完成,成功率 1.00,最佳代价 1483.2020,平均代价 1483.2020,平均奖励 11.6923,耗时 0.89 秒
[2026-03-20 22:19:01] 策略网络训练轮次 1/3 完成,验证损失 1.486671
[2026-03-20 22:19:02] 策略网络训练轮次 2/3 完成,验证损失 1.370790
[2026-03-20 22:19:03] 策略网络训练轮次 3/3 完成,验证损失 1.290557
[2026-03-20 22:19:03] 第 9/60 轮完成,成功率 1.00,最佳代价 1483.2020,平均代价 1483.2020,平均奖励 11.6923,耗时 0.84 秒
[2026-03-20 22:19:04] 第 10/60 轮完成,成功率 1.00,最佳代价 1483.2020,平均代价 1483.2020,平均奖励 11.6923,耗时 1.05 秒
[2026-03-20 22:19:05] 第 11/60 轮完成,成功率 1.00,最佳代价 1483.2020,平均代价 1483.2020,平均奖励 11.6923,耗时 0.89 秒
[2026-03-20 22:19:06] 策略网络训练轮次 1/3 完成,验证损失 1.139731
[2026-03-20 22:19:07] 策略网络训练轮次 2/3 完成,验证损失 1.074959
[2026-03-20 22:19:08] 策略网络训练轮次 3/3 完成,验证损失 1.029366
[2026-03-20 22:19:08] 第 12/60 轮完成,成功率 1.00,最佳代价 1483.2020,平均代价 1483.2020,平均奖励 11.6923,耗时 0.85 秒
[2026-03-20 22:19:09] 第 13/60 轮完成,成功率 1.00,最佳代价 1483.2020,平均代价 1483.2020,平均奖励 11.6923,耗时 1.01 秒
[2026-03-20 22:19:09] 第 14/60 轮完成,成功率 1.00,最佳代价 1483.2020,平均代价 1483.2020,平均奖励 11.6923,耗时 0.89 秒
[2026-03-20 22:19:11] 策略网络训练轮次 1/3 完成,验证损失 0.910160
[2026-03-20 22:19:12] 策略网络训练轮次 2/3 完成,验证损失 0.869024
[2026-03-20 22:19:12] 策略网络训练轮次 3/3 完成,验证损失 0.831498
[2026-03-20 22:19:12] 第 15/60 轮完成,成功率 1.00,最佳代价 1483.2020,平均代价 1483.2020,平均奖励 11.6923,耗时 0.83 秒
[2026-03-20 22:19:13] 第 16/60 轮完成,成功率 1.00,最佳代价 1483.2020,平均代价 1483.2020,平均奖励 11.6923,耗时 0.84 秒
[2026-03-20 22:19:14] 第 17/60 轮完成,成功率 1.00,最佳代价 1483.2020,平均代价 1483.2020,平均奖励 11.6923,耗时 0.82 秒
[2026-03-20 22:19:16] 策略网络训练轮次 1/3 完成,验证损失 0.777425
[2026-03-20 22:19:17] 策略网络训练轮次 2/3 完成,验证损失 0.744737
[2026-03-20 22:19:18] 策略网络训练轮次 3/3 完成,验证损失 0.701545
[2026-03-20 22:19:18] 第 18/60 轮完成,成功率 1.00,最佳代价 1483.2020,平均代价 1483.2020,平均奖励 11.6923,耗时 0.86 秒
[2026-03-20 22:19:19] 第 19/60 轮完成,成功率 1.00,最佳代价 1483.2020,平均代价 1483.2020,平均奖励 11.6923,耗时 1.04 秒
[2026-03-20 22:19:20] 第 20/60 轮完成,成功率 1.00,最佳代价 1483.2020,平均代价 1483.2020,平均奖励 11.6923,耗时 1.06 秒
[2026-03-20 22:19:22] 策略网络训练轮次 1/3 完成,验证损失 0.628643
[2026-03-20 22:19:23] 策略网络训练轮次 2/3 完成,验证损失 0.598774
[2026-03-20 22:19:24] 策略网络训练轮次 3/3 完成,验证损失 0.561684
[2026-03-20 22:19:24] 第 21/60 轮完成,成功率 1.00,最佳代价 1483.2020,平均代价 1483.2020,平均奖励 11.6923,耗时 0.88 秒
[2026-03-20 22:19:25] 第 22/60 轮完成,成功率 1.00,最佳代价 1483.2020,平均代价 1483.2020,平均奖励 11.6923,耗时 0.87 秒
[2026-03-20 22:19:26] 第 23/60 轮完成,成功率 1.00,最佳代价 1483.2020,平均代价 1483.2020,平均奖励 11.6923,耗时 0.86 秒
[2026-03-20 22:19:28] 策略网络训练轮次 1/3 完成,验证损失 0.504448
[2026-03-20 22:19:29] 策略网络训练轮次 2/3 完成,验证损失 0.474524
[2026-03-20 22:19:30] 策略网络训练轮次 3/3 完成,验证损失 0.451190
[2026-03-20 22:19:30] 第 24/60 轮完成,成功率 1.00,最佳代价 1483.2020,平均代价 1483.2020,平均奖励 11.6923,耗时 0.88 秒
[2026-03-20 22:19:31] 第 25/60 轮完成,成功率 1.00,最佳代价 1483.2020,平均代价 1483.2020,平均奖励 11.6923,耗时 0.88 秒
[2026-03-20 22:19:32] 第 26/60 轮完成,成功率 1.00,最佳代价 1483.2020,平均代价 1483.2020,平均奖励 11.6923,耗时 0.86 秒
[2026-03-20 22:19:34] 策略网络训练轮次 1/3 完成,验证损失 0.426870
[2026-03-20 22:19:35] 策略网络训练轮次 2/3 完成,验证损失 0.402816
[2026-03-20 22:19:36] 策略网络训练轮次 3/3 完成,验证损失 0.385846
[2026-03-20 22:19:36] 第 27/60 轮完成,成功率 1.00,最佳代价 1483.2020,平均代价 1483.2020,平均奖励 11.6923,耗时 0.86 秒
[2026-03-20 22:19:37] 第 28/60 轮完成,成功率 1.00,最佳代价 1483.2020,平均代价 1483.2020,平均奖励 11.6923,耗时 0.91 秒
[2026-03-20 22:19:38] 第 29/60 轮完成,成功率 1.00,最佳代价 1483.2020,平均代价 1483.2020,平均奖励 11.6923,耗时 0.96 秒
[2026-03-20 22:19:40] 策略网络训练轮次 1/3 完成,验证损失 0.182466
[2026-03-20 22:19:41] 策略网络训练轮次 2/3 完成,验证损失 0.158805
[2026-03-20 22:19:43] 策略网络训练轮次 3/3 完成,验证损失 0.143712
[2026-03-20 22:19:43] 第 30/60 轮完成,成功率 1.00,最佳代价 1483.2020,平均代价 1483.2020,平均奖励 11.6923,耗时 0.92 秒
[2026-03-20 22:19:44] 第 31/60 轮完成,成功率 1.00,最佳代价 1483.2020,平均代价 1483.2020,平均奖励 11.6923,耗时 1.00 秒
[2026-03-20 22:19:45] 第 32/60 轮完成,成功率 1.00,最佳代价 1483.2020,平均代价 1483.2020,平均奖励 11.6923,耗时 0.88 秒
[2026-03-20 22:19:47] 策略网络训练轮次 1/3 完成,验证损失 0.132502
[2026-03-20 22:19:48] 策略网络训练轮次 2/3 完成,验证损失 0.121612
[2026-03-20 22:19:49] 策略网络训练轮次 3/3 完成,验证损失 0.115841
[2026-03-20 22:19:49] 第 33/60 轮完成,成功率 1.00,最佳代价 1483.2020,平均代价 1483.2020,平均奖励 11.6923,耗时 0.96 秒
[2026-03-20 22:19:50] 第 34/60 轮完成,成功率 1.00,最佳代价 1483.2020,平均代价 1483.2020,平均奖励 11.6923,耗时 0.87 秒
[2026-03-20 22:19:51] 第 35/60 轮完成,成功率 1.00,最佳代价 1483.2020,平均代价 1483.2020,平均奖励 11.6923,耗时 0.85 秒
[2026-03-20 22:19:53] 策略网络训练轮次 1/3 完成,验证损失 0.109354
[2026-03-20 22:19:54] 策略网络训练轮次 2/3 完成,验证损失 0.104257
[2026-03-20 22:19:56] 策略网络训练轮次 3/3 完成,验证损失 0.097281
[2026-03-20 22:19:56] 第 36/60 轮完成,成功率 1.00,最佳代价 1483.2020,平均代价 1483.2020,平均奖励 11.6923,耗时 0.87 秒
[2026-03-20 22:19:57] 第 37/60 轮完成,成功率 1.00,最佳代价 1483.2020,平均代价 1483.2020,平均奖励 11.6923,耗时 0.87 秒
[2026-03-20 22:19:57] 第 38/60 轮完成,成功率 1.00,最佳代价 1483.2020,平均代价 1483.2020,平均奖励 11.6923,耗时 0.91 秒
[2026-03-20 22:20:00] 策略网络训练轮次 1/3 完成,验证损失 0.092842
[2026-03-20 22:20:01] 策略网络训练轮次 2/3 完成,验证损失 0.086109
[2026-03-20 22:20:02] 策略网络训练轮次 3/3 完成,验证损失 0.085719
[2026-03-20 22:20:02] 第 39/60 轮完成,成功率 1.00,最佳代价 1483.2020,平均代价 1483.2020,平均奖励 11.6923,耗时 0.89 秒
[2026-03-20 22:20:03] 第 40/60 轮完成,成功率 1.00,最佳代价 1483.2020,平均代价 1483.2020,平均奖励 11.6923,耗时 0.90 秒
[2026-03-20 22:20:04] 第 41/60 轮完成,成功率 1.00,最佳代价 1483.2020,平均代价 1483.2020,平均奖励 11.6923,耗时 0.87 秒
[2026-03-20 22:20:06] 策略网络训练轮次 1/3 完成,验证损失 0.082687
[2026-03-20 22:20:07] 策略网络训练轮次 2/3 完成,验证损失 0.080101
[2026-03-20 22:20:08] 策略网络训练轮次 3/3 完成,验证损失 0.077669
[2026-03-20 22:20:08] 第 42/60 轮完成,成功率 1.00,最佳代价 1483.2020,平均代价 1483.2020,平均奖励 11.6923,耗时 0.88 秒
[2026-03-20 22:20:09] 第 43/60 轮完成,成功率 1.00,最佳代价 1483.2020,平均代价 1483.2020,平均奖励 11.6923,耗时 0.93 秒
[2026-03-20 22:20:10] 第 44/60 轮完成,成功率 1.00,最佳代价 1483.2020,平均代价 1483.2020,平均奖励 11.6923,耗时 0.88 秒
[2026-03-20 22:20:12] 策略网络训练轮次 1/3 完成,验证损失 0.077204
[2026-03-20 22:20:13] 策略网络训练轮次 2/3 完成,验证损失 0.075566
[2026-03-20 22:20:14] 策略网络训练轮次 3/3 完成,验证损失 0.073931
[2026-03-20 22:20:14] 第 45/60 轮完成,成功率 1.00,最佳代价 1483.2020,平均代价 1483.2020,平均奖励 11.6923,耗时 0.89 秒
[2026-03-20 22:20:15] 第 46/60 轮完成,成功率 1.00,最佳代价 1483.2020,平均代价 1483.2020,平均奖励 11.6923,耗时 0.87 秒
[2026-03-20 22:20:16] 第 47/60 轮完成,成功率 1.00,最佳代价 1483.2020,平均代价 1483.2020,平均奖励 11.6923,耗时 0.87 秒
[2026-03-20 22:20:18] 策略网络训练轮次 1/3 完成,验证损失 0.073574
[2026-03-20 22:20:19] 策略网络训练轮次 2/3 完成,验证损失 0.072477
[2026-03-20 22:20:21] 策略网络训练轮次 3/3 完成,验证损失 0.073351
[2026-03-20 22:20:21] 第 48/60 轮完成,成功率 1.00,最佳代价 1483.2020,平均代价 1483.2020,平均奖励 11.6923,耗时 0.87 秒
[2026-03-20 22:20:22] 第 49/60 轮完成,成功率 1.00,最佳代价 1483.2020,平均代价 1483.2020,平均奖励 11.6923,耗时 0.88 秒
[2026-03-20 22:20:22] 第 50/60 轮完成,成功率 1.00,最佳代价 1483.2020,平均代价 1483.2020,平均奖励 11.6923,耗时 0.87 秒
[2026-03-20 22:20:24] 策略网络训练轮次 1/3 完成,验证损失 0.072544
[2026-03-20 22:20:26] 策略网络训练轮次 2/3 完成,验证损失 0.071234
[2026-03-20 22:20:27] 策略网络训练轮次 3/3 完成,验证损失 0.070466
[2026-03-20 22:20:27] 第 51/60 轮完成,成功率 1.00,最佳代价 1483.2020,平均代价 1483.2020,平均奖励 11.6923,耗时 0.87 秒
[2026-03-20 22:20:28] 第 52/60 轮完成,成功率 1.00,最佳代价 1483.2020,平均代价 1483.2020,平均奖励 11.6923,耗时 0.87 秒
[2026-03-20 22:20:29] 第 53/60 轮完成,成功率 1.00,最佳代价 1483.2020,平均代价 1483.2020,平均奖励 11.6923,耗时 0.86 秒
[2026-03-20 22:20:31] 策略网络训练轮次 1/3 完成,验证损失 0.068708
[2026-03-20 22:20:32] 策略网络训练轮次 2/3 完成,验证损失 0.068802
[2026-03-20 22:20:33] 策略网络训练轮次 3/3 完成,验证损失 0.067710
[2026-03-20 22:20:33] 第 54/60 轮完成,成功率 1.00,最佳代价 1483.2020,平均代价 1483.2020,平均奖励 11.6923,耗时 0.86 秒
[2026-03-20 22:20:34] 第 55/60 轮完成,成功率 1.00,最佳代价 1483.2020,平均代价 1483.2020,平均奖励 11.6923,耗时 0.88 秒
[2026-03-20 22:20:35] 第 56/60 轮完成,成功率 1.00,最佳代价 1483.2020,平均代价 1483.2020,平均奖励 11.6923,耗时 0.86 秒
[2026-03-20 22:20:37] 策略网络训练轮次 1/3 完成,验证损失 0.068073
[2026-03-20 22:20:38] 策略网络训练轮次 2/3 完成,验证损失 0.067461
[2026-03-20 22:20:39] 策略网络训练轮次 3/3 完成,验证损失 0.066123
[2026-03-20 22:20:39] 第 57/60 轮完成,成功率 1.00,最佳代价 1483.2020,平均代价 1483.2020,平均奖励 11.6923,耗时 0.87 秒
[2026-03-20 22:20:40] 第 58/60 轮完成,成功率 1.00,最佳代价 1483.2020,平均代价 1483.2020,平均奖励 11.6923,耗时 0.88 秒
[2026-03-20 22:20:41] 第 59/60 轮完成,成功率 1.00,最佳代价 1483.2020,平均代价 1483.2020,平均奖励 11.6923,耗时 0.93 秒
[2026-03-20 22:20:43] 策略网络训练轮次 1/3 完成,验证损失 0.065940
[2026-03-20 22:20:44] 策略网络训练轮次 2/3 完成,验证损失 0.066901
[2026-03-20 22:20:45] 策略网络训练轮次 3/3 完成,验证损失 0.064972
[2026-03-20 22:20:45] 第 60/60 轮完成,成功率 1.00,最佳代价 1483.2020,平均代价 1483.2020,平均奖励 11.6923,耗时 0.87 秒
[2026-03-20 22:20:46] ACO-DXL规划完成
[2026-03-20 22:20:46] 已有状态样本预测开始
[2026-03-20 22:20:46] 已有状态样本预测完成
[2026-03-20 22:20:46] 最佳模型保存完成
[2026-03-20 22:20:46] 评估图形绘制开始
[2026-03-20 22:20:48] 绘图完成,最佳综合代价 1483.2020,路径长度 336.1124,最小安全距离 7.6658
[2026-03-20 22:20:48] 评估图形绘制完成
[2026-03-20 22:20:48] 程序运行结束
>>