用JS简单实现一个群智能算法(布谷鸟搜索算法(CS))
有时我们会遇到一些非凸、不可微、不可导的问题,传统的算法无法解决这些问题。这时,我们可以用群智能算法(比如遗传算法、粒子群算法、布谷鸟算法等等)在符合要求的时间内找到一个近似解,这个解未必是最优解,但足够解决问题了。
群智能算法
群智能算法是一种新兴的演化计算技术,是受到群体生物启发的算法。这里不具体阐述。
布谷鸟算法(CS)
我不再赘述布谷鸟算法,在谷歌学术有大把论文介绍这个算法,在各大博客也有很多文章介绍这个算法。不过基本上都是用MATLAB跑算法。
JS实现CS
我学习CS的时候是用MATLAB写的,JS缺失了大量的方法(即MATLAB中的函数),所以我用了其它方法实现CS,可能会和论文的代码流程不太一致。我试着从0开始写一个算法,为了节约时间就选用了js(js是动态数据类型)。
function CS(testFunction) {
//属性,算法参数
this.NP = 30;
this.D = 30;
this.MaxIterations = 10000;
this.pa = 0.25;
//方法
this.getCS = getCS;
this.getCuckoos = getCuckoos;
this.emptyNests = emptyNests;
this.getBestNest = getBestNest;
this.simplebounds = simplebounds;
this.benchmarkFunction = testFunction;
this.nest = [];//合格的种群
this.newnest = [];//新种群
this.fitness = [];
this.LB = []; this.UP = [];
this.best; this.fmin;
}
function getCS(np, d, G, lb, up) {
//初始化
this.D = d; this.NP = np; this.MaxIterations = G;
for (let i = 0; i < this.NP; i++) {
this.fitness[i] = this.LB * 1000000;
}
for (let i = 0; i < this.D; i++) { this.LB[i] = lb };
for (let i = 0; i < this.D; i++) { this.UP[i] = up };
for (let i = 0; i < this.NP; i++) {
this.nest[i] = this.Lb + (this.Ub - this.Lb) * Math.random();
}
this.newnest = this.nest;
this.getBestNest();
let t = 0;
while (t < this.MaxIterations) {
t++;
this.getCuckoos();
this.getBestNest();
this.emptyNests();
this.getBestNest();
}
}
//全局
function getCuckoos() {
beta = 3 / 2;
//sigma = Math.pow((gamma(1 + beta) * Math.sin(Math.PI * beta / 2) / (gamma((1 + beta) / 2) * beta * Math.pow(2, ((beta - 1) / 2))), (1 / beta));
//js没有gamma函数,我一下子写不出来,所以用手算的值代替
sigma = Math.pow((1.3293 * Math.sin(Math.PI * beta / 2) / (1.3293 / 2) * beta * Math.pow(2, ((beta - 1) / 2))), (1 / beta));
for (let i = 0; i < this.n; i++) {
let s = this.newnest[i];
let u = randomNormalSize(0, 1, this.D) * sigma;
let v = randomNormalSize(0, 1, this.D);
let step = Math.pow((u / Math.abs(v)), (1 / beta));
stepsize = 0.01 * step * (s - this.best);
s = s + stepsize * randomNormalSize(0, 1, this.D);
this.newnest[i] = simplebounds(s);
}
}
//局部
function emptyNests() {
let K = [];
for (let i = 0; i < this.NP; i++) { K[i] = Math.random() > this.pa ? 0 : 1; }
let s = this.nest;
let s1 = s.sort(function () {
return Math.random() > 0.5 ? -1 : 1
})
let s2 = s.sort(function () {
return Math.random() > 0.5 ? -1 : 1
})
let stepsize = Math.random() * (s1 - s2);
this.newnest = this.nrst + stepsize * K;
for (let i = 0; i < this.NP; i++) {
this.newnest[i] = simplebounds(this.newnest[i]);
}
}
//评价
function getBestNest() {
let newfit = 1000;
for (let i = 0; i < this.NP; i++) {
newfit = this.benchmarkFunction(this.newnest[i]);
if (newfit < this.fitness[i]) {
this.fitness[i] = newfit;
this.nest[i] = this.newnest[i];
}
}
let temp = this.fitness[0];
let t = 0;
for (let i = 1; i < this.NP; i++) {
if (this.fitness[i] < temp) {
temp = this.fitness[i];
t = i;
}
}
this.fmin = temp; this.best = this.nest[t];
}
//越界处理
function simplebounds(s) {
for(let i in s){
if(s[i]>this.UP[i]){
s[i]=this.UP[i];
}else if(s[i]<this.LP[i]){
s[i]=this.LP[i];
}
}
return s;
}
//由于js没有产生正态分布随机数,所以写了这个函数用于产生随机数 normal
function randomNormal(mean, std) {
let u = 0.0, v = 0.0, w = 0.0, c = 0.0;
do {
//获得两个(-1,1)的独立随机变量
u = Math.random() * 2 - 1.0;
v = Math.random() * 2 - 1.0;
w = u * u + v * v;
} while (w == 0.0 || w >= 1.0)
//这里就是 Box-Muller转换
c = Math.sqrt((-2 * Math.log(w)) / w);
let random = mean + (u * c) * std;
return random;
}
//用于生产服从正态分布的随机数矩阵
function randomNormalSize(mean, std, size) {
let random = [];
for (let i = 0; i < size; i++) {
random[i] = randomNormal(mean, std);
}
return random;
}
//gamma函数
//如果x为整数,gamma(x)=(x-1)!
//gamma(x) = integral from 0 to inf of t^(x-1) exp(-t) dt.
// function gamma(x){
//没有想好如何用js求积分
//return gamma;
// }
//测试函数
//计算平方和累加,输入解
function testFunction(n) {
let x = 0;
for (let i in n) {
x += Math.pow(n[i], 2);
}
return x;
}
testCs = new CS(testFunction);
testCs.getCS(30,30,1000,-10,10);
document.write("The bast value is: ",testCs.fmin);
很多数学工具js没有进行封装,要写原生代码,不太友好,若非必要,可以使用其他语言完成复杂的算法
结果是0,有兴趣的小伙伴可以写其它的测试函数测试一下这个算法。
本文来自博客园,作者:Patrick-Rex,转载请注明原文链接:https://www.cnblogs.com/patrickrex/p/18028812
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 百万级群聊的设计实践
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
· 永远不要相信用户的输入:从 SQL 注入攻防看输入验证的重要性
· 全网最简单!3分钟用满血DeepSeek R1开发一款AI智能客服,零代码轻松接入微信、公众号、小程
· .NET 10 首个预览版发布,跨平台开发与性能全面提升