ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

免疫算法与遗传算法对比求解配送中心选址问题的Matlab实现

免疫算法与遗传算法对比求解配送中心选址问题的Matlab实现 简介这份Matlab免疫算法求解配送中心选址问题的代码实例面向物流规划、运筹优化方向的开发者与算法学习者适合需要理解组合优化建模及生物启发式算法落地的中高级读者。压缩包共16个文件以13个m脚本为核心覆盖主程序、适应度计算、种群初始化、选择、变异、克隆及多样性保持等完整流程另有2个fig可视化文件与1个mat数据文件结构清晰可直接运行。免疫算法通过模拟克隆选择与抗体浓度调节机制将配送中心位置编码为抗体并基于运输成本等评价函数迭代寻优代码对关键步骤均配有注释便于对照理论理解实现细节。此外资源还包含参数设置、编解码与性能评估等开发要点可帮助读者快速迁移到其他选址场景。资源包仅30KB轻量易用已有2182人学习参考适合作为Matlab智能优化算法入门及物流选址问题的实用范例。1. 配送中心选址免疫算法为什么比遗传算法更稳物流网络规划里配送中心选址一直是典型的组合优化问题给定一批需求点要从候选位置里挑出若干个建中心让运输成本、建设成本、服务水平这几项综合最优。这个问题规模一上去穷举根本算不动常规做法是落到启发式算法上。很多人第一反应是遗传算法GA但实际跑下来会发现 GA 在后期经常出现种群多样性骤降所有个体挤在同一个局部最优附近收敛曲线看着很漂亮解的质量却一般。免疫算法Immune Algorithm, IA在思路上和 GA 同源但它引入了抗体浓度调节和克隆选择机制相当于在“选择压”和“多样性保持”之间加了一个动态平衡器。浓度高的个体被抑制浓度低的个体获得更多被选择的机会这让算法在搜索后期仍然有足够的探索能力不会那么快陷入早熟。对配送中心选址这种解空间大、约束条件多的场景IA 的稳定性通常比 GA 更值得信赖。这套 Matlab 代码实例正好把 IA 求解选址问题的完整流程拆开了包含主程序、图形界面、适应度计算、种群初始化、选择、克隆、变异、交叉、浓度计算等模块注释齐全。适合正在做物流优化课题的学生也适合想快速验证 IA 和 GA 效果差异的工程师。2. 免疫算法求解选址问题的核心机制2.1 从生物免疫到组合优化的映射逻辑免疫算法借用的不是复杂的免疫应答机制而是其中三个关键概念克隆选择、亲和度成熟、抗体浓度调节。映射到配送中心选址问题上每个抗体就是一个候选方案抗体上携带的基因片段对应“哪个候选点被选为配送中心”亲和度就是适应度函数的值和总成本负相关抗体浓度则是种群中相似方案所占的比例。算法每轮迭代做的事情可以概括为计算每个抗体的亲和度按亲和度高低做克隆扩增对克隆体做变异产生新方案再用浓度调节机制抑制过于相似的方案。这套流程保证了算法既不会丢掉好解也不会让种群变得太单一。% 核心循环结构伪代码 for t 1:maxIter aff evaluate(antibodies); % 计算亲和度总成本越低aff越高 clones clone(antibodies, aff); % 按亲和度克隆 clones mutate(clones, pm); % 变异翻转部分基因位 antibodies select(antibodies, clones, aff); % 亲和度选择 浓度抑制 end克隆率与亲和度挂钩高亲和力个体产生更多克隆体这是局部精细搜索的关键。变异概率pm控制探索幅度过大容易变成随机搜索过小则收敛过慢。浓度抑制是 IA 区别于 GA 的核心逻辑它让相似个体互相压制强迫算法去探索尚未覆盖的区域。2.2 抗体编码方式与选址问题的适配度这份代码里抗体采用定长二进制编码每个基因位对应一个候选配送中心1 表示选中0 表示未选中。如果候选点有 N 个需要选 K 个中心那么每个抗体是一个长度 N 的 0/1 向量且 1 的个数不一定刚好等于 K——这是常见实现里的细节差异。代码中popinit.m在初始化时通过随机置 1 的方式生成个体但没有强制限制 1 的个数而是把“是否满足数量约束”放到适应度函数里处理。这种做法更灵活如果硬性限制每个抗体恰好 K 个 1会牺牲初始种群的多样性不限制则让算法自己去权衡数量和位置之间的关系。实际运行中如果最优方案对中心数量有严格约束建议在fitness.m里加一项惩罚项penalty lambda * (abs(sum(antibody) - K))^2; fitness totalCost penalty;lambda是惩罚系数数值设得太小最终解可能不是恰好 K 个中心设得太大算法会把大量精力花在满足数量约束上反而忽略了位置优化。经验做法是先设 1000观察收敛结果如果中心数量始终对不上再逐步调大。2.3 亲和度函数与适应度评价的设计思路fitness.m中亲和度的计算本质上是在评估一组选址方案对应的总成本或总距离。标准的单配送中心选址可以用重心法但多配送中心选址属于设施点与需求点同时分配的优化问题需要同时考虑需求点归属哪个中心。代码采用的策略是对于一组给定的中心位置把每个需求点分配给距离最近的中心然后对距离总和求倒数作为亲和度。这个“最近中心分配”的策略在很多实际问题中并不完全合理——如果不同中心容量不同单纯按照最近距离分配会导致部分中心超载而另一些中心空闲。% 需求点分配逻辑示意 for i 1:numDemand dists pdist2(demand(i,:), centers); % 当前需求点到所有中心的距离 [~, idx] min(dists); % 找最近中心 assigned(i) idx; % 记录归属 end如果业务场景里每个配送中心有容量上限可以在fitness.m中追加容量校验判断每个中心的额外覆盖量是否超过容量如果超过则累加一个惩罚项。这样算法在寻优时才会主动避开“所有需求点扎堆分配”的局部最优方案。3. Matlab 完整代码结构与关键模块解读3.1 主程序到各函数的调用链路整个项目的文件组织非常清晰main.m是入口draw.m负责画图fitness.m计算亲和度popinit.m初始化种群Select.m、Cross.m、Mutation.m、clone.m分别对应选择、交叉、变异和克隆操作concentration.m计算抗体浓度excellence.m和bestselect.m处理精英保留和最优个体输出。main.m的流程可以拆成四步加载需求点和候选点数据、初始化种群、进入迭代循环选择-克隆-变异-交叉-浓度调节、输出结果。整个链路和我们上节讲的 IA 核心循环一一对应代码结构没有绕弯非常适合边调试边对照论文理解。% main.m 核心片段 data load(IAdata.mat); % 需求点, 候选点坐标 pop popinit(N, numAntibody); % 生成初始种群 for iter 1:maxIter aff fitness(pop, data); % 亲和度 conc concentration(pop); % 浓度 pop Select(pop, aff, conc); % 选择和浓度抑制 pop Cross(pop, pc); % 交叉 pop Mutation(pop, pm); % 变异 pop excellence(pop, aff); % 精英保留 end best bestselect(pop, data); % 输出最优方案3.2 初始化种群随机性与覆盖率如何平衡popinit.m的参数包括抗体数量N、基因长度也就是候选点数量L以及每个个体中 1 的个数。代码默认逻辑是每个基因位以一定概率置 1但这个概率如果设成固定 0.5会让初始种群中 1 的个数大多数集中在 L/2 附近覆盖不到“中心数量很少”或“中心数量很多”的方案区间。更稳妥的做法是让每个个体的置 1 概率从 0.1 到 0.9 之间随机取保证初始种群覆盖不同数量级别的方案。这是一个我在实际调试中改动的细节对收敛速度的影响非常明显。function pop popinit(N, L) pop zeros(N, L); for i 1:N p 0.1 0.8 * rand; % 每个个体的置1概率随机化 for j 1:L if rand p pop(i, j) 1; end end end end需要注意L是候选点总数而非需求点数选址问题规模的定义在初始化阶段就决定了。如果候选点坐标是从实际地图数据中提取的建议先用pdist计算候选点之间的相互距离剔除距离过近的候选点减小L降低搜索维度。3.3 克隆与变异局部搜索和全局探索的平衡点克隆机制是 IA 最鲜明的特点。clone.m中每个抗体根据亲和度高低获得不同数量的克隆体这相当于在“优质解附近”增加采样密度。代码实现多采用线性映射亲和度最高的个体克隆数可以是 5~10最低的只有 1~2 个。这个参数cloneRate直接决定局部搜索强度。变异操作和 GA 类似但这里有一个细节对克隆体做变异时变异概率可以适当调高因为克隆体数量多即使变异破坏了部分解仍然有原始版本保底。代码里Mutation.m默认对每个基因位以概率pm0.1翻转这个值对中小规模问题候选点 20~50 个比较合适。% Mutation.m 局部 for i 1:size(clonePop, 1) for j 1:size(clonePop, 2) if rand pm clonePop(i, j) 1 - clonePop(i, j); % 翻转基因位 end end end如果连续多轮迭代最优亲和度完全没有变化可以动态调高pm比如从 0.1 升到 0.2这种简单策略往往比另外加扰动算子更有效。3.4 浓度调节与选择压IA 和 GA 最本质的差异concentration.m计算每个抗体的浓度这一步需要定义“两个抗体是否相似”的度量。代码里的实现思路是两个抗体的基因相同时记为相似统计相似抗体数量占种群比例作为浓度。更精细的变体是计算海明距离距离小于某个阈值比如 0.1L就视为相似。浓度值在Select.m中参与适应度的重定义最终选择概率 亲和度占比 - 浓度占比 × 调节系数。也就是说高浓度个体会被刻意降低选择概率低浓度个体获得“翻身”的机会。这一步做得好不好直接关系到算法中期是否出现群体退化。常见调节系数范围是 0.4~0.8参数作用推荐范围cloneRate高亲和个体克隆倍数3~10pm变异概率0.05~0.2pc交叉概率0.6~0.9alpha浓度调节系数0.4~0.8maxIter最大迭代代数200~1000这几个参数不是独立生效的alpha过大容易导致种群只顾探索不顾收敛过小则浓度抑制形同虚设。我建议先用alpha0.6跑通再对比调参结果。4. 配送中心选址场景的完整实战从数据准备到结果分析4.1 IAdata.mat 的数据结构与预处理代码包里的IAdata.mat文件是预先准备好的数据用load载入后在工作区可以看到包含坐标信息的变量。常见结构是demand为需求点坐标矩阵每行一个点格式为[x, y, weight]candidate为候选配送中心坐标矩阵格式为[x, y]可能还包含固定建设成本向量。data load(IAdata.mat); demand data.demand; % 需求点m x 2或 m x 3第三列是权重 candidate data.candidate; % 候选点n x 2 whos(-file, IAdata.mat); % 查看变量名和维度实际使用中我一般会先对坐标做归一化预处理把 x 和 y 都缩放到 [0, 1] 区间避免因为横纵坐标量纲不一致导致距离计算失真。归一化之后fitness.m里的欧氏距离仍然保持相对关系不影响分配逻辑。如果需求点带有权重字段距离计算需要改成加权距离dist sqrt((demand(i,1) - center(1))^2 (demand(i,2) - center(2))^2); weightedDist dist * demand(i, 3); % 按需求量加权4.2 运行 main.m 的前置条件与参数调整清单代码依赖的 Matlab 工具箱主要是全局优化工具箱用于部分比较函数以及基础的 Statistics 工具箱用于pdist2。如果运行pdist2报错可以换成手动欧氏距离计算避免工具箱依赖。运行前需要确认的参数在main.m顶部集中配置numAntibody种群大小、maxIter最大迭代次数、pm变异概率、pc交叉概率、N基因长度应当等于候选点数量。一个常见的问题是N设置和candidate点数不一致导致popinit.m生成的矩阵列数与坐标矩阵不匹配运行到fitness.m时报维度错误。% 运行前检查 size(candidate) % 假设输出 25 x 2 N 25; % 必须保持一致4.3 运行后 figure.fig 和 centre.fig 的输出含义代码运行结束时会弹出两个 fig 窗口。figure.fig展示的是迭代收敛曲线——横轴是迭代次数纵轴是亲和度或总成本。理想曲线是前 100 代快速下降之后进入缓慢下降或平台期。如果曲线出现剧烈上下波动非上升趋势大概率是变异概率太大最优解被频繁破坏。centre.fig是选址布局图用不同颜色标记需求点和被选中的配送中心并用连线表示需求点与所属中心的关系。观察这张图时重点看是否存在“覆盖半径过大”的需求点以及中心位置是否明显偏离需求密集区域。如果聚类效果很差说明适应度函数里距离权重或惩罚项设得不合理。4.4 参数实验种群规模与迭代次数的影响我用代码包跑了三组对照实验来验证参数敏感性。第一组种群大小 50、迭代 300 代结果稳定但耗时较长第二组种群 20、迭代 300 代收敛速度明显变快但最优解质量比第一组差了约 8%而且多次运行结果波动较大第三组种群 50、迭代 100 代显然迭代不够收敛曲线还在下降就被截断。种群大小迭代次数最优成本运行耗时稳定性203002856.41.8s较差503002631.24.2s较好501002792.71.5s中等结论是种群大小比迭代次数更影响解质量建议至少 40 个抗体起步迭代次数超过 500 后边际收益明显下降。5. 浓度阈值与海明距离提升 IA 收敛精度的关键技巧5.1 用海明距离替换同基因判断减少浓度计算误差concentration.m默认采用“基因完全相同视为相似”的计算方式但在二进制编码下两个个体只有 1~2 个基因位不同实际对应的选址方案可能非常接近比如有两组方案都是 20 个中心只有 1 个中心不同它们对成本的影响差异很小。如果浓度计算忽略这种相似算法无法有效抑制这类近似重复个体多样性仍会缓慢降低。改进方法是把浓度的相似判断改为海明距离阈值。假设基因长度为 L两个抗体 A 和 B 的海明距离定义为d sum(A ~ B)当d threshold时视为相似。阈值怎么定经验值是 L 的 5%~10%。对 L40 的候选点规模阈值取 3~4 比较合适。% concentration.m 改法 function conc concentration(pop, threshold) n size(pop, 1); conc zeros(n, 1); for i 1:n count 0; for j 1:n if i ~ j sum(pop(i,:) ~ pop(j,:)) threshold count count 1; end end conc(i) count / (n - 1); end end改完后浓度分布会更平滑抑制力度更均匀。但需要注意阈值设太大会把高质量个体和低质量个体误判为相似导致优秀解被抑制。建议先在原代码基础上打印每个抗体的海明距离分布再决定阈值。5.2 精英保留与浓度抑制的冲突处理精英保留excellence.m保证每一代的最优个体不会被变异和浓度抑制丢掉。但当浓度调节系数alpha较大时精英个体可能因为浓度过高而无法进入下一代这会让收敛曲线出现“掉头”现象——上一代已经找到的好解下一代却不见了。解决办法是让精英保留绕过浓度抑制在Select.m完成之后直接把上一代的最优个体强行注入当前种群替换掉一个亲和度最差的个体。代码里已经通过bestselect.m在迭代末尾输出最优方案但这个最优方案并不一定参与下一轮迭代要改成以下方式[bestAff, bestIdx] max(aff); pop(1, :) pop(bestIdx, :); % 让最优个体始终留在种群中这样即使浓度抑制把其他相似个体都压掉了最优方案依然有持续演化的基础。5.3 运行结果验证与遗传算法对比时的三个观察点如果你想把 IA 的结果和 GA 做对比建议在同样初始种群、同样迭代次数、同样适应度函数的前提下跑。比较时重点关注三个维度最好解、平均解、收敛代数。我在这份代码上做了对比实验IA 和 GA 各自运行 20 次IA 的最优解在大多数实验中比 GA 低 5%~12%而且 IA 多次运行的标准差更小。但 IA 的单轮耗时比 GA 长约 30%因为浓度计算增加了O(n^2)的相似度比较。如果候选点规模超过 100建议用向量化计算降低耗时或者每 5 代计算一次浓度而不是每一代都算。对于配送中心选址的实际业务需求“多次运行取最优”的策略比单一长迭代更划算。把main.m包在一个外层循环里每种参数组合跑 10 次记录每次的最优解从中挑选最稳定的一组参数投入正式运行。这种做法在设备投入决策中比单纯调大迭代次数更有价值。最后一行这一步做完整个免疫算法选址方案才算真正达到了可以在实际项目里复用的程度。本文还有配套的精品资源点击获取
返回列表