Directorio de artículos
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í:
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
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+y−11 )2+( X+y2−7 )2
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 )=− un∗mi 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 .
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 Python
el almacén exclusivo de la columna [Algoritmo inteligente (Recurrencia)]: Algoritmos en la biblioteca de tiempo de ejecución de IALib :IALib
PSO-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