
io.github.ericmedvet.jgea.experimenter.builders.NamedFunctions Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jgea.experimenter Show documentation
Show all versions of jgea.experimenter Show documentation
Experimenter tool based on jgea and textual config files (with jnb).
/*
* Copyright 2022 eric
*
* 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.
*/
package io.github.ericmedvet.jgea.experimenter.builders;
import io.github.ericmedvet.jgea.core.listener.NamedFunction;
import io.github.ericmedvet.jgea.core.solver.Individual;
import io.github.ericmedvet.jgea.core.solver.state.POSetPopulationState;
import io.github.ericmedvet.jgea.core.solver.state.State;
import io.github.ericmedvet.jgea.core.util.Misc;
import io.github.ericmedvet.jgea.core.util.TextPlotter;
import io.github.ericmedvet.jnb.core.Param;
import io.github.ericmedvet.jnb.core.ParamMap;
import java.io.ByteArrayOutputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.*;
import java.util.function.Function;
import java.util.logging.Logger;
public class NamedFunctions {
private final static Logger L = Logger.getLogger(NamedFunctions.class.getName());
private NamedFunctions() {
}
public enum Op {
PLUS("+"), MINUS("-"), PROD("*"), DIV("/");
private final String rendered;
Op(String rendered) {
this.rendered = rendered;
}
}
@SuppressWarnings("unused")
public static NamedFunction, Collection>> all() {
return NamedFunction.build("all", s -> s.getPopulation().all());
}
@SuppressWarnings("unused")
public static NamedFunction base64(
@Param("f") NamedFunction f
) {
return NamedFunction.build(c("base64", f.getName()), x -> {
try (ByteArrayOutputStream baos = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(
baos)) {
oos.writeObject(f.apply(x));
oos.flush();
return Base64.getEncoder().encodeToString(baos.toByteArray());
} catch (Throwable t) {
L.warning("Cannot serialize %s due to %s".formatted(f.getName(), t));
return "not-serializable";
}
});
}
@SuppressWarnings("unused")
public static NamedFunction, Individual> best() {
return NamedFunction.build("best", s -> Misc.first(s.getPopulation().firsts()));
}
@SuppressWarnings("unused")
public static NamedFunction, T> bestFitness(
@Param(value = "f", dNPM = "ea.nf.identity()") NamedFunction function,
@Param(value = "s", dS = "%s") String s
) {
return NamedFunction.build(
c(function.getName(), "fitness", "best"),
s.equals("%s") ? function.getFormat() : s,
state -> function.apply(Objects.requireNonNull(Misc.first(state.getPopulation().firsts())).fitness())
);
}
@SuppressWarnings("unused")
public static NamedFunction, Long> births() {
return NamedFunction.build("births", "%6d", POSetPopulationState::getNOfBirths);
}
private static String c(String... names) {
return Arrays.stream(names).reduce(NamedFunction.NAME_COMPOSER::apply).orElseThrow();
}
@SuppressWarnings("unused")
public static NamedFunction> each(
@Param("map") NamedFunction mapF,
@Param("collection") NamedFunction> collectionF,
@Param(value = "s", dS = "%s") String s
) {
return NamedFunction.build(
c("each[%s]".formatted(mapF.getName()), collectionF.getName()),
s,
x -> collectionF.apply(x).stream().map(mapF).toList()
);
}
@SuppressWarnings("unused")
public static NamedFunction, Double> elapsed() {
return NamedFunction.build("elapsed.seconds", "%5.1f", s -> s.getElapsedMillis() / 1000d);
}
@SuppressWarnings("unused")
public static NamedFunction, Long> evals() {
return NamedFunction.build("evals", "%6d", POSetPopulationState::getNOfFitnessEvaluations);
}
@SuppressWarnings("unused")
public static NamedFunction expr(
@Param("f1") NamedFunction f1, @Param("f2") NamedFunction f2, @Param("op") Op op
) {
return NamedFunction.build(
"%s%s%s".formatted(f1.getName(), op.rendered, f2.getName()),
f1.getFormat(),
x -> switch (op) {
case PLUS -> f1.apply(x).doubleValue() + f2.apply(x).doubleValue();
case MINUS -> f1.apply(x).doubleValue() - f2.apply(x).doubleValue();
case PROD -> f1.apply(x).doubleValue() * f2.apply(x).doubleValue();
case DIV -> f1.apply(x).doubleValue() / f2.apply(x).doubleValue();
}
);
}
@SuppressWarnings("unused")
public static NamedFunction f(
@Param("outerF") Function outerFunction,
@Param(value = "innerF", dNPM = "ea.nf.identity()") NamedFunction innerFunction,
@Param("name") String name,
@Param(value = "s", dS = "%s") String s,
@Param(value = "", injection = Param.Injection.MAP) ParamMap map
) {
if ((name == null) || name.isEmpty()) {
name = map.npm("outerF").getName();
}
return NamedFunction.build(c(name, innerFunction.getName()), s, x -> outerFunction.apply(innerFunction.apply(x)));
}
@SuppressWarnings("unused")
public static NamedFunction, Collection>> firsts() {
return NamedFunction.build("firsts", s -> s.getPopulation().firsts());
}
@SuppressWarnings("unused")
public static NamedFunction fitness(
@Param(value = "individual", dNPM = "ea.nf.identity()") NamedFunction> individualF,
@Param(value = "s", dS = "%s") String s
) {
return NamedFunction.build(c("fitness", individualF.getName()), s, x -> individualF.apply(x).fitness());
}
@SuppressWarnings("unused")
public static NamedFunction, String> fitnessHist(
@Param(value = "f", dNPM = "ea.nf.identity()") NamedFunction function,
@Param(value = "nBins", dI = 8) int nBins
) {
return NamedFunction.build(
c("hist", "each[%s]".formatted(c(function.getName(), "fitness")), "all"),
"%" + nBins + "." + nBins + "s",
state -> {
List numbers = state.getPopulation().all().stream().map(i -> function.apply(i.fitness())).toList();
return TextPlotter.histogram(numbers, nBins);
}
);
}
@SuppressWarnings("unused")
public static NamedFunction formatted(
@Param("s") String s, @Param("f") NamedFunction f
) {
return f.reformat(s);
}
@SuppressWarnings("unused")
public static NamedFunction genotype(
@Param(value = "individual", dNPM = "ea.nf.identity()") NamedFunction> individualF,
@Param(value = "s", dS = "%s") String s
) {
return NamedFunction.build(c("genotype", individualF.getName()), s, x -> individualF.apply(x).genotype());
}
@SuppressWarnings("unused")
public static NamedFunction hist(
@Param("collection") NamedFunction> collectionF, @Param(value = "nBins", dI = 8) int nBins
) {
return NamedFunction.build(c("hist", collectionF.getName()), "%" + nBins + "." + nBins + "s", x -> {
Collection collection = collectionF.apply(x);
return TextPlotter.histogram(collection instanceof List list ? list : new ArrayList<>(collection), nBins);
});
}
@SuppressWarnings("unused")
public static NamedFunction identity() {
return NamedFunction.build("", t -> t);
}
@SuppressWarnings("unused")
public static NamedFunction, Long> iterations() {
return NamedFunction.build("iterations", "%3d", State::getNOfIterations);
}
@SuppressWarnings("unused")
public static NamedFunction, Collection>> lasts() {
return NamedFunction.build("lasts", s -> s.getPopulation().lasts());
}
@SuppressWarnings("unused")
public static > NamedFunction max(
@Param("collection") NamedFunction> collectionF, @Param(value = "s", dS = "%s") String s
) {
return NamedFunction.build(c("max", collectionF.getName()), s, x -> {
List collection = collectionF.apply(x).stream().sorted().toList();
return collectionF.apply(x).stream().max(Comparable::compareTo).orElse(null);
});
}
@SuppressWarnings("unused")
public static > NamedFunction median(
@Param("collection") NamedFunction> collectionF, @Param(value = "s", dS = "%s") String s
) {
return percentile(collectionF, 0.5, s);
}
@SuppressWarnings("unused")
public static > NamedFunction min(
@Param("collection") NamedFunction> collectionF, @Param(value = "s", dS = "%s") String s
) {
return NamedFunction.build(c("min", collectionF.getName()), s, x -> {
List collection = collectionF.apply(x).stream().sorted().toList();
return collectionF.apply(x).stream().min(Comparable::compareTo).orElse(null);
});
}
@SuppressWarnings("unused")
public static > NamedFunction percentile(
@Param("collection") NamedFunction> collectionF,
@Param("p") double p,
@Param(value = "s", dS = "%s") String s
) {
return NamedFunction.build(c("perc[%2d]".formatted((int) Math.round(p * 100)), collectionF.getName()), s, x -> {
List collection = collectionF.apply(x).stream().sorted().toList();
int i = (int) Math.max(Math.min(((double) collection.size()) * p, collection.size() - 1), 0);
return collection.get(i);
});
}
@SuppressWarnings("unused")
public static NamedFunction, Double> progress() {
return NamedFunction.build("progress", "%4.2f", s -> s.getProgress().rate());
}
@SuppressWarnings("unused")
public static NamedFunction size(
@Param("f") NamedFunction f, @Param(value = "s", dS = "%s") String s
) {
return NamedFunction.build(
c("size", f.getName()),
s,
x -> io.github.ericmedvet.jgea.core.listener.NamedFunctions.size(f.apply(x))
);
}
@SuppressWarnings("unused")
public static NamedFunction solution(
@Param(value = "individual", dNPM = "ea.nf.identity()") NamedFunction> individualF,
@Param(value = "s", dS = "%s") String s
) {
return NamedFunction.build(c("solution", individualF.getName()), s, x -> individualF.apply(x).solution());
}
@SuppressWarnings("unused")
public static NamedFunction uniqueness(
@Param("collection") NamedFunction> collectionF
) {
return NamedFunction.build(c("uniqueness", collectionF.getName()), "%4.2f", x -> {
Collection collection = collectionF.apply(x);
return ((double) (new HashSet<>(collection).size())) / ((double) collection.size());
});
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy