Skip to content

Instantly share code, notes, and snippets.

@jenetics
Created January 10, 2020 17:03
Show Gist options
  • Save jenetics/07311ff0f3673a006e814688b7c0857c to your computer and use it in GitHub Desktop.
Save jenetics/07311ff0f3673a006e814688b7c0857c to your computer and use it in GitHub Desktop.
Structure of a more complex GA problem
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