Operators¶
Crossover¶
crossover
¶
NullCrossover()
¶
Bases: Crossover[Solution, Solution]
A no-operation crossover operator that simply returns copies of the parents.
This operator is useful as a placeholder when no crossover is desired in an algorithm. It creates deep copies of the parent solutions without performing any genetic recombination. The number of parents and children is fixed at 2.
Example
from jmetal.operator import NullCrossover from jmetal.core.solution import FloatSolution
Create two test solutions¶
parent1 = FloatSolution([0], [1], 1) parent2 = FloatSolution([0], [1], 1) parent1.variables = [0.5] parent2.variables = [1.5]
Apply null crossover¶
crossover = NullCrossover() offspring = crossover.execute([parent1, parent2])
Offspring are copies of parents¶
offspring[0].variables[0] == parent1.variables[0] True offspring[1].variables[0] == parent2.variables[0] True
Initialize the null crossover operator with zero probability.
Source code in src/jmetal/operator/crossover.py
execute(parents)
¶
Execute the crossover operation.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
parents
|
list[Solution]
|
A list of exactly two parent solutions. |
required |
Returns:
| Type | Description |
|---|---|
list[Solution]
|
A list containing deep copies of the parent solutions. |
Raises:
| Type | Description |
|---|---|
Exception
|
If the number of parents is not exactly two. |
Source code in src/jmetal/operator/crossover.py
get_number_of_parents()
¶
Get the number of parent solutions required.
Returns:
| Name | Type | Description |
|---|---|---|
int |
int
|
Always returns 2, as this operator works with exactly two parents. |
get_number_of_children()
¶
Get the number of offspring solutions produced.
Returns:
| Name | Type | Description |
|---|---|---|
int |
int
|
Always returns 2, as this operator produces two offspring. |
PMXCrossover(probability, rng=None)
¶
Bases: Crossover[PermutationSolution, PermutationSolution]
Partially Mapped Crossover (PMX) for permutation problems.
PMX is a specialized crossover operator designed for permutation-based representations, commonly used in problems like the Traveling Salesman Problem (TSP) and other ordering problems.
The operator works by:
- Selecting two random cut points in the parent permutations.
- Creating an offspring by copying the segment between the cut points from parent1.
- Filling the remaining positions with the relative order of elements from parent2, while avoiding duplicates using a mapping relationship.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
probability
|
float
|
The probability of applying the crossover (0.0 to 1.0). For each pair of parents, this probability determines whether crossover is applied. |
required |
Example
from jmetal.operator import PMXCrossover from jmetal.core.solution import PermutationSolution
Create two test solutions (permutation of [0,1,2,3,4])¶
parent1 = PermutationSolution(5, 1) parent2 = PermutationSolution(5, 1) parent1.variables = [0, 1, 2, 3, 4] parent2.variables = [4, 3, 2, 1, 0]
Apply PMX crossover (with probability 1.0 to ensure execution)¶
crossover = PMXCrossover(probability=1.0) offspring = crossover.execute([parent1, parent2])
The offspring will be a mix of both parents while preserving the permutation property¶
all(x in offspring[0].variables for x in range(5)) True
Reference
Goldberg, D. E., & Lingle, R. (1985). Alleles, loci, and the traveling salesman problem. In Proceedings of the First International Conference on Genetic Algorithms and their Applications (pp. 154-159).
Initialize the PMX crossover operator.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
probability
|
float
|
Crossover probability between 0.0 and 1.0. |
required |
rng
|
Generator | None
|
Optional NumPy Generator for reproducible randomness. |
None
|
Source code in src/jmetal/operator/crossover.py
execute(parents)
¶
Execute the PMX crossover operation.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
parents
|
list[PermutationSolution]
|
A list of exactly two parent solutions of type PermutationSolution. |
required |
Returns:
| Type | Description |
|---|---|
list[PermutationSolution]
|
A list containing two offspring solutions. |
Raises:
| Type | Description |
|---|---|
Exception
|
If the number of parents is not exactly two. |
Source code in src/jmetal/operator/crossover.py
167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 | |
CXCrossover(probability, rng=None)
¶
Bases: Crossover[PermutationSolution, PermutationSolution]
Cycle Crossover (CX) for permutation-based solutions.
Cycle Crossover is a specialized operator for permutation problems that preserves the absolute positions of elements from both parents. It works by identifying cycles between two parent permutations and creating offspring by alternating between the cycles of the parents.
The algorithm works as follows:
- Start with the first parent and identify a cycle of positions where the elements alternate between the two parents.
- For the first offspring, take elements from parent 1 at the cycle positions and from parent 2 at all other positions.
- For the second offspring, do the opposite (parent 2 at cycle positions, parent 1 elsewhere).
This operator is particularly useful for problems where the absolute position of elements is important, such as the Traveling Salesman Problem (TSP).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
probability
|
float
|
Crossover probability (0.0 to 1.0). The probability that crossover will be applied to a given pair of parents. |
required |
Example
from jmetal.operator import CXCrossover from jmetal.core.solution import PermutationSolution
Create two parent solutions (permutation of [0,1,2,3,4])¶
parent1 = PermutationSolution(5, 1) parent2 = PermutationSolution(5, 1) parent1.variables = [0, 1, 2, 3, 4] # Identity permutation parent2.variables = [4, 3, 2, 1, 0] # Reverse permutation
Create CX crossover with probability 1.0¶
crossover = CXCrossover(probability=1.0) offspring = crossover.execute([parent1, parent2])
The offspring will preserve absolute positions from both parents¶
all(x in offspring[0].variables for x in range(5)) # Still a valid permutation True
Reference
Oliver, I. M., Smith, D. J., & Holland, J. R. (1987). A study of permutation crossover operators on the traveling salesman problem. In Proceedings of the Second International Conference on Genetic Algorithms on Genetic algorithms and their application (pp. 224-230).
Initialize the Cycle Crossover operator.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
probability
|
float
|
Crossover probability between 0.0 and 1.0. |
required |
rng
|
Generator | None
|
Optional random generator. When None, falls back to a fresh np.random.default_rng(). |
None
|
Source code in src/jmetal/operator/crossover.py
execute(parents)
¶
Execute the Cycle Crossover operation.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
parents
|
list[PermutationSolution]
|
A list of exactly two parent solutions of type PermutationSolution. Both parents must have the same length and contain the same elements. |
required |
Returns:
| Type | Description |
|---|---|
list[PermutationSolution]
|
A list containing two offspring solutions. |
Raises:
| Type | Description |
|---|---|
Exception
|
If the number of parents is not exactly two. |
Source code in src/jmetal/operator/crossover.py
get_number_of_parents()
¶
Get the number of parent solutions required.
Returns:
| Name | Type | Description |
|---|---|---|
int |
int
|
Always returns 2, as this operator works with exactly two parents. |
get_number_of_children()
¶
Get the number of offspring solutions produced.
Returns:
| Name | Type | Description |
|---|---|---|
int |
int
|
Always returns 2, as this operator produces two offspring. |
SBXCrossover(probability, distribution_index=20.0, repair_operator=ClampFloatRepair(), rng=None)
¶
Bases: Crossover[FloatSolution, FloatSolution]
Simulated Binary Crossover (SBX) for real-valued solutions.
SBX is a popular crossover operator for real-coded genetic algorithms that simulates the behavior of the single-point crossover operator in binary-coded GAs. It creates offspring solutions based on a probability distribution centered around the parent solutions, with the spread of the distribution controlled by the distribution index.
The operator works by:
- For each variable, compute a spread factor beta based on a random number and the distribution index.
- Use beta to compute new variable values that are spread around the parent values.
- The distribution index controls whether offspring are likely to be near the parents (high values) or more spread out (low values).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
probability
|
float
|
Crossover probability (0.0 to 1.0). The probability that crossover will be applied to a given pair of parents. |
required |
distribution_index
|
float
|
Distribution index (must be ≥ 0). Controls the shape of the probability distribution: - High values (>20): Offspring are very close to parents - Medium values (~10-20): Balanced exploration/exploitation - Low values (<5): High exploration, offspring can be far from parents Typical values range from 5 to 30, with 20 being a common default. |
20.0
|
Raises:
| Type | Description |
|---|---|
ValueError
|
If distribution_index is negative |
Example
from jmetal.operator import SBXCrossover from jmetal.core.solution import FloatSolution
Create two parent solutions¶
parent1 = FloatSolution([0, 0], [1, 1], 1) parent2 = FloatSolution([0, 0], [1, 1], 1) parent1.variables = [0.2, 0.8] parent2.variables = [0.8, 0.2]
Create SBX crossover with probability 0.9 and distribution index 20¶
crossover = SBXCrossover(probability=0.9, distribution_index=20.0)
Generate offspring¶
offspring = crossover.execute([parent1, parent2])
Offspring will be similar to parents due to high distribution index¶
all(0.1 < x < 0.9 for x in offspring[0].variables + offspring[1].variables) True
References
Deb, K., & Agrawal, R. B. (1995). Simulated binary crossover for continuous search space. Complex Systems, 9(2), 115-148.
Deb, K., & Deb, K. (2014). Multi-objective optimization. In Search methodologies (pp. 403-449). Springer, Boston, MA.
Source code in src/jmetal/operator/crossover.py
SPXCrossover(probability, rng=None)
¶
Bases: Crossover[BinarySolution, BinarySolution]
A high-performance single-point crossover operator for BinarySolution.
This implementation uses NumPy's vectorized operations for better performance when working with BinarySolution solutions. It performs a single-point crossover between two parent solutions to produce two offspring.
The crossover point is selected uniformly at random from all possible bit positions in the solution. The bits after the crossover point are swapped between the two parents to create the offspring.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
probability
|
float
|
The probability of applying the crossover (must be between 0.0 and 1.0) |
required |
Raises:
| Type | Description |
|---|---|
ValueError
|
If the probability is not in the range [0.0, 1.0] |
Source code in src/jmetal/operator/crossover.py
execute(parents)
¶
Execute the single-point crossover operation.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
parents
|
list[BinarySolution]
|
A list of exactly two parent solutions of type BinarySolution. Both parents must have the same number of bits. |
required |
Returns:
| Type | Description |
|---|---|
list[BinarySolution]
|
List[BinarySolution]: A list containing two offspring solutions. |
Note
This method assumes that both parents are valid BinarySolution instances with properly initialized bits attributes.
Source code in src/jmetal/operator/crossover.py
get_number_of_parents()
¶
get_number_of_children()
¶
BLXAlphaCrossover(probability=0.9, alpha=0.5, repair_operator=None, rng=None)
¶
Bases: Crossover[FloatSolution, FloatSolution]
BLX-α (Blend Crossover) for real-valued solutions.
The BLX-α crossover creates offspring within a range that is extended by a factor of α (alpha) beyond the range defined by the parent values. This allows for exploration beyond the region defined by the parents while maintaining a balance between exploration and exploitation.
The crossover works by: 1. For each variable, determine the min and max values from the parents 2. Calculate the range between parents 3. Expand the range by α * range in both directions 4. Sample new values uniformly from this expanded range 5. Apply bounds repair if values fall outside the variable bounds
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
probability
|
float
|
Crossover probability (0.0 to 1.0) |
0.9
|
alpha
|
float
|
Expansion factor (must be ≥ 0). Controls the exploration range: - alpha = 0: Offspring will be in the range defined by parents (no exploration) - alpha > 0: Offspring can be outside parent range (increased exploration) - Typical values: 0.1 to 0.5 |
0.5
|
repair_operator
|
Callable[[float, float, float], float] | None
|
Optional function to repair out-of-bounds values. If None, values are clamped to the variable bounds using min/max. Signature: repair_operator(value: float, lower_bound: float, upper_bound: float) -> float |
None
|
Raises:
| Type | Description |
|---|---|
ValueError
|
If probability is not in [0,1] or alpha is negative. |
Reference
Eshelman, L. J., & Schaffer, J. D. (1993). Real-coded genetic algorithms and interval-schemata. Foundations of genetic algorithms, 2, 187-202.
Source code in src/jmetal/operator/crossover.py
doCrossover(probability, parent1, parent2)
¶
Perform the crossover operation.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
probability
|
float
|
Crossover probability |
required |
parent1
|
FloatSolution
|
First parent solution |
required |
parent2
|
FloatSolution
|
Second parent solution |
required |
Returns:
| Type | Description |
|---|---|
list[FloatSolution]
|
A list containing two offspring solutions |
Source code in src/jmetal/operator/crossover.py
BLXAlphaBetaCrossover(probability=0.9, alpha=0.5, beta=0.5, repair_operator=None, rng=None)
¶
Bases: Crossover[FloatSolution, FloatSolution]
BLX-αβ (Blend Crossover with separate alpha and beta) for real-valued solutions.
An extension of BLX-α crossover that uses two different expansion factors (α and β) for the lower and upper bounds respectively. This allows for asymmetric exploration around the parent solutions.
The crossover works by: 1. For each variable, determine the min and max values from the parents 2. Calculate the range between parents (d = max - min) 3. Expand the range by αd below the min and βd above the max 4. Sample new values uniformly from this expanded range 5. Apply bounds repair if values fall outside the variable bounds
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
probability
|
float
|
Crossover probability (0.0 to 1.0) |
0.9
|
alpha
|
float
|
Lower expansion factor (must be ≥ 0). Controls exploration below parents: - alpha = 0: No exploration below the smaller parent value - alpha > 0: Expands range below smaller parent by alpha*d - Typical values: 0.1 to 0.5 |
0.5
|
beta
|
float
|
Upper expansion factor (must be ≥ 0). Controls exploration above parents: - beta = 0: No exploration above the larger parent value - beta > 0: Expands range above larger parent by beta*d - Typical values: 0.1 to 0.5 |
0.5
|
repair_operator
|
Callable[[float, float, float], float] | None
|
Optional function to repair out-of-bounds values. If None, values are clamped to the variable bounds using min/max. Signature: repair_operator(value: float, lower_bound: float, upper_bound: float) -> float |
None
|
Raises:
| Type | Description |
|---|---|
ValueError
|
If probability is not in [0,1] or alpha/beta are negative. |
Reference
Eshelman, L. J., & Schaffer, J. D. (1993). Real-coded genetic algorithms and interval-schemata. Foundations of genetic algorithms, 2, 187-202.
Source code in src/jmetal/operator/crossover.py
doCrossover(probability, parent1, parent2)
¶
Perform the crossover operation.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
probability
|
float
|
Crossover probability |
required |
parent1
|
FloatSolution
|
First parent solution |
required |
parent2
|
FloatSolution
|
Second parent solution |
required |
Returns:
| Type | Description |
|---|---|
list[FloatSolution]
|
A list containing two offspring solutions |
Source code in src/jmetal/operator/crossover.py
ArithmeticCrossover(probability=0.9, repair_operator=None, rng=None)
¶
Bases: Crossover[FloatSolution, FloatSolution]
Arithmetic Crossover for real-valued solutions.
This operator performs an arithmetic combination of two parent solutions to produce two offspring. For each variable, a random weight (alpha) is used to compute a weighted average of the parent values.
The crossover works by:
- For each variable, generate a random weight alpha in [0, 1].
- Calculate new values as
child1 = alpha * parent1 + (1 - alpha) * parent2andchild2 = (1 - alpha) * parent1 + alpha * parent2. - Apply bounds repair if values fall outside the variable bounds.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
probability
|
float
|
Crossover probability (0.0 to 1.0) |
0.9
|
repair_operator
|
Callable[[float, float, float], float] | None
|
Optional function to repair out-of-bounds values. If None, values are clamped to the variable bounds using min/max. Signature: repair_operator(value: float, lower_bound: float, upper_bound: float) -> float |
None
|
Raises:
| Type | Description |
|---|---|
ValueError
|
If probability is not in [0,1] |
Reference
Michalewicz, Z. (1996). Genetic Algorithms + Data Structures = Evolution Programs. Springer-Verlag, Berlin.
Source code in src/jmetal/operator/crossover.py
doCrossover(probability, parent1, parent2)
¶
Perform the arithmetic crossover operation.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
probability
|
float
|
Crossover probability |
required |
parent1
|
FloatSolution
|
First parent solution |
required |
parent2
|
FloatSolution
|
Second parent solution |
required |
Returns:
| Type | Description |
|---|---|
list[FloatSolution]
|
A list containing two offspring solutions |
Source code in src/jmetal/operator/crossover.py
1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 | |
UnimodalNormalDistributionCrossover(probability=0.9, zeta=0.5, eta=0.35, repair_operator=None, rng=None)
¶
Bases: Crossover[FloatSolution, FloatSolution]
Unimodal Normal Distribution Crossover (UNDX) for real-valued solutions.
UNDX is a multi-parent crossover operator that generates offspring based on the normal distribution defined by three parent solutions. It is particularly effective for continuous optimization problems as it preserves the statistics of the population.
Reference
Onikura, T., & Kobayashi, S. (1999). Extended UNIMODAL DISTRIBUTION CROSSOVER for REAL-CODED GENETIC ALGORITHMS. In Proceedings of the 1999 Congress on Evolutionary Computation-CEC99 (Cat. No. 99TH8406) (Vol. 2, pp. 1581-1588). IEEE.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
probability
|
float
|
Crossover probability (0.0 to 1.0) |
0.9
|
zeta
|
float
|
Controls the spread along the line connecting parents (typically in [0.1, 1.0], where smaller values produce offspring closer to the parents) |
0.5
|
eta
|
float
|
Controls the spread in the orthogonal direction (typically in [0.1, 0.5], where smaller values produce more concentrated distributions) |
0.35
|
repair_operator
|
Callable[[float, float, float], float] | None
|
Optional function to repair out-of-bounds values. If None, values are clamped to the variable bounds using min/max. Signature: repair_operator(value: float, lower_bound: float, upper_bound: float) -> float |
None
|
Raises:
| Type | Description |
|---|---|
ValueError
|
If probability is not in [0,1] or if zeta or eta are negative |
Source code in src/jmetal/operator/crossover.py
doCrossover(probability, parent1, parent2, parent3)
¶
Perform the UNDX crossover operation.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
probability
|
float
|
Crossover probability |
required |
parent1
|
FloatSolution
|
First parent solution |
required |
parent2
|
FloatSolution
|
Second parent solution |
required |
parent3
|
FloatSolution
|
Third parent solution (used to determine the orthogonal direction) |
required |
Returns:
| Type | Description |
|---|---|
list[FloatSolution]
|
A list containing two offspring solutions |
Source code in src/jmetal/operator/crossover.py
1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 | |
DifferentialEvolutionCrossover(CR, F, K=0.5, rng=None)
¶
Bases: Crossover[FloatSolution, FloatSolution]
Differential Evolution (DE) crossover operator for real-valued solutions.
This operator implements the standard DE crossover used in the DE/rand/1/bin and DE/best/1/bin variants. It creates a trial vector by combining the target vector with a difference vector, then performs binomial crossover between the target and trial vectors.
The operator requires three parents and three mutation factors (F, CR, and K). The first parent is the target vector, while the other two are used to compute the difference vector.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
CR
|
float
|
Crossover probability (0.0 to 1.0). Controls the probability of each variable being taken from the trial vector versus the target vector. |
required |
F
|
float
|
Differential weight (mutation factor) for the difference vector. Typically in [0, 2]. |
required |
K
|
float
|
Scaling factor for the difference vector. Typically in [0, 1]. |
0.5
|
Raises:
| Type | Description |
|---|---|
ValueError
|
If CR is not in [0,1] or F/K are negative. |
Reference
Storn, R., & Price, K. (1997). Differential evolution - a simple and efficient heuristic for global optimization over continuous spaces. Journal of global optimization, 11(4), 341-359.
Source code in src/jmetal/operator/crossover.py
execute(parents)
¶
Execute the differential evolution crossover ('best/1/bin' variant in jMetal).
Source code in src/jmetal/operator/crossover.py
Mutation¶
mutation
¶
NullMutation()
¶
Source code in src/jmetal/operator/mutation.py
get_name()
¶
Get the name of the operator.
Returns:
| Name | Type | Description |
|---|---|---|
str |
str
|
A string containing the operator name and mutation probability. |
BitFlipMutation(probability, rng=None)
¶
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.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
probability
|
float
|
The probability of flipping each bit (0.0 to 1.0) |
required |
Raises:
| Type | Description |
|---|---|
ValueError
|
If probability is not in range [0.0, 1.0] |
Source code in src/jmetal/operator/mutation.py
execute(solution)
¶
Execute the bit flip mutation operation.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
solution
|
BinarySolution
|
The solution to be mutated. Must be a BinarySolution with a 'bits' attribute. |
required |
Returns:
| Type | Description |
|---|---|
BinarySolution
|
The mutated solution (modified in-place) |
Raises:
| Type | Description |
|---|---|
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.
Source code in src/jmetal/operator/mutation.py
get_name()
¶
Return the name of the operator.
Returns:
| Name | Type | Description |
|---|---|---|
str |
str
|
A string representing the name of the operator |
PolynomialMutation(probability=0.01, distribution_index=20.0, repair_operator=None, rng=None)
¶
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.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
probability
|
float
|
The probability of mutating each variable (0 ≤ p ≤ 1). |
0.01
|
distribution_index
|
float
|
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 |
20.0
|
repair_operator
|
Callable[[float, float, float], float] | None
|
Optional function to repair out-of-bounds values. If None, values are clamped to the variable bounds. |
None
|
Raises:
| Type | Description |
|---|---|
ValueError
|
If probability is not in [0,1] or distribution_index is negative. |
Source code in src/jmetal/operator/mutation.py
IntegerPolynomialMutation(probability, distribution_index=20.0, repair_operator=None, rng=None)
¶
Bases: Mutation[IntegerSolution]
Polynomial mutation operator for integer-valued decision variables.
This operator adapts the polynomial mutation for integer solutions by rounding the continuous values to the nearest integer. It's particularly useful for problems where variables must take discrete integer values.
The mutation works by: 1. Applying polynomial mutation to the integer variable (treated as float) 2. Rounding the result to the nearest integer 3. Clamping the value to the variable's bounds
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
probability
|
float
|
The probability of mutating each variable (0 ≤ p ≤ 1). |
required |
distribution_index
|
float
|
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 |
20.0
|
Example
from jmetal.operator import IntegerPolynomialMutation from jmetal.core.solution import IntegerSolution
Create an integer solution with bounds [0, 10] for all variables¶
solution = IntegerSolution(3, 1, 0) # 3 variables, 1 objective, 0 constraints solution.variables = [5, 5, 5] solution.lower_bound = [0] * 3 solution.upper_bound = [10] * 3
Apply polynomial mutation with 100% probability¶
mutation = IntegerPolynomialMutation(probability=1.0, distribution_index=20.0) mutated = mutation.execute(solution)
Variables will be mutated with integer values within [0, 10]¶
Source code in src/jmetal/operator/mutation.py
get_name()
¶
Get the name of the operator.
Returns:
| Name | Type | Description |
|---|---|---|
str |
str
|
A string containing the operator name and distribution index. |
SimpleRandomMutation(probability, rng=None)
¶
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.
The mutation works by:
- For each variable, with probability
probability, replace its value with a random value from a uniform distribution between the variable's lower and upper bounds. - Leave the variable unchanged otherwise.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
probability
|
float
|
The probability of mutating each variable (0 ≤ p ≤ 1). Higher values increase exploration but may disrupt good solutions. |
required |
Example
from jmetal.operator import SimpleRandomMutation from jmetal.core.solution import FloatSolution
Create a solution with bounds [0, 10] for all variables¶
solution = FloatSolution([0, 0], [10, 10], 1) # 2 variables, 1 objective solution.variables = [5.0, 5.0] # Initial values
Apply random mutation with 50% probability¶
mutation = SimpleRandomMutation(probability=0.5) mutated = mutation.execute(solution)
Each variable has a 50% chance to be replaced with a random value in [0, 10]¶
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
probability
|
float
|
The probability of mutating each variable (0 ≤ p ≤ 1). |
required |
Raises:
| Type | Description |
|---|---|
ValueError
|
If probability is not in [0,1]. |
Source code in src/jmetal/operator/mutation.py
UniformMutation(probability, perturbation=0.5, repair_operator=None, rng=None)
¶
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.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
probability
|
float
|
The probability of mutating each variable (0 ≤ p ≤ 1). |
required |
perturbation
|
float
|
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 |
0.5
|
Raises:
| Type | Description |
|---|---|
ValueError
|
If probability is not in [0,1] or perturbation is not positive. |
Source code in src/jmetal/operator/mutation.py
NonUniformMutation(probability, perturbation=0.5, max_iterations=1000, repair_operator=None, rng=None)
¶
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::
delta(t, y) = y * (r * (1 - t/T)^b - 1) if r <= 0.5
delta(t, y) = y * (1 - r * (1 - t/T)^b) if r > 0.5
where t is the current iteration, T is max_iterations, b is the perturbation
index, r is a random number in [0, 1], and y is the variable's range.
The operator is particularly useful for: - Fine-tuning solutions in later generations - Problems requiring adaptive exploration/exploitation balance - Situations where solution precision increases over time
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
probability
|
float
|
The probability of mutating each variable (0 ≤ p ≤ 1). |
required |
perturbation
|
float
|
Controls the perturbation strength (must be > 0). - Lower values (e.g., 1-5): Smoother decrease in mutation strength - Higher values (e.g., 5-20): Faster transition to smaller mutations |
0.5
|
max_iterations
|
int
|
The maximum number of iterations/generations (must be > 0). This is used to calculate the current progress (t/T). |
1000
|
Example
from jmetal.operator import NonUniformMutation from jmetal.core.solution import FloatSolution
Create a solution with bounds [0, 10] for all variables¶
solution = FloatSolution([0, 0], [10, 10], 1) # 2 variables, 1 objective solution.variables = [5.0, 5.0] # Initial values
Create a non-uniform mutation operator¶
With 30% mutation probability, medium perturbation (5.0), and 1000 max iterations¶
mutation = NonUniformMutation(probability=0.3, perturbation=5.0, max_iterations=1000)
In early generations (e.g., iteration 10 of 1000)¶
mutation.current_iteration = 10 mutated_early = mutation.execute(solution)
In later generations (e.g., iteration 900 of 1000)¶
mutation.current_iteration = 900 mutated_late = mutation.execute(solution)
Later mutations will be much smaller in magnitude¶
Note
Remember to update current_iteration before each generation to ensure
proper adaptation of the mutation strength.
Raises:
| Type | Description |
|---|---|
ValueError
|
If probability is not in [0,1] or parameters are not positive. |
Source code in src/jmetal/operator/mutation.py
execute(solution)
¶
Execute the non-uniform mutation on a solution.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
solution
|
FloatSolution
|
The solution to be mutated. |
required |
Returns:
| Type | Description |
|---|---|
FloatSolution
|
The mutated solution. |
Source code in src/jmetal/operator/mutation.py
set_current_iteration(current_iteration)
¶
Set the current iteration number for controlling mutation strength.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
current_iteration
|
int
|
The current iteration number (must be ≥ 0). |
required |
Source code in src/jmetal/operator/mutation.py
get_name()
¶
Get the name of the operator.
Returns:
| Type | Description |
|---|---|
str
|
A string containing the operator name and parameters. |
Source code in src/jmetal/operator/mutation.py
PermutationSwapMutation(probability, rng=None)
¶
Bases: Mutation[PermutationSolution]
Implementation of a swap mutation operator for permutation solutions.
This operator randomly selects two distinct positions in the permutation and swaps their values. It is commonly used for permutation-based optimization problems like the Traveling Salesman Problem (TSP).
The mutation works by: 1. Randomly selecting two distinct positions in the permutation 2. Swapping the values at these positions 3. Only performing the swap with a given probability
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
probability
|
float
|
The probability of applying the mutation to a solution (0 ≤ p ≤ 1). If the probability is 1.0, the mutation is always applied. |
required |
Example
from jmetal.operator import PermutationSwapMutation from jmetal.core.solution import PermutationSolution
Create a permutation solution [0, 1, 2, 3, 4]¶
solution = PermutationSolution(5, 1) # 5 variables, 1 objective solution.variables = [0, 1, 2, 3, 4]
Apply swap mutation with 100% probability¶
mutation = PermutationSwapMutation(probability=1.0) mutated = mutation.execute(solution)
Two random positions will be swapped, e.g., [2, 1, 0, 3, 4]¶
Source code in src/jmetal/operator/mutation.py
CompositeMutation(mutation_operator_list)
¶
A composite mutation operator that applies different mutation operators to different solution components.
This operator is particularly useful for composite solutions where each component may require a different mutation strategy. It maintains a list of mutation operators, one for each component of the composite solution.
The mutation works by: 1. Taking a composite solution as input 2. Applying each mutation operator to the corresponding solution component 3. Combining the results into a new composite solution
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
mutation_operator_list
|
list[Mutation]
|
A list of mutation operators, one for each component of the composite solution. The length of this list must match the number of variables in the composite solution. |
required |
Raises:
| Type | Description |
|---|---|
ValueError
|
If the mutation_operator_list is empty or None. |
TypeError
|
If any element in mutation_operator_list is not a subclass of Mutation. |
Example
from jmetal.operator import CompositeMutation, BitFlipMutation, PolynomialMutation from jmetal.core.solution import CompositeSolution, BinarySolution, FloatSolution
Create a composite solution with binary and float components¶
binary_solution = BinarySolution(5, 1) # 5 bits, 1 objective float_solution = FloatSolution([0]3, [1]3, 1) # 3 variables, 1 objective composite = CompositeSolution([binary_solution, float_solution])
Create a composite mutation with appropriate operators for each component¶
mutation = CompositeMutation([ ... BitFlipMutation(0.1), # For binary component ... PolynomialMutation(0.1, 20) # For float component ... ])
Apply the composite mutation¶
mutated = mutation.execute(composite)
Source code in src/jmetal/operator/mutation.py
get_name()
¶
Get the name of the operator.
Returns:
| Name | Type | Description |
|---|---|---|
str |
str
|
A string containing the operator name and the names of the component operators. |
Source code in src/jmetal/operator/mutation.py
ScrambleMutation(probability, rng=None)
¶
Bases: Mutation[PermutationSolution]
Implementation of a scramble mutation operator for permutation solutions.
This operator selects a random subsequence of the permutation and randomly reorders (scrambles) the elements within that subsequence. It is particularly useful for permutation problems where the relative ordering of elements is important.
The mutation works by: 1. Randomly selecting a subsequence of the permutation (limited to max 20 elements) 2. Randomly shuffling the elements within this subsequence 3. Only performing the scramble with a given probability
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
probability
|
float
|
The probability of applying the mutation to a solution (0 ≤ p ≤ 1). If the probability is 1.0, the mutation is always applied. |
required |
Example
from jmetal.operator import ScrambleMutation from jmetal.core.solution import PermutationSolution
Create a permutation solution [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]¶
solution = PermutationSolution(10, 1) # 10 variables, 1 objective solution.variables = list(range(10))
Apply scramble mutation with 100% probability¶
mutation = ScrambleMutation(probability=1.0) mutated = mutation.execute(solution)
A random subsequence will be scrambled, e.g., [0, 1, 4, 3, 2, 5, 6, 7, 8, 9]¶
Source code in src/jmetal/operator/mutation.py
get_name()
¶
Get the name of the operator.
Returns:
| Name | Type | Description |
|---|---|---|
str |
str
|
A string containing the operator name. |
LevyFlightMutation(mutation_probability=0.01, beta=1.5, step_size=0.01, repair_operator=None, rng=None)
¶
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:
- Generate
ufrom a normal distribution scaled by a factor derived from the beta parameter (via the gamma function). - Generate
vfrom a standard normal distribution. - Compute the Lévy step as
udivided by the absolute value ofvraised to the power1 / beta.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
mutation_probability
|
float
|
The probability of mutating each variable (0 ≤ p ≤ 1). |
0.01
|
beta
|
float
|
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 |
1.5
|
step_size
|
float
|
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 |
0.01
|
repair_operator
|
Callable[[float, float, float], float] | None
|
Optional function to repair out-of-bounds values. If None, values are clamped to the variable bounds. |
None
|
Raises:
| Type | Description |
|---|---|
ValueError
|
If parameters are outside their valid ranges. |
Source code in src/jmetal/operator/mutation.py
PowerLawMutation(probability=0.01, delta=1.0, repair_operator=None, rng=None)
¶
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)
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
probability
|
float
|
The probability of mutating each variable (0 ≤ p ≤ 1). |
0.01
|
delta
|
float
|
The power-law exponent parameter (must be > 0). Controls distribution shape: values below 1.0 give more uniform distributions with moderate perturbations, values near 1.0 balance exploration and exploitation (the default), and values above 1.0 give heavy-tailed distributions favoring small perturbations with occasional large jumps. |
1.0
|
repair_operator
|
Callable[[float, float, float], float] | None
|
Optional function to repair out-of-bounds values. If None, values are clamped to the variable bounds. |
None
|
Raises:
| Type | Description |
|---|---|
ValueError
|
If probability is not in [0,1] or delta is not positive. |
Source code in src/jmetal/operator/mutation.py
Selection¶
selection
¶
S = TypeVar('S', bound=Solution)
module-attribute
¶
.. module:: selection :platform: Unix, Windows :synopsis: Module implementing selection operators.
.. moduleauthor:: Antonio J. Nebro antonio@lcc.uma.es, Antonio BenÃtez-Hidalgo antonio.b@uma.es
RouletteWheelSelection(objective_index=0, rng=None)
¶
Performs roulette wheel selection.
This selection operator selects solutions based on their fitness values using a roulette wheel mechanism. It can handle both single and multi-objective optimization by using the first objective value for selection. For multi-objective optimization, consider using a proper fitness assignment strategy first.
Note: This implementation assumes all objective values are non-negative. If negative values are present, a proper normalization should be applied first.
Initialize the roulette wheel selection operator.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
objective_index
|
int
|
Index of the objective to use for selection (default: 0). Only used if no fitness value is present in the solution attributes. |
0
|
rng
|
Generator | None
|
Optional random generator. When None, falls back to the global |
None
|
Source code in src/jmetal/operator/selection.py
execute(front)
¶
Select a solution using roulette wheel selection.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
front
|
list[S]
|
List of solutions to select from. |
required |
Returns:
| Type | Description |
|---|---|
S
|
The selected solution. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If the front is None, empty, or contains invalid fitness values. |
Source code in src/jmetal/operator/selection.py
TournamentSelection(tournament_size=2, comparator=DominanceComparator(), rng=None)
¶
Performs k-ary tournament selection.
This selection operator randomly selects k solutions from the population and returns the best one according to the provided comparator. It's a generalization of binary tournament selection that allows controlling selection pressure through the tournament size.
A larger tournament size (k) increases selection pressure, favoring better solutions more strongly. A smaller k provides more diversity but slower convergence.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
tournament_size
|
int
|
Number of solutions to participate in each tournament (default: 2). Must be at least 2. |
2
|
comparator
|
Comparator
|
Comparator used to compare solutions (default: DominanceComparator). |
DominanceComparator()
|
rng
|
Generator | None
|
Optional random generator. When None, falls back to the global |
None
|
Example
from jmetal.operator import TournamentSelection from jmetal.util.comparator import DominanceComparator
Create a tournament selection with size 5¶
selector = TournamentSelection(tournament_size=5)
Select from a population¶
winner = selector.execute(population)
Source code in src/jmetal/operator/selection.py
execute(front)
¶
Execute the k-ary tournament selection.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
front
|
list[S]
|
List of solutions to select from. |
required |
Returns:
| Type | Description |
|---|---|
S
|
The best solution among the tournament participants. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If front is None, empty, or smaller than tournament size. |
Source code in src/jmetal/operator/selection.py
BinaryTournamentSelection(comparator=DominanceComparator(), rng=None)
¶
Bases: TournamentSelection
Performs binary tournament selection between two random solutions.
This is a specialization of TournamentSelection with tournament_size=2. It randomly selects two solutions from the population and returns the better one according to the provided comparator. If the comparator returns 0 (tie), a random solution is chosen.
This class is provided for convenience and backward compatibility. For more control over tournament size, use TournamentSelection directly.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
comparator
|
Comparator
|
Comparator used to compare solutions (default: DominanceComparator). |
DominanceComparator()
|
rng
|
Generator | None
|
Optional random generator. When None, falls back to the global |
None
|
Example
from jmetal.operator import BinaryTournamentSelection from jmetal.util.comparator import DominanceComparator
Create binary tournament selection¶
selector = BinaryTournamentSelection()
Or with a custom comparator¶
selector = BinaryTournamentSelection(comparator=DominanceComparator())
Select from a population¶
winner = selector.execute(population)
Source code in src/jmetal/operator/selection.py
BestSolutionSelection()
¶
Selects the best solution from a population based on dominance comparison.
This selection operator returns the non-dominated solution from the population. If multiple solutions are non-dominated with respect to each other, it returns the first one encountered in the front.
The comparison is done using the DominanceComparator, which follows these rules:
- Solution A dominates solution B if A is not worse than B in all objectives and A is strictly better than B in at least one objective.
- If neither solution dominates the other, they are considered non-dominated.
Example
from jmetal.operator import BestSolutionSelection from jmetal.core.solution import FloatSolution
Create a population of solutions¶
solution1 = FloatSolution([0], [1], 2) # 2 objectives solution1.objectives = [0.5, 0.8] solution2 = FloatSolution([0], [1], 2) solution2.objectives = [0.3, 0.9] population = [solution1, solution2]
Select the best solution¶
selector = BestSolutionSelection() best_solution = selector.execute(population)
Initialize the best solution selector.
Source code in src/jmetal/operator/selection.py
execute(front)
¶
Select the best solution from the front.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
front
|
list[S]
|
List of solutions to select from. |
required |
Returns:
| Type | Description |
|---|---|
S
|
The best solution in the front according to dominance comparison. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If front is None or empty. |
Source code in src/jmetal/operator/selection.py
get_name()
¶
Get the name of the selection operator.
Returns:
| Type | Description |
|---|---|
str
|
A string representing the name of the selection operator. |
NaryRandomSolutionSelection(number_of_solutions_to_be_returned=1, rng=None)
¶
Bases: Selection[list[S], list[S]]
Performs random selection of multiple solutions from a population.
This selection operator randomly selects a specified number of distinct solutions from the population with uniform probability. The selection is done without replacement, meaning each solution can be selected at most once.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
number_of_solutions_to_be_returned
|
int
|
Number of distinct solutions to select (default: 1). Must be a positive integer. |
1
|
rng
|
Generator | None
|
Optional random generator. When None, falls back to the global |
None
|
Example
from jmetal.operator import NaryRandomSolutionSelection
Select 3 random solutions¶
selector = NaryRandomSolutionSelection(number_of_solutions_to_be_returned=3) selected = selector.execute(population) # Returns List[S] with 3 solutions
Source code in src/jmetal/operator/selection.py
execute(front)
¶
Randomly select multiple solutions from the front.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
front
|
list[S]
|
List of solutions to select from. |
required |
Returns:
| Type | Description |
|---|---|
list[S]
|
A list of randomly selected solutions from the front. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If front is None, empty, or has fewer solutions than requested. |
Source code in src/jmetal/operator/selection.py
get_name()
¶
Get the name of the selection operator.
Returns:
| Type | Description |
|---|---|
str
|
A string representing the name of the selection operator. |
DifferentialEvolutionSelection(index_to_exclude=None, rng=None)
¶
Bases: Selection[list[S], list[S]]
Performs selection for differential evolution algorithms.
This selection operator is specifically designed for differential evolution algorithms. It selects three distinct solutions from the population, with an optional index to exclude (typically the current solution's index to avoid self-selection).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
index_to_exclude
|
int
|
Optional index of a solution to exclude from selection. This is useful to avoid selecting the same solution as the base vector. |
None
|
rng
|
Generator | None
|
Optional random generator. When None, falls back to the global |
None
|
Source code in src/jmetal/operator/selection.py
execute(front)
¶
Select three distinct solutions for differential evolution.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
front
|
list[S]
|
List of solutions to select from. |
required |
Returns:
| Type | Description |
|---|---|
list[S]
|
A list containing three distinct solutions from the front. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If front is None, empty, or has fewer than 4 solutions. |
Source code in src/jmetal/operator/selection.py
set_index_to_exclude(index)
¶
Set the index of the solution to exclude from selection.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
index
|
int
|
Index of the solution to exclude. Can be None to disable exclusion. |
required |
Source code in src/jmetal/operator/selection.py
get_name()
¶
Get the name of the selection operator.
Returns:
| Type | Description |
|---|---|
str
|
A string representing the name of the selection operator. |
RandomSelection(rng=None)
¶
Performs random selection of a solution from a population.
This selection operator randomly selects a single solution from the provided population with uniform probability. It's a simple selection method that doesn't consider solution quality.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
rng
|
Generator | None
|
Optional random generator. When None, falls back to the global |
None
|
Source code in src/jmetal/operator/selection.py
execute(front)
¶
Randomly select a solution from the front.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
front
|
list[S]
|
List of solutions to select from. |
required |
Returns:
| Type | Description |
|---|---|
S
|
A randomly selected solution from the front. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If front is None or empty. |
Source code in src/jmetal/operator/selection.py
RankingAndCrowdingDistanceSelection(max_population_size, dominance_comparator=DominanceComparator())
¶
Bases: Selection[list[S], list[S]]
Performs selection based on non-dominated ranking and crowding distance.
This selection operator first ranks the solutions using non-dominated sorting and then applies crowding distance to maintain diversity within each rank. It's commonly used in NSGA-II and other multi-objective evolutionary algorithms.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
max_population_size
|
int
|
Maximum number of solutions to select. |
required |
dominance_comparator
|
Comparator
|
Comparator used for non-dominated sorting. Defaults to DominanceComparator(). |
DominanceComparator()
|
Source code in src/jmetal/operator/selection.py
execute(front)
¶
Select solutions using non-dominated ranking and crowding distance.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
front
|
list[S]
|
List of solutions to select from. |
required |
Returns:
| Type | Description |
|---|---|
list[S]
|
A list of selected solutions, with size up to max_population_size. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If front is None, empty, or max_population_size is invalid. |
Source code in src/jmetal/operator/selection.py
get_name()
¶
Get the name of the selection operator.
Returns:
| Type | Description |
|---|---|
str
|
A string representing the name of the selection operator. |
RankingAndFitnessSelection(max_population_size, reference_point, dominance_comparator=DominanceComparator())
¶
Bases: Selection[list[S], list[S]]
Performs selection based on non-dominated ranking and hypervolume contribution.
This selection operator first ranks the solutions using non-dominated sorting and then applies hypervolume contribution to maintain diversity within each rank. It's commonly used in multi-objective evolutionary algorithms that aim to maximize the hypervolume indicator.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
max_population_size
|
int
|
Maximum number of solutions to select. |
required |
reference_point
|
S
|
Reference point used for hypervolume calculation. Should be dominated by all solutions. |
required |
dominance_comparator
|
Comparator
|
Comparator used for non-dominated sorting. Defaults to DominanceComparator(). |
DominanceComparator()
|
Source code in src/jmetal/operator/selection.py
hypesub(l, A, actDim, bounds, pvec, alpha, k)
¶
Recursively compute hypervolume contributions.
This is a helper method for hypervolume calculation. It's an implementation of the Hype algorithm for hypervolume approximation.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
l
|
int
|
Number of points. |
required |
A
|
list[list[float]]
|
List of objective vectors. |
required |
actDim
|
int
|
Current dimension being processed. |
required |
bounds
|
list[float]
|
Reference point coordinates. |
required |
pvec
|
list[int]
|
Indices of points in A. |
required |
alpha
|
list[float]
|
Weighting factors for hypervolume contribution. |
required |
k
|
int
|
Number of points to consider. |
required |
Returns:
| Type | Description |
|---|---|
list[float]
|
List of hypervolume contributions for each point. |
Source code in src/jmetal/operator/selection.py
compute_hypervol_fitness_values(population, reference_point, k)
¶
Compute hypervolume-based fitness values for a population.
This method computes the hypervolume contribution of each solution in the population and stores it in the solution's attributes as 'fitness'.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
population
|
list[S]
|
List of solutions to evaluate. |
required |
reference_point
|
S
|
Reference point for hypervolume calculation. |
required |
k
|
int
|
Number of points to consider for hypervolume approximation. If negative, uses the entire population size. |
required |
Returns:
| Type | Description |
|---|---|
list[S]
|
The input population with updated fitness values in their attributes. |
Source code in src/jmetal/operator/selection.py
execute(front)
¶
Select solutions using non-dominated ranking and hypervolume contribution.
This method first performs non-dominated sorting of the input front. It then fills the new population with solutions from the best ranks, using hypervolume contribution to select solutions when a rank needs to be split.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
front
|
list[S]
|
List of solutions to select from. |
required |
Returns:
| Type | Description |
|---|---|
list[S]
|
A list of selected solutions, with size equal to max_population_size. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If front is None or empty. |
Source code in src/jmetal/operator/selection.py
get_name()
¶
Get the name of the selection operator.
Returns:
| Type | Description |
|---|---|
str
|
A string representing the name of the selection operator. |
BinaryTournament2Selection(comparator_list, rng=None)
¶
Performs binary tournament selection with multiple comparators.
This selection operator uses a list of comparators in sequence to determine the winner between two randomly selected solutions. The first comparator that can determine a winner is used. If all comparators result in a tie, a random solution is chosen.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
comparator_list
|
list[Comparator]
|
List of comparators to use in sequence. |
required |
rng
|
Generator | None
|
Optional random generator. When None, falls back to the global |
None
|
Source code in src/jmetal/operator/selection.py
execute(front)
¶
Execute the binary tournament selection with multiple comparators.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
front
|
list[S]
|
List of solutions to select from. |
required |
Returns:
| Type | Description |
|---|---|
S
|
The selected solution. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If front is None, empty, or contains only one solution. |
Source code in src/jmetal/operator/selection.py
Repair¶
repair
¶
FloatRepairOperator
¶
Base interface for repair operators that work on continuous (float) variables.
Implementations should provide two APIs:
- repair_scalar(value, lb, ub) repairs a single float value.
- repair_vector(values, lbs, ubs) repairs arrays element-wise and returns a
numpy array.
A callable adapter (ensure_float_repair) is provided so that existing code
that passes simple scalar callables continues to work. The default
repair_vector implementation applies repair_scalar element-wise.
ClampFloatRepair
¶
Bases: FloatRepairOperator
Default clamp-to-bounds repair for float variables.
This implementation reproduces the common min(max(x, lb), ub) behavior and
provides an optimized repair_vector using numpy.clip.
IntegerRepairOperator
¶
Repair operator for integer-valued variables.
Default behavior: round to the nearest integer and clamp to bounds.
NoOpRepair
¶
No-op repair operator: returns inputs unchanged.
Useful for solution types that do not require repair (binary, permutation), or as a placeholder in tests.
RandomUniformRepair(rng=None)
¶
Bases: FloatRepairOperator
Repair operator that replaces out-of-bounds values by a uniform sample inside the provided bounds. Uses a NumPy Generator for reproducibility.
Source code in src/jmetal/operator/repair.py
ReflectiveRepair
¶
Bases: FloatRepairOperator
Reflective (mirror) repair: values outside bounds are reflected back into the interval. Repeated reflections handled via modulo arithmetic.
BoundSwapRepair
¶
Bases: FloatRepairOperator
If value exceeds upper bound assign lower bound, and viceversa.
This is an aggressive repair that 'jumps' the value to the opposite bound.
ensure_float_repair(repair)
¶
Normalize a repair argument into a FloatRepairOperator instance.
Rules:
- If repair is None: return ClampFloatRepair() (default clamp behavior).
- If repair is already a FloatRepairOperator: return it unchanged.
- If repair is a callable: wrap it in an adapter that implements
repair_scalar and inherits the default repair_vector behavior.
Source code in src/jmetal/operator/repair.py
Replacement¶
replacement
¶
Replacement
¶
Bases: ABC, Generic[S]
Base class for population replacement strategies.
A replacement strategy decides which solutions from a parent population and an offspring population survive into the next generation. Concrete strategies (ranking-based, crowding-distance-based, hypervolume-based, ...) differ enough in their selection logic that this base class only fixes the shared contract, not any implementation.
replace(solution_list, offspring_list)
abstractmethod
¶
Combine a parent and an offspring population and select the survivors.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
solution_list
|
list[S]
|
The parent population. |
required |
offspring_list
|
list[S]
|
The offspring population. |
required |
Returns:
| Type | Description |
|---|---|
list[S]
|
The population that survives into the next generation. |
Source code in src/jmetal/operator/replacement.py
RemovalPolicyType
¶
Bases: Enum
Defines the policy for removing solutions in replacement strategies.
Attributes:
| Name | Type | Description |
|---|---|---|
SEQUENTIAL |
Remove solutions one by one, updating density estimates after each removal. This is more computationally expensive but can lead to better diversity. |
|
ONE_SHOT |
Remove all solutions at once based on initial density estimates. This is faster but may be less accurate in maintaining diversity. |
RankingAndDensityEstimatorReplacement(ranking, density_estimator, removal_policy=RemovalPolicyType.ONE_SHOT)
¶
Bases: Replacement[S]
A replacement strategy that combines non-dominated ranking with density estimation.
This replacement strategy is commonly used in multi-objective evolutionary algorithms to maintain a good balance between convergence and diversity in the population. It first ranks solutions using non-dominated sorting and then applies a density estimator to select solutions within each front.
The replacement process works as follows: 1. Combine parent and offspring populations 2. Rank all solutions using non-dominated sorting 3. Fill the new population with solutions from the best fronts 4. When a front needs to be split, use the density estimator to select the most diverse solutions
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
ranking
|
Ranking
|
The ranking strategy to use (e.g., FastNonDominatedRanking) |
required |
density_estimator
|
DensityEstimator
|
The density estimator to use (e.g., CrowdingDistance) |
required |
removal_policy
|
RemovalPolicyType
|
The policy for removing solutions (SEQUENTIAL or ONE_SHOT) |
ONE_SHOT
|
Example
from jmetal.operator import RankingAndDensityEstimatorReplacement from jmetal.util.ranking import FastNonDominatedRanking from jmetal.util.density_estimator import CrowdingDistance
Create a replacement operator with crowding distance¶
replacement = RankingAndDensityEstimatorReplacement( ... ranking=FastNonDominatedRanking(), ... density_estimator=CrowdingDistance(), ... removal_policy=RemovalPolicyType.SEQUENTIAL ... )
Apply replacement to combine parent and offspring populations¶
new_population = replacement.replace(parents, offspring)
Source code in src/jmetal/operator/replacement.py
replace(solution_list, offspring_list)
¶
Combine parent and offspring populations and select the best solutions.
This method combines the parent and offspring populations, ranks all solutions using non-dominated sorting, and then applies the specified removal policy to select the best solutions.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
solution_list
|
list[S]
|
The parent population (list of solutions). |
required |
offspring_list
|
list[S]
|
The offspring population (list of solutions). |
required |
Returns:
| Type | Description |
|---|---|
list[S]
|
A new population with the same size as solution_list containing the |
list[S]
|
best solutions from the combined population. |
Note
The size of the returned population will be equal to the size of solution_list, not the combined size of both populations.
Source code in src/jmetal/operator/replacement.py
sequential_truncation(ranking_id, size_of_the_result_list)
¶
Select solutions using sequential truncation based on density estimation.
This method is called recursively to fill the new population with solutions from the best non-dominated fronts. When a front needs to be split, it uses the density estimator to select the most diverse solutions.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
ranking_id
|
int
|
The current front index to process. |
required |
size_of_the_result_list
|
int
|
Number of solutions still needed to fill the population. |
required |
Returns:
| Type | Description |
|---|---|
list[S]
|
A list of selected solutions from the current and subsequent fronts. |
Note
This method is typically called internally by the replace() method and should not be called directly in most cases.
Source code in src/jmetal/operator/replacement.py
one_shot_truncation(ranking_id, size_of_the_result_list)
¶
Select solutions using one-shot truncation based on density estimation.
This method is similar to sequential_truncation but is more efficient as it doesn't recompute density estimates after each removal. It's faster but may be less accurate in maintaining diversity compared to sequential truncation.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
ranking_id
|
int
|
The current front index to process. |
required |
size_of_the_result_list
|
int
|
Number of solutions still needed to fill the population. |
required |
Returns:
| Type | Description |
|---|---|
list[S]
|
A list of selected solutions from the current and subsequent fronts. |
Note
This method is typically called internally by the replace() method when the removal policy is set to ONE_SHOT.
Source code in src/jmetal/operator/replacement.py
RankingAndCrowdingDistanceReplacement(ranking=None, density_estimator=None)
¶
Bases: Replacement[S]
Replacement operator based on non-dominated ranking and crowding distance.
This operator combines the parent and offspring populations, ranks them using non-dominated sorting, and selects the best solutions based on crowding distance. It's a specialized version of RankingAndDensityEstimatorReplacement that's specifically designed for NSGA-II and similar algorithms.
The replacement process works as follows: 1. Combine parent and offspring populations 2. Rank all solutions using non-dominated sorting 3. Fill the new population with solutions from the best fronts 4. When a front needs to be split, use crowding distance to select the most diverse solutions
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
ranking
|
Ranking
|
The ranking strategy to use (default: FastNonDominatedRanking) |
None
|
density_estimator
|
DensityEstimator
|
The density estimator to use (default: CrowdingDistance) |
None
|
Example
from jmetal.operator import RankingAndCrowdingDistanceReplacement from jmetal.core.solution import FloatSolution
Create a replacement operator¶
replacement = RankingAndCrowdingDistanceReplacement()
Apply replacement to combine parent and offspring populations¶
new_population = replacement.replace(parents, offspring)
Source code in src/jmetal/operator/replacement.py
replace(solution_list, offspring_list)
¶
Replace solutions in the population with offspring solutions.
This method combines the parent and offspring populations, ranks them using non-dominated sorting, and selects the best solutions based on crowding distance.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
solution_list
|
list[S]
|
The parent population (list of solutions). |
required |
offspring_list
|
list[S]
|
The offspring population (list of solutions). |
required |
Returns:
| Type | Description |
|---|---|
list[S]
|
A new population with the same size as solution_list containing the |
list[S]
|
best solutions from the combined population. |
Note
The size of the returned population will be equal to the size of solution_list, not the combined size of both populations.
Source code in src/jmetal/operator/replacement.py
get_name()
¶
Get the name of the replacement operator.
Returns:
| Type | Description |
|---|---|
str
|
A string representing the name of this replacement operator. |
SMSEMOAReplacement(ranking=None)
¶
Bases: Replacement[S]
Replacement operator for the SMS-EMOA (S-Metric Selection Evolutionary Multiobjective Algorithm).
This replacement operator combines the parent and offspring populations, ranks them
using non-dominated sorting, keeps every front except the last one whole, and prunes
the last front down to size by sorting it by hypervolume contribution and dropping the
worst-contributing solutions -- the same logic as
jmetal.algorithm.multiobjective.smsemoa.SMSEMOA.replacement, generalized from
"exactly one excess solution" (true when offspring_population_size=1, SMS-EMOA's
usual steady-state configuration) to any number of excess solutions.
The hypervolume contribution of a solution is the hypervolume that would be lost if that solution was removed from the front. Pruning by it, front by front, is what keeps a good spread of solutions along the Pareto front.
The reference point is not fixed at construction time: it is recomputed on every
replace() call as the merged population's worst objective values plus an offset of
1.0, matching the classic SMSEMOA's formula.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
ranking
|
Ranking
|
The ranking strategy to use (default: |
None
|
Example
from jmetal.operator import SMSEMOAReplacement
replacement = SMSEMOAReplacement() new_population = replacement.replace(parents, offspring)
Initialize the SMS-EMOA replacement operator.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
ranking
|
Ranking
|
The ranking strategy to use. Defaults to |
None
|
Source code in src/jmetal/operator/replacement.py
replace(solution_list, offspring_list)
¶
Replace solutions in the population with offspring solutions.
This method combines the parent and offspring populations, ranks them using
non-dominated sorting, keeps every front but the last whole, and -- if the last
front doesn't fit entirely -- sorts it by hypervolume contribution (descending)
and keeps only as many of its best-contributing solutions as needed to reach the
size of solution_list. Contributions are computed once, over the whole
overflowing front, exactly as jmetal.algorithm.multiobjective.smsemoa.SMSEMOA's
own replacement does for its single-excess-solution case -- this is that same
computation generalized to however many solutions are in excess.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
solution_list
|
list[S]
|
The parent population (list of solutions). |
required |
offspring_list
|
list[S]
|
The offspring population (list of solutions). |
required |
Returns:
| Type | Description |
|---|---|
list[S]
|
A new population of the same size as solution_list containing the |
list[S]
|
best solutions from the combined population. |