/*
* Copyright 2012 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.impl.ranking;
import java.util.Comparator;
import java.util.List;
import java.util.Objects;
import org.optaplanner.benchmark.impl.result.SingleBenchmarkResult;
import org.optaplanner.benchmark.impl.result.SolverBenchmarkResult;
import org.optaplanner.core.api.domain.solution.PlanningSolution;
import org.optaplanner.core.api.score.Score;
/**
* This {@link SolverRankingWeightFactory} orders a {@link SolverBenchmarkResult} by how many times each of its
* {@link SingleBenchmarkResult}s beat {@link SingleBenchmarkResult}s of the other {@link SolverBenchmarkResult}.
* It maximizes the overall ranking.
* <p>
* When the inputSolutions differ greatly in size or difficulty, this often produces a difference in
* {@link Score} magnitude between each {@link PlanningSolution}. For example: score 10 for dataset A versus 1000 for dataset B.
* In such cases, this ranking is more fair than {@link TotalScoreSolverRankingComparator},
* because in this ranking, dataset B wouldn't marginalize dataset A.
*/
public class TotalRankSolverRankingWeightFactory implements SolverRankingWeightFactory {
private final Comparator<SingleBenchmarkResult> singleBenchmarkRankingComparator = new TotalScoreSingleBenchmarkRankingComparator();
@Override
public Comparable createRankingWeight(List<SolverBenchmarkResult> solverBenchmarkResultList, SolverBenchmarkResult solverBenchmarkResult) {
int betterCount = 0;
int equalCount = 0;
int lowerCount = 0;
List<SingleBenchmarkResult> singleBenchmarkResultList = solverBenchmarkResult.getSingleBenchmarkResultList();
for (SingleBenchmarkResult single : singleBenchmarkResultList) {
List<SingleBenchmarkResult> otherSingleList = single.getProblemBenchmarkResult().getSingleBenchmarkResultList();
for (SingleBenchmarkResult otherSingle : otherSingleList) {
if (single == otherSingle) {
continue;
}
int scoreComparison = singleBenchmarkRankingComparator.compare(single, otherSingle);
if (scoreComparison > 0) {
betterCount++;
} else if (scoreComparison == 0) {
equalCount++;
} else {
lowerCount++;
}
}
}
return new TotalRankSolverRankingWeight(solverBenchmarkResult, betterCount, equalCount, lowerCount);
}
public static class TotalRankSolverRankingWeight implements Comparable<TotalRankSolverRankingWeight> {
private final Comparator<SolverBenchmarkResult> totalScoreSolverRankingComparator
= new TotalScoreSolverRankingComparator();
private SolverBenchmarkResult solverBenchmarkResult;
private int betterCount;
private int equalCount;
private int lowerCount;
public SolverBenchmarkResult getSolverBenchmarkResult() {
return solverBenchmarkResult;
}
public int getBetterCount() {
return betterCount;
}
public int getEqualCount() {
return equalCount;
}
public int getLowerCount() {
return lowerCount;
}
public TotalRankSolverRankingWeight(SolverBenchmarkResult solverBenchmarkResult,
int betterCount, int equalCount, int lowerCount) {
this.solverBenchmarkResult = solverBenchmarkResult;
this.betterCount = betterCount;
this.equalCount = equalCount;
this.lowerCount = lowerCount;
}
@Override
public int compareTo(TotalRankSolverRankingWeight other) {
return Comparator
.comparingInt(TotalRankSolverRankingWeight::getBetterCount)
.thenComparingInt(TotalRankSolverRankingWeight::getEqualCount)
.thenComparingInt(TotalRankSolverRankingWeight::getLowerCount)
.thenComparing(TotalRankSolverRankingWeight::getSolverBenchmarkResult, totalScoreSolverRankingComparator) // Tie-breaker
.compare(this, other);
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
} else if (o instanceof TotalRankSolverRankingWeight) {
TotalRankSolverRankingWeight other = (TotalRankSolverRankingWeight) o;
return this.compareTo(other) == 0;
} else {
return false;
}
}
@Override
public int hashCode() {
return Objects.hash(getBetterCount(), getEqualCount(), getLowerCount());
}
}
}