Thresholds.java

152 lines | 5.267 kB Blame History Raw Download
package br.ufrgs.inf.prosoft.aplcachetf.extension.metrics;

import java.math.BigDecimal;
import java.math.MathContext;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.List;

public class Thresholds {

  public static final List<BigDecimal> DISTANCES = new ArrayList<>();
  public static final List<Double> HIT_RATIOS = new ArrayList<>();
  public static final List<Double> MISS_RATIOS = new ArrayList<>();
  public static final List<Long> EXECUTION_TIMES = new ArrayList<>();
  public static final List<Double> SHAREABILITIES = new ArrayList<>();
  public static long population;
  private static BigDecimal stdDevDistance;
  private static Double stdDevHitRatio;
  private static Double stdDevMissRatio;
  private static Double stdDevExecutionTime;
  private static Double stdDevShareability;


  public static void reset() {
    Thresholds.population = 0;

    Thresholds.DISTANCES.clear();
    Thresholds.stdDevDistance = null;

    Thresholds.HIT_RATIOS.clear();
    Thresholds.stdDevHitRatio = null;

    Thresholds.MISS_RATIOS.clear();
    Thresholds.stdDevMissRatio = null;

    Thresholds.EXECUTION_TIMES.clear();
    Thresholds.stdDevExecutionTime = null;

    Thresholds.SHAREABILITIES.clear();
    Thresholds.stdDevShareability = null;
  }

  public static BigDecimal getAverageDistance() {
    if (DISTANCES.isEmpty()) return BigDecimal.ZERO;
    return DISTANCES.stream().reduce(BigDecimal::add).orElse(BigDecimal.ZERO).divide(BigDecimal.valueOf(DISTANCES.size()), MathContext.DECIMAL128);
  }

  public static BigDecimal getStdDevDistance() {
    if (population == 0) return BigDecimal.ZERO;
    if (stdDevDistance != null) return stdDevDistance;
    BigDecimal mean = getAverageDistance();
    BigDecimal temp = DISTANCES.stream()
      .map(difference -> difference.subtract(mean).multiply(difference.subtract(mean)))
      .reduce(BigDecimal::add)
      .orElse(BigDecimal.ZERO);
    stdDevDistance = temp.divide(BigDecimal.valueOf(population), MathContext.DECIMAL128).sqrt(MathContext.DECIMAL128);
    return stdDevDistance;
  }

  public static BigDecimal distanceThreshold(int kStdDev) {
    return getAverageDistance().subtract((getStdDevDistance().multiply(BigDecimal.valueOf(kStdDev))));
  }


  public static double getAverageHitRatio() {
    if (population == 0) return 0;
    return HIT_RATIOS.stream().reduce(Double::sum).orElse(0D) / population;
  }

  public static double getStdDevHitRatio() {
    if (population == 0) return 0;
    if (stdDevHitRatio != null) return stdDevHitRatio;
    double mean = getAverageHitRatio();
    double temp = HIT_RATIOS.stream()
      .map(hitRate -> (hitRate - mean) * (hitRate - mean))
      .reduce(Double::sum)
      .orElse(0D);
    stdDevHitRatio = Math.sqrt(temp / population);
    return stdDevHitRatio;
  }

  public static double hitThreshold(int kStdDev) {
    return getAverageHitRatio() + (kStdDev * getStdDevHitRatio());
  }


  public static double getAverageMissRatio() {
    if (population == 0) return 0;
    return BigDecimal.valueOf(MISS_RATIOS.stream().reduce(Double::sum).orElse(0D)).divide(new BigDecimal(population), 5, RoundingMode.HALF_UP).doubleValue();
  }

  public static double getStdDevMissRatio() {
    if (population == 0) return 0;
    if (stdDevMissRatio != null) return stdDevMissRatio;
    double mean = getAverageMissRatio();
    double temp = MISS_RATIOS.stream().map(missRatio -> (missRatio - mean) * (missRatio - mean))
      .reduce(Double::sum)
      .orElse(0D);
    stdDevMissRatio = Math.sqrt(temp / population);
    return stdDevMissRatio;
  }

  public static double missThreshold(int kStdDev) {
    return getAverageMissRatio() + (kStdDev * getStdDevMissRatio());
  }


  public static double getAverageExecutionTime() {
    if (population == 0) return 0;
    return new BigDecimal(EXECUTION_TIMES.stream().reduce(Long::sum).orElse(0L)).divide(new BigDecimal(population), 5, RoundingMode.HALF_UP).doubleValue();
  }

  public static double getStdDevExecutionTime() {
    if (population == 0) return 0;
    if (stdDevExecutionTime != null) return stdDevExecutionTime;
    double mean = getAverageExecutionTime();
    double temp = EXECUTION_TIMES.stream()
      .map(executionTime -> (executionTime - mean) * (executionTime - mean))
      .reduce(Double::sum)
      .orElse(0D);
    stdDevExecutionTime = Math.sqrt(temp / population);
    return stdDevExecutionTime;
  }

  public static double expensivenessThreshold(int kStdDev) {
    return getAverageExecutionTime() + (kStdDev * getStdDevExecutionTime());
  }


  public static double getAverageShareability() {
    if (population == 0) return 0;
    return BigDecimal.valueOf(SHAREABILITIES.stream().reduce(Double::sum).orElse(0D)).divide(new BigDecimal(population), 5, RoundingMode.HALF_UP).doubleValue();
  }

  public static double getStdDevShareability() {
    if (population == 0) return 0;
    if (stdDevShareability != null) return stdDevShareability;
    double mean = getAverageShareability();
    double temp = SHAREABILITIES.stream()
      .map(shareability -> (shareability - mean) * (shareability - mean))
      .reduce(Double::sum)
      .orElse(0D);
    stdDevShareability = Math.sqrt(temp / population);
    return stdDevShareability;
  }

  public static double shareabilityThreshold(int kStdDev) {
    return getAverageShareability() + (kStdDev * getStdDevShareability());
  }

}