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

ai.timefold.solver.benchmark.impl.SolverBenchmarkFactory Maven / Gradle / Ivy

Go to download

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.

There is a newer version: 1.16.0
Show newest version
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