The Monarch Butterfly Optimization (MBO) algorithm is a nature-inspired metaheuristic optimization technique. It mimics the migration behavior of monarch butterflies between different regions (e.g., North America and Mexico). The goal of the algorithm is to solve optimization problems by simulating exploration and exploitation of the solution space.
-
Subpopulations:
- The population is divided into two subpopulations representing different regions.
- Subpopulation A: Larger, focusing on exploration.
- Subpopulation B: Smaller, focusing on exploitation.
-
Migration:
- A portion of the solutions in subpopulation A is transferred to subpopulation B.
- This represents the movement of butterflies between regions, helping to explore new areas of the search space.
-
Mutation:
- Random alterations (e.g., flipping binary values) are applied to solutions to maintain diversity and avoid premature convergence.
-
Selection:
- The best solutions are retained across generations to ensure that the population improves over time.
The 0–1 Knapsack Problem is a classic combinatorial optimization problem.
You are given:
- A knapsack with a maximum capacity (
C
). - A set of items, where each item has:
- A value (
v
) indicating its importance. - A weight (
w
) indicating its space requirement.
- A value (
Objective: Select a subset of items to maximize the total value without exceeding the knapsack's weight capacity.
Let ( x_i ) represent whether an item ( i ) is selected (( x_i = 1 )) or not (( x_i = 0 )).
[ \text{Maximize } \sum_{i=1}^n v_i x_i \quad \text{subject to} \quad \sum_{i=1}^n w_i x_i \leq C ]
- Resource allocation.
- Budget optimization.
- Supply chain management.
The Enhanced Monarch Butterfly Optimization Algorithm solves the 0–1 Knapsack Problem by:
- Representing solutions as binary arrays (e.g.,
[1, 0, 1]
where1
means the item is selected). - Evaluating the fitness of each solution (total value of selected items, penalizing infeasible solutions).
- Using migration, mutation, and selection to iteratively improve solutions.
Additionally, Google Gemini AI is used to:
- Generate problem instances: Create knapsack problems dynamically based on user-defined parameters.
- Analyze results: Provide insights into convergence and performance.
Parameter | Description |
---|---|
Population Size | Number of candidate solutions in each generation. Larger sizes improve diversity but increase runtime. |
Number of Generations | Total iterations for which the algorithm will run. More generations allow better optimization. |
Mutation Rate | Probability of flipping a bit in a solution during mutation. Higher rates improve diversity. |
Knapsack Capacity | Maximum weight the knapsack can hold. |
Item Values | Importance or profit associated with each item. |
Item Weights | Space or cost required by each item. |
-
generate_random_solution(num_items)
:- Purpose: Creates a random binary solution (e.g.,
[0, 1, 1, 0]
). - Parameters:
num_items
: Total number of items.
- Returns: A list of
0
s and1
s.
- Purpose: Creates a random binary solution (e.g.,
-
initialize_population(pop_size, num_items)
:- Purpose: Generates the initial population of random solutions.
- Parameters:
pop_size
: Number of solutions in the population.num_items
: Total number of items.
- Returns: A list of binary solutions.
-
fitness(solution, values, weights, capacity)
:- Purpose: Calculates the fitness (value) of a solution.
- Logic:
- If the total weight exceeds the capacity, the fitness is
0
. - Otherwise, it sums the values of selected items.
- If the total weight exceeds the capacity, the fitness is
- Parameters:
solution
: Binary solution.values
: List of item values.weights
: List of item weights.capacity
: Knapsack capacity.
- Returns: Fitness score.
-
repair(solution, weights, capacity, values)
:- Purpose: Fixes infeasible solutions by removing items until the total weight is within capacity.
- Logic:
- Removes items with the lowest value-to-weight ratio first.
- Returns: A feasible binary solution.
-
split_population(population)
:- Purpose: Divides the population into two subpopulations.
- Returns: Two subpopulations.
-
single_point_crossover(parent1, parent2)
:- Purpose: Performs crossover between two parent solutions.
- Logic:
- Combines parts of
parent1
andparent2
to create two offspring.
- Combines parts of
- Returns: Two child solutions.
-
migration_phase(population)
:- Purpose: Simulates migration by performing crossover between subpopulations.
- Returns: Migrated population.
-
mutate(solution, mutation_rate)
:- Purpose: Applies mutation to a solution by flipping bits with a certain probability.
- Parameters:
mutation_rate
: Probability of flipping a bit.
- Returns: Mutated solution.
-
local_search(solution, values, weights, capacity)
:- Purpose: Improves a solution by locally adding items if they fit and improve value.
- Returns: Improved solution.
-
mutate_and_search(population, mutation_rate, values, weights, capacity)
:- Purpose: Applies mutation and local search to all solutions in the population.
-
select_next_generation(population, fitness_values, pop_size)
:- Purpose: Selects the top solutions to form the next generation.
-
main_knapsack_mbo(values, weights, capacity, pop_size, max_generations, mutation_rate, verbose)
:- Purpose: Main function to solve the knapsack problem using MBO.
- Steps:
- Initializes the population.
- Iterates through generations, applying migration, mutation, and selection.
- Tracks and prints the best solution.
-
load_knapsack_instance(file_path)
:- Purpose: Loads a knapsack problem instance from a file.
- Returns: Item values, weights, and knapsack capacity.
-
main()
:- Purpose: Command-line interface for running the algorithm.
- Logic:
- Parses command-line arguments.
- Loads the knapsack instance.
- Executes the MBO algorithm.
- Saves or displays plots.
-
plot_solution(solution, values, weights, capacity, save_path)
:- Purpose: Visualizes the selected items in a bar chart.
- Parameters:
save_path
: If provided, saves the plot as an image.
-
plot_fitness_history(fitness_history, save_path)
:- Purpose: Plots the fitness convergence over generations.
-
test_generate_random_solution()
:- Validates that generated solutions have the correct length and format.
-
test_fitness_feasible()
:- Verifies correct fitness calculation for feasible solutions.
-
test_fitness_infeasible()
:- Ensures that infeasible solutions are penalized.
-
test_repair_feasible()
:- Confirms that feasible solutions remain unchanged during repair.
-
test_repair_infeasible()
:- Checks that infeasible solutions are repaired correctly.
See the README file for more details.