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