Created
May 9, 2016 18:09
-
-
Save jenetics/cb2c2a285a855966ac1de86d34a7b995 to your computer and use it in GitHub Desktop.
Example for dynamic Genotype/Chromosome length
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import static java.lang.Math.pow; | |
import static org.jenetics.internal.math.random.indexes; | |
import java.util.ArrayList; | |
import java.util.List; | |
import java.util.Random; | |
import java.util.stream.IntStream; | |
import org.jenetics.internal.util.IntRef; | |
import org.jenetics.AbstractAlterer; | |
import org.jenetics.Chromosome; | |
import org.jenetics.DoubleChromosome; | |
import org.jenetics.DoubleGene; | |
import org.jenetics.Gene; | |
import org.jenetics.Genotype; | |
import org.jenetics.Phenotype; | |
import org.jenetics.Population; | |
import org.jenetics.engine.Engine; | |
import org.jenetics.engine.EvolutionResult; | |
import org.jenetics.util.Factory; | |
import org.jenetics.util.ISeq; | |
import org.jenetics.util.RandomRegistry; | |
public class DynamicGenotype { | |
// Explicit Genotype factory instead of Genotype templates. | |
private static final Factory<Genotype<DoubleGene>> ENCODING = () -> { | |
final Random random = RandomRegistry.getRandom(); | |
return Genotype.of( | |
// Vary the chromosome count between 10 and 20. | |
IntStream.range(0, random.nextInt(10) + 10) | |
// Vary the chromosome length between 10 and 20. | |
.mapToObj(i -> DoubleChromosome.of(0, 10, random.nextInt(10) + 10)) | |
.collect(ISeq.toISeq()) | |
); | |
}; | |
private static double fitness(final Genotype<DoubleGene> gt) { | |
// Calculate fitness from "dynamic" Genotype. | |
System.out.println("Gene count: " + gt.getNumberOfGenes()); | |
return 0; | |
} | |
// The special mutator also variates the chromosome/genotype length. | |
private static final class DynamicMutator< | |
G extends Gene<?, G>, | |
C extends Comparable<? super C> | |
> | |
extends AbstractAlterer<G, C> | |
{ | |
public DynamicMutator(double probability) { | |
super(probability); | |
} | |
@Override | |
public int alter( | |
final Population<G, C> population, | |
final long generation | |
) { | |
final double p = pow(_probability, 1.0/3.0); | |
final IntRef alterations = new IntRef(0); | |
indexes(RandomRegistry.getRandom(), population.size(), p).forEach(i -> { | |
final Phenotype<G, C> pt = population.get(i); | |
final Genotype<G> gt = pt.getGenotype(); | |
final Genotype<G> mgt = mutate(gt, p, alterations); | |
final Phenotype<G, C> mpt = pt.newInstance(mgt, generation); | |
population.set(i, mpt); | |
}); | |
return alterations.value; | |
} | |
private Genotype<G> mutate( | |
final Genotype<G> genotype, | |
final double p, | |
final IntRef alterations | |
) { | |
final List<Chromosome<G>> chromosomes = | |
new ArrayList<>(genotype.toSeq().asList()); | |
// Add/remove Chromosome to Genotype. | |
final Random random = RandomRegistry.getRandom(); | |
final double rd = random.nextDouble(); | |
if (rd < 1/3.0) { | |
chromosomes.remove(0); | |
} else if (rd < 2/3.0) { | |
chromosomes.add(chromosomes.get(0).newInstance()); | |
} | |
alterations.value += | |
indexes(RandomRegistry.getRandom(), chromosomes.size(), p) | |
.map(i -> mutate(chromosomes, i, p)) | |
.sum(); | |
return Genotype.of(chromosomes); | |
} | |
private int mutate(final List<Chromosome<G>> c, final int i, final double p) { | |
final Chromosome<G> chromosome = c.get(i); | |
final List<G> genes = new ArrayList<>(chromosome.toSeq().asList()); | |
final int mutations = mutate(genes, p); | |
if (mutations > 0) { | |
c.set(i, chromosome.newInstance(ISeq.of(genes))); | |
} | |
return mutations; | |
} | |
private int mutate(final List<G> genes, final double p) { | |
final Random random = RandomRegistry.getRandom(); | |
// Add/remove Gene from chromosome. | |
final double rd = random.nextDouble(); | |
if (rd < 1/3.0) { | |
genes.remove(0); | |
} else if (rd < 2/3.0) { | |
genes.add(genes.get(0).newInstance()); | |
} | |
return (int)indexes(random, genes.size(), p) | |
.peek(i -> genes.set(i, genes.get(i).newInstance())) | |
.count(); | |
} | |
} | |
public static void main(final String[] args) { | |
final Engine<DoubleGene, Double> engine = Engine | |
.builder(DynamicGenotype::fitness, ENCODING) | |
.alterers(new DynamicMutator<>(0.25)) | |
.build(); | |
final EvolutionResult<DoubleGene, Double> result = engine.stream() | |
.limit(20) | |
.collect(EvolutionResult.toBestEvolutionResult()); | |
System.out.println(result.getBestFitness()); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment