diff --git a/.gitignore b/.gitignore index 524f096..22509b8 100644 --- a/.gitignore +++ b/.gitignore @@ -22,3 +22,5 @@ # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml hs_err_pid* replay_pid* + +.idea diff --git a/Metaheuristics/AVOA/AVOA.java b/Metaheuristics/AVOA/AVOA.java new file mode 100644 index 0000000..4afa100 --- /dev/null +++ b/Metaheuristics/AVOA/AVOA.java @@ -0,0 +1,97 @@ +package Metaheuristics.AVOA; + +import java.util.Random; + +import static Metaheuristics.AVOA.BoundaryCheck.boundaryCheck; +import static Metaheuristics.AVOA.Exploitation.exploitation; +import static Metaheuristics.AVOA.Exploration.exploration; +import static Metaheuristics.AVOA.Initialization.initialization; +import static Metaheuristics.AVOA.RandomSelection.randomSelect; + +public class AVOA { + /** + * Runs the Artificial Vulture Optimization Algorithm (AVOA) to find the global optimum. + * + * @param pop_size The population size. + * @param max_iter The maximum number of iterations. + * @param lower_bound The lower bound of the variables. + * @param upper_bound The upper bound of the variables. + * @param variables_no The number of variables. + * @param fobj The objective function. + * @return An array containing the best vulture 1 fitness, best vulture 1 position, + * and the convergence curve of the algorithm. + */ + public static Object[] AVOA(int pop_size, int max_iter, double[] lower_bound, double[] upper_bound, + int variables_no, ObjectiveFunction fobj) { + // Initialize Best_vulture1, Best_vulture2 + double[] Best_vulture1_X = new double[variables_no]; + double Best_vulture1_F = Double.POSITIVE_INFINITY; + double[] Best_vulture2_X = new double[variables_no]; + double Best_vulture2_F = Double.POSITIVE_INFINITY; + + // Initialize the first random population of vultures + double[][] X = initialization(pop_size, variables_no, upper_bound, lower_bound); + + // Controlling parameters + double p1 = 0.6; + double p2 = 0.4; + double p3 = 0.6; + double alpha = 0.8; + double beta = 0.2; + double gamma = 2.5; + + // Main loop + int current_iter = 0; // Loop counter + double[] convergence_curve = new double[max_iter]; + + while (current_iter < max_iter) { + for (int i = 0; i < X.length; i++) { + // Calculate the fitness of the population + double[] current_vulture_X = X[i]; + double current_vulture_F = fobj.evaluate(current_vulture_X); + + // Update the first best two vultures if needed + if (current_vulture_F < Best_vulture1_F) { + Best_vulture1_F = current_vulture_F; // Update the first best vulture + System.arraycopy(current_vulture_X, 0, Best_vulture1_X, 0, variables_no); + } + if (current_vulture_F > Best_vulture1_F && current_vulture_F < Best_vulture2_F) { + Best_vulture2_F = current_vulture_F; // Update the second-best vulture + System.arraycopy(current_vulture_X, 0, Best_vulture2_X, 0, variables_no); + } + } + + Random rand = new Random(); + double a = rand.nextDouble() * 4 - 2; + a *= (Math.pow(Math.sin(Math.PI / 2 * (current_iter / (double)max_iter)), gamma) + + Math.cos(Math.PI / 2 * (current_iter / (double)max_iter)) - 1); + double P1 = (2 * rand.nextDouble() + 1) * (1 - (current_iter / (double)max_iter)) + a; + + // Update the location + for (int i = 0; i < X.length; i++) { + double[] current_vulture_X = X[i].clone(); // Pick the current vulture back to the population + double F = P1 * (2 * rand.nextDouble() - 1); + + double[] random_vulture_X = randomSelect(Best_vulture1_X, Best_vulture2_X, alpha, beta); + + if (Math.abs(F) >= 1) { // Exploration + current_vulture_X = exploration(current_vulture_X, random_vulture_X, F, p1, upper_bound, lower_bound); + } else if (Math.abs(F) < 1) { // Exploitation + current_vulture_X = exploitation(current_vulture_X, Best_vulture1_X, Best_vulture2_X, random_vulture_X, F, p2, p3, variables_no); + } + + X[i] = current_vulture_X; // Place the current vulture back into the population + } + + current_iter++; + convergence_curve[current_iter - 1] = Best_vulture1_F; + + X = boundaryCheck(X, lower_bound, upper_bound); + + System.out.printf("In Iteration %d, best estimation of the global optimum is %4.4f \n", current_iter, Best_vulture1_F); + } + + + return new Object[]{Best_vulture1_F, Best_vulture1_X, convergence_curve}; + } +} diff --git a/Metaheuristics/AVOA/AVOAExample.java b/Metaheuristics/AVOA/AVOAExample.java new file mode 100644 index 0000000..3be8453 --- /dev/null +++ b/Metaheuristics/AVOA/AVOAExample.java @@ -0,0 +1,40 @@ +package Metaheuristics.AVOA; +import static Metaheuristics.AVOA.AVOA.AVOA; + +import java.util.Arrays; + +public class AVOAExample { + + public static void main(String[] args) { + int pop_size = 30; + int max_iter = 100; + + // Define your objective function's details here + ObjectiveFunction fobj = new ObjectiveFunction(); + int variables_no = 10; + double[] lower_bound = new double[variables_no]; + Arrays.fill(lower_bound, -100); + double[] upper_bound = new double[variables_no]; + Arrays.fill(upper_bound, 100); + + Object[] result = AVOA(pop_size, max_iter, lower_bound, upper_bound, variables_no, fobj); + double Best_vulture1_F = (double) result[0]; + double[] Best_vulture1_X = (double[]) result[1]; + double[] convergence_curve = (double[]) result[2]; + + // Best optimal values for the decision variables + // parallelcoords(Best_vulture1_X) + System.out.println("Decision variables:"); + for (double value : Best_vulture1_X) { + System.out.println(value); + } + + // Best convergence curve + // plot(convergence_curve); + System.out.println("\nConvergence curve of AVOA:"); + for (double value : convergence_curve) { + System.out.println(value); + } + } + +} diff --git a/Metaheuristics/AVOA/BoundaryCheck.java b/Metaheuristics/AVOA/BoundaryCheck.java new file mode 100644 index 0000000..23b667a --- /dev/null +++ b/Metaheuristics/AVOA/BoundaryCheck.java @@ -0,0 +1,28 @@ +package Metaheuristics.AVOA; + +public class BoundaryCheck { + /** + * Performs boundary check on the matrix X. + * + * @param X The input matrix + * @param lb The lower bounds vector + * @param ub The upper bounds vector + * @return The modified matrix after boundary check + */ + public static double[][] boundaryCheck(double[][] X, double[] lb, double[] ub) { + int numRows = X.length; + int numCols = X[0].length; + + for (int i = 0; i < numRows; i++) { + for (int j = 0; j < numCols; j++) { + boolean FU = X[i][j] > ub[j]; // Check if element exceeds the upper bound + boolean FL = X[i][j] < lb[j]; // Check if element is below the lower bound + + // Perform the boundary check and assign the appropriate value to X[i][j] + X[i][j] = (X[i][j] * ((!(FU || FL)) ? 1 : 0)) + ub[j] * (FU ? 1 : 0) + lb[j] * (FL ? 1 : 0); + } + } + + return X; + } +} diff --git a/Metaheuristics/AVOA/Exploitation.java b/Metaheuristics/AVOA/Exploitation.java new file mode 100644 index 0000000..c69f933 --- /dev/null +++ b/Metaheuristics/AVOA/Exploitation.java @@ -0,0 +1,73 @@ +package Metaheuristics.AVOA; + +import java.util.Random; + +import static Metaheuristics.AVOA.LevyFlight.levyFlight; + +public class Exploitation { + /** + * Updates the current vulture position based on exploitation. + * + * @param current_vulture_X The current vulture position array to be updated. + * @param Best_vulture1_X The position of the best vulture 1. + * @param Best_vulture2_X The position of the best vulture 2. + * @param random_vulture_X The random vulture position array. + * @param F The exploitation factor. + * @param p2 The probability threshold for phase 1 exploitation. + * @param p3 The probability threshold for phase 2 exploitation. + * @param variables_no The number of variables. + * @return The updated current vulture position array. + */ + public static double[] exploitation(double[] current_vulture_X, double[] Best_vulture1_X, double[] Best_vulture2_X, + double[] random_vulture_X, double F, double p2, double p3, int variables_no) { + Random rand = new Random(); + + // Phase 1 + if (Math.abs(F) < 0.5) { + if (rand.nextDouble() < p2) { + // Calculate intermediate values A and B + double[] A = new double[current_vulture_X.length]; + double[] B = new double[current_vulture_X.length]; + for (int i = 0; i < current_vulture_X.length; i++) { + A[i] = Best_vulture1_X[i] - ((Best_vulture1_X[i] * current_vulture_X[i]) / (Best_vulture1_X[i] - Math.pow(current_vulture_X[i], 2))) * F; + B[i] = Best_vulture2_X[i] - ((Best_vulture2_X[i] * current_vulture_X[i]) / (Best_vulture2_X[i] - Math.pow(current_vulture_X[i], 2))) * F; + } + // Update current vulture position by averaging A and B + for (int i = 0; i < current_vulture_X.length; i++) { + current_vulture_X[i] = (A[i] + B[i]) / 2; + } + } else { + // Update current vulture position using random vulture position, absolute difference, F, and levyFlight + double[] levyFlight = levyFlight(variables_no); // Replace this line with your levyFlight implementation + for (int i = 0; i < current_vulture_X.length; i++) { + current_vulture_X[i] = random_vulture_X[i] - Math.abs(random_vulture_X[i] - current_vulture_X[i]) * F * levyFlight[i]; + } + } + } + + // Phase 2 + if (Math.abs(F) >= 0.5) { + if (rand.nextDouble() < p3) { + // Update current vulture position using random vulture position, random values, and F + for (int i = 0; i < current_vulture_X.length; i++) { + double randomValue = 2 * rand.nextDouble(); + current_vulture_X[i] = Math.abs(randomValue * random_vulture_X[i] - current_vulture_X[i]) * (F + rand.nextDouble()) - (random_vulture_X[i] - current_vulture_X[i]); + } + } else { + // Calculate intermediate values s1 and s2 + double[] s1 = new double[current_vulture_X.length]; + double[] s2 = new double[current_vulture_X.length]; + for (int i = 0; i < current_vulture_X.length; i++) { + s1[i] = random_vulture_X[i] * (rand.nextDouble() * current_vulture_X[i] / (2 * Math.PI)) * Math.cos(current_vulture_X[i]); + s2[i] = random_vulture_X[i] * (rand.nextDouble() * current_vulture_X[i] / (2 * Math.PI)) * Math.sin(current_vulture_X[i]); + } + // Update current vulture position by subtracting s1 and s2 from random vulture position + for (int i = 0; i < current_vulture_X.length; i++) { + current_vulture_X[i] = random_vulture_X[i] - (s1[i] + s2[i]); + } + } + } + + return current_vulture_X; + } +} diff --git a/Metaheuristics/AVOA/Exploration.java b/Metaheuristics/AVOA/Exploration.java new file mode 100644 index 0000000..56fd039 --- /dev/null +++ b/Metaheuristics/AVOA/Exploration.java @@ -0,0 +1,40 @@ +package Metaheuristics.AVOA; + +import java.util.Random; + +public class Exploration { + /** + * Updates the current vulture position based on exploration. + * + * @param current_vulture_X The current vulture position array to be updated. + * @param random_vulture_X The random vulture position array. + * @param F The exploration factor. + * @param p1 The probability threshold for exploration. + * @param upper_bound The upper bound of the vulture position range. + * @param lower_bound The lower bound of the vulture position range. + * @return The updated current vulture position array. + */ + public static double[] exploration(double[] current_vulture_X, double[] random_vulture_X, double F, double p1, double[] upper_bound, double[] lower_bound) { + Random rand = new Random(); + + // Check if a randomly generated value is less than p1 + if (rand.nextDouble() < p1) { + // Exploration based on random vulture position + for (int i = 0; i < current_vulture_X.length; i++) { + double randomFactor = 2 * rand.nextDouble(); // Generate a random factor between 0 and 2 + // Update the current vulture position using the random factor and F + current_vulture_X[i] = random_vulture_X[i] - Math.abs((randomFactor * random_vulture_X[i]) - current_vulture_X[i]) * F; + } + } else { + // Exploration based on random values within bounds + for (int i = 0; i < current_vulture_X.length; i++) { + double randomFactor = rand.nextDouble(); // Generate a random factor between 0 and 1 + double range = upper_bound[i] - lower_bound[i]; // Calculate the range for the current dimension + // Update the current vulture position using the random factor, F, upper bound, and lower bound + current_vulture_X[i] = random_vulture_X[i] - F + randomFactor * (range * rand.nextDouble() + lower_bound[i]); + } + } + + return current_vulture_X; + } +} \ No newline at end of file diff --git a/Metaheuristics/AVOA/Initialization.java b/Metaheuristics/AVOA/Initialization.java new file mode 100644 index 0000000..5e9d133 --- /dev/null +++ b/Metaheuristics/AVOA/Initialization.java @@ -0,0 +1,45 @@ +package Metaheuristics.AVOA; + +import java.util.Random; + +public class Initialization { + /** + * Initialize the first population of search agents. + * + * @param N The population size + * @param dim The dimensionality of the search space + * @param ub The upper bounds vector + * @param lb The lower bounds vector + * @return The initialized population matrix + */ + public static double[][] initialization(int N, int dim, double[] ub, double[] lb) { + int boundaryNo = ub.length; // Number of boundaries + + Random rand = new Random(); + double[][] X = new double[N][dim]; // Initialized population matrix + + // If the boundaries of all variables are equal and the user enters a single number for both ub and lb + if (boundaryNo == 1) { + double upperBound = ub[0]; + double lowerBound = lb[0]; + for (int i = 0; i < N; i++) { + for (int j = 0; j < dim; j++) { + X[i][j] = rand.nextDouble() * (upperBound - lowerBound) + lowerBound; + } + } + } + + // If each variable has a different lb and ub + if (boundaryNo > 1) { + for (int i = 0; i < dim; i++) { + double upperBound = ub[i]; + double lowerBound = lb[i]; + for (int j = 0; j < N; j++) { + X[j][i] = rand.nextDouble() * (upperBound - lowerBound) + lowerBound; + } + } + } + + return X; + } +} diff --git a/Metaheuristics/AVOA/LevyFlight.java b/Metaheuristics/AVOA/LevyFlight.java new file mode 100644 index 0000000..c58f88e --- /dev/null +++ b/Metaheuristics/AVOA/LevyFlight.java @@ -0,0 +1,38 @@ +package Metaheuristics.AVOA; + +import org.apache.commons.math3.special.Gamma; +import java.util.Random; + +public class LevyFlight { + /** + * Generates a Levy flight of length d. + * + * @param d The length of the Levy flight + * @return The Levy flight as an array + */ + public static double[] levyFlight(int d) { + double beta = 3.0 / 2.0; + + // Calculate the sigma value + double sigma = Math.pow((Gamma.gamma(1 + beta) * Math.sin(Math.PI * beta / 2) / + (Gamma.gamma((1 + beta) / 2) * beta * Math.pow(2, (beta - 1) / 2))), 1 / beta); + + Random rand = new Random(); + + // Generate random values for u and v + double[] u = new double[d]; + double[] v = new double[d]; + for (int i = 0; i < d; i++) { + u[i] = rand.nextGaussian() * sigma; + v[i] = rand.nextGaussian(); + } + + // Calculate the step values + double[] step = new double[d]; + for (int i = 0; i < d; i++) { + step[i] = u[i] / Math.pow(Math.abs(v[i]), 1 / beta); + } + + return step; + } +} diff --git a/Metaheuristics/AVOA/ObjectiveFunction.java b/Metaheuristics/AVOA/ObjectiveFunction.java new file mode 100644 index 0000000..563efb9 --- /dev/null +++ b/Metaheuristics/AVOA/ObjectiveFunction.java @@ -0,0 +1,25 @@ +package Metaheuristics.AVOA; + +public class ObjectiveFunction { + /** + * Evaluates the objective function for the given response time, wait time, and makespan. + * +// * @param responseTime The response time +// * @param waitTime The wait time +// * @param makespan The makespan + * @return The weighted sum of response time, wait time, and makespan + */ +// public static double evaluate(double responseTime, double waitTime, double makespan) { + public static double evaluate(double[] felan){ + // Define the weights for each component + double weightResponseTime = 0.5; + double weightWaitTime = 0.3; + double weightMakespan = 0.2; + + // Calculate the weighted sum + return 2.0; +// return weightResponseTime * responseTime + +// weightWaitTime * waitTime + +// weightMakespan * makespan; + } +} diff --git a/Metaheuristics/AVOA/RandomSelection.java b/Metaheuristics/AVOA/RandomSelection.java new file mode 100644 index 0000000..63ba86c --- /dev/null +++ b/Metaheuristics/AVOA/RandomSelection.java @@ -0,0 +1,30 @@ +package Metaheuristics.AVOA; + +import static Metaheuristics.AVOA.RouletteWheelSelection.rouletteWheelSelection; + +public class RandomSelection { + /** + * Performs random selection between two vulture positions based on given probabilities. + * + * @param Best_vulture1_X The position of the first best vulture + * @param Best_vulture2_X The position of the second best vulture + * @param alpha The probability of selecting the first best vulture + * @param beta The probability of selecting the second best vulture + * @return The randomly selected vulture position + */ + public static double[] randomSelect(double[] Best_vulture1_X, double[] Best_vulture2_X, double alpha, double beta) { + double[] probabilities = {alpha, beta}; + + int selectedIndex = rouletteWheelSelection(probabilities); + + // Random selection based on the chosen index + double[] random_vulture_X; + if (selectedIndex == 0) { + random_vulture_X = Best_vulture1_X; + } else { + random_vulture_X = Best_vulture2_X; + } + + return random_vulture_X; + } +} diff --git a/Metaheuristics/AVOA/RouletteWheelSelection.java b/Metaheuristics/AVOA/RouletteWheelSelection.java new file mode 100644 index 0000000..9422664 --- /dev/null +++ b/Metaheuristics/AVOA/RouletteWheelSelection.java @@ -0,0 +1,35 @@ +package Metaheuristics.AVOA; + +import java.util.Random; + +public class RouletteWheelSelection { + /** + * Performs roulette wheel selection based on the given probability distribution. + * + * @param x The probability distribution array + * @return The selected index + */ + public static int rouletteWheelSelection(double[] x) { + Random rand = new Random(); + double cumulativeSum = 0.0; + int selectedIndex = -1; + + // Calculate the cumulative sum of the probability distribution array + double[] cumulativeSumArray = new double[x.length]; + for (int i = 0; i < x.length; i++) { + cumulativeSum += x[i]; + cumulativeSumArray[i] = cumulativeSum; + } + + // Perform the roulette wheel selection + double randomValue = rand.nextDouble(); + for (int i = 0; i < x.length; i++) { + if (randomValue <= cumulativeSumArray[i]) { + selectedIndex = i; + break; + } + } + + return selectedIndex; + } +}