| 1 | package net.bmahe.genetics4j.gp.spec.selection; | |
| 2 | ||
| 3 | import java.util.Comparator; | |
| 4 | ||
| 5 | import org.apache.commons.lang3.Validate; | |
| 6 | import org.immutables.value.Value; | |
| 7 | ||
| 8 | import net.bmahe.genetics4j.core.Individual; | |
| 9 | import net.bmahe.genetics4j.core.spec.selection.SelectionPolicy; | |
| 10 | import net.bmahe.genetics4j.core.spec.selection.Tournament; | |
| 11 | ||
| 12 | /** | |
| 13 | * Double tournament selection strategy that combines fitness-based and parsimony-based selection to control bloat in | |
| 14 | * genetic programming and other evolutionary algorithms. | |
| 15 | * | |
| 16 | * <p>Double tournament selection operates in two modes: | |
| 17 | * <ul> | |
| 18 | * <li><b>Fitness First Mode</b> (default): Performs two independent fitness tournaments, then applies parsimony | |
| 19 | * selection between the winners to select the less complex individual</li> | |
| 20 | * <li><b>Parsimony First Mode</b>: For each tournament candidate, performs parsimony selection on random pairs first, | |
| 21 | * then selects the fittest among the parsimony winners</li> | |
| 22 | * </ul> | |
| 23 | * | |
| 24 | * <p>The parsimony tournament uses a probabilistic approach where the parsimony tournament size parameter controls the | |
| 25 | * selection pressure toward less complex individuals: | |
| 26 | * <ul> | |
| 27 | * <li>Size 0.0: Always selects randomly (no parsimony pressure)</li> | |
| 28 | * <li>Size 1.0: Balanced selection between complexity preferences</li> | |
| 29 | * <li>Size 2.0: Always selects the less complex individual</li> | |
| 30 | * </ul> | |
| 31 | * | |
| 32 | * <p>This selection method is particularly effective in genetic programming where it helps prevent code bloat while | |
| 33 | * maintaining competitive fitness levels. | |
| 34 | * | |
| 35 | * @param <T> the fitness type, must be Comparable | |
| 36 | * | |
| 37 | * @see DoubleTournamentSelector | |
| 38 | * @see Tournament | |
| 39 | */ | |
| 40 | @Value.Immutable | |
| 41 | public abstract class DoubleTournament<T extends Comparable<T>> implements SelectionPolicy { | |
| 42 | ||
| 43 | /** | |
| 44 | * The fitness tournament configuration used for selecting individuals based on fitness. This tournament determines | |
| 45 | * how many candidates compete in each fitness-based selection round. | |
| 46 | * | |
| 47 | * @return the tournament configuration for fitness-based selection | |
| 48 | */ | |
| 49 | @Value.Parameter | |
| 50 | public abstract Tournament<T> fitnessTournament(); | |
| 51 | ||
| 52 | /** | |
| 53 | * Comparator used to evaluate parsimony (complexity) between individuals. Typically compares individuals based on | |
| 54 | * size, depth, or other complexity metrics. The comparator should return: | |
| 55 | * <ul> | |
| 56 | * <li>Negative value if first individual is less complex than second</li> | |
| 57 | * <li>Zero if both individuals have equal complexity</li> | |
| 58 | * <li>Positive value if first individual is more complex than second</li> | |
| 59 | * </ul> | |
| 60 | * | |
| 61 | * @return the comparator for evaluating individual complexity | |
| 62 | */ | |
| 63 | @Value.Parameter | |
| 64 | public abstract Comparator<Individual<T>> parsimonyComparator(); | |
| 65 | ||
| 66 | /** | |
| 67 | * Controls the selection pressure toward less complex individuals in parsimony tournaments. Must be between 0.0 and | |
| 68 | * 2.0 inclusive. | |
| 69 | * <ul> | |
| 70 | * <li>0.0: No parsimony pressure, selection is random</li> | |
| 71 | * <li>1.0: Balanced parsimony pressure</li> | |
| 72 | * <li>2.0: Maximum parsimony pressure, always selects less complex individual</li> | |
| 73 | * </ul> | |
| 74 | * | |
| 75 | * @return the parsimony tournament size parameter | |
| 76 | */ | |
| 77 | @Value.Parameter | |
| 78 | public abstract double parsimonyTournamentSize(); | |
| 79 | ||
| 80 | /** | |
| 81 | * Determines the order of selection operations. | |
| 82 | * <ul> | |
| 83 | * <li>{@code true} (default): Fitness first mode - perform fitness tournaments first, then apply parsimony selection | |
| 84 | * between winners</li> | |
| 85 | * <li>{@code false}: Parsimony first mode - apply parsimony selection to random pairs first, then perform fitness | |
| 86 | * tournament among parsimony winners</li> | |
| 87 | * </ul> | |
| 88 | * | |
| 89 | * @return true for fitness-first mode, false for parsimony-first mode | |
| 90 | */ | |
| 91 | @Value.Default | |
| 92 | public boolean doFitnessFirst() { | |
| 93 |
2
1. doFitnessFirst : replaced boolean return with false for net/bmahe/genetics4j/gp/spec/selection/DoubleTournament::doFitnessFirst → KILLED 2. doFitnessFirst : Substituted 1 with 0 → KILLED |
return true; |
| 94 | } | |
| 95 | ||
| 96 | /** | |
| 97 | * Validates that the parsimony tournament size is within the allowed range [0.0, 2.0]. | |
| 98 | * | |
| 99 | * @throws IllegalArgumentException if parsimony tournament size is outside valid range | |
| 100 | */ | |
| 101 | @Value.Check | |
| 102 | public void check() { | |
| 103 | Validate.inclusiveBetween(0.0d, 2.0d, parsimonyTournamentSize()); | |
| 104 | } | |
| 105 | ||
| 106 | /** | |
| 107 | * Creates a new DoubleTournament selection policy with fitness-first mode enabled. | |
| 108 | * | |
| 109 | * @param <U> the fitness type, must be Comparable | |
| 110 | * @param fitnessTournament the tournament configuration for fitness-based selection | |
| 111 | * @param parsimonyComparator comparator for evaluating individual complexity | |
| 112 | * @param parsimonyTournamentSize selection pressure parameter, must be between 0.0 and 2.0 | |
| 113 | * @return a new DoubleTournament instance with the specified parameters | |
| 114 | * @throws IllegalArgumentException if parsimony tournament size is outside valid range | |
| 115 | */ | |
| 116 | public static <U extends Comparable<U>> DoubleTournament<U> of(final Tournament<U> fitnessTournament, | |
| 117 | final Comparator<Individual<U>> parsimonyComparator, final double parsimonyTournamentSize) { | |
| 118 |
2
1. of : removed call to net/bmahe/genetics4j/gp/spec/selection/ImmutableDoubleTournament::of → KILLED 2. of : replaced return value with null for net/bmahe/genetics4j/gp/spec/selection/DoubleTournament::of → KILLED |
return ImmutableDoubleTournament.of(fitnessTournament, parsimonyComparator, parsimonyTournamentSize); |
| 119 | } | |
| 120 | } | |
Mutations | ||
| 93 |
1.1 2.2 |
|
| 118 |
1.1 2.2 |