211 lines
7.4 KiB
Python
211 lines
7.4 KiB
Python
# -*- coding: utf-8 -*-
|
|
"""
|
|
Created on Thirsday March 21 2019
|
|
|
|
@author:
|
|
% _____________________________________________________
|
|
% Main paper:
|
|
% Harris hawks optimization: Algorithm and applications
|
|
% Ali Asghar Heidari, Seyedali Mirjalili, Hossam Faris, Ibrahim Aljarah, Majdi Mafarja, Huiling Chen
|
|
% Future Generation Computer Systems,
|
|
% DOI: https://doi.org/10.1016/j.future.2019.02.028
|
|
% _____________________________________________________
|
|
|
|
"""
|
|
import random
|
|
import numpy
|
|
import math
|
|
from .solution import solution
|
|
import time
|
|
|
|
|
|
def HHO(objf, lb, ub, dim, SearchAgents_no, Max_iter):
|
|
|
|
# dim=30
|
|
# SearchAgents_no=50
|
|
# lb=-100
|
|
# ub=100
|
|
# Max_iter=500
|
|
|
|
# initialize the location and Energy of the rabbit
|
|
Rabbit_Location = numpy.zeros(dim)
|
|
Rabbit_Energy = float("inf") # change this to -inf for maximization problems
|
|
|
|
if not isinstance(lb, list):
|
|
lb = [lb for _ in range(dim)]
|
|
ub = [ub for _ in range(dim)]
|
|
lb = numpy.asarray(lb)
|
|
ub = numpy.asarray(ub)
|
|
|
|
# Initialize the locations of Harris' hawks
|
|
X = numpy.asarray(
|
|
[x * (ub - lb) + lb for x in numpy.random.uniform(0, 1, (SearchAgents_no, dim))]
|
|
)
|
|
|
|
# Initialize convergence
|
|
convergence_curve = numpy.zeros(Max_iter)
|
|
|
|
############################
|
|
s = solution()
|
|
|
|
print('HHO is now tackling "' + objf.__name__ + '"')
|
|
|
|
timerStart = time.time()
|
|
s.startTime = time.strftime("%Y-%m-%d-%H-%M-%S")
|
|
############################
|
|
|
|
t = 0 # Loop counter
|
|
|
|
# Main loop
|
|
while t < Max_iter:
|
|
for i in range(0, SearchAgents_no):
|
|
|
|
# Check boundries
|
|
|
|
X[i, :] = numpy.clip(X[i, :], lb, ub)
|
|
|
|
# fitness of locations
|
|
fitness = objf(X[i, :])
|
|
|
|
# Update the location of Rabbit
|
|
if fitness < Rabbit_Energy: # Change this to > for maximization problem
|
|
Rabbit_Energy = fitness
|
|
Rabbit_Location = X[i, :].copy()
|
|
|
|
E1 = 2 * (1 - (t / Max_iter)) # factor to show the decreaing energy of rabbit
|
|
|
|
# Update the location of Harris' hawks
|
|
for i in range(0, SearchAgents_no):
|
|
|
|
E0 = 2 * random.random() - 1 # -1<E0<1
|
|
Escaping_Energy = E1 * (
|
|
E0
|
|
) # escaping energy of rabbit Eq. (3) in the paper
|
|
|
|
# -------- Exploration phase Eq. (1) in paper -------------------
|
|
|
|
if abs(Escaping_Energy) >= 1:
|
|
# Harris' hawks perch randomly based on 2 strategy:
|
|
q = random.random()
|
|
rand_Hawk_index = math.floor(SearchAgents_no * random.random())
|
|
X_rand = X[rand_Hawk_index, :]
|
|
if q < 0.5:
|
|
# perch based on other family members
|
|
X[i, :] = X_rand - random.random() * abs(
|
|
X_rand - 2 * random.random() * X[i, :]
|
|
)
|
|
|
|
elif q >= 0.5:
|
|
# perch on a random tall tree (random site inside group's home range)
|
|
X[i, :] = (Rabbit_Location - X.mean(0)) - random.random() * (
|
|
(ub - lb) * random.random() + lb
|
|
)
|
|
|
|
# -------- Exploitation phase -------------------
|
|
elif abs(Escaping_Energy) < 1:
|
|
# Attacking the rabbit using 4 strategies regarding the behavior of the rabbit
|
|
|
|
# phase 1: ----- surprise pounce (seven kills) ----------
|
|
# surprise pounce (seven kills): multiple, short rapid dives by different hawks
|
|
|
|
r = random.random() # probablity of each event
|
|
|
|
if (
|
|
r >= 0.5 and abs(Escaping_Energy) < 0.5
|
|
): # Hard besiege Eq. (6) in paper
|
|
X[i, :] = (Rabbit_Location) - Escaping_Energy * abs(
|
|
Rabbit_Location - X[i, :]
|
|
)
|
|
|
|
if (
|
|
r >= 0.5 and abs(Escaping_Energy) >= 0.5
|
|
): # Soft besiege Eq. (4) in paper
|
|
Jump_strength = 2 * (
|
|
1 - random.random()
|
|
) # random jump strength of the rabbit
|
|
X[i, :] = (Rabbit_Location - X[i, :]) - Escaping_Energy * abs(
|
|
Jump_strength * Rabbit_Location - X[i, :]
|
|
)
|
|
|
|
# phase 2: --------performing team rapid dives (leapfrog movements)----------
|
|
|
|
if (
|
|
r < 0.5 and abs(Escaping_Energy) >= 0.5
|
|
): # Soft besiege Eq. (10) in paper
|
|
# rabbit try to escape by many zigzag deceptive motions
|
|
Jump_strength = 2 * (1 - random.random())
|
|
X1 = Rabbit_Location - Escaping_Energy * abs(
|
|
Jump_strength * Rabbit_Location - X[i, :]
|
|
)
|
|
X1 = numpy.clip(X1, lb, ub)
|
|
|
|
if objf(X1) < fitness: # improved move?
|
|
X[i, :] = X1.copy()
|
|
else: # hawks perform levy-based short rapid dives around the rabbit
|
|
X2 = (
|
|
Rabbit_Location
|
|
- Escaping_Energy
|
|
* abs(Jump_strength * Rabbit_Location - X[i, :])
|
|
+ numpy.multiply(numpy.random.randn(dim), Levy(dim))
|
|
)
|
|
X2 = numpy.clip(X2, lb, ub)
|
|
if objf(X2) < fitness:
|
|
X[i, :] = X2.copy()
|
|
if (
|
|
r < 0.5 and abs(Escaping_Energy) < 0.5
|
|
): # Hard besiege Eq. (11) in paper
|
|
Jump_strength = 2 * (1 - random.random())
|
|
X1 = Rabbit_Location - Escaping_Energy * abs(
|
|
Jump_strength * Rabbit_Location - X.mean(0)
|
|
)
|
|
X1 = numpy.clip(X1, lb, ub)
|
|
|
|
if objf(X1) < fitness: # improved move?
|
|
X[i, :] = X1.copy()
|
|
else: # Perform levy-based short rapid dives around the rabbit
|
|
X2 = (
|
|
Rabbit_Location
|
|
- Escaping_Energy
|
|
* abs(Jump_strength * Rabbit_Location - X.mean(0))
|
|
+ numpy.multiply(numpy.random.randn(dim), Levy(dim))
|
|
)
|
|
X2 = numpy.clip(X2, lb, ub)
|
|
if objf(X2) < fitness:
|
|
X[i, :] = X2.copy()
|
|
|
|
convergence_curve[t] = Rabbit_Energy
|
|
if t % 1 == 0:
|
|
print(
|
|
[
|
|
"At iteration "
|
|
+ str(t)
|
|
+ " the best fitness is "
|
|
+ str(Rabbit_Energy)
|
|
]
|
|
)
|
|
t = t + 1
|
|
|
|
timerEnd = time.time()
|
|
s.endTime = time.strftime("%Y-%m-%d-%H-%M-%S")
|
|
s.executionTime = timerEnd - timerStart
|
|
s.convergence = convergence_curve
|
|
s.optimizer = "HHO"
|
|
s.objfname = objf.__name__
|
|
s.best = Rabbit_Energy
|
|
s.bestIndividual = Rabbit_Location
|
|
|
|
return s
|
|
|
|
|
|
def Levy(dim):
|
|
beta = 1.5
|
|
sigma = (
|
|
math.gamma(1 + beta)
|
|
* math.sin(math.pi * beta / 2)
|
|
/ (math.gamma((1 + beta) / 2) * beta * 2 ** ((beta - 1) / 2))
|
|
) ** (1 / beta)
|
|
u = 0.01 * numpy.random.randn(dim) * sigma
|
|
v = numpy.random.randn(dim)
|
|
zz = numpy.power(numpy.absolute(v), (1 / beta))
|
|
step = numpy.divide(u, zz)
|
|
return step
|