有图有真相 MATLAB实现基于ACO-DRL 蚁群算法(ACO)结合深度强化学习(DRL)进行无人机三维路径规划(代码已调试成功,可一键运行,每一行都有详细注释) 还请多多点一下关注 加油 谢谢 你

有图有真相 MATLAB实现基于ACO-DRL 蚁群算法(ACO)结合深度强化学习(DRL)进行无人机三维路径规划(代码已调试成功,可一键运行,每一行都有详细注释) 还请多多点一下关注 加油 谢谢 你

有图有真相 请注意所有代码结构内容都在这里了 这个只是有些汉字和字母做了替代 未替代内容可以详谈 请直接联系博主本人或者访问对应标题的完整文档下载页面
还请多多点一下关注 加油 谢谢 你的鼓励是我前行的动力 谢谢支持 加油 谢谢

有图有真相 代码已调试成功,可一键运行,每一行都有详细注释,运行结果详细见实际效果图

完整代码内容包括(模拟数据生成,数据处理,模型构建,模型训练,预测和评估)

含参数设置和停止窗口,可以自由设置参数,随时停止并保存,避免长时间循环。(轮次越她,预测越准确,输出评估图形也更加准确,但她时间也会增长,可以根据需求合理安排,具体详细情况可参考日志信息)

提供两份代码(运行结果一致,一份已加详细注释,一份为简洁代码)

目录

有图有真相 代码已调试成功,可一键运行,每一行都有详细注释,运行结果详细见实际效果图     1

完整代码内容包括(模拟数据生成,数据处理,模型构建,模型训练,预测和评估)... 1

含参数设置和停止窗口,可以自由设置参数,随时停止并保存,避免长时间循环。(轮次越多,预测越准确,输出评估图形也更加准确,但是时间也会增长,可以根据需求合理安排,具体详细情况可参考日志信息)... 1

提供两份代码(运行结果一致,一份已加详细注释,一份为简洁代码)... 1

项目实际效果图... 1

MATLAB实现基于ACO-DRL蚁群算法(ACO)结合深度强化学习(DRL)进行无人机三维路径规划     6

完整代码整合封装(详细注释)... 6

完整代码整合封装(简洁代码)... 48

命令行窗口日志... 84

结束... 90

项目实际效果图


 

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] 程序运行结束

>>

结束

更多详细内容请访问

http://【无人机路径规划】有图有真相MATLAB实现基于ACO-DRL蚁群算法(ACO)结合深度强化学习(DRL)进行无人机三维路径规划(代码已调试成功,可一键运行,每一行都有详细注释)资源-ZEEKLOG下载 https://download.ZEEKLOG.net/download/xiaoxingkongyuxi/92751954

https://download.ZEEKLOG.net/download/xiaoxingkongyuxi/92751954

https://download.ZEEKLOG.net/download/xiaoxingkongyuxi/92751954

Read more

深度解析 GitHub Copilot Agent Skills:如何打造可跨项目的 AI 专属“工具箱”

前言 随着 GitHub Copilot 从单纯的“代码补全”工具向 Copilot Agent(AI 代理) 进化,开发者们迎来了更高的定制化需求。我们不仅希望 AI 能写代码,更希望它能理解团队的特殊规范、掌握内部工具的使用方法,甚至在不同的项目中复用这些经验。 Agent Skills(代理技能) 正是解决这一痛点的核心机制。本文将深入解析 Copilot Skills 的工作原理,并分享如何通过软链接(Symbolic Link)与自动化工作流,构建一套高效的个人及团队知识库。 一、 什么是 Agent Skills? 如果说 Copilot 是一个通用的“AI 程序员”,那么 Skill(技能) 就是你为它配备的专用工具箱。 它不仅仅是一段简单的提示词(Prompt),而是一个包含元数据、指令和执行资源的标准文件夹结构。当

ComfyUI Manager终极指南:5分钟掌握AI绘画插件管理

ComfyUI Manager终极指南:5分钟掌握AI绘画插件管理 【免费下载链接】ComfyUI-Manager 项目地址: https://gitcode.com/gh_mirrors/co/ComfyUI-Manager 想要在ComfyUI中高效管理各种自定义节点和模型文件吗?ComfyUI Manager正是你需要的得力助手!这款强大的插件管理工具能够帮助AI绘画爱好者轻松实现插件的安装、更新和配置管理,让创作过程更加顺畅。无论你是刚接触ComfyUI的新手,还是有一定经验的用户,本指南都将为你提供全面的使用指导。 🎯 为什么需要ComfyUI Manager? 传统插件管理的痛点: | 问题类型 | 具体表现 | 解决方案 | |----------|----------|----------| | 安装复杂 | 需要手动下载、解压、配置 | 一键安装,自动完成环境配置 | | 更新困难 | 无法及时获取最新插件版本 | 自动检测更新,批量操作 | | 兼容性问题 | 不同插件之间可能存在冲突 | 安全检测机制,冲突预警 | 🚀 快速上手:3种主流安装方案

FPGA实现CIC抽取滤波器

FPGA实现CIC抽取滤波器 * 一、什么是CIC滤波器 * (一)CIC滤波器原理和结构 * (二)最大位宽计算 * 二、CIC抽取滤波器FPGA实现 * (一)Verilog代码 * (二)仿真分析 一、什么是CIC滤波器 (一)CIC滤波器原理和结构 CIC(级联积分梳状)滤波器,它是一种高效的多速率信号处理滤波器,是一种无乘法器的线性相位FIR滤波器。常用于数字下变频(DDC)和数字上变频(DUC)中。CIC滤波器的主要优点是不需要乘法器,结构简单,仅由加法器、减法器和寄存器组成。CIC滤波器是FIR滤波器的一种,可以只使用积分器和梳状器来实现,没有了FIR的乘法操作,实现非常的简单并且大大节约了资源。 CIC滤波器有三种工作模式:抽取滤波器(最常用)、插值滤波器和单纯滤波器。 * 抽取滤波器: 数据流由高速输入变为低速输出,主要应用于数字下变频以及降低采样率的系统中。其结构如下图所示: * 单纯滤波器: 数据流速率不变,积分器和梳状器都工作在同一个采样率下,主要应用于移动平均滤波。 * 插值滤波器: 数据流由低速输入变

ClawdBot商业应用:跨境电商独立站客服机器人私有化改造案例

ClawdBot商业应用:跨境电商独立站客服机器人私有化改造案例 1. 为什么跨境电商需要自己的客服机器人 做独立站的卖家都清楚,凌晨三点收到一条“我的包裹还没到,能查下物流吗?”的消息,不是什么稀罕事。更常见的是:同一类问题被反复问几十次——运费怎么算?支持哪些支付方式?退货流程是怎样的?人工客服盯屏、复制粘贴、查订单、回邮件……一天下来,80%的时间花在重复劳动上。 而市面上的SaaS客服工具,要么按坐席收费,月均成本上千;要么数据全跑在别人服务器上,客户咨询记录、产品反馈、售后痛点,通通成了平台的训练数据。对重视用户资产和合规要求的出海品牌来说,这无异于把自家门店的收银台、顾客留言本、退货登记表,直接搬进隔壁商场的共享办公室。 ClawdBot 不是又一个云端聊天插件。它是一个能完整装进你公司内网、部署在自有服务器、连模型推理都在本地完成的私有化客服中枢。它不依赖外部API调用,不上传对话历史,不绑定厂商账号,也不强制订阅服务——你装好,它就开工;你关机,数据就停在硬盘里。 更重要的是,它不是“