在优化算法领域,受自然界生物行为启发的算法不断涌现,为解决复杂优化问题提供了新的思路。哈里斯鹰优化算法(Harris Hawks Optimizer,HHO)便是其中之一,它由Ali Asghar Heidari等人于2019年提出,灵感来源于哈里斯鹰独特的合作狩猎行为。下面将参考论文《Harris hawks optimization: Algorithm and applications》,详细讲解哈里斯鹰优化算法的原理及其应用。

哈里斯鹰优化算法原理

哈里斯鹰是一种生活在自然界的智能鸟类,它们以独特的合作方式捕食猎物,这种行为为优化算法的设计提供了灵感。HHO算法将哈里斯鹰的狩猎策略转化为数学模型,用于解决各种优化问题。算法主要包括探索阶段(Exploitation phase)、从探索到开发的过渡(Transition from exploration to exploitation) 以及开发阶段(Exploitation phase),通过模拟哈里斯鹰在不同情况下的行为,平衡算法的全局探索和局部利用能力。

哈里斯鹰的狩猎行为

哈里斯鹰具有高度的智能和协作能力,在捕食时,它们会采用突袭策略(surprise pounce)。多只哈里斯鹰从不同方向合作攻击猎物,根据猎物的动态和逃脱模式展现多种追逐方式。当猎物试图逃脱时,哈里斯鹰会根据猎物的状态调整攻击策略,直至捕获猎物。这种狩猎行为体现了哈里斯鹰在探索猎物位置和利用已发现猎物信息方面的高效协作。

在这里插入图片描述

HHO算法的数学模型与实现

探索阶段(Exploitation phase)

哈里斯鹰通过强大的眼睛跟踪和发现猎物,但偶尔猎物不容易被看到。因此,哈里斯鹰需要等待、观察和监视,这可能需要几个小时才能发现猎物。在HHO算法中,哈里斯鹰随机栖息在某些位置上,并根据两种策略等待发现猎物,由随机数 q q q决定:

  1. q ≥ 0.5 q \geq 0.5 q0.5 时,哈里斯鹰随机栖息在群体家庭范围(group’s home range)内的高大树木上,具体是 基于其他随机鹰的位置来更新自身位置,公式为:
    X ( t + 1 ) = X r a n d ( t ) − r 1 ∣ X r a n d ( t ) − 2 r 2 X ( t ) ∣ X(t + 1)=X_{rand}(t)-r_{1}\left|X_{rand}(t)-2r_{2}X(t)\right| X(t+1)=Xrand(t)r1Xrand(t)2r2X(t)
    其中, X ( t + 1 ) X(t + 1) X(t+1)是鹰在下一次迭代鹰的位置向量, X r a n d ( t ) X_{rand}(t) Xrand(t)是当前种群中随机选择的一只鹰的位置, r 1 r_{1} r1 r 2 r_{2} r2是在 ( 0 , 1 ) (0,1) (0,1)内的随机数, X ( t ) X(t) X(t)是当前鹰的位置向量。
  2. q < 0.5 q < 0.5 q<0.5 时,鹰根据当前最优解(兔子)与群体平均位置的差异及随机缩放分量更新位置,公式为:
    X ( t + 1 ) = ( X r a b b i t ( t ) − X m ( t ) ) − r 3 ( L B + r 4 ( U B − L B ) ) X(t + 1)=(X_{rabbit}(t)-X_{m}(t))-r_{3}(LB + r_{4}(UB - LB)) X(t+1)=(Xrabbit(t)Xm(t))r3(LB+r4(UBLB))
    其中, X r a b b i t ( t ) X_{rabbit}(t) Xrabbit(t)是兔子(当前最优解)的位置, X m ( t ) X_{m}(t) Xm(t)是当前种群中鹰的平均位置, r 3 r_{3} r3 r 4 r_{4} r4是在 ( 0 , 1 ) (0,1) (0,1)内的随机数, L B LB LB U B UB UB是变量的上下界。
    平均位置 X m ( t ) X_{m}(t) Xm(t)的计算公式为为:
    X m ( t ) = 1 N ∑ i = 1 N X i ( t ) X_m(t) = \frac{1}{N}\sum\limits_{i=1}^N X_i(t) Xm(t)=N1i=1NXi(t)
    X i ( t ) X_i(t) Xi(t)表示迭代 t t t 中第 i i i 个鹰的位置, N N N 表示鹰的总数。

从探索阶段到开发阶段的过渡

HHO算法通过模拟猎物逃脱过程中逃逸能量(escaping energy)的变化来控制算法从探索阶段(Exploration phase)到开发阶段(Exploitation phase)的转换。猎物的逃逸能量 E E E由以下公式表示:
E = 2 E 0 ( 1 − t T ) E = 2E_{0}\left(1-\frac{t}{T}\right) E=2E0(1Tt)
其中, E 0 E_{0} E0在每次迭代中随机在 ( − 1 , 1 ) (-1,1) (1,1)内变化, T T T是最大迭代次数, t t t是当前迭代次数。当 ∣ E ∣ ≥ 1 |E| \geq 1 E1时,算法执行探索阶段,哈里斯鹰搜索不同区域以寻找猎物位置;当 ∣ E ∣ < 1 |E| < 1 E<1时,算法进入开发阶段,尝试利用已发现的有希望的解区域。
逃逸能量E和迭代时间t的模拟

开发阶段(Exploitation phase)

在开发阶段,哈里斯鹰根据猎物的逃脱几率(由随机数 r r r表示, r < 0.5 r<0.5 r<0.5代表逃脱成功; r ≥ 0.5 r\geq0.5 r0.5代表逃脱未成功)和剩余能量(由 E E E表示,当 ∣ E ∣ < 0.5 |E|<0.5 E<0.5 采用软围攻;当 ∣ E ∣ ≥ 0 |E|\geq 0 E0采用硬围攻),采用不同的攻击策略。根据猎物的逃跑行为和哈里斯鹰的追逐策略,在HHO中,提出了四种可能的策略来模拟攻击行为

  1. 软围攻(Soft besiege):当 r ≥ 0.5 r \geq 0.5 r0.5 ∣ E ∣ ≥ 0.5 |E| \geq 0.5 E0.5时,兔子仍有足够能量试图逃脱,但最终难以成功。哈里斯鹰通过以下公式更新位置,对兔子进行软围攻:
    X ( t + 1 ) = Δ X ( t ) − E ∣ J X r a b b i t ( t ) − X ( t ) ∣ X(t + 1)=\Delta X(t)-E\left|J X_{rabbit}(t)-X(t)\right| X(t+1)=ΔX(t)EJXrabbit(t)X(t)
    Δ X ( t ) = X r a b b i t ( t ) − X ( t ) \Delta X(t)=X_{rabbit}(t)-X(t) ΔX(t)=Xrabbit(t)X(t)
    其中, Δ X ( t ) \Delta X(t) ΔX(t)是兔子位置与当前鹰位置的差值, J = 2 ( 1 − r 5 ) J = 2(1 - r_{5}) J=2(1r5)代表兔子在逃脱过程中的随机跳跃强度, r 5 r_{5} r5是在 ( 0 , 1 ) (0,1) (0,1)内的随机数。

  2. 硬围攻(Hard besiege):当 r ≥ 0.5 r \geq 0.5 r0.5 ∣ E ∣ < 0.5 |E| < 0.5 E<0.5时,猎物已非常疲惫,哈里斯鹰采用硬围攻策略,直接逼近猎物。此时位置更新公式为:
    X ( t + 1 ) = X r a b b i t ( t ) − E ∣ Δ X ( t ) ∣ X(t + 1)=X_{rabbit}(t)-E|\Delta X(t)| X(t+1)=Xrabbit(t)E∣ΔX(t)
    在这里插入图片描述

  3. 软围攻与渐进快速俯冲(Soft besiege with progressive rapid dives):当 ∣ E ∣ ≥ 0.5 |E| \geq 0.5 E0.5 r < 0.5 r < 0.5 r<0.5时,兔子有足够能量成功逃脱,哈里斯鹰采用软围攻并结合渐进快速俯冲的策略。此过程利用Levy flight(LF)概念模拟猎物的逃脱模式和鹰的不规则快速俯冲。首先计算一个可能的位置 Y Y Y
    Y = X r a b b i t ( t ) − E ∣ J X r a b b i t ( t ) − X ( t ) ∣ Y = X_{rabbit}(t)-E\left|J X_{rabbit}(t)-X(t)\right| Y=Xrabbit(t)EJXrabbit(t)X(t)
    然后根据Levy flight公式计算另一个位置 Z Z Z
    Z = Y + S × L F ( D ) Z = Y + S \times LF(D) Z=Y+S×LF(D)
    其中, D D D是问题的维度, S S S是大小为 1 × D 1×D 1×D的随机向量, L F LF LFLevy Flight函数,计算方式为:
    L F ( x ) = 0.01 × u × σ ∣ v ∣ 1 β , σ = ( Γ ( 1 + β ) × sin ⁡ ( π β 2 ) Γ ( 1 + β 2 ) × β × 2 ( β − 1 2 ) ) 1 β LF(x)=0.01 \times \frac{u \times \sigma}{|v|^{\frac{1}{\beta}}}, \quad \sigma=\left(\frac{\Gamma(1+\beta) \times \sin \left(\frac{\pi \beta}{2}\right)}{\Gamma\left(\frac{1+\beta}{2}\right) \times \beta \times 2^{\left(\frac{\beta - 1}{2}\right)}}\right)^{\frac{1}{\beta}} LF(x)=0.01×vβ1u×σ,σ= Γ(21+β)×β×2(2β1)Γ(1+β)×sin(2πβ) β1
    这里, x x x 起什么作用还没有搞明白 u u u v v v是在 ( 0 , 1 ) (0,1) (0,1)内的随机值, β \beta β是默认常数,通常设为 1.5 1.5 1.5。最终,根据 F ( Y ) F(Y) F(Y) F ( Z ) F(Z) F(Z)与当前位置 F ( X ( t ) ) F(X(t)) F(X(t))的比较结果,选择更好的位置作为下一次迭代的位置:
    X ( t + 1 ) = { Y , if  F ( Y ) < F ( X ( t ) ) Z , if  F ( Z ) < F ( X ( t ) ) X(t + 1)=\begin{cases}Y, & \text{if } F(Y)<F(X(t)) \\ Z, & \text{if } F(Z)<F(X(t))\end{cases} X(t+1)={Y,Z,if F(Y)<F(X(t))if F(Z)<F(X(t))
    F ( ⋅ ) F(\cdot) F()函数未明确指出,可能是目标函数。

  1. 硬围攻与渐进快速俯冲(Hard besiege with progressive rapid dives):当 ∣ E ∣ < 0.5 |E| < 0.5 E<0.5 r < 0.5 r < 0.5 r<0.5时,兔子没有足够能量逃脱,哈里斯鹰采用硬围攻并结合渐进快速俯冲的策略。此时,计算 Y Y Y Z Z Z的公式如下:
    Y = X r a b b i t ( t ) − E ∣ J X r a b b i t ( t ) − X m ( t ) ∣ Y = X_{rabbit}(t)-E\left|J X_{rabbit}(t)-X_{m}(t)\right| Y=Xrabbit(t)EJXrabbit(t)Xm(t)
    Z = Y + S × L F ( D ) Z = Y + S \times LF(D) Z=Y+S×LF(D)
    同样,根据 F ( Y ) F(Y) F(Y) F ( Z ) F(Z) F(Z)与当前位置 F ( X ( t ) ) F(X(t)) F(X(t))的比较结果,选择更好的位置作为下一次迭代的位置。
    X ( t + 1 ) = { Y , if  F ( Y ) < F ( X ( t ) ) Z , if  F ( Z ) < F ( X ( t ) ) X(t + 1)=\begin{cases}Y, & \text{if } F(Y)<F(X(t)) \\ Z, & \text{if } F(Z)<F(X(t))\end{cases} X(t+1)={Y,Z,if F(Y)<F(X(t))if F(Z)<F(X(t))
    在这里插入图片描述

算法流程

HHO算法在每一代中,根据猎物能量 E E E的值决定采用探索阶段还是利用阶段的策略来更新解的位置。更新后的解通过目标函数进行评估,以判断是否达到最优解或满足终止条件。整个算法流程不断迭代,直到达到最大迭代次数或满足其他终止条件为止。文章中给出伪代码如下:

Inputs: The population size N and maximum number of iterations T
Outputs: The location of rabbit and its fitness value
Initialize the random population Xi(i = 1, 2, . . . , N)
while (stopping condition is not met) do
    Calculate the fitness values of hawks
    Set Xrabbit as the location of rabbit (best location)
    for (each hawk (Xi)) do
        E0 = 2rand() - 1, J = 2(1 - rand())
        Update the initial energy E0 and jump strength J
        Update the E using Eq. (3)
        if (|E|1) then ▷Exploration phase
            Update the location vector using Eq. (1)
        if (|E|< 1) then ▷Exploitation phase
            if (r ≥0.5 and |E|0.5 ) then ▷Soft besiege
                Update the location vector using Eq. (4)
            else if (r ≥0.5 and |E|< 0.5 ) then ▷Hard besiege
                Update the location vector using Eq. (6)
            else if (r < 0.5 and |E|0.5 ) then ▷Soft besiege with progressive rapid dives
                Update the location vector using Eq. (10)
            else if (r < 0.5 and |E|< 0.5 ) then ▷Hard besiege with progressive rapid dives
                Update the location vector using Eq. (11)
Return Xrabbit

代码

文中给出了文章代码,请参考HHO或直接访问HHO-matlab code
在这里插入图片描述

main 主函数

clear all %#ok<CLALL>
close all
clc

N=30; % Number of search agents

Function_name='F1'; % Name of the test function 

T=500; % Maximum number of iterations

% Load details of the selected benchmark function
[lb,ub,dim,fobj]=Get_Functions_details(Function_name);

[Rabbit_Energy,Rabbit_Location,CNVG]=HHO(N,T,lb,ub,dim,fobj);


%Draw objective space
figure,
hold on
semilogy(CNVG,'Color','b','LineWidth',4);
title('Convergence curve')
xlabel('Iteration');
ylabel('Best fitness obtained so far');
axis tight
grid off
box on
legend('HHO')

display(['The best location of HHO is: ', num2str(Rabbit_Location)]);
display(['The best fitness of HHO is: ', num2str(Rabbit_Energy)]);

initialization 初始化函数

function [X]=initialization(N,dim,up,down)
% 输入:种群数量N、维度dim、最大值up、最小值down
% 输出:种群位置X
if size(up,1)==1
    X=rand(N,dim).*(up-down)+down;
end
if size(up,1)>1
    for i=1:dim
        high=up(i);low=down(i);
        X(:,i)=rand(1,N).*(high-low)+low;
    end
end
end

HHO函数

function [Rabbit_Energy,Rabbit_Location,CNVG]=HHO(N,T,lb,ub,dim,fobj)

disp('HHO is now tackling your problem')
tic
% initialize the location and Energy of the rabbit
Rabbit_Location=zeros(1,dim);
Rabbit_Energy=inf;

%Initialize the locations of Harris' hawks
X=initialization(N,dim,ub,lb);

CNVG=zeros(1,T);

t=0; % Loop counter

while t<T
    for i=1:size(X,1)
        % Check boundries
        FU=X(i,:)>ub;FL=X(i,:)<lb;X(i,:)=(X(i,:).*(~(FU+FL)))+ub.*FU+lb.*FL;
        % fitness of locations
        fitness=fobj(X(i,:));
        % Update the location of Rabbit
        if fitness<Rabbit_Energy
            Rabbit_Energy=fitness;
            Rabbit_Location=X(i,:);
        end
    end
    
    E1=2*(1-(t/T)); % factor to show the decreaing energy of rabbit
    % Update the location of Harris' hawks
    for i=1:size(X,1)
        E0=2*rand()-1; %-1<E0<1
        Escaping_Energy=E1*(E0);  % escaping energy of rabbit
        
        if abs(Escaping_Energy)>=1
            %% Exploration:
            % Harris' hawks perch randomly based on 2 strategy:
            
            q=rand();
            rand_Hawk_index = floor(N*rand()+1);
            X_rand = X(rand_Hawk_index, :);
            if q<0.5
                % perch based on other family members
                X(i,:)=X_rand-rand()*abs(X_rand-2*rand()*X(i,:));
            elseif q>=0.5
                % perch on a random tall tree (random site inside group's home range)
                X(i,:)=(Rabbit_Location(1,:)-mean(X))-rand()*((ub-lb)*rand+lb);
            end
            
        elseif abs(Escaping_Energy)<1
            %% Exploitation:
            % Attacking the rabbit using 4 strategies regarding the behavior of the rabbit
            
            %% phase 1: surprise pounce (seven kills)
            % surprise pounce (seven kills): multiple, short rapid dives by different hawks
            
            r=rand(); % probablity of each event
            
            if r>=0.5 && abs(Escaping_Energy)<0.5 % Hard besiege
                X(i,:)=(Rabbit_Location)-Escaping_Energy*abs(Rabbit_Location-X(i,:));
            end
            
            if r>=0.5 && abs(Escaping_Energy)>=0.5  % Soft besiege
                Jump_strength=2*(1-rand()); % random jump strength of the rabbit
                X(i,:)=(Rabbit_Location-X(i,:))-Escaping_Energy*abs(Jump_strength*Rabbit_Location-X(i,:));
            end
            
            %% phase 2: performing team rapid dives (leapfrog movements)
            if r<0.5 && abs(Escaping_Energy)>=0.5, % Soft besiege % rabbit try to escape by many zigzag deceptive motions
                
                Jump_strength=2*(1-rand());
                X1=Rabbit_Location-Escaping_Energy*abs(Jump_strength*Rabbit_Location-X(i,:));
                
                if fobj(X1)<fobj(X(i,:)) % improved move?
                    X(i,:)=X1;
                else % hawks perform levy-based short rapid dives around the rabbit
                    X2=Rabbit_Location-Escaping_Energy*abs(Jump_strength*Rabbit_Location-X(i,:))+rand(1,dim).*Levy(dim);
                    if (fobj(X2)<fobj(X(i,:))), % improved move?
                        X(i,:)=X2;
                    end
                end
            end
            
            if r<0.5 && abs(Escaping_Energy)<0.5, % Hard besiege % rabbit try to escape by many zigzag deceptive motions
                % hawks try to decrease their average location with the rabbit
                Jump_strength=2*(1-rand());
                X1=Rabbit_Location-Escaping_Energy*abs(Jump_strength*Rabbit_Location-mean(X));
                
                if fobj(X1)<fobj(X(i,:)) % improved move?
                    X(i,:)=X1;
                else % Perform levy-based short rapid dives around the rabbit
                    X2=Rabbit_Location-Escaping_Energy*abs(Jump_strength*Rabbit_Location-mean(X))+rand(1,dim).*Levy(dim);
                    if (fobj(X2)<fobj(X(i,:))), % improved move?
                        X(i,:)=X2;
                    end
                end
            end
            %%
        end
    end
    t=t+1;
    CNVG(t)=Rabbit_Energy;
%    Print the progress every 100 iterations
%    if mod(t,100)==0
%        display(['At iteration ', num2str(t), ' the best fitness is ', num2str(Rabbit_Energy)]);
%    end
end
toc
end

Levy Fight函数

function o=Levy(d)
beta=1.5;
sigma=(gamma(1+beta)*sin(pi*beta/2)/(gamma((1+beta)/2)*beta*2^((beta-1)/2)))^(1/beta);
u=randn(1,d)*sigma;v=randn(1,d);step=u./abs(v).^(1/beta);
o=step;
end

虽然文章中未给出具体代码,但根据算法原理,可以使用Python或Matlab等编程语言实现HHO算法。以Python为例,以下是一个简单的实现框架:

import numpy as np

def hho(population_size, max_iterations, lower_bound, upper_bound, dim, fitness_function):
    # 初始化哈里斯鹰的位置
    hawks = np.random.uniform(lower_bound, upper_bound, (population_size, dim))
    fitness = np.array([fitness_function(hawk) for hawk in hawks])
    best_index = np.argmin(fitness)
    best_hawk = hawks[best_index]
    best_fitness = fitness[best_index]
    convergence_curve = []

    for t in range(max_iterations):
        E0 = 2 * np.random.rand() - 1
        J = 2 * (1 - np.random.rand())
        E = 2 * E0 * (1 - t / max_iterations)

        for i in range(population_size):
            if np.abs(E) >= 1:
                q = np.random.rand()
                if q >= 0.5:
                    rand_index = np.random.randint(0, population_size)
                    hawks[i] = hawks[rand_index] - np.random.rand() * np.abs(
                        hawks[rand_index] - 2 * np.random.rand() * hawks[i])
                else:
                    hawks[i] = (best_hawk - np.mean(hawks, axis=0)) - np.random.rand() * (
                        lower_bound + np.random.rand() * (upper_bound - lower_bound))
            else:
                r = np.random.rand()
                if r >= 0.5:
                    if np.abs(E) >= 0.5:
                        delta_X = best_hawk - hawks[i]
                        hawks[i] = delta_X - E * np.abs(J * best_hawk - hawks[i])
                    else:
                        hawks[i] = best_hawk - E * np.abs(delta_X)
                else:
                    if np.abs(E) >= 0.5:
                        Y = best_hawk - E * np.abs(J * best_hawk - hawks[i])
                        # 这里省略Levy flight计算,需根据公式实现
                        # Z = Y + S * LF(D)
                        # 假设LF函数已实现为levy_flight
                        S = np.random.rand(1, dim)
                        Z = Y + S * levy_flight(dim)
                        if fitness_function(Z) < fitness_function(hawks[i]):
                            hawks[i] = Z
                        elif fitness_function(Y) < fitness_function(hawks[i]):
                            hawks[i] = Y
                    else:
                        Y = best_hawk - E * np.abs(J * best_hawk - np.mean(hawks, axis=0))
                        # 同样省略Levy flight计算,需根据公式实现
                        # Z = Y + S * LF(D)
                        S = np.random.rand(1, dim)
                        Z = Y + S * levy_flight(dim)
                        if fitness_function(Z) < fitness_function(hawks[i]):
                            hawks[i] = Z
                        elif fitness_function(Y) < fitness_function(hawks[i]):
                            hawks[i] = Y

            # 边界处理
            hawks[i] = np.clip(hawks[i], lower_bound, upper_bound)
            current_fitness = fitness_function(hawks[i])
            if current_fitness < best_fitness:
                best_fitness = current_fitness
                best_hawk = hawks[i]

        convergence_curve.append(best_fitness)

    return best_hawk, best_fitness, convergence_curve

参考资料
[1] Ali Asghar Heidari, Seyedali Mirjalili, Hossam Faris, et al. Harris hawks optimization: Algorithm and applications[J]. Future Generation Computer Systems, 2019, 97: 849 - 872.

更多推荐