further clean up

This commit is contained in:
Armin Wolf 2020-03-21 20:54:03 +01:00
parent 21c072fe7a
commit a246f8f203
34 changed files with 1765 additions and 1159 deletions

File diff suppressed because it is too large Load Diff

View File

@ -1,27 +1,12 @@
package de.wwwu.awolf;
import de.wwwu.awolf.model.Line;
import de.wwwu.awolf.model.LineModel;
import de.wwwu.awolf.model.Point;
import de.wwwu.awolf.presenter.Presenter;
import de.wwwu.awolf.presenter.algorithms.advanced.LeastMedianOfSquaresEstimator;
import de.wwwu.awolf.presenter.algorithms.advanced.RepeatedMedianEstimator;
import de.wwwu.awolf.presenter.algorithms.advanced.TheilSenEstimator;
import de.wwwu.awolf.presenter.algorithms.naiv.NaivLeastMedianOfSquaresEstimator;
import de.wwwu.awolf.presenter.algorithms.naiv.NaivRepeatedMedianEstimator;
import de.wwwu.awolf.presenter.algorithms.naiv.NaivTheilSenEstimator;
import de.wwwu.awolf.presenter.generator.DatasetGenerator;
import de.wwwu.awolf.presenter.util.IntersectionComputer;
import de.wwwu.awolf.presenter.util.Logging;
import de.wwwu.awolf.view.MainFrame;
import org.apache.commons.cli.*;
import javax.swing.*;
import java.awt.*;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* Implementierung verschiedener Algorithmen zur Berechnung von Ausgleichsgeraden.
@ -49,62 +34,27 @@ public class App {
}
}
/**
* Die Methode rechnet für gegebene Größen die Algorithmen durch und gibt jeweils die benötigte Zeit
*/
public static void benchmark() {
ExecutorService executorService = Executors.newFixedThreadPool(6);
Logging.logInfo("---- Datasetgröße: " + 100 + " ----");
DatasetGenerator generator = new DatasetGenerator();
LinkedList<Line> lines = generator.generateDataCloud(10000);
IntersectionComputer computer = new IntersectionComputer(lines);
ArrayList<Point> points = computer.compute();
executorService.submit(new NaivLeastMedianOfSquaresEstimator(lines));
executorService.submit(new NaivRepeatedMedianEstimator(lines));
executorService.submit(new NaivTheilSenEstimator(lines));
executorService.submit(new LeastMedianOfSquaresEstimator(lines, points));
executorService.submit(new RepeatedMedianEstimator(lines));
executorService.submit(new TheilSenEstimator(lines, points));
}
/**
* Maim Methode
*
* @param argv
*/
public static void main(String[] argv) {
Options options = new Options();
options.addOption("benchmark", "Start stresstest");
options.addOption("", "default");
CommandLineParser parser = new DefaultParser();
try {
CommandLine line = parser.parse(options, argv); // Sensitive
String[] args = line.getArgs();
if (args.length > 0 && args[0].equals("benchmark")) {
benchmark();
} else {
final Presenter presenter = new Presenter(new LineModel(), null);
SwingUtilities.invokeLater(() -> {
MainFrame view = new MainFrame();
setUIFont(new javax.swing.plaf.FontUIResource(new Font("SansSerif", Font.PLAIN, 12)));
try {
UIManager.setLookAndFeel("javax.swing.plaf.metal.MetalLookAndFeel");
} catch (ClassNotFoundException | UnsupportedLookAndFeelException | IllegalAccessException | InstantiationException e) {
Logging.logError("Error with the UI. ", e);
}
view.setPresenter(presenter);
view.setActionListeners();
presenter.setView(view);
});
final Presenter presenter = new Presenter(new LineModel(), null);
SwingUtilities.invokeLater(() -> {
MainFrame view = new MainFrame();
setUIFont(new javax.swing.plaf.FontUIResource(new Font("SansSerif", Font.PLAIN, 12)));
try {
UIManager.setLookAndFeel("javax.swing.plaf.metal.MetalLookAndFeel");
} catch (ClassNotFoundException | UnsupportedLookAndFeelException | IllegalAccessException | InstantiationException e) {
Logging.logError("Error with the UI. ", e);
}
} catch (ParseException e) {
Logging.logError("Error while parsing the command line arguments.", e);
}
view.setPresenter(presenter);
view.setActionListeners();
presenter.setView(view);
});
}

View File

@ -2,16 +2,44 @@ package de.wwwu.awolf.model.communication;
import de.wwwu.awolf.presenter.algorithms.Algorithm;
import java.io.Serializable;
import java.util.List;
import java.util.Map;
public class EvaluationData implements Data {
private SubscriberType type;
private List<Algorithm.Type> algorithmtypes;
private List<Double> oneColumnresult;
private List<List<String>> multipleColumnResult;
private List<Serializable> oneColumnresult;
private Map<Algorithm.Type, Map<String, String>> multipleColumnResult;
private int rowsPerColumn;
private int column;
private List<String> labels;
public int getRowsPerColumn() {
return rowsPerColumn;
}
public void setRowsPerColumn(int rowsPerColumn) {
this.rowsPerColumn = rowsPerColumn;
}
public int getColumn() {
return column;
}
public void setColumn(int col) {
this.column = col;
}
public List<String> getLabels() {
return labels;
}
public void setLabels(List<String> tableInput) {
this.labels = tableInput;
}
public List<Algorithm.Type> getAlgorithmtypes() {
return algorithmtypes;
}
@ -20,19 +48,19 @@ public class EvaluationData implements Data {
this.algorithmtypes = algorithmtype;
}
public List<Double> getOneColumnresult() {
public List<Serializable> getOneColumnresult() {
return oneColumnresult;
}
public void setOneColumnresult(List<Double> oneColumnresult) {
public void setOneColumnresult(List<Serializable> oneColumnresult) {
this.oneColumnresult = oneColumnresult;
}
public List<List<String>> getMultipleColumnResult() {
public Map<Algorithm.Type, Map<String, String>> getMultipleColumnResult() {
return multipleColumnResult;
}
public void setMultipleColumnResult(List<List<String>> multipleColumnResult) {
public void setMultipleColumnResult(Map<Algorithm.Type, Map<String, String>> multipleColumnResult) {
this.multipleColumnResult = multipleColumnResult;
}
@ -45,12 +73,4 @@ public class EvaluationData implements Data {
public void setType(SubscriberType type) {
this.type = type;
}
public void setColumn(int col) {
this.column = col;
}
public void setLabels(List<String> tableInput) {
this.labels = tableInput;
}
}

View File

@ -1,25 +0,0 @@
package de.wwwu.awolf.model.communication;
public class ExportData implements Data {
private SubscriberType type;
private String message;
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
@Override
public SubscriberType getType() {
return type;
}
@Override
public void setType(SubscriberType type) {
this.type = type;
}
}

View File

@ -2,17 +2,14 @@ package de.wwwu.awolf.model.communication;
public enum SubscriberType {
EVALUATE_DATASET_GENERATED,
EVAL_D,
EVAL_DS,
EVALUATION_TABLE_DATA,
EVAL_T,
LINES_RES,
LINES_RES_MULT,
LMS,
RM,
TS,
IMPORT,
PICTURE,
EXPORT,
GENERATOR
}

View File

@ -0,0 +1,25 @@
package de.wwwu.awolf.model.evaluation;
import de.wwwu.awolf.model.Line;
import de.wwwu.awolf.presenter.algorithms.Algorithm;
import java.util.EnumMap;
import java.util.Map;
public class ComparisonResult {
private final Map<Algorithm.Type, Line> resultMapping;
public ComparisonResult() {
this.resultMapping = new EnumMap<>(Algorithm.Type.class);
}
public void put(final Algorithm.Type type, final Line lineResult) {
this.resultMapping.put(type, lineResult);
}
public Line get(final Algorithm.Type type) {
return this.resultMapping.get(type);
}
}

View File

@ -2,6 +2,7 @@ package de.wwwu.awolf.presenter;
import de.wwwu.awolf.model.LineModel;
import de.wwwu.awolf.model.communication.Data;
import de.wwwu.awolf.presenter.data.DataProvider;
import de.wwwu.awolf.presenter.evaluation.EvaluateAlgorithms;
import de.wwwu.awolf.presenter.util.IntersectionComputer;
import de.wwwu.awolf.presenter.util.Logging;
@ -25,6 +26,7 @@ public abstract class AbstractPresenter implements Flow.Subscriber<Data> {
private LineModel model;
private MainFrame view;
private EvaluateAlgorithms eval;
private DataProvider dataProvider;
/**
* Konstruktor
@ -36,6 +38,7 @@ public abstract class AbstractPresenter implements Flow.Subscriber<Data> {
this.model = model;
this.view = view;
executor = Executors.newCachedThreadPool();
dataProvider = new DataProvider(this);
}
@ -49,21 +52,9 @@ public abstract class AbstractPresenter implements Flow.Subscriber<Data> {
@Override
public void onNext(Data data) {
switch (data.getType()) {
case EVAL_D:
evaluatedData(data);
break;
case EVAL_DS:
case EVALUATION_TABLE_DATA:
evaluatedDatas(data);
break;
case EVAL_T:
evaluatedTypes(data);
break;
case LINES_RES:
visualizeResults(data);
break;
case LINES_RES_MULT:
visualizeMultipleData(data);
break;
case LMS:
visualizeLmsAlgorithm(data);
break;
@ -73,12 +64,6 @@ public abstract class AbstractPresenter implements Flow.Subscriber<Data> {
case TS:
visualizeTsAlgorithm(data);
break;
case IMPORT:
handleImport(data);
break;
case EXPORT:
handleExport(data);
break;
case GENERATOR:
Logging.logInfo("Generierung war Erfolgreich");
break;
@ -87,26 +72,14 @@ public abstract class AbstractPresenter implements Flow.Subscriber<Data> {
}
}
protected abstract void handleExport(Data data);
protected abstract void handleImport(Data data);
protected abstract void visualizeTsAlgorithm(Data data);
protected abstract void visualizeRmAlgorithm(Data data);
protected abstract void visualizeLmsAlgorithm(Data data);
protected abstract void visualizeMultipleData(Data data);
protected abstract void visualizeResults(Data data);
protected abstract void evaluatedTypes(Data data);
protected abstract void evaluatedDatas(Data data);
protected abstract void evaluatedData(Data data);
@Override
public void onError(Throwable throwable) {
@ -143,7 +116,7 @@ public abstract class AbstractPresenter implements Flow.Subscriber<Data> {
start = System.currentTimeMillis();
startIntersectionCalculation();
end = System.currentTimeMillis();
Logging.logInfo("Zeit: " + (end - start) / 1000);
Logging.logInfo("Computing intersections took " + (end - start) / 1000 + "ms");
});
//darstellung der Ergebnisse
@ -200,7 +173,15 @@ public abstract class AbstractPresenter implements Flow.Subscriber<Data> {
this.eval = eval;
}
public DataProvider getDataProvider() {
return dataProvider;
}
public ExecutorService getExecutor() {
return executor;
if (executor == null)
return Executors.newCachedThreadPool();
else
return executor;
}
}

View File

@ -4,16 +4,12 @@ import de.wwwu.awolf.model.Line;
import de.wwwu.awolf.model.LineModel;
import de.wwwu.awolf.model.communication.AlgorithmData;
import de.wwwu.awolf.model.communication.Data;
import de.wwwu.awolf.model.communication.ExportData;
import de.wwwu.awolf.model.communication.ImportData;
import de.wwwu.awolf.model.communication.EvaluationData;
import de.wwwu.awolf.presenter.algorithms.advanced.LeastMedianOfSquaresEstimator;
import de.wwwu.awolf.presenter.algorithms.advanced.RepeatedMedianEstimator;
import de.wwwu.awolf.presenter.algorithms.advanced.TheilSenEstimator;
import de.wwwu.awolf.presenter.data.DataProvider;
import de.wwwu.awolf.presenter.evaluation.EvaluateAlgorithms;
import de.wwwu.awolf.presenter.evaluation.PictureProcessor;
import de.wwwu.awolf.presenter.generator.DatasetGenerator;
import de.wwwu.awolf.presenter.io.DataExporter;
import de.wwwu.awolf.presenter.io.DataImporter;
import de.wwwu.awolf.presenter.util.Logging;
import de.wwwu.awolf.view.MainFrame;
@ -36,33 +32,12 @@ public class Presenter extends AbstractPresenter {
super(model, view);
}
@Override
protected void handleExport(Data data) {
ExportData exportData = (ExportData) data;
Logging.logInfo(exportData.getMessage());
Logging.logInfo("Export der Daten als CSV");
Logging.logInfo("Export war Erfolgreich");
}
@Override
protected void handleImport(Data data) {
ImportData importData = (ImportData) data;
double max = importData.getNumberOfLines();
double current = importData.getCurrent();
Integer progress = (int) (100 * (current / max));
//100% erreicht
Logging.logInfo("Import war erfolgreich!");
SwingUtilities.invokeLater(() -> getView().showImportProgress(progress));
}
@Override
protected void visualizeTsAlgorithm(Data data) {
AlgorithmData algorithmData = (AlgorithmData) data;
SwingUtilities.invokeLater(() -> getView().visualizeTS(algorithmData.getLineData()));
Logging.logInfo("Theil-Sen Estimator");
Logging.logInfo(algorithmData.getLineData().toString());
Logging.logInfo("Berechnung wurde Erfolgreich durchgeführt.");
}
@Override
@ -71,7 +46,6 @@ public class Presenter extends AbstractPresenter {
SwingUtilities.invokeLater(() -> getView().visualizeRM(algorithmData.getLineData()));
Logging.logInfo("Repeated Median Estimator");
Logging.logInfo(algorithmData.getLineData().toString());
Logging.logInfo("Berechnung wurde Erfolgreich durchgeführt.");
}
@Override
@ -80,34 +54,12 @@ public class Presenter extends AbstractPresenter {
SwingUtilities.invokeLater(() -> getView().visualizeLMS(algorithmData.getLineData()));
Logging.logInfo("Least Median of Squares");
Logging.logInfo(algorithmData.getLineData().toString());
Logging.logInfo("Berechnung wurde Erfolgreich durchgeführt.");
}
@Override
protected void visualizeMultipleData(Data data) {
//Result:
//0:
SwingUtilities.invokeLater(() -> getView().drawLineResults(result));
}
@Override
protected void visualizeResults(Data data) {
SwingUtilities.invokeLater(() -> getView().drawLineResults(result));
}
@Override
protected void evaluatedTypes(Data data) {
SwingUtilities.invokeLater(() -> getView().appendEvalResult(result, Integer.parseInt(result[1]), true));
}
@Override
protected void evaluatedDatas(Data data) {
SwingUtilities.invokeLater(() -> getView().appendEvalResult(result));
}
@Override
protected void evaluatedData(Data data) {
SwingUtilities.invokeLater(() -> getView().appendEvalResult(result, Integer.parseInt(result[1]), false));
EvaluationData evaluationData = (EvaluationData) data;
SwingUtilities.invokeLater(() -> getView().appendEvalResults(evaluationData.getMultipleColumnResult()));
}
@ -128,14 +80,13 @@ public class Presenter extends AbstractPresenter {
if (input[0] != null && input[1] != null) {
//Parameter für den Algortihmus
Double constant = Double.parseDouble(input[0]);
Double error = Double.parseDouble(input[1]);
double error = Double.parseDouble(input[1]);
LeastMedianOfSquaresEstimator lms = new LeastMedianOfSquaresEstimator(getModel().getLines(), getModel().getNodes(), this);
//setzen der Parameter
lms.setConstant(constant);
lms.setQuantileError(error);
//Presenter soll die Klasse überwachen
getExecutor().execute(lms);
getExecutor().submit(lms);
}
}
@ -151,8 +102,7 @@ public class Presenter extends AbstractPresenter {
Double parameter = Double.parseDouble(input);
rm.setBeta(parameter);
//Presenter soll die Klasse überwachen
getExecutor().execute(rm);
getExecutor().submit(rm);
}
}
@ -166,8 +116,7 @@ public class Presenter extends AbstractPresenter {
if (input != null) {
TheilSenEstimator ts = new TheilSenEstimator(getModel().getLines(), getModel().getNodes(), this);
//Presenter soll die Klasse überwachen
getExecutor().execute(ts);
getExecutor().submit(ts);
}
}
@ -181,41 +130,12 @@ public class Presenter extends AbstractPresenter {
* @param file importierender Datensatz
*/
public void startImport(File file) {
DataImporter importer = new DataImporter(file, this);
//Presenter soll die Klasse überwachen
getExecutor().execute(new Runnable() {
@Override
public void run() {
List<Line> importedLines = importer.run();
if (importedLines != null) {
//Berechnung der Schnittpunkte und vis. der Ergebnisse (anz. Geraden, anz. Schnittpunkte)
getModel().setLines(importedLines);
computeIntersections();
}
}
});
}
/**
* Startet den Import eines Bildes.
*
* @param file importierendes Bild
*/
public void startPictureDataImport(File file) {
PictureProcessor pictureProcessor = new PictureProcessor(this, file);
//Presenter soll die Klasse überwachen
getExecutor().execute(new Runnable() {
@Override
public void run() {
pictureProcessor.run();
//Berechnung der Schnittpunkte und vis. der Ergebnisse (anz. Geraden, anz. Schnittpunkte)
computeIntersections();
}
});
List<Line> data = getDataProvider().getData(file);
if (data != null) {
//Berechnung der Schnittpunkte und vis. der Ergebnisse (anz. Geraden, anz. Schnittpunkte)
getModel().setLines(data);
computeIntersections();
}
}
@ -225,15 +145,7 @@ public class Presenter extends AbstractPresenter {
* @param file Datei in der die Informationen gespeichert werden sollen
*/
public void startExport(File file) {
DataExporter exporter = new DataExporter(getModel().getLines(), file, this);
//Presenter soll die Klasse überwachen
getExecutor().execute(new Runnable() {
@Override
public void run() {
exporter.export();
}
});
getDataProvider().exportData(file, getModel().getLines());
}
/**
@ -242,15 +154,7 @@ public class Presenter extends AbstractPresenter {
* @param file Datei in der die Informationen gespeichert werden sollen
*/
public void startDatasetExportEvaluation(File file) {
DataExporter exporter = new DataExporter(getEval().getData(), file, this);
//Presenter soll die Klasse überwachen
getExecutor().execute(new Runnable() {
@Override
public void run() {
exporter.export();
}
});
getDataProvider().exportData(file, getEval().getData());
}
/**
@ -259,23 +163,11 @@ public class Presenter extends AbstractPresenter {
* @param n Größe des Datensatzes
* @param type Art der Datensatzes
*/
public void generateDataset(int n, int type) {
DatasetGenerator generator = new DatasetGenerator(this);
getExecutor().execute(() -> {
switch (type) {
case 1:
getModel().setLines(generator.generateDataLines(n));
break;
case 2:
getModel().setLines(generator.generateCircle(n));
break;
default:
getModel().setLines(generator.generateDataCloud(n));
break;
}
computeIntersections();
getView().enableFunctionality();
});
public void generateDataset(int n, DataProvider.DataType type) {
List<Line> data = getDataProvider().getData(type, n);
getModel().setLines(data);
computeIntersections();
getView().enableFunctionality();
}
/**
@ -286,14 +178,10 @@ public class Presenter extends AbstractPresenter {
* @param typ Typ der Evaluation
* @param n Größe des Datensatzes
* @param alg code für die auszuführenden Algorithmen (siehe <code>EvaluationPanel.checkSelection()</code> Method)
* @param datasettyp Typ des Datensatzes (Geradem Punktwolke, Kreis und Gerade)
* @param datasetTyp Typ des Datensatzes (Geradem Punktwolke, Kreis und Gerade)
*/
public void startEvaluation(int typ, int n, int alg, String datasettyp) {
setEval(new EvaluateAlgorithms(typ, n, alg, datasettyp, this));
getExecutor().submit(() -> {
getEval().run();
});
public void startEvaluation(int typ, int n, int alg, DataProvider.DataType datasetTyp) {
getExecutor().submit(new EvaluateAlgorithms(typ, n, alg, datasetTyp, this));
}
/**
@ -306,14 +194,6 @@ public class Presenter extends AbstractPresenter {
* @param file Typ des Datensatzes (Geradem Punktwolke, Kreis und Gerade)
*/
public void startEvaluation(int typ, int alg, File file) {
EvaluateAlgorithms evaluateAlgorithms = new EvaluateAlgorithms(typ, alg, file);
if (evaluateAlgorithms.getData().size() > 0) {
setEval(evaluateAlgorithms);
}
getExecutor().submit(() -> {
getEval().run();
}).isDone();
getExecutor().submit(new EvaluateAlgorithms(typ, alg, file, this));
}
}

View File

@ -1,5 +1,9 @@
package de.wwwu.awolf.presenter.algorithms;
import de.wwwu.awolf.model.Line;
import java.util.concurrent.Callable;
/**
* Implementierung verschiedener Algorithmen zur Berechnung von Ausgleichsgeraden.
*
@ -7,7 +11,14 @@ package de.wwwu.awolf.presenter.algorithms;
* @Email: a_wolf28@uni-muenster.de
* @Date: 28.05.2017.
*/
public interface Algorithm extends Runnable {
public interface Algorithm extends Callable<Line> {
/**
* Startet die Berechnung des jeweiligen Algorithmus.
*/
@Override
Line call();
enum Type {
LMS,
@ -17,16 +28,4 @@ public interface Algorithm extends Runnable {
NAIV_RM,
NAIV_TS
}
/**
* Startet die Berechnung des jeweiligen Algorithmus.
*/
@Override
void run();
/**
* Standardisierung der Lösung in Form (m,b), sodass die Geraden Visualisiert werden können.
*/
void pepareResult();
}

View File

@ -11,7 +11,6 @@ import de.wwwu.awolf.presenter.algorithms.Algorithm;
import de.wwwu.awolf.presenter.util.IntersectionCounter;
import de.wwwu.awolf.presenter.util.Logging;
import java.security.SecureRandom;
import java.util.*;
import java.util.concurrent.Flow;
@ -82,7 +81,8 @@ public class LeastMedianOfSquaresEstimator implements Algorithm, Flow.Publisher<
* A practical approximation algorithm for the LMS line estimator. 2007
* Computational statistics & data Analysis 51.5, S. 24612486
*/
public void run() {
@Override
public Line call() {
Logging.logInfo("=== S T A R T - L M S ===");
long start;
@ -103,7 +103,7 @@ public class LeastMedianOfSquaresEstimator implements Algorithm, Flow.Publisher<
intervals = new PriorityQueue<>(comparator);
intervals.add(new Interval(-100000, 100000));
heightsigmaMin = Double.MAX_VALUE;
List<Point> tmpIntersections = intersections;
List<Point> tmpIntersections = new ArrayList<>(intersections);
//(3.) Apply the following steps as long as the exists active intervals
boolean active = true;
@ -120,7 +120,7 @@ public class LeastMedianOfSquaresEstimator implements Algorithm, Flow.Publisher<
} else {
//(c.) otherwise....
// get random intersections point...
Collections.shuffle(tmpIntersections, new SecureRandom());
Collections.shuffle(tmpIntersections);
boolean found = false;
for (Point tmpIntersection : tmpIntersections) {
if (tmpIntersection.getX() > interval.getLower()
@ -156,7 +156,7 @@ public class LeastMedianOfSquaresEstimator implements Algorithm, Flow.Publisher<
end = System.currentTimeMillis();
Logging.logInfo("Zeit: " + ((end - start) / 1000));
pepareResult();
return pepareResult();
}
/**
@ -367,8 +367,7 @@ public class LeastMedianOfSquaresEstimator implements Algorithm, Flow.Publisher<
}
@Override
public void pepareResult() {
private Line pepareResult() {
if (this.subscriber != null) {
double m = (getSigmaMin().getX2() + getSigmaMin().getX1()) * 0.5;
double b = (getSigmaMin().getY2() + getSigmaMin().getY1()) * -0.5;
@ -387,6 +386,8 @@ public class LeastMedianOfSquaresEstimator implements Algorithm, Flow.Publisher<
slope = m;
yInterception = b;
}
return new Line(getSlope(), getYInterception());
}
/**
@ -455,7 +456,7 @@ public class LeastMedianOfSquaresEstimator implements Algorithm, Flow.Publisher<
/**
* @return y-Achsenabschnitt
*/
public Double getyInterception() {
public Double getYInterception() {
return yInterception;
}

View File

@ -104,7 +104,7 @@ public class RepeatedMedianEstimator implements Algorithm, Flow.Publisher<Data>
* Efficient Randomized Algorithms for the Repeated Median Line Estimator. 1998
* Algorithmica 20.2, S. 136150
*/
public void run() {
public Line call() {
Logging.logInfo("=== S T A R T - R M ===");
long start;
@ -145,7 +145,7 @@ public class RepeatedMedianEstimator implements Algorithm, Flow.Publisher<Data>
end = System.currentTimeMillis();
Logging.logInfo("Zeit: " + ((end - start) / 1000));
pepareResult();
return pepareResult();
}
@ -252,8 +252,7 @@ public class RepeatedMedianEstimator implements Algorithm, Flow.Publisher<Data>
}
}
@Override
public void pepareResult() {
private Line pepareResult() {
if (this.subscriber != null) {
double m = thetaLow;
double b = (-1) * (
@ -272,6 +271,8 @@ public class RepeatedMedianEstimator implements Algorithm, Flow.Publisher<Data>
slope = m;
yInterception = b;
}
return new Line(getSlope(), getyInterception());
}
/**

View File

@ -95,7 +95,7 @@ public class TheilSenEstimator implements Algorithm, Flow.Publisher<Data> {
* "Jiri Matousek, Randomized optimal algorithm for slope selection,
* Information Processing Letters 39 (1991) 183-187
*/
public void run() {
public Line call() {
//damit eine initiale Ordnung herscht
//Collections.sort(intervalIntersections);
@ -130,7 +130,7 @@ public class TheilSenEstimator implements Algorithm, Flow.Publisher<Data> {
}
}
pepareResult();
return pepareResult();
}
@ -216,8 +216,7 @@ public class TheilSenEstimator implements Algorithm, Flow.Publisher<Data> {
return list;
}
@Override
public void pepareResult() {
private Line pepareResult() {
double m, x;
double b, y;
@ -248,6 +247,8 @@ public class TheilSenEstimator implements Algorithm, Flow.Publisher<Data> {
data.setLineData(new Line(m, b));
this.subscriber.onNext(data);
}
return new Line(getSlope(), getYInterception());
}
/**
@ -260,7 +261,7 @@ public class TheilSenEstimator implements Algorithm, Flow.Publisher<Data> {
/**
* @return y-Achsenabschnitt
*/
public Double getyInterception() {
public Double getYInterception() {
return yInterception;
}

View File

@ -37,7 +37,7 @@ public class NaivLeastMedianOfSquaresEstimator implements Algorithm {
/**
* Crude Algorithmus zum berechnen des LSM-Schätzers.
*/
private void crudeAlg() {
private Line crudeAlg() {
ds = Double.MAX_VALUE;
b = 0d;
m = 0d;
@ -70,6 +70,8 @@ public class NaivLeastMedianOfSquaresEstimator implements Algorithm {
}
end = System.currentTimeMillis();
Logging.logInfo("Zeit: " + ((end - start) / 1000));
return new Line(getSlope(), getYInterception());
}
/**
@ -88,26 +90,21 @@ public class NaivLeastMedianOfSquaresEstimator implements Algorithm {
}
@Override
public void run() {
crudeAlg();
}
@Override
public void pepareResult() {
public Line call() {
return crudeAlg();
}
/**
* @return y-Achsenabschnitt
*/
public Double getB() {
public Double getYInterception() {
return b * -1;
}
/**
* @return Steigung
*/
public Double getM() {
public Double getSlope() {
return m * -1;
}
}

View File

@ -42,7 +42,7 @@ public class NaivRepeatedMedianEstimator implements Algorithm {
}
@Override
public void run() {
public Line call() {
//init the List for the slopes
Logging.logInfo("=== S T A R T - naiv R M ===");
long start;
@ -87,11 +87,8 @@ public class NaivRepeatedMedianEstimator implements Algorithm {
medianY = FastElementSelector.randomizedSelect(yMedians, yMedians.size() * 0.5);
end = System.currentTimeMillis();
Logging.logInfo("Zeit: " + ((end - start) / 1000));
}
@Override
public void pepareResult() {
return new Line(getSlope(), getYInterception());
}
/**
@ -128,14 +125,14 @@ public class NaivRepeatedMedianEstimator implements Algorithm {
/**
* @return Steigung
*/
public double getM() {
public double getSlope() {
return medianX * -1;
}
/**
* @return y-Achsenabschnitt
*/
public double getB() {
public double getYInterception() {
return medianY * -1;
}
}

View File

@ -35,7 +35,7 @@ public class NaivTheilSenEstimator implements Algorithm {
@Override
public void run() {
public Line call() {
Logging.logInfo("=== S T A R T - naiv T S ===");
long start;
long end;
@ -68,24 +68,22 @@ public class NaivTheilSenEstimator implements Algorithm {
yInterception = median2 - slope * median1;
end = System.currentTimeMillis();
Logging.logInfo("Zeit: " + ((end - start) / 1000));
return new Line(getSlope(), getYInterception());
}
@Override
public void pepareResult() {
}
/**
* @return Steigung
*/
public double getM() {
public double getSlope() {
return slope * -1;
}
/**
* @return y-Achsenabschnitt
*/
public double getB() {
public double getYInterception() {
return yInterception * -1;
}
}

View File

@ -0,0 +1,80 @@
package de.wwwu.awolf.presenter.data;
import de.wwwu.awolf.model.Line;
import de.wwwu.awolf.presenter.AbstractPresenter;
import de.wwwu.awolf.presenter.data.generator.CircleDatasetGenerator;
import de.wwwu.awolf.presenter.data.generator.CloudDatasetGenerator;
import de.wwwu.awolf.presenter.data.generator.LineDatasetGenerator;
import de.wwwu.awolf.presenter.data.io.DataExporter;
import de.wwwu.awolf.presenter.data.io.DataImporter;
import de.wwwu.awolf.presenter.util.Logging;
import java.io.File;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorCompletionService;
public class DataProvider {
private final AbstractPresenter presenter;
public DataProvider(AbstractPresenter presenter) {
this.presenter = presenter;
}
public List<Line> getData(final File file) {
//Presenter soll die Klasse überwachen
ExecutorCompletionService<List<Line>> completionService = new ExecutorCompletionService<>(this.presenter.getExecutor());
completionService.submit(new DataImporter(file));
//wait until future is ready
try {
return completionService.take().get();
} catch (InterruptedException | ExecutionException e) {
Logging.logError("Interrupted while importing... ", e);
Thread.currentThread().interrupt();
return Collections.emptyList();
}
}
public List<Line> getData(final DataType type, final int dataSize) {
//Presenter soll die Klasse überwachen
ExecutorCompletionService<List<Line>> completionService = new ExecutorCompletionService<>(this.presenter.getExecutor());
switch (type) {
case CIRCLE:
completionService.submit(new CircleDatasetGenerator(dataSize));
break;
case LINE:
completionService.submit(new LineDatasetGenerator(dataSize));
break;
case CLOUD:
completionService.submit(new CloudDatasetGenerator(dataSize));
break;
default:
return Collections.emptyList();
}
try {
return completionService.take().get();
} catch (InterruptedException | ExecutionException e) {
Logging.logError("Interrupted while generating... ", e);
Thread.currentThread().interrupt();
return Collections.emptyList();
}
}
public void exportData(File file, List<Line> lines) {
this.presenter.getExecutor().submit(new DataExporter(lines, file));
}
public enum DataType {
CLOUD,
LINE,
CIRCLE
}
}

View File

@ -0,0 +1,65 @@
package de.wwwu.awolf.presenter.data.generator;
import de.wwwu.awolf.model.Line;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.Callable;
import static de.wwwu.awolf.presenter.data.generator.DatasetGenerator.generateDataLines;
/**
* Implementierung verschiedener Algorithmen zur Berechnung von Ausgleichsgeraden.
*
* @Author: Armin Wolf
* @Email: a_wolf28@uni-muenster.de
* @Date: 01.08.2017.
*/
public class CircleDatasetGenerator implements Callable<List<Line>> {
private final int size;
public CircleDatasetGenerator(int size) {
this.size = size;
}
/**
* Generiert einen Datensatz des typen: Gerade mit zirkulärer Störung. Zuerst wird die
* zirkuläre Störung zu der Liste der (dualen-)Geraden hinzugefügt danach wird die wrapper Methode
* <code>generateDataLines()</code> aufgerufen.
*
* @return Liste der Geraden
*/
@Override
public List<Line> call() throws Exception {
List<Line> lines = new LinkedList<>();
double from = 0;
double to = Math.PI * 5;
//obere Grenze für die neuen Punkte
int n = size / 2 + lines.size();
//calculate the distance between every two points
double distance = (to - from) / ((double) n);
//create points
double currentDistance = from;
//an die aktuelle Liste dranhängen
for (int i = lines.size(); i < n; i++) {
double x = Math.cos(currentDistance);
double y = Math.sin(currentDistance);
Line line = new Line(x, y);
line.setId(i + "");
lines.add(line);
//distance for the next iteration
currentDistance += distance;
}
int generateSize = (int) (size * 0.5);
return generateDataLines(lines, generateSize);
}
}

View File

@ -0,0 +1,55 @@
package de.wwwu.awolf.presenter.data.generator;
import de.wwwu.awolf.model.Line;
import java.security.SecureRandom;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.Callable;
/**
* Implementierung verschiedener Algorithmen zur Berechnung von Ausgleichsgeraden.
*
* @Author: Armin Wolf
* @Email: a_wolf28@uni-muenster.de
* @Date: 01.08.2017.
*/
public class CloudDatasetGenerator implements Callable<List<Line>> {
private final int size;
public CloudDatasetGenerator(int size) {
this.size = size;
}
/**
* Generiert zu einer gegebenen Größe einen Datensatz des typen: Punktwolke
*
* @return Liste der Geraden
*/
public List<Line> generateDataCloud() {
LinkedList<Line> lines = new LinkedList<>();
SecureRandom random = new SecureRandom();
double m = 1 + random.nextDouble();
double b = random.nextDouble();
for (int i = 1; i < (size + 1); i++) {
double y = (random.nextGaussian() * 100) % 100;
double signal = m * i + b;
signal *= -1;
Line line = new Line(i, signal - y);
line.setId(i - 1 + "");
lines.add(line);
}
return lines;
}
@Override
public List<Line> call() throws Exception {
return generateDataCloud();
}
}

View File

@ -0,0 +1,68 @@
package de.wwwu.awolf.presenter.data.generator;
import de.wwwu.awolf.model.Line;
import java.security.SecureRandom;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* Implementierung verschiedener Algorithmen zur Berechnung von Ausgleichsgeraden.
*
* @Author: Armin Wolf
* @Email: a_wolf28@uni-muenster.de
* @Date: 01.08.2017.
*/
public class DatasetGenerator {
private static SecureRandom random;
/**
* Konstruktor
*/
private DatasetGenerator() {
random = new SecureRandom();
}
/**
* Generieren eines Datensatzes des typen: Gerade. Die Geraden werden in eine
* übergebene Liste hinzugefügt.
*
* @param n Größe des Datensatzes
* @return Liste des Geraden
*/
public static List<Line> generateDataLines(List<Line> lines, int n) {
double m = 5d;
double b = 0d;
int size = 0;
Map<Double, Double> points = new HashMap<>();
//speichere die Koordinaten in einer HashMap, damit keine Punkte
//entstehen deren x-Koordinate zu sehr beieinander liegt.
while (size < n) {
double y = random.nextGaussian();
double signal = m * y + b;
signal *= -1;
if (!points.containsKey(y)) {
points.put(y, signal);
size++;
}
}
int idx = lines.size();
for (Double d : points.keySet()) {
Line line = new Line(d, points.get(d));
line.setId(idx + "");
lines.add(line);
idx++;
}
return lines;
}
}

View File

@ -0,0 +1,36 @@
package de.wwwu.awolf.presenter.data.generator;
import de.wwwu.awolf.model.Line;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
/**
* Implementierung verschiedener Algorithmen zur Berechnung von Ausgleichsgeraden.
*
* @Author: Armin Wolf
* @Email: a_wolf28@uni-muenster.de
* @Date: 01.08.2017.
*/
public class LineDatasetGenerator implements Callable<List<Line>> {
private final int size;
public LineDatasetGenerator(int size) {
this.size = size;
}
/**
* Wrapper Methode zum generieren eines Datensatzes des typen: Gerade
*
* @return Liste des Geraden
*/
@Override
public List<Line> call() throws Exception {
return DatasetGenerator.generateDataLines(new ArrayList<>(), size);
}
}

View File

@ -1,17 +1,14 @@
package de.wwwu.awolf.presenter.io;
package de.wwwu.awolf.presenter.data.io;
import com.opencsv.CSVWriter;
import de.wwwu.awolf.model.Line;
import de.wwwu.awolf.model.communication.Data;
import de.wwwu.awolf.model.communication.ExportData;
import de.wwwu.awolf.model.communication.SubscriberType;
import de.wwwu.awolf.presenter.util.Logging;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.List;
import java.util.concurrent.Flow;
/**
* Implementierung verschiedener Algorithmen zur Berechnung von Ausgleichsgeraden.
@ -20,11 +17,10 @@ import java.util.concurrent.Flow;
* @Email: a_wolf28@uni-muenster.de
* @Date: 03.08.2017.
*/
public class DataExporter implements Flow.Publisher<Data> {
public class DataExporter implements Runnable {
private List<Line> lines;
private File file;
private Flow.Subscriber<? super Data> subscriber;
/**
* Konstruktor
@ -32,10 +28,9 @@ public class DataExporter implements Flow.Publisher<Data> {
* @param lines Liste der Geraden
* @param file Datei in die, die Informationen exportiert werden sollen
*/
public DataExporter(List<Line> lines, File file, Flow.Subscriber<Data> subscriber) {
public DataExporter(List<Line> lines, File file) {
this.file = file;
this.lines = lines;
subscribe(subscriber);
}
/**
@ -43,7 +38,8 @@ public class DataExporter implements Flow.Publisher<Data> {
* Der Aufbau der Datei ist: id, m, b. Wenn der Export beendet wurde wird die Beobachter-Klasse informiert.
* In diesem Fall ist dies die Presenter Klasse.
*/
public void export() {
@Override
public void run() {
CSVWriter writer = null;
try {
@ -57,20 +53,11 @@ public class DataExporter implements Flow.Publisher<Data> {
writer.writeNext(entries);
}
writer.close();
String[] ret = {"export", "Das aktuelle Modell wurde erfolgreich unter: " + file.getAbsolutePath() + " gespeichert."};
ExportData data = new ExportData();
data.setType(SubscriberType.EXPORT);
data.setMessage("Das aktuelle Modell wurde erfolgreich unter: " + file.getAbsolutePath() + " gespeichert.");
this.subscriber.onNext(data);
} catch (IOException e) {
Logging.logError(e.getMessage(), e);
}
}
@Override
public void subscribe(Flow.Subscriber<? super Data> subscriber) {
this.subscriber = subscriber;
Logging.logInfo("The model has been successfully saved under: " + file.getAbsolutePath() + ".");
}
}

View File

@ -1,10 +1,7 @@
package de.wwwu.awolf.presenter.io;
package de.wwwu.awolf.presenter.data.io;
import com.opencsv.CSVReader;
import de.wwwu.awolf.model.Line;
import de.wwwu.awolf.model.communication.Data;
import de.wwwu.awolf.model.communication.ImportData;
import de.wwwu.awolf.model.communication.SubscriberType;
import de.wwwu.awolf.presenter.util.Logging;
import javax.swing.*;
@ -14,7 +11,7 @@ import java.io.FileReader;
import java.io.IOException;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.Flow;
import java.util.concurrent.Callable;
/**
@ -24,18 +21,16 @@ import java.util.concurrent.Flow;
* @Email: a_wolf28@uni-muenster.de
* @Date: 21.06.2017.
*/
public class DataImporter implements Flow.Publisher<Data> {
public class DataImporter implements Callable<List<Line>> {
private CSVReader reader;
private Flow.Subscriber<? super Data> subscriber;
/**
* Konstruktor
*
* @param file Datei aus der die Informationen imortiert werden sollen.
*/
public DataImporter(File file, Flow.Subscriber<? super Data> subscriber) {
subscribe(subscriber);
public DataImporter(File file) {
try {
this.reader = new CSVReader(new FileReader(file));
@ -51,7 +46,8 @@ public class DataImporter implements Flow.Publisher<Data> {
*
* @return Liste der Geraden
*/
public List<Line> run() {
@Override
public List<Line> call() throws Exception {
List<Line> list = new LinkedList<>();
try {
List<String[]> lines = reader.readAll();
@ -69,9 +65,6 @@ public class DataImporter implements Flow.Publisher<Data> {
counter++;
result[2] = counter + "";
Thread.sleep(10);
communicate(counter, lines.size());
} else if (nextLine.length == 2) {
double x = Double.parseDouble(nextLine[1]);
double y = Double.parseDouble(nextLine[2]) * (-1);
@ -84,8 +77,6 @@ public class DataImporter implements Flow.Publisher<Data> {
counter++;
result[2] = counter + "";
Thread.sleep(10);
communicate(counter, lines.size());
} else {
JOptionPane.showMessageDialog(null, "Diese Datei kann nicht importiert werden." +
"Es müssen mindestens zwei Spalten enthalten sein (x,y).", "Fehler bei der Eingabe", JOptionPane.ERROR_MESSAGE);
@ -101,18 +92,4 @@ public class DataImporter implements Flow.Publisher<Data> {
}
return list;
}
private void communicate(int counter, int size) {
// communication
ImportData data = new ImportData();
data.setType(SubscriberType.IMPORT);
data.setCurrent(counter);
data.setNumberOfLines(size);
this.subscriber.onNext(data);
}
@Override
public void subscribe(Flow.Subscriber<? super Data> subscriber) {
this.subscriber = subscriber;
}
}

View File

@ -0,0 +1,70 @@
package de.wwwu.awolf.presenter.evaluation;
import de.wwwu.awolf.model.Line;
import de.wwwu.awolf.model.Point;
import de.wwwu.awolf.model.evaluation.ComparisonResult;
import de.wwwu.awolf.presenter.algorithms.Algorithm;
import de.wwwu.awolf.presenter.algorithms.advanced.LeastMedianOfSquaresEstimator;
import de.wwwu.awolf.presenter.algorithms.advanced.RepeatedMedianEstimator;
import de.wwwu.awolf.presenter.algorithms.advanced.TheilSenEstimator;
import de.wwwu.awolf.presenter.algorithms.naiv.NaivLeastMedianOfSquaresEstimator;
import de.wwwu.awolf.presenter.algorithms.naiv.NaivRepeatedMedianEstimator;
import de.wwwu.awolf.presenter.algorithms.naiv.NaivTheilSenEstimator;
import de.wwwu.awolf.presenter.util.Logging;
import java.util.EnumMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.*;
public class AlgorithmComparison {
private final List<Algorithm.Type> types;
private final ExecutorService executorService;
private final Map<Algorithm.Type, Algorithm> algorithmMap;
private final CompletionService<Line> completionService;
public AlgorithmComparison(List<Algorithm.Type> types, List<Line> lines, List<Point> nodes) {
this.types = types;
this.executorService = Executors.newFixedThreadPool(3);
completionService = new ExecutorCompletionService<>(this.executorService);
algorithmMap = new EnumMap<>(Algorithm.Type.class);
algorithmMap.put(Algorithm.Type.LMS, new LeastMedianOfSquaresEstimator(lines, nodes));
algorithmMap.put(Algorithm.Type.RM, new RepeatedMedianEstimator(lines));
algorithmMap.put(Algorithm.Type.TS, new TheilSenEstimator(lines, nodes));
algorithmMap.put(Algorithm.Type.NAIV_LMS, new NaivLeastMedianOfSquaresEstimator(lines));
algorithmMap.put(Algorithm.Type.NAIV_RM, new NaivRepeatedMedianEstimator(lines));
algorithmMap.put(Algorithm.Type.NAIV_TS, new NaivTheilSenEstimator(lines));
}
public ComparisonResult compare() {
ComparisonResult comparisonResult = new ComparisonResult();
getTypes().forEach(tye -> {
completionService.submit(algorithmMap.get(tye));
});
for (Algorithm.Type value : getTypes()) {
Algorithm.Type type;
synchronized (types) {
type = value;
}
try {
Line line = completionService.take().get();
comparisonResult.put(type, line);
} catch (InterruptedException interupted) {
Logging.logError("Error while waiting for the Line result. Type: " + type, interupted);
Thread.currentThread().interrupt();
} catch (ExecutionException e) {
Logging.logError("Execution failed. Type: " + type, e);
}
}
return comparisonResult;
}
private List<Algorithm.Type> getTypes() {
return types;
}
}

View File

@ -2,27 +2,22 @@ package de.wwwu.awolf.presenter.evaluation;
import de.wwwu.awolf.model.Line;
import de.wwwu.awolf.model.LineModel;
import de.wwwu.awolf.model.Point;
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.algorithms.advanced.LeastMedianOfSquaresEstimator;
import de.wwwu.awolf.presenter.algorithms.advanced.RepeatedMedianEstimator;
import de.wwwu.awolf.presenter.algorithms.advanced.TheilSenEstimator;
import de.wwwu.awolf.presenter.algorithms.naiv.NaivLeastMedianOfSquaresEstimator;
import de.wwwu.awolf.presenter.algorithms.naiv.NaivRepeatedMedianEstimator;
import de.wwwu.awolf.presenter.algorithms.naiv.NaivTheilSenEstimator;
import de.wwwu.awolf.presenter.generator.DatasetGenerator;
import de.wwwu.awolf.presenter.io.DataImporter;
import de.wwwu.awolf.presenter.data.DataProvider;
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.IntersectionComputer;
import de.wwwu.awolf.presenter.util.Logging;
import java.io.File;
import java.util.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Flow;
/**
@ -32,30 +27,17 @@ import java.util.concurrent.Flow;
* @Email: a_wolf28@uni-muenster.de
* @Date: 01.08.2017.
*/
public class EvaluateAlgorithms implements Flow.Publisher<Data> {
public class EvaluateAlgorithms implements Runnable, Flow.Publisher<Data> {
private LineModel arrangement;
private List<Line> lmsL;
private List<Line> rmL;
private List<Line> tsL;
private List<Point> lmsP;
private List<Point> tsP;
private Thread lmsThread;
private Thread rmThread;
private Thread tsThread;
private DatasetGenerator generator;
private String[][] names = {{"MSE", "RMSE", "MAE", "MDAE", "Steigung", "y-Achsenabschnitt", "S-MSE", "S-RMSE", "S-MAE", "S-MDAE", "Brute-force Steigung", "Brute-force y-Achsenabschnitt"}, {"MAPE", "MDAPE", "RMSPE", "RMDSPE", "Steigung", "y-Achsenabschnitt"}};
//ü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
@ -71,34 +53,23 @@ public class EvaluateAlgorithms implements Flow.Publisher<Data> {
* 6 = lms, rm, ts,
* @param datasettyp typ der zu generierenden Datensatz
*/
public EvaluateAlgorithms(int type, int n, int alg, String datasettyp, Presenter presenter) {
public EvaluateAlgorithms(int type, int n, int alg, DataProvider.DataType datasettyp, Presenter presenter) {
subscribe(presenter);
this.arrangement = new LineModel();
generator = new DatasetGenerator(presenter);
switch (datasettyp) {
case "Punktwolke":
arrangement.setLines(generator.generateDataCloud(n));
break;
case "Gerade":
arrangement.setLines(generator.generateDataLines(n));
break;
case "Kreis und Gerade":
arrangement.setLines(generator.generateCircle(n));
break;
}
this.resultMapping = new EnumMap<>(Algorithm.Type.class);
List<Line> data = presenter.getDataProvider().getData(datasettyp, n);
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;
IntersectionComputer computer = new IntersectionComputer(arrangement.getLines());
arrangement.setNodes(computer.compute());
lmsL = new LinkedList<>(arrangement.getLines());
rmL = new LinkedList<>(arrangement.getLines());
tsL = new LinkedList<>(arrangement.getLines());
lmsP = new ArrayList<>(arrangement.getNodes());
tsP = new ArrayList<>(arrangement.getNodes());
}
/**
@ -114,225 +85,81 @@ public class EvaluateAlgorithms implements Flow.Publisher<Data> {
* 6 = lms, rm, ts,
* @param file Datei die importiert werden soll
*/
public EvaluateAlgorithms(int type, int alg, File file) {
this.arrangement = new LineModel();
DataImporter importer = new DataImporter(file, this.subscriber);
List<Line> importedLines = importer.run();
if (importedLines != null)
arrangement.setLines(importedLines);
public EvaluateAlgorithms(int type, int alg, File file, Presenter presenter) {
subscribe(presenter);
presenter.startImport(file);
this.arrangement = presenter.getModel();
this.resultMapping = new EnumMap<>(Algorithm.Type.class);
this.type = type;
this.alg = alg;
IntersectionComputer computer = new IntersectionComputer(arrangement.getLines());
arrangement.setNodes(computer.compute());
lmsL = new LinkedList<>(arrangement.getLines());
rmL = new LinkedList<>(arrangement.getLines());
tsL = new LinkedList<>(arrangement.getLines());
lmsP = new ArrayList<>(arrangement.getNodes());
tsP = new ArrayList<>(arrangement.getNodes());
}
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.unmodifiableList(arrangement.getLines()), Collections.unmodifiableList(arrangement.getNodes()));
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.unmodifiableList(arrangement.getLines()), Collections.unmodifiableList(arrangement.getNodes()));
ComparisonResult comparisonResult = comparison.compare();
Map<String, String> multipleResults = new HashMap<>();
types.forEach(type -> this.resultMapping.put(type, getPercentigeErrorBasedMeasure(arrangement.getLines(), comparisonResult, type)));
Logging.logInfo("finished with execution of the algorithms.");
return this.resultMapping;
}
/**
* Startet die Evaluation zu den passenden Typ. Bei beendigung wird der Beobachter informiert.
*
* @throws InterruptedException
*/
@Override
public void run() {
List<String> result;
List<List<String>> multipleResults = new ArrayList<>();
ExecutorService executorService = Executors.newCachedThreadPool();
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) {
final Line naivEstimator = new Line(0,0);
final Line advancedEstimator = new Line(0,0);
executorService.submit(() -> {
NaivLeastMedianOfSquaresEstimator l = new NaivLeastMedianOfSquaresEstimator(arrangement.getLines());
l.run();
naivEstimator.setM(l.getM());
naivEstimator.setB(l.getB());
});
executorService.submit(() -> {
LeastMedianOfSquaresEstimator lmsAlg = new LeastMedianOfSquaresEstimator(lmsL, lmsP);
lmsAlg.run();
lmsAlg.pepareResult();
advancedEstimator.setM(lmsAlg.getSlope());
advancedEstimator.setB(lmsAlg.getyInterception());
});
result = getScaleDependentMeasure(arrangement.getLines(), advancedEstimator.getM(), advancedEstimator.getB());
result.addAll(getScaledErrorBasedMeasure(arrangement.getLines(), advancedEstimator.getM(), advancedEstimator.getB(), naivEstimator.getM(), naivEstimator.getB()));
Double[] tmp = {advancedEstimator.getM(), advancedEstimator.getB(), naivEstimator.getM(), naivEstimator.getB()};
sendPlotLineResults(Arrays.asList(tmp), Algorithm.Type.LMS);
result = benchmarkSameEstimator(Algorithm.Type.LMS, Algorithm.Type.NAIV_LMS);
} else if (alg == 1) {
final double[] m = new double[1];
final double[] b = new double[1];
Thread t = new Thread(() -> {
NaivRepeatedMedianEstimator r = new NaivRepeatedMedianEstimator(arrangement.getLines());
r.run();
m[0] = r.getM();
b[0] = r.getB();
});
t.start();
try {
startRM();
} catch (InterruptedException e) {
Logging.logError(e.getMessage(), e);
Thread.currentThread().interrupt();
}
result = getScaleDependentMeasure(arrangement.getLines(), Double.valueOf(rmRes[0]), Double.valueOf(rmRes[1]));
result.addAll(getScaledErrorBasedMeasure(arrangement.getLines(), Double.valueOf(rmRes[0]), Double.valueOf(rmRes[1]), m[0], b[0]));
Double[] tmp = {Double.valueOf(rmRes[0]), Double.valueOf(rmRes[1]), m[0], b[0]};
sendPlotLineResults(Arrays.asList(tmp), Algorithm.Type.NAIV_RM);
result = benchmarkSameEstimator(Algorithm.Type.RM, Algorithm.Type.NAIV_RM);
} else {
final double[] m = new double[1];
final double[] b = new double[1];
Thread t = new Thread(() -> {
NaivTheilSenEstimator ts = new NaivTheilSenEstimator(arrangement.getLines());
ts.run();
m[0] = ts.getM();
b[0] = ts.getB();
});
t.start();
try {
startTS();
} catch (InterruptedException e) {
Logging.logError(e.getMessage(), e);
Thread.currentThread().interrupt();
}
result = getScaleDependentMeasure(arrangement.getLines(), Double.valueOf(tsRes[0]), Double.valueOf(tsRes[1]));
result.addAll(getScaledErrorBasedMeasure(arrangement.getLines(), Double.valueOf(tsRes[0]), Double.valueOf(tsRes[1]), m[0], b[0]));
Double[] tmp = { Double.valueOf(tsRes[0]), Double.valueOf(tsRes[1]), m[0], b[0]};
sendPlotLineResults(Arrays.asList(tmp), Algorithm.Type.NAIV_TS);
result = benchmarkSameEstimator(Algorithm.Type.TS, Algorithm.Type.NAIV_TS);
}
sendTableApproximationTypes();
sendTableApproximationData(result, alg);
break;
case 1:
List<List<String>> lineRes;
switch (alg) {
case 3:
try {
startLMS();
startRM();
} catch (InterruptedException e) {
Logging.logError(e.getMessage(), e);
Thread.currentThread().interrupt();
}
result = getPercentigeErrorBasedMeasure(arrangement.getLines(), lmsRes[0], lmsRes[1]);
multipleResults.add(result);
result = getPercentigeErrorBasedMeasure(arrangement.getLines(), rmRes[0], rmRes[1]);
multipleResults.add(result);
result = fillPseudoResults();
multipleResults.add(result);
lineRes = new ArrayList<>();
lineRes.add(Arrays.asList(lmsRes));
lineRes.add(Arrays.asList(rmRes));
sendPloteLineResults(lineRes, Arrays.asList(Algorithm.Type.LMS, Algorithm.Type.RM));
result = benchmarkDifferentEstimators(Arrays.asList(Algorithm.Type.LMS, Algorithm.Type.RM));
break;
case 4:
try {
startLMS();
startTS();
} catch (InterruptedException e) {
Logging.logError(e.getMessage(), e);
Thread.currentThread().interrupt();
}
result = getPercentigeErrorBasedMeasure(arrangement.getLines(), lmsRes[0], lmsRes[1]);
multipleResults.add(result);
result = fillPseudoResults();
multipleResults.add(result);
result = getPercentigeErrorBasedMeasure(arrangement.getLines(), tsRes[0], tsRes[1]);
multipleResults.add(result);
lineRes = new ArrayList<>();
lineRes.add(Arrays.asList(lmsRes));
lineRes.add(Arrays.asList(tsRes));
sendPloteLineResults(lineRes, Arrays.asList(Algorithm.Type.LMS, Algorithm.Type.TS));
result = benchmarkDifferentEstimators(Arrays.asList(Algorithm.Type.LMS, Algorithm.Type.TS));
break;
case 5:
try {
startRM();
startTS();
} catch (InterruptedException e) {
Logging.logError(e.getMessage(), e);
Thread.currentThread().interrupt();
}
result = fillPseudoResults();
multipleResults.add(result);
result = getPercentigeErrorBasedMeasure(arrangement.getLines(), rmRes[0], rmRes[1]);
multipleResults.add(result);
result = getPercentigeErrorBasedMeasure(arrangement.getLines(), tsRes[0], tsRes[1]);
multipleResults.add(result);
lineRes = new ArrayList<>();
lineRes.add(Arrays.asList(rmRes));
lineRes.add(Arrays.asList(tsRes));
sendPloteLineResults(lineRes, Arrays.asList(Algorithm.Type.RM, Algorithm.Type.TS));
result = benchmarkDifferentEstimators(Arrays.asList(Algorithm.Type.RM, Algorithm.Type.TS));
break;
case 6:
try {
startLMS();
startRM();
startTS();
} catch (InterruptedException e) {
Logging.logError(e.getMessage(), e);
Thread.currentThread().interrupt();
}
result = getPercentigeErrorBasedMeasure(arrangement.getLines(), lmsRes[0], lmsRes[1]);
multipleResults.add(result);
result = getPercentigeErrorBasedMeasure(arrangement.getLines(), rmRes[0], rmRes[1]);
multipleResults.add(result);
result = getPercentigeErrorBasedMeasure(arrangement.getLines(), tsRes[0], tsRes[1]);
multipleResults.add(result);
lineRes = new ArrayList<>();
lineRes.add(Arrays.asList(lmsRes));
lineRes.add(Arrays.asList(rmRes));
lineRes.add(Arrays.asList(tsRes));
sendPloteLineResults(lineRes, Arrays.asList(Algorithm.Type.LMS, Algorithm.Type.RM, Algorithm.Type.TS));
result = benchmarkDifferentEstimators(Arrays.asList(Algorithm.Type.LMS, Algorithm.Type.RM, Algorithm.Type.TS));
break;
}
sendTableApproximationData(multipleResults);
break;
}
}
/**
* Die berechneten Ergebnisse werden an den Beobachter übermittelt um dann visualisiert zu werden.
*
* @param result Ergebnisse
* @param col Spalte
*/
public void sendTableApproximationData(List<String> result, int col) {
List<String> tableInput = new ArrayList<>();
for (int i = 0; i < names[type].length; i++) {
tableInput.add(result.get(i));
}
tableInput.add("");
EvaluationData data = new EvaluationData();
data.setColumn(col);
data.setLabels(tableInput);
tableInput.clear();
sendTableApproximationData(result);
}
/**
@ -340,145 +167,38 @@ public class EvaluateAlgorithms implements Flow.Publisher<Data> {
*
* @param result Ergebnisse
*/
public void sendTableApproximationData(List<List<String>> result) {
List<String> tableInput = new ArrayList<>();
private void sendTableApproximationData(Map<Algorithm.Type, Map<String, String>> result) {
//TODO Hääää? xD
//iteration über die ApproximationsGüten -- Zeilen
for (int j = 0; j <= result.get(0).size(); j++) {
tableInput.add("eval-ds");
if (j != result.get(0).size()) {
tableInput.add(names[type][j]);
//iteration über die alg. -- Spalten
for (int i = 0; i < 3; i++) {
tableInput.add(result.get(i).get(j));
}
} else {
tableInput.add("");
tableInput.add("");
tableInput.add("");
tableInput.add("");
}
EvaluationData data = new EvaluationData();
data.setType(SubscriberType.EVAL_DS);
data.setMultipleColumnResult(result);
this.subscriber.onNext(data);
tableInput.clear();
}
}
/**
* Die Art der Ergebnisse (MSE, RMSE,...) wird an der Beobachter übermittelt.
*/
public void sendTableApproximationTypes() {
EvaluationData data = new EvaluationData();
data.setType(SubscriberType.EVAL_T);
data.setLabels(Arrays.asList(names[type]));
data.setType(SubscriberType.EVALUATION_TABLE_DATA);
data.setMultipleColumnResult(result);
data.setRowsPerColumn(result.keySet().size());
this.subscriber.onNext(data);
}
/**
* Zur visualisierung der berechneten Geraden wird die Steigung und der y-Achsenabschnitt an den
* Beobachter übermittelt.
*
* @param res Feld mit den Werten für die Steigung und dern y-Achsenabschnitt
* @param alg code für welchen Algorithmus sich die Werte beziehen
*/
public void sendPlotLineResults(List<Double> res, Algorithm.Type alg) {
EvaluationData data = new EvaluationData();
data.setType(SubscriberType.LINES_RES);
data.setAlgorithmtypes(Collections.singletonList(alg));
data.setOneColumnresult(res);
this.subscriber.onNext(data);
}
/**
* Zur visualisierung der berechneten Geraden wird die Steigung und der y-Achsenabschnitt an den
* Beobachter übermittelt.
*
* @param res Feld mit den Werten für die Steigung und dern y-Achsenabschnitt (alle)
* @param algs codes für welchen Algorithmus sich die Werte beziehen (alle)
*/
public void sendPloteLineResults(List<List<String>> res, List<Algorithm.Type> algs) {
EvaluationData data = new EvaluationData();
data.setType(SubscriberType.LINES_RES_MULT);
data.setAlgorithmtypes(algs);
data.setMultipleColumnResult(res);
this.subscriber.onNext(data);
}
/**
* Startet die Berechnung des Alg. zum LMS-Schätzer
*
* @throws InterruptedException
*/
public void startLMS() throws InterruptedException {
lmsThread = new Thread(() -> {
LeastMedianOfSquaresEstimator lmsAlg = new LeastMedianOfSquaresEstimator(lmsL, lmsP);
lmsAlg.run();
lmsAlg.pepareResult();
lmsRes[0] = lmsAlg.getSlope();
lmsRes[1] = lmsAlg.getyInterception();
});
lmsThread.start();
lmsThread.join();
}
/**
* Startet die Berechnung des Alg. zum RM-Schätzer
*
* @throws InterruptedException
*/
public void startRM() throws InterruptedException {
rmThread = new Thread(() -> {
RepeatedMedianEstimator rmAlg = new RepeatedMedianEstimator(rmL);
rmAlg.run();
rmAlg.pepareResult();
rmRes[0] = rmAlg.getSlope();
rmRes[1] = rmAlg.getyInterception();
});
rmThread.start();
rmThread.join();
}
/**
* Startet die Berechnung des Alg. zum TS-Schätzer
*
* @throws InterruptedException
*/
public void startTS() throws InterruptedException {
tsThread = new Thread(() -> {
TheilSenEstimator tsAlg = new TheilSenEstimator(tsL, tsP);
tsAlg.run();
tsAlg.pepareResult();
tsRes[0] = tsAlg.getSlope();
tsRes[1] = tsAlg.getyInterception();
});
tsThread.start();
tsThread.join();
}
/**
* Startet die Berechnung der skalierungsabbhängigen Maße.
*
* @param lines Liste der Geraden
* @param m Steigung
* @param b y-Achsenabschnitt
* @return Liste mit den Ergebnissen, bereit zum visualisieren
*/
public List<String> getScaleDependentMeasure(final List<Line> lines, final Double m, final Double b) {
private Map<String, String> getScaleDependentMeasure(final List<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);
List<String> ret = new ArrayList<>();
ret.add(scaleDependentMeasure.mse().toString());
ret.add(scaleDependentMeasure.rmse().toString());
ret.add(scaleDependentMeasure.mae().toString());
ret.add(scaleDependentMeasure.mdae().toString());
ret.add(m.toString());
ret.add(b.toString());
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;
}
@ -487,19 +207,22 @@ public class EvaluateAlgorithms implements Flow.Publisher<Data> {
* Startet die Berechnung der Maße die auf dem prozentualen Fehler basieren.
*
* @param lines Liste der Geraden
* @param m Steigung
* @param b y-Achsenabschnitt
* @return Liste mit den Ergebnissen, bereit zum visualisieren
*/
public List<String> getPercentigeErrorBasedMeasure(final List<Line> lines, final Double m, final Double b) {
private Map<String, String> getPercentigeErrorBasedMeasure(final List<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);
ArrayList<String> ret = new ArrayList<>();
ret.add(percentageErrorBasedMeasure.mape().toString());
ret.add(percentageErrorBasedMeasure.mdape().toString());
ret.add(percentageErrorBasedMeasure.rmspe().toString());
ret.add(percentageErrorBasedMeasure.rmdspe().toString());
ret.add(m.toString());
ret.add(b.toString());
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;
}
@ -507,36 +230,30 @@ public class EvaluateAlgorithms implements Flow.Publisher<Data> {
* Startet die Berechnung der skalierungsunabbhängigen Maße.
*
* @param lines Liste der Geraden
* @param m Steigung
* @param b y-Achsenabschnitt
* @return Liste mit den Ergebnissen, bereit zum visualisieren
*/
public List<String> getScaledErrorBasedMeasure(final List<Line> lines, final Double m, final Double b, final Double nM, final Double nB) {
ScaledErrorBasedMeasure scaledErrorBasedMeasure = new ScaledErrorBasedMeasure(lines, m, b, nM, nB);
List<String> ret = new ArrayList<>();
ret.add(scaledErrorBasedMeasure.mse().toString());
ret.add(scaledErrorBasedMeasure.rmse().toString());
ret.add(scaledErrorBasedMeasure.mae().toString());
ret.add(scaledErrorBasedMeasure.mdae().toString());
ret.add(nM.toString());
ret.add(nB.toString());
return ret;
}
private Map<String, String> getScaledErrorBasedMeasure(final List<Line> lines, final ComparisonResult comparisonResult, final Algorithm.Type advanced, final Algorithm.Type naiv) {
/**
* Damit es bei der Visualisierung trennende Zeilen gibt.
*
* @return
*/
private List<String> fillPseudoResults() {
List<String> result = new ArrayList<>();
result.add(" ");
result.add(" ");
result.add(" ");
result.add(" ");
result.add(" ");
result.add(" ");
return result;
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;
}
/**

View File

@ -1,4 +1,4 @@
package de.wwwu.awolf.presenter.evaluation;
package de.wwwu.awolf.presenter.evaluation.measures;
import de.wwwu.awolf.model.Line;
import de.wwwu.awolf.presenter.util.FastElementSelector;

View File

@ -1,4 +1,4 @@
package de.wwwu.awolf.presenter.evaluation;
package de.wwwu.awolf.presenter.evaluation.measures;
import de.wwwu.awolf.model.Line;
import de.wwwu.awolf.model.communication.Data;

View File

@ -1,4 +1,4 @@
package de.wwwu.awolf.presenter.evaluation;
package de.wwwu.awolf.presenter.evaluation.measures;
import de.wwwu.awolf.model.Line;
import de.wwwu.awolf.presenter.util.FastElementSelector;

View File

@ -1,4 +1,4 @@
package de.wwwu.awolf.presenter.evaluation;
package de.wwwu.awolf.presenter.evaluation.measures;
import de.wwwu.awolf.model.Line;
import de.wwwu.awolf.presenter.util.FastElementSelector;

View File

@ -1,175 +0,0 @@
package de.wwwu.awolf.presenter.generator;
import de.wwwu.awolf.model.Line;
import de.wwwu.awolf.model.communication.Data;
import de.wwwu.awolf.model.communication.GeneratorData;
import de.wwwu.awolf.model.communication.SubscriberType;
import de.wwwu.awolf.presenter.Presenter;
import java.security.SecureRandom;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
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 DatasetGenerator implements Flow.Publisher<Data> {
private Double m;
private Double b;
private SecureRandom random;
private Flow.Subscriber<? super Data> subscriber;
/**
* Konstruktor
*/
public DatasetGenerator(Presenter presenter) {
random = new SecureRandom();
this.subscribe(presenter);
}
/**
* Konstruktor
*/
public DatasetGenerator() {
random = new SecureRandom();
}
/**
* Generiert zu einer gegebenen Größe einen Datensatz des typen: Punktwolke
*
* @param size Größe des Datensatzes
* @return Liste der Geraden
*/
public LinkedList<Line> generateDataCloud(int size) {
LinkedList<Line> lines = new LinkedList<>();
m = 1 + random.nextDouble();
b = random.nextDouble();
for (int i = 1; i < (size + 1); i++) {
double y = (random.nextGaussian() * 100) % 100;
double signal = m * i + b;
signal *= -1;
Line line = new Line(i, signal - y);
line.setId(i - 1 + "");
lines.add(line);
}
communicate("Es wurden " + size + " Daten generiert mit den Parametern", m, b);
return lines;
}
/**
* Wrapper Methode zum generieren eines Datensatzes des typen: Gerade
*
* @param size Größe des Datensatzes
* @return Liste des Geraden
*/
public List<Line> generateDataLines(int size) {
List<Line> lines = new LinkedList<>();
return generateDataLines(lines, size);
}
/**
* Generieren eines Datensatzes des typen: Gerade. Die Geraden werden in eine
* übergebene Liste hinzugefügt.
*
* @param lines Liste der Geraden
* @param n Größe des Datensatzes
* @return Liste des Geraden
*/
private List<Line> generateDataLines(List<Line> lines, int n) {
m = 5d;
b = 0d;
int size = 0;
Map<Double, Double> points = new HashMap<>();
//speichere die Koordinaten in einer HashMap, damit keine Punkte
//entstehen deren x-Koordinate zu sehr beieinander liegt.
while (size < n) {
double y = random.nextGaussian();
double signal = m * y + b;
signal *= -1;
if (!points.containsKey(y)) {
points.put(y, signal);
size++;
}
}
int idx = lines.size();
for (Double d : points.keySet()) {
Line line = new Line(d, points.get(d));
line.setId(idx + "");
lines.add(line);
idx++;
}
communicate("Es wurden " + n + " Daten generiert mit den Parametern", m, b);
return lines;
}
/**
* Generiert einen Datensatz des typen: Gerade mit zirkulärer Störung. Zuerst wird die
* zirkuläre Störung zu der Liste der (dualen-)Geraden hinzugefügt danach wird die wrapper Methode
* <code>generateDataLines()</code> aufgerufen.
*
* @param size Größe des Datensatzes
* @return Liste der Geraden
*/
public List<Line> generateCircle(int size) {
List<Line> lines = new LinkedList<>();
double from = 0;
double to = Math.PI * 5;
//obere Grenze für die neuen Punkte
int n = size / 2 + lines.size();
//calculate the distance between every two points
double distance = (to - from) / ((double) n);
//create points
double currentDistance = from;
//an die aktuelle Liste dranhängen
for (int i = lines.size(); i < n; i++) {
double x = Math.cos(currentDistance);
double y = Math.sin(currentDistance);
Line line = new Line(x, y);
line.setId(i + "");
lines.add(line);
//distance for the next iteration
currentDistance += distance;
}
return generateDataLines(lines, size / 2);
}
@Override
public void subscribe(Flow.Subscriber<? super Data> subscriber) {
}
private void communicate(final String message, final double m, final double b) {
if (this.subscriber != null) {
GeneratorData data = new GeneratorData();
data.setType(SubscriberType.GENERATOR);
data.setMessage(message);
data.setM(m);
data.setB(b);
this.subscriber.onNext(data);
}
}
}

View File

@ -4,6 +4,7 @@ package de.wwwu.awolf.view;
import de.wwwu.awolf.model.Line;
import de.wwwu.awolf.presenter.AbstractPresenter;
import de.wwwu.awolf.presenter.Presenter;
import de.wwwu.awolf.presenter.algorithms.Algorithm;
import de.wwwu.awolf.presenter.util.Logging;
import de.wwwu.awolf.view.listener.*;
import de.wwwu.awolf.view.panels.DualityPanel;
@ -19,9 +20,10 @@ import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.*;
import java.io.IOException;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
/**
* Implementierung verschiedener Algorithmen zur Berechnung von Ausgleichsgeraden.
@ -244,21 +246,14 @@ public class MainFrame extends JFrame {
}
/**
* Fügt der Evaluations-Tabelle eine Spalte mit Daten hinzu
* Fügt der Evaluations-Tabelle eine Zeile mit Daten hinzu
*
* @param res Daten der Spalte
* @param col Spalte
* @param isApprCol <code>true</code>, falls es sich um die Überschirften der Approximationsgüten handelt
* @param tableEntries Data of the Table
*/
public void appendEvalResult(Object[] res, int col, boolean isApprCol) {
public void appendEvalResult(Map<Algorithm.Type, Map<String, String>> tableEntries) {
SwingUtilities.invokeLater(() -> {
Object[] tmp = Arrays.copyOfRange(res, 2, res.length);
if (isApprCol) {
evaluationPanel.setCurrentRow(tmp.length);
evaluationPanel.addColumn(tmp, col, true);
} else {
evaluationPanel.addColumn(tmp, col + 1, false);
}
evaluationPanel.addRow(tableEntries);
evaluationPanel.repaint();
evaluationPanel.revalidate();
});
@ -269,65 +264,8 @@ public class MainFrame extends JFrame {
*
* @param res Daten der Spalte
*/
public void appendEvalResult(Object[] res) {
SwingUtilities.invokeLater(() -> {
Object[] tmp = Arrays.copyOfRange(res, 1, res.length);
evaluationPanel.addRow(tmp);
evaluationPanel.repaint();
evaluationPanel.revalidate();
});
}
/**
* Visualisiert die Ausgleichsgerade zu gegebenen Algorithmen
*
* @param res Steigungen und y-Achsenabschnitte
* @param alg Kodierung der Alg.
*/
public void drawLineResult(Object[] res, int alg) {
SwingUtilities.invokeLater(() -> {
Object[] result = Arrays.copyOfRange(res, 2, res.length);
evaluationPanel.drawLines(result, alg);
evaluationPanel.repaint();
evaluationPanel.revalidate();
});
}
/**
* Visualisiert die Ausgleichsgerade zu einem gegebenen Algorithmus
*
* @param res Steigungen und y-Achsenabschnitte
*/
public void drawLineResults(Object[] res) {
SwingUtilities.invokeLater(() -> {
Object[] result = Arrays.copyOfRange(res, 1, res.length);
List<Double[]> algs = new ArrayList<>();
for (int i = 0; i < (result.length + 1) / 3; i++) {
String name = (String) result[(3 * i)];
String m = (String) result[(3 * i) + 1];
String b = (String) result[(3 * i) + 2];
Double[] tmp = {Double.parseDouble(name), Double.parseDouble(m), Double.parseDouble(b)};
algs.add(tmp);
}
evaluationPanel.drawLines(algs);
evaluationPanel.repaint();
evaluationPanel.revalidate();
});
}
/**
* Evaluations-Datensätze werden Visualisiert
*
* @param lines Liste der Geraden
*/
public void addEvalDataset(List<Line> lines) {
SwingUtilities.invokeLater(() -> {
evaluationPanel.setDualPoints(lines);
evaluationPanel.repaint();
evaluationPanel.revalidate();
});
public void appendEvalResults(Map<Algorithm.Type, Map<String, String>> res) {
appendEvalResult(res);
}

View File

@ -4,7 +4,6 @@ import de.wwwu.awolf.presenter.Presenter;
import de.wwwu.awolf.view.listener.ExportDataListener;
import de.wwwu.awolf.view.listener.GenerateDataListener;
import de.wwwu.awolf.view.listener.ImportDataListener;
import de.wwwu.awolf.view.listener.PictureImportListener;
import de.wwwu.awolf.view.panels.AboutPanel;
import javax.swing.*;
@ -31,7 +30,6 @@ public class MenuBar {
private JMenuItem generateItem;
private JMenuItem evaluateItem;
private JMenuItem aboutItem;
private JMenuItem importPicture;
/**
* Konstruktor
@ -48,7 +46,6 @@ public class MenuBar {
this.exitItem = new JMenuItem("Exit");
this.importItem = new JMenuItem("Import");
this.importPicture = new JMenuItem("Bildimport");
this.exportItem = new JMenuItem("Export");
this.generateItem = new JMenuItem("Generiere...");
this.aboutItem = new JMenuItem("Über das Programm");
@ -61,7 +58,6 @@ public class MenuBar {
fileMenu.add(exportItem);
toolsMenu.add(generateItem);
toolsMenu.add(importPicture);
toolsMenu.add(evaluateItem);
@ -95,7 +91,6 @@ public class MenuBar {
dialog.setVisible(true);
});
});
this.importPicture.addActionListener(new PictureImportListener((Presenter) view.getPresenter(), view));
}

View File

@ -1,6 +1,7 @@
package de.wwwu.awolf.view.listener;
import de.wwwu.awolf.presenter.Presenter;
import de.wwwu.awolf.presenter.data.DataProvider;
import javax.swing.*;
import java.awt.*;
@ -57,8 +58,8 @@ public class GenerateDataListener implements ActionListener {
dialog.add(aproveButton);
aproveButton.addActionListener(e1 -> {
int n = Integer.parseInt(textField.getText());
int type = datasetTypeComboBox.getSelectedIndex();
Thread t = new Thread(() -> presenter.generateDataset(n, type));
int index = datasetTypeComboBox.getSelectedIndex();
Thread t = new Thread(() -> presenter.generateDataset(n, DataProvider.DataType.values()[index]));
t.start();
dialog.dispose();
});

View File

@ -1,56 +0,0 @@
package de.wwwu.awolf.view.listener;
import de.wwwu.awolf.presenter.Presenter;
import javax.swing.*;
import javax.swing.filechooser.FileNameExtensionFilter;
import javax.swing.filechooser.FileSystemView;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
/**
* Implementierung verschiedener Algorithmen zur Berechnung von Ausgleichsgeraden.
*
* @Author: Armin Wolf
* @Email: a_wolf28@uni-muenster.de
* @Date: 17.09.2017.
*/
public class PictureImportListener implements ActionListener {
private Presenter presenter;
private Container component;
/**
* Konstruktor
*
* @param presenter Presenter
* @param component visuelle Elternkomponente
*/
public PictureImportListener(Presenter presenter, Container component) {
this.presenter = presenter;
this.component = component;
}
@Override
public void actionPerformed(ActionEvent e) {
SwingUtilities.invokeLater(() -> {
File file = null;
JFileChooser chooser = new JFileChooser(FileSystemView.getFileSystemView().getHomeDirectory());
chooser.setPreferredSize(new Dimension(800, 700));
chooser.setFileFilter(new FileNameExtensionFilter("Bilder", "tiff", "png", "jpg", "jpeg"));
chooser.setMultiSelectionEnabled(false);
chooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
if (chooser.showOpenDialog(component) == JFileChooser.APPROVE_OPTION) {
//Logging.logInfo ("Datei "+chooser.getSelectedFile()+ " ausgewählt.");
file = chooser.getSelectedFile();
final File input = file;
Thread t = new Thread(() -> presenter.startPictureDataImport(input));
t.start();
}
});
}
}

View File

@ -2,25 +2,23 @@ package de.wwwu.awolf.view.panels;
import de.wwwu.awolf.model.Line;
import de.wwwu.awolf.presenter.Presenter;
import de.wwwu.awolf.presenter.algorithms.Algorithm;
import de.wwwu.awolf.presenter.data.DataProvider;
import de.wwwu.awolf.presenter.util.Logging;
import de.wwwu.awolf.view.MainFrame;
import de.wwwu.awolf.view.custom.ButtonGroupAtLeastTwo;
import de.wwwu.awolf.view.custom.ColorColumnRenderer;
import javax.swing.*;
import javax.swing.border.TitledBorder;
import javax.swing.filechooser.FileNameExtensionFilter;
import javax.swing.filechooser.FileSystemView;
import javax.swing.plaf.FontUIResource;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.JTableHeader;
import javax.swing.table.TableColumn;
import java.awt.*;
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedList;
import java.io.Serializable;
import java.util.List;
import java.util.*;
/**
* Created by
@ -59,6 +57,7 @@ public class EvaluationPanel extends JPanel {
private int currentRowOfTypes;
private JPanel buttonPanel;
private PlotPanel plotPanel;
private Map<Algorithm.Type, Color> colorMap;
private String[] selections = {"Approximationsgüte", "Least Median of Squares", "Repeated-Median", "Theil-Sen"};
/**
@ -71,6 +70,13 @@ public class EvaluationPanel extends JPanel {
this.view = view;
this.setLayout(new BorderLayout());
this.currentRowOfTypes = 0;
this.colorMap = new HashMap<>();
this.colorMap.put(Algorithm.Type.LMS, Color.ORANGE);
this.colorMap.put(Algorithm.Type.RM, Color.RED);
this.colorMap.put(Algorithm.Type.TS, Color.MAGENTA);
this.colorMap.put(Algorithm.Type.NAIV_LMS, Color.BLUE);
this.colorMap.put(Algorithm.Type.NAIV_RM, Color.GREEN);
this.colorMap.put(Algorithm.Type.NAIV_TS, Color.CYAN);
init();
addListener();
@ -157,7 +163,6 @@ public class EvaluationPanel extends JPanel {
comp.setBorder(new TitledBorder("Konfiguration"));
//Tabelle
model.setColumnIdentifiers(selections);
table.setDragEnabled(true);
JScrollPane scrollPane = new JScrollPane(table);
scrollPane.setWheelScrollingEnabled(true);
@ -182,14 +187,6 @@ public class EvaluationPanel extends JPanel {
this.add(buttonPanel, BorderLayout.SOUTH);
TableColumn tm = table.getColumnModel().getColumn(0);
tm.setCellRenderer(new ColorColumnRenderer(Color.lightGray, Color.blue));
for (int i = 1; i < 4; i++) {
DefaultTableCellRenderer rightRenderer = new DefaultTableCellRenderer();
rightRenderer.setHorizontalAlignment(SwingConstants.RIGHT);
rightRenderer.setFont(new FontUIResource("Courier", Font.PLAIN, 12));
table.getColumnModel().getColumn(i).setCellRenderer(rightRenderer);
}
}
/**
@ -228,7 +225,7 @@ public class EvaluationPanel extends JPanel {
});
} else {
((Presenter) view.getPresenter()).startEvaluation(type, n, alg, datatyp);
((Presenter) view.getPresenter()).startEvaluation(type, n, alg, DataProvider.DataType.values()[datasetType.getSelectedIndex()]);
}
clearTable.setEnabled(true);
exportData.setEnabled(true);
@ -303,13 +300,14 @@ public class EvaluationPanel extends JPanel {
* @param col Spalte
* @param isLabel <code>true</code>, falls es sich um die Approximations Überschriften handelt
*/
public void addColumn(Object[] data, int col, boolean isLabel) {
public void addColumn(final List<? extends Serializable> data, final int col, final boolean isLabel) {
if (isLabel) {
addBlankRows(data.length);
addBlankRows(data.size());
}
for (int i = 0; i < data.length; i++) {
int row = currentRowOfTypes - data.length + i;
model.setValueAt(data[i], row, col);
for (int i = 0; i < data.size(); i++) {
int row = currentRowOfTypes - data.size() + i;
model.setValueAt(data.get(i), row, col);
}
this.repaint();
this.revalidate();
@ -318,55 +316,41 @@ public class EvaluationPanel extends JPanel {
/**
* Fügt der Tabelle eine Zeile hinzu
*
* @param data Daten der Zeile
* @param tableEntries Daten der Tabelle
*/
public void addRow(Object[] data) {
addBlankRows(1);
for (int i = 0; i < 4; i++) {
model.setValueAt(data[i], currentRowOfTypes, i);
}
public void addRow(Map<Algorithm.Type, Map<String, String>> tableEntries) {
currentRowOfTypes++;
this.repaint();
this.revalidate();
SwingUtilities.invokeLater(() -> {
Set<Algorithm.Type> types = tableEntries.keySet();
List<String> columnlabels = new ArrayList<>();
types.forEach(type -> {
columnlabels.add(" ");
});
model.setColumnIdentifiers(columnlabels.toArray());
tableEntries.entrySet().forEach(row -> {
model.addRow(row.getValue().keySet().toArray());
model.addRow(row.getValue().values().toArray());
});
this.repaint();
this.revalidate();
});
}
/**
* Visualisierung der Ausgleichsgeraden
*
* @param alg Steigung und y-Achsenabschnitt der Geraden, bestimmt durch die Schätzer
*/
public void drawLines(List<Double[]> alg) {
Paint[] color = {Color.ORANGE, Color.RED, Color.MAGENTA};
String[] name = {"LMS", "RM", "TS"};
for (Double[] o : alg) {
int i = o[0].intValue();
Double m = o[1];
Double b = o[2];
plotPanel.addLineToPlot(m, b, color[i], name[i]);
}
}
/**
* <p>
* Visualisierung der Ausgleichsgerade
*
* @param results Steigung und y-Achsenabschnitt der Gerade, bestimmt durch die Schätzer
* @param alg identifizierung des Alg.
* @param lines the lines
* @param alg identifizierung des Alg.
*/
public void drawLines(Object[] results, int alg) {
String[] castedResults = Arrays.copyOf(results, results.length, String[].class);
Paint[] color = {Color.ORANGE, Color.RED, Color.MAGENTA};
String[] name = {"LMS", "RM", "TS"};
String[] nName = {"Brute-force LMS", "Brute-force RM", "Brute-force TS"};
double m = Double.parseDouble(castedResults[0]);
double b = Double.parseDouble(castedResults[1]);
plotPanel.addLineToPlot(m, b, color[alg], name[alg]);
double nM = Double.parseDouble(castedResults[2]);
double nB = Double.parseDouble(castedResults[3]);
plotPanel.addLineToPlot(nM, nB, Color.BLACK, nName[alg]);
public void drawLines(final List<Line> lines, final Algorithm.Type alg) {
for (Line line : lines) {
plotPanel.addLineToPlot(line.getM(), line.getB(), colorMap.get(alg), alg.name());
}
}
/**