algorithms-for-computing-li.../src/main/java/de/wwwu/awolf/presenter/evaluation/EvaluatationHandler.java

283 lines
11 KiB
Java

package de.wwwu.awolf.presenter.evaluation;
import de.wwwu.awolf.model.Line;
import de.wwwu.awolf.model.LineModel;
import de.wwwu.awolf.model.communication.Data;
import de.wwwu.awolf.model.communication.EvaluationData;
import de.wwwu.awolf.model.communication.SubscriberType;
import de.wwwu.awolf.model.evaluation.ComparisonResult;
import de.wwwu.awolf.presenter.Presenter;
import de.wwwu.awolf.presenter.algorithms.Algorithm;
import de.wwwu.awolf.presenter.data.DataHandler;
import de.wwwu.awolf.presenter.data.generator.DatasetGenerator;
import de.wwwu.awolf.presenter.evaluation.measures.PercentageErrorBasedMeasure;
import de.wwwu.awolf.presenter.evaluation.measures.ScaleDependentMeasure;
import de.wwwu.awolf.presenter.evaluation.measures.ScaledErrorBasedMeasure;
import de.wwwu.awolf.presenter.util.Logging;
import java.io.File;
import java.util.Arrays;
import java.util.Collections;
import java.util.EnumMap;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.Flow;
/**
* Implementierung verschiedener Algorithmen zur Berechnung von Ausgleichsgeraden.
*
* @Author: Armin Wolf
* @Email: a_wolf28@uni-muenster.de
* @Date: 01.08.2017.
*/
public class EvaluatationHandler implements Runnable, Flow.Publisher<Data> {
private LineModel arrangement;
private DatasetGenerator generator;
//übergebene Parameter
private int type;
private int iterations;
private int alg;
private Flow.Subscriber<? super Data> subscriber;
private Map<Algorithm.Type, Map<String, String>> resultMapping;
/**
* Konstruktor zur evaluation
*
* @param type Typ der evaluation
* @param n Größe des Datensatzes
* @param alg 0 = lms, 1 = rm, 2 = ts, 3 = lms, rm, 4 = lms, ts, 5 = rm, ts, 6 = lms, rm, ts,
* @param datasettyp typ der zu generierenden Datensatz
*/
public EvaluatationHandler(int type, int n, int alg, DataHandler.DataType datasettyp) {
Presenter instance = Presenter.getInstance();
subscribe(instance);
this.arrangement = new LineModel();
this.resultMapping = new EnumMap<>(Algorithm.Type.class);
Set<Line> data = instance.generateDataset(n, datasettyp);
Logging.logInfo("Starting the Benchmark...");
arrangement.setLines(data);
Logging.logInfo("Benchmark on Dataset: " + datasettyp + " with " + n + " points");
this.type = type;
this.iterations = n;
this.alg = alg;
}
/**
* Konstruktor zur evaluation
*
* @param type Typ der evaluation
* @param alg 0 = lms, 1 = rm, 2 = ts, 3 = lms, rm, 4 = lms, ts, 5 = rm, ts, 6 = lms, rm, ts,
* @param file Datei die importiert werden soll
*/
public EvaluatationHandler(int type, int alg, File file) {
Presenter instance = Presenter.getInstance();
subscribe(instance);
instance.importDataset(file);
this.arrangement = instance.getModel();
this.resultMapping = new EnumMap<>(Algorithm.Type.class);
this.type = type;
this.alg = alg;
}
private Map<Algorithm.Type, Map<String, String>> benchmarkSameEstimator(
final Algorithm.Type advanced, final Algorithm.Type naiv) {
Logging
.logInfo("AlgorithmComparison with Types: " + advanced.name() + ", " + naiv.name());
AlgorithmComparison comparison = new AlgorithmComparison(Arrays.asList(naiv, advanced),
Collections.unmodifiableSet(arrangement.getLines()));
ComparisonResult comparisonResult = comparison.compare();
Map<String, String> result = new HashMap<>();
result.putAll(
getScaleDependentMeasure(arrangement.getLines(), comparisonResult, advanced));
result.putAll(
getScaledErrorBasedMeasure(arrangement.getLines(), comparisonResult, advanced,
naiv));
Logging.logInfo("finished with execution of the algorithms.");
this.resultMapping.put(advanced, result);
return this.resultMapping;
}
private Map<Algorithm.Type, Map<String, String>> benchmarkDifferentEstimators(
List<Algorithm.Type> types) {
Logging.logInfo("AlgorithmComparison with Types: " + types);
AlgorithmComparison comparison = new AlgorithmComparison(types,
Collections.unmodifiableSet(arrangement.getLines()));
ComparisonResult comparisonResult = comparison.compare();
types.forEach(typeEntry -> this.resultMapping.put(typeEntry,
getPercentigeErrorBasedMeasure(arrangement.getLines(), comparisonResult,
typeEntry)));
Logging.logInfo("finished with execution of the algorithms.");
return this.resultMapping;
}
/**
* Startet die Evaluation zu den passenden Typ. Bei beendigung wird der Beobachter informiert.
*/
@Override
public void run() {
Map<Algorithm.Type, Map<String, String>> result = new EnumMap<>(Algorithm.Type.class);
switch (type) {
case 0:
//der alg der gewählt wurde
if (alg == 0) {
result = benchmarkSameEstimator(Algorithm.Type.LMS,
Algorithm.Type.NAIVE_LMS);
} else if (alg == 1) {
result = benchmarkSameEstimator(Algorithm.Type.RM,
Algorithm.Type.NAIVE_RM);
} else {
result = benchmarkSameEstimator(Algorithm.Type.TS,
Algorithm.Type.NAIVE_TS);
}
break;
case 1:
switch (alg) {
case 3:
result = benchmarkDifferentEstimators(
Arrays.asList(Algorithm.Type.LMS, Algorithm.Type.RM));
break;
case 4:
result = benchmarkDifferentEstimators(
Arrays.asList(Algorithm.Type.LMS, Algorithm.Type.TS));
break;
case 5:
result = benchmarkDifferentEstimators(
Arrays.asList(Algorithm.Type.RM, Algorithm.Type.TS));
break;
case 6:
result = benchmarkDifferentEstimators(
Arrays.asList(Algorithm.Type.LMS, Algorithm.Type.RM,
Algorithm.Type.TS));
break;
}
break;
}
sendTableApproximationData(result);
}
/**
* Die berechneten Ergebnisse werden an den Beobachter übermittelt um dann visualisiert zu werden.
*
* @param result Ergebnisse
*/
private void sendTableApproximationData(Map<Algorithm.Type, Map<String, String>> result) {
EvaluationData data = new EvaluationData();
data.setType(SubscriberType.EVALUATION_TABLE_DATA);
data.setMultipleColumnResult(result);
data.setRowsPerColumn(result.keySet().size());
this.subscriber.onNext(data);
}
/**
* Startet die Berechnung der skalierungsabbhängigen Maße.
*
* @param lines Liste der Geraden
* @return Liste mit den Ergebnissen, bereit zum visualisieren
*/
private Map<String, String> getScaleDependentMeasure(final Set<Line> lines,
final ComparisonResult comparisonResult, final Algorithm.Type type) {
Logging.logInfo("Calculating ScaleDependentMeasure for " + type);
Double m = comparisonResult.get(type).getM();
Double b = comparisonResult.get(type).getB();
ScaleDependentMeasure scaleDependentMeasure = new ScaleDependentMeasure(lines, m, b);
Map<String, String> ret = new HashMap<>();
ret.put(type + " MSE", scaleDependentMeasure.mse().toString());
ret.put(type + " RMSE", scaleDependentMeasure.rmse().toString());
ret.put(type + " MAE", scaleDependentMeasure.mae().toString());
ret.put(type + " MDAE", scaleDependentMeasure.mdae().toString());
ret.put(type + " SLOPE", m.toString());
ret.put(type + " y-INTERCEPTION", b.toString());
Logging.logInfo("finished calculating ScaleDependentMeasure.");
return ret;
}
/**
* Startet die Berechnung der Maße die auf dem prozentualen Fehler basieren.
*
* @param lines Liste der Geraden
* @return Liste mit den Ergebnissen, bereit zum visualisieren
*/
private Map<String, String> getPercentigeErrorBasedMeasure(final Set<Line> lines,
final ComparisonResult comparisonResult, final Algorithm.Type type) {
Logging.logInfo("Calculating PercentigeErrorBasedMeasure for " + type);
Double m = comparisonResult.get(type).getM();
Double b = comparisonResult.get(type).getB();
PercentageErrorBasedMeasure percentageErrorBasedMeasure = new PercentageErrorBasedMeasure(
lines,
m, b);
Map<String, String> ret = new HashMap<>();
ret.put(type + " MAPE", percentageErrorBasedMeasure.mape().toString());
ret.put(type + " MDAPE", percentageErrorBasedMeasure.mdape().toString());
ret.put(type + " RMSPE", percentageErrorBasedMeasure.rmspe().toString());
ret.put(type + " RMDSPE", percentageErrorBasedMeasure.rmdspe().toString());
ret.put(type + " SLOPE", m.toString());
ret.put(type + " y-INTERCEPTION", b.toString());
Logging.logInfo("finished calculating PercentigeErrorBasedMeasure.");
return ret;
}
/**
* Startet die Berechnung der skalierungsunabbhängigen Maße.
*
* @param lines Liste der Geraden
* @return Liste mit den Ergebnissen, bereit zum visualisieren
*/
private Map<String, String> getScaledErrorBasedMeasure(final Set<Line> lines,
final ComparisonResult comparisonResult, final Algorithm.Type advanced,
final Algorithm.Type naiv) {
Logging.logInfo("Calculating ScaledErrorBasedMeasure for " + advanced + ", " + naiv);
//first
Double m = comparisonResult.get(advanced).getM();
Double b = comparisonResult.get(advanced).getB();
//second
Double naivM = comparisonResult.get(naiv).getM();
Double naivB = comparisonResult.get(naiv).getB();
ScaledErrorBasedMeasure scaledErrorBasedMeasure = new ScaledErrorBasedMeasure(lines, m,
b,
naivM, naivB);
Map<String, String> ret = new HashMap<>();
ret.put(advanced + " MSE", scaledErrorBasedMeasure.mse().toString());
ret.put(advanced + " RMSE", scaledErrorBasedMeasure.rmse().toString());
ret.put(advanced + " MAE", scaledErrorBasedMeasure.mae().toString());
ret.put(advanced + " MDAE", scaledErrorBasedMeasure.mdae().toString());
ret.put(advanced + " Naiv-SLOPE", naivM.toString());
ret.put(advanced + " Naiv-y-INTERCEPTION", naivB.toString());
Logging.logInfo("finished calculating ScaledErrorBasedMeasure.");
return ret;
}
/**
* @return Liste der Geraden auf der die Berechnungen ausgeführt wurden
*/
public Set<Line> getData() {
return arrangement.getLines();
}
@Override
public void subscribe(Flow.Subscriber<? super Data> subscriber) {
this.subscriber = subscriber;
}
}