Created
January 10, 2020 17:03
-
-
Save jenetics/07311ff0f3673a006e814688b7c0857c to your computer and use it in GitHub Desktop.
Structure of a more complex GA problem
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.util.Collections.emptyList; | |
import static io.jenetics.engine.EvolutionResult.toBestPhenotype; | |
import java.util.List; | |
import java.util.function.Function; | |
import java.util.stream.DoubleStream; | |
import java.util.stream.Stream; | |
import io.jenetics.DoubleChromosome; | |
import io.jenetics.DoubleGene; | |
import io.jenetics.Genotype; | |
import io.jenetics.Optimize; | |
import io.jenetics.Phenotype; | |
import io.jenetics.TournamentSelector; | |
import io.jenetics.TruncationSelector; | |
import io.jenetics.engine.Codec; | |
import io.jenetics.engine.Codecs; | |
import io.jenetics.engine.Constraint; | |
import io.jenetics.engine.Engine; | |
import io.jenetics.engine.EvolutionStatistics; | |
import io.jenetics.engine.Limits; | |
import io.jenetics.engine.Problem; | |
import io.jenetics.engine.RetryConstraint; | |
import io.jenetics.util.DoubleRange; | |
import io.jenetics.util.ISeq; | |
public class ConstrainedSampleGA { | |
private static final Problem<double[][], DoubleGene, Double> PROBLEM = | |
new RealTimePricingProblem(emptyList(), emptyList()); | |
private static final Constraint<DoubleGene, Double> CONSTRAINT = | |
RetryConstraint.of(pt -> { | |
final double[][] value = PROBLEM.codec().decode(pt.getGenotype()); | |
// Implement your constraint here. If your constraint implementation | |
// is longer than a view line, consider defining a static private | |
// method and use a method reference instead. Just like you did with | |
// the fitness function. | |
return false; | |
}); | |
public static void main(final String[] args) { | |
final Engine<DoubleGene, Double> engine = Engine.builder(PROBLEM) | |
.populationSize(100) | |
.optimize(Optimize.MAXIMUM) | |
.offspringFraction(0.5) | |
.offspringSelector(new TruncationSelector<>()) | |
.survivorsSelector(new TournamentSelector<>()) | |
.constraint(CONSTRAINT) | |
.build(); | |
final EvolutionStatistics<Double, ?> | |
statistics = EvolutionStatistics.ofNumber(); | |
final Phenotype<DoubleGene, Double> best = engine.stream() | |
.limit(Limits.byPopulationConvergence(0.0001)) | |
.limit(1000) | |
.peek(statistics) | |
.collect(toBestPhenotype()); | |
} | |
// Optional implementation of constraint, if you can repair an invalid | |
// individual easily. | |
static final class SpecialConstraint implements Constraint<DoubleGene, Double> { | |
@Override | |
public boolean test(final Phenotype<DoubleGene, Double> individual) { | |
final double[][] value = PROBLEM.codec().decode(individual.getGenotype()); | |
// Implement your constraint test. | |
return false; | |
} | |
@Override | |
public Phenotype<DoubleGene, Double> repair( | |
final Phenotype<DoubleGene, Double> individual, | |
final long generation | |
) { | |
final double[][] value = PROBLEM.codec().decode(individual.getGenotype()); | |
// Repair it | |
value[0][0] = Math.PI; | |
// ... | |
return newPhenotype(value, generation); | |
} | |
// This part is not that obvious, I must confess ;-) | |
private static Phenotype<DoubleGene, Double> newPhenotype(double[][] matrix, long gen) { | |
final Genotype<DoubleGene> gt = Genotype.of( | |
Stream.of(matrix) | |
.map(SpecialConstraint::toChromosome) | |
.collect(ISeq.toISeq()) | |
); | |
return Phenotype.of(gt, gen); | |
} | |
private static DoubleChromosome toChromosome(final double[] row) { | |
return DoubleChromosome.of( | |
DoubleStream.of(row).boxed() | |
.map(v -> DoubleGene.of(v, DoubleRange.of(-2, 2))) | |
.collect(ISeq.toISeq()) | |
); | |
} | |
} | |
} | |
// For more complex problems, use the `Problem` interface. This decouples the | |
// problem definition from the GA setup. | |
final class RealTimePricingProblem implements Problem<double[][], DoubleGene, Double> { | |
private static final Codec<double[][], DoubleGene> CODEC = | |
Codecs.ofMatrix(DoubleRange.of(-2, 2), 2, 24); | |
private final List<Double> electricityDemandProsumers; | |
private final List<Double> electricityGenerationProsumers; | |
// Parametrization of your problem; shortened. | |
RealTimePricingProblem( | |
final List<Double> electricityDemandProsumers, | |
final List<Double> electricityGenerationProsumers | |
) { | |
this.electricityDemandProsumers = electricityDemandProsumers; | |
this.electricityGenerationProsumers = electricityGenerationProsumers; | |
} | |
private double __fitness(final double[][] priceDeviationsThisRound) { | |
return 0.0; | |
} | |
@Override | |
public Function<double[][], Double> fitness() { | |
return this::__fitness; | |
} | |
@Override | |
public Codec<double[][], DoubleGene> codec() { | |
return CODEC; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment