Source code for mealpy.human_based.AFT

#!/usr/bin/env python
# Created by "Thieu" at 22:47, 15/08/2025 ----------%                                                                               
#       Email: nguyenthieu2102@gmail.com            %                                                    
#       Github: https://github.com/thieu1995        %                         
# --------------------------------------------------%

import numpy as np
from mealpy.optimizer import Optimizer
from mealpy.utils.opt_info import OptInfo


[docs]class OriginalAFT(Optimizer): """ The original version of: Ali baba and the Forty Thieves (AFT) optimizer Parameters ---------- epoch : int Maximum number of iterations, in range [1, 100000]. Default is 10000. pop_size : int Number of population size, in range [5, 10000]. Default is 100. References ~~~~~~~~~~ 1. Braik, M., Ryalat, M. H., & Al-Zoubi, H. (2022). A novel meta-heuristic algorithm for solving numerical optimization problems: Ali Baba and the forty thieves. Neural Computing and Applications, 34(1), 409-455. https://doi.org/10.1007/s00521-021-06392-x Examples ~~~~~~~~ >>> import numpy as np >>> from mealpy import FloatVar, AFT >>> >>> def objective_function(solution): >>> return np.sum(solution**2) >>> >>> problem_dict = { >>> "bounds": FloatVar(lb=(-10.,) * 30, ub=(10.,) * 30, name="delta"), >>> "minmax": "min", >>> "obj_func": objective_function >>> } >>> >>> model = AFT.OriginalAFT(epoch=1000, pop_size=50) >>> g_best = model.solve(problem_dict) >>> print(f"Solution: {g_best.solution}, Fitness: {g_best.target.fitness}") >>> print(f"Solution: {model.g_best.solution}, Fitness: {model.g_best.target.fitness}") """ OPT_INFO = OptInfo(name="Ali baba and the Forty Thieves", year=2022, difficulty="easy", kind="original") def __init__(self, epoch: int = 10000, pop_size: int = 100, **kwargs: object) -> None: super().__init__(**kwargs) self.epoch = self.validator.check_int("epoch", epoch, [1, 100000]) self.pop_size = self.validator.check_int("pop_size", pop_size, [5, 10000]) self.set_parameters(["epoch", "pop_size"]) self.sort_flag = False
[docs] def before_main_loop(self): # Initialize best positions (Marjaneh's astute plans) self.pop_best = self.pop.copy() # It is like local best positions like in PSO
# self.pop is population of alibaba ==> It will always update with new version no matter what
[docs] def evolve(self, epoch): """ The main operations (equations) of algorithm. Inherit from Optimizer class Args: epoch (int): The current iteration """ # Calculate AFT parameters # Perception potential - decreases over iterations Pp = 0.1 * np.log(2.75 * (epoch/ self.epoch) ** 0.1) # Tracking distance - decreases over iterations Td = 2 * np.exp(-2 * (epoch / self.epoch) ** 2) # Generate random candidate followers indices random_followers = self.generator.integers(0, self.pop_size, size=self.pop_size) # Update positions for each thief for idx in range(self.pop_size): if self.generator.random() >= 0.5: # Thieves know where to search (TRUE case) if self.generator.random() > Pp: # Case 1: Follow global best with tracking distance direction = np.sign(self.generator.random() - 0.5) movement = (Td * (self.pop_best[idx].solution - self.pop[idx].solution) * self.generator.random() + Td * (self.pop[idx].solution - self.pop_best[random_followers[idx]].solution) * self.generator.random()) pos_new = self.g_best.solution + movement * direction else: # Case 3: Random exploration within tracking distance pos_new = self.problem.lb + Td * (self.problem.ub - self.problem.lb) * self.generator.random(self.problem.n_dims) else: # Thieves don't know where to search - opposite direction (Marjaneh's tricks) direction = np.sign(self.generator.random() - 0.5) movement = (Td * (self.pop_best[idx].solution - self.pop[idx].solution) * self.generator.random() + Td * (self.pop[idx].solution - self.pop_best[random_followers[idx]].solution) * self.generator.random()) pos_new = self.g_best.solution - movement * direction # Clip to bounds pos_new = self.correct_solution(pos_new) agent = self.generate_empty_agent(pos_new) self.pop[idx] = agent # self.pop_baba[idx] = agent if self.mode not in self.AVAILABLE_MODES: # self.pop_baba[idx].target = self.get_target(pos_new) self.pop[idx].target = self.get_target(pos_new) if self.mode in self.AVAILABLE_MODES: self.pop = self.update_target_for_population(self.pop) self.pop_best = self.greedy_selection_population(self.pop_best, self.pop, self.problem.minmax)