C#利用粒子群算法实现求一元函数最小值
程序员文章站
2022-06-08 18:40:41
...
粒子群算法是一种人工智能算法,它模拟自然界中鸟类觅食的规律,被广泛用于优化领域。出于学习的目的,笔者用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)。推荐阅读