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 }