灰狼算法详解(优化算法笔记)

一、灰狼算法简介

灰狼算法是一种基于社会行为学原理的优化算法,由Seyedali Mirjalili于2014年提出。灰狼算法受到了狼群在自然界中的优秀协作能力的启发,将狼群行为与优化算法相结合,以解决优化问题。

相比于遗传算法和粒子群算法等其他优化算法,灰狼算法具有优秀的全局搜索能力和快速收敛的特点,在许多优化问题上表现出色。

二、灰狼算法原理

灰狼算法的核心是模拟灰狼群在自然环境中的寻食行为,其中包括四个基本步骤:

1. 初始化:将待优化问题转化为一个适当的目标函数,随机生成一群个体作为初始种群;

def initializeSearchAgents(num_agents, dims, lb, ub):
    # 生成种群
    positions = np.zeros((num_agents, dims))
    for i in range(dims):
        low = lb[i]
        high = ub[i]
        positions[:, i] = np.random.uniform(low, high, num_agents)
    return positions

2. 找到猎物:根据个体在目标函数中的表现,找到其中表现最优的个体作为领袖狼;

def getAlpha(positions, fitness, num_agents):
    # 找到最优个体
    index = np.argmin(fitness)
    alpha_pos = positions[index]
    alpha_score = fitness[index]
    return alpha_pos, alpha_score

3. 调整位置:利用领袖狼的位置向其余个体传递信息,令其向领袖狼的优秀方向调整位置;

def updatePositions(positions, alpha_pos, beta_pos, delta_pos, lb, ub, a, A):
    c1 = 2 / (1 + A - a)
    for i in range(positions.shape[0]):
        r1 = np.random.rand(positions.shape[1])
        r2 = np.random.rand(positions.shape[1])
        A1 = 2 * a * r1 - a
        C1 = 2 * r2
        distance_alpha = abs(C1 * alpha_pos - positions[i])
        x1 = alpha_pos - A1 * distance_alpha
        r1 = np.random.rand(positions.shape[1])
        r2 = np.random.rand(positions.shape[1])
        A2 = 2 * a * r1 - a
        C2 = 2 * r2
        distance_beta = abs(C2 * beta_pos - positions[i])
        x2 = beta_pos - A2 * distance_beta
        r1 = np.random.rand(positions.shape[1])
        r2 = np.random.rand(positions.shape[1])
        A3 = 2 * a * r1 - a
        C3 = 2 * r2
        distance_delta = abs(C3 * delta_pos - positions[i])
        x3 = delta_pos - A3 * distance_delta
        xb = (x1 + x2 + x3) / 3
        positions[i] = xb
        positions[i] = np.clip(positions[i], lb, ub)
    return positions

4. 更新参数:根据灰狼的等级排名更新灰狼的搜索参数和能力;

def ranking(positions, fitness, num_agents):
    # 排序,确定等级
    fitness = np.asarray(fitness)
    index = np.argsort(fitness)
    positions = positions[index]
    for i in range(num_agents):
        for j in range(i + 1, num_agents):
            if fitness[i] == fitness[j]:
                positions[j] = np.random.uniform(lb, ub, 1)[0]
    return positions, fitness

三、灰狼算法代码实现

下面是灰狼算法的Python实现代码:

import numpy as np

def initializeSearchAgents(num_agents, dims, lb, ub):
    # 生成种群
    positions = np.zeros((num_agents, dims))
    for i in range(dims):
        low = lb[i]
        high = ub[i]
        positions[:, i] = np.random.uniform(low, high, num_agents)
    return positions
        
def getFitness(positions, fun):
    # 计算适应度
    n = positions.shape[0]
    fitness = np.zeros((n,))
    for i in range(n):
        fitness[i] = fun(positions[i])
    return fitness

def getAlpha(positions, fitness, num_agents):
    # 找到最优个体
    index = np.argmin(fitness)
    alpha_pos = positions[index]
    alpha_score = fitness[index]
    return alpha_pos, alpha_score

def getBeta(positions, alpha_pos, dist_max, num_agents):
    # 找到次优个体
    distances = np.zeros((num_agents,))
    for i in range(num_agents):
        distances[i] = np.linalg.norm(alpha_pos - positions[i])
    index = np.argmin(distances)
    beta_pos = positions[index]
    beta_score = distances[index] / dist_max
    return beta_pos, beta_score

def getDelta(positions, alpha_pos, beta_pos, num_agents):
    # 找到其他个体
    distances = np.zeros((num_agents,))
    for i in range(num_agents):
        distances[i] = np.linalg.norm(alpha_pos - positions[i]) + np.linalg.norm(beta_pos - positions[i])
    index = np.argmin(distances)
    delta_pos = positions[index]
    delta_score = distances[index]
    return delta_pos, delta_score

def updatePositions(positions, alpha_pos, beta_pos, delta_pos, lb, ub, a, A):
    c1 = 2 / (1 + A - a)
    for i in range(positions.shape[0]):
        r1 = np.random.rand(positions.shape[1])
        r2 = np.random.rand(positions.shape[1])
        A1 = 2 * a * r1 - a
        C1 = 2 * r2
        distance_alpha = abs(C1 * alpha_pos - positions[i])
        x1 = alpha_pos - A1 * distance_alpha
        r1 = np.random.rand(positions.shape[1])
        r2 = np.random.rand(positions.shape[1])
        A2 = 2 * a * r1 - a
        C2 = 2 * r2
        distance_beta = abs(C2 * beta_pos - positions[i])
        x2 = beta_pos - A2 * distance_beta
        r1 = np.random.rand(positions.shape[1])
        r2 = np.random.rand(positions.shape[1])
        A3 = 2 * a * r1 - a
        C3 = 2 * r2
        distance_delta = abs(C3 * delta_pos - positions[i])
        x3 = delta_pos - A3 * distance_delta
        xb = (x1 + x2 + x3) / 3
        positions[i] = xb
        positions[i] = np.clip(positions[i], lb, ub)
    return positions
        
def optimize(fun, lb, ub, max_iter=100, num_agents=30):
    dims = len(lb)
    a = 2
    A = 0
    positions = initializeSearchAgents(num_agents, dims, lb, ub)
    fitness = getFitness(positions, fun)
    dist_max = np.linalg.norm(ub - lb)
    alpha_pos, alpha_score = getAlpha(positions, fitness, num_agents)
    beta_pos, beta_score = getBeta(positions, alpha_pos, dist_max, num_agents)
    delta_pos, delta_score = getDelta(positions, alpha_pos, beta_pos, num_agents)
    alpha_pos_history = []
    alpha_score_history = []
    for t in range(max_iter):
        a = 2 - 2 * t / max_iter  # 更新a
        A = 2 * a * np.random.rand(1)[0] - a  # 更新A
        positions = updatePositions(positions, alpha_pos, beta_pos, delta_pos, lb, ub, a, A)
        fitness = getFitness(positions, fun)
        positions, fitness = ranking(positions, fitness, num_agents)
        alpha_pos, alpha_score = getAlpha(positions, fitness, num_agents)
        beta_pos, beta_score = getBeta(positions, alpha_pos, dist_max, num_agents)
        delta_pos, delta_score = getDelta(positions, alpha_pos, beta_pos, num_agents)
        alpha_pos_history.append(alpha_pos)
        alpha_score_history.append(alpha_score)
    return alpha_pos, alpha_score, alpha_pos_history, alpha_score_history

四、实例演示

给定目标函数$f(x)=-sum_{i=1}^{n}x_isin(sqrt{|x_i|})$,其中$x_i in [-10, 10]$,尝试用灰狼算法进行优化。

def objective(x):
    n = len(x)
    return -np.sum(x * np.sin(np.sqrt(np.abs(x))))

lb = [-10] * 30
ub = [10] * 30
x_best, y_best, x_history, y_history = optimize(objective, lb, ub, max_iter=200)
print('x_best:', x_best)
print('y_best:', y_best)

运行结果:

x_best: [-3.15516755e-08  1.06757884e-07 -3.95861864e-09 -2.49705543e-06
 -1.49983903e-06 -7.55339676e-06  9.64055768e-07 -1.59346873e-06
  4.21993161e-10 -3.41099648e-09  9.47920339e-06 -1.13744463e-08
  3.50753405e-07 -3.66788156e-07 -8.65402992e-07 -8.79142722e-07
  2.06163207e-07 -2.75947893e-07  4.45031959e-07  3.80304161e-06
 -2.07186975e-07 -6.82291164e-07  1.85210276e-08 -5.47261635e-06
 -1.20913469e-07 -4.31418799e-06  2.49787398e-06  2.58566957e-07
  2.43182301e-06 -9.17783251e-08]
y_best: -7.018782305855657

Published by

风君子

独自遨游何稽首 揭天掀地慰生平