ai.timefold.solver.benchmark.impl.SolverBenchmarkFactory Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of timefold-solver-benchmark Show documentation
Show all versions of timefold-solver-benchmark Show documentation
Timefold solves planning problems.
This lightweight, embeddable planning engine implements powerful and scalable algorithms
to optimize business resource scheduling and planning.
This module contains the benchmarker toolkit.
package ai.timefold.solver.benchmark.impl;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import ai.timefold.solver.benchmark.config.ProblemBenchmarksConfig;
import ai.timefold.solver.benchmark.config.SolverBenchmarkConfig;
import ai.timefold.solver.benchmark.config.statistic.ProblemStatisticType;
import ai.timefold.solver.benchmark.config.statistic.SingleStatisticType;
import ai.timefold.solver.benchmark.impl.result.PlannerBenchmarkResult;
import ai.timefold.solver.benchmark.impl.result.SolverBenchmarkResult;
import ai.timefold.solver.core.config.solver.SolverConfig;
import ai.timefold.solver.core.config.solver.monitoring.MonitoringConfig;
import ai.timefold.solver.core.config.solver.monitoring.SolverMetric;
import ai.timefold.solver.core.config.util.ConfigUtils;
import ai.timefold.solver.core.impl.domain.solution.descriptor.SolutionDescriptor;
import ai.timefold.solver.core.impl.solver.DefaultSolverFactory;
public class SolverBenchmarkFactory {
private final SolverBenchmarkConfig config;
public SolverBenchmarkFactory(SolverBenchmarkConfig config) {
this.config = config;
}
public void buildSolverBenchmark(ClassLoader classLoader, PlannerBenchmarkResult plannerBenchmark,
Solution_[] extraProblems) {
validate();
SolverBenchmarkResult solverBenchmarkResult = new SolverBenchmarkResult(plannerBenchmark);
solverBenchmarkResult.setName(config.getName());
solverBenchmarkResult.setSubSingleCount(ConfigUtils.inheritOverwritableProperty(config.getSubSingleCount(), 1));
if (config.getSolverConfig().getClassLoader() == null) {
config.getSolverConfig().setClassLoader(classLoader);
}
if (config.getSolverConfig().getMonitoringConfig() != null &&
config.getSolverConfig().getMonitoringConfig().getSolverMetricList() != null &&
!config.getSolverConfig().getMonitoringConfig().getSolverMetricList().isEmpty()) {
throw new IllegalArgumentException(
"The solverBenchmarkConfig (" + config + ") has a " + SolverConfig.class.getSimpleName() +
" (" + config.getSolverConfig() + " ) with a non-empty " + MonitoringConfig.class.getSimpleName() +
" (" + config.getSolverConfig().getMonitoringConfig() + ").");
}
List solverMetricList = getSolverMetrics(config.getProblemBenchmarksConfig());
solverBenchmarkResult.setSolverConfig(config.getSolverConfig()
.copyConfig().withMonitoringConfig(
new MonitoringConfig()
.withSolverMetricList(solverMetricList)));
DefaultSolverFactory defaultSolverFactory = new DefaultSolverFactory<>(config.getSolverConfig());
SolutionDescriptor solutionDescriptor = defaultSolverFactory.getSolutionDescriptor();
for (Solution_ extraProblem : extraProblems) {
if (!solutionDescriptor.getSolutionClass().isInstance(extraProblem)) {
throw new IllegalArgumentException("The solverBenchmark name (" + config.getName()
+ ") for solution class (" + solutionDescriptor.getSolutionClass()
+ ") cannot solve a problem (" + extraProblem
+ ") of class (" + (extraProblem == null ? null : extraProblem.getClass()) + ").");
}
}
solverBenchmarkResult.setScoreDefinition(solutionDescriptor.getScoreDefinition());
solverBenchmarkResult.setSingleBenchmarkResultList(new ArrayList<>());
ProblemBenchmarksConfig problemBenchmarksConfig_ =
config.getProblemBenchmarksConfig() == null ? new ProblemBenchmarksConfig()
: config.getProblemBenchmarksConfig();
plannerBenchmark.getSolverBenchmarkResultList().add(solverBenchmarkResult);
ProblemBenchmarksFactory problemBenchmarksFactory = new ProblemBenchmarksFactory(problemBenchmarksConfig_);
problemBenchmarksFactory.buildProblemBenchmarkList(solverBenchmarkResult, extraProblems);
}
protected void validate() {
if (!DefaultPlannerBenchmarkFactory.VALID_NAME_PATTERN.matcher(config.getName()).matches()) {
throw new IllegalStateException("The solverBenchmark name (" + config.getName()
+ ") is invalid because it does not follow the nameRegex ("
+ DefaultPlannerBenchmarkFactory.VALID_NAME_PATTERN.pattern() + ")" +
" which might cause an illegal filename.");
}
if (!config.getName().trim().equals(config.getName())) {
throw new IllegalStateException("The solverBenchmark name (" + config.getName()
+ ") is invalid because it starts or ends with whitespace.");
}
if (config.getSubSingleCount() != null && config.getSubSingleCount() < 1) {
throw new IllegalStateException("The solverBenchmark name (" + config.getName()
+ ") is invalid because the subSingleCount (" + config.getSubSingleCount() + ") must be greater than 1.");
}
}
protected List getSolverMetrics(ProblemBenchmarksConfig config) {
List out = new ArrayList<>();
for (ProblemStatisticType problemStatisticType : Optional.ofNullable(config)
.map(ProblemBenchmarksConfig::determineProblemStatisticTypeList)
.orElseGet(ProblemStatisticType::defaultList)) {
if (problemStatisticType == ProblemStatisticType.SCORE_CALCULATION_SPEED) {
out.add(SolverMetric.SCORE_CALCULATION_COUNT);
} else {
out.add(SolverMetric.valueOf(problemStatisticType.name()));
}
}
for (SingleStatisticType singleStatisticType : Optional.ofNullable(config)
.map(ProblemBenchmarksConfig::determineSingleStatisticTypeList)
.orElseGet(Collections::emptyList)) {
out.add(SolverMetric.valueOf(singleStatisticType.name()));
}
return out;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy