All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.github.ericmedvet.jgea.experimenter.builders.Solvers Maven / Gradle / Ivy

The newest version!
/*-
 * ========================LICENSE_START=================================
 * jgea-experimenter
 * %%
 * Copyright (C) 2018 - 2024 Eric Medvet
 * %%
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * =========================LICENSE_END==================================
 */

package io.github.ericmedvet.jgea.experimenter.builders;

import io.github.ericmedvet.jgea.core.InvertibleMapper;
import io.github.ericmedvet.jgea.core.distance.Jaccard;
import io.github.ericmedvet.jgea.core.operator.GeneticOperator;
import io.github.ericmedvet.jgea.core.operator.Mutation;
import io.github.ericmedvet.jgea.core.representation.graph.*;
import io.github.ericmedvet.jgea.core.representation.graph.numeric.Constant;
import io.github.ericmedvet.jgea.core.representation.graph.numeric.Input;
import io.github.ericmedvet.jgea.core.representation.graph.numeric.Output;
import io.github.ericmedvet.jgea.core.representation.graph.numeric.operatorgraph.BaseOperator;
import io.github.ericmedvet.jgea.core.representation.graph.numeric.operatorgraph.OperatorGraph;
import io.github.ericmedvet.jgea.core.representation.graph.numeric.operatorgraph.OperatorNode;
import io.github.ericmedvet.jgea.core.representation.graph.numeric.operatorgraph.ShallowFactory;
import io.github.ericmedvet.jgea.core.selector.Last;
import io.github.ericmedvet.jgea.core.selector.Tournament;
import io.github.ericmedvet.jgea.core.solver.*;
import io.github.ericmedvet.jgea.core.solver.cabea.CellularAutomataBasedSolver;
import io.github.ericmedvet.jgea.core.solver.cabea.SubstrateFiller;
import io.github.ericmedvet.jgea.core.solver.es.CMAEvolutionaryStrategy;
import io.github.ericmedvet.jgea.core.solver.es.OpenAIEvolutionaryStrategy;
import io.github.ericmedvet.jgea.core.solver.es.SimpleEvolutionaryStrategy;
import io.github.ericmedvet.jgea.core.solver.mapelites.CoMapElites;
import io.github.ericmedvet.jgea.core.solver.mapelites.MapElites;
import io.github.ericmedvet.jgea.core.solver.mapelites.strategy.CoMEStrategy;
import io.github.ericmedvet.jgea.core.solver.pso.ParticleSwarmOptimization;
import io.github.ericmedvet.jgea.core.solver.speciation.LazySpeciator;
import io.github.ericmedvet.jgea.core.solver.speciation.SpeciatedEvolver;
import io.github.ericmedvet.jgea.experimenter.Representation;
import io.github.ericmedvet.jnb.core.Cacheable;
import io.github.ericmedvet.jnb.core.Discoverable;
import io.github.ericmedvet.jnb.core.Param;
import io.github.ericmedvet.jnb.datastructure.Grid;
import io.github.ericmedvet.jnb.datastructure.Pair;
import java.util.List;
import java.util.Map;
import java.util.function.BiFunction;
import java.util.function.Function;
import java.util.stream.DoubleStream;

@Discoverable(prefixTemplate = "ea.solver|s")
public class Solvers {

  private Solvers() {}

  @SuppressWarnings("unused")
  @Cacheable
  public static  Function> cabea(
      @Param(value = "name", dS = "cabea") String name,
      @Param("representation") Function> representation,
      @Param(value = "mapper", dNPM = "ea.m.identity()") InvertibleMapper mapper,
      @Param(value = "keepProbability", dD = 0.00d) double keepProbability,
      @Param(value = "crossoverP", dD = 0.8d) double crossoverP,
      @Param(value = "nTour", dI = 1) int nTour,
      @Param(value = "nEval", dI = 1000) int nEval,
      @Param(value = "toroidal", dB = true) boolean toroidal,
      @Param(value = "mooreRadius", dI = 1) int mooreRadius,
      @Param(value = "gridSize", dI = 11) int gridSize,
      @Param(value = "substrate", dS = "empty") SubstrateFiller.Predefined substrate) {
    return exampleS -> {
      Representation r = representation.apply(mapper.exampleFor(exampleS));
      return new CellularAutomataBasedSolver<>(
          mapper.mapperFor(exampleS),
          r.factory(),
          StopConditions.nOfFitnessEvaluations(nEval),
          substrate.apply(Grid.create(gridSize, gridSize, true)),
          new CellularAutomataBasedSolver.MooreNeighborhood(mooreRadius, toroidal),
          keepProbability,
          r.geneticOperators(crossoverP),
          new Tournament(nTour));
    };
  }

  @SuppressWarnings("unused")
  @Cacheable
  public static  Function> cmaEs(
      @Param(value = "name", dS = "cmaEs") String name,
      @Param(value = "mapper", dNPM = "ea.m.identity()") InvertibleMapper, S> mapper,
      @Param(value = "initialMinV", dD = -1d) double initialMinV,
      @Param(value = "initialMaxV", dD = 1d) double initialMaxV,
      @Param(value = "nEval", dI = 1000) int nEval) {
    return exampleS -> new CMAEvolutionaryStrategy<>(
        mapper.mapperFor(exampleS),
        Representations.doubleString(initialMinV, initialMaxV, 0)
            .apply(mapper.exampleFor(exampleS))
            .factory(),
        StopConditions.nOfFitnessEvaluations(nEval));
  }

  @SuppressWarnings("unused")
  @Cacheable
  public static  Function> coMapElites(
      @Param(value = "name", iS = "coMe-{strategy}") String name,
      @Param("representation1") Function> representation1,
      @Param("representation2") Function> representation2,
      @Param(value = "mapper1", dNPM = "ea.m.identity()") InvertibleMapper mapper1,
      @Param(value = "mapper2", dNPM = "ea.m.identity()") InvertibleMapper mapper2,
      @Param("merger") InvertibleMapper, S> invertibleMapperMerger,
      @Param(value = "descriptors1") List> descriptors1,
      @Param(value = "descriptors2") List> descriptors2,
      @Param(value = "nEval", dI = 1000) int nEval,
      @Param(value = "populationSize", dI = 100) int populationSize,
      @Param(value = "nOfOffspring", dI = 50) int nOfOffspring,
      @Param(value = "strategy", dS = "identity") CoMEStrategy.Prepared strategy,
      @Param(value = "neighborRadius", dD = 2) double neighborRadius) {
    return exampleS -> {
      Pair splitExample = invertibleMapperMerger.exampleFor(exampleS);
      Representation r1 = representation1.apply(mapper1.exampleFor(splitExample.first()));
      Representation r2 = representation2.apply(mapper2.exampleFor(splitExample.second()));
      BiFunction merger =
          (s1, s2) -> invertibleMapperMerger.mapperFor(exampleS).apply(new Pair<>(s1, s2));
      if (descriptors1.isEmpty() || descriptors2.isEmpty()) {
        throw new IllegalArgumentException("Descriptors for representations must be initialized.");
      }
      return new CoMapElites<>(
          StopConditions.nOfFitnessEvaluations(nEval),
          r1.factory(),
          r2.factory(),
          mapper1.mapperFor(splitExample.first()),
          mapper2.mapperFor(splitExample.second()),
          merger,
          descriptors1,
          descriptors2,
          r1.mutations().getFirst(),
          r2.mutations().getFirst(),
          populationSize,
          nOfOffspring,
          strategy,
          neighborRadius);
    };
  }

  @SuppressWarnings("unused")
  @Cacheable
  public static  Function> differentialEvolution(
      @Param(value = "name", dS = "de") String name,
      @Param(value = "mapper", dNPM = "ea.m.identity()") InvertibleMapper, S> mapper,
      @Param(value = "initialMinV", dD = -1d) double initialMinV,
      @Param(value = "initialMaxV", dD = 1d) double initialMaxV,
      @Param(value = "populationSize", dI = 15) int populationSize,
      @Param(value = "nEval", dI = 1000) int nEval,
      @Param(value = "differentialWeight", dD = 0.5) double differentialWeight,
      @Param(value = "crossoverP", dD = 0.8) double crossoverP,
      @Param(value = "remap") boolean remap) {
    return exampleS -> new DifferentialEvolution<>(
        mapper.mapperFor(exampleS),
        Representations.doubleString(initialMinV, initialMaxV, 0)
            .apply(mapper.exampleFor(exampleS))
            .factory(),
        populationSize,
        StopConditions.nOfFitnessEvaluations(nEval),
        differentialWeight,
        crossoverP,
        remap);
  }

  @SuppressWarnings("unused")
  @Cacheable
  public static  Function> ga(
      @Param(value = "name", dS = "ga") String name,
      @Param("representation") Function> representation,
      @Param(value = "mapper", dNPM = "ea.m.identity()") InvertibleMapper mapper,
      @Param(value = "crossoverP", dD = 0.8d) double crossoverP,
      @Param(value = "tournamentRate", dD = 0.05d) double tournamentRate,
      @Param(value = "minNTournament", dI = 3) int minNTournament,
      @Param(value = "nPop", dI = 100) int nPop,
      @Param(value = "nEval", dI = 1000) int nEval,
      @Param(value = "maxUniquenessAttempts", dI = 100) int maxUniquenessAttempts,
      @Param(value = "remap") boolean remap) {
    return exampleS -> {
      Representation r = representation.apply(mapper.exampleFor(exampleS));
      return new StandardEvolver<>(
          mapper.mapperFor(exampleS),
          r.factory(),
          nPop,
          StopConditions.nOfFitnessEvaluations(nEval),
          r.geneticOperators(crossoverP),
          new Tournament(Math.max(minNTournament, (int) Math.ceil((double) nPop * tournamentRate))),
          new Last(),
          nPop,
          true,
          maxUniquenessAttempts,
          remap);
    };
  }

  @SuppressWarnings("unused")
  @Cacheable
  public static  Function> mapElites(
      @Param(value = "name", dS = "me") String name,
      @Param("representation") Function> representation,
      @Param(value = "mapper", dNPM = "ea.m.identity()") InvertibleMapper mapper,
      @Param(value = "nPop", dI = 100) int nPop,
      @Param(value = "nEval", dI = 1000) int nEval,
      @Param("descriptors") List> descriptors) {
    return exampleS -> {
      Representation r = representation.apply(mapper.exampleFor(exampleS));
      return new MapElites<>(
          mapper.mapperFor(exampleS),
          r.factory(),
          StopConditions.nOfFitnessEvaluations(nEval),
          r.mutations().getFirst(),
          nPop,
          descriptors);
    };
  }

  @SuppressWarnings("unused")
  @Cacheable
  public static  Function> nsga2(
      @Param(value = "name", dS = "nsga2") String name,
      @Param("representation") Function> representation,
      @Param(value = "mapper", dNPM = "ea.m.identity()") InvertibleMapper mapper,
      @Param(value = "crossoverP", dD = 0.8d) double crossoverP,
      @Param(value = "nPop", dI = 100) int nPop,
      @Param(value = "nEval", dI = 1000) int nEval,
      @Param(value = "maxUniquenessAttempts", dI = 100) int maxUniquenessAttempts,
      @Param(value = "remap") boolean remap) {
    return exampleS -> {
      Representation r = representation.apply(mapper.exampleFor(exampleS));
      return new NsgaII<>(
          mapper.mapperFor(exampleS),
          r.factory(),
          nPop,
          StopConditions.nOfFitnessEvaluations(nEval),
          r.geneticOperators(crossoverP),
          maxUniquenessAttempts,
          remap);
    };
  }

  @SuppressWarnings("unused")
  @Cacheable
  public static  Function, S, Q>> oGraphea(
      @Param(value = "name", dS = "oGraphea") String name,
      @Param(value = "mapper", dNPM = "ea.m.identity()")
          InvertibleMapper, S> mapper,
      @Param(value = "minConst", dD = 0d) double minConst,
      @Param(value = "maxConst", dD = 5d) double maxConst,
      @Param(value = "nConst", dI = 10) int nConst,
      @Param(
              value = "operators",
              dSs = {"addition", "subtraction", "multiplication", "prot_division", "prot_log"})
          List operators,
      @Param(value = "nPop", dI = 100) int nPop,
      @Param(value = "nEval", dI = 1000) int nEval,
      @Param(value = "arcAdditionRate", dD = 3d) double arcAdditionRate,
      @Param(value = "arcRemovalRate", dD = 0.1d) double arcRemovalRate,
      @Param(value = "nodeAdditionRate", dD = 1d) double nodeAdditionRate,
      @Param(value = "nPop", dI = 5) int minSpeciesSizeForElitism,
      @Param(value = "rankBase", dD = 0.75d) double rankBase,
      @Param(value = "remap") boolean remap) {
    return exampleS -> {
      Map>, Double> geneticOperators = Map.ofEntries(
          Map.entry(
              new NodeAddition(
                      OperatorNode.sequentialIndexFactory(operators.toArray(BaseOperator[]::new)),
                      Mutation.copy(),
                      Mutation.copy())
                  .withChecker(OperatorGraph.checker()),
              nodeAdditionRate),
          Map.entry(
              new ArcAddition(r -> OperatorGraph.NON_VALUED_ARC, false)
                  .withChecker(OperatorGraph.checker()),
              arcAdditionRate),
          Map.entry(
              new ArcRemoval(node -> (node instanceof Input)
                      || (node instanceof Constant)
                      || (node instanceof Output))
                  .withChecker(OperatorGraph.checker()),
              arcRemovalRate));
      Graph graph = mapper.exampleFor(exampleS);
      double constStep = (maxConst - minConst) / nConst;
      List constants = DoubleStream.iterate(minConst, d -> d + constStep)
          .limit(nConst)
          .boxed()
          .toList();
      return new SpeciatedEvolver<>(
          mapper.mapperFor(exampleS),
          new ShallowFactory(
              graph.nodes().stream()
                  .filter(n -> n instanceof Input)
                  .map(n -> ((Input) n).getName())
                  .distinct()
                  .toList(),
              graph.nodes().stream()
                  .filter(n -> n instanceof Output)
                  .map(n -> ((Output) n).getName())
                  .distinct()
                  .toList(),
              constants),
          StopConditions.nOfFitnessEvaluations(nEval),
          geneticOperators,
          nPop,
          remap,
          minSpeciesSizeForElitism,
          new LazySpeciator<>(
              (new Jaccard()).on(i -> i.genotype().nodes()), 0.25),
          rankBase);
    };
  }

  @SuppressWarnings("unused")
  @Cacheable
  public static  Function> openAiEs(
      @Param(value = "name", dS = "openAiEs") String name,
      @Param(value = "mapper", dNPM = "ea.m.identity()") InvertibleMapper, S> mapper,
      @Param(value = "initialMinV", dD = -1d) double initialMinV,
      @Param(value = "initialMaxV", dD = 1d) double initialMaxV,
      @Param(value = "sigma", dD = 0.02d) double sigma,
      @Param(value = "batchSize", dI = 30) int batchSize,
      @Param(value = "stepSize", dD = 0.02d) double stepSize,
      @Param(value = "beta1", dD = 0.9d) double beta1,
      @Param(value = "beta2", dD = 0.999d) double beta2,
      @Param(value = "epsilon", dD = 1e-8) double epsilon,
      @Param(value = "nEval", dI = 1000) int nEval) {
    return exampleS -> new OpenAIEvolutionaryStrategy<>(
        mapper.mapperFor(exampleS),
        Representations.doubleString(initialMinV, initialMaxV, 0)
            .apply(mapper.exampleFor(exampleS))
            .factory(),
        StopConditions.nOfFitnessEvaluations(nEval),
        batchSize,
        sigma,
        stepSize,
        beta1,
        beta2,
        epsilon);
  }

  @SuppressWarnings("unused")
  @Cacheable
  public static  Function> pso(
      @Param(value = "name", dS = "pso") String name,
      @Param(value = "mapper", dNPM = "ea.m.identity()") InvertibleMapper, S> mapper,
      @Param(value = "initialMinV", dD = -1d) double initialMinV,
      @Param(value = "initialMaxV", dD = 1d) double initialMaxV,
      @Param(value = "nEval", dI = 1000) int nEval,
      @Param(value = "nPop", dI = 100) int nPop,
      @Param(value = "w", dD = 0.8d) double w,
      @Param(value = "phiParticle", dD = 1.5d) double phiParticle,
      @Param(value = "phiGlobal", dD = 1.5d) double phiGlobal) {
    return exampleS -> new ParticleSwarmOptimization<>(
        mapper.mapperFor(exampleS),
        Representations.doubleString(initialMinV, initialMaxV, 0)
            .apply(mapper.exampleFor(exampleS))
            .factory(),
        StopConditions.nOfFitnessEvaluations(nEval),
        nPop,
        w,
        phiParticle,
        phiGlobal);
  }

  @SuppressWarnings("unused")
  @Cacheable
  public static  Function> randomSearch(
      @Param(value = "name", dS = "rs") String name,
      @Param("representation") Function> representation,
      @Param(value = "mapper", dNPM = "ea.m.identity()") InvertibleMapper mapper,
      @Param(value = "nEval", dI = 1000) int nEval) {
    return exampleS -> {
      Representation r = representation.apply(mapper.exampleFor(exampleS));
      return new RandomSearch<>(
          mapper.mapperFor(exampleS), r.factory(), StopConditions.nOfFitnessEvaluations(nEval));
    };
  }

  @SuppressWarnings("unused")
  @Cacheable
  public static  Function> randomWalk(
      @Param(value = "name", dS = "rw") String name,
      @Param("representation") Function> representation,
      @Param(value = "mapper", dNPM = "ea.m.identity()") InvertibleMapper mapper,
      @Param(value = "nEval", dI = 1000) int nEval) {
    return exampleS -> {
      Representation r = representation.apply(mapper.exampleFor(exampleS));
      return new RandomWalk<>(
          mapper.mapperFor(exampleS),
          r.factory(),
          StopConditions.nOfFitnessEvaluations(nEval),
          r.mutations().getFirst());
    };
  }

  @SuppressWarnings("unused")
  @Cacheable
  public static  Function> simpleEs(
      @Param(value = "name", dS = "es") String name,
      @Param(value = "mapper", dNPM = "ea.m.identity()") InvertibleMapper, S> mapper,
      @Param(value = "initialMinV", dD = -1d) double initialMinV,
      @Param(value = "initialMaxV", dD = 1d) double initialMaxV,
      @Param(value = "sigma", dD = 0.35d) double sigma,
      @Param(value = "parentsRate", dD = 0.33d) double parentsRate,
      @Param(value = "nOfElites", dI = 1) int nOfElites,
      @Param(value = "nPop", dI = 30) int nPop,
      @Param(value = "nEval", dI = 1000) int nEval,
      @Param(value = "remap") boolean remap) {
    return exampleS -> new SimpleEvolutionaryStrategy<>(
        mapper.mapperFor(exampleS),
        Representations.doubleString(initialMinV, initialMaxV, 0)
            .apply(mapper.exampleFor(exampleS))
            .factory(),
        nPop,
        StopConditions.nOfFitnessEvaluations(nEval),
        nOfElites,
        (int) Math.round(nPop * parentsRate),
        sigma,
        remap);
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy