Mutation

class jmetal.operator.mutation.BitFlipMutation(probability: float)[source]

Bases: Mutation[BinarySolution]

NumPy-optimized bit flip mutation for BinarySolution.

This implementation uses NumPy’s vectorized operations for better performance when working with BinarySolution solutions. It flips each bit with a given probability, but does so using efficient array operations.

Args:

probability: The probability of flipping each bit (0.0 to 1.0)

Raises:

ValueError: If probability is not in range [0.0, 1.0]

execute(solution: BinarySolution) BinarySolution[source]

Execute the bit flip mutation operation.

Args:

solution: The solution to be mutated. Must be a BinarySolution with a ‘bits’ attribute.

Returns:

The mutated solution (modified in-place)

Raises:

TypeError: If solution is not a BinarySolution or doesn’t have a ‘bits’ attribute ValueError: If the solution has no variables or invalid bit values

Note:

The input solution is modified in-place and also returned.

get_name() str[source]

Return the name of the operator.

Returns:

str: A string representing the name of the operator

class jmetal.operator.mutation.CompositeMutation(mutation_operator_list: List[Mutation])[source]

Bases: Mutation[Solution]

execute(solution: CompositeSolution) CompositeSolution[source]
get_name() str[source]
class jmetal.operator.mutation.IntegerPolynomialMutation(probability: float, distribution_index: float = 20.0)[source]

Bases: Mutation[IntegerSolution]

Polynomial mutation adapted to integer-valued decision variables.

  • probability: Per-variable mutation probability.

  • distribution_index: Controls mutation spread. Typical values ~20.0 for fine-grained moves; lower values increase exploration.

execute(solution: IntegerSolution) IntegerSolution[source]
get_name()[source]
class jmetal.operator.mutation.LevyFlightMutation(mutation_probability: float = 0.01, beta: float = 1.5, step_size: float = 0.01, repair_operator: Callable[[float, float, float], float] | None = None)[source]

Bases: Mutation[FloatSolution]

Implementation of a Lévy flight mutation operator for real-valued solutions.

Lévy flights are characterized by heavy-tailed distributions with infinite variance, producing mostly small steps with occasional very large jumps. This behavior is beneficial for global optimization as it provides both local search capabilities and the ability to escape local optima through large jumps.

The implementation uses the Mantegna algorithm to generate Lévy-distributed steps: 1. Generate u ~ Normal(0, σ_u²) where σ_u = [Γ(1+β)sin(πβ/2)/Γ((1+β)/2)β2^((β-1)/2)]^(1/β) 2. Generate v ~ Normal(0, 1) 3. Lévy step = u / |v|^(1/β)

Args:

mutation_probability: The probability of mutating each variable (0 ≤ p ≤ 1). beta: The Lévy index parameter (1 < β ≤ 2). Controls the tail heaviness:

  • Values closer to 1.0 produce heavier tails with more frequent large jumps

  • Values around 1.5 provide balanced exploration (default)

  • Values closer to 2.0 approach Gaussian behavior with fewer large jumps

step_size: The scaling factor for Lévy steps (must be > 0). Typical values:
  • 0.001-0.01: Fine-grained local search

  • 0.01-0.05: Balance of local and global search (default: 0.01)

  • 0.05-0.1: Emphasize global exploration

repair_operator: Optional function to repair out-of-bounds values.

If None, values are clamped to the variable bounds.

Raises:

ValueError: If parameters are outside their valid ranges.

execute(solution: FloatSolution) FloatSolution[source]
get_name()[source]
class jmetal.operator.mutation.NonUniformMutation(probability: float, perturbation: float = 0.5, max_iterations: int = 1000)[source]

Bases: Mutation[FloatSolution]

Implementation of a non-uniform mutation operator for real-valued solutions.

This operator perturbs solutions in a way that the mutation strength decreases over time, allowing for more exploration in early generations and more exploitation in later generations. The mutation strength is controlled by the current iteration number relative to the maximum number of iterations.

The mutation follows the formula:

Δ(t, y) = y * (r * (1 - t/T)^b - 1) if r ≤ 0.5 Δ(t, y) = y * (1 - r * (1 - t/T)^b) if r > 0.5

where t is the current iteration, T is max_iterations, and b is the perturbation.

Args:

probability: The probability of mutating each variable (0 ≤ p ≤ 1). perturbation: Controls the perturbation strength (must be > 0).

  • Lower values: More gradual decrease in mutation strength

  • Higher values: More rapid decrease in mutation strength

max_iterations: The maximum number of iterations (must be > 0).

Used to normalize the current iteration count.

Raises:

ValueError: If probability is not in [0,1] or parameters are not positive.

execute(solution: FloatSolution) FloatSolution[source]

Execute the non-uniform mutation on a solution.

Args:

solution: The solution to be mutated.

Returns:

The mutated solution.

get_name() str[source]

Get the name of the operator.

Returns:

A string containing the operator name and parameters.

set_current_iteration(current_iteration: int) None[source]

Set the current iteration number for controlling mutation strength.

Args:

current_iteration: The current iteration number (must be ≥ 0).

class jmetal.operator.mutation.NullMutation[source]

Bases: Mutation[Solution]

execute(solution: Solution) Solution[source]
get_name()[source]
class jmetal.operator.mutation.PermutationSwapMutation(probability: float)[source]

Bases: Mutation[PermutationSolution]

execute(solution: PermutationSolution) PermutationSolution[source]
get_name()[source]
class jmetal.operator.mutation.PolynomialMutation(probability: float = 0.01, distribution_index: float = 20.0, repair_operator: Callable[[float, float, float], float] | None = None)[source]

Bases: Mutation[FloatSolution]

Implementation of a polynomial mutation operator for real-valued solutions.

The polynomial mutation is based on a polynomial probability distribution that perturbs solutions in a way that favors small changes while still allowing occasional larger jumps. This provides a good balance between exploration and exploitation in evolutionary algorithms.

The mutation follows a polynomial probability distribution centered on the parent value, with the spread controlled by the distribution index.

Args:

probability: The probability of mutating each variable (0 ≤ p ≤ 1). distribution_index: Controls the perturbation magnitude (must be ≥ 0):

  • Lower values (e.g., 5-20): More exploratory, larger mutations

  • Medium values (e.g., 20-100): Balanced exploration/exploitation

  • Higher values (e.g., >100): More exploitative, smaller mutations

repair_operator: Optional function to repair out-of-bounds values.

If None, values are clamped to the variable bounds.

Raises:

ValueError: If probability is not in [0,1] or distribution_index is negative.

execute(solution: FloatSolution) FloatSolution[source]
get_name()[source]
class jmetal.operator.mutation.PowerLawMutation(probability: float = 0.01, delta: float = 1.0, repair_operator: Callable[[float, float, float], float] | None = None)[source]

Bases: Mutation[FloatSolution]

Implementation of a power-law mutation operator for real-valued solutions.

The power-law distribution produces heavy-tailed perturbations that can occasionally create large jumps while favoring smaller perturbations, which is beneficial for both exploration and exploitation in optimization.

The mutation follows the formula:

temp_delta = rnd^(-delta) deltaq = 0.5 * (rnd - 0.5) * (1 - temp_delta) new_value = old_value + deltaq * (upper_bound - lower_bound)

Args:

probability: The probability of mutating each variable (0 ≤ p ≤ 1). delta: The power-law exponent parameter (must be > 0). Controls distribution shape:

  • Values < 1.0: More uniform distributions with moderate perturbations

  • Values ≈ 1.0: Balanced exploration/exploitation (default)

  • Values > 1.0: Heavy-tailed distributions favoring small perturbations with occasional large jumps

repair_operator: Optional function to repair out-of-bounds values.

If None, values are clamped to the variable bounds.

Raises:

ValueError: If probability is not in [0,1] or delta is not positive.

execute(solution: FloatSolution) FloatSolution[source]
get_name()[source]
class jmetal.operator.mutation.ScrambleMutation(probability: float)[source]

Bases: Mutation[PermutationSolution]

execute(solution: PermutationSolution) PermutationSolution[source]
get_name()[source]
class jmetal.operator.mutation.SimpleRandomMutation(probability: float)[source]

Bases: Mutation[FloatSolution]

Implementation of a simple random mutation operator for real-valued solutions.

This operator replaces the value of a decision variable with a random value uniformly distributed between the lower and upper bounds of that variable. This is one of the simplest mutation operators but can be effective for exploration, especially in the early stages of optimization.

Args:

probability: The probability of mutating each variable (0 ≤ p ≤ 1).

Raises:

ValueError: If probability is not in [0,1].

execute(solution: FloatSolution) FloatSolution[source]
get_name() str[source]
class jmetal.operator.mutation.UniformMutation(probability: float, perturbation: float = 0.5)[source]

Bases: Mutation[FloatSolution]

Implementation of a uniform mutation operator for real-valued solutions.

This operator adds a random perturbation uniformly distributed in [-perturbation/2, perturbation/2] to each variable with a given probability. The perturbation is scaled by the variable’s range, making the operator scale-invariant to the problem’s bounds.

Args:

probability: The probability of mutating each variable (0 ≤ p ≤ 1). perturbation: Controls the maximum relative perturbation size (must be > 0).

  • Smaller values (e.g., 0.1-0.5): Small, local perturbations

  • Larger values (e.g., 1.0-2.0): Larger, more exploratory perturbations

Raises:

ValueError: If probability is not in [0,1] or perturbation is not positive.

execute(solution: FloatSolution) FloatSolution[source]
get_name() str[source]