路径优化建模、优化算法分类及工程化小结

路径优化数学建模

  1. 基本假设:起点固定,不考虑回程,重量时间体积硬约束,经停点停留时间,开放式路径,时效约束,不拆单
  2. min车辆数、min车辆数+里程数、min总成本【用到两阶段:跨区成本最低,放小车辆数-》里程短】
  3. 每个客户点服务一次
  4. 决策变量:xijk yik:客户被车k服务 zk:车k被使用一次 uik:车k访问i时累计重量
  5. 多目标:第一目标车辆数【sum(zk)】最小,第二目标里程最短(sum(dij * xijk))->minF=a * F1+b * F2, a>>b【数学规划里,决策变量可只出现在约束中,不出现在目标函数里】
  6. 约束:
  • 每个客户必须且仅被服务一次:sum(yik)=1;
  • 车辆使用与路径起终点约束:sumx0jk=zk;
  • 车辆容量约束:车辆k服务总重量不超过车辆最大载重 sum(qi * yik)<=Qzk;
  • 车辆运营时间约束:tij* xijk + si* yik<=Tmax;
  • 路径连续性约束(车k服务客户i,则它有一条进入i的路和一条离开i的路):sum(xijk)=yik, sum(xjik)=yik.
  • 子回路消除约束(重要):给每个送货点排个先后顺序,必须一路往前走,不许绕圈圈,不会在半路打转【防止车辆不去别的点,也不回起点】uik-ujk+M* xijk<=M-1 qi<=uik<=Q
    【MTZ和DFJ区别】:MTZ多项式规模但LP松弛弱,DFJ指数规模但LP松弛紧

建模技巧:两个约束"至少满足一个"怎么建模?ML和OR怎么结合?

大M法+二进制变量。如 a* x<=b1+M(1-y);c* x<=b2+M* y;扩展:至少满足k个约束,Ai* x<=bi+M(1-yi), sumyi>=k

ML预测+OR优化:需求预测,库存优化;ML加速OR:ML学习OR启发式,如学习分支策略,学习割平面;OR优化ML:OR调ML超参数,贝叶斯优化调参;端到端学习优化:ML直接输出决策。

路径优化的三类不同解法

  • 精确算法:分支定界、分支割平面、列生成、分支定价、动态规划
  • 启发式算法:节约算法、扫描算法、最近邻算法
  • 元启发式算法:禁忌算法、模拟退火、遗传算法、大邻域搜索、自适应大邻域搜索

启发式算法【具体问题的经验规则】:针对某个问题,用经验规则快速找到一个能用的解,即快速找个解。通常一次构造,不迭代,容易陷入局部最优;典型算法:节约算法,最近邻,扫描,贪心

元启发式算法【通用搜索框架】:用一个通用框架,反复改进解,努力跳出局部最优,找更好的解,即不断折腾,把解越改越好。一定迭代,反复改进,合理时间内找近优解。典型算法:模拟退火,禁忌搜索,遗传算法,ALNS

启发式是元启发式的起点和零件,元启发式是启发式的升级和指挥。启发式是找一个能用的解,元启发式是不断折腾,把解越改越好。

混合策略:先用启发式快速构造初始解,再用gurobi做局部精确优化,大规模用ALNS小规模用gurobi。

精确算法

分支定界【branch and bound】(枚举+剪枝;精确但慢,上界(贪心可行,兜底)+下界(松弛后分支对比上界),松弛、分支、剪枝);

分支割平面【branch and cut】(分支+割平面;先割,割不动再分);

列生成【column generation】(主问题+定价子问题);

Branch and price【分支定价】(列生成+分支定界);

动态规划(状态转移;两个条件:大问题拆成小问题,小问题答案能重复;适合背包问题,最短路径,资源分配)

分支定界:先找兜底定上界,放松规矩定下界,下界若比上界差,这一枝子全砍掉,找到更好压上界,越找越省油

分支定界过程:1)先解松弛,得到下界(理论最乐观);2)分支,找可行解,把上界从正无穷降下来;3)继续分支,把下界提上去;4)上下界越来越近,最后相等或差距够小,问题收敛。总结:分支既可能降低上界,也可能提升下界【找到更好的可行解,降低上界;子问题更松弛,提升下界。找到整数可行解,就用它更新上界;如果解出来还是分数,但目标值比父节点更接近整数最优,则这个子问题下界会提升,带动全局下界提升】。

分支的节点选择:1)深度优先【一条路走到底,适合找可行解】;2)广度优先【一层层看,内存爆炸】;3)最佳优先【看哪个下界最好,最小化问题下界最小,适用于证明最优优先】;4)最优估计【不止看下界,还看最有希望;结合下界和估计,更聪明,缺点是估计函数难设计】;5)混合策略(前期深度,中期最佳优先,后期最优估计)

分支割平面:放松以后出假解,半趟半路都不行,加条规矩切掉它,真方案不能切掉,先割再分更聪明,下界变紧算的快,这个就叫割平面,分支割平面一起来。-》分支定界+割平面,割平面负责切掉假答案,分支定界负责分情况找真答案

列生成:定义主问题,构建对偶问题,定价子问题(min reduced cost),分支【避免枚举所有列】注意,列生成只求解线性松弛,若要求整数解,则需结合分支定界,即branch and price(列生成+分支定界->分支定价)

列生成的循环:初始RMP->解RMP【restricted master problem】->得到赏金(对偶问题)->定价子问题:找新路线(标签算法或启发式定价,搜索新路线,使得"成本-赏金之和"最小)->加列(加进菜单)->重新解RMP->赏金更新->再找新路线(标签算法)【解RMP->定价->加列->再解】

标签算法:看赏金榜->从车场出发->每走一步记一笔->砍掉不划算->保留有希望->回到车场->选最负的【定价子问题从车场出发,按赏金和油钱一步步计算,找到reduced cost最负那条路线】,新生成的路线列叠加到模型约束中(竖的列)

启发式定价(快速找到一条reduced cost<0的路径):贪心算法、插入法、邻域搜索法、限制候选列表、随机扰动

【列生成和分支定界区别】:列生成动态生成变量,分支定界固定变量

列生成与分支定价:变量数目远大于约束条件时用什么方法?主问题和子问题分别是什么?Branch and Price的流程?

ans:

用列生成,即不一次性枚举所有值,只维护部分列,通过定价子问题动态生成新列。当变量数远大于约束数时,用列生成,它不枚举所有列,而是先限制主问题,得到对偶价格,再用定价子问题找负reduced cost列,动态加入,这样避免指数及的列枚举。

主问题:集合覆盖模型,即从所有可行路径中选一组,使总成本最小,覆盖所有客户。子问题是定价问题,找一条路径使得reduced cost最负,即成本减去覆盖客户的对偶价格之和最小。子问题在VRP中是带资源约束的最短路径问题,用标签算法求解。

分支定价问题:列生成只解LP松弛,可能得到分数解,要得到整数解,必须要结合分支定界,组合成分支定价问题。

分支定价流程:1)初始化RMP:用节约算法(启发式)生成少量初始列;2)求解RMP,得到对偶变量pie;3)求解定价问题:找负列,找到就加入RMP重新解,直到无负列;4)检查LP解是否为整数:是整数,更新上界,剪枝;是分数,进如step5;5)分支:选择分支变量,生成两个子节点;6)对每个子节点:继承父节点列池;重新运行列生成;递归分支;7)直到所有节点剪枝,找到整数最优解。

如何判断上界和下界已收敛:6种判断。1)gap小于1%或5% 2)上下界不变:连续多次迭代 3)时间限制 4)节点限制:内存爆炸 5)无改进迭代:连续n次无改进 6)对偶gap:定价子问题无负reduced cost列

启发式算法

构造启发式:【节约算法(从每条客户单独一条线,合并节省最多)】,扫描算法(极角排序),最近邻算法(最临近点)

节约算法:sij = d(0,i)+d(0,j)-d(i,j)_;本质是先让每个客户单独跑,然后算把两个客户串起来省多少,按省的多顺序合并,直到装不下为止。

元启发式算法

禁忌搜索(记录禁忌表,避免循环);模拟退火(以概率接受劣解);遗传算法(适合多目标);大领域搜索(破坏+修复);自适应大领域搜索(多算子自适应选择)

NS(单点搜索,变领域结构,即从当前解出发,探索领域,如2-opt,3-opt,主要是用交换,插入和反转生成新解,但易陷入局部最优)

模拟退火(以一定概率接受差解,概率随问题降低而减小,接受概率=exp(-delta/T),delta=新解-当前解(最小化问题),T=当前温度,初始温度高,逐渐降低。)

遗传算法(模拟生物进化,通过选择,交叉和变异产生下一代;选择:轮盘赌,保留适应度高个体,交叉:两个父代产生子代;变异:随机改变个体基因)

蚁群算法(根据信息素浓度选择路径,信息素随迭代挥发和更新,启发式信息yita,转移概率权重=tau*yita,挥发率和加强【delta加强=信息素总量Q/该只蚂蚁走过的最短路径,每条弧新一轮的信息素=上一轮所有蚂蚁的信息素在该弧留下的delta tau进行加总】)

蚁群算法流程:1)初始化:所有弧(tauij)=1 信息素;2)a。每只蚂蚁构造一条完整路径:从车场出发,按转移概率【通过轮盘赌进行选择】选择下一个客户,直到所有客户被访问,回到车场;b。计算每只蚂蚁路径长度Lk;c。信息素挥发;d。信息素加强:对每只蚂蚁经过的弧,加Q/Lk,或只对最优蚂蚁加;e。记录当前最优路径;f。t=t+1 ;3)输出全局最优路径

ALNS(核心:破坏+修复,多个算子自适应选择;1)初始解 2)选择破坏算子 3)选择修复算子 4)根据算子表现自适应调整权重 5)接受准则【模拟退火,记录最优】6)直到收敛)

ALNS:1)构造初始解(节约算法构造)2)选择破坏算子(删除部分客户) 3)选择修复算子(贪心插入,遗憾插入)4)根据算子表现自适应权重 5)接受准则(模拟退火,记录最优)6)迭代直到收敛

禁忌搜索(允许接收劣解,更新禁忌表,藐视准则,即新解优于全局最优,就破禁)

禁忌搜索算法流程:1)初始解构造;2)初始化禁忌表;3)重复直到终止:a. 生成当前解的领域候选算子;b. 在候选解选一个:不在禁忌表中或满足藐视准则;c. 选择最好的候选解作为新的当前解(即使比当前解差);d. 更新禁忌表:加入刚刚的操作,释放过期的禁忌;e. 如果新解优于历史最优,更新最优解;4)输出历史最优解

禁忌表中邻域算子设计:移动(客户a从路线A挪到路线B);交换(交换路线A和路线B的一个客户);2-opt(交换两条路线尾段);Or-opt(段移动,把一条路线中连续2-3个客户移到另一条路线)

2-opt:一条路线内反转一段,消除交叉

3-opt:一条路线内拆三段重连,更强但更慢

swap:交换两个客户,可跨路线,局部微调。

VRP工程化

大规模VRP工程化:1)问题分解(区域分区,聚类)2)求解加速(并行化,多线程,增量式计算目标函数)3)调优(设置timelimit,设置minGap,添加有效不等式【割平面】)

怎么保证秒级求解:候选列表+增量计算+并行+分区

精确算法何时用:需要最优解,离线规划用

如何处理不可行解:软约束+惩罚项,或修复算子保证可行性

动态VRP如何处理:滚动时域优化,新订单实时插入,已有路线局部调整

Gurobi调优:1)设置mipGap 2)设置timelimit 3)设置mipStart 4)调整mipFocus(1=找可行解,2=证明最优) 5)添加有效不等式(割平面)

热启动:本质是提供一个好的初始上界,让它有上界可以剪枝,加速剪枝【类似先找到一个初始可行解】

两阶段:先聚类后路由;或先路由后聚类

Gurobi求解时间太长怎么优化(收紧可行域、添加割平面、调整参数、热启动)?Gap长时间不收敛怎么办?

gap不收敛,说明下界上不去(LP松弛太弱,需要加割平面或改模型),上界下不来(找不到更好的可行解,需要启发式或热启动)

加割平面:提高下界,砍掉分数值;调mipFocus=1,优先找可行解,压低上界;调参数:增强启发式,找更好的可行解;热启动:给更好的初始解;分解问题:按区域/时间分批求解;放宽gap:接受2%-5%gap;设timelimit:时间到就返回当前最优;数值调优。

遇到gurobi慢,4步走:1)诊断:看日志,根节点gap,LP松弛强度(LP松弛强度=LP下界离真实最优解有多近,LP松弛紧,说明LP解已接近整数最优解.);2)收紧可行域:筛选变量,加业务约束,设变量上下界;3)加割平面:容量割,时间割;子回路割,调cuts参数;4)调参数+热启动:timelimit,启发式,mipGap,MIPStart。

判断是上界还是下界,主要根据gurobi日志里的incumbent和bestBd两列,看哪个停留久,如果incumbent停留久,说明上界下不去,此时要用增强启发式,或给mipStart热启动;若bestBd停留久,说明下界上不来,LP松弛弱,此时要增强割平面。

线性规划基础

单纯形法步骤、检验数和影子价格含义、强对偶弱对偶、拉格朗日松弛系数怎么求

单纯形法步骤:1)化为标准型:引入松弛变量,将不等式变为等式;2)找初始可行解:令非基变量为0,解出基变量;3)计算检验数;4)判断最优;5)选择入基变量;6)选择出基变量;7)枢轴运算:高斯消元,更新基;8)重复步骤,直到最优或无界。

检验数:表示非基变量xj每增加一个单位,目标函数的变化量;对于最小化问题,检验数小于0,说明增加xj能降低目标,应入基;所有检验数大于等于0时最优。

影子价格(对偶价格):对应对偶变量pie;表示约束右端bi增加1单位,目标函数的变化量,也叫对偶价格,是约束的边际价值,它衡量的是这个约束有多紧,多值钱;影子价格>0:该资源稀缺,增加资源能改善目标;影子价格=0,:该资源有剩余,增加无益。

弱对偶:对任意可行解x和y(对偶问题),c* x>=b* y,对偶目标值总是原问题目标值的下界。强对偶:如果原问题有最优解,则对偶问题也有最优解,即c* x=b* y,即原问题和对偶问题最优目标值相等。【意义:强对偶是列生成,对偶单纯形法的理论基础】

拉格朗日松弛系数怎么求:原问题:min c* x st. Ax<=b -》转换为:L(x,lamda)=c* x + lambda* (Ax-b),lambda>=0;拉格朗日对偶函数:g(lambda)=min(x)L(x,lambda),对偶问题:max(lambda>=0)g(lambda)

影子价格vs检验数:检验数 对应 变量,即非基变量增加1单位,目标函数变化多少;影子价格 对应 约束,约束右端增加1单位,目标函数变化多少

相关推荐
小羊没烦恼!1 小时前
Ajax与JSON的一些总结
android·java·前端·数据库·mysql·算法·okhttp
2501_926978331 小时前
人机通信协议--人和机器之间的交互想象
人工智能·经验分享·算法·ai写作
行者全栈架构师1 小时前
【鸿蒙心迹】互动卡片全链路——把核心功能放到桌面(FormKit 实战)(HarmonyOS 7.x)
前端·算法·架构
无定义_1 小时前
10.11日常训练
算法
Code_Solitude1 小时前
c语言:关于qsoet函数知识点
c语言·数据结构·算法
Nil2082 小时前
leetcode 49字母异位分组
算法·leetcode·哈希算法
weixin_307779132 小时前
C++代码实现MATLAB中的spectralcluster函数功能
开发语言·c++·算法·matlab
行者全栈架构师2 小时前
【鸿蒙心迹】让应用“悬浮“起来——闪控球(floatingBall)从接入到实战全链路(HarmonyOS 7.x)
前端·算法·架构
云的雨 雨的云2 小时前
手写算法动画上位机:从排序到线性代数可视化
线性代数·算法