Source code for HMB.MetaheuristicsHelper

import numpy as np


[docs] def MantaRayForagingOptimizer( X, # Current population of candidate solutions. Fs, # Fitness values for each candidate in X. Ps, # Population size. D, # Number of dimensions. lb, # Lower bounds for each dimension. ub, # Upper bounds for each dimension. t, # Current iteration number. T, # Total number of iterations. fitnessFunction=None, # Function to evaluate fitness of a candidate. spiral=True, # Whether to use spiral foraging phase. spiralConstant=2.0, # Spiral constant for spiral foraging phase. explorationProb=0.5, # Probability of exploration phase. customUpdate=None, # Optional custom update function for candidates. ): r''' Perform one iteration of the Manta Ray Foraging Optimization (MRFO) algorithm with dynamic options. Parameters: X (numpy.ndarray): Current population of candidate solutions (shape: [Ps, D]). Fs (list or numpy.ndarray): Fitness values for each candidate in X. Ps (int): Population size. D (int): Number of dimensions. lb (numpy.ndarray): Lower bounds for each dimension. ub (numpy.ndarray): Upper bounds for each dimension. t (int): Current iteration number. T (int): Total number of iterations. fitnessFunction (callable): Function to evaluate fitness of a candidate. spiral (bool, optional): Whether to use spiral foraging phase. Default is True. spiralConstant (float, optional): Spiral constant for spiral foraging phase. Default is 2.0. explorationProb (float, optional): Probability of exploration phase. Default is 0.5. customUpdate (callable, optional): Custom update function with signature (i, X, newX, bestSolution, r, alpha, beta, coef, lb, ub, D, t, T) -> np.ndarray. Returns: tuple: (newX, bestSolution, bestFitness) - newX (numpy.ndarray): Updated population after this iteration. - bestSolution (numpy.ndarray): Best solution found so far. - bestFitness (float): Fitness value of the best solution. ''' # Set initial best solution, fitness, and index. bestSolution, bestFitness, bestIndex = X[0], Fs[0], 0 # Copy current population. newX = np.copy(X) # Calculate coefficient for current iteration. coef = t / float(T) # Iterate over each candidate in the population. for i in range(0, Ps): # Generate random number for exploration/exploitation. r = np.random.random(1) # Calculate alpha parameter. alpha = 2.0 * r * np.sqrt(np.abs(np.log(r))) # Generate another random number for beta calculation. r1 = np.random.random(1) # Calculate factor for beta. factor = (T - t + 1.0) / (T * 1.0) # Calculate beta parameter. beta = 2.0 * np.exp(r1 * factor) * np.sin(2.0 * np.pi * r1) # Use custom update function if provided. if (customUpdate is not None): # Call the custom update function for candidate i. newX[i, :] = customUpdate( i, X, newX, bestSolution, r, alpha, beta, coef, lb, ub, D, t, T ) else: # Decide update strategy based on exploration probability. if (np.random.random(1) < explorationProb): # Exploration phase. if (coef < np.random.random(1)): # Generate random solution within bounds. low, high = 0, 1 s = np.subtract(ub, lb) u = np.random.uniform(low=low, high=high, size=D) m = np.multiply(u, s) xRand = np.clip(np.add(lb, m), lb, ub) # Update candidate based on random solution. if (i == 0): newX[i, :] = xRand + r * (xRand - X[i, :]) + beta * (xRand - X[i, :]) else: newX[i, :] = xRand + r * (X[i - 1, :] - X[i, :]) + beta * (xRand - X[i, :]) else: # Update candidate based on best solution. if (i == 0): newX[i, :] = bestSolution + r * (bestSolution - X[i, :]) + beta * (bestSolution - X[i, :]) else: newX[i, :] = bestSolution + r * (X[i - 1, :] - X[i, :]) + beta * (bestSolution - X[i, :]) else: # Exploitation phase. if (i == 0): newX[i, :] = X[i, :] + r * (bestSolution - X[i, :]) + alpha * (bestSolution - X[i, :]) else: newX[i, :] = X[i, :] + r * (X[i - 1, :] - X[i, :]) + alpha * (bestSolution - X[i, :]) # Ensure candidate is within bounds. newX[i, :] = np.clip(newX[i, :], lb, ub) # Evaluate fitness of updated candidate. currentScore = fitnessFunction(newX[i, :]) # Update the best solution if improved. if (currentScore < bestFitness): bestSolution, bestFitness = newX[i, :].copy(), currentScore # Spiral foraging phase if enabled. if (spiral): r2, r3 = np.random.random(1), np.random.random(1) newX[i, :] = X[i, :] + spiralConstant * (r2 * bestSolution - r3 * X[i, :]) # Ensure candidate is within bounds after spiral update. newX[i, :] = np.clip(newX[i, :], lb, ub) # Evaluate fitness after spiral update. currentScore = fitnessFunction(newX[i, :]) # Update the best solution if improved. if (currentScore < bestFitness): bestSolution, bestFitness = newX[i, :].copy(), currentScore # Ensure all candidates are within bounds. newX = np.clip(newX, lb, ub) # Return updated population, the best solution, and best fitness. return newX, bestSolution, bestFitness
if __name__ == "__main__": import tqdm # Define a simple fitness function (sum of elements). def FitnessFunction(X): # Calculate sum of elements as fitness. result = np.sum(X) return result # Set population size. Ps = 100 # Set number of dimensions. D = 10 # Set lower bounds. LB = np.ones(D) * 0 # Set upper bounds. UB = np.ones(D) * 20 # Initialize population randomly within bounds. X = LB + (UB - LB) * np.random.random((Ps, D)) X = np.clip(X, LB, UB) # Set number of iterations. T = 100 # Initialize the best fitness. bestFitness = np.inf # Initialize the best solution. bestSolution = np.zeros(D) # Run optimization for T iterations. for t in tqdm.tqdm(range(1, T + 1)): # Evaluate fitness for all candidates. Fs = [FitnessFunction(fs) for fs in X] # Sort population by fitness. X, Fs = zip(*sorted(zip(X, Fs), key=lambda x: x[1])) X = np.array(X) # Run one iteration of MRFO. X, bestSolution, bestFitness = MantaRayForagingOptimizer( X, Fs, Ps, D, LB, UB, t, T, FitnessFunction ) # Print final population shape and best fitness. print("The shape of X is:", X.shape) print("The best fitness is:", bestFitness) print("The best solution is:", bestSolution)