前言

狼群算法((Wolf pack algorithm ,WPA)采用了基于人工狼主体的自下而上的设计方法和基于职责分工的协作式搜索路径结构。

  1. 吴虎胜等在 2013 年提出
  2. 模拟狼群捕食行为及其猎物分配方式

截止到 2023 年,算法引用趋势

1. 狼相关的生物群行为

狼是分布最广的群居群猎动物。有明确的社会分工,它们团结协作为狼群的生存与发展承担着各自的责任。智能颇高,彼此之间通过气味、叫声沟通。

狼的社会分工有头狼、探狼和猛狼:

  • 头狼: 将当前离猎物气味浓度最高(适应度最优)的狼作为头狼,起指挥狼群行动的作用,头领狼召唤其他狼向猎物靠近,具有指挥狼群行动的能力,在搜寻过程中头狼的角色是动态变化的。
  • 探狼: 初始时,狼群会派出一部分狼作为探狼,在环境四周搜寻猎物。探狼在搜寻过程中如果发现猎物气味浓度更高,就作为头狼,呼唤其他的狼进行围捕行为。后期,比较不同的探狼猎物的适应度,选择适应度较高的作为头狼。
  • 猛狼: 猛狼感应到头狼呼唤,就立刻向头狼位置奔袭,在奔袭的过程中,若是发现猎物的适应度更高,则立刻替代原来的头领狼,指挥其他狼行动。

猎物分配规则: 捕获猎物后,狼群并不是平均分配猎物,而是按“论功行赏、由强到弱”的方式分配,即先将猎物分配给最先发现、捕到猎物的强壮的狼,而后再分配给弱小的狼。(即论功行赏,先强后弱)

将狼群的整个捕猎行动抽象为三种智能行为:游走行为、召唤行为和围攻行为

2. 算法仿生设计

2.1 头狼产生规则

初始化: 初始解空间中,具有最优目标函数值的人工狼即为头狼。

迭代: 在迭代过程中,将每次迭代后最优狼的目标函数值与前一代中头狼的值进行比较,若更优则对头狼位置进行更新,若此时存在多匹的情况,则随机选一匹成为头狼。头狼不执行3种智能行为而直接进入下次迭代,直到它被其他更强的人工狼所替代。

目标函数值:定义为人工狼所能感知到的猎物气味浓度 Y = f ( X ) Y=f(X) Y=f(X)

2.2 游走行为:探狼搜索猎物

初始化: 将解空间中除头狼外最佳的 S_num 匹人工狼视为探狼,在解空间中搜索猎物, S_num 随机取 [ n / ( α + 1 ) , n / α ] [n/(α+1),n/α] [n/(α+1),n/α] 之间的整数, α α α 为探狼比例因子。

游走: 选择气味最浓并且大于当前位置气味浓度 Y i 0 Y_{i0} Yi0 的方向前进一步:

x i d p = x i d + s i n ⁡ ( 2 π × p / h ) × s t e p a d x_{id}^p=x_{id}+sin⁡(2π×p/ℎ)× step_a^d xidp=xid+sin(2π×p/h)×stepad

其中, s t e p a d step_a^d stepad 为游走步长, h ℎ h 为游走方向, p = 1 , 2 , … , h p=1,2,…,ℎ p=1,2,,h

重复以上游走行为,直至存在某一匹探狼的气味浓度 Y i > Y l e a d Y_i> Y_{lead} Yi>Ylead,则探狼 i i i 代替头狼并发起召唤行为,或者达到最大游走次数 T m a x T_{max} Tmax

2.3 召唤行为:

头狼通过嚎叫发起召唤行为,头狼周围的猛狼以较大的奔袭步长逼近头狼所在位置。

x i d k + 1 = x i d k + s t e p b d ⋅ ( g d k − x i d k ) ∣ g d k − x i d k ∣ x_{id}^{k+1}=x_{id}^k+step_b^d⋅\frac{(g_d^k−x_{id}^k)}{|g_d^k−x_{id}^k|} xidk+1=xidk+stepbdgdkxidk(gdkxidk)

其中, g d k g_d^k gdk 为第 k k k 代群体头狼在第 d d d 维空间的位置, s t e p b d step_b^d stepbd 为奔袭步长。

奔袭途中,若猛狼 i i i 的气味浓度 Y i > Y l e a d Y_i> Y_{lead} Yi>Ylead,则猛狼 i i i 代替头狼并发起召唤行为;若 Y i < Y l e a d Y_i< Y_{lead} Yi<Ylead,则猛狼 i i i 继续奔袭直到 d i s ≤ d n e a r d_{is}≤d_{near} disdnear 时加入到对猎物的攻击行列,即转入围攻行为。
d n e a r = 1 D ω ∑ d = 1 D ∣ m a x d − m i n d ∣ d_{near}=\frac{1}{Dω}\sum_{d=1}^D|max_d−min_d| dnear=Dω1d=1Dmaxdmind

其中, ω ω ω 为距离判定因子,待寻优的第 d d d 维变量取值范围为 [ m i n d , m a x d ] [min_d, max_d] [mind,maxd]

2.4 围攻行为:猛狼和探狼联合对猎物进行围攻以捕获猎物

x i d k + 1 = x i d k + λ ⋅ s t e p c d ⋅ ∣ G d k − x i d k ∣ x_{id}^{k+1}=x_{id}^k+λ⋅step_c^d⋅|G_d^k−x_{id}^k| xidk+1=xidk+λstepcdGdkxidk

其中, G d k G_d^k Gdk 为第 k k k 代群体中猎物在第 d d d 维空间的位置, s t e p c d step_c^d stepcd 为攻击步长, λ λ λ 为 [-1, 1] 之间均匀分布的随机数。

围攻途中,若人工狼 i i i 的气味浓度大于原有位置气味浓度,则更新位置;否则,人工狼位置不变。

注: 围攻行为和召唤行为,其实都是猛狼响应头狼的召唤,向头狼位置移动,只是在召唤阶段以较大的步长移动,在距离头狼较近时,转而执行围攻行为,以较小的步长移动,以防止步长过大,跨过头狼的位置。

2.5 三种步长的关系

s t e p a d = s t e p b d 2 = 2 ⋅ s t e p c d = ∣ m a x d − m i n d ∣ / S step_a^d=\frac{step_b^d}{2}=2⋅step_c^d=|max_d−min_d|/S stepad=2stepbd=2stepcd=maxdmind∣/S
其中, S S S 为步长因子,待寻优的第 d d d 维变量取值范围为 [ m i n d , m a x d ] [min_d, max_d] [mind,maxd]


在这里插入图片描述


2.6 “强者生存”的狼群更新机制

猎物按照“由强到弱”的原则进行分配,导致弱小的狼会被饿死。即在算法中去除目标函数值最差的R匹人工狼,同时随机产生R匹人工狼。

R 取 [ n 2 × β , n / β ] [\frac{n}{2}×β, n/β] [2n×β,n/β] 之间的随机整数, β β β 为群体更新比例因子。

3. 算法流程

4. 算法相关改进

  • 奔袭步长采用非线性的动态惯性权重系数公式,使得奔袭步长的取值依靠适应度值的变化而自动调整,从而增加在搜索过程中的智能性;

  • 围攻步长采用自适应的更新公式,使围攻步长随着迭代次数的不断增大而逐渐减小,从而就提高找到更优值的概率;

  • 在狼群每次移动过程中, 利用头狼移动方向包含的潜在猎物位置信息引导狼群进化,并加强头狼在狼群中的领导力度。

5. 代码实现(chatGPT)

其中,fitness_func 是优化问题的目标函数,lb 和 ub 是自变量的上下界,dim 是自变量的维度,max_gen 是最大迭代次数,pop_size 是种群大小,alpha、beta 和 delta 是狼群更新常数。函数返回最优解 bestX 和最优解的函数值 bestF。
需要注意的是,在更新狼群位置时,需要对狼群的位置进行边界处理,确保自变量在规定的区间内。此外,狼群算法的收敛性较差,需要通过适当的参数设置和多次运行来获得较优的解。

function [bestX, bestF] = wolf_pack_algorithm(fitness_func, lb, ub, dim, max_gen, pop_size, alpha, beta, delta)
% 狼群算法
% fitness_func - 适应度函数
% lb - 自变量下界
% ub - 自变量上界
% dim - 自变量维度
% max_gen - 最大迭代次数
% pop_size - 种群大小
% alpha - 狼群更新常数
% beta - 狼群更新常数
% delta - 狼群更新常数
    % 初始化种群
    pop = create_population(lb, ub, dim, pop_size);
    % 计算适应度
    fitness = evaluate_fitness(fitness_func, pop, pop_size);
    % 寻找最优解
    [bestF, bestIdx] = min(fitness);
    bestX = pop(bestIdx, :);
    % 迭代优化
    for gen = 1:max_gen
        % 更新狼群位置
        for i = 1:pop_size
            % 计算狼群中每个狼的适应度
            fitness_i = fitness(i);
            for j = 1:pop_size
                if fitness(j) < fitness_i
                    r1 = rand(1, dim);
                    r2 = rand(1, dim);
                    A = alpha * (2 * r1 - 1);
                    C = 2 * r2;
                    D = abs(C .* bestX - pop(i, :));
                    X1 = bestX - A .* D;
                    fitness_X1 = evaluate_fitness(fitness_func, X1, 1);
                    % 更新最优解
                    if fitness_X1 < bestF
                        bestF = fitness_X1;
                        bestX = X1;
                    end
                    % 更新狼群位置
                    if fitness_X1 < fitness_i
                        pop(i, :) = X1;
                        fitness_i = fitness_X1;
                    else
                        r3 = rand;
                        if r3 < beta
                            X2 = pop(j, :) + delta * (rand(1, dim) - 0.5);
                            fitness_X2 = evaluate_fitness(fitness_func, X2, 1);
                            % 更新最优解
                            if fitness_X2 < bestF
                                bestF = fitness_X2;
                                bestX = X2;
                            end
                            % 更新狼群位置
                            if fitness_X2 < fitness_i
                                pop(i, :) = X2;
                                fitness_i = fitness_X2;
                            end
                        end
                    end
                end
            end
        end
    end
end
% 初始化种群
function pop = create_population(lb, ub, dim, pop_size)
    pop = repmat(lb, pop_size, 1) + rand(pop_size, dim) .* repmat((ub - lb), pop_size, 1);
end
% 计算适应度
function fitness = evaluate_fitness(fitness_func, pop, pop_size)
    fitness = zeros(pop_size, 1);
    for i = 1:pop_size
        fitness(i) = fitness_func(pop(i, :));
    end
end

5.1 函数输入

function [bestX, bestF] = wolf_pack_algorithm(fitness_func, lb, ub, dim, max_gen, pop_size, alpha, beta, delta)

这个函数的输入参数包括:

fitness_func:用户定义的适应度函数,用于计算每个个体的适应度值。

lb 和 ub:自变量的最小值和最大值。

dim:自变量的维度。

max_gen:最大迭代次数。

pop_size:种群大小。

alpha、beta 和 delta:狼群更新常数。

5.2 种群初始化

pop = create_population(lb, ub, dim, pop_size);

这个函数用于生成初始的种群,其中 lb 和 ub 分别是自变量的最小值和最大值,dim 是自变量的维度,pop_size 是种群大小。这里采用了随机生成的方式,即将每个自变量的取值随机生成在 lb 和 ub 之间。

5.3 适应度计算

fitness = evaluate_fitness(fitness_func, pop, pop_size);

这个函数用于计算种群中每个个体的适应度值,其中 fitness_func 是用户定义的适应度函数,pop 是种群的矩阵表示,pop_size 是种群大小。

5.4 最优解寻找

[bestF, bestIdx] = min(fitness);
bestX = pop(bestIdx, :);

这段代码用于寻找当前种群中的最优解,即使适应度函数最小化的自变量取值。min 函数返回种群中最小适应度值 bestF 和对应的索引 bestIdx,然后通过 pop(bestIdx, 😃 取出最优解的自变量取值 bestX。

5.5 迭代优化

for gen = 1:max_gen
    % 更新狼群位置
    for i = 1:pop_size
        % 计算狼群中每个狼的适应度
        fitness_i = fitness(i);
        for j = 1:pop_size
            if fitness(j) < fitness_i
                r1 = rand(1, dim);
                r2 = rand(1, dim);
                A = alpha * (2 * r1 - 1);
                C = 2 * r2;
                D = abs(C .* bestX - pop(i, :));
                X1 = bestX - A .* D;
                fitness_X1 = evaluate_fitness(fitness_func, X1, 1);
                % 更新最优解
                if fitness_X1 < bestF
                    bestF = fitness_X1;
                    bestX = X1;
                end
                % 更新狼群位置
                if fitness_X1 < fitness_i
                    pop(i, :) = X1;
                    fitness_i = fitness_X1;
                else
                    r3 = rand;
                    if r3 < beta
                        X2 = pop(j, :) + delta * (rand(1, dim) - 0.5);
                        fitness_X2 = evaluate_fitness(fitness_func, X2, 1);
                        % 更新最优解
                        if fitness_X2 < bestF
                            bestF = fitness_X2;
                            bestX = X2;
                        end
                        % 更新狼群位置
                        if fitness_X2 < fitness_i
                            pop(i, :) = X2;
                            fitness_i = fitness_X2;
                        end
                    end
                end
            end
        end
    end
end

这段代码是狼群算法的核心部分,主要是通过更新狼群的位置来优化目标函数。具体来说,每个狼的位置通过以下方式进行更新:

计算狼与最优解的距离,并计算出一个向量 D。

根据 alpha、beta 和 delta 的值,计算出一个向量 A。

计算出新的位置向量 X1。

计算新位置的适应度值 fitness_X1。

如果新位置的适应度值小于当前位置的适应度值,更新位置和适应度值。

如果新位置的适应度值大于等于当前位置的适应度值,根据 beta 的值决定是否采用另一个狼的位置进行更新。如果随机数小于 beta,则找到另一个适应度更好的狼,并根据 delta 的值计算出新位置 X2,然后计算新位置的适应度值 fitness_X2。如果新位置的适应度值小于当前位置的适应度值,更新位置和适应度值。
在上述过程中,还需要注意对位置向量进行边界处理,确保自变量在规定的区间内。

5.6 函数输出

function [bestX, bestF] = wolf_pack_algorithm(fitness_func, lb, ub, dim, max_gen, pop_size, alpha, beta, delta)

最后,函数输出寻找到的最优解 bestX 和最优解的适应度值 bestF。

References

[1] 吴虎胜, 张凤鸣, 吴庐山. 一种新的群体智能算法——狼群算法[J]. 系统工程与电子技术, 2013, 35(11):9.

[2] 基于群智能的路径规划算法(五)------狼群算法

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐