Sunday, March 12, 2023

A simple OOP example of 3D-FOA by Python

 """

A simple OOP example of 3D-FOA by Python to find the min value of QF 

Author: Wei-Yuan Lin

Soochow University, Taipei

Taiwan

Ver.3

In this version, there are two classes - Fly and FOA.

The Fly class represents each individual fly in the swarm

This code implements the Fruitfly  Optimization Algorithm (FOA) to optimize a function called "smell". FOA is a nature-inspired algorithm that mimics the behavior of fruit fly to find the optimal solution. The "smell" function is defined in the Fly class, and it is calculated based on the distance of the fly from the origin. The optimization process involves moving the flies randomly and calculating the new value of the "smell" function. The best fly is chosen based on the minimum value of the "smell" function. The FOA is run for a certain number of generations, and the results are plotted in 2D and 3D.


The code defines two classes: Fly and FOA. The Fly class represents a fruit fly, and it has the following attributes:

* x: the x-coordinate of the fruit fly

* y: the y-coordinate of the fruit fly

* z: the z-coordinate of the fruit fly

* smell: the value of the "smell" function for the fruit fly

The class also has three methods:

* calculate_smell(): calculates the value of the "smell" function for the fruit fly based on its coordinates.

* move(): moves the fruit fly randomly in 3D space.

* lt(): a comparison operator that is used to compare two flies based on their "smell" value. This is used to determine the best fly.


The FOA class represents the optimization process, and it has the following attributes:


* population: the number of flies in the population

* generations: the number of generations to run the optimization

* fly_list: a list of Fly objects representing the population of flies

* best_fly: the Fly object with the minimum "smell" value

* xlist, ylist, zlist, value: lists that store the x, y, z coordinates and "smell" values of the best fly at each generation


The class also has four methods:

* initialize_population(): creates the initial population of flies and calculates their "smell" values.

* optimize(): runs the optimization process for a certain number of generations.

* plot_results(): plots the results in 2D and 3D.

The main function creates an instance of the FOA class with a population of 100 flies and 100 generations. It then initializes the population and runs the optimization process. Finally, it plots the results using the plot_results() method.

"""

# Step 1 import required libraries

import numpy as np

import matplotlib.pyplot as plt

from mpl_toolkits.mplot3d import Axes3D


# Step 2 define the class- Fly

class Fly:

    def __init__(self, x, y, z):

        self.x = x

        self.y = y

        self.z = z

        self.smell = None


    def calculate_smell(self):

        S = 1 / np.sqrt(self.x ** 2 + self.y ** 2 + self.z ** 2)

        self.smell = -7 + S ** 2


    def move(self):

        self.x += 2 * np.random.rand() - 1

        self.y += 2 * np.random.rand() - 1

        self.z += 2 * np.random.rand() - 1


    def __lt__(self, other):

        return self.smell < other.smell


# Step 3 define the class- FOA.

class FOA:

    def __init__(self, population, generations):

        self.population = population

        self.generations = generations

        self.fly_list = []

        self.best_fly = None

        self.xlist, self.ylist, self.zlist, self.smell_list = [][][][]


    def initialize_population(self):

        for _ in range(self.population):

            fly = Fly(10 * np.random.rand(), 10 * np.random.rand(), 10 * np.random.rand())

            fly.calculate_smell()

            self.fly_list.append(fly)

        self.best_fly = min(self.fly_list)


    def optimize(self):

        for i in range(self.generations):

            for fly in self.fly_list:

                fly.move()

                fly.calculate_smell()

                if fly < self.best_fly:

                    self.best_fly = fly

                    self.xlist.append(fly.x)

                    self.ylist.append(fly.y)

                    self.zlist.append(fly.z)

                    self.smell_list.append(fly.smell)


    # Step 4 plot the graphs

    def plot_results(self):

        fig, ax = plt.subplots(1, 3, figsize=(12, 4))


        plt.subplot(1, 3, 1)

        plt.plot(range(1, len(self.smell_list) + 1), self.smell_list, '*', color='blue')

        plt.xlabel('Gen')

        plt.title('Min f(S)=-7+S**2', fontsize=14)

        plt.ylabel('Best Value', fontsize=10)

        plt.grid(linestyle='--')


        plt.subplot(1, 3, 2)

        plt.plot(self.xlist, self.ylist, '*', color='black')

        plt.title('2D-Route of Best Fly', fontsize=14)

        plt.xlabel('X Axis', fontsize=12)

        plt.ylabel('Y Axis', fontsize=12)

        plt.grid(linestyle='--')


        plt.subplot(1, 3, 3, projection='3d')

        plt.plot(self.xlist, self.ylist, self.zlist, '*', color='green')

        plt.title("3D-Route of Best Fly", fontsize=14)

        plt.xlabel('X Axis', fontsize=12)

        plt.ylabel('Y Axis', fontsize=12)

        plt.gca().set_zlabel("Z Axis")

        plt.grid(linestyle='--')


        plt.show()

        fig.savefig("3dFOA.png")

        print("best value for gen : ", self.best_fly.smell)



# Main program

if __name__ == '__main__':

    foa = FOA(population=500, generations=100)

    foa.initialize_population()

    foa.optimize()  # added the optimize method call

    foa.plot_results()



The main changes in the code include adding self.smell_list to store the smell of the best fly in each generation and calling the optimize() method in the main program. Additionally, the plot() method was corrected to plot self.smell_list instead of self.smell, which was not defined in the FOA class.


未知.png

best value for gen :  -6.9989065313201735




Wednesday, March 1, 2023

 The  FOA with constraints program generated by ChatGPT


import random

import numpy as np


# Define the optimization problem with constraints

def objective_function(x):

    # objective function: x1^2 + x2^2 + x3^2

    # constraint: 2*x1 + 3*x2 + 4*x3 <= 5

    f = x[0]**2 + x[1]**2 + x[2]**2

    g = 2*x[0] + 3*x[1] + 4*x[2] - 5

    if g > 0:

        # if constraint violated, add a penalty to the objective function

        f += g**2

    return f


# Define the FOA algorithm

def foa(n, lb, ub, max_iter):

    # n: number of fruit flies (solutions)

    # lb: lower bound of decision variables

    # ub: upper bound of decision variables

    # max_iter: maximum number of iterations

    

    # Initialize the positions of the fruit flies

    positions = np.zeros((n, 3))

    for i in range(n):

        positions[i] = [random.uniform(lb[0], ub[0]), 

                        random.uniform(lb[1], ub[1]), 

                        random.uniform(lb[2], ub[2])]

    

    # Evaluate the objective function at the initial positions

    fitness = np.zeros(n)

    for i in range(n):

        fitness[i] = objective_function(positions[i])

    

    # Initialize the best solution and its fitness value

    best_fitness = np.min(fitness)

    best_solution = positions[np.argmin(fitness)]

    

    # Main loop of the FOA algorithm

    for t in range(max_iter):

        # Compute the distance between each pair of fruit flies

        distances = np.zeros((n, n))

        for i in range(n):

            for j in range(n):

                distances[i][j] = np.linalg.norm(positions[i] - positions[j])

        

        # Compute the attraction and repulsion forces between each pair of fruit flies

        forces = np.zeros((n, 3))

        for i in range(n):

            for j in range(n):

                if i != j:

                    if fitness[j] < fitness[i]:

                        f = fitness[j] / (distances[i][j] + 1e-10)

                        forces[i] += f * (positions[j] - positions[i])

                    else:

                        f = fitness[i] / (distances[i][j] + 1e-10)

                        forces[i] -= f * (positions[j] - positions[i])

        

        # Compute the new positions of the fruit flies

        new_positions = np.zeros((n, 3))

        for i in range(n):

            new_positions[i] = positions[i] + forces[i]

            # Apply boundary constraints

            new_positions[i] = np.clip(new_positions[i], lb, ub)

        

        # Evaluate the objective function at the new positions

        new_fitness = np.zeros(n)

        for i in range(n):

            new_fitness[i] = objective_function(new_positions[i])

        

        # Update the best solution and its fitness value

        if np.min(new_fitness) < best_fitness:

            best_fitness = np.min(new_fitness)

            best_solution = new_positions[np.argmin(new_fitness)]

        

        # Update the positions and fitness values of the fruit flies

        positions = new_positions

        fitness = new_fitness


    

    return best_solution, best_fitness


# Test the FOA algorithm with the given problem and constraints


best_solution, best_fitness = foa(100, [-5,-5,-5][5,5,5], 1000)

print(f"best_solution: {best_solution}")

print(f"best_fitness: {best_fitness}")


"""

Output:


best_solution: [ 0.49919158  0.12151386 -0.61439392]

best_fitness: 0.6414377366696835


"""





Thursday, October 18, 2018

A simple example of 3D-FOA by Python

##A simple example of 3D-FOA by Python
# Find the min value of QF by FOA

"""
author: Wei-Yuan Lin
Soochow University, Taipei
Taiwan
Ver.2
"""

import numpy as np
import matplotlib.pyplot as plt

Population = 100
Gen = 100
def initParams(bestX,bestY,bestZ,Population):
    location = []
    fitness = []
    for num in range(Population):
        x,y,z= bestX+2*np.random.rand()-1,bestY+2*np.random.rand()-1,bestZ+2*np.random.rand()-1
        S = 1/np.sqrt(x**2+y**2+z**2)
        smell = -7+S**2
        location.append((x,y,z))
        fitness.append(smell)
   
    bestIndex = np.argmin(fitness)
    bestX,bestY,bestZ = location[bestIndex]
    bestSmell = fitness[bestIndex]
    return bestX,bestY,bestZ,bestSmell
bestX,bestY,bestZ,bestSmell = initParams(10*np.random.rand(),10*np.random.rand(),10*np.random.rand(),Population)
xlist,ylist,zlist,value = [],[],[],[]
for time in range(Gen):
    tmpX,tmpY,tmpZ,tmpSmell = initParams(bestX,bestY,bestZ,Population)
    if tmpSmell < bestSmell:
        bestX = tmpX
        bestY = tmpY
        bestZ = tmpZ
        bestSmell = tmpSmell
        xlist.append(bestX)
        ylist.append(bestY)
        zlist.append(bestZ)
        value.append(bestSmell)
# fig,ax
fig,ax = plt.subplots(1,2,figsize=(12,4))
       
plt.subplot(1, 3, 1)
plt.plot(range(1,Gen+1),value,'*',color='blue')
plt.xlabel('Gen')
plt.title('Min f(S)=-7+S**2',fontsize=16)
plt.ylabel('Best Value',fontsize=10)
plt.grid(linestyle='--')

plt.subplot(1, 3, 2)
plt.plot(xlist,ylist,'*',color='black')
plt.title('2D-Route of Best Fly',fontsize=16)
plt.xlabel('X Axis',fontsize=12)
plt.ylabel('Y Axis',fontsize=12)
plt.grid(linestyle='--')

# plt.subplot(1, 3, 3)
# add 3-D Graph
fig = plt.figure()
ax = fig.gca(projection='3d')
ax.plot(xlist,ylist,zlist,'*')
ax.set_title("3D-Route of Best Fly",fontsize=16)
# plt.title('3D-Route of Best Fly',fontsize=16)
ax.set_xlabel("X Axis")
ax.set_ylabel("Y Axis")
ax.set_zlabel("Z Axis")
# ax.xlabel('X',fontsize=12)
# plt.ylabel('Y',fontsize=12)
# plt.zlabel('Z',fontsize=12)
plt.show()
fig.savefig("3dFOA.png")