Pareto.java
Home
/
src /
main /
java /
br /
ufrgs /
inf /
prosoft /
tfcache /
Pareto.java
package br.ufrgs.inf.prosoft.tfcache;
import br.ufrgs.inf.prosoft.tfcache.configuration.Configuration;
import java.math.BigDecimal;
import java.math.MathContext;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class Pareto {
private final Map<Long, Metrics> savedTimeHasMetrics;
private Metrics bestMetrics;
private BigDecimal minEuclideanDistance;
public Pareto() {
savedTimeHasMetrics = new ConcurrentHashMap<>();
}
public Pareto(Collection<Metrics> metrics) {
this();
metrics.forEach(this::addIfPareto);
}
public Pareto(Stream<Metrics> metrics) {
this();
metrics.forEach(this::addIfPareto);
}
public static void removeDominatedMetrics(Collection<Metrics> allMetrics) {
Map<Long, List<Metrics>> groupBySavedTime = allMetrics.stream().collect(Collectors.groupingBy(Metrics::getSavedTime));
groupBySavedTime.remove(0L);
groupBySavedTime.forEach((savedTime, metrics) -> {
double minIdleTime = metrics.stream().mapToDouble(Metrics::getIdleTime).min().orElse(0);
metrics.removeIf(metric -> metric.getIdleTime() > minIdleTime);
});
List<Metrics> localMaxima = groupBySavedTime.values().stream()
.map(Collection::stream)
.reduce(Stream::concat)
.orElse(Stream.empty())
.collect(Collectors.toList());
allMetrics.removeIf(metrics -> !localMaxima.contains(metrics));
}
public synchronized void addIfPareto(Metrics metrics) {
savedTimeHasMetrics.merge(metrics.getSavedTime(), metrics, (existing, incoming) -> existing.getIdleTime() < incoming.getIdleTime() ? existing : incoming);
}
public Collection<Metrics> values() {
return savedTimeHasMetrics.values();
}
public Set<Long> getTtls() {
return values().stream().map(Metrics::getTtl).collect(Collectors.toSet());
}
public BigDecimal getNormalisedMinEuclideanDistance() {
if (savedTimeHasMetrics.isEmpty()) throw new RuntimeException("savedTimeHasMetrics is empty");
double minSavedTime = values().stream().mapToDouble(Metrics::getSavedTime).min().orElseThrow();
double maxSavedTime = values().stream().mapToDouble(Metrics::getSavedTime).max().orElseThrow();
double distanceSavedTime = maxSavedTime - minSavedTime;
double minIdleTime = values().stream().mapToDouble(Metrics::getIdleTime).min().orElseThrow();
double maxIdleTime = values().stream().mapToDouble(Metrics::getIdleTime).max().orElseThrow();
double distanceIdleTime = maxIdleTime - minIdleTime;
List<BigDecimal> normalisedEuclideanDistances = values().stream().map(it -> {
BigDecimal normalisedSavedTime = new BigDecimal(it.getSavedTime() - minSavedTime).divide(BigDecimal.valueOf(distanceSavedTime), MathContext.DECIMAL128);
BigDecimal normalisedIdleTime = new BigDecimal(it.getIdleTime() - minIdleTime).divide(BigDecimal.valueOf(distanceIdleTime), MathContext.DECIMAL128);
return Metrics.calculateEuclideanDistance(normalisedSavedTime, normalisedIdleTime, Configuration.getPreferences().get(0), Configuration.getPreferences().get(1));
}).collect(Collectors.toList());
return normalisedEuclideanDistances.stream().min(BigDecimal::compareTo).orElseThrow();
}
public BigDecimal getMinEuclideanDistance() {
getBestMetrics();
return minEuclideanDistance;
}
public Metrics getBestMetrics() {
if (bestMetrics == null) bestMetrics = getBestMetrics(Configuration.getPreferences().get(0), Configuration.getPreferences().get(1));
return bestMetrics;
}
private Metrics getBestMetrics(double percentageObjectiveSavedTime, double percentageObjectiveIdleTime) {
if (percentageObjectiveSavedTime < 0 || percentageObjectiveSavedTime > 1) throw new RuntimeException("invalid objective saved time");
if (percentageObjectiveIdleTime < 0 || percentageObjectiveIdleTime > 1) throw new RuntimeException("invalid objective idle time");
if (savedTimeHasMetrics.isEmpty()) return new Metrics();
double minIdleTime = values().stream().mapToDouble(Metrics::getIdleTime).min().orElseThrow() * percentageObjectiveIdleTime;
double maxSavedTime = values().stream().mapToDouble(Metrics::getSavedTime).max().orElseThrow() * percentageObjectiveSavedTime;
bestMetrics = values().stream().min(Comparator.comparing(it -> it.calculateEuclideanDistance(maxSavedTime, minIdleTime))).orElseThrow();
minEuclideanDistance = bestMetrics.calculateEuclideanDistance(maxSavedTime, minIdleTime);
return bestMetrics;
}
}