tfcache

increased precision by changing to bigDecimal on euclidean

1/26/2021 1:27:48 AM

Details

diff --git a/src/main/java/br/ufrgs/inf/prosoft/tfcache/metadata/Method.java b/src/main/java/br/ufrgs/inf/prosoft/tfcache/metadata/Method.java
index ae74a46..6291cfb 100755
--- a/src/main/java/br/ufrgs/inf/prosoft/tfcache/metadata/Method.java
+++ b/src/main/java/br/ufrgs/inf/prosoft/tfcache/metadata/Method.java
@@ -6,6 +6,7 @@ import br.ufrgs.inf.prosoft.tfcache.Simulator;
 import br.ufrgs.inf.prosoft.tfcache.StorageManager;
 import br.ufrgs.inf.prosoft.tfcache.configuration.Configuration;
 
+import java.math.BigDecimal;
 import java.text.MessageFormat;
 import java.util.*;
 import java.util.concurrent.ConcurrentHashMap;
@@ -22,7 +23,7 @@ public class Method {
   private List<GroupOfOccurrences> groupsOfOccurrences;
   private Integer countChangeableGroups;
   private Pareto pareto;
-  private Double minEuclideanDistance;
+  private BigDecimal normalisedMinEuclideanDistance;
 
   public Method(String name, List<Occurrence> occurrences) {
     this.name = name;
@@ -48,9 +49,10 @@ public class Method {
     return name;
   }
 
-  public double getMinEuclideanDistance() {
-    if (minEuclideanDistance == null) minEuclideanDistance = this.pareto.getNormalised().getMinEuclideanDistance();
-    return minEuclideanDistance;
+  public BigDecimal getNormalisedMinEuclideanDistance() {
+    if (this.pareto == null) throw new RuntimeException("trying to access pareto before calculating it");
+    if (normalisedMinEuclideanDistance == null) normalisedMinEuclideanDistance = this.pareto.getNormalisedMinEuclideanDistance();
+    return normalisedMinEuclideanDistance;
   }
 
   public Metrics getBestMetrics() {
@@ -58,9 +60,9 @@ public class Method {
     return this.pareto.getBestMetrics();
   }
 
-  public double getEstimatedSavedTime() {
+  public long getEstimatedSavedTime() {
     if (getBestMetrics() != null) return getBestMetrics().getSavedTime();
-    return groupsOfOccurrences().map(it -> it.getBestMetrics().getSavedTime()).reduce(Double::sum).orElse(0D);
+    return groupsOfOccurrences().map(it -> it.getBestMetrics().getSavedTime()).reduce(Long::sum).orElse(0L);
   }
 
   public Stream<Occurrence> occurrences() {
diff --git a/src/main/java/br/ufrgs/inf/prosoft/tfcache/Metrics.java b/src/main/java/br/ufrgs/inf/prosoft/tfcache/Metrics.java
index d230722..40f3810 100755
--- a/src/main/java/br/ufrgs/inf/prosoft/tfcache/Metrics.java
+++ b/src/main/java/br/ufrgs/inf/prosoft/tfcache/Metrics.java
@@ -10,7 +10,6 @@ import br.ufrgs.inf.prosoft.tfcache.metadata.Occurrence;
 
 import java.math.BigDecimal;
 import java.math.MathContext;
-import java.util.logging.Level;
 import java.util.logging.Logger;
 import java.util.stream.Collectors;
 import java.util.stream.Stream;
@@ -20,167 +19,139 @@ import java.util.stream.Stream;
  */
 public class Metrics implements Comparable<Metrics> {
 
-    private long ttl;
-    private long hits;
-    private long timeInCache;
-    private long computationTime;
-    private long stales;
-    private double savedTime;
-
-    private transient String uuid;
-    private transient Double idleTime;
-
-    protected Metrics() {
-        Logger.getLogger(Metrics.class.getName()).log(Level.FINEST, "returning empty metrics");
-    }
-
-    public Metrics(long ttl, long hits, long timeInCache, long computationTime, long stales, double savedTime, String uuid) {
-        this(ttl, hits, timeInCache, computationTime, stales, savedTime);
-        this.uuid = uuid;
-    }
-
-    public Metrics(long ttl, long hits, long timeInCache, long computationTime, long stales, double savedTime) {
-        if (ttl < 0 || hits < 0 || timeInCache < 0 || computationTime < 0 || stales < 0 || savedTime < 0) {
-            throw new RuntimeException("Metrics cannot be under zero."
-                    + " TTL: " + ttl
-                    + " hits: " + hits
-                    + " timeInCache: " + timeInCache
-                    + " computationTime: " + computationTime
-                    + " stales: " + stales
-                    + " savedTime: " + savedTime);
-        }
-        if (ttl == 0 || computationTime == 0 || timeInCache == 0) {
-            throw new RuntimeException("Metrics cannot be zero."
-                    + " TTL: " + ttl
-                    + " timeInCache: " + timeInCache
-                    + " computationTime: " + computationTime);
-        }
-        this.ttl = ttl;
-        this.hits = hits;
-        this.timeInCache = timeInCache;
-        this.computationTime = computationTime;
-        this.stales = stales;
-        this.savedTime = savedTime;
-    }
-
-    public static String getUUID(Stream<Occurrence> occurrences) {
-        return occurrences.map(it -> it.getStartTime() + ":" + it.getEndTime()).collect(Collectors.joining(","));
-    }
-
-    private static double calculateEuclideanDistance(double x1, double y1, double x2, double y2) {
-        return Math.sqrt(Math.pow(x1 - x2, 2) - Math.pow(y1, y2));
-    }
-
-    protected double calculateEuclideanDistance(double objectiveSavedTime, double objectiveIdleTime) {
-        return calculateEuclideanDistance(getSavedTime(), getIdleTime(), objectiveSavedTime, objectiveIdleTime);
-    }
-
-    protected String getUUID() {
-        return uuid;
-    }
-
-    public long getTtl() {
-        return this.ttl;
-    }
-
-    public long getHits() {
-        return this.hits;
-    }
-
-    public long getTimeInCache() {
-        return timeInCache;
-    }
-
-    public double getIdleTime() {
-        if (this.idleTime == null) {
-            this.idleTime = (double) timeInCache - hits;
-        }
-        return this.idleTime;
-    }
-
-    public long getComputationTime() {
-        return computationTime;
-    }
-
-    public long getStales() {
-        return this.stales;
-    }
-
-    public double getSavedTime() {
-        return this.savedTime;
-    }
-
-    public BigDecimal getSavedTimePerTimeInCache() {
-        if (this.timeInCache + this.computationTime == 0) {
-            return BigDecimal.ZERO;
-        }
-        return new BigDecimal(this.savedTime)
-                .divide(new BigDecimal(this.timeInCache + this.computationTime), MathContext.DECIMAL128);
-    }
-
-    public Double getDifference() {
-        return Configuration.getPreferences().get(0) * getSavedTime() - Configuration.getPreferences().get(1) * getIdleTime();
-    }
-
-    protected Metrics getNormalised(double savedTime, double idleTime) {
-        if (savedTime < 0 || savedTime > 1) {
-            throw new RuntimeException("wrong savedTime");
-        }
-        if (idleTime < 0 || idleTime > 1) {
-            throw new RuntimeException("wrong idleTime");
-        }
-        Metrics metrics = new Metrics(ttl,
-                hits,
-                timeInCache,
-                computationTime,
-                stales,
-                savedTime,
-                uuid);
-        metrics.idleTime = idleTime;
-        return metrics;
-    }
-
-    @Override
-    public int compareTo(Metrics other) {
-        if (getTtl() == other.getTtl()) {
-            return 0;
-        }
-        if (getSavedTime() == other.getSavedTime() && getIdleTime() == other.getIdleTime()) {
-            throw new RuntimeException("different ttls leading to same metrics");
-        }
-        if (getSavedTime() >= other.getSavedTime() && getIdleTime() <= other.getIdleTime()) {
-            return 1;
-        }
-        if (getSavedTime() <= other.getSavedTime() && getIdleTime() >= other.getIdleTime()) {
-            return -1;
-        }
-        throw new RuntimeException("comparing pareto metrics");
-    }
-
-    @Override
-    public int hashCode() {
-        int hash = 7;
-        hash = 97 * hash + (int) (this.ttl ^ (this.ttl >>> 32));
-        return hash;
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-        if (!(obj instanceof Metrics)) {
-            return false;
-        }
-        return compareTo((Metrics) obj) == 0;
-    }
-
-    @Override
-    public String toString() {
-        return "TTL: " + this.ttl
-                + " STpTiC: " + getSavedTimePerTimeInCache()
-                + " Stales: " + this.stales
-                + " Hits: " + this.hits
-                + " SavedTime: " + this.savedTime
-                + " TimeInCache: " + this.timeInCache
-                + " ComputationTime: " + this.computationTime;
-    }
+  private static final Logger LOGGER = Logger.getLogger(Metrics.class.getName());
+  private long ttl;
+  private long hits;
+  private long timeInCache;
+  private long computationTime;
+  private long stales;
+  private long savedTime;
+
+  private transient Long idleTime;
+  private transient String uuid;
+
+  protected Metrics() {
+    LOGGER.finest("returning empty metrics");
+  }
+
+  public Metrics(long ttl, long hits, long timeInCache, long computationTime, long stales, long savedTime, String uuid) {
+    this(ttl, hits, timeInCache, computationTime, stales, savedTime);
+    this.uuid = uuid;
+  }
+
+  public Metrics(long ttl, long hits, long timeInCache, long computationTime, long stales, long savedTime) {
+    if (ttl < 0 || hits < 0 || timeInCache < 0 || computationTime < 0 || stales < 0 || savedTime < 0)
+      throw new RuntimeException("Metrics cannot be under zero."
+        + " TTL: " + ttl
+        + " hits: " + hits
+        + " timeInCache: " + timeInCache
+        + " computationTime: " + computationTime
+        + " stales: " + stales
+        + " savedTime: " + savedTime);
+    if (ttl == 0 || computationTime == 0 || timeInCache == 0) throw new RuntimeException("Metrics cannot be zero."
+      + " TTL: " + ttl
+      + " timeInCache: " + timeInCache
+      + " computationTime: " + computationTime);
+    this.ttl = ttl;
+    this.hits = hits;
+    this.timeInCache = timeInCache;
+    this.computationTime = computationTime;
+    this.stales = stales;
+    this.savedTime = savedTime;
+  }
+
+  public static String getUUID(Stream<Occurrence> occurrences) {
+    return occurrences.map(it -> it.getStartTime() + ":" + it.getEndTime()).collect(Collectors.joining(","));
+  }
+
+  public static BigDecimal calculateEuclideanDistance(double x1, double y1, double x2, double y2) {
+    return BigDecimal.valueOf(x1 - x2).pow(2).add(BigDecimal.valueOf(y1 - y2).pow(2)).sqrt(MathContext.DECIMAL128);
+  }
+
+  public static BigDecimal calculateEuclideanDistance(BigDecimal x1, BigDecimal y1, double x2, double y2) {
+    return x1.subtract(BigDecimal.valueOf(x2)).pow(2)
+      .add(y1.subtract(BigDecimal.valueOf(y2)).pow(2))
+      .sqrt(MathContext.DECIMAL128);
+  }
+
+  protected BigDecimal calculateEuclideanDistance(double objectiveSavedTime, double objectiveIdleTime) {
+    return calculateEuclideanDistance(getSavedTime(), getIdleTime(), objectiveSavedTime, objectiveIdleTime);
+  }
+
+  protected String getUUID() {
+    return uuid;
+  }
+
+  public long getTtl() {
+    return this.ttl;
+  }
+
+  public long getHits() {
+    return this.hits;
+  }
+
+  public long getTimeInCache() {
+    return timeInCache;
+  }
+
+  public long getIdleTime() {
+    if (this.idleTime == null) this.idleTime = timeInCache - hits;
+    return this.idleTime;
+  }
+
+  public long getComputationTime() {
+    return computationTime;
+  }
+
+  public long getStales() {
+    return this.stales;
+  }
+
+  public long getSavedTime() {
+    return this.savedTime;
+  }
+
+  public BigDecimal getSavedTimePerTimeInCache() {
+    if (this.timeInCache + this.computationTime == 0) return BigDecimal.ZERO;
+    return BigDecimal.valueOf(this.savedTime).divide(new BigDecimal(this.timeInCache + this.computationTime), MathContext.DECIMAL128);
+  }
+
+  public Double getDifference() {
+    return Configuration.getPreferences().get(0) * getSavedTime() - Configuration.getPreferences().get(1) * getIdleTime();
+  }
+
+  @Override
+  public int compareTo(Metrics other) {
+    if (getTtl() == other.getTtl()) return 0;
+    if (getSavedTime() == other.getSavedTime() && getIdleTime() == other.getIdleTime()) throw new RuntimeException("different ttls leading to same metrics");
+    if (getSavedTime() >= other.getSavedTime() && getIdleTime() <= other.getIdleTime()) return 1;
+    if (getSavedTime() <= other.getSavedTime() && getIdleTime() >= other.getIdleTime()) return -1;
+    throw new RuntimeException("comparing pareto metrics");
+  }
+
+  @Override
+  public int hashCode() {
+    int hash = 7;
+    hash = 97 * hash + (int) (this.ttl ^ (this.ttl >>> 32));
+    return hash;
+  }
+
+  @Override
+  public boolean equals(Object obj) {
+    if (!(obj instanceof Metrics)) {
+      return false;
+    }
+    return compareTo((Metrics) obj) == 0;
+  }
+
+  @Override
+  public String toString() {
+    return "TTL: " + this.ttl
+      + " SavedTime: " + this.savedTime
+      + " Hits: " + this.hits
+      + " ComputationTime: " + this.computationTime
+      + " TimeInCache: " + this.timeInCache
+      + " Stales: " + this.stales;
+  }
 
 }
diff --git a/src/main/java/br/ufrgs/inf/prosoft/tfcache/Pareto.java b/src/main/java/br/ufrgs/inf/prosoft/tfcache/Pareto.java
index 50e96cd..1d8fdac 100755
--- a/src/main/java/br/ufrgs/inf/prosoft/tfcache/Pareto.java
+++ b/src/main/java/br/ufrgs/inf/prosoft/tfcache/Pareto.java
@@ -2,6 +2,8 @@ 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;
@@ -9,9 +11,9 @@ import java.util.stream.Stream;
 
 public class Pareto {
 
-  private final Map<Double, Metrics> savedTimeHasMetrics;
+  private final Map<Long, Metrics> savedTimeHasMetrics;
   private Metrics bestMetrics;
-  private Double minEuclideanDistance;
+  private BigDecimal minEuclideanDistance;
 
   public Pareto() {
     savedTimeHasMetrics = new ConcurrentHashMap<>();
@@ -28,8 +30,8 @@ public class Pareto {
   }
 
   public static void removeDominatedMetrics(Collection<Metrics> allMetrics) {
-    Map<Double, List<Metrics>> groupBySavedTime = allMetrics.stream().collect(Collectors.groupingBy(Metrics::getSavedTime));
-    groupBySavedTime.remove(0D);
+    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);
@@ -45,7 +47,6 @@ public class Pareto {
   }
 
   public synchronized void addIfPareto(Metrics metrics) {
-    if (metrics.getSavedTime() == 0) return;
     savedTimeHasMetrics.merge(metrics.getSavedTime(), metrics, (existing, incoming) -> existing.getIdleTime() < incoming.getIdleTime() ? existing : incoming);
   }
 
@@ -57,8 +58,9 @@ public class Pareto {
     return values().stream().map(Metrics::getTtl).collect(Collectors.toSet());
   }
 
-  public Pareto getNormalised() {
-    if (savedTimeHasMetrics.isEmpty()) return this;
+  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;
@@ -66,23 +68,22 @@ public class Pareto {
     double maxIdleTime = values().stream().mapToDouble(Metrics::getIdleTime).max().orElseThrow();
     double distanceIdleTime = maxIdleTime - minIdleTime;
 
-    Stream<Metrics> normalisedPareto = values().stream().map(it -> {
-      double normalisedSavedTime = (it.getSavedTime() - minSavedTime) / distanceSavedTime;
-      double normalisedIdleTime = (it.getIdleTime() - minIdleTime) / distanceIdleTime;
-      return it.getNormalised(normalisedSavedTime, normalisedIdleTime);
-    });
-    return new Pareto(normalisedPareto);
+    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 Double getMinEuclideanDistance() {
-    if (minEuclideanDistance == null) getBestMetrics();
+  public BigDecimal getMinEuclideanDistance() {
+    getBestMetrics();
     return minEuclideanDistance;
   }
 
   public Metrics getBestMetrics() {
-    if (this.bestMetrics == null) this.bestMetrics = getBestMetrics(Configuration.getPreferences().get(0), Configuration.getPreferences().get(1));
-    this.minEuclideanDistance = this.bestMetrics.calculateEuclideanDistance(Configuration.getPreferences().get(0), Configuration.getPreferences().get(1));
-    return this.bestMetrics;
+    if (bestMetrics == null) bestMetrics = getBestMetrics(Configuration.getPreferences().get(0), Configuration.getPreferences().get(1));
+    return bestMetrics;
   }
 
   private Metrics getBestMetrics(double percentageObjectiveSavedTime, double percentageObjectiveIdleTime) {
@@ -91,7 +92,9 @@ public class Pareto {
     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;
-    return values().stream().min(Comparator.comparingDouble(it -> it.calculateEuclideanDistance(maxSavedTime, minIdleTime))).orElseThrow();
+    bestMetrics = values().stream().min(Comparator.comparing(it -> it.calculateEuclideanDistance(maxSavedTime, minIdleTime))).orElseThrow();
+    minEuclideanDistance = bestMetrics.calculateEuclideanDistance(maxSavedTime, minIdleTime);
+    return bestMetrics;
   }
 
 }
diff --git a/src/main/java/br/ufrgs/inf/prosoft/tfcache/Simulator.java b/src/main/java/br/ufrgs/inf/prosoft/tfcache/Simulator.java
index 7744b76..447c4a0 100755
--- a/src/main/java/br/ufrgs/inf/prosoft/tfcache/Simulator.java
+++ b/src/main/java/br/ufrgs/inf/prosoft/tfcache/Simulator.java
@@ -54,8 +54,8 @@ public class Simulator {
       if (occurrence.getExecutionTime() < 0) throw new RuntimeException("executionTime cannot be under zero");
       if (adjustedEndTime < adjustedStartTime) throw new RuntimeException("adjustedEndTime should not be lesser than adjustedStartTime");
 
-      if (inputHasCachedTime.containsKey(occurrence.getParametersSerialised()) &&
-        adjustedStartTime - inputHasCachedTime.get(occurrence.getParametersSerialised()) > ttl) {
+      if (inputHasCachedTime.containsKey(occurrence.getParametersSerialised())
+        && adjustedStartTime - inputHasCachedTime.get(occurrence.getParametersSerialised()) > ttl) {
         inputHasCachedTime.remove(occurrence.getParametersSerialised());
       }
       if (inputHasCachedTime.containsKey(occurrence.getParametersSerialised())) {