Source code for mealpy.bio_based.TSeedA

#!/usr/bin/env python
# Created by "Ahmet Tunahan Yalcin" on 28/02/2026
# Email: ytunahan7878@gmail.com
# Github: https://github.com/tunayalc
# ----------------------------------------------%

from mealpy.optimizer import Optimizer
from mealpy.utils.opt_info import OptInfo, ScientificConcern


[docs]class OriginalTSeedA(Optimizer): """ The original version: Tree-Seed Algorithm (TSeedA) Parameters ---------- epoch : int Maximum number of iterations. Default is 10000. pop_size : int Population size (number of trees). Default is 100. st : float Search tendency parameter, in range (0.0, 1.0). Default is 0.1. Danger ------ 1. Lack of Mathematical Novelty: The search equations (Eq. 3 and Eq. 4) are functionally equivalent to basic difference-based mutation operators found in classical Differential Evolution (DE) and Particle Swarm Optimization (PSO). 2. Over-Simplistic Selection: The exploration-exploitation balance is managed solely by a simple 'if-else' decision branch controlled by a single parameter (Search Tendency, ST) , which lacks the dynamic adaptation mechanisms of modern metaheuristics. 3. Low Selection Pressure: Replacing parent trees directly with marginally better seeds can lead to premature convergence, high stagnation rates, and poor performance on high-dimensional multimodal landscapes. 4. For solving high-performance or real-world industrial continuous optimization problems, users are strongly encouraged to choose more robust, mathematically sound, and modern algorithms References ---------- 1. Kiran, M. S. (2015). TSA: Tree-seed algorithm for continuous optimization. Expert Systems with Applications, 42(19), 6686-6698. https://doi.org/10.1016/j.eswa.2015.04.055 Examples -------- >>> import numpy as np >>> from mealpy import FloatVar, TSeedA >>> >>> 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 = TSeedA.OriginalTSeedA(epoch=1000, pop_size=50, st=0.1) >>> g_best = model.solve(problem_dict) >>> print(f"Solution: {g_best.solution}, Fitness: {g_best.target.fitness}") """ OPT_INFO = OptInfo(name="Tree-Seed Algorithm", year=2015, difficulty="medium", kind="original", scientific_status="questionable", concerns=( ScientificConcern.LACK_OF_NOVELTY, ScientificConcern.QUESTIONABLE_MATH, ScientificConcern.POOR_REPRODUCIBILITY, ScientificConcern.FABRICATED_RESULTS )) def __init__(self, epoch: int = 10000, pop_size: int = 100, st: float = 0.1, **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.st = self.validator.check_float("st", st, [0, 1.0]) self.set_parameters(["epoch", "pop_size", "st"]) self.sort_flag = False
[docs] def evolve(self, epoch: int) -> None: """ The main operations (equations) of algorithm. """ # Decide seed production limits (10% to 25% of population size) min_seeds = max(1, int(0.1 * self.pop_size)) max_seeds = max(2, int(0.25 * self.pop_size)) for idx in range(self.pop_size): # Decide the number of seeds produced for this tree n_seeds = self.generator.integers(min_seeds, max_seeds + 1) pop_new = [] rdx_list = self.sample_indexes_exclude_one(self.generator, self.pop_size, idx, n_samples=n_seeds, replace=True) for jdx in range(n_seeds): # Select a random tree 'r' different from 'i' rdx = rdx_list[jdx] # Create a new seed from the current tree seed = self.pop[idx].solution.copy() alpha = self.generator.uniform(-1, 1, self.problem.n_dims) # Scaling factor # Update dimensions based on Search Tendency (ST) rand_vals = self.generator.random(self.problem.n_dims) mask_eq3 = rand_vals < self.st mask_eq4 = ~mask_eq3 # Update using Eq. 3 seed[mask_eq3] = self.pop[idx].solution[mask_eq3] + alpha[mask_eq3] * (self.g_best.solution[mask_eq3] - self.pop[idx].solution[mask_eq3]) # Update using Eq. 4 seed[mask_eq4] = self.pop[idx].solution[mask_eq4] + alpha[mask_eq4] * (self.pop[idx].solution[mask_eq4] - self.pop[rdx].solution[mask_eq4]) # Boundary enforcement and create new agent pos_new = self.correct_solution(seed) # agent = self.generate_empty_agent(pos_new) pop_new.append(self.generate_empty_agent(pos_new)) if self.mode not in self.AVAILABLE_MODES: pop_new[-1].target = self.get_target(seed) # Update parallel if self.mode in self.AVAILABLE_MODES: pop_new = self.update_target_for_population(pop_new) # Update the current tree by the best seed best, _ = self.get_best_agent(pop_new, self.problem.minmax) if self.compare_target(best.target, self.pop[idx].target, self.problem.minmax): self.pop[idx] = best