#!/usr/bin/env python3 import time import random class Particle: def __init__(self, x, y, z): self.Pbest_x = 0 self.Pbest_y = 0 self.Pbest_z = 0 self.x = x self.y = y self.z = z self.x_k1 = 0 self.y_k1 = 0 self.z_k1 = 0 self.V_x = 0 self.V_y = 0 self.V_z = 0 self.V_xk1 = 0 self.V_yk1 = 0 self.V_zk1 = 0 def __repr__(self): return ( "{x: %s , y: %s, z: %s, Pbest_x: %s, Pbest_y: %s, Pbest_z: %s}\n" % ( self.x, self.y, self.z, self.Pbest_x, self.Pbest_y, self.Pbest_z, ) ) def __str__(self): return ( "{x: %s , y: %s, z: %s, Pbest_x: %s, Pbest_y: %s, Pbest_z: %s}\n" % ( self.x, self.y, self.z, self.Pbest_x, self.Pbest_y, self.Pbest_z, ) ) def update_X(self): self.x = self.x + self.V_xk1 self.y = self.y + self.V_yk1 self.z = self.z + self.V_zk1 def update_V(self, w, c1, c2, Gbest_x, Gbest_y, Gbest_z): rand1 = random.random() rand2 = random.random() self.V_xk1 = ( w * self.V_x + c1 * rand1 * (self.Pbest_x - self.x) + c2 * rand2 * (Gbest_x - self.x) ) self.V_yk1 = ( w * self.V_y + c1 * rand1 * (self.Pbest_y - self.y) + c2 * rand2 * (Gbest_y - self.y) ) self.V_zk1 = ( w * self.V_z + c1 * rand1 * (self.Pbest_z - self.z) + c2 * rand2 * (Gbest_z - self.z) ) def update_Pbest(self, x, y, z: float): self.Pbest_x = x self.Pbest_y = y self.Pbest_z = z def doRound(self, w, c1, c2, Gbest_x, Gbest_y, Gbest_z, fitness): fitness_x = fitness(self.x, self.y, self.z) self.update_V(w, c1, c2, Gbest_x, Gbest_y, Gbest_z) self.update_X() if abs(fitness(self.Pbest_x, self.Pbest_y, self.Pbest_z)) > abs( fitness_x ): self.update_Pbest(self.x, self.y, self.z) class PSO: def __init__(self, w, c1, c2, particle_count): self.Gbest_x = 0 self.Gbest_y = 0 self.Gbest_z = 0 self.particle_count = particle_count self.Particles = self.factory() self.w = w self.c1 = c1 self.c2 = c2 def factory(self): result = list() for _ in range(1, self.particle_count): x = ( random.random() * 10 if random.random() > 0.5 else -random.random() * 10 ) y = ( random.random() * 10 if random.random() > 0.5 else -random.random() * 10 ) z = ( random.random() * 10 if random.random() > 0.5 else -random.random() * 10 ) result.append(Particle(x, y, z)) return result def fitness(self, x, y, z: float): return ( (x ** 5) - ((x ** 2) * y * z) + (z * x) + (y ** 2) - (z ** 3) - 10 ) def doRround(self): roundBest_x = float() roundBest_y = float() roundBest_z = float() for particle in self.Particles: if abs(self.fitness(roundBest_x, roundBest_y, roundBest_z)) > abs( self.fitness(particle.x, particle.y, particle.z) ): roundBest_x = particle.x roundBest_y = particle.y roundBest_z = particle.z self.Gbest_x = roundBest_x self.Gbest_y = roundBest_y self.Gbest_z = roundBest_z for particle in self.Particles: particle.doRound( self.w, self.c1, self.c2, self.Gbest_x, self.Gbest_y, self.Gbest_z, self.fitness, ) def printGlobalBest(self): print( "x: %s, y: %s, z: %s, fitness: %s" % ( self.Gbest_x, self.Gbest_y, self.Gbest_z, self.fitness(self.Gbest_x, self.Gbest_y, self.Gbest_z), ), ) def main(): random.seed(time.time()) round_count = 10 pso = PSO(5, 1.5, 1.5, 50) for _ in range(1, round_count): pso.doRround() pso.printGlobalBest() if __name__ == "__main__": main()