大邻域搜索
回顾邻域
一个在最速下降局部搜索里的关键步骤是:
大邻域
大邻域搜索(LNS)
我们如何指定一个大邻域?通常:
也可以用其他方法:
优势:
考虑:
基本的最小化问题的大邻域搜索算法框架:
large_neighbourhood_search(f, D)
d := initial_validation(D)
while(not stoppingcondition())
N := define_neighbourthood(d, D)
e := explore_neighbourhood(N)
if (f(e) < f(d))
d := e
return d
注:通常限制邻域的搜索
initial_validation(D)
define_neighbourthood(d, D)
explore_neighbourhood(N)
就像其它的局部搜索算法,大邻域搜索不能证明最优。在实践中,我们运行大邻域搜索直到资源耗尽并返回当前答案。
定义邻域
根据具体问题而定:如果我们理解了问题之后我们可能会选择松弛
以车辆寻路问题为例,它有以下要点:
可能的邻域定义:
我们也可以使用自适应选择的邻域:
一般化的随机邻域定义
随机邻域定义
关于 \(k\) :
自适应的随机邻域定义
从 \(k\%\) 的固定率开始,对于任意邻域最多允许搜索 \(S\) 步
重复以下步骤
自适应邻域定义具有鲁棒性,而且很难很难被击败!
大邻域搜索的变种——贪心的大邻域搜索
在大邻域中搜索
第一个得到改善的解,或者
直到资源耗尽
前往第一个解
继续大邻域搜索的循环
小结
灭火问题
灭火问题模型
数据
int: w; % 悟空数量
int: n; % 火点数量
set of int: FIRE = 1..n;
array[FIRE] of int: d; % 持续时间
array[FIRE] of int: reqW; % 需要的悟空数量
array[FIRE] of int: best; % 最好时机
int: m; % 优先次序对的数量
set of int: PREC = 1..m;
array[PREC] of FIRE: pre; % 先扑灭这个
array[PREC] of FIRE: post; % 再扑灭这个
int: maxt = sum(f in FIRE))(d[f]); % 最大时间点
决策变量
array[FIRE] of var 0..maxt: s; % 灭火开始时间
array[FIRE] of var 0..maxt:
e = [s[f] + d[f] | f in FIRE]; % 结束时间
约束
constraint forall(i in PREC)
(e[pre[i]] <= s[post[i]]);
include "cumulative.mzn";
constraint cumulative(s, d, reqW, w);
目标
var int: obj =
sum(f in FIRE)(abs(s[f] - best[f]));
solve minimize obj;
output["Start = \(s)\n" ++
"End = \(e)\n" ++
"Obj = \(obj)\n"];
原文:https://www.cnblogs.com/xxxxxxxxx/p/13139094.html