aboutsummaryrefslogblamecommitdiffstats
path: root/PSO.py
blob: 0d019cd608407dd3f1f6146ff95c15a72985704c (plain) (tree)












































































































































































                                                                              
#!/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()