Java-自然启发的算法教程-全-

Java 自然启发的算法教程(全)

原文:Nature-Inspired Optimization Algorithms with Java

协议:CC BY-NC-SA 4.0

一、最优化导论:问题与技术

真正的优化是现代研究对决策过程的革命性贡献。

—乔治·丹齐格,美国科学家

本章介绍了优化技术,重点是那些元启发/自然启发的技术。您将学习如何对这些技术和可用的基准函数类型进行基准测试。

优化一览

在商业、政府和我们的个人生活中,我们每天都在决定如何最好地利用可用资源,包括时间和金钱。很难决定买哪些东西或者走哪条路线去上班。

对于与供应链打交道的组织来说,这种挑战更加严峻。例如,他们必须解决如何将包裹装载到一队卡车上,司机应该选择哪条路线在最少的时间内交付货物,或者如何在航班全天穿越全国时为航班分配机组人员和飞机。

当有许多选择和相互关系时,将有限资源分配给不同用途的决策是优化的主要候选。在优化中,您需要定量地定义一个模型,该模型指定您的资源可能被分配的所有方式、时间或位置,以及必须满足的对资源和使用的所有重要约束。然后确定满足最佳资源分配的解决方案。

一般来说,最优化问题基于三个基本原则。

  • 决策变量

  • 目标函数

  • 限制

量化的决策变量是分配给每次使用的资源数量;例如,每班工作的员工人数或装载到每辆卡车上的包裹数量。为了确定什么是最佳方法,您必须定义一个称为目标的量,它可以计算决策变量的值——例如最小化成本、最大化利润或最小化生产时间。

由于任何资源都受到一些限制,为了完成模型,您必须定义每个约束或限制资源的分配方式,以反映现实世界的情况。通常,这些是从决策变量中计算出来的简单约束限制,例如“完成任务的最大时间是 150 小时”

例如,一个店主希望保留一些商品,以最大化利润或降低库存成本。在这种情况下,决策变量是要保留的项目。一个限制因素可能是资本的数量。利润是目标函数。

另一个例子是股票投资组合。目标函数是财富最大化。决策变量是个股。一个限制是投资者拥有的资金数量。

一个优化问题可以通过两种主要方式来解决:精确方法启发式方法

精确优化方法的优点来自于对最佳解决方案(从技术上讲,是一个最优解决方案)的有保证的识别。但是根据问题集的不同,最优的解决方案可能是昂贵的、耗时的或者不切实际的。如果决策变量空间太大,精确的方法优化可能是棘手的。

在这种情况下,最好使用启发式方法,这通常会提供良好、快速的解决方案。启发法通常是在有限的时间内解决最困难的商业问题的关键。

你现在看到了我们在日常生活和工作中面临的各种优化问题。

优化问题

最优化问题可以大致分为五种类型。如果问题是线性的,约束和目标函数只能是线性的。在非线性问题中,约束和目标函数可以是线性的,也可以是非线性的。当没有提到决策变量时,假设它们是连续的。在整数规划中,决策变量是离散的。在混合整数规划中,决策变量可以是连续的,也可以是离散的。这些优化问题在表 1-1 中有进一步描述。

表 1-1

与优化相关的问题

|

类型

|

决策变量

|

限制

|

目标函数

|
| --- | --- | --- | --- |
|

连续的

|

分离的

|

线性的

|

非线性的

|

线性的

|

非线性的

|
| --- | --- | --- | --- | --- | --- |
| 线性规划 | 是 | 不 | 是 | 不 | 是 | 不 |
| 非线性规划 | 是 | 不 | 是 | 是 | 是 | 是 |
| 整数线性规划 | 不 | 是 | 是 | 不 | 是 | 不 |
| 混合整数线性规划 | 是 | 是 | 是 | 不 | 是 | 不 |
| 混合整数非线性规划 | 是 | 是 | 是 | 是 | 是 | 是 |

优化技术

有三种类型的优化技术来解决优化问题。

  • 数学技巧基于问题的几何性质。

例子包括整数规划的单纯形算法,其中约束和目标函数是线性的;混合整数线性规划的分枝定界法:以及非线性规划的最速下降法和牛顿法。

  • 元启发式技术基于近似解,主要受自然过程的启发。

元启发式技术的例子包括粒子群优化、灰狼优化和蚁群优化。

元启发式技术的美妙之处在于它不依赖于问题的结构。求解线性规划问题的方法与求解非线性规划问题的方法相同。因此,这些技术也被称为黑盒优化技术

  • 其他技术包括斐波那契方法和黄金分割法。

这本书关注元启发式技术。其他技术的探索留给读者自己。

优化阻碍进化。除了第一次,所有的东西都应该自上而下的构建。简单不在复杂之前,而是在复杂之后。

——艾伦·珀利斯

优化的元启发式技术

元启发式技术受到自然和自然过程的启发。大多数技术都是基于自组织和涌现的原理。

自然界充满了涌现的例子。物理学的两大定律——热力学和广义相对论——是突现行为的例子。以温度为例。这是许多分子相互剧烈作用的结果。广义相对论认为时空是一条曲线。重力是空间和时间弯曲的结果。是什么导致的?科学家努力定义引力的量子观点。

但是什么是涌现呢?我们来探索一下。

两个科学模型定义了我们周围的所有事物、行为和过程。这些过程从植物到动物再到社会网络中的人类。

还原论和涌现

我们来看一个简单的现象——水。量子层次由分子、原子、电子、质子、中子和夸克组成。看待事物有两种不同的尺度。在物理学中,这被称为重整化。由于一个物体中的分子数量多得数不过来,而且每个分子都有很高的自由度,所以很难区分整体和部分。

让我们来看看一个物体在两个尺度上的属性。

  • 微观描述单个粒子的属性,比如质量、速度、位置。

  • 宏观描述压力和温度等属性。

“从部分到整体”意味着我们观察子部分中的每个分子,然后计算整个系统的行为/特性。这是一种简化的方法:将系统分解成最低层次,然后从那里开始。

约翰·惠勒(John Wheeler)是一位颇具影响力的普林斯顿大学物理学家,他的工作涉及从核物理到黑洞的各种主题,他表达了一种有趣的替代观点:“每一条被推到极致的物理定律都会被发现是统计上的和近似的,而不是数学上的完美和精确。”这意味着聚合是在每个级别或规模上完成的。这也被称为重整化。这种数学形式系统地从小到大。关键的一步是取平均值。突现模型没有深入微观细节,而是描述了出现的集体行为。一个经典的例子是基于神经元相互作用的人类智能。单个神经元非常简单(要么激活,要么不激活)。

多个神经元之间的相互作用产生了智能和感知,或者你可以说智能出现了。自然界有大量涌现的例子——蚁群、鸟群、蜜蜂。例如,一只蚂蚁的能力非常有限,但当在一个群体中时,集体行为就会出现,这有助于蚂蚁完成觅食等任务。

蚂蚁是复杂的蚁群系统中相对简单的组成部分。或者,更具体地说,与整个系统正在做的事情相比,每个 ant 组件的行为相对简单。一个蚁群可以从事复杂的行为,如筑巢、觅食、饲养蚜虫“牲畜”、与其他蚁群展开战争以及埋葬它们的死者。相比之下,没有一个人有独立承担这种集体任务的冲动或知识。意外出现的集体行为称为突发行为。

单个元素遵循一些明确定义的交互规则,复杂的行为就出现了。互联网和社交网络是新兴系统的例子。试图通过神经网络或自然启发的算法来模拟人脑的计算机科学研究都是计算机科学中出现的案例。

自组织

自组织是解释集体行为的复杂适应系统的一个原理。把它们想象成具有反馈回路的紧急系统,不断允许在微观层面上进行调整。系统的各个部分根据从环境中感知的信息和它们共同遵守的简单原则来组织自己。当原则对每个人都起作用且明确时,系统就会自我组织。团队不仅仅是各个部分的总和,而且拥有个人所没有的涌现的特性。

根据系统观,一个有机体或生命系统的本质属性是整体的属性,任何一个部分都不具备。它们产生于各部分之间的相互作用和关系。当系统在物理上或理论上被分解成孤立的元素时,这些性质就被破坏了。虽然我们可以辨别任何系统中的个别部分,但这些部分不是孤立的,整体的性质总是不同于其部分的简单总和。

—弗里乔夫·卡普拉,生命之网

元启发式技术是这样一种技术,它不依赖于问题的形状(像一个数学属性),而更像一个黑盒一样对待优化。应用这种技术导致在一个大的搜索空间中找到一个近似解,在这个搜索空间中,普通技术很容易变得计算密集甚至难以处理。

探索与开发

在接下来的章节中,你会遇到探索和开发,并了解大自然如何利用这些机制来达到最佳解决方案。

探索意为探索新的解决方案。例如,在日常生活中,我们通常试图学习新的东西。我们不断探索世界,寻找解决问题的新方法或增长知识。动物同样会探索新的解决方案来完成某些任务。

另一方面, exploitation 意味着使用现有的解决方案或附近的东西。它优化已知的解决方案和知识。

勘探和开发之间总是有一个权衡,需要混合使用这两种策略才能得到一个好的解决方案。勘探和开采最好放在多臂强盗问题的保护伞下理解(见 https://en.wikipedia.org/wiki/Multi-armed_bandit )。

元启发式技术的工作流程

以下术语都是元启发式技术工作流的一部分,所以在回顾这个过程之前把它们放在上下文中是很重要的。

  • 一个代表个人的维度或特征。

  • 群体是个体解的集合。

  • 参数可以针对具体算法进行调整/微调。

  • 适应度函数是需要优化的目标函数。

  • 迭代/世代是达到最优或最佳解决方案的迭代次数。

下面描述了工作流程。

  1. 定义问题的参数,例如群体大小和迭代次数。

  2. 生成随机解决方案的群体。

  3. 迭代。

  4. 从总体中选择一些解决方案。

  5. 稍微改变一下解决方案。

  6. 检查在步骤 5 中获得的解决方案的适用性。

  7. 应用幸存者函数以获得最佳解决方案。

  8. 转到步骤 3。(继续这样做,直到达到最大迭代次数)。

元启发式技术的基准函数

基准函数测试元启发式算法的性能。在基准函数中表现良好的算法往往在现实问题中表现良好。有大量的基准函数。表 1-2 列出了其中的几个。它们中的一些被用在后面几章讨论的算法中。

表 1-2

基准函数

| - ![img/507910_1_En_1_Figa_HTML.gif](https://gitee.com/OpenDocCN/vkdoc-java-zh/raw/master/docs/ni-opti-algo-java/img/507910_1_En_1_Figa_HTML.gif) |

摘要

本章讨论了最优化和解决最优化问题所涉及的各种技术。它介绍了解决优化问题的元启发式方法,并描述了元启发式算法评估的一些基准函数。

二、哺乳动物:鲸鱼、灰狼和蝙蝠优化

本章通过观察鲸鱼、灰狼和蝙蝠向你介绍最优化问题解决的世界。你将了解这些哺乳动物如何发展出特定的技术来解决它们生存所需要解决的某些问题。这些问题包括觅食或狩猎。

历史:鲸鱼

鲸鱼不唱歌是因为它们有答案。他们唱歌是因为他们有一首歌。

—格利高里·考伯特,加拿大电影人

鲸鱼是世界上最大的哺乳动物。它们可以长到 30 米长,重达 180 吨。有许多不同种类的鲸鱼,包括虎鲸、小须鲸、座头鲸、露脊鲸、露脊鲸和蓝鲸。

鲸鱼是具有高智商和高情商的食肉哺乳动物。

根据研究,鲸鱼大脑中某些区域的细胞与人类相似。这些纺锤体细胞负责判断能力、情绪和社会行为。一只鲸鱼的这些细胞数量几乎是成年人的两倍,这是它们聪明的主要原因之一。已经证明,鲸鱼可以像人类一样思考、学习、判断、交流和变得情绪化,尽管智力水平低得多。鲸鱼也是群居的。他们中的一些物种(例如虎鲸)可以一生都生活在一个家庭中。

本章重点介绍座头鲸,最大的须鲸之一。

座头鲸最有趣的是它们特殊的捕猎方式。这种觅食行为被称为泡网喂食法。座头鲸喜欢捕食成群的磷虾或靠近水面的小鱼。据观察,这种觅食是通过沿着圆形或 9 字形路径产生独特的气泡来完成的。在 2011 年之前,这种行为只是从表面观察到的。然而,Goldbogen 等人[4]使用标签传感器研究了这种行为。他们捕获了 9 头座头鲸的 300 个标签衍生的泡泡网进食事件。他们发现了两种与泡沫相关的动作,并将它们命名为上升螺旋双循环。在向上螺旋运动中,座头鲸潜到大约 12 米,在猎物周围形成一个螺旋形状的气泡,然后向水面游去。双环机动包括三个不同的阶段:珊瑚环、长尾和捕获环。

值得一提的是,泡网摄食是一种独特的行为,只有在座头鲸身上才能观察到。螺旋泡网进料策略的数学模型用于执行优化。

泡沫网喂食是鲸鱼故意从鼻子里吹出泡沫,像网一样包围它们的食物(磷虾和鱼),将它们的猎物集中成一个紧密的球。然后,鲸鱼或一群鲸鱼一起从这个球下面游出来,浮上水面,张开它们的嘴,吞下它们的猎物。

鲸鱼优化算法(WOA)是最近开发的一种基于群体的元启发式算法,基于泡网搜索策略技术,用于解决复杂的优化问题。由于其结构简单、所需算子少、收敛速度快、在勘探和开发阶段之间具有更好的平衡能力,已成为一种被广泛接受的群体智能技术。由于其优化的性能和效率,该算法在多学科领域得到了广泛的应用。

Whale 优化基于两种策略。

  • 探索(环绕)

  • 漏洞利用(使用泡泡网方法的攻击)

包围猎物

让我们讨论一下鲸鱼在包围猎物时表现出的一些特征。

img/507910_1_En_2_Figa_HTML.jpg

  • 座头鲸知道猎物的位置并包围它们。

  • 他们认为当前的最佳候选解决方案是获得的最佳和接近最佳的解决方案。

  • 在指定最佳候选解之后,其他代理朝着最佳搜索代理更新它们的位置,如等式 2-1 所示。

方程式 2-1。鲸鱼位置更新

在方程 2-1 中, t 为当前迭代, AC 为系数向量, X *为最佳解的位置向量, X 表示一个解的位置向量,| |为绝对值。

如公式 2-2 所示计算 AC 矢量。

img/507910_1_En_2_Figb_HTML.jpg

方程式 2-2。计算系数向量

在整个迭代过程中, a 的分量从 2 线性减少到 0, r 是[0;1].

开发阶段:泡沫网攻击方法

座头鲸利用泡泡网机制攻击猎物。这种机制在数学上是通过收缩环绕机制来表述的。

在这个机制中, A 是区间–Aa 中的随机值。在整个迭代过程中, a 的值从 2 减小到 0。然后,鲸鱼的位置以螺旋方式更新。这是基于鲸的位置和猎物的位置之间的距离,并基于两个相等的概率方程进行计算(见方程 [2-3 和 2-4 )。

X(t + 1) = X ,(t)-a(p<0.5)

X(t+1)=D′eblcos(27d)+X(t)(p>0.5)*

方程式 2-3。泡泡网机制*

D′是猎物与鲸鱼之间的距离。

D’= | XT5(t)= X(t)*|

方程式 2-4。猎物和鲸鱼之间的距离更新

鲸鱼流程图

图 2-1 描绘了 whale 优化算法的流程。它首先初始化参数,如种群大小和迭代次数。它初始化群体本身,然后在每次迭代期间,它更新每个代理(群体成员)的位置,并计算每个代理的适应度。在最后一次迭代之后,最适合的代理被认为是最佳解决方案。

img/507910_1_En_2_Fig1_HTML.png

图 2-1

鲸鱼优化算法的流程图

鲸鱼伪代码

以下伪代码描述了图 2-1 中概述的 whale 优化算法。

Randomly initialize the whale population.
Evaluate the fitness values of whales and find out the best search agent X* .
Initialize the whales population Xi (i = 1, 2, ..., n)
Calculate the fitness of each search agent
X*=the best search agent
while (t < maximum number of iterations)
    for each search agent
    Update a, A, C, l, and p
        if1 (p<0.5)
            if2 (|A| < 1)
                Update the position of the current search agent by the Eq. (2.1)
            else if2 (|A|>=1)
                Select a random search agent ( )
                Update the position of the current search agent by the Eq. (2.3)
            end if2
        else if1 (p >=0.5)
                Update the position of the current search by the Eq. (2.3)
        end if1
    end for
    Check if any search agent goes beyond the search space and amend it
    Calculate the fitness of each search agent
    Update X* if there is a better solution
    t=t+1
end while
return X*

Whale 先决条件和代码

确保您的计算机上安装了 Java 8 (JDK8 或更高版本)。像 Eclipse 这样的 IDE 是推荐的,但不是必需的,因为您可以使用命令行界面来运行代码,而不需要 IDE。

whale 算法的代码包含以下类。

img/507910_1_En_2_Figc_HTML.jpg

  • 点工具类,有三个成员(见清单 2-1 )

    • 双数组

    • 整数数组

    • 整数

  • 优化评估函数的 Rastrigin 实用程序类(见清单 2-2 和方程 2-5

  • WhaleOptimizer 优化类,算法功能的主要 Java 类(参见清单 2-3 )

方程式 2-5。 Rastrigin 基准函数

import java.lang.Math;
import java.util.*;
public class WhaleOptimizer
{
// declare variables for population size, number of iterations, dimensions and bounds.

int popSize;
int iterations;

int dimensions;
int ub=100,lb=-100;
// an array to represent the fitness values.
double fitness[];
// Represents the best Solution
double[] bestSolution;

double minValueOfSolution;
double leaderDistance;
double[][] positions;
// other constants used within the algorithm
double a,t,a2,p;

/*
Initialize the variables

and arrays within the constructor. We will initialize the population here with dimensions capped between lower and upper bounds.
*/
public WhaleOptimizer(int iterations,int popSize, int dimensions)
{

    this.iterations=iterations;
    this.popSize=popSize;
    this.dimensions=dimensions;
    positions=new double[popSize][dimensions];
    fitness=new double[popSize];
//Initialize the population of all solutions
    for(int i=0;i<popSize;i++)
    {
    for (int j=0;j<dimensions;j++)
    {
// cap the values between upper and lower bounds
        positions[i][j]=Math.random()*(ub-lb)+lb;
    }
    }
// calculate the fitness of each solution in the population
    for(int i=0;i<popSize;i++)
    {
        fitness[i]=fitnessCalculator(positions[i]);

    }

// Get the best solution in population with random initialized values.
    int bestIndex= indexOfSmallest(fitness);
    bestSolution=positions[bestIndex];
    minValueOfSolution=smallestInArray(fitness);
}
//rastrigin function used for calculating the fitness of the solutions
private  double fitnessCalculator(double[] candidate)
{

    Point p= new Point(candidate);
    Rastrigin rast=new Rastrigin(10,dimensions);
// The other benchmark which can be experimented with is Ackley.
    //Ackley ack=new Ackley(10,10,10,10);
    return rast.f(p);

}
/*
Helper method which finds the smallest member in an array of doubles
*/
private static double smallestInArray(double[] array){

    // add this
    if (array.length == 0)
       return -1;

    int index = 0;
    double min = array[index];

    for (int i = 1; i < array.length; i++){
       if (array[i] <= min){
       min = array[i];
       //index = i;
       }
    }
    return min;
}

/*
Helper method which finds the index of the smallest member in an array of doubles
*/

private static int indexOfSmallest(double[] array){

    // add this
    if (array.length == 0)
       return -1;

    int index = 0;
    double min = array[index];

    for (int i = 1; i < array.length; i++){
       if (array[i] <= min){
       min = array[i];
       index = i;
       }
    }
    return index;
}

/*
Main method for running the algorithm
*/
private void optimize()
{
    //main loop for iterating over configured number of iterations

    for(int i=0;i<iterations;i++){
        //loop over individual whale in the population. Each whale represents a solution in the
        //search space

        for(int j=0;j<popSize;j++)
        {

            //get positions of whales in bounds
            positions[j]=simpleBounds(positions[j],lb,ub);
            //System.out.println("velocities="+s[j][0]);

            // calculate fitness of each whale
                   double fNew = fitnessCalculator(positions[j]);

             // Update the current best solution
          if (fNew < minValueOfSolution)
            {
             bestSolution =positions[j].clone();
             minValueOfSolution = fNew;

            }

        }
    //loop over the population again
        for(int j=0;j<popSize;j++)
        {

         a = 2 - i * ((2) / iterations);
       // a decreases linearly from 2 to 0

       // a2 linearly decreases from -1 to -2 to calculate t
       a2 = -1 + i * ((-1) / iterations);
        double r1=Math.random();
        double r2=Math.random();
        //exploit phase starts

        double A = 2 * a * r1 - a;  // Equation 2.2 for calculating A
        double  C = 2 * r2 ; // Equation 2.2 for calculating C

        int   b = 1;
          double l = (a2 - 1) * Math.random() + 1;

        //random variable for calculating probablity
        p= Math.random();
        // Iterate over individual dimension of each of the solution
        for(int k=0;k<dimensions;k++)
        {
            //check for probability value via a random variable p
        //update position of individual whale using Equation 2.3

            if (p < 0.5)
            {
                if (Math.abs(A) >= 1)
                    {
                    int rand_leader_index = (int)Math.floor(popSize * Math.random());
                   double[] X_rand = positions[rand_leader_index].clone();
           double val= C * X_rand[k] - positions[j][k];
                   double D_X_rand = Math.abs(val);
            //update the whale position
            positions[j][k]= X_rand[k] - A * D_X_rand;

                    }

                    else if (Math.abs(A) < 1){
                        double val=C * bestSolution[j] - positions[j][k];
                    leaderDistance = Math.abs(val);
            //update the whale position
                    positions[j][k] = bestSolution[j] - A * leaderDistance;
                    }
            }

            else if (p >= 0.5)
            {

                double distance2Leader = Math.abs(bestSolution[j] - positions[j][k]);
            //update the whale position
            positions[j][k] = distance2Leader * Math.exp(b * l) * Math.cos(l * 2 * Math.PI)+ bestSolution[j];

            }

        }
        }
                // print the best solution
        System.out.println("iter="+i+" best fitness is ="+minValueOfSolution);

    }

}

/*
Method for bounding the value between lower and upper bounds
*/
private double[] simpleBounds(double[] val, double lower, double upper){
    double[] result = new double[val.length];
    for (int i = 0; i < val.length; i++) {

       if (val[i] < lower){
          result[i] = lower;
        }
       else if (val[i] > upper){
          result[i] = upper;
        }
        else
        {
            result[i]=val[i];
        }

    }
       return result;
}

/*
Main method to pass inputs and launch the algorithm
*/

public static void main(String[] args)
{
//takes input as number of iterations, population size and dimensions
int iter=Integer.parseInt(args[0]);
int pop=Integer.parseInt(args[1]);
int dim=Integer.parseInt(args[2]);
WhaleOptimizer whale =new WhaleOptimizer(iter,pop,dim);
whale.optimize();
}

}

Listing 2-3The WhaleOptimizer Class

    /*
    This class is used as the benchmark function and will be used throughout all algorithms.

    */
public class Rastrigin {

    private double A;
    private double n;

    public Rastrigin(double A, double n) {
        this.A = A;
        this.n = n;
    }

    /*
    This method is the main method for the Rastrigin benchmark function. It takes as input a Point object (explained above) and performs the calculations for the benchmark

.
    */

    public double f(Point x) {
        double sum = 0;
        //o = numpy.sum(x ** 2 - 10 * numpy.cos(2 * math.pi * x)) + 10 * dim
        for (int i = 0; i < x.dim; i++) {

            sum += Math.pow(x.p[i], 2) - A*Math.cos(2*Math.PI*x.p[i]);

        }
        return A*n + sum;
    }

}

/*
This class is the main optimizer class. Our objective function is the minimization of the benchmark function (Rastrigin in this case)

Listing 2-2The Rastrigin Class

public class Point {
    public double p[];
    public int ip[];
    public int dim;

    public Point(double p[]) {
        this.dim = p.length;
        this.p = p.clone();
    }

    public Point(int p[]) {
        this.dim = p.length;
        this.ip = p.clone();
    }

    public Point(int dim) {
        this.dim = dim;
        p = new double[dim];
    }
    /*
    this method returns the square root of the sum of the square of the members in the array of doubles
    */
    public double norm(){
        double sum = 0;
        for (int i = 0; i < dim ; i ++) {
            sum += Math.pow(this.p[i], 2);
        }
        return Math.sqrt(sum);
    }
    /*
    This method

returns the square root of the distance between 2 points. Its calculated by taking sum of the square of the distance between each element of the double array and then doing a square root of it.
    */
    public double dist(Point b){
        double sum = 0;
        for (int i = 0; i < dim ; i ++) {
            sum += Math.pow(this.p[i]-b.p[i], 2);
        }
        return Math.sqrt(sum);
    }
    /*
    This method adds the two Points by taking sum of the individual elements of the double array of each Point
    */

    public static Point add(Point a, Point b) throws Exception {
        if (a.dim != b.dim){
            throw new IllegalArgumentException("Adding points from different dimensions");
        }
        int dim  = a.dim;
        double cp[] = new double[dim];
        for (int i = 0; i < dim; i++){
            cp[i] = a.p[i] + b.p[i];
        }
        return new Point(cp);
    }
    /*
    This method

adds the two Points by taking sum of the individual elements of the double array of each Point and then takes an average of each added elements and finally returns a Point with the averages points in the new array
    */

    public static Point mid(Point a, Point b) throws Exception{
        if (a.dim != b.dim){
            throw new IllegalArgumentException("Incompatible points");
        }
        int dim  = a.dim;
        double cor[] = new double[dim];
        for (int i = 0; i < dim; i++){
            cor[i] = (a.p[i] + b.p[i]) / 2.0;
        }
        return new Point (cor);
    }
    /*
    This method multiplies each element of the array of double with the constant a. a is the coefficient we use in the optimization algorithm.
    */
    public Point mull(double a) {
        double p[] = new double[this.dim];
        Point m = new Point(p);
        for (int i = 0; i < this.dim; i++){
            m.p[i] = this.p[i]*a;
        }
        return m;
    }
    /*
    This method returns a string representation of the double array
    */

    @Override
    public String toString() {
        if (p != null) {
            String s = "[";
            for (int i = 0; i < this.dim; i++){
                s += (float)p[i];
                if (i == this.dim - 1) {
                    s += "]";
                } else {
                    s += ",";
                }
            }

            return s;
        } else {
            String s = "[";
            for (int i = 0; i < this.dim; i++){
                s += (int)ip[i];
                if (i == this.dim - 1) {
                    s += "]";
                } else {
                    s += ",";
                }
            }
            return s;
        }
    }
}

Listing 2-1The Point Class

执行鲸鱼代码

要编译 Java 文件,请使用以下命令。

javac Point.java
javac Rastrigin.java
javac WhaleOptimizer.java
//running the example with 50 iterations and population size of 10 and 30 dimensions
java WhaleOptimizer 50 10 30

以下是运行上述代码的输出。

iter=0 best fitness is =64618.62705831786
iter=1 best fitness is =6089.687035911165
iter=2 best fitness is =1191.832252196124
iter=3 best fitness is =1191.832252196124
iter=4 best fitness is =557.1033568751382
iter=5 best fitness is =294.5584859459394
iter=6 best fitness is =227.37519747187895
iter=7 best fitness is =227.37519747187895
iter=8 best fitness is =169.87626519543952
iter=9 best fitness is =164.24808671529178
iter=10 best fitness is =164.24808671529178
iter=11 best fitness is =164.24808671529178
iter=12 best fitness is =38.5966387729996
iter=13 best fitness is =38.5966387729996
iter=14 best fitness is =38.5966387729996
iter=15 best fitness is =38.5966387729996
iter=16 best fitness is =38.5966387729996
iter=17 best fitness is =36.691018990274586
iter=18 best fitness is =31.104006893451526
iter=19 best fitness is =31.104006893451526
iter=20 best fitness is =31.104006893451526
iter=21 best fitness is =31.104006893451526

iter=22 best fitness is =31.104006893451526
iter=23 best fitness is =31.104006893451526
iter=24 best fitness is =31.104006893451526
iter=25 best fitness is =31.104006893451526
iter=26 best fitness is =31.104006893451526
iter=27 best fitness is =30.71055488621937
iter=28 best fitness is =30.030588201965543
iter=29 best fitness is =30.030588201965543
iter=30 best fitness is =30.030588201965543
iter=31 best fitness is =30.030588201965543
iter=32 best fitness is =30.01029093772968
iter=33 best fitness is =29.990401804857754
iter=34 best fitness is =29.990401804857754
iter=35 best fitness is =29.950989401883703
iter=36 best fitness is =29.950989401883703
iter=37 best fitness is =29.88823708275629
iter=38 best fitness is =29.883783242305753
iter=39 best fitness is =22.450413721771895
iter=40 best fitness is =5.573548743084075
iter=41 best fitness is =1.2819795525663835
iter=42 best fitness is =1.2819795525663835
iter=43 best fitness is =1.2819795525663835
iter=44 best fitness is =1.2819795525663835

iter=45 best fitness is =1.2819795525663835
iter=46 best fitness is =1.2819795525663835
iter=47 best fitness is =1.2819795525663835
iter=48 best fitness is =1.2819795525663835
iter=49 best fitness is =0.9079497282054376

历史:灰狼

一个人可以和一只狼套近乎,甚至驯服一只狼,但没有人能真正驯服一只狼。

—乔治·马丁

这种元启发式算法是由 Seyedali Mirajaliali、Seyed Muhammad 和 Andrew Lewis 在 2014 年的一篇论文中提出的。它的灵感来自灰狼狩猎技术中的社会等级制度。

灰狼的社会等级根据适应度被定义为四个等级。

  • 一级(阿尔法)

    • 群体的领导者(可以是男性或女性)

    • 负责决定何时何地狩猎

    • 低级狼跟随阿尔法狼,并通过压低尾巴来表示认可

  • 2 级(测试版)

    • 这些狼帮助阿尔法做决策

    • 建议阿尔法狼并负责维持纪律

    • 在需要的时候从他们中间选出阿尔法(由于前阿尔法生病或死亡)

    • 充当阿尔法狼和其他低等狼之间的中间人,监督阿尔法狼的命令得到执行,并向阿尔法狼提供反馈

  • 三级(增量)

    • 他们被称为下属

    • 向阿尔法和贝塔报告,向欧米茄报告

    • 三角洲进一步分为

      • 负责监视边界的侦察员

      • 负责保护狼群的哨兵

      • 曾经是阿尔法和贝塔的长者

      • 帮助阿尔法和贝塔打猎的猎人

      • 帮助狼群中伤病者的看护者

  • 四级(欧米茄)

    • 等级制度中的最低层

    • 大多是族群的替罪羊

    • 必须最后一个吃

这种层次结构如图 2-2 所示。

img/507910_1_En_2_Fig2_HTML.png

图 2-2

灰狼的社会等级制度

狼越健康,它的级别就越高。这意味着阿尔法狼最适合,其次是贝塔狼,然后是德尔塔狼,最后是欧米加狼。

灰狼优化如何工作

寻找最优解的搜索过程基于灰狼狩猎行为模型,该模型有三个阶段。

  1. 寻找猎物。

  2. 包围猎物。

  3. 攻击猎物。

前两个阶段是探索性的,最后一个阶段是开拓性的。

搜索(探索)

探险是根据狼α、 βδ 的指引寻找猎物。 C α参数,如果其值为> 1,则表示正在进行探测。 C p 参数引入了狼与猎物之间距离的随机性。这种随机性对于避免解决方案陷入局部最优非常重要。

环绕(探索)

在捕猎过程中,灰狼包围猎物,数学上用方程 2-6 表示。

img/507910_1_En_2_Figd_HTML.jpg

方程式 2-6。狼和猎物之间的距离更新

在方程 2-6 中, t 代表当前迭代, AC 为系数向量。 X p 是猎物的位置向量, X 是狼的位置向量。在等式 2-7 中计算出 AC 矢量,并在迭代过程中线性减小。r1 和r2 为随机变量。

img/507910_1_En_2_Fige_HTML.jpg

方程式 2-7。更新系数

攻击(剥削)

阿尔法狼带头发起攻击。贝塔狼和德尔塔狼可能会不时参与进来。最佳解决方案是根据阿尔法狼、贝塔狼和德尔塔狼的位置得出的。

攻击行为如图 2-3 所示。它还描述了该过程的开发阶段。当 C α参数减小时,暗示着狼正在向猎物靠近。相反,如果 C α增加,那么狼正在远离猎物。当这个参数变得小于 1 时,狼正在攻击猎物。

img/507910_1_En_2_Fig3_HTML.png

图 2-3

灰狼的狩猎行为

ω 根据狼α、 βδ 的位置不断更新其位置。等式 2-8 反映了其位置的更新。

img/507910_1_En_2_Figh_HTML.jpg

img/507910_1_En_2_Figg_HTML.jpg

img/507910_1_En_2_Figf_HTML.jpg

方程式 2-8。根据狼α、β和δ的位置更新ω狼的位置

灰狼流程图

图 2-4 展示了灰狼优化算法的流程图。在高层次上,该流程图从初始化迭代次数和群体大小等参数开始。在每次迭代中,狼群的位置根据猎物的位置进行更新,并计算每只狼的适应度函数。在所有迭代之后,选择最佳适应值作为最佳解。

img/507910_1_En_2_Fig4_HTML.png

图 2-4

灰狼优化流程图

灰狼伪代码

以下伪代码描述了灰狼优化算法,如图 2-4 所示。

Begin
Initialize the parameters popsize, maxiter, ub and lb where
popsize: size of population,
maxiter: maximum number of iterations,
ub: upper bound(s) of the variables,
lb: lower bound(s) of the variables;
Generate the initial positions of gray wolves with ub and lb;
Initialize and Calculate the fitness of each gray wolf;
alpha = the gray wolf with the first maximum fitness;
beta = the gray wolf with the second maximum fitness;
delta = the gray wolf with the third maximum fitness;
While
   for  : popsize
     Update the position of the current gray wolf  ;
  end for
  Update and
  Calculate the fitness of all gray wolves;
  Update alpha, beta, and delta;
  ;;
end while
Return alpha;
End

灰狼先决条件和代码

同样,确保您的计算机上安装了 Java 8 (JDK8 或更高版本)。像 Eclipse 这样的 IDE 是推荐的,但不是必需的,因为您可以使用命令行界面来运行代码,而不需要 IDE。

whale 算法的代码包含以下 Java 类。

img/507910_1_En_2_Figi_HTML.jpg

  • 点工具类,有三个成员(见清单 2-4 )

    • 双数组

    • 整数数组

    • 整数

  • 优化评估函数的 Rastrigin 实用程序类(见清单 2-5 和方程 2-9

  • GrayWolfOptimizer 优化类,算法功能的主要 Java 类(参见清单 2-6 )

方程式 2-9。 Rastrigin 基准函数

/*
Main optimizer class for Gray Wolf optimization. Objective function is minimizing the Rastrigin benchmark function
*/
import java.lang.Math;
import java.util.*;
public class GrayWolfOptimizer
{
// declare variables for population size, iterations and dimensions
int popSize;
int iterations;

int dimensions;
//declare upper and lower bounds for the search space
double ub=5.12,lb=-5.12;
//declare array for holding the fitness values
double fitness[];
// array which holds dimensions of the best solution
double[] bestSolution;
// declare coefficients like alpha, beta and gamma
double alpha = 0.5 ; // Randomness 0--1 (highly random)
double betamin = 0.20 ; // minimum value of beta
// minimum value of the solution

double minValueOfSolution;
//declare two dimensional array for holding position of each solution
double[][] positions;
double[][] positions1;
int[] sortedIndex;
double[] alphaPosition;
double[] betaPosition;
double[] deltaPosition;
//start with a high value (randomly chosen as 100000000)
double alphaScore=10000000;
double betaScore=10000000;
double deltaScore=10000000;
public GrayWolfOptimizer(int iterations,int popSize, int dimensions)
{
//initialize the iterations , population size and dimensions
    this.iterations=iterations;
    this.popSize=popSize;
    this.dimensions=dimensions;
    positions=new double[popSize][dimensions];
    positions1=new double[popSize][dimensions];

    fitness=new double[popSize];
    alphaPosition=new double[dimensions];
    betaPosition=new double[dimensions];
    deltaPosition=new double[dimensions];
    //loop through the population size and initialize the dimensions for each solution
    // in the population
    for(int i=0;i<popSize;i++)
    {

    for (int j=0;j<dimensions;j++)
    {
    // cap the positions between lower and upper bounds
        positions[i][j]=Math.random()*(ub-lb)+lb;

    }

    }

}

//rastrigin function used
private  double fitnessCalculator(double[] candidate)
{

    Point p= new Point(candidate);
    Rastrigin rast=new Rastrigin(10,dimensions);
    //Ackley ack=new Ackley(10,10,10,10);
    return rast.f(p);
}

/*
Method for updating the position of the wolves. This takes in a coefficient as the parameter value
*/
private void updateWolvesPosition(double a)
{

    // Update the Position of search agents including omegas
       for (int i=0;i<popSize;i++)
        {
          for (int j=0;j<dimensions;j++){

             double r1 = Math.random()  ;// r1 is a random number in [0,1]
             double r2 = Math.random() ;//  r2 is a random number in [0,1]
// calculate A1 and C1 based on Equation 2-6.
             double A1 = 2 * a * r1 - a;
             double C1 = 2 * r2;
// update the position of alpha wolves

             double  D_alpha = Math.abs(C1 * alphaPosition[j] - positions[i][j]);
             double X1 = alphaPosition[j] - A1 * D_alpha;

             r1 = Math.random()  ;// r1 is a random number in [0,1]
             r2 = Math.random() ;//  r2 is a random number in [0,1]

             double A2 = 2 * a * r1 - a;
             double C2 = 2 * r2;
// update the position of beta wolves

             double D_beta = Math.abs(C2 * betaPosition[j] - positions[i][j]);
             double X2 = betaPosition[j] - A2 * D_beta;

             r1 = Math.random();
             r2 = Math.random();

             double A3 = 2 * a * r1 - a;
             double C3 = 2 * r2;
// update the position of delta wolves

             double D_delta = Math.abs(C3 * deltaPosition[j] - positions[i][j]);
             double X3 = deltaPosition[j] - A3 * D_delta;

             positions[i][j] = (X1 + X2 + X3) / 3  ;// Equation (2.8)
            }

        }
}

/*
This code is main method for the Gray Wolf optimization algorithm
*/
private void optimize()
{

    //main loop for number of iterations
    for(int it=0;it<iterations;it++){
        //loop over individual

    // loop through individual solution (wolves) in each iteration
        for(int i=0;i<popSize;i++)
    {
                       // calculate fitness of each solution
        fitness[i]=fitnessCalculator(positions[i]);

        // Update Alpha, Beta, and Delta scores and positions of alpha, beta and delta wolves
          if (fitness[i] < alphaScore)
            {
             deltaScore=betaScore;
                deltaPosition=betaPosition.clone();
             betaScore=alphaScore;
             betaPosition=alphaPosition.clone();
             alphaScore=fitness[i];
             alphaPosition=positions[i].clone();
            }
        // Update Alpha, Beta, and Delta scores and positions of alpha, beta and delta wolves

              if (fitness[i] > alphaScore && fitness[i] < betaScore)
              {
             deltaScore=betaScore;
                deltaPosition=betaPosition.clone();
             betaScore=fitness[i];

              betaPosition=positions[i].clone();
              }

        // Update Alpha, Beta, and Delta scores and positions of alpha, beta and delta wolves

        if (fitness[i] > alphaScore && fitness[i] > betaScore && fitness[i] < deltaScore)
        {
             deltaScore = fitness[i] ;
             deltaPosition=positions[i].clone();

        }

         double a = 2 - it * ((2) / iterations);
        // in each iteration update positions of wolves based on updates to a
updateWolvesPosition(a);
        }

    System.out.println("best score after iteration "+it+" ="+alphaScore);
}
}
/*
Main method for executing the code. It takes as input the number of iterations, population Size and number of dimensions as command line parameters
*/
public static void main(String[] args)
{
int iter=Integer.parseInt(args[0]);
int pop=Integer.parseInt(args[1]);
int dim=Integer.parseInt(args[2]);
GrayWolfOptimizer gwo =new GrayWolfOptimizer(iter,pop,dim);
gwo.optimize();
}
}

Listing 2-6The GrayWolfOptimizer Class

     /*
     This class is used as the benchmark function and will be used throughout all algorithms.

     */

public class Rastrigin {

    private double A;
    private double n;

    public Rastrigin(double A, double n) {
        this.A = A;
        this.n = n;
    }

    /*
      This method is the main method for the Rastrigin benchmark function. It takes as input a Point object (explained above) and performs the calculations for the benchmark.
     */

    public double f(Point x) {
        double sum = 0;
        //o = numpy.sum(x ** 2 - 10 * numpy.cos(2 * math.pi * x)) + 10 * dim
        for (int i = 0; i < x.dim; i++) {

            sum += Math.pow(x.p[i], 2) - A*Math.cos(2*Math.PI*x.p[i]);

        }
        return A*n + sum;
    }

}

Listing 2-5The Rastrigin Class

public class Point {
    public double p[];
    public int ip[];
    public int dim;

    public Point(double p[]) {
        this.dim = p.length;
        this.p = p.clone();
    }

    public Point(int p[]) {
        this.dim = p.length;
        this.ip = p.clone();
    }

    public Point(int dim) {
        this.dim = dim;
        p = new double[dim];
    }
    /*
     this method returns the square root of the sum of the square of the members in the array of doubles
    */
    public double norm(){
        double sum = 0;
        for (int i = 0; i < dim ; i ++) {
            sum += Math.pow(this.p[i], 2);
        }
        return Math.sqrt(sum);
    }

    /*
     This method returns the square root of the distance between 2 points. Its calculated by taking sum of the square of the distance between each element of the double array and then doing a square root of it.
    */
    public double dist(Point b){
        double sum = 0;
        for (int i = 0; i < dim ; i ++) {
            sum += Math.pow(this.p[i]-b.p[i], 2);
        }
        return Math.sqrt(sum);
    }
    /*
     This method adds the two Points by taking sum of the individual elements of the double array of each Point
    */

    public static Point add(Point a, Point b) throws Exception {
        if (a.dim != b.dim){
            throw new IllegalArgumentException("Adding points from different dimensions");
        }
        int dim  = a.dim;
        double cp[] = new double[dim];
        for (int i = 0; i < dim; i++){
            cp[i] = a.p[i] + b.p[i];
        }
        return new Point(cp);
    }

     /*
    This method adds the two Points by taking sum of the individual elements of the double array of each Point and then takes an average of each added elements and finally returns a Point with the averages points in the new array
    */

    public static Point mid(Point a, Point b) throws Exception{
        if (a.dim != b.dim){
            throw new IllegalArgumentException("Incompatible points");
        }
        int dim  = a.dim;
        double cor[] = new double[dim];
        for (int i = 0; i < dim; i++){
            cor[i] = (a.p[i] + b.p[i]) / 2.0;
        }
        return new Point (cor);
    }
    /*
    This method multiplies each element of the array of double with the constant a. a is the coefficient we use in the optimization algorithm.
    */
    public Point mull(double a) {
        double p[] = new double[this.dim];
        Point m = new Point(p);
        for (int i = 0; i < this.dim; i++){
            m.p[i] = this.p[i]*a;
        }
        return m;
    }
    /*
       This method returns a string representation of the double array
    */

    @Override
    public String toString() {
        if (p != null) {
            String s = "[";
            for (int i = 0; i < this.dim; i++){
                s += (float)p[i];
                if (i == this.dim - 1) {
                    s += "]";
                } else {
                    s += ",";
                }
            }

            return s;
        } else {
            String s = "[";
            for (int i = 0; i < this.dim; i++){
                s += (int)ip[i];
                if (i == this.dim - 1) {
                    s += "]";
                } else {
                    s += ",";
                }
            }
            return s;
        }
    }
}

Listing 2-4The Point Class

执行 Wolf 代码

下面的代码编译这些文件。

javac Point.java
javac Rastrigin.java
javac GrayWolfOptimizer.java

//running the example with 50 iterations and population size of 10 and 30 dimensions
java GrayWolfOptimizer 50 10 30

以下是运行上述代码的输出。

best score after iteration 0 =509.96673667327343
best score after iteration 1 =426.41598649085057
best score after iteration 2 =338.22309610465413
best score after iteration 3 =308.52361359264995
best score after iteration 4 =277.9213584359936
best score after iteration 5 =248.83646851559863
best score after iteration 6 =203.07265223211158
best score after iteration 7 =203.07265223211158
best score after iteration 8 =203.07265223211158
best score after iteration 9 =203.07265223211158
best score after iteration 10 =203.07265223211158
best score after iteration 11 =203.07265223211158
best score after iteration 12 =203.07265223211158
best score after iteration 13 =184.70404858170573
best score after iteration 14 =184.70404858170573
best score after iteration 15 =184.70404858170573
best score after iteration 16 =184.70404858170573
best score after iteration 17 =184.70404858170573
best score after iteration 18 =184.70404858170573
best score after iteration 19 =182.58434165600903
best score after iteration 20 =182.58434165600903
best score after iteration 21 =181.7495365991856
best score after iteration 22 =181.7495365991856
best score after iteration 23 =181.663022402521
best score after iteration 24 =181.663022402521
best score after iteration 25 =157.10334848914758
best score after iteration 26 =156.35153795887368
best score after iteration 27 =139.32771778897705

best score after iteration 28 =139.32771778897705
best score after iteration 29 =139.32771778897705
best score after iteration 30 =137.75584129668897
best score after iteration 31 =137.75584129668897
best score after iteration 32 =137.75584129668897
best score after iteration 33 =128.32651340584417
best score after iteration 34 =126.37388487653246
best score after iteration 35 =126.37388487653246
best score after iteration 36 =126.37388487653246
best score after iteration 37 =126.37388487653246
best score after iteration 38 =124.71241252923625
best score after iteration 39 =124.71241252923625
best score after iteration 40 =124.71241252923625
best score after iteration 41 =124.71241252923625
best score after iteration 42 =124.71241252923625
best score after iteration 43 =124.71241252923625
best score after iteration 44 =124.71241252923625
best score after iteration 45 =124.71241252923625
best score after iteration 46 =124.71241252923625
best score after iteration 47 =124.71241252923625
best score after iteration 48 =124.71241252923625
best score after iteration 49 =124.71241252923625

历史:蝙蝠

大黄蜂蝙蝠,你晚上怎么看?

我发出吱吱的声音,无论碰到什么都会反弹回来。我通过听觉看到。

——达林伦德

蝙蝠算法与其他元启发式算法是一致的,近似 NP 难问题。杨新社在 2010 年开发了这个算法。

这种算法是基于微老鼠的回声定位能力,其中发射率和响度是变化的。

微型蝙蝠是一种体重约 2 克的小蝙蝠。回声定位是蝙蝠以一定角度发出的声音脉冲。蝙蝠听到声波从周围物体反射回来的回声。这有助于蝙蝠找到猎物并避开障碍物。声波的频率范围从 25 千赫到 150 千赫。

图 2-5 展示了蝙蝠发射声纳波时回声定位的工作原理。距离障碍物的距离是通过结合声波反射回来的时间和发射波的频率来计算的。

img/507910_1_En_2_Fig5_HTML.jpg

图 2-5

蝙蝠的回声定位

蝙蝠利用图 2-6 所示的尺寸来搜寻猎物。

img/507910_1_En_2_Fig6_HTML.jpg

图 2-6

蝙蝠的各种尺寸

蝙蝠会根据与猎物的距离自动调整发射脉冲的频率或波长。假设响度从很高的值( A 0)变化到固定的最小值。等式 2-10 计算蝙蝠变化的位置和速度。

img/507910_1_En_2_Figj_HTML.jpg

方程式 2-10。根据物体的位置改变位置和速度

Bat 流程图

图 2-7 是蝙蝠优化算法的流程图。在高层次上,该流程图从初始化参数(例如,迭代次数和蝙蝠种群大小)开始。在每次迭代中,蝙蝠的位置和速度被更新,并且每个蝙蝠的适应度函数被计算。在所有迭代之后,选择最佳适应值作为最佳解。

img/507910_1_En_2_Fig7_HTML.png

图 2-7

Bat 优化流程图

Bats 伪代码

以下伪代码描述了 bat 优化算法,如图 2-7 所示。

   Objective function f(x), x = (x1, ..., xd)
   Initialize the bat population Xi (i = 1, 2, . . ., n)
   Define the pulse rate ri and the loudness Ai
   Input: Initial bat population
   while ( t < Max number of iterations ) do
       Generate new solutions by adjusting frequency, and updating velocities and locations/solutions (Equations in 2-10 )
      if ( rand > ri ) then
             Select a solution among the best solutions
             Generate a local solution around the selected best solution
       end if
       Generate a new solution by flying randomly
       if ( rand < Ai & f(Xi) < f(X∗) ) then
             Accept the new solutions
            Increase emission rate and reduce loudness
       end if
       Rank the bats and find the current best Xbest
    end while
    Output: Best bat found (i.e. best solution)

Bat 先决条件和 Bat 代码

同样,确保您的计算机上安装了 Java 8 (JDK8 或更高版本)。像 Eclipse 这样的 IDE 是推荐的,但不是必需的,因为您可以使用命令行界面来运行代码,而不需要 IDE。

bat 算法的代码包含以下类。

img/507910_1_En_2_Figk_HTML.jpg

  • 点工具类,有三个成员(见清单 2-7 )

    • 双数组

    • 整数数组

    • 整数

  • 优化评估函数的 Rastrigin 实用程序类(见清单 2-8 和方程 2-11

  • BatOptimizer 优化类,算法功能的主要 Java 类(参见清单 2-9 )

方程式 2-11。 Rastrigin 基准函数

/*
Main class for the Bat optimizer. Goal is to minimize the objective function represented by the Rastrigin benchmark
*/
import java.lang.Math;
import java.util.*;
public class BatOptimizer
{
// Declare number of iterations, population size and dimensions of each bat
int popSize;
int iterations;
int dimensions;
int ub=100,lb=-100;
// declare different coefficients and constants for the algo
double a=0.5;
double r=0.5;
double freq_min=0;
double freq_max=2;
// double array to hold the frequencies
double[] frequencies;
//two dimensional array of doubles for bat velocities
double[][] velocities;
double[][] solutions;
// array holding fitness value for each solution

double fitness[];
double[] bestSolution;
double[][] s;
double minValueOfSolution;

/*
Constructor for initializing the population and populating initial fitness of each solution (bat)
*/
public BatOptimizer(int iterations,int popSize, int dimensions)
{
    this.iterations=iterations;
    this.popSize=popSize;
    this.dimensions=dimensions;
    frequencies=new double[popSize];
    velocities=new double[popSize][dimensions];
    solutions=new double[popSize][dimensions];
    s=new double[popSize][dimensions];
    fitness=new double[popSize];
    //initialize solutions by looping over each member in the population

    for(int i=0;i<popSize;i++)
    {
    for (int j=0;j<dimensions;j++)
    {

        solutions[i][j]=Math.random()*(ub-lb)+lb;
    }
    }
    // calculate fitness of each solution
    for(int i=0;i<popSize;i++)
    {
        fitness[i]=fitnessCalculator(solutions[i]);
    }

// find the index of the best solution initially as well as the bestSolution
    int bestIndex= indexOfSmallest(fitness);
    bestSolution=solutions[bestIndex];
    minValueOfSolution=smallestInArray(fitness);
}
//rastrigin function used
private  double fitnessCalculator(double[] candidate)
{

    Point p= new Point(candidate);
    Rastrigin rast=new Rastrigin(10,dimensions);
    return rast.f(p);

    }
/*
Helper method for returning smallest value in array of doubles.
*/
private static double smallestInArray(double[] array){

    // add this
    if (array.length == 0)
       return -1;

    int index = 0;
    double min = array[index];

    for (int i = 1; i < array.length; i++){
       if (array[i] <= min){
       min = array[i];
       //index = i;
       }
    }
    return min;
}

/*
Helper method for returning index of the smallest member in the array
*/

private static int indexOfSmallest(double[] array){

    // add this
    if (array.length == 0)
       return -1;

    int index = 0;
    double min = array[index];

    for (int i = 1; i < array.length; i++){
       if (array[i] <= min){
       min = array[i];
       index = i;
       }
    }
    return index;
}
/*
Main method of the algorithm
*/

private void optimize()
{
    //main loop for number of iterations

    for(int i=0;i<iterations;i++){
        //loop over individual bat
        for(int j=0;j<popSize;j++)
        {
            // update frequency of each bat
            frequencies[j]=freq_min+(freq_max-freq_min)*Math.random();
            //velocities update for each bat

                //v[i, :] = v[i, :] + (Sol[i, :] - best) * Q[i]
// calculate difference from the best solution
double[] diffFromBest=subtractElementwise(solutions[j],bestSolution,frequencies);
            //update velocities for the bat
            velocities[j]= addElementwise(velocities[j],diffFromBest);

            s[j]= addElementwise(solutions[j],velocities[j]);

            s[j]=simpleBounds(s[j],lb,ub);

          if( Math.random() > r){

            s[j] = addArrayToRnd(bestSolution , 0.001 * rnd(dimensions));

            }

            //update the solution if fitness is better for the candidate
            // Evaluate new solutions
          double fNew = fitnessCalculator(s[j]);

          // Update if the solution improves
          if ((fNew <= fitness[j]) && (Math.random() < a))
            {
                solutions[j]= s[j].clone();
             //Sol[i, :] = numpy.copy(S[i, :])
             fitness[j] = fNew;
            }

             // Update the current best solution
          if (fNew <= minValueOfSolution)
            {
             bestSolution =s[j].clone();
             minValueOfSolution = fNew;

            }

        }
        System.out.println("iter="+i+" best fitness is ="+minValueOfSolution);
    }

}

/*
Helper method for returning a new array of double by adding the passed argument to individual member of the array
*/

private static double[] addArrayToRnd(double[] a, double num) throws ArithmeticException {

          double[] result = new double[a.length];
          for (int i = 0; i < a.length; i++) {
             result[i] = (a[i] + num);
          }
          return result;
}

/*
Helper method for returning a random value sampled from a gaussian
*/

private double rnd(int dim)
{

    Random r = new Random(dim);
double randomValue =  0+ r.nextGaussian()*1;
return randomValue;
}

/*
Helper method for keeping values in between lower and upper bounds
*/
private double[] simpleBounds(double[] val, double lower, double upper){
    double[] result = new double[val.length];
    for (int i = 0; i < val.length; i++) {

       if (val[i] < lower){
          result[i] = lower;
        }
       else if (val[i] > upper){
          result[i] = upper;
        }

        else
        {
            result[i]=val[i];
        }

    }
       return result;
}
/*
Helper method for returning difference between the elements of two array of doubles multiplied by the frequency of the specific bat
*/

 private static double[] subtractElementwise(double[] a, double[] b, double[] freq) throws ArithmeticException {

       if (a.length != b.length) {
          throw new ArithmeticException();
       } else {
          double[] result = new double[a.length];
          for (int i = 0; i < a.length; i++) {
             result[i] = (a[i] - b[i])*freq[i];
          }
          return result;
       }

    }

/*
Helper method for adding individual elements of the arrays of doubles
*/

private static double[] addElementwise(double[] a, double[] b) throws ArithmeticException {

       if (a.length != b.length) {
          throw new ArithmeticException();
       } else {
          double[] result = new double[a.length];
          for (int i = 0; i < a.length; i++) {
             result[i] = (a[i] + b[i]);
          }
          return result;
       }

    }
public static void main(String[] args)
{
int iter=Integer.parseInt(args[0]);
int pop=Integer.parseInt(args[1]);
int dim=Integer.parseInt(args[2]);
BatOptimizer bat=new BatOptimizer(iter,pop,dim);
bat.optimize();
}

}

Listing 2-9The BatOptimizer Class

      /*
      This class is used as the benchmark function and will be used throughout all algorithms.

      */

public class Rastrigin {

    private double A;
    private double n;

    public Rastrigin(double A, double n) {
        this.A = A;
        this.n = n;
    }

    /*
      This method is the main method for the Rastrigin benchmark function. It takes as input a Point object (explained above) and performs the calculations for the benchmark

.
       */

    public double f(Point x) {
        double sum = 0;
        //o = numpy.sum(x ** 2 - 10 * numpy.cos(2 * math.pi * x)) + 10 * dim
        for (int i = 0; i < x.dim; i++) {

            sum += Math.pow(x.p[i], 2) - A*Math.cos(2*Math.PI*x.p[i]);

        }
        return A*n + sum;
    }

}

Listing 2-8The Rastrigin Class

public class Point {
    public double p[];
    public int ip[];
    public int dim;

    public Point(double p[]) {
        this.dim = p.length;
        this.p = p.clone();
    }

    public Point(int p[]) {
        this.dim = p.length;
        this.ip = p.clone();
    }

    public Point(int dim) {
        this.dim = dim;
        p = new double[dim];
    }
     /*
     this method returns the square root of the sum of the square of the members in the array of doubles
     */
    public double norm(){
        double sum = 0;
        for (int i = 0; i < dim ; i ++) {
            sum += Math.pow(this.p[i], 2);
        }

        return Math.sqrt(sum);
    }
    /*
      This method returns the square root of the distance between 2 points. Its calculated by taking sum of the square of the distance between each element of the double array and then doing a square root of it.
    */
    public double dist(Point b){
        double sum = 0;
        for (int i = 0; i < dim ; i ++) {
            sum += Math.pow(this.p[i]-b.p[i], 2);
        }
        return Math.sqrt(sum);
    }
    /*
      This method adds the two Points by taking sum of the individual elements of the double array of each Point
     */

    public static Point add(Point a, Point b) throws Exception {
        if (a.dim != b.dim){
            throw new IllegalArgumentException("Adding points from different dimensions");
        }
        int dim  = a.dim;
        double cp[] = new double[dim];
        for (int i = 0; i < dim; i++){
            cp[i] = a.p[i] + b.p[i];
        }
        return new Point(cp);
    }
      /*
       This method adds the two Points by taking sum of the individual elements of the double array of each Point and then takes an average of each added elements and finally returns a Point with the averages points in the new array
      */

    public static Point mid(Point a, Point b) throws Exception{
        if (a.dim != b.dim){
            throw new IllegalArgumentException("Incompatible points");
        }

        int dim  = a.dim;
        double cor[] = new double[dim];
        for (int i = 0; i < dim; i++){
            cor[i] = (a.p[i] + b.p[i]) / 2.0;
        }
        return new Point (cor);
    }
    /*
      This method multiplies each element of the array of double with the constant a. a is the coefficient we use in the optimization algorithm.
     */
    public Point mull(double a) {
        double p[] = new double[this.dim];
        Point m = new Point(p);
        for (int i = 0; i < this.dim; i++){
            m.p[i] = this.p[i]*a;
        }
        return m;
    }
    /*
       This method returns a string representation of the double array
      */

    @Override
    public String toString() {
        if (p != null) {
            String s = "[";
            for (int i = 0; i < this.dim; i++){
                s += (float)p[i];
                if (i == this.dim - 1) {
                    s += "]";
                } else {
                    s += ",";
                }
            }

            return s;
        } else {
            String s = "[";
            for (int i = 0; i < this.dim; i++){
                s += (int)ip[i];
                if (i == this.dim - 1) {
                    s += "]";
                } else {
                    s += ",";
                }
            }
            return s;
        }
    }
}

Listing 2-7The Point Class

执行 Bat 代码

下面的代码编译这些文件。

javac Point.java
javac Rastrigin.java
javac BatOptimizer.java

//running the example with 50 iterations and population size of 10 and 30 dimensions
java BatOptimizer 50 10 30

以下是运行上述代码的输出。

iter=0 best fitness is =76483.71345283325
iter=1 best fitness is =76478.96155973038
iter=2 best fitness is =42783.77839770218
iter=3 best fitness is =42781.20842991052
iter=4 best fitness is =42779.167603237656
iter=5 best fitness is =42776.63576280687
iter=6 best fitness is =42774.62583068019
iter=7 best fitness is =42772.62987212166
iter=8 best fitness is =42771.63717776008
iter=9 best fitness is =42769.66244601229
iter=10 best fitness is =42766.72724352279
iter=11 best fitness is =42764.3061741315
iter=12 best fitness is =42761.43117104229
iter=13 best fitness is =42758.589572619385
iter=14 best fitness is =42755.31708648613
iter=15 best fitness is =42753.00804487652
iter=16 best fitness is =42751.17802334106
iter=17 best fitness is =42748.01258167695
iter=18 best fitness is =42746.22509580061
iter=19 best fitness is =42743.57316308794
iter=20 best fitness is =42742.260442575454
iter=21 best fitness is =42741.82483808292
iter=22 best fitness is =42738.80326661441
iter=23 best fitness is =42736.25202522932
iter=24 best fitness is =42733.320918717385
iter=25 best fitness is =42731.25727358482
iter=26 best fitness is =42728.007604724946
iter=27 best fitness is =42726.406891353756
iter=28 best fitness is =42723.64438883426
iter=29 best fitness is =42721.315796905874
iter=30 best fitness is =42718.64490574986
iter=31 best fitness is =42716.767293101264
iter=32 best fitness is =42714.54728307373
iter=33 best fitness is =42713.45080389827
iter=34 best fitness is =42711.64333019462

iter=35 best fitness is =42709.50725503373
iter=36 best fitness is =42708.10307075944
iter=37 best fitness is =42707.40691961385
iter=38 best fitness is =42705.34214633038
iter=39 best fitness is =42704.66175678234
iter=40 best fitness is =42703.64852114836
iter=41 best fitness is =42702.31121228729
iter=42 best fitness is =42700.33439530883
iter=43 best fitness is =42698.713593464
iter=44 best fitness is =42697.752620941945
iter=45 best fitness is =42695.54366609986
iter=46 best fitness is =42693.68707677068
iter=47 best fitness is =42691.56348775477
iter=48 best fitness is =42690.37030417116
iter=49 best fitness is =42688.31731561078

摘要

本章介绍了针对哺乳动物的优化问题解决方案,特别是鲸鱼、灰狼和蝙蝠。它涵盖了优化问题和解决方案的基本流程,并提供了相关的流程图、伪代码和用 Java 编写的代码。Rastrigin 基准函数用作所有算法的目标函数。*

三、鸟类:粒子群和布谷鸟搜索优化

本章讨论了鸟类如何利用群体行为来觅食。在这个过程中,他们寻找优化食物搜索的方法。本章简要介绍了这种行为的历史,然后讨论了驱动鸟类搜索行为的算法。

历史:粒子群

物以类聚,人以群分

群体行为是一组实体——动物、鸟类或昆虫——在参与觅食或迁徙等活动时表现出的集体行为。动物或鸟类的群体在特定的方向上同步运动。从一个更抽象的概念来看,群体行为是一种基于自组织原则的自律行为。鸥群没有核心领袖。多是去中心化、自我调节的行为,有一些随意的动作。鸟群示例如图 3-1 所示。

img/507910_1_En_3_Fig1_HTML.jpg

图 3-1

鸟群

正如克雷格·w·雷诺兹在 1987 年的论文中所解释的那样,鸟类遵循三个简单的规则。

  • 避免碰撞:每只鸟都避免与鸟群中的其他鸟发生碰撞。

  • 速度均匀性:所有的鸟保持相同的速度。

  • 羊群对中。所有的鸟都试图向鸟群的中心移动。

在一个鸟群中,每只鸟都有一种本地行为,称为认知成分。还有一种全球行为叫做社会成分。群体的动态是基于个体成员和整个群体先前行为的历史。鸟儿根据自己和群体的经验改变它们的位置和速度。

粒子群优化算法

假设有 N 个粒子。这里的每个粒子代表搜索空间中的一个解。每个粒子都应该有大小为 D 的维度(每个粒子的向量表示,包含了粒子的距离和速度)。目标函数是基于为特定问题指定的标准来定义的。粒子群均匀分布在整个搜索空间中。速度和位置最初是随机分配的。

全局最小值必须位于搜索空间内。这意味着在空间中寻找最佳解决方案。只有一个全局最小值。没有一个粒子知道全局最小值在哪里。他们只知道每个粒子的适应度函数。

粒子以一定的速度移动,这些速度是在每次迭代中随机选择的。这允许他们探索搜索空间并不断更新他们的位置。每只鸟以一定的速度移动时都会改变位置。它试图根据直觉寻找食物,但也会受到群体行为的影响。随着粒子在搜索空间中移动,它们会记住自己的最佳位置和群体的最佳位置,如方程 3-1 所示。这总是影响粒子向那个方向运动,并使它们向那个方向加速。

等式 3-1 首先更新速度( V ,然后更新粒子的位置( P )。

img/507910_1_En_3_Figa_HTML.jpg

方程式 3-1。根据局部最佳和全局最佳位置更新速度

等式 3-1 中的第一个等式是对位置的更新。

等式 3-1 中的第二个等式是每个时间戳的速度更新。它有三个术语。

  • 是当前时间的惯性。

  • 第二项通过从粒子看到的最佳位置中减去当前粒子位置来更新粒子在时间 t +1 的速度。这使得粒子向其最佳位置移动。

  • 第三项使粒子速度的更新向目前所见的全局最佳位置移动。

一旦粒子速度在时间 t +1 发生更新,位置也使用第一方程在时间 t +1 被更新。

第二个方程中也有两个系数:c1r1c2r2。这些系数控制着勘探和开采的程度。利用是粒子瞄准目前为止发现的最佳解的能力。探索则是粒子评估整个研究空间的能力。本文剩余部分的挑战是确定这些系数的影响,以便在勘探和开采之间找到良好的平衡。

粒子群算法流程图

PSO 算法的流程图如图 3-2 所示。该算法初始化群体、迭代次数和其他参数。在每次迭代中,每个粒子的速度和位置都会更新。在每次迭代中,计算每个粒子的适应度,并估计全局和局部最佳值。这一直持续到达到最大迭代次数并获得全局最大值。

img/507910_1_En_3_Fig2_HTML.png

图 3-2

流程图

PSO 伪代码

以下伪代码描述了 PSO 算法,如图 3-2 所示。

For each particle
{
    Initialize particle
}

Do until maximum iterations are done
{
    For each particle
    {
        Calculate Data fitness value
        If the fitness value is better than pBest
        {
            Set pBest = current fitness value
        }
        If pBest is better than gBest
        {
            Set gBest = pBest
        }
    }

    For each particle
    {
        Calculate particle Velocity
        Use gBest and Velocity to update particle Data
    }
}

PSO 先决条件和代码

确保您的计算机上安装了 Java 8 (JDK8 或更高版本)。像 Eclipse 这样的 IDE 是推荐的,但不是必需的,因为您可以使用命令行界面来运行代码,而不需要 IDE。

PSO 算法的代码由两个实用程序类和一个优化器类组成。

  • 点工具类,有三个成员(见清单 3-1 )

    • 双数组

    • 整数数组

    • 整数

  • 优化评估函数的 Rastrigin 实用程序类(参见清单 3-2

  • ParticleSwarmOptimizer 类,算法功能的主要 Java 类(参见清单 3-3 )

Rastrigin 基准函数如公式 3-2 所示。

img/507910_1_En_3_Figb_HTML.jpg

方程式 3-2。 Rastrigin 基准函数

public class Point {
    public double p[];
    public int ip[];
    public int dim;

    public Point(double p[]) {
        this.dim = p.length;
        this.p = p.clone();
    }

    public Point(int p[]) {
        this.dim = p.length;
        this.ip = p.clone();
    }

    public Point(int dim) {
        this.dim = dim;
        p = new double[dim];
    }

    /*
    this method returns the square root of the sum of the square of the members in the array of doubles
    */
    public double norm(){
        double sum = 0;
        for (int i = 0; i < dim ; i ++) {
            sum += Math.pow(this.p[i], 2);
        }
        return Math.sqrt(sum);
    }
    /*
    This method returns the square root of the distance between 2 points. It's calculated by taking sum of the square of the distance between each element of the double array and then doing a square root of it.
    */
    public double dist(Point b){
        double sum = 0;
        for (int i = 0; i < dim ; i ++) {
            sum += Math.pow(this.p[i]-b.p[i], 2);
        }
        return Math.sqrt(sum);
    }
    /*
    This method adds the two Points by taking sum of the individual elements of the double array of each Point
    */

    public static Point add(Point a, Point b) throws Exception {
        if (a.dim != b.dim){
            throw new IllegalArgumentException("Adding points from different dimensions");
        }

        int dim  = a.dim;
        double cp[] = new double[dim];
        for (int i = 0; i < dim; i++){
            cp[i] = a.p[i] + b.p[i];
        }
        return new Point(cp);
    }
    /*
    This method adds the two Points by taking sum of the individual elements of the double array of each Point and then takes an average of each added elements and finally returns a Point with the averages points in the new array
    */

    public static Point mid(Point a, Point b) throws Exception{
        if (a.dim != b.dim){
            throw new IllegalArgumentException("Incompatible points");
        }
        int dim  = a.dim;
        double cor[] = new double[dim];
        for (int i = 0; i < dim; i++){
            cor[i] = (a.p[i] + b.p[i]) / 2.0;
        }
        return new Point (cor);
    }
    /*
     This method multiplies each element of the array of double with the constant a. a is the coefficient we use in the optimization algorithm.
    */
    public Point mull(double a) {
        double p[] = new double[this.dim];
        Point m = new Point(p);
        for (int i = 0; i < this.dim; i++){
            m.p[i] = this.p[i]*a;
        }
        return m;
    }

    /*
    This method returns a string representation of the double array
     */

    @Override
    public String toString() {
        if (p != null) {
            String s = "[";
            for (int i = 0; i < this.dim; i++){
                s += (float)p[i];
                if (i == this.dim - 1) {
                    s += "]";
                } else {
                    s += ",";
                }
            }
            return s;
        } else {
            String s = "[";
            for (int i = 0; i < this.dim; i++){
                s += (int)ip[i];
                if (i == this.dim - 1) {
                    s += "]";
                } else {
                    s += ",";
                }
            }
            return s;
        }
    }

}// Point class ends here.

Listing 3-1The Point Class

接下来是下一个 Java 类,也就是用作基准函数的 Rastrigin 类。

/*
Main class for the Particle Swarm Optimizer

. Goal is to minimize the objective function which is the Rastrigin benchmark function in this case
*/
import java.lang.Math;
import java.util.*;
public class ParticleSwarmOptimizer
{
// declare the variables for iterations, population size and number of dimensions
int popSize;
int iterations;
int dimensions;
// bound variables for upper and lower bounds
double ub=5.12,lb=-5.12;
// array to hold fitness values of the solutions
double fitness[];
// array holding dimension of best solution
double[] bestSolution;
// declare dimensions of each member
double[][] positions;
double[][] positions1;
double[] pBestScore,gBest;
double[][] pBest;
// keep best score as high. We will try and minimize this
double gBestScore=100000000;
int Vmax = 6;
double wMax = 0.9;
double wMin = 0.2;
int c1 = 2;
int c2 = 2;
/*
Constructor for initializing the population
*/
public ParticleSwarmOptimizer(int iterations,int popSize, int dimensions)
{

    this.iterations=iterations;
    this.popSize=popSize;
    this.dimensions=dimensions;
    positions=new double[popSize][dimensions];
    positions1=new double[popSize][dimensions];

    fitness=new double[popSize];
    //initialize solutions

    // local best score
    pBestScore = new double[popSize];

    pBest = new double[popSize][dimensions];
//global best
    gBest = new double[popSize];

    for(int i=0;i<popSize;i++)
    {
        pBestScore[i]=10000000;
    for (int j=0;j<dimensions;j++)
    {
        positions[i][j]=Math.random()*(ub-lb)+lb;
    }
    }
}

//rastrigin function used
private  double fitnessCalculator(double[] candidate)
{

    Point p= new Point(candidate);
    Rastrigin rast=new Rastrigin(10,dimensions);
    //Ackley ack=new Ackley(10,10,10,10);
    return rast.f(p);
}
/*
Optimize function for running the optimization code
*/
private void optimize()
{

    //main loop
    //loop through the population

    for(int it=0;it<iterations;it++){

        //loop over individual
        for(int i=0;i<popSize;i++)
    {
        //calculate the fitness of the individual particle
        fitness[i]=fitnessCalculator(positions[i]);

        if (pBestScore[i] > fitness[i]){
            pBestScore[i] = fitness[i];
                for(int j=0;j<dimensions;j++)
                {
                //update local best solution
           pBest[i][j] = positions[i][j];
                }

        if (gBestScore > fitness[i]){
           gBestScore = fitness[i];
                for(int j=0;j<dimensions;j++)
                {
                //update global best
           gBest[i] = positions[i][j];
                }
            }
         }

    }
       //Update the W of PSO
      double w = wMax - it * ((wMax - wMin) / iterations);
    //loop through population
    for(int i=0;i<popSize;i++)
    {

// loop through each dimension of each particle/bird
        for (int j=0;j<dimensions;j++){
           double r1 = Math.random();
           double r2 = Math.random();
// update positions as per Equation 3-1
           positions1[i][j] = (w * positions1[i][j]+ c1 * r1 * (pBest[i][j] - positions[i][j])+ c2 * r2 * (gBest[i] - positions[i][j]));

           if (positions1[i][j] > Vmax)

                {
             positions1[i][j] = Vmax;
                }

           if (positions1[i][j] < -Vmax)
                {
             positions1[i][j] = -Vmax;
                }
                //update the position of the individual particle
           positions[i][j] = positions[i][j] + positions1[i][j];
            }

    }

    System.out.println("best score after iteration "+it+" ="+gBestScore);
}
}

 /*
Main method to take command line arguments like iterations, population size and number of dimensions
*/
public static void main(String[] args)
{
int iter=Integer.parseInt(args[0]);
int pop=Integer.parseInt(args[1]);
int dim=Integer.parseInt(args[2]);
ParticleSwarmOptimizer pso =new ParticleSwarmOptimizer(iter,pop,dim);
pso.optimize();
}
}

Listing 3-3The PSO Class

    /*
    This class is used as the benchmark function and will be used throughout all algorithms.

     */
public class Rastrigin {

    private double A;
    private double n;

    public Rastrigin(double A, double n) {
        this.A = A;
        this.n = n;
    }

    /*
    This method is the main method for the Rastrigin benchmark function. It takes as input a Point object (explained above) and performs the calculations for the benchmark.
    */

    public double f(Point x) {
        double sum = 0;
        //o = numpy.sum(x ** 2 - 10 * numpy.cos(2 * math.pi * x)) + 10 * dim
        for (int i = 0; i < x.dim; i++) {

            sum += Math.pow(x.p[i], 2) - A*Math.cos(2*Math.PI*x.p[i]);

        }
        return A*n + sum;
    }

}//Rastrigin class ends here

Listing 3-2The Rastrigin Class

执行完整的 PSO 代码

要编译 Java 文件,请使用以下命令。

javac Point.java
javac Rastrigin.java
javac ParticleSwarmOptimizer.java

//running the example with 50 iterations and population size of 10 and 30 dimensions
Command for running the Optimizer class is shown below
java ParticleSwarmOptimizer 50 10 30

以下是运行代码后的输出。

best score after iteration 0 =478.2638626565206
best score after iteration 1 =310.2955850826501
best score after iteration 2 =310.2955850826501
best score after iteration 3 =310.2955850826501
best score after iteration 4 =310.2955850826501
best score after iteration 5 =310.092438291369
best score after iteration 6 =310.092438291369
best score after iteration 7 =310.092438291369
best score after iteration 8 =310.092438291369
best score after iteration 9 =310.092438291369
best score after iteration 10 =306.3686693103556
best score after iteration 11 =306.3686693103556
best score after iteration 12 =306.3686693103556
best score after iteration 13 =286.6539375829212
best score after iteration 14 =286.6539375829212
best score after iteration 15 =233.26582419197734
best score after iteration 16 =233.26582419197734
best score after iteration 17 =233.26582419197734
best score after iteration 18 =233.26582419197734
best score after iteration 19 =233.26582419197734
best score after iteration 20 =233.26582419197734

best score after iteration 21 =206.18491064141006
best score after iteration 22 =206.18491064141006
best score after iteration 23 =206.18491064141006
best score after iteration 24 =206.18491064141006
best score after iteration 25 =203.7517447417162
best score after iteration 26 =203.7517447417162
best score after iteration 27 =203.7517447417162
best score after iteration 28 =203.7517447417162
best score after iteration 29 =203.7517447417162
best score after iteration 30 =203.7517447417162
best score after iteration 31 =203.7517447417162
best score after iteration 32 =203.7517447417162
best score after iteration 33 =203.7517447417162
best score after iteration 34 =203.7517447417162
best score after iteration 35 =203.7517447417162
best score after iteration 36 =203.7517447417162
best score after iteration 37 =190.62736084546805
best score after iteration 38 =190.62736084546805
best score after iteration 39 =190.62736084546805
best score after iteration 40 =190.62736084546805
best score after iteration 41 =190.62736084546805
best score after iteration 42 =190.62736084546805
best score after iteration 43 =190.62736084546805
best score after iteration 44 =190.62736084546805
best score after iteration 45 =190.62736084546805
best score after iteration 46 =190.62736084546805
best score after iteration 47 =190.62736084546805

best score after iteration 48 =190.62736084546805
best score after iteration 49 =190.62736084546805

您已经看到了 PSO 算法是如何工作的。接下来,让我们讨论另一种基于鸟优化的算法,称为布谷鸟搜索

历史:布谷鸟搜索

阿咕!我可以称你为鸟,还是只是一个流浪的声音?

—威廉·华兹华斯

布谷鸟搜索算法是由杨新社和 Suash Deb 于 2009 年提出的一种元启发式优化算法。布谷鸟的两种行为被用于布谷鸟搜索算法中。它基于一种布谷鸟的专性寄生繁殖行为,即在其他鸟类的巢中产卵,以增加其存活率和生产力。它也解释了杜鹃和其他鸟类、动物和昆虫所表现出的笨拙的飞行动作。

幼虫寄生

一些杜鹃物种表现出繁殖寄生行为。孵卵寄生行为包括在其他鸟类的巢中产卵,以便其他鸟类可以孵化杜鹃的蛋。通过进化,布谷鸟产下的蛋在形状和颜色上与宿主鸟的蛋非常相似。这使得布谷鸟欺骗宿主鸟来孵化布谷鸟蛋。雌布谷鸟拜访各种各样的巢来产卵。然而,如果宿主鸟发现了布谷鸟的蛋,它们要么扔掉蛋,要么放弃巢去建一个新的。图 3-3 显示了一个宿主巢,一只布谷鸟的蛋在宿主蛋旁边。

img/507910_1_En_3_Fig3_HTML.jpg

图 3-3

布谷鸟蛋

莱维航班

Lévy flight 是自然过程、科学和社交媒体中的一个数学概念。许多鸟类和昆虫表现出很强的飞行行为。这是一类被称为随机行走的随机过程。它的特点是以 90 度的急转弯打断直线运动。伴随着一点直觉,这种运动允许探索和开发机制被使用。解决方案通常是在当地社区进行探索,急转弯可以让探索发生。图 3-4 展示了李维的飞行行为。

img/507910_1_En_3_Fig4_HTML.jpg

图 3-4

李维函数

它的特点是许多随机的短动作,并由不常见的大动作连接起来。以经常光顾一家喜欢的商店为例,然后探索新的商店并经常光顾它们。Lévy flights 的特征是步长是从“重尾”概率分布中选择的,这意味着更长长度的下降概率不会小到足以压倒增加的长度;从技术上讲,重尾分布具有无限的方差(可能的长度)。

布谷鸟搜索优化算法

在一个简单的公式中,布谷鸟搜索算法具有以下假设

  • 每个宿主巢有一个蛋,每个蛋代表搜索空间中的一个解。

  • 有一个固定数量的宿主巢,这是解决方案的人口。

  • 布谷鸟下一个蛋,这是新的解决方案。布谷鸟随机地用它的蛋替换另一个巢里的蛋。这相当于用新的解决方案取代旧的解决方案。

  • 拥有高质量卵(溶液)的最好的巢会延续到下一代。

  • 发现布谷鸟蛋的概率由 p 表示。在每次迭代中,总巢的一部分被丢弃。这意味着一小部分糟糕的解决方案被扔掉了。

让我们从一组 N 个解开始。

( X 1X 2 ,… X N )代表搜索空间内解的数量。每个解决方案都有 D 尺寸。每次迭代都通过更新现有的解决方案来创建新的解决方案。Lévy 函数执行更新(见公式 3-3 )。

X(t+1)=X(t)+c.L(u)

方程式 3-3。解决方案更新

通过对其应用 Lévy 飞行来更新时间 t 处的解,从而更新时间 t +1 处的解。L(u)是模拟转移概率的 Lévy 分布,从而使下一个位置取决于当前位置和转移概率(见方程 3-4 )。

l(u)= t–u其中 1 < = u < =3

方程式 3-4。李维函数

在这里,您可以看到 Lévy flight 运算符允许通过开发和探索进行搜索。使步长变大允许解决方案探索。保持较小的步长可以更好地利用空间。

在较大的步长下,搜索不会陷入局部最优,并能很快地跳出局部最优。概率参数控制勘探和开采的量。所以,p=.2 意味着 20%的开发和 80%的探索。

CSO 流程图

图 3-5 描绘了布谷鸟搜索算法。它首先初始化群体和其他参数,比如迭代次数。在每次迭代期间,计算每个巢(称为)的适应度。在所有迭代结束时,选择最适合的解决方案。

img/507910_1_En_3_Fig5_HTML.jpg

图 3-5

流程图

CSO 伪代码

下面的伪代码描述了布谷鸟搜索算法,如图 3-5 所示。

Initialize
    Create N nests
    Create 1 solution in each nest. Each solution has D dimensions . Initialize the dimension randomly
    Define number of iterations we should run the process
Iterate
In each iteration
    Generate a new cuckoo solution using Levy flight (Cn)
    Calculate fitness (Fc)
    Choose a random nest j and pick a solution with Fitness Fj
    If (Fc>Fj)
        Replace j by new solution
    End if
    Abandon worst nest with probability p and build new nest (solution)
    Nests are ranked according to fitness
    Nest with best fitness is ranked the current best
Iterate till the max iterations configured
Nest with best fitness is the global best solution

CSO 先决条件和代码

同样,确保您的计算机上安装了 Java 8 (JDK8 或更高版本)。像 Eclipse 这样的 IDE 是推荐的,但不是必需的,因为您可以使用命令行界面来运行代码,而不需要 IDE。

CSO 算法的代码包含以下类。

img/507910_1_En_3_Figc_HTML.jpg

  • Point 是具有三个成员的实用程序类(参见清单 3-4 )。

    • 双份

    • 整数数组

    • 整数

  • Rastrigin 是优化评估函数的实用程序类(参见清单 3-5 )。Rastrigin 基准函数如方程 3-4 所示。

方程式 3-4。 Rastrigin 基准函数

  • CuckooSearchDataHolder 类充当数据容器(参见清单 3-6 )。它保存了最佳解决方案、嵌套数组以及每个嵌套的适应值。

  • CuckooSearchOptimizer 类是主要的 Java 类(参见清单 3-7 )。它通过最小化由 Rastrigin 基准函数表示的目标函数来进行优化。

和上一节一样,我在代码中添加了注释。

/*
This class optimizes by minimizing the objective function

represented by the Rastrigin benchmark function
*/

import java.lang.Math;
import java.util.*;
public class CuckooSearch
{
// declare the iterations, population size and the dimensions variables
int popSize;
int iterations;

int dimensions;
// declare and initialize lower and upper bounds
double ub=5.12,lb=-5.12;
double fitness[];
double[] bestSolution;
//coefficients and constants for the algo
double beta = 1.5;
//discovery rate of alien/egg solution

double pa = 0.25;
double minValueOfSolution;
double leaderDistance;
double[][] positions;
List solutionCurve;

public CuckooSearch(int iterations,int popSize, int dimensions)
{
    solutionCurve=new ArrayList();
    this.iterations=iterations;
    this.popSize=popSize;
    this.dimensions=dimensions;
    positions=new double[popSize][dimensions];

    fitness=new double[popSize];
    //initialize solutions
    for(int i=0;i<popSize;i++)
    {
    for (int j=0;j<dimensions;j++)
    {
        //System.out.println("i="+i+"j="+j);
        positions[i][j]=Math.random()*(ub-lb)+lb;
    }
    }
    for(int i=0;i<popSize;i++)
    {
        //passing high fitness to start with
        fitness[i]=100000;
        System.out.println("fitness for "+i +" solution="+fitness[i]);
    }

}
/*
Sigma function for standard variance
*/
private double doSigma(){
      double term1 = this.logGamma(beta+1)*Math.sin((Math.PI*beta)/2);
      double term2 = this.logGamma((beta+1)/2)*beta*Math.pow(2,(beta-1)/2);
      return Math.pow((term1/term2),(1/beta));
    }
    private Double logGamma(double x){
      double tmp = (x - 0.5) * Math.log(x + 4.5) - (x + 4.5);
      double ser = 1.0 + 76.18009173    / (x + 0)   - 86.50532033    / (x + 1)
                + 24.01409822    / (x + 2)   -  1.231739516   / (x + 3)
                +  0.00120858003 / (x + 4)   -  0.00000536382 / (x + 5);
      return Math.exp(tmp + Math.log(ser * Math.sqrt(2 * Math.PI)));
    }

/*
Replace few nests from the initial population of nests
*/
private double[][] emptyNests(double[][] nest, double pa){

    double[][] tmpPositions=nest.clone();

    int k;
    if(Math.random()>pa)
    {
        k=1;
    }
    else
        k=0;

    for(int i=0;i<popSize;i++)
    {
        double tmp1[]=nest[i].clone();
        double tmp2[]=nest[i].clone();
        Collections.shuffle(Arrays.asList(tmp1));
        Collections.shuffle(Arrays.asList(tmp2));
        for(int j=0;j<dimensions;j++)
    {

    double stepsize =Math.random()*(tmp1[j]-tmp2[j])*k;
    tmpPositions[i][j]=nest[i][j]+stepsize;
    }
    }

    return tmpPositions;

}

/*
Return a nest by performing a levy flight.
*/
private double[][] getCuckooNest(double[][] nest, double[] best){

    // perform Levy flights

    double[][] tmpPositions=nest.clone();

    double beta = 3 / 2;
    double sigma = doSigma();

    double[] s = new double[dimensions];
    System.out.println("lent="+nest.length);

    for (int j =0;j<nest.length;j++)
    {
        s=nest[j].clone();
        Random rnd=new Random();

        double u= rnd.nextGaussian()*sigma ;
        double v = rnd.nextGaussian();
        double step = u / Math.abs(v) * (1 / beta);

      for (int k=0;k<dimensions;k++)
        {
            double x=s[k]- best[k];
            double  stepsize = 0.01 * (step * x);

            double y= stepsize * rnd.nextGaussian();
            s[k]=s[k]+y;
        tmpPositions[j][k] = clipVal(s[k],lb,ub);
        }

    }
    return tmpPositions;

}
/*
Get the best fit nest
*/
private CuckooSearchDataHolder getBestNest(double[][]nest, double[][]newnest, double[]fitness){
    // Evaluating all new solutions
    double[][] tmpPositions=nest.clone();
    for(int j=0;j<popSize;j++)
    {

     double fNew=fitnessCalculator(newnest[j]);

      if (fNew <= fitness[j])
        {
        fitness[j] = fNew;
        tmpPositions[j] = newnest[j];

        }
    }
    // Find the current best

    int bestIndex= indexOfSmallest(fitness);
    bestSolution=tmpPositions[bestIndex];
    minValueOfSolution=smallestInArray(fitness);

    CuckooSearchDataHolder    csdh=new CuckooSearchDataHolder(minValueOfSolution,bestSolution,tmpPositions,fitness);
return csdh;
    }

private double clipVal(double val,double lower,double upper)
{
    double result;
      if (val < lower){
        result = lower;

        }
      else if (val > upper){
        result = upper;

        }
        else
        {
            result=val;

        }
    return result;
}

//rastrigin function used
private  double fitnessCalculator(double[] candidate)
{

    Point p= new Point(candidate);
    Rastrigin rast=new Rastrigin(10,dimensions);
    //Ackley ack=new Ackley(10,10,10,10);
    return rast.f(p);
}
/*
Helper method which finds the smallest member in an array of doubles
*/

private static double smallestInArray(double[] array){

    // add this
    if (array.length == 0)
      return -1;

    int index = 0;
    double min = array[index];

    for (int i = 1; i < array.length; i++){
      if (array[i] <= min){
      min = array[i];
      //index = i;
      }
    }

    return min;
}
/*
Helper method which finds the index of the smallest member in an array of doubles
*/

private static int indexOfSmallest(double[] array){

    // add this
    if (array.length == 0)
      return -1;

    int index = 0;
    double min = array[index];

    for (int i = 1; i < array.length; i++){
      if (array[i] <= min){
      min = array[i];
      index = i;
      }
    }
    return index;
}
/*
Main method for running the Cuckoo Search algorithm
*/

private void optimize()
{
    //main loop
    //bestSolution is initialized

    CuckooSearchDataHolder csdh=getBestNest(positions,positions.clone(),fitness);

    for(int i=0;i<iterations;i++){
        //loop over individual
        // get a nest by performing a Levy flight

    CuckooSearchDataHolder csdh1;
        double[][] newNest=getCuckooNest(csdh.nest,csdh.best);
        // get best nest by evaluating the fitness function
        csdh1=getBestNest(positions,newNest,csdh.fitness);
        // create some new nests and discard some old nests
         newNest = emptyNests(newNest, pa);

        // get best nest by evaluating the fitness function

      csdh1=getBestNest(positions,newNest,csdh1.fitness);

      //fnew, best, nest, fitness = get_best_nest(nest, new_nest, fitness, n, dim, objf)

        if (csdh1.fNew < csdh.fNew)
        {
        csdh.fNew = csdh1.fNew;
            csdh.best = csdh1.best;

        }

        for(int j=0;j<popSize;j++)
        {

        System.out.println("iter="+i+" best fitness is ="+csdh.fNew);
        solutionCurve.add(minValueOfSolution);
    }

}
for (int i=0;i< solutionCurve.size();i++)
        {
            System.out.println("\n"+solutionCurve.get(i));
        }
}
/*
Main method to pass inputs and launch the algorithm
*/
//takes input as number of iterations, population size and dimensions

public static void main(String[] args)
{

int iter=Integer.parseInt(args[0]);
int pop=Integer.parseInt(args[1]);
int dim=Integer.parseInt(args[2]);
CuckooSearch cuckoo =new CuckooSearch(iter,pop,dim);
cuckoo.optimize();
}
}

Listing 3-7The CuckooSearch Class

/*
A data holder class for holding the best solution

, array of nests and the fitness values of each nest.
*/
public class CuckooSearchDataHolder
{
 double fNew;
double[] best;
double[][]nest;
 double[]fitness;
 public CuckooSearchDataHolder(double fNew,double[] best,double[][]nest,double[]fitness)
 {
    this.fNew=fNew;
    this.best=best;
    this.nest=nest;
    this.fitness=fitness;
 }
}

Listing 3-6The CuckooSearchDataHolder Class

    /*
    This class

is used as the benchmark function and will be used throughout all algorithms.

    */
public class Rastrigin {

    private double A;
    private double n;

    public Rastrigin(double A, double n) {
        this.A = A;
        this.n = n;
    }

    /*
    This method is the main method for the Rastrigin benchmark function. It takes as input a Point object (explained above) and performs the calculations for the benchmark.
     */

    public double f(Point x) {
        double sum = 0;
        //o = numpy.sum(x ** 2 - 10 * numpy.cos(2 * math.pi * x)) + 10 * dim
        for (int i = 0; i < x.dim; i++) {

            sum += Math.pow(x.p[i], 2) - A*Math.cos(2*Math.PI*x.p[i]);

        }
        return A*n + sum;
    }

}

Listing 3-5The Rastrigin Class

public class Point {
    public double p[];
    public int ip[];
    public int dim;

    public Point(double p[]) {
        this.dim = p.length;
        this.p = p.clone();
    }

    public Point(int p[]) {
        this.dim = p.length;
        this.ip = p.clone();
    }

    public Point(int dim) {
        this.dim = dim;
        p = new double[dim];
    }

    /*
    this method returns the square root of the sum of the square of the members in the array of doubles
    */
    public double norm(){
        double sum = 0;
        for (int i = 0; i < dim ; i ++) {
            sum += Math.pow(this.p[i], 2);
        }
        return Math.sqrt(sum);
    }
    /*
    This method returns the square root of the distance between 2 points. Its calculated by taking sum of the square of the distance between each element of the double array and then doing a square root of it.
    */
    public double dist(Point b){
        double sum = 0;
        for (int i = 0; i < dim ; i ++) {
            sum += Math.pow(this.p[i]-b.p[i], 2);
        }
        return Math.sqrt(sum);
    }
    /*
    This method adds the two Points by taking sum of the individual elements of the double array of each Point
    */

    public static Point add(Point a, Point b) throws Exception {
        if (a.dim != b.dim){
            throw new IllegalArgumentException("Adding points from different dimensions");
        }
        int dim  = a.dim;
        double cp[] = new double[dim];
        for (int i = 0; i < dim; i++){
            cp[i] = a.p[i] + b.p[i];
        }
        return new Point(cp);
    }

    /*
    This method adds the two Points by taking sum of the individual elements of the double array of each Point and then takes an average of each added elements and finally returns a Point with the averages points in the new array
    */

    public static Point mid(Point a, Point b) throws Exception{
        if (a.dim != b.dim){
            throw new IllegalArgumentException("Incompatible points");
        }
        int dim  = a.dim;
        double cor[] = new double[dim];
        for (int i = 0; i < dim; i++){
            cor[i] = (a.p[i] + b.p[i]) / 2.0;
        }
        return new Point (cor);
    }
    /*
    This method multiplies each element of the array of double with the constant a. a is the coefficient we use in the optimization algorithm.
    */
    public Point mull(double a) {
        double p[] = new double[this.dim];
        Point m = new Point(p);
        for (int i = 0; i < this.dim; i++){
            m.p[i] = this.p[i]*a;
        }
        return m;
    }

    /*
    This method returns a string representation of the double array
    */

    @Override
    public String toString() {
        if (p != null) {
            String s = "[";
            for (int i = 0; i < this.dim; i++){
                s += (float)p[i];
                if (i == this.dim - 1) {
                    s += "]";
                } else {
                    s += ",";
                }
            }
            return s;
        } else {
            String s = "[";
            for (int i = 0; i < this.dim; i++){
                s += (int)ip[i];
                if (i == this.dim - 1) {
                    s += "]";
                } else {
                    s += ",";
                }
            }
            return s;
        }
    }
}

Listing 3-4The Point Class

执行代码

要编译 Java 文件,请使用以下命令。

javac Point.java
javac Rastrigin.java
javac CuckooSearchDataHolder.java
javac CuckooSearch.java

//running the example with 50 iterations and population size of 10 and 30 dimensions
java CuckooSearch 50 10 30

输出

以下是运行代码后的输出。

iter=0 best fitness is =465.6496390625076
iter=1 best fitness is =465.6496390625076
iter=2 best fitness is =465.6496390625076
iter=3 best fitness is =465.6496390625076
iter=4 best fitness is =465.6496390625076
iter=5 best fitness is =465.6496390625076
iter=6 best fitness is =465.6496390625076

最佳适应度是 1000 度。36860.88888888667

iter=8 best fitness is =465.6496390625076
iter=9 best fitness is =465.6496390625076
iter=10 best fitness is =465.6496390625076
iter=11 best fitness is =465.6496390625076
iter=12 best fitness is =465.6496390625076
iter=13 best fitness is =465.6496390625076
iter=14 best fitness is =465.6496390625076
iter=15 best fitness is =465.6496390625076
iter=16 best fitness is =465.6496390625076
iter=17 best fitness is =465.6496390625076
iter=18 best fitness is =465.6496390625076
iter=19 best fitness is =465.6496390625076
iter=20 best fitness is =465.6496390625076
iter=21 best fitness is =465.6496390625076
iter=22 best fitness is =465.6496390625076
iter=23 best fitness is =465.6496390625076
iter=24 best fitness is =465.6496390625076
iter=25 best fitness is =465.6496390625076
iter=26 best fitness is =465.6496390625076
iter=27 best fitness is =465.6496390625076
iter=28 best fitness is =465.6496390625076
iter=29 best fitness is =465.6496390625076
iter=30 best fitness is =465.6496390625076
iter=31 best fitness is =465.6496390625076
iter=32 best fitness is =465.6496390625076

iter=33 best fitness is =465.6496390625076
iter=34 best fitness is =465.6496390625076
iter=35 best fitness is =465.6496390625076
iter=36 best fitness is =465.6496390625076
iter=37 best fitness is =464.14178857501577
iter=38 best fitness is =464.14178857501577
iter=39 best fitness is =464.14178857501577
iter=40 best fitness is =464.14178857501577
iter=41 best fitness is =464.14178857501577
iter=42 best fitness is =464.14178857501577
iter=43 best fitness is =464.14178857501577
iter=44 best fitness is =464.14178857501577
iter=45 best fitness is =458.7217674665756
iter=46 best fitness is =443.12284759917725
iter=47 best fitness is =443.12284759917725
iter=48 best fitness is =443.12284759917725
iter=49 best fitness is =443.12284759917725

摘要

本章介绍了针对一类鸟类的优化问题解决方案,特别是粒子群优化和布谷鸟搜索优化。它涵盖了优化问题和解决方案的基本流程,并提供了流程图、伪代码和用 Java 编写的代码。Rastrigin 基准函数被用作算法中的目标函数。

四、昆虫:萤火虫优化

草原上的萤火虫在跳动着来来去去。

—詹姆斯·罗素洛厄尔

本章向你介绍用萤火虫解决最优化问题。你将了解萤火虫如何根据周围光线的强度发展出特定的闪光技术。萤火虫算法是一种元启发式算法,其中搜索空间是基于探索和利用。

历史

萤火虫是甲虫目鞘翅目中属于萤科的昆虫。它们有时俗称为闪电虫。大多数物种是夜间活动的,白天藏在树叶下或裂缝中。它们很小,长度为 4 到 9 毫米,平均重量为 3 到 6 毫克。萤火虫生活在潮湿的地方——树下、腐烂的木头里、石头下、树皮下,以及树木和灌木的接合处之间。大多数物种没有侵略性或领地意识,已经适应了彼此邻近生活。

萤火虫在黄昏和夜晚表现出闪光的行为。它们有节奏地晃动腹部,持续时间约为一秒,模式为五到十秒。闪光是萤火虫交配过程中的重要组成部分;它允许雄性给雌性发信号。

在野外有很长的观察闪电虫的历史。许多古代文化将萤火虫称为“夜之精灵”

这两种行为激发了萤火虫优化。

  • 遮雨板

  • 莱维航班

Lévy flight 是在第三章中讨论的随机漫步。

算法

萤火虫算法的工作有三个基本假设。

  • 所有萤火虫都是雌雄同体的,这意味着任何一只萤火虫都可以被其他任何一只萤火虫吸引,这取决于相应萤火虫的闪光亮度。

  • 个体萤火虫的亮度是由其适应度函数决定的。

  • 萤火虫的吸引力取决于它发出的光的强度。一只萤火虫总是向更吸引人的萤火虫移动。如果没有其他吸引人的(明亮的)萤火虫,那么它只是随机移动。萤火虫之间的距离越大,吸引力越小。

由于光的强度与距光源距离的平方成反比,等式 4-1 定义了吸引力。

B(r)=B(0)e -gr2

方程式 4-1。定义吸引力

距离 r ,(B(r))处的吸引力由 B(0))处的吸引力决定。如果位于Xj的萤火虫比位于 X i 的萤火虫更有吸引力,那么位于 X i 的萤火虫就向 X j 移动。

萤火虫在XIT5 的位置更新由等式 4-2 描述。

img/507910_1_En_4_Figa_HTML.png

等式 4-2 萤火虫位置更新

等式的右边对于位置 X 的萤火虫有三个部分。

  • 萤火虫在迭代 t 时的位置。

  • 萤火虫在地点 j 的吸引力。

  • Alpha 是一个随机项,而 epsilon 是从高斯、均匀或李维分布中抽取的随机数。

流程图

本节描述 firefly 优化算法。在高层次上,它涉及初始化参数,如萤火虫数量或迭代次数(见图 4-1 )。萤火虫的位置在每次迭代中根据其他萤火虫发出的光的强度进行更新,并计算它们的适应度。在最后一次迭代结束时,选择最佳的解决方案。

img/507910_1_En_4_Fig1_HTML.png

图 4-1

萤火虫优化算法的流程图

伪代码

下面的伪代码描述了 firefly 优化算法,如图 4-1 所示。

Initialize
    Initialize the population of fireflies
    Randomly assign a location to each firefly
    Define the fitness function (its same as the intensity of light emitted)
Iterate
    Loop over the population of fireflies (for i=1 to N)
        Start another loop of fireflies (for j=1 to N)
        Calculate fitness f(i) and f(j)
        If (f(i)>f(j))
        Move firefly j towards firefly i
        endif
        Update intensity of fireflies as they take new positions
        End inner for loop
    End outer for loop
    Rank the fireflies as per their fitness values
    Keep iterating till max value of iterations is reached
Firefly with max fitness is the global optima.

先决条件和代码

确保您的计算机上安装了 Java 8 (JDK8 或更高版本)。像 Eclipse 这样的 IDE 是推荐的,但不是必需的,因为您可以使用命令行界面来运行代码,而不需要 IDE。

firefly 算法的代码由以下类组成。

  • 点工具类,有三个成员(见清单 4-1

    • 双数组

    • 整数数组

    • 整数

  • 优化评估函数的 Rastrigin 实用程序类(参见清单 4-2

  • 实用函数的 ArrayUtils 类(参见清单 4-3

  • FireflyOptimizer 优化类,算法功能的主要 Java 类(参见清单 4-4 )

firefly 算法的 Rastrigin 基准函数如公式 4-3 所示。

img/507910_1_En_4_Figb_HTML.jpg

方程式 4-3。 Rastrigin 基准函数

import java.util.Arrays;
import java.util.Comparator;
import java.util.Random;

public final class ArrayUtils {
    public static int[] argsort(final double[] a) {
        return argsort(a, true);
    }
/*
Arg sort method . This returns indices which would sort the array
*/
    public static int[] argsort(final double[] a, final boolean ascending) {
        Integer[] indexes = new Integer[a.length];
        for (int i = 0; i < indexes.length; i++) {
            indexes[i] = i;
        }
        Arrays.sort(indexes, new Comparator<Integer>() {
            @Override
            public int compare(final Integer i1, final Integer i2) {
                return (ascending ? 1 : -1) * Double.compare(a[i1], a[i2]);
            }
        });
        return asArray(indexes);
    }

    public static <T extends Number> int[] asArray(final T... a) {
        int[] b = new int[a.length];
        for (int i = 0; i < b.length; i++) {
            b[i] = a[i].intValue();
        }
        return b;
    }

    public static double[] castOf(final double[] x) {
        double[] y = new double[x.length];
        for (int i = 0; i < y.length; i++) {
            y[i] = x[i];
        }
        return y;
    }

    public static int[] castOf(final long[] original) {
        return castOf(original, original.length);
    }

    public static int[] castOf(final long[] original, final int newLength) {
        int[] cast = new int[newLength];
        int length = Math.min(cast.length, original.length);
        for (int i = 0; i < length; i++) {
            long o = original[i];
            if (o < Integer.MIN_VALUE || o > Integer.MAX_VALUE) {
                throw new IllegalArgumentException();
            }
            cast[i] = (int) o;
        }

        return cast;
    }

/*
Copies the array  upto the length specified.
*/
    public static double[][] copyOf(final double[][] x, final int newLength) {
        double[][] y = new double[newLength][];
        for (int i = 0; i < y.length; i++) {
            if (x[i] != null) {
                y[i] = Arrays.copyOf(x[i], x[i].length);
            }
        }
        return y;
    }

    /**
    * Assigns a random value to each element of the specified array of doubles.
    */
    public static void fillRandom(final double[] x, final Random rng) {
        for (int i = 0; i < x.length; i++) {
            x[i] = rng.nextDouble();
        }
    }

    private ArrayUtils() {
    }
}//end of ArrayUtils class

Listing 4-3The ArrayUtils Utility Class

    /*
    This class is used as the benchmark function and will be used throughout all algorithms.

    */

public class Rastrigin {

    private double A;
    private double n;

    public Rastrigin(double A, double n) {
        this.A = A;
        this.n = n;
    }

    /*
    This method is the main method for the Rastrigin benchmark function. It takes as input a Point object (explained above) and performs the calculations for the benchmark.
     */

    public double f(Point x) {
        double sum = 0;
        //o = numpy.sum(x ** 2 - 10 * numpy.cos(2 * math.pi * x)) + 10 * dim
        for (int i = 0; i < x.dim; i++) {

            sum += Math.pow(x.p[i], 2) - A*Math.cos(2*Math.PI*x.p[i]);

        }
        return A*n + sum;
    }

}//end of Rastrigin class

Listing 4-2The Rastrigin Benchmark Function Class

public class Point {
    public double p[];
    public int ip[];
    public int dim;

    public Point(double p[]) {
        this.dim = p.length;
        this.p = p.clone();
    }

    public Point(int p[]) {
        this.dim = p.length;
        this.ip = p.clone();
    }

    public Point(int dim) {
        this.dim = dim;
        p = new double[dim];
    }
    /*
    this method returns the square root of the sum of the square of the members in the array of doubles
    */
    public double norm(){
        double sum = 0;
        for (int i = 0; i < dim ; i ++) {
            sum += Math.pow(this.p[i], 2);
        }
        return Math.sqrt(sum);
    }

    /*
     This method returns the square root of the distance between 2 points. It's calculated by taking sum of the square of the distance between each element of the double array and then doing a square root of it.
    */
    public double dist(Point b){
        double sum = 0;
        for (int i = 0; i < dim ; i ++) {
            sum += Math.pow(this.p[i]-b.p[i], 2);
        }
        return Math.sqrt(sum);
    }
    /*
    This method adds the two Points by taking sum of the individual elements of the double array of each Point
    */

    public static Point add(Point a, Point b) throws Exception {
        if (a.dim != b.dim){
            throw new IllegalArgumentException("Adding points from different dimensions");
        }
        int dim  = a.dim;
        double cp[] = new double[dim];
        for (int i = 0; i < dim; i++){
            cp[i] = a.p[i] + b.p[i];
        }
        return new Point(cp);
    }
    /*
    This method adds the two Points by taking sum of the individual elements of the double array of each Point and then takes an average of each added elements and finally returns a Point with the averages points in the new array
    */

    public static Point mid(Point a, Point b) throws Exception{
        if (a.dim != b.dim){
            throw new IllegalArgumentException("Incompatible points");
        }

        int dim  = a.dim;
        double cor[] = new double[dim];
        for (int i = 0; i < dim; i++){
            cor[i] = (a.p[i] + b.p[i]) / 2.0;
        }
        return new Point (cor);
    }
    /*
    This method multiplies each element of the array of double with the constant a. a is the coefficient we use in the optimization algorithm.
    */
    public Point mull(double a) {
        double p[] = new double[this.dim];
        Point m = new Point(p);
        for (int i = 0; i < this.dim; i++){
            m.p[i] = this.p[i]*a;
        }
        return m;
    }
    /*
     This method returns a string representation of the double array
    */

    @Override
    public String toString() {
        if (p != null) {
            String s = "[";
            for (int i = 0; i < this.dim; i++){
                s += (float)p[i];
                if (i == this.dim - 1) {
                    s += "]";
                } else {
                    s += ",";
                }
            }

            return s;
        } else {
            String s = "[";
            for (int i = 0; i < this.dim; i++){
                s += (int)ip[i];
                if (i == this.dim - 1) {
                    s += "]";
                } else {
                    s += ",";
                }
            }
            return s;
        }
    }

}// end of Point class

Listing 4-1The Point Class

清单 4-4 中的 FireflyOptimizer 类是优化器功能的主要类。它使用其他类,如 Point、Rastrigin 和 ArrayUtils。

import java.lang.Math;
import java.util.*;
public class FireFlyOptimizer
{
// declare the number of iterations, population size and dimensions
int popSize;
int iterations;
int dimensions;
// declare the bounds for upper and lower values
double ub=5.12,lb=-5.12;
double fitness[];
double[] bestSolution;
// declare variables for coefficients and constants
double alpha = 0.5 ; // Randomness 0--1 (highly random)
double betamin = 0.20 ; // minimum value of beta
double gamma = 1  ;// Absorption coefficient
double minValueOfSolution;
double[][] positions;
double[][] positions1;
int[] sortedIndex;

public FireFlyOptimizer(int iterations,int popSize, int dimensions)
{
    // initialize the population
    this.iterations=iterations;
    this.popSize=popSize;
    this.dimensions=dimensions;
    positions=new double[popSize][dimensions];

    positions1=new double[popSize][dimensions];
    fitness=new double[popSize];
    //initialize solutions

    for(int i=0;i<popSize;i++)
    {
    for (int j=0;j<dimensions;j++)
    {

        positions[i][j]=Math.random()*(ub-lb)+lb;

        positions[i][j]=clipVal(positions[i][j],lb,ub);
    }
    }

}
/*
Method to Clip the values between lower and upper bounds
*/
private double clipVal(double val,double lower,double upper)
{
    double result;
      if (val < lower){
        result = lower;

        }
      else if (val > upper){
        result = upper;

        }
        else
        {
            result=val;

        }
    return result;
}
//rastrigin function used
private  double fitnessCalculator(double[] candidate)
{

    Point p= new Point(candidate);
    Rastrigin rast=new Rastrigin(10,dimensions);
    //Ackley ack=new Ackley(10,10,10,10);
    return rast.f(p);
}
/*
Helper method which finds the index of the smallest member in an array of doubles
*/

private static int indexOfSmallest(double[] array){

    // add this

    if (array.length == 0)
        return -1;

    int index = 0;
    double min = array[index];

    for (int i = 1; i < array.length; i++){
        if (array[i] <= min){
        min = array[i];
        index = i;
        }
    }
    return index;
}
/*
Method to update firefly positions based on fitness
*/
private void updateFireFlies(int iterations)
{

        double alpha1=getAlpha(alpha,iterations);
      double[] scale = new double[dimensions];

        double[] fireflies=new double[popSize];
        //loop through all fireflies
        for(int i=0;i<popSize;i++)
        {
        // inner loop for fireflies
            for(int j=0;j<popSize;j++)
        {
            double sum=0;
            double r=0;
            for(int k=0;k<dimensions;k++)
            {
                double diff=positions[i][k]-positions[j][k];
                sum=sum+diff;
                r=Math.pow(sum,2);

            }

        // if fitness of ith firefly  greater then jth firefly
            if(fitness[i]>fitness[j])
            {
                double beta0 = 1;
             double beta = (beta0 - betamin) * Math.exp(-gamma * Math.pow(r , 2)) + betamin;

                  double tmpf[]=new double[dimensions];

                    for(int k=0;k<dimensions;k++)
            {
                    tmpf[k] = alpha1 * (Math.random()*dimensions - 0.5) * scale[k];
//keep updating the position of the firefly
positions[i][k] = positions[i][k]* (1 - beta) + positions1[j][k] * beta + tmpf[k];

            }
            }

        }
        }

}

/*
Method for reducing alpha value
*/
private double  getAlpha(double alpha, int gen){

    double  delta = 1 - Math.pow((Math.pow(10,-4) / 0.9) , (1 / gen));
    alpha = (1 - delta) * alpha;
    return alpha;
}

/*
Method for optimizing
*/

private void optimize()
{
    //main loop for starting the iterations
    for(int it=0;it<iterations;it++){
        //loop over individual  firefly

        for(int i=0;i<popSize;i++)
    {
        // calculate the fitness of the firefly based on position
        fitness[i]=fitnessCalculator(positions[i]);

    }
    int bestIndex= indexOfSmallest(fitness);

    bestSolution=positions[bestIndex];

    minValueOfSolution=fitness[bestIndex];
    System.out.println("best solution at iteration "+it+"="+minValueOfSolution);
    sortedIndex=ArrayUtils.argsort(fitness,true);

    for(int x=0;x<sortedIndex.length;x++)
    {
        for(int y=0;y<dimensions;y++)
        {
            int p=sortedIndex[x];
            positions1[p][y]=positions[p][y];
        }

    }
        // update the firefly positions based on existing positions
        updateFireFlies(iterations);

}

}

/*
Main method to pass inputs and launch the algorithm
*/

public static void main(String[] args)
{
//takes input as number of iterations, population size and dimensions

int iter=Integer.parseInt(args[0]);
int pop=Integer.parseInt(args[1]);
int dim=Integer.parseInt(args[2]);
FireFlyOptimizer firefly =new FireFlyOptimizer(iter,pop,dim);
firefly.optimize();
}
}

Listing 4-4The FireflyOptimizer Class

执行代码

让我们编译源代码并执行它。以下是编译 Java 文件的命令。

javac Point.java
javac Rastrigin.java
javac ArrayUtils.java
javac FireFlyOptimizer.java

//running the example with 50 iterations and population size of 10 and 30 dimensions
The following command is used for running the code.
java FireFlyOptimizer 50 10 30

输出

执行代码后,您会看到以下结果。

best solution at iteration 0=531.4740994175238
best solution at iteration 1=305.28766121650875
best solution at iteration 2=286.9754494150518
best solution at iteration 3=262.68691724344035
best solution at iteration 4=262.5778766205223
best solution at iteration 5=262.5778766205223
best solution at iteration 6=262.53064502982664
best solution at iteration 7=262.53064502982664
best solution at iteration 8=262.53064502982664
best solution at iteration 9=262.53064502982664
best solution at iteration 10=262.53064502982664
best solution at iteration 11=262.53064502982664
best solution at iteration 12=262.53064502982664
best solution at iteration 13=262.53064502982664
best solution at iteration 14=262.53064502982664
best solution at iteration 15=262.53064502982664
best solution at iteration 16=262.53064502982664
best solution at iteration 17=262.53064502982664
best solution at iteration 18=262.53064502982664
best solution at iteration 19=262.53064502982664
best solution at iteration 20=262.53064502982664
best solution at iteration 21=262.53064502982664
best solution at iteration 22=262.53064502982664
best solution at iteration 23=262.53064502982664
best solution at iteration 24=262.53064502982664
best solution at iteration 25=262.53064502982664
best solution at iteration 26=262.53064502982664
best solution at iteration 27=262.53064502982664
best solution at iteration 28=262.53064502982664
best solution at iteration 29=262.53064502982664

best solution at iteration 30=262.53064502982664
best solution at iteration 31=262.53064502982664
best solution at iteration 32=262.53064502982664
best solution at iteration 33=262.53064502982664
best solution at iteration 34=262.53064502982664
best solution at iteration 35=262.53064502982664
best solution at iteration 36=262.53064502982664
best solution at iteration 37=262.53064502982664
best solution at iteration 38=262.53064502982664
best solution at iteration 39=262.53064502982664
best solution at iteration 40=262.53064502982664
best solution at iteration 41=262.53064502982664
best solution at iteration 42=262.53064502982664
best solution at iteration 43=262.53064502982664
best solution at iteration 44=262.53064502982664
best solution at iteration 45=262.53064502982664
best solution at iteration 46=262.53064502982664
best solution at iteration 47=262.53064502982664
best solution at iteration 48=262.53064502982664
best solution at iteration 49=262.53064502982664

摘要

本章介绍了针对萤火虫及其闪烁行为的优化问题解决方案。它涵盖了优化问题和解决方案的基本流程,并给出了相应的流程图、伪代码和用 Java 编写的代码。Rastrigin 基准函数被用作算法中的目标函数。

五、海洋生物:Salp 群优化

本章向您介绍 salp 群优化方法,这是另一种元启发式技术。优属于生活在海底的一类动物。

历史

Salps 属于 Salpidae 家族。它们有一个透明的桶形身体,它们的组织与水母高度相似。它们像水母一样移动,因为水是通过身体向前推进的。

关于这些生物的生物学研究正处于早期阶段,主要是因为它们的生活环境极难进入,很难将它们保持在实验室环境中。

萨尔普斯最有趣的行为之一是成群结队。在深海中,salp 经常形成一个群体,称为 salp 链。这种行为的主要原因尚不清楚,但一些研究人员认为,这是为了通过快速协调变化和觅食来实现更好的运动。

Salp 链主要分为两部分。

  • 链中的第一个 salp 是领导者

  • 链条中的所有其他 salps 都是跟随者

Salp 群算法

salp 群算法(SSA)基于 salp 的群体行为。这种算法技术通常比其他群算法具有更好的性能。SSA 是一种随机算法。在优化过程开始时,通过创建一组随机解来形成初始群体。这些解决方案随着时间的推移分两个阶段进行改进,即勘探和开发。在探索阶段,探索搜索空间。在剥削中,邻里被剥削。该算法将探索和开发结合起来,避免了陷入局部最优。

领导者的位置在等式 5-1 中更新。

img/507910_1_En_5_Figa_HTML.jpg

方程式 5-1。【salp 群的位置更新

Xj1F j 分别表示 j 维中首领和馈源的位置。ubjlbj表示 j 维的上(上)界和下(下)界。c2 和c3 是来自封闭区间[0,1]的两个随机浮点数。

系数 c 1 ,SSA 中最有效的参数,在整个迭代过程中逐渐减小,以平衡勘探和开采,如方程 5-2 中所定义。

c1= 2e(4l L)(功率)2

方程式 5-2。系数 c1T5计算

L 和 L 分别表示当前迭代和最大迭代次数。等式 5-3 更新从动轮的位置。

img/507910_1_En_5_Figb_HTML.png

方程式 5-3。跟随者位置更新

流程图

图 5-1 是 salp 群优化算法的流程图。在高层次上,这个流程图从初始化参数开始,比如迭代次数和群体大小。在每次迭代中,领导者和跟随者的位置被更新,并且每个 salp 的适应度被计算。最大迭代次数后,返回最合适的解。

img/507910_1_En_5_Fig1_HTML.png

图 5-1

salp 群优化流程图

伪代码

以下伪代码描述了 salp 群优化算法,如图 5-1 所示。

Initialize the population of salps (i = 1, 2, .., n) considering lower and upper bounds
    while (max iterations are not done)
    Calculate the fitness value of each salp
    Set F as the best salp
    Update the parameter c, using Eq (5.2)
        for salp
            f(i==1)
                Update the position of leader salp by Eq (5.1)
            else
                Update the position of follower salps by Eq (5.3)
            end
        end
    Update the position of salps considering lower and upper limits of variables end
return F

先决条件和代码

确保您的计算机上安装了 Java 8 (JDK8 或更高版本)。像 Eclipse 这样的 IDE 是推荐的,但不是必需的,因为您可以使用命令行界面来运行代码,而不需要 IDE。

salp swarm optimizer 算法的代码包含以下类。

img/507910_1_En_5_Figc_HTML.jpg

  • Point 是具有三个成员的实用程序类(参见清单 5-1 )。

    • 双数组

    • 整数数组

    • 整数

  • Rastrigin 是优化评估函数的实用程序类(参见清单 5-2 )。拉斯特里金方程如方程 5-4 所示。

  • SalpSwarmOptimizer 是主要的优化器类(参见清单 5-3 )。目标函数是基准函数(本例中为 Rastrigin)的最小化。

方程式 5-4。 Rastrigin 基准函数

每个清单都包含详细的注释,以便更准确地描述代码的特定部分。

/*
This class is the main optimizer class . Our objective function is the minimization of the benchmark function (Rastrigin in this case)
*/

import java.lang.Math;
import java.util.*;
public class SalpSwarmOptimizer
{
// declare variables for population size, number of iterations, dimensions and bounds.

int popSize;
int iterations;

int dimensions;
//declaration of bounds
double ub=5.12,lb=-5.12;
//array for holding the fitness values

double fitness[];
double[] bestSolution;

double minValueOfSolution;
double[][] positions;

public SalpSwarmOptimizer(int iterations,int popSize, int dimensions)
{
    this.iterations=iterations;
    this.popSize=popSize;
    this.dimensions=dimensions;
    positions=new double[popSize][dimensions];
    fitness=new double[popSize];
    //initialize solutions

    for(int i=0;i<popSize;i++)
    {
    for (int j=0;j<dimensions;j++)
    {

        double rnd=Math.random();

        positions[i][j]=rnd*(ub-lb)+lb;
    }
    }

    for(int i=0;i<popSize;i++)
    {
        fitness[i]=fitnessCalculator(positions[i]);

    }
    int bestIndex= indexOfSmallest(fitness);

    bestSolution=positions[bestIndex];

    minValueOfSolution=fitness[bestIndex];

}

//rastrigin function used
private  double fitnessCalculator(double[] candidate)
{

    Point p= new Point(candidate);
    Rastrigin rast=new Rastrigin(10,dimensions);
    return rast.f(p);

}
/*
Helper method which finds the index of the smallest member in an array of doubles
*/

private static int indexOfSmallest(double[] array){

    // add this
    if (array.length == 0)
        return -1;

    int index = 0;
    double min = array[index];

    for (int i = 1; i < array.length; i++){
        if (array[i] <= min){
        min = array[i];
        index = i;
        }
    }

    return index;
}
/*
Helper method to do a matrix transpose
*/

private double[][] transpose(double[][] original ,int rows, int columns)
{

     double[][] transpose=new double[rows][columns];
     for(int i=0;i<rows;i++){
for(int j=0;j<columns;j++){

transpose[i][j]=original[j][i];
}
}
return transpose;
}
/*
Helper method to return rows for a specific column of the matrix
*/

private double[] getRows(double[][] arr,int colIndex)
{
    double[] result=new double[arr.length]; //size is number of rows

    for(int i=0;i<arr.length;i++)
    {

        for (int col = 0; col < arr[i].length; col++) {

        if(col==colIndex)
        {

        result[i]=arr[i][col];
        }

        }
    }
    return result;
}
/*
Helper method which adds element of two dimensional each array and returns a two dimensional array
*/

private  double[][] addElementwise(double[] a, double[] b,double[][] positions,int dim, int pop) throws ArithmeticException {

        if (a.length != b.length) {
            throw new ArithmeticException();
        } else {

            for (int i = 0; i < a.length; i++) {
                positions[dim][pop] = ((a[i] + b[i])/2);
            }
            return positions;
        }

    }

/*
Method for running the iterations and optimizer code
*/

private void optimize()
{
    //main loop

    for(int i=0;i<iterations;i++){

        double c1 = 2 * Math.exp(-(Math.pow(4 * i / iterations,2)));
        //loop over individual moth
        for(int j=0;j<popSize;j++)
        {
            // perform a matrix transform
            positions =transpose(positions,dimensions,popSize);

            if (j < popSize/2)
            {
             for (int k=0;k<dimensions;k++)

                {
                double c2 = Math.random();
                double c3 = Math.random();
        // update the position at kth row and jth column based on value of c1 and c2
                if (c3 < 0.5)
                {
                    positions[k][j] = bestSolution[k] + c1 * ((ub - lb) * c2 + lb);

                    }
                else
                    {
                    positions[k][j] = bestSolution[k] - c1 * ((ub - lb) * c2 + lb);

                    }
                }
            }

            else if ((j >= popSize / 2) && (j < popSize + 1)){
                double[] point1= getRows(positions,j-1);

             double[] point2 = getRows(positions,j);

                  for (int k=0;k<dimensions;k++)
                {
                positions=addElementwise(point1,point2,positions,k,j);

                }

        }
        // transpose the matrix back for next iteration
        positions = transpose(positions,popSize,dimensions);

        }

        for(int j=0;j<popSize;j++)
        {

            positions[j]=simpleBounds(positions[j],lb,ub);

            // calculate fitness of each salp swarm
          double fNew = fitnessCalculator(positions[j]);

             // Update the current best solution
          if (fNew < minValueOfSolution)
            {
             bestSolution =positions[j].clone();
             minValueOfSolution = fNew;

            }

        }
        System.out.println("minimum value at iterartion "+i+"="+minValueOfSolution);

    }

}
/*
Method for bounding the value between lower and upper bounds
*/
private double[] simpleBounds(double[] val, double lower, double upper){
    double[] result = new double[val.length];
    for (int i = 0; i < val.length; i++) {

       if (val[i] < lower){
          result[i] = lower;

        }
       else if (val[i] > upper){
          result[i] = upper;

        }
        else
        {
            result[i]=val[i];

        }

    }

       return result;
}
/*
Main method to pass inputs and launch the algorithm
*/

public static void main(String[] args)
{
//takes input as number of iterations, population size and dimensions

int iter=Integer.parseInt(args[0]);
int pop=Integer.parseInt(args[1]);
int dim=Integer.parseInt(args[2]);
SalpSwarmOptimizer swarm =new SalpSwarmOptimizer(iter,pop,dim);
swarm.optimize();
}

}

Listing 5-3The SalpSwarmOptimizer Class

    /*
    This class is used as the benchmark function and will be used throughout all algorithms.

    */

public class Rastrigin {

    private double A;
    private double n;

    public Rastrigin(double A, double n) {
       this.A = A;
       this.n = n;
    }

    /*
    This method is the main method for the Rastrigin benchmark function. It takes as input a Point object (explained above) and performs the calculations for the benchmark.
    */

    public double f(Point x) {
       double sum = 0;
       //o = numpy.sum(x ** 2 - 10 * numpy.cos(2 * math.pi * x)) + 10 * dim
       for (int i = 0; i < x.dim; i++) {

          sum += Math.pow(x.p[i], 2) - A*Math.cos(2*Math.PI*x.p[i]);

       }

       return A*n + sum;
    }

}

Listing 5-2The Rastrigin Class

public class Point {
    public double p[];
    public int ip[];
    public int dim;

    public Point(double p[]) {
       this.dim = p.length;
       this.p = p.clone();
    }

    public Point(int p[]) {
       this.dim = p.length;
       this.ip = p.clone();
    }

    public Point(int dim) {
       this.dim = dim;
       p = new double[dim];
    }
    /*
    this method returns the square root of the sum of the square of the members in the array of doubles
    */
    public double norm(){
       double sum = 0;
       for (int i = 0; i < dim ; i ++) {
          sum += Math.pow(this.p[i], 2);
       }
       return Math.sqrt(sum);
    }

    /*
    This method returns the square root of the distance between 2 points. Its calculated by taking sum of the square of the distance between each element of the double array and then doing a square root of it.
    */
    public double dist(Point b){
       double sum = 0;
       for (int i = 0; i < dim ; i ++) {
          sum += Math.pow(this.p[i]-b.p[i], 2);
       }
       return Math.sqrt(sum);
    }
    /*
    This method adds the two Points by taking sum of the individual elements of the double array of each Point
    */

    public static Point add(Point a, Point b) throws Exception {
       if (a.dim != b.dim){
          throw new IllegalArgumentException("Adding points from different dimensions");
       }
       int dim  = a.dim;
       double cp[] = new double[dim];
       for (int i = 0; i < dim; i++){
          cp[i] = a.p[i] + b.p[i];
       }
       return new Point(cp);
    }
    /*
    This method adds the two Points by taking sum of the individual elements of the double array of each Point and then takes an average of each added elements and finally returns a Point with the averages points in the new array
    */

    public static Point mid(Point a, Point b) throws Exception{
       if (a.dim != b.dim){
          throw new IllegalArgumentException("Incompatible points");
       }

       int dim  = a.dim;
       double cor[] = new double[dim];
       for (int i = 0; i < dim; i++){
          cor[i] = (a.p[i] + b.p[i]) / 2.0;
       }
       return new Point (cor);
    }
    /*
    This method multiplies each element of the array of double with the constant a. a is the coefficient we use in the optimization algorithm.
    */
    public Point mull(double a) {
       double p[] = new double[this.dim];
       Point m = new Point(p);
       for (int i = 0; i < this.dim; i++){
          m.p[i] = this.p[i]*a;
       }
       return m;
    }
    /*
    This method returns a string representation of the double array
    */

    @Override
    public String toString() {
       if (p != null) {
          String s = "[";
          for (int i = 0; i < this.dim; i++){
             s += (float)p[i];
             if (i == this.dim - 1) {
                s += "]";
             } else {
                s += ",";
             }
          }

          return s;
       } else {
          String s = "[";
          for (int i = 0; i < this.dim; i++){
             s += (int)ip[i];
             if (i == this.dim - 1) {
                s += "]";
             } else {
                s += ",";
             }
          }
          return s;
       }
    }
}

Listing 5-1The Point Class

执行代码

让我们编译源代码并执行它。以下是编译 Java 文件的命令。

javac Point.java
javac Rastrigin.java
javac SalpSwarmOptimizer.java

//running the example with 50 iterations and population size of 10 and 30 dimensions
java SalpSwarmOptimizer 50 10 30

输出

执行代码后,您会看到以下结果。

minimum value at iterartion 0=244.86356621486414
minimum value at iterartion 1=124.07861122372111
minimum value at iterartion 2=45.215002332220735
minimum value at iterartion 3=45.215002332220735
minimum value at iterartion 4=10.8885992360552
minimum value at iterartion 5=10.8885992360552
minimum value at iterartion 6=10.8885992360552
minimum value at iterartion 7=10.8885992360552
minimum value at iterartion 8=10.8885992360552
minimum value at iterartion 9=10.8885992360552
minimum value at iterartion 10=10.8885992360552
minimum value at iterartion 11=10.8885992360552
minimum value at iterartion 12=10.8885992360552
minimum value at iterartion 13=10.8885992360552
minimum value at iterartion 14=10.8885992360552
minimum value at iterartion 15=10.8885992360552
minimum value at iterartion 16=10.8885992360552
minimum value at iterartion 17=10.8885992360552
minimum value at iterartion 18=10.8885992360552
minimum value at iterartion 19=10.8885992360552
minimum value at iterartion 20=10.8885992360552
minimum value at iterartion 21=0.29297658145605965
minimum value at iterartion 22=0.29297658145605965
minimum value at iterartion 23=0.29297658145605965
minimum value at iterartion 24=0.29297658145605965
minimum value at iterartion 25=0.29297658145605965
minimum value at iterartion 26=0.29297658145605965
minimum value at iterartion 27=0.29297658145605965
minimum value at iterartion 28=0.29297658145605965
minimum value at iterartion 29=0.29297658145605965
minimum value at iterartion 30=0.29297658145605965
minimum value at iterartion 31=0.29297658145605965
minimum value at iterartion 32=0.29297658145605965
minimum value at iterartion 33=0.29297658145605965
minimum value at iterartion 34=0.29297658145605965
minimum value at iterartion 35=0.29297658145605965
minimum value at iterartion 36=0.29297658145605965
minimum value at iterartion 37=0.29297658145605965
minimum value at iterartion 38=0.28874178108526394
minimum value at iterartion 39=0.28857296330363624
minimum value at iterartion 40=0.2515754513162278
minimum value at iterartion 41=0.2433592726172833

minimum value at iterartion 42=0.1984760429712651
minimum value at iterartion 43=0.18909883434662333
minimum value at iterartion 44=0.17737272169620155
minimum value at iterartion 45=0.1590004357810244
minimum value at iterartion 46=0.14865231084121433
minimum value at iterartion 47=0.14865231084121433
minimum value at iterartion 48=0.14865231084121433
minimum value at iterartion 49=0.12695612866474448

摘要

本章介绍了针对 salp 群体及其觅食行为的优化问题解决方案。它涵盖了优化问题和解决方案的基本流程、流程图、伪代码和用 Java 编写的代码。Rastrigin 基准函数被用作算法中的目标函数。

posted @ 2024-08-06 16:40  绝不原创的飞龙  阅读(0)  评论(0编辑  收藏  举报