粒子群算法是一种人工智能算法,它模拟自然界中鸟类觅食的规律,被广泛用于优化领域。出于学习的目的,笔者用C#写了一个求函数y=x*2+1/x的最小值的示例,并利用TeeChart绘图控件,将求解最小值的过程形象地表示出来。
算法的思路:
1.指定一定规模的鸟群(笔者只使用了10只鸟作为搜索),每只鸟Bird都有三个属性:X、V、Best
public class Bird { public double X { get; set; } public double V { get; set; } public double Best { get; set; } }
其中,X代表鸟Bird的当前位置,V代表鸟当前的移动方向和移动速度,由于本文研究的是一元函数,所以X和V都是一维的,读者可以根据所研究问题的领域设计搜索空间的维度。Best代表当前这只鸟目前所找到的最小值。
2.按照将每只鸟按照b.V = (w * b.V + c1 * rand1 * (b.Best - b.X) + c2 * rand2 * (gBest - b.X));更新鸟的位置,即让每只鸟飞行一段距离。其中w代表惯性指数,这是代表该鸟对其移动方向的自信程度,c1代表该鸟对自己之前找到的最小值的信任程度,c2代表该鸟对整个种群的最小值的信任程度。
public void run() { int count = 0; double rand1 = rand.NextDouble(); double rand2 = rand.NextDouble(); //根据标准差(种群中粒子的分布的离散程度)和最大迭代次数进行收敛判断 while (count < 50000 && stdd > 0.0001) { Thread.Sleep(100); foreach (Bird b in birds) { double oldValue = F1(b.Best); b.V = (w * b.V + c1 * rand1 * (b.Best - b.X) + c2 * rand2 * (gBest - b.X)); if ((b.X + b.V) > Double.Parse(txtXStart.Text) && (b.X + b.V) < Double.Parse(txtXEnd.Text)) { b.X = b.X + b.V; } else if((b.X + b.V) < Double.Parse(txtXStart.Text)) { b.X = Double.Parse(txtXStart.Text); } else { b.X = Double.Parse(txtXEnd.Text); } if (F1(b.X) < oldValue) { b.Best = b.X; } if (F1(b.X) < F1(gBest)) { gBest = b.X; } } ShowSwarm(birds); double[] x = new double[birdnum]; //计算种群的离散程度 for (int i = 0; i < birds.Count; i++) { x[i] = birds[i].X; } stdd = StDev(x); count++; } }需要特别注意的是,笔者采用鸟群分布的离散程度作为收敛条件,读者也可以自己定义其他的指标判断收敛。其他的具体细节可以参考 项目github地址(vs2015)。