有图有真相 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

AIGC(生成式AI)试用 46 -- AI与软件开发过程1

一切从如何验证AI开发提交的结果开始。 什么能保证软件质量? 是人?是软件的创造者(们)?是质量保障人员?是软件项目经理?。。。。。。 是过程?用制度、过程最佳实践约束行为?软件工程? 靠人还是靠过程? AI的出现会彻底推翻 或 舍弃原有的软件开发过程?会重构软件工程? 不妨实际应用,验证之。。。。。。 有哪些问题? - 软件工程标准过程? - AI如何融入软件生命周期? - 实际需求? - 在提问到 问题 5 时,AI的回复出现 “modules = ['用户管理', '订单系统', '支付模块', '商品管理', '促销活动']”,严重偏离了问题的核心内容。 - 参考回复提示:

2026年AI编程工具推荐:从Copilot到Trae,开发者该如何选型?

2026年AI编程工具推荐:从Copilot到Trae,开发者该如何选型?

面对琳琅满目的AI编程工具,字节跳动的Trae正以其本土化优势和工程级代码生成能力,悄然改变着中国开发者的工作流。 “有没有一个能完美适应国内网络环境,理解中文开发需求的AI编程工具?” 当字节跳动推出Trae时,这个问题开始有了清晰答案。与需要科学上网的Cursor、订阅费用昂贵的GitHub Copilot不同,Trae作为原生AI IDE,深度结合了中国开发者的实际工作环境。 一个有趣的现象是,越来越多的中国开发者开始将Trae与VS Code的无缝迁移体验作为选择标准之一。这种“无感切换”正成为本土AI编程工具获取用户的关键策略。 01 核心选型维度 开发者选择AI编程工具时往往陷入功能对比的细节中,而忽略了更本质的匹配度问题。真正影响工作效率的,不是工具宣传的“强大功能”,而是工具与开发者身份、工作场景的契合程度。 对于中国开发者而言,选型维度需要特别增加本土化适配这一项。网络稳定性、中文语境理解、本地支付便利性以及是否符合国内数据安全法规,这些在评估海外工具时常被忽略的因素,实际上决定了工具能否真正融入日常工作流。 不同规模的团队对AI编程工具的需求差异显著

【大模型科普】AIGC技术发展与应用实践(一文读懂AIGC)

【大模型科普】AIGC技术发展与应用实践(一文读懂AIGC)

【作者主页】Francek Chen 【专栏介绍】 ⌈ ⌈ ⌈人工智能与大模型应用 ⌋ ⌋ ⌋ 人工智能(AI)通过算法模拟人类智能,利用机器学习、深度学习等技术驱动医疗、金融等领域的智能化。大模型是千亿参数的深度神经网络(如ChatGPT),经海量数据训练后能完成文本生成、图像创作等复杂任务,显著提升效率,但面临算力消耗、数据偏见等挑战。当前正加速与教育、科研融合,未来需平衡技术创新与伦理风险,推动可持续发展。 文章目录 * 一、AIGC概述 * (一)什么是AIGC * (二)AIGC与大模型的关系 * (三)常见的AIGC应用场景 * (四)AIGC技术对行业发展的影响 * (五)AIGC技术对职业发展的影响 * (六)常见的AIGC大模型工具 * (七)AIGC大模型的提示词 * 二、文本类AIGC应用实践 * (一)案例1:与DeepSeek进行对话 * (二)案例2:与百度文心一言进行对话 * (三)案例3:使用讯飞智文生成PPT

Whisper-large-v3语音识别效果展示:中英日法西等99语种高精度转录案例

Whisper-large-v3语音识别效果展示:中英日法西等99语种高精度转录案例 1. 引言:当AI能听懂全世界 想象一下,你有一段包含中文、英文、日语的会议录音,或者一段法语播客、西班牙语访谈,甚至是你完全听不懂的某种小众语言音频。传统上,你需要分别找懂这些语言的人来听写,费时费力还容易出错。 现在,情况完全不同了。基于OpenAI Whisper Large v3模型构建的语音识别服务,就像一个精通99种语言的“超级翻译官”,能够自动识别音频中的语言,并高精度地将其转换为文字。无论是清晰的演讲、嘈杂的访谈,还是带口音的对话,它都能从容应对。 本文将带你直观感受Whisper-large-v3的实际识别效果。我们将通过多个真实音频案例,展示它在不同语言、不同场景下的转录能力,看看这个“多语言耳朵”究竟有多厉害。 2. 核心能力概览:99种语言的“超级耳朵” 在深入案例之前,我们先快速了解一下Whisper-large-v3的核心能力。这有助于我们理解后续展示的效果是如何实现的。 2.1 技术基石:OpenAI Whisper Large v3