View Javadoc
1   package net.bmahe.genetics4j.core.postevaluationprocess;
2   
3   import java.util.ArrayList;
4   import java.util.List;
5   import java.util.Objects;
6   import java.util.function.BiFunction;
7   import java.util.function.Function;
8   
9   import org.apache.commons.lang3.Validate;
10  import org.immutables.value.Value;
11  
12  import net.bmahe.genetics4j.core.Genotype;
13  import net.bmahe.genetics4j.core.Individual;
14  import net.bmahe.genetics4j.core.Population;
15  import net.bmahe.genetics4j.core.spec.PostEvaluationProcessor;
16  
17  @Value.Immutable
18  public abstract class FitnessSharing<T extends Comparable<T>> implements PostEvaluationProcessor<T> {
19  
20  	@Value.Parameter
21  	public abstract BiFunction<Genotype, Genotype, Double> distance();
22  
23  	@Value.Parameter
24  	public abstract Function<Double, Double> sharing();
25  
26  	@Value.Parameter
27  	public abstract BiFunction<Individual<T>, Double, T> scaleFitness();
28  
29  	@Override
30  	public Population<T> apply(final long generation, final Population<T> population) {
31  		Validate.isTrue(generation >= 0);
32  		Objects.requireNonNull(population);
33  
34  		if (population.isEmpty()) {
35  			return population;
36  		}
37  
38  		final List<T> newFitness = new ArrayList<>();
39  		for (int i = 0; i < population.size(); i++) {
40  			final Genotype genotypeI = population.getGenotype(i);
41  			final Individual<T> individual = population.getIndividual(i);
42  
43  			double sumSharing = 0.0d;
44  			for (int j = 0; j < population.size(); j++) {
45  				final Genotype genotypeJ = population.getGenotype(j);
46  
47  				final double distance = distance().apply(genotypeI, genotypeJ);
48  				final double sharing = sharing().apply(distance);
49  				sumSharing += sharing;
50  			}
51  
52  			final T newFitnessI = scaleFitness().apply(individual, sumSharing);
53  			newFitness.add(newFitnessI);
54  		}
55  
56  		return Population.<T>of(population.getAllGenotypes(), newFitness);
57  	}
58  
59  	public static FitnessSharing<Double> of(final BiFunction<Genotype, Genotype, Double> distance,
60  			final Function<Double, Double> sharing) {
61  		return ImmutableFitnessSharing
62  				.of(distance, sharing, (individual, sumSharing) -> individual.fitness() / sumSharing);
63  	}
64  
65  	public static FitnessSharing<Double> ofStandard(final BiFunction<Genotype, Genotype, Double> distance,
66  			final double sigma) {
67  		return FitnessSharing.of(distance, (d) -> {
68  			if (d < 0.0 || d > sigma) {
69  				return 0.0;
70  			}
71  
72  			return 1 - d / sigma;
73  		});
74  	}
75  
76  	public static FitnessSharing<Double> ofStandard(final BiFunction<Genotype, Genotype, Double> distance,
77  			final double sigma, final double alpha) {
78  		return FitnessSharing.of(distance, (d) -> {
79  			if (d < 0.0 || d > sigma) {
80  				return 0.0;
81  			}
82  
83  			return 1 - Math.pow(d / sigma, alpha);
84  		});
85  	}
86  
87  	public static FitnessSharing<Float> ofFloatFitness(final BiFunction<Genotype, Genotype, Double> distance,
88  			final Function<Double, Double> sharing) {
89  		return ImmutableFitnessSharing
90  				.of(distance, sharing, (individual, sumSharing) -> (float) (individual.fitness() / sumSharing));
91  	}
92  }