PSO (Particle Swarm Optimization) 算法即粒子群优化算法,源于对鸟群捕食行为的学习。基本思想是:个体获取的局部信息提供给群体,群体根据所有局部信息获得一个动态的全局最优解,每个个体再根据这个全局最优解调整自身的局部最优解,这个过程进行迭代,直到达到终止条件。
TSP (Traveling Salesman Problem) 即旅行商问题,简单来说就是:给定 n 个城市的位置,求一条访问各个城市一次的最短路径,TSP 也是一个组合优化问题。
- PSO 算法基础公式
这里,Vj 代表每个粒子的速度;w 是惯性权重系数,有利于算法的收敛;c1 和 c2 分别为局部加速权重系数和全局加速权重系数,决定了下一代的局部速度取决于局部最优解多一些,还是全局最优解多一些;r1 和 r2 是两个 0~1 中间的随机数,也是为了算法收敛。
下面是我在 report 里做的 PSO 算法运行流程图:
PSO 算法流程图
但很明显,PSO 算法更适合用来解决连续优化问题,而旅行商问题是一个组合优化问题。经过大量的论文学习和讨论后,使用了一种改进的 PSO 算法,引入了交换子和交换序的概念。
假设在一个旅行商问题中,有 n 个城市节点,那么这个问题的解序列可记为 S = (ai), i = 1, 2, …, n. 那么 SO(i1, i2) 就是一个交换子,i1 和 i2 表示城市节点 a1 和 a2. 若对解序列进行 S’ = S + SO(i1, i2) 的运算,就是将解序列 S 中 a1 和 a2 的位置进行调换。多个交换子的序列 SS = (SO1, SO2, …, SOn) 就是一个交换序,其中交换子的顺序是有意义的,不同的顺序可能产生不同的解序列。
放在这个具体路线规划问题中,就是先将所有城市节点随机排列,得到一个解序列,然后对城市节点进行逐个调换,将调换前后的路径长度进行对比,如果变好则更新全局最优解,否则继续寻找更佳的交换子和交换序,在这一过程中,w 系数就起到了收敛的作用,它会使我们进行调换的局部解序列越来越短。
- 核心程序
private void particle(int i) {
ArrayList<SO> Vi;
int len;
int j;
float ra;
float rb;
ArrayList<SO> Vii = new ArrayList<SO>();
// refresh velocity
// Vii=wVi+ra(Pid-Xid)+rb(Pgd-Xid)
Vi = listV.get(i);
// wVi+表示获取Vi中size*w取整个交换序列
len = (int) (Vi.size() * w);
for (j = 0; j < len; j++) {
Vii.add(Vi.get(j));
}
// Pid-Xid
ArrayList<SO> a = minus(Pd[i], oPopulation[i]);
ra = random.nextFloat();
// ra(Pid-Xid)
len = (int) (a.size() * ra);
for (j = 0; j < len; j++) {
Vii.add(a.get(j));
}
// Pgd-Xid
ArrayList<SO> b = minus(Pgd, oPopulation[i]);
rb = random.nextFloat();
// rb(Pgd-Xid)
len = (int) (b.size() * rb);
for (j = 0; j < len; j++) {
SO tt = b.get(j);
Vii.add(tt);
}
// save new Vii
listV.set(i, Vii);
// refresh position
// Xid’=Xid+Vid
add(oPopulation[i], Vii);
}
改变 swarm 的数目和迭代次数,得到的路径长度如下:
随着两个参数的无限增长,得到的最佳路径也会越来越短,但同时所耗的内存和时间也会有所增加。
最佳路径大概长这样:
P.S. 在 IntelliJ 里面做界面真的太方便了。
代码已上传到 github,点击传送门~
欢迎关注我的知乎专栏【数据池塘】,专注于分享机器学习、数据挖掘干货:https://zhuanlan.zhihu.com/datapool
⬇️ 扫描下方二维码关注公众号【数据池塘】 ⬇️
回复【算法】,获取最全面的机器学习算法网络图: