/* * Copyright 2011 Red Hat, Inc. and/or its affiliates. * * 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 org.optaplanner.benchmark.config; import java.io.File; import java.util.ArrayList; import java.util.List; import com.thoughtworks.xstream.annotations.XStreamAlias; import com.thoughtworks.xstream.annotations.XStreamImplicit; import org.apache.commons.io.FilenameUtils; import org.optaplanner.benchmark.config.statistic.ProblemStatisticType; import org.optaplanner.benchmark.config.statistic.SingleStatisticType; import org.optaplanner.benchmark.impl.result.PlannerBenchmarkResult; import org.optaplanner.benchmark.impl.result.ProblemBenchmarkResult; import org.optaplanner.benchmark.impl.result.SingleBenchmarkResult; import org.optaplanner.benchmark.impl.result.SolverBenchmarkResult; import org.optaplanner.benchmark.impl.result.SubSingleBenchmarkResult; import org.optaplanner.benchmark.impl.statistic.ProblemStatistic; import org.optaplanner.core.config.AbstractConfig; import org.optaplanner.core.config.SolverConfigContext; import org.optaplanner.core.config.util.ConfigUtils; import org.optaplanner.persistence.common.api.domain.solution.SolutionFileIO; import org.optaplanner.persistence.xstream.impl.domain.solution.XStreamSolutionFileIO; @XStreamAlias("problemBenchmarks") public class ProblemBenchmarksConfig extends AbstractConfig<ProblemBenchmarksConfig> { private Class<SolutionFileIO> solutionFileIOClass = null; @XStreamImplicit(itemFieldName = "xStreamAnnotatedClass") private List<Class> xStreamAnnotatedClassList = null; private Boolean writeOutputSolutionEnabled = null; @XStreamImplicit(itemFieldName = "inputSolutionFile") private List<File> inputSolutionFileList = null; @XStreamImplicit(itemFieldName = "problemStatisticType") private List<ProblemStatisticType> problemStatisticTypeList = null; @XStreamImplicit(itemFieldName = "singleStatisticType") private List<SingleStatisticType> singleStatisticTypeList = null; // ************************************************************************ // Constructors and simple getters/setters // ************************************************************************ public Class<SolutionFileIO> getSolutionFileIOClass() { return solutionFileIOClass; } public void setSolutionFileIOClass(Class<SolutionFileIO> solutionFileIOClass) { this.solutionFileIOClass = solutionFileIOClass; } public List<Class> getXStreamAnnotatedClassList() { return xStreamAnnotatedClassList; } public void setXStreamAnnotatedClassList(List<Class> xStreamAnnotatedClassList) { this.xStreamAnnotatedClassList = xStreamAnnotatedClassList; } public Boolean getWriteOutputSolutionEnabled() { return writeOutputSolutionEnabled; } public void setWriteOutputSolutionEnabled(Boolean writeOutputSolutionEnabled) { this.writeOutputSolutionEnabled = writeOutputSolutionEnabled; } public List<File> getInputSolutionFileList() { return inputSolutionFileList; } public void setInputSolutionFileList(List<File> inputSolutionFileList) { this.inputSolutionFileList = inputSolutionFileList; } public List<ProblemStatisticType> getProblemStatisticTypeList() { return problemStatisticTypeList; } public void setProblemStatisticTypeList(List<ProblemStatisticType> problemStatisticTypeList) { this.problemStatisticTypeList = problemStatisticTypeList; } public List<SingleStatisticType> getSingleStatisticTypeList() { return singleStatisticTypeList; } public void setSingleStatisticTypeList(List<SingleStatisticType> singleStatisticTypeList) { this.singleStatisticTypeList = singleStatisticTypeList; } // ************************************************************************ // Builder methods // ************************************************************************ public void buildProblemBenchmarkList(SolverConfigContext solverConfigContext, SolverBenchmarkResult solverBenchmarkResult) { validate(solverBenchmarkResult); PlannerBenchmarkResult plannerBenchmarkResult = solverBenchmarkResult.getPlannerBenchmarkResult(); SolutionFileIO solutionFileIO = buildSolutionFileIO(); List<ProblemBenchmarkResult> problemBenchmarkResultList = new ArrayList<>(inputSolutionFileList.size()); List<ProblemBenchmarkResult> unifiedProblemBenchmarkResultList = plannerBenchmarkResult.getUnifiedProblemBenchmarkResultList(); for (File inputSolutionFile : inputSolutionFileList) { if (!inputSolutionFile.exists()) { throw new IllegalArgumentException("The inputSolutionFile (" + inputSolutionFile + ") does not exist."); } // 2 SolverBenchmarks containing equal ProblemBenchmarks should contain the same instance ProblemBenchmarkResult newProblemBenchmarkResult = buildProblemBenchmark( solverConfigContext, plannerBenchmarkResult, solutionFileIO, inputSolutionFile); ProblemBenchmarkResult problemBenchmarkResult; int index = unifiedProblemBenchmarkResultList.indexOf(newProblemBenchmarkResult); if (index < 0) { problemBenchmarkResult = newProblemBenchmarkResult; unifiedProblemBenchmarkResultList.add(problemBenchmarkResult); } else { problemBenchmarkResult = unifiedProblemBenchmarkResultList.get(index); } problemBenchmarkResultList.add(problemBenchmarkResult); buildSingleBenchmark(solverConfigContext, solverBenchmarkResult, problemBenchmarkResult); } } private void validate(SolverBenchmarkResult solverBenchmarkResult) { if (ConfigUtils.isEmptyCollection(inputSolutionFileList)) { throw new IllegalArgumentException( "Configure at least 1 <inputSolutionFile> for the solverBenchmarkResult (" + solverBenchmarkResult.getName() + ") directly or indirectly by inheriting it."); } } private SolutionFileIO buildSolutionFileIO() { if (solutionFileIOClass != null && xStreamAnnotatedClassList != null) { throw new IllegalArgumentException("Cannot use solutionFileIOClass (" + solutionFileIOClass + ") and xStreamAnnotatedClassList (" + xStreamAnnotatedClassList + ") together."); } if (solutionFileIOClass != null) { return ConfigUtils.newInstance(this, "solutionFileIOClass", solutionFileIOClass); } else { Class[] xStreamAnnotatedClasses; if (xStreamAnnotatedClassList != null) { xStreamAnnotatedClasses = xStreamAnnotatedClassList.toArray(new Class[0]); } else { xStreamAnnotatedClasses = new Class[0]; } return new XStreamSolutionFileIO(xStreamAnnotatedClasses); } } private ProblemBenchmarkResult buildProblemBenchmark(SolverConfigContext solverConfigContext, PlannerBenchmarkResult plannerBenchmarkResult, SolutionFileIO solutionFileIO, File inputSolutionFile) { ProblemBenchmarkResult problemBenchmarkResult = new ProblemBenchmarkResult(plannerBenchmarkResult); String name = FilenameUtils.getBaseName(inputSolutionFile.getName()); problemBenchmarkResult.setName(name); problemBenchmarkResult.setSolutionFileIO(solutionFileIO); problemBenchmarkResult.setWriteOutputSolutionEnabled( writeOutputSolutionEnabled == null ? false : writeOutputSolutionEnabled); problemBenchmarkResult.setInputSolutionFile(inputSolutionFile); List<ProblemStatistic> problemStatisticList = new ArrayList<>( problemStatisticTypeList == null ? 0 : problemStatisticTypeList.size()); if (problemStatisticTypeList != null) { for (ProblemStatisticType problemStatisticType : problemStatisticTypeList) { problemStatisticList.add(problemStatisticType.buildProblemStatistic(problemBenchmarkResult)); } } problemBenchmarkResult.setProblemStatisticList(problemStatisticList); problemBenchmarkResult.setSingleBenchmarkResultList(new ArrayList<>()); return problemBenchmarkResult; } private void buildSingleBenchmark(SolverConfigContext solverConfigContext, SolverBenchmarkResult solverBenchmarkResult, ProblemBenchmarkResult problemBenchmarkResult) { SingleBenchmarkResult singleBenchmarkResult = new SingleBenchmarkResult(solverBenchmarkResult, problemBenchmarkResult); buildSubSingleBenchmarks(singleBenchmarkResult, solverBenchmarkResult.getSubSingleCount()); for (SubSingleBenchmarkResult subSingleBenchmarkResult : singleBenchmarkResult.getSubSingleBenchmarkResultList()) { subSingleBenchmarkResult.setPureSubSingleStatisticList(new ArrayList<>( singleStatisticTypeList == null ? 0 : singleStatisticTypeList.size())); } if (singleStatisticTypeList != null) { for (SingleStatisticType singleStatisticType : singleStatisticTypeList) { for (SubSingleBenchmarkResult subSingleBenchmarkResult : singleBenchmarkResult.getSubSingleBenchmarkResultList()) { subSingleBenchmarkResult.getPureSubSingleStatisticList().add(singleStatisticType.buildPureSubSingleStatistic(subSingleBenchmarkResult)); } } } singleBenchmarkResult.initSubSingleStatisticMaps(); solverBenchmarkResult.getSingleBenchmarkResultList().add(singleBenchmarkResult); problemBenchmarkResult.getSingleBenchmarkResultList().add(singleBenchmarkResult); } private void buildSubSingleBenchmarks(SingleBenchmarkResult parent, int subSingleCount) { List<SubSingleBenchmarkResult> subSingleBenchmarkResultList = new ArrayList<>(subSingleCount); for (int i = 0; i < subSingleCount; i++) { SubSingleBenchmarkResult subSingleBenchmarkResult = new SubSingleBenchmarkResult(parent, i); subSingleBenchmarkResultList.add(subSingleBenchmarkResult); } parent.setSubSingleBenchmarkResultList(subSingleBenchmarkResultList); } @Override public void inherit(ProblemBenchmarksConfig inheritedConfig) { solutionFileIOClass = ConfigUtils.inheritOverwritableProperty(solutionFileIOClass, inheritedConfig.getSolutionFileIOClass()); xStreamAnnotatedClassList = ConfigUtils.inheritMergeableListProperty(xStreamAnnotatedClassList, inheritedConfig.getXStreamAnnotatedClassList()); writeOutputSolutionEnabled = ConfigUtils.inheritOverwritableProperty(writeOutputSolutionEnabled, inheritedConfig.getWriteOutputSolutionEnabled()); inputSolutionFileList = ConfigUtils.inheritMergeableListProperty(inputSolutionFileList, inheritedConfig.getInputSolutionFileList()); problemStatisticTypeList = ConfigUtils.inheritMergeableListProperty(problemStatisticTypeList, inheritedConfig.getProblemStatisticTypeList()); singleStatisticTypeList = ConfigUtils.inheritMergeableListProperty(singleStatisticTypeList, inheritedConfig.getSingleStatisticTypeList()); } }