View Javadoc
1   package net.bmahe.genetics4j.moo.nsga2.spec;
2   
3   import java.util.Comparator;
4   import java.util.Optional;
5   import java.util.function.Function;
6   
7   import org.immutables.value.Value;
8   
9   import net.bmahe.genetics4j.core.Genotype;
10  import net.bmahe.genetics4j.core.spec.selection.SelectionPolicy;
11  import net.bmahe.genetics4j.moo.FitnessVector;
12  import net.bmahe.genetics4j.moo.ObjectiveDistance;
13  
14  /**
15   * Tournament based NSGA2 selection
16   * <p>This method of selection follows the method describe in the NSGA2 paper where the individuals are sorted according
17   * to NSGA2 and then selected through tournaments where they are compared based on their NSGA2 metric
18   *
19   * @param <T> Type of the fitness measurement
20   */
21  @Value.Immutable
22  public abstract class TournamentNSGA2Selection<T extends Comparable<T>> implements SelectionPolicy {
23  
24  	/**
25  	 * Describe how many objectives are embedded in T
26  	 * 
27  	 * @return Number of objectives embedded in T
28  	 */
29  	@Value.Parameter
30  	public abstract int numberObjectives();
31  
32  	/**
33  	 * Override the dominance operator.
34  	 * <p>If not specified, it assumes the default comparator conforms to the Pareto dominance relation
35  	 * 
36  	 * @return
37  	 */
38  	@Value.Default
39  	public Comparator<T> dominance() {
40  		return (a, b) -> a.compareTo(b);
41  	}
42  
43  	/**
44  	 * Comparator used for deduplication of solution prior to processing
45  	 * <p>If not specified, it defaults to not do any deduplication
46  	 * 
47  	 * @return
48  	 */
49  	@Value.Default
50  	public Optional<Comparator<Genotype>> deduplicate() {
51  		return Optional.empty();
52  	}
53  
54  	/**
55  	 * Sort T based on the objective passed as a parameter
56  	 * 
57  	 * @return
58  	 */
59  	@Value.Parameter
60  	public abstract Function<Integer, Comparator<T>> objectiveComparator();
61  
62  	/**
63  	 * Define how to compute distances between fitness scores along their objectives
64  	 * 
65  	 * @return Distance computation method
66  	 */
67  	@Value.Parameter
68  	public abstract ObjectiveDistance<T> distance();
69  
70  	/**
71  	 * Number of candidates in each tournament
72  	 * 
73  	 * @return Number of candidates in each tournament
74  	 */
75  	@Value.Parameter
76  	public abstract int numCandidates();
77  
78  	public static class Builder<T extends Comparable<T>> extends ImmutableTournamentNSGA2Selection.Builder<T> {
79  	}
80  
81  	public static <U extends Comparable<U>> Builder<U> builder() {
82  		return new Builder<U>();
83  	}
84  
85  	/**
86  	 * Factory method to instantiate a Tournament based NSGA2 selection when fitness is defined as a FitnessVector of a
87  	 * Number
88  	 * 
89  	 * @param <U>              Type of the fitness measurement
90  	 * @param numberObjectives Number of objectives and dimensions of the FitnessVector
91  	 * @param numberCandidates Number of candidates in each tournament
92  	 * @param deduplicate      Deduplicator comparator. Null value with disable deduplication
93  	 * @return A new instance of TournamentNSGA2Selection
94  	 */
95  	public static <U extends Number & Comparable<U>> TournamentNSGA2Selection<FitnessVector<U>> ofFitnessVector(
96  			final int numberObjectives, final int numberCandidates, final Comparator<Genotype> deduplicate) {
97  
98  		final var builder = new Builder<FitnessVector<U>>();
99  
100 		builder.objectiveComparator((m) -> (a, b) -> Double.compare(a.get(m)
101 				.doubleValue(),
102 				b.get(m)
103 						.doubleValue()))
104 				.distance((a, b, m) -> Math.abs(b.get(m)
105 						.doubleValue()
106 						- a.get(m)
107 								.doubleValue()))
108 				.numberObjectives(numberObjectives)
109 				.numCandidates(numberCandidates)
110 				.deduplicate(Optional.ofNullable(deduplicate));
111 
112 		return builder.build();
113 	}
114 
115 	/**
116 	 * Factory method to instantiate a Tournament based NSGA2 selection when fitness is defined as a FitnessVector of a
117 	 * Number
118 	 * 
119 	 * @param <U>              Type of the fitness measurement
120 	 * @param numberObjectives Number of objectives and dimensions of the FitnessVector
121 	 * @param numberCandidates Number of candidates in each tournament
122 	 * @return A new instance of TournamentNSGA2Selection
123 	 */
124 	public static <U extends Number & Comparable<U>> TournamentNSGA2Selection<FitnessVector<U>> ofFitnessVector(
125 			final int numberObjectives, final int numberCandidates) {
126 
127 		return ofFitnessVector(numberObjectives, numberCandidates, null);
128 	}
129 
130 }