Algoritmo de recocido simulado basado en la optimización de enjambres de partículas de series de algoritmos inteligentes

prefacio

  Este artículo es el cuarto artículo de la columna Algoritmo inteligente (reproducción de Python) y presenta principalmente la combinación del algoritmo de optimización de enjambre de partículas y el algoritmo de recocido simulado para compensar las deficiencias entre los respectivos algoritmos.

  En el blog anterior [Algoritmo de optimización de enjambre de partículas de la serie de algoritmos inteligentes], se introdujo el algoritmo de optimización de enjambre de partículas híbridas, como las nuevas partículas obtenidas después de actualizar las partículas, utilizando la idea de recocido simulado para decidir si aceptar el próximo iteración de generación. Sin embargo, este artículo puede considerarse como un algoritmo de optimización de enjambre de partículas híbrido. El enfoque es aplicar la optimización de enjambre de partículas al algoritmo de recocido simulado, en lugar de aplicar el algoritmo de recocido simulado al algoritmo de optimización de enjambre de partículas.

1. Combinar ideas con algoritmos

El algoritmo de recocido simulado presentado en este blog [Algoritmo de recocido simulado de la serie de algoritmos inteligentes] se puede optimizar. Por ejemplo, en la selección de la solución inicial, el valor predeterminado es seleccionar aleatoriamente una solución como solución inicial, así que surgió la   idea : Si la solución inicial es una solución óptima local y el algoritmo de recocido simulado se aplica sobre esta base, el resultado definitivamente será mejor que la solución inicial aleatoria.
  ¿Cómo elegir la solución inicial o la solución óptima local? Hay muchos algoritmos. Se pueden usar tanto el algoritmo genético como el algoritmo de optimización de enjambre de partículas presentado anteriormente. Este artículo utiliza la optimización de enjambre de partículas para seleccionar la solución inicial.

  En el futuro, también actualizaremos el uso del algoritmo genético para seleccionar la solución inicial en este artículo, pero no planeamos actualizar el artículo de este algoritmo. Para más detalles, puede consultar el código de la biblioteca IALib .

  Como se mencionó anteriormente, este artículo no aplica el algoritmo de recocido simulado en cada generación (en este caso, es un enjambre de partículas mixtas), sino así:

inserte la descripción de la imagen aquí

2. Escenario del problema

  Todavía es el problema de mayor valor, pero el problema de mayor valor de la función unaria original se reemplaza por el problema de mayor valor de la función binaria [la complejidad no ha aumentado mucho, principalmente por la conveniencia de la visualización]. En esta ocasión, se resuelve el valor máximo de las tres funciones clásicas:

2.1 Esfera

f ( x , y ) = x 2 + y 2 f(x, y) = x^2 + y^2f ( x ,y )=X2+y2

inserte la descripción de la imagen aquí

2.2 azul cielo

f ( x , y ) = ( x 2 + y − 11 ) 2 + ( x + y 2 − 7 ) 2 f(x, y) = (x^2 + y - 11)^2 + (x + y^ 2 - 7)^2f ( x ,y )=( X2+y11 )2+( X+y27 )2

inserte la descripción de la imagen aquí

2.3 Ackley

f ( x , y ) = − a ∗ exp [ − bx 2 + y 2 2 ] − exp [ cos ( cx ) + cos ( cy ) 2 ] + a + ef(x, y) = -a * exp\bigg [{ -b\sqrt{\frac {x^2 + y^2} {2}} }\bigg] -exp\bigg[ \frac {cos(cx) + cos(cy)} {2} \bigg] + un + mif ( x ,y )=unmi X pags [ - segundo2X2+y2 ]e x p [2porque ( c x )+cos ( cy )]+a+donde a = 20 , b = 0.2 , c = 2 π , e = 2.71282 a=20, b=0.2, c=2\pi, e=  2.71282a=20 ,b=0.2 ,C=2 pags ,mi=2.71282 .

inserte la descripción de la imagen aquí

2.4 Visualización de funciones

# -*- coding:utf-8 -*-
# Author:   xiayouran
# Email:    [email protected]
# Datetime: 2023/3/30 14:22
# Filename: visu_func.py
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D


class Visu3DFunc(object):
    def __init__(self, func_name='Sphere'):
        self.func_name = func_name
        self.X = np.linspace(-5, 5, num=200)
        self.Y = np.linspace(-5, 5, num=200)

    @classmethod
    def sphere(cls, x, y):
        """Sphere"""
        return x**2 + y**2

    @classmethod
    def himmelblau(cls, x, y):
        """Himmelblau"""
        return (x**2 + y - 11)**2 + (x + y**2 - 7)**2

    @classmethod
    def ackley(cls, x, y, a=20, b=0.2, c=2*np.pi):
        """Ackley"""
        term1 = -a * np.exp(-b * np.sqrt((x**2 + y**2)/2))
        term2 = -np.exp((np.cos(c*x) + np.cos(c*y))/2)
        return term1 + term2 + a + np.exp(1)

    def draw(self):
        fig = plt.figure()
        # ax = fig.gca(projection='3d')
        ax = Axes3D(fig)
        X, Y = np.meshgrid(self.X, self.Y)

        if self.func_name == 'Sphere':
            Z = self.sphere(X, Y)
        elif self.func_name == 'Himmelblau':
            Z = self.himmelblau(X, Y)
        else:
            Z = self.ackley(X, Y)

        ax.plot_surface(X, Y, Z, cmap=plt.cm.cool)
        ax.contour(X, Y, Z, levels=5, offset=0)
        ax.set_xlabel('X')
        ax.set_ylabel('Y')
        ax.set_zlabel('Z')
        ax.set_title('{} Function'.format(self.func_name))
        # ax.scatter3D(0, 0, self.sphere(0, 0), s=100, lw=0, c='green', alpha=0.7)
        plt.savefig(self.func_name)

        plt.show()


if __name__ == '__main__':
    # Sphere, Himmelblau, Ackley
    visu_obj = Visu3DFunc(func_name='Sphere')
    visu_obj.draw()

3. Implementación del algoritmo

# -*- coding:utf-8 -*-
# Author:   xiayouran
# Email:    [email protected]
# Datetime: 2023/3/30 15:50
# Filename: pso_saa.py
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D

from IALib.base_algorithm import BaseAlgorithm
from IALib.particle_swarm_optimization import ParticleSwarmOptimization, Particle
from IALib.simulate_anneal_algorithm import SimulateAnnealAlgorithm
from IALib.mixup.visu_func import Visu3DFunc


__all__ = ['PSO_SAA']


class PSO_SAA(BaseAlgorithm):
    def __init__(self, population_size=100, p_dim=1, v_dim=1, max_iter=500, x_range=(0, 5),
                 t_max=1.0, t_min=1e-3, coldrate=0.9, seed=10086):
        super(PSO_SAA, self).__init__()
        self.__population_size = population_size  # 种群大小
        self.__p_dim = p_dim        # 粒子位置维度
        self.__v_dim = v_dim        # 粒子速度维度
        self.__max_iter = max_iter  # 最大迭代次数
        self.__t_max = t_max  # 初始温度
        self.__t_min = t_min  # 终止温度
        self.__coldrate = coldrate  # 降温速率
        self.saa_best_particle = None   # 模拟退火算法得到的最优解
        self.best_particle = None       # 最优解
        self.__x_range = x_range
        self.__seed = seed
        self.optimal_solution = None

        np.random.seed(self.__seed)

    def problem_function(self, x):
        if self.__p_dim == 1:
            return super().problem_function(x)
        else:
            return Visu3DFunc.sphere(*x)

    def solution(self):
        # PSO
        algo_pso = ParticleSwarmOptimization(population_size=self.__population_size,
                                             p_dim=self.__p_dim, v_dim=self.__v_dim,
                                             max_iter=self.__max_iter, x_range=self.__x_range)
        algo_pso.solution()

        # SAA
        x = algo_pso.global_best_particle.best_position   # 初始解
        while self.__t_max > self.__t_min:
            for _ in range(self.__max_iter):
                x_new = np.clip(x + np.random.randn(), a_min=self.__x_range[0], a_max=self.__x_range[1])
                delta = self.problem_function(x_new) - self.problem_function(x)  # 计算目标函数的值差
                if delta < 0:  # 局部最优解
                    x = x_new   # 直接接受更优解
                else:
                    p = np.exp(-delta / self.__t_max)  # 粒子在温度T时趋于平衡的概率为exp[-ΔE/(kT)]
                    r = np.random.uniform(0, 1)
                    if p > r:  # 以一定概率来接受最优解
                        x = x_new
            self.__t_max *= self.__coldrate

        # optimal solution
        saa_best_particle = Particle()
        saa_best_particle.position = x
        saa_best_particle.best_position = x
        saa_best_particle.fitness = self.problem_function(x)
        self.saa_best_particle = saa_best_particle

        if saa_best_particle.fitness < algo_pso.global_best_particle.fitness:
            self.best_particle = saa_best_particle
        else:
            self.best_particle = algo_pso.global_best_particle

        self.optimal_solution = (self.parse_format(self.best_particle.position),
                                 self.parse_format(self.best_particle.fitness))
        print('the optimal solution is', self.optimal_solution)
        # print('optimal solution:\nposition: {} \nfitness: {}'.format(self.best_particle.best_position,
        #                                                              self.best_particle.fitness))

    def draw(self):
        # PSO
        algo_pso = ParticleSwarmOptimization(population_size=self.__population_size,
                                             p_dim=self.__p_dim, v_dim=self.__v_dim,
                                             max_iter=self.__max_iter, x_range=self.__x_range)
        algo_pso.draw(mixup=True)
        plt.clf()
        x = np.linspace(*self.__x_range, 200)
        plt.plot(x, self.problem_function(x))

        # SAA
        x = algo_pso.global_best_particle.best_position   # 初始解
        while self.__t_max > self.__t_min:
            for _ in range(self.__max_iter):
                # something about plotting
                if 'sca' in globals() or 'sca' in locals():
                    sca.remove()
                sca = plt.scatter(x, self.problem_function(x), s=100, lw=0, c='red', alpha=0.5)
                plt.pause(0.01)

                x_new = np.clip(x + np.random.randn(), a_min=self.__x_range[0], a_max=self.__x_range[1])
                delta = self.problem_function(x_new) - self.problem_function(x)  # 计算目标函数的值差
                if delta < 0:  # 局部最优解
                    x = x_new   # 直接接受更优解
                else:
                    p = np.exp(-delta / self.__t_max)  # 粒子在温度T时趋于平衡的概率为exp[-ΔE/(kT)]
                    r = np.random.uniform(0, 1)
                    if p > r:  # 以一定概率来接受最优解
                        x = x_new
            self.__t_max *= self.__coldrate

        # optimal solution
        saa_best_particle = Particle()
        saa_best_particle.position = x
        saa_best_particle.best_position = x
        saa_best_particle.fitness = self.problem_function(x)
        self.saa_best_particle = saa_best_particle

        if saa_best_particle.fitness < algo_pso.global_best_particle.fitness:
            self.best_particle = saa_best_particle
        else:
            self.best_particle = algo_pso.global_best_particle

        plt.scatter(self.best_particle.best_position, self.best_particle.fitness, s=100, lw=0, c='green', alpha=0.7)
        plt.ioff()
        plt.show()

        self.optimal_solution = (self.parse_format(self.best_particle.position),
                                 self.parse_format(self.best_particle.fitness))
        print('the optimal solution is', self.optimal_solution)
        # print('optimal solution:\nposition: {} \nfitness: {}'.format(self.best_particle.best_position,
        #                                                              self.best_particle.fitness))

    def draw3D(self):
        # PSO
        algo_pso = ParticleSwarmOptimization(population_size=self.__population_size,
                                             p_dim=self.__p_dim, v_dim=self.__v_dim,
                                             max_iter=self.__max_iter, x_range=self.__x_range)
        algo_pso.draw3D(mixup=True)
        plt.clf()
        ax = Axes3D(algo_pso.fig)
        x_ = np.linspace(*self.__x_range, num=200)
        X, Y = np.meshgrid(x_, x_)
        Z = self.problem_function([X, Y])
        ax.plot_surface(X, Y, Z, cmap=plt.cm.cool)
        ax.contour(X, Y, Z, levels=5, offset=0)
        ax.set_xlabel('X')
        ax.set_ylabel('Y')
        ax.set_zlabel('Z')

        # SAA
        x = algo_pso.global_best_particle.best_position   # 初始解
        while self.__t_max > self.__t_min:
            for _ in range(self.__max_iter):
                # something about plotting
                if 'sca' in globals() or 'sca' in locals():
                    sca.remove()
                sca = ax.scatter3D(*x, self.problem_function(x), s=100, lw=0, c='red', alpha=0.5)
                plt.pause(0.01)

                x_new = np.clip(x + np.random.randn(), a_min=self.__x_range[0], a_max=self.__x_range[1])
                delta = self.problem_function(x_new) - self.problem_function(x)  # 计算目标函数的值差
                if delta < 0:  # 局部最优解
                    x = x_new   # 直接接受更优解
                else:
                    p = np.exp(-delta / self.__t_max)  # 粒子在温度T时趋于平衡的概率为exp[-ΔE/(kT)]
                    r = np.random.uniform(0, 1)
                    if p > r:  # 以一定概率来接受最优解
                        x = x_new
            self.__t_max *= self.__coldrate

        # optimal solution
        saa_best_particle = Particle()
        saa_best_particle.position = x
        saa_best_particle.best_position = x
        saa_best_particle.fitness = self.problem_function(x)
        self.saa_best_particle = saa_best_particle

        if saa_best_particle.fitness < algo_pso.global_best_particle.fitness:
            self.best_particle = saa_best_particle
        else:
            self.best_particle = algo_pso.global_best_particle

        ax.scatter3D(*self.best_particle.best_position, self.best_particle.fitness, s=100, lw=0, c='green', alpha=0.7)
        plt.ioff()
        plt.show()

        self.optimal_solution = (self.parse_format(self.best_particle.position),
                                 self.parse_format(self.best_particle.fitness))
        print('the optimal solution is', self.optimal_solution)
        # print('optimal solution:\nposition: {} \nfitness: {}'.format(self.best_particle.best_position,
        #                                                              self.best_particle.fitness))


if __name__ == '__main__':
    algo = PSO_SAA()
    # algo.draw()
    algo.draw3D()

Repositorio de código: IALib[GitHub]

  El código de este artículo se ha sincronizado con Pythonel almacén exclusivo de la columna [Algoritmo inteligente (Recurrencia)]: Algoritmos en la biblioteca   de tiempo de ejecución de IALib :
IALibPSO-SAA

git clone [email protected]:xiayouran/IALib.git
cd examples
python main.py -algo pso_saa		# 2D visu
python main_pro.py -algo pso_saa	# 3D visu

Supongo que te gusta

Origin blog.csdn.net/qq_42730750/article/details/130451914
Recomendado
Clasificación