JavaDoc hinzugefügt. Es fehlt noch bei dem Package: naiv, comparators, advanced und view

This commit is contained in:
Armin Wolf 2017-10-15 12:45:47 +02:00
parent 16b0ad7bec
commit 5b177b36e3
24 changed files with 519 additions and 252 deletions

View File

@ -20,10 +20,14 @@ public abstract class AbstractPresenter implements Observer {
private LineModel model;
private MainFrame view;
private EvaluateAlgorithms eval;
/**
* Konstruktor
* @param model Modell
* @param view View
*/
public AbstractPresenter(LineModel model, MainFrame view) {
this.model = model;
this.view = view;
@ -32,90 +36,84 @@ public abstract class AbstractPresenter implements Observer {
@Override
public void update(Observable o, Object arg) {
String[] result = ((String[]) arg);
String observable = result[0];
if (result[0] == "eval-dataset-generated") {
SwingUtilities.invokeLater(() -> getView().addEvalDataset(getEval().getData()));
}
if (result[0] == "eval-d") {
SwingUtilities.invokeLater(() -> getView().appendEvalResult(result, Integer.parseInt(result[1]), false));
}
if (result[0] == "eval-ds") {
SwingUtilities.invokeLater(() -> getView().appendEvalResult(result));
}
if (result[0] == "eval-t") {
SwingUtilities.invokeLater(() -> getView().appendEvalResult(result, Integer.parseInt(result[1]), true));
}
if (result[0] == "lines-res") {
SwingUtilities.invokeLater(() -> getView().drawLineResult(result, Integer.parseInt(result[1])));
}
if (result[0] == "lines-res-mult") {
SwingUtilities.invokeLater(() -> getView().drawLineResults(result));
}
if (result[0] == "lms") {
SwingUtilities.invokeLater(() -> {
getView().visualizeLMS(Double.parseDouble(result[1]), Double.parseDouble(result[2]));
//getView().setLmsIsComplete(true);
getView().logHeading("Least Median of Squares");
getView().log("<b>m:</b> " + result[1]);
getView().log("<b>b:</b> " + result[2]);
getView().logSuccess("Berechnung wurde Erfolgreich durchgeführt <hr>");
});
}
if (result[0] == "rm") {
SwingUtilities.invokeLater(() -> {
getView().visualizeRM(Double.parseDouble(result[1]), Double.parseDouble(result[2]));
getView().logHeading("Repeated Median Estimator");
getView().log("<b>m:</b> " + result[1]);
getView().log("<b>b:</b> " + result[2]);
getView().logSuccess("Berechnung wurde Erfolgreich durchgeführt <hr>");
});
}
if (result[0] == "ts") {
SwingUtilities.invokeLater(() -> {
getView().visualizeTS(Double.parseDouble(result[1]), Double.parseDouble(result[2]));
getView().logHeading("Theil-Sen Estimator");
getView().log("<b>m:</b> " + result[1]);
getView().log("<b>b:</b> " + result[2]);
getView().logSuccess("Berechnung wurde Erfolgreich durchgeführt <hr>");
});
}
if (result[0] == "import") {
Double max = Double.parseDouble(result[1]);
Double current = Double.parseDouble(result[2]);
Integer progress = (int) (100 * (current / max));
//100% erreicht
SwingUtilities.invokeLater(() -> {
switch (observable){
case "eval-dataset-generated":
SwingUtilities.invokeLater(() -> getView().addEvalDataset(getEval().getData()));
break;
case "eval-d":
SwingUtilities.invokeLater(() -> getView().appendEvalResult(result, Integer.parseInt(result[1]), false));
break;
case "eval-ds":
SwingUtilities.invokeLater(() -> getView().appendEvalResult(result));
break;
case "eval-t":
SwingUtilities.invokeLater(() -> getView().appendEvalResult(result, Integer.parseInt(result[1]), true));
break;
case "lines-res":
SwingUtilities.invokeLater(() -> getView().drawLineResult(result, Integer.parseInt(result[1])));
break;
case "lines-res-mult":
SwingUtilities.invokeLater(() -> getView().drawLineResults(result));
break;
case "lms":
SwingUtilities.invokeLater(() -> {
getView().visualizeLMS(Double.parseDouble(result[1]), Double.parseDouble(result[2]));
//getView().setLmsIsComplete(true);
getView().logHeading("Least Median of Squares");
getView().log("<b>m:</b> " + result[1]);
getView().log("<b>b:</b> " + result[2]);
getView().logSuccess("Berechnung wurde Erfolgreich durchgeführt <hr>");
});
break;
case "rm":
SwingUtilities.invokeLater(() -> {
getView().visualizeRM(Double.parseDouble(result[1]), Double.parseDouble(result[2]));
getView().logHeading("Repeated Median Estimator");
getView().log("<b>m:</b> " + result[1]);
getView().log("<b>b:</b> " + result[2]);
getView().logSuccess("Berechnung wurde Erfolgreich durchgeführt <hr>");
});
break;
case "ts":
SwingUtilities.invokeLater(() -> {
getView().visualizeTS(Double.parseDouble(result[1]), Double.parseDouble(result[2]));
getView().logHeading("Theil-Sen Estimator");
getView().log("<b>m:</b> " + result[1]);
getView().log("<b>b:</b> " + result[2]);
getView().logSuccess("Berechnung wurde Erfolgreich durchgeführt <hr>");
});
break;
case "import":
Double max = Double.parseDouble(result[1]);
Double current = Double.parseDouble(result[2]);
Integer progress = (int) (100 * (current / max));
//100% erreicht
SwingUtilities.invokeLater(() -> {
getView().showImportProgress(progress);
});
}
if (result[0] == "export") {
SwingUtilities.invokeLater(() -> {
getView().logHeading("Export der Daten als CSV");
getView().logSuccess("Export war Erfolgreich");
getView().log(result[1] + "<hr>");
});
}
if (result[0] == "generator") {
SwingUtilities.invokeLater(() -> {
getView().logSuccess("Generierung war Erfolgreich");
getView().log(result[1] + "<hr>");
});
});
break;
case "export":
SwingUtilities.invokeLater(() -> {
getView().logHeading("Export der Daten als CSV");
getView().logSuccess("Export war Erfolgreich");
getView().log(result[1] + "<hr>");
});
break;
case "generator":
SwingUtilities.invokeLater(() -> {
getView().logSuccess("Generierung war Erfolgreich");
getView().log(result[1] + "<hr>");
});
break;
}
}
private void calculateIntersections() {
/**
* Startet das parallele Berechnen der Schnittpunkte der Geraden die im Modell enthalten sind.
*/
private void startIntersectionCalculation() {
try {
Thread thread = new Thread(() -> {
getModel().resetRanges();
@ -134,10 +132,13 @@ public abstract class AbstractPresenter implements Observer {
}
}
/**
* Wrapper Methode die das berechnen der Schnittpunkte anstößt und die Ergebnisse(Anzahl der Schnittpunkte)
* visuell darstellt.
*/
protected void computeIntersections(){
System.out.println("Anzahl der Geraden: "+ getModel().getLines().size());
Thread t = new Thread(() -> {
calculateIntersections();
startIntersectionCalculation();
});
t.start();
try {
@ -145,7 +146,7 @@ public abstract class AbstractPresenter implements Observer {
} catch (InterruptedException e) {
e.printStackTrace();
}
//darstellung der Ergebnisse
SwingUtilities.invokeLater(() -> {
getView().enableFunctionality();
getView().getProgressDialog().dispose();
@ -156,27 +157,44 @@ public abstract class AbstractPresenter implements Observer {
});
}
/**
* @return das zu grunde legende Modell
*/
public LineModel getModel() {
return model;
}
/**
* @param model das zu grunde legende Modell
*/
public void setModel(LineModel model) {
this.model = model;
}
/**
* @return die zu grunde legende View
*/
public MainFrame getView() {
return view;
}
/**
* @param view die zu grunde legende View
*/
public void setView(MainFrame view) {
this.view = view;
}
/**
* @return Evaluation
*/
public EvaluateAlgorithms getEval() {
return eval;
}
/**
* @param eval Evaluation
*/
public void setEval(EvaluateAlgorithms eval) {
this.eval = eval;
}

View File

@ -1,5 +1,6 @@
package presenter;
import model.Line;
import model.LineModel;
import presenter.algorithms.advanced.LeastMedianOfSquaresEstimator;
import presenter.algorithms.advanced.RepeatedMedianEstimator;
@ -14,6 +15,7 @@ import view.MainFrame;
import javax.swing.table.DefaultTableModel;
import java.io.File;
import java.util.LinkedList;
/**
@ -36,6 +38,7 @@ public class Presenter extends AbstractPresenter {
private Thread generatorThread;
private Thread evalThread;
public Presenter(LineModel model, MainFrame view) {
super(model, view);
}
@ -57,14 +60,17 @@ public class Presenter extends AbstractPresenter {
if (input[0] != null && input[1] != null) {
if (lmsThread == null || !lmsThread.isAlive()) {
lmsThread = new Thread(() -> {
//Parameter für den Algortihmus
Double constant = Double.parseDouble(input[0]);
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
lms.addObserver(this);
lms.run();
lms.getResult();
lms.pepareResult();
});
lmsThread.start();
try {
@ -87,9 +93,10 @@ public class Presenter extends AbstractPresenter {
RepeatedMedianEstimator rm = new RepeatedMedianEstimator(getModel().getLines(), this);
Double parameter = Double.parseDouble(input);
rm.setBeta(parameter);
//Presenter soll die Klasse überwachen
rm.addObserver(this);
rm.run();
rm.getResult();
rm.pepareResult();
});
rmThread.start();
try {
@ -110,9 +117,10 @@ public class Presenter extends AbstractPresenter {
if (tsThread == null || !tsThread.isAlive()) {
tsThread = new Thread(() -> {
TheilSenEstimator ts = new TheilSenEstimator(getModel().getLines(), getModel().getNodes(), this);
//Presenter soll die Klasse überwachen
ts.addObserver(this);
ts.run();
ts.getResult();
ts.pepareResult();
});
tsThread.start();
try {
@ -136,9 +144,14 @@ public class Presenter extends AbstractPresenter {
if (importThread == null || !importThread.isAlive()) {
importThread = new Thread(() -> {
DataImporter importer = new DataImporter(file);
//Presenter soll die Klasse überwachen
importer.addObserver(this);
getModel().setLines(importer.run());
computeIntersections();
LinkedList<Line> importedLines = importer.run();
if (importedLines != null) {
//Berechnung der Schnittpunkte und vis. der Ergebnisse (anz. Geraden, anz. Schnittpunkte)
getModel().setLines(importedLines);
computeIntersections();
}
});
importThread.start();
try {
@ -157,8 +170,10 @@ public class Presenter extends AbstractPresenter {
if (importPictureThread == null || !importPictureThread.isAlive()) {
importPictureThread = new Thread(() -> {
PictureProcessor pictureProcessor = new PictureProcessor(this, file);
//Presenter soll die Klasse überwachen
pictureProcessor.addObserver(this);
pictureProcessor.run();
//Berechnung der Schnittpunkte und vis. der Ergebnisse (anz. Geraden, anz. Schnittpunkte)
computeIntersections();
});
importPictureThread.start();
@ -180,6 +195,7 @@ public class Presenter extends AbstractPresenter {
if (exportThread == null || !exportThread.isAlive()) {
exportThread = new Thread(() -> {
DataExporter exporter = new DataExporter(getModel().getLines(), file);
//Presenter soll die Klasse überwachen
exporter.addObserver(this);
exporter.export();
});
@ -200,6 +216,7 @@ public class Presenter extends AbstractPresenter {
if (exportThread == null || !exportThread.isAlive()) {
exportThread = new Thread(() -> {
DataExporter exporter = new DataExporter(getEval().getData(), file);
//Presenter soll die Klasse überwachen
exporter.addObserver(this);
exporter.export();
});
@ -270,11 +287,13 @@ public class Presenter extends AbstractPresenter {
}
/**
*
* @param typ
* @param n
* @param alg
* @param datasettyp
* Startet die Evaluation zu einen gegegbenen Typ mit den Informationen zu den Datensatz.
* Beispielsweise kann ein Alg. auf mit verschiedenen Datensätzen untersucht werden, oder mehrere Algorithmen
* auf einem gegebenen Datensatz.
* @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)
*/
public void startEvaluation(int typ, int n, int alg, String datasettyp) {
if (evalThread == null || !evalThread.isAlive()) {
@ -292,19 +311,23 @@ public class Presenter extends AbstractPresenter {
}
/**
*
* @param typ
* @param n
* @param alg
* @param file
* Startet die Evaluation zu einen gegegbenen Datensatz, der importiert wird.
* Beispielsweise kann ein Alg. auf mit verschiedenen Datensätzen untersucht werden, oder mehrere Algorithmen
* auf einem gegebenen Datensatz.
* @param typ Typ der Evaluation
* @param alg code für die auszuführenden Algorithmen (siehe <code>EvaluationPanel.checkSelection()</code> Method)
* @param file Typ des Datensatzes (Geradem Punktwolke, Kreis und Gerade)
*/
public void startEvaluation(int typ, int n, int alg, File file) {
public void startEvaluation(int typ, int alg, File file) {
if (evalThread == null || !evalThread.isAlive()) {
evalThread = new Thread(() -> {
try {
setEval(new EvaluateAlgorithms(typ, n, alg, file));
getEval().addObserver(this);
getEval().run();
EvaluateAlgorithms evaluateAlgorithms = new EvaluateAlgorithms(typ, alg, file);
if (evaluateAlgorithms.getData().size() > 0) {
setEval(evaluateAlgorithms);
getEval().addObserver(this);
getEval().run();
}
} catch (InterruptedException e) {
e.printStackTrace();
}

View File

@ -8,8 +8,13 @@ package presenter.algorithms;
* @Date: 28.05.2017.
*/
public interface Algorithm {
/**
* Startet die Berechnung des jeweiligen Algorithmus.
*/
void run();
void getResult();
/**
* Standardisierung der Lösung in Form (m,b), sodass die Geraden Visualisiert werden können.
*/
void pepareResult();
}

View File

@ -347,7 +347,7 @@ public class LeastMedianOfSquaresEstimator extends Observable implements Algorit
}
@Override
public void getResult() {
public void pepareResult() {
if (presenter != null) {
setChanged();
double m = (getSigmaMin().getX2() + getSigmaMin().getX1()) * 0.5;

View File

@ -282,7 +282,7 @@ public class RepeatedMedianEstimator extends Observable implements Algorithm {
}
@Override
public void getResult() {
public void pepareResult() {
if (presenter != null) {
setChanged();
double m = thetaLow;

View File

@ -191,7 +191,7 @@ public class TheilSenEstimator extends Observable implements Algorithm {
}
@Override
public void getResult() {
public void pepareResult() {
double m, x;
double b, y;

View File

@ -80,7 +80,7 @@ public class NaivLeastMedianOfSquaresEstimator implements Algorithm {
}
@Override
public void getResult() {
public void pepareResult() {
}

View File

@ -88,7 +88,7 @@ public class NaivRepeatedMedianEstimator implements Algorithm {
}
@Override
public void getResult() {
public void pepareResult() {
}

View File

@ -65,7 +65,7 @@ public class NaivTheilSenEstimator implements Algorithm {
}
@Override
public void getResult() {
public void pepareResult() {
}

View File

@ -8,7 +8,12 @@ package presenter.algorithms.util;
* @Date: 26.06.2017.
*/
public class BinomialCoeffizient {
/**
* Berechnet den Binomialkoeffizient zu der eingabe. Bin(n,k)
* @param n n
* @param k k
* @return Ergebnis
*/
public static Double run(int n, int k) {
int res = 1;

View File

@ -5,14 +5,19 @@ import java.util.List;
import java.util.Random;
/**
* Created by armin on 29.06.17.
* Implementierung verschiedener Algorithmen zur Berechnung von Ausgleichsgeraden.
*
* @Author: Armin Wolf
* @Email: a_wolf28@uni-muenster.de
* @Date: 29.06.2017.
*/
public class FastElementSelector {
/**
* @param a
* @param i
* @return
* Liefert das k-te Element aus der Eingabeliste zurück in Theta(n) Zeit.
* @param a Eingabeliste
* @param i Rang des gewünschten Elements
* @return das Element
*/
public static Double randomizedSelect(List<Double> a, double i) {
int start = 0;
@ -43,10 +48,12 @@ public class FastElementSelector {
}
/**
* @param a
* @param start
* @param end
* @return
* Hilfsmethode
*
* @param a Eingabeliste
* @param start Startindex
* @param end Index des letzten Elements
* @return Pivotelement
*/
private static int randomizedPartition(List<Double> a, int start, int end) {
int i = 0;
@ -64,10 +71,12 @@ public class FastElementSelector {
}
/**
* @param a
* @param start
* @param end
* @return
* Hilfsmethode
*
* @param a Eingabeliste
* @param start Startindex
* @param end Index des letzten Elements
* @return Pivotelement
*/
private static int partition(List<Double> a, int start, int end) {
Double x = a.get(end);

View File

@ -18,7 +18,7 @@ import java.util.TreeSet;
*/
public class IntersectionComputer {
private LinkedList<Line> lines;
private LinkedList<Line> lines;
private TreeSet<Point> intersections;
private Double xMinimum;
@ -28,6 +28,10 @@ public class IntersectionComputer {
private Thread[] worker;
/**
* Konstruktor
* @param lines Liste der Geraden
*/
public IntersectionComputer(LinkedList<Line> lines) {
this.lines = lines;
this.worker = new Thread[4];
@ -39,9 +43,17 @@ public class IntersectionComputer {
yMaximum = Double.MIN_VALUE;
}
/**
* Berechnet zu einer gegebenen Menge von dualen Geraden die Schnittpunkte. Dafür wird ein modifizierter Merge-Sort
* Algorithmus verwendett. Um die Performance zu steigern wird die Berechnung ab einer passenden Größe auf vier
* Threads ausgelagert.
* @param lower untere Schranke
* @param higher obere Schranke
* @return Liste der Schnittpunkte
*/
public ArrayList<Point> compute(final double lower, final double higher) {
if (lines.size() > 10) {
if (lines.size() > 16) {
worker[0] = new Thread(() -> {
work(lines.subList(0, (lines.size() / 4)),lower,higher);
});
@ -74,7 +86,12 @@ public class IntersectionComputer {
return new ArrayList<>(intersections);
}
/**
* Berechnet zu einer gegebenen Menge von dualen Geraden die Schnittpunkte. Dafür wird ein modifizierter Merge-Sort
* Algorithmus verwendett. Um die Performance zu steigern wird die Berechnung ab einer passenden Größe auf vier
* Threads ausgelagert.
* @return Liste der Schnittpunkte
*/
public ArrayList<Point> compute() {
return compute(-99999, 99999);
}
@ -93,14 +110,27 @@ public class IntersectionComputer {
}
/**
* Synchronisierter Zugriff auf die Liste der Geraden
* @return Liste der Geraden
*/
public synchronized LinkedList<Line> getLines() {
return lines;
}
/**
* Synchronisierter hinzufügen eines Schnittpunkts
* @param p Schnittpunkt
*/
public synchronized void addIntersection(Point p) {
this.intersections.add(p);
}
/**
* Synchronisiertes abfragen ob ein Schnittpunkt bereits gefunden wurde.
* @param p Schnittpunkt
* @return <code>true</code>, falls der Schnittpunkt p bereits gefunden wurde
*/
public synchronized boolean isFound(Point p) {
if (intersections.contains(p)) {
return true;
@ -109,6 +139,11 @@ public class IntersectionComputer {
}
}
/**
* Zu einem Punkt werden die minimalen, maximalen x- und y-Koordinaten überprüft und ggf.
* neu gesetzt
* @param point Schnittpunkt
*/
public void setRanges(Point point) {
xMaximum = (point.getX() > xMaximum) ? point.getX() : xMaximum;
xMinimum = (point.getX() < xMinimum) ? point.getX() : xMinimum;
@ -116,18 +151,34 @@ public class IntersectionComputer {
yMinimum = (point.getY() < yMinimum) ? point.getY() : yMinimum;
}
/**
* Synchronisierter Zugriff auf die minimale x-Koordiante
* @return minimale x-Koordiante
*/
public synchronized Double getxMinimum() {
return xMinimum;
}
/**
* Synchronisierter Zugriff auf die maximale x-Koordinate
* @return maximale x-Koordinate
*/
public synchronized Double getxMaximum() {
return xMaximum;
}
/**
* Synchronisierter Zugriff auf die minimale y-Koordinate
* @return minimale y-Koordinate
*/
public synchronized Double getyMinimum() {
return yMinimum;
}
/**
* Synchronisierter Zugriff auf die maximale y-Koordinate
* @return maximale y-Koordinate
*/
public synchronized Double getyMaximum() {
return yMaximum;
}

View File

@ -150,7 +150,6 @@ public class IntersectionCounter {
int index = start;
//hier beginnt das merging
//iteriere über die Teillisten
//Two-way Merge - Knuth Vol 3 The Art of Computer Programming -
while (left <= mid && right <= end) {
//wenn die linke Teilliste das kleinere Element besitzt kopiere
//das Element in das neue Array
@ -173,76 +172,6 @@ public class IntersectionCounter {
return invCount;
}
/**
* Diese Methode liefert nur nach dem Ausführen der <code>run</code> Funktion Sinnvolle Werte.
*
* @return Map mit Schnittpunkt Paaren.
*/
public HashMap<Line, ArrayList<Line>> getIntersectionLinePairs() {
ArrayList<Pair> result = new ArrayList<>();
HashMap<Line, ArrayList<Line>> ret = new HashMap<>();
for (int i = 0; i < inversions.size(); i++) {
result.add(new Pair(dictionaryBACK.get(inversions.get(i).getP1()),
dictionaryBACK.get(inversions.get(i).getP2())));
}
ArrayList<Line> linePairs;
for (Pair p : result) {
Line l1 = secondaryDictionaryBACK.get(p.getP1());
Line l2 = secondaryDictionaryBACK.get(p.getP2());
if (ret.get(l2) == null) {
linePairs = new ArrayList<>();
} else {
linePairs = ret.get(l2);
}
linePairs.add(l1);
ret.put(l2, linePairs);
//Symetrie
if (ret.get(l1) == null) {
linePairs = new ArrayList<>();
} else {
linePairs = ret.get(l1);
}
linePairs.add(l2);
ret.put(l1, linePairs);
}
/*System.out.println("----------------------------------------------------------");
for (Line outerLine : ret.keySet()){
System.out.println("Linie: "+outerLine);
for (Line innerLine : ret.get(outerLine)){
System.out.println("\t\t -> "+innerLine);
}
}
System.out.println("----------------------------------------------------------");*/
return ret;
}
/**
* Diese Methode liefert nur nach dem Ausführen der <code>run</code> Funktion Sinnvolle Werte.
*/
public void calculateIntersectionAbscissas(LineModel model) {
ArrayList<Pair> result = new ArrayList<>();
for (int i = 0; i < inversions.size(); i++) {
result.add(new Pair(dictionaryBACK.get(inversions.get(i).getP1()),
dictionaryBACK.get(inversions.get(i).getP2())));
}
for (Pair p : result) {
Line line = secondaryDictionaryBACK.get(p.getP1());
Line sampledLine = secondaryDictionaryBACK.get(p.getP2());
if (!line.equals(sampledLine)) {
double intersection = (line.getB() - sampledLine.getB()) / (sampledLine.getM() - line.getM());
double yintercept = sampledLine.getM() * intersection + sampledLine.getB();
model.addNode(new Point(intersection, yintercept));
}
}
}
/**
* Diese Methode liefert nur nach dem Ausführen der <code>run</code> Funktion Sinnvolle Werte.

View File

@ -45,14 +45,6 @@ public class RandomSampler {
public static ArrayList<Double> run(ArrayList<Point> set, Double r) {
ArrayList<Double> sampledLines = new ArrayList<>();
// Integer indexOfEnd = set.size()-1;
//
// for (int i = 0; i < r; i++) {
// sampledLines.add(set.get(ThreadLocalRandom.current().nextInt(0, indexOfEnd)).getX());
// }
// return sampledLines;
for (Point p : set){
sampledLines.add(p.getX());
}

View File

@ -1,6 +1,5 @@
package presenter.evaluation;
import model.Interval;
import model.Line;
import model.LineModel;
import model.Point;
@ -11,7 +10,6 @@ import presenter.algorithms.naiv.NaivLeastMedianOfSquaresEstimator;
import presenter.algorithms.naiv.NaivRepeatedMedianEstimator;
import presenter.algorithms.naiv.NaivTheilSenEstimator;
import presenter.algorithms.util.IntersectionComputer;
import presenter.algorithms.util.IntersectionCounter;
import presenter.generator.DatasetGenerator;
import presenter.io.DataImporter;
@ -67,6 +65,7 @@ public class EvaluateAlgorithms extends Observable {
* 4 = lms, ts,
* 5 = rm, ts,
* 6 = lms, rm, ts,
* @param datasettyp typ der zu generierenden Datensatz
*/
public EvaluateAlgorithms(int type, int n, int alg, String datasettyp) {
this.arrangement = new LineModel();
@ -101,15 +100,29 @@ public class EvaluateAlgorithms extends Observable {
tsP = new ArrayList<>(arrangement.getNodes());
}
public EvaluateAlgorithms(int type, int n, int alg, File file) {
/**
* 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 EvaluateAlgorithms(int type, int alg, File file) {
this.arrangement = new LineModel();
DataImporter importer = new DataImporter(file);
this.arrangement.setLines(importer.run());
LinkedList<Line> importedLines = importer.run();
if (importedLines != null)
arrangement.setLines(importedLines);
this.type = type;
this.iterations = n;
this.alg = alg;
//IntersectionCounter counter = new IntersectionCounter();
@ -128,6 +141,10 @@ public class EvaluateAlgorithms extends Observable {
tsP = new ArrayList<>(arrangement.getNodes());
}
/**
* Startet die Evaluation zu den passenden Typ. Bei beendigung wird der Beobachter informiert.
* @throws InterruptedException
*/
public void run() throws InterruptedException {
setChanged();
String[] msg = {"eval-dataset-generated"};
@ -268,6 +285,11 @@ public class EvaluateAlgorithms extends Observable {
}
/**
* Die berechneten Ergebnisse werden an den Beobachter übermittelt um dann visualisiert zu werden.
* @param result Ergebnisse
* @param col Spalte
*/
public void sendTableApproximationData(ArrayList<String> result, int col) {
ArrayList<String> tableInput = new ArrayList<>();
tableInput.add("eval-d");
@ -281,6 +303,10 @@ public class EvaluateAlgorithms extends Observable {
tableInput.clear();
}
/**
* Die berechneten Ergebnisse werden an den Beobachter übermittelt um dann visualisiert zu werden.
* @param result Ergebnisse
*/
public void sendTableApproximationData(ArrayList<ArrayList<String>> result) {
ArrayList<String> tableInput = new ArrayList<>();
@ -304,10 +330,11 @@ public class EvaluateAlgorithms extends Observable {
notifyObservers(tableInput.stream().toArray(String[]::new));
tableInput.clear();
}
}
/**
* Die Art der Ergebnisse (MSE, RMSE,...) wird an der Beobachter übermittelt.
*/
public void sendTableApproximationTypes() {
ArrayList<String> tableInput = new ArrayList<>();
tableInput.add("eval-t");
@ -321,6 +348,12 @@ public class EvaluateAlgorithms extends Observable {
tableInput.clear();
}
/**
* 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(Double[] res, int alg) {
//visualisiere m,b
@ -335,6 +368,12 @@ public class EvaluateAlgorithms extends Observable {
notifyObservers(lines.stream().toArray(String[]::new));
}
/**
* 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(ArrayList<Double[]> res, Integer[] algs) {
ArrayList<String> lines = new ArrayList<>();
lines.add("lines-res-mult");
@ -349,12 +388,15 @@ public class EvaluateAlgorithms extends Observable {
notifyObservers(lines.stream().toArray(String[]::new));
}
/**
* 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.getResult();
lmsAlg.pepareResult();
lmsRes[0] = lmsAlg.getSlope();
lmsRes[1] = lmsAlg.getyInterception();
});
@ -362,24 +404,31 @@ public class EvaluateAlgorithms extends Observable {
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.getResult();
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.getResult();
tsAlg.pepareResult();
tsRes[0] = tsAlg.getSlope();
tsRes[1] = tsAlg.getyInterception();
});
@ -387,7 +436,13 @@ public class EvaluateAlgorithms extends Observable {
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 ArrayList<String> getScaleDependentMeasure(final LinkedList<Line> lines, final Double m, final Double b) {
ScaleDependentMeasure scaleDependentMeasure = new ScaleDependentMeasure(lines, m, b);
ArrayList<String> ret = new ArrayList<>();
@ -401,6 +456,13 @@ public class EvaluateAlgorithms extends Observable {
return ret;
}
/**
* 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 ArrayList<String> getPercentigeErrorBasedMeasure(final LinkedList<Line> lines, final Double m, final Double b) {
PercentageErrorBasedMeasure percentageErrorBasedMeasure = new PercentageErrorBasedMeasure(lines, m, b);
ArrayList<String> ret = new ArrayList<>();
@ -413,6 +475,13 @@ public class EvaluateAlgorithms extends Observable {
return ret;
}
/**
* 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 ArrayList<String> getScaledErrorBasedMeasure(final LinkedList<Line> lines, final Double m, final Double b, final Double nM, final Double nB) {
ScaledErrorBasedMeasure scaledErrorBasedMeasure = new ScaledErrorBasedMeasure(lines, m, b, nM, nB);
ArrayList<String> ret = new ArrayList<>();
@ -425,6 +494,10 @@ public class EvaluateAlgorithms extends Observable {
return ret;
}
/**
* Damit es bei der Visualisierung trennende Zeilen gibt.
* @return
*/
private ArrayList<String> fillPseudoResults() {
ArrayList<String> result = new ArrayList<>();
result.add(" ");
@ -436,6 +509,9 @@ public class EvaluateAlgorithms extends Observable {
return result;
}
/**
* @return Liste der Geraden auf der die Berechnungen ausgeführt wurden
*/
public LinkedList<Line> getData() {
return arrangement.getLines();
}

View File

@ -18,17 +18,23 @@ public class PercentageErrorBasedMeasure {
private ArrayList<Double> percentageError;
/**
* Konstruktor
* @param lines Liste der Geraden
* @param m Steigung
* @param b y-Achenabschnitt
*/
public PercentageErrorBasedMeasure(final LinkedList<Line> lines, Double m, Double b) {
//Berechnung des Sampson-Fehlers
ArrayList<Double> sampson = new ArrayList<>();
for (Line line : lines) {
Double e = Math.pow(m * line.getM() - line.getB() + b, 2) / (Math.pow(m, 2) + 1);
sampson.add(e);
}
//Berechnung der prozentuelen-Fehlers
percentageError = new ArrayList<>();
for (int j = 0; j < sampson.size(); j++) {
percentageError.add(100 * sampson.get(j) / lines.get(j).getB());
}
@ -36,6 +42,11 @@ public class PercentageErrorBasedMeasure {
/* Percentege Error Approximation Measures */
//verschiedene Eingaben für einen Alg.
/**
* Mean Absolute Precentage Error
* @return Ergebnis
*/
public Double mape() {
double error = 0;
@ -48,6 +59,10 @@ public class PercentageErrorBasedMeasure {
return error;
}
/**
* Median Absolute Precentage Error:
* @return Ergebnis
*/
public Double mdape() {
ArrayList<Double> abs = new ArrayList<>();
@ -59,6 +74,10 @@ public class PercentageErrorBasedMeasure {
return FastElementSelector.randomizedSelect(abs, abs.size() * 0.5);
}
/**
* Root Mean Square Percentage Error
* @return Ergebnis
*/
public Double rmspe() {
double error = 0;
@ -71,6 +90,10 @@ public class PercentageErrorBasedMeasure {
return Math.sqrt(error);
}
/**
* Root Median Square Percentage Error
* @return Ergebnis
*/
public Double rmdspe() {
ArrayList squares = new ArrayList();
for (Double d : percentageError) {

View File

@ -30,11 +30,19 @@ public class PictureProcessor extends Observable {
private ArrayList<MatOfPoint> contours;
private double contourLength;
/**
* Konstruktor
* @param presenter Presenter
* @param file Bilddatei
*/
public PictureProcessor(Presenter presenter, File file) {
this.file = file;
this.presenter = presenter;
}
/**
* startet den Import des Bild und die Vorverarbeitung
*/
public void run() {
image = Imgcodecs.imread(file.getAbsolutePath());
contour = process(image);
@ -42,6 +50,11 @@ public class PictureProcessor extends Observable {
createInputData();
}
/**
* Vorverarbeitung des Eingabebilds. Dabei wird auf verschiedene OpenCV Methoden zurückgegriffen.
* @param image Eingabebild
* @return Matrix representation des Bilds
*/
private Mat process(Mat image) {
Mat threshold = new Mat(image.width(), image.height(), CvType.CV_8UC1);
Mat source = new Mat(image.width(), image.height(), CvType.CV_8UC1);
@ -78,7 +91,11 @@ public class PictureProcessor extends Observable {
return viscont;
}
/**
* Das Bild wird passend umgewandelt, um im nächsten Schritt visualisiert werden zu können.
* @param m Matrix representation des Bilds
* @return visualisierbares Bild
*/
private BufferedImage toBufferedImage(Mat m) {
int type = BufferedImage.TYPE_BYTE_GRAY;
if (m.channels() > 1) {
@ -94,6 +111,9 @@ public class PictureProcessor extends Observable {
}
/**
* Das gefilerte Bild ist bereit ins Modell aufgenommen zu werden um darauf dann die Algorithmen laufen zu lassen.
*/
private void createInputData() {
Thread t = new Thread(() -> {
double minArea = 50;

View File

@ -17,10 +17,17 @@ public class ScaleDependentMeasure {
private ArrayList<Double> errorValues;
/**
* Konstruktor
* @param lines Liste des Geraden
* @param m Steigung
* @param b y-Achsenabschnitt
*/
public ScaleDependentMeasure(final LinkedList<Line> lines, Double m, Double b) {
//Liste mit den Fehler zu jedem Punkt
errorValues = new ArrayList<>();
//Sampson-Fehler Berechnung
for (Line line : lines) {
Double e = Math.pow(m * line.getM() - line.getB() + b, 2) / (Math.pow(m, 2) + 1);
errorValues.add(e);
@ -29,6 +36,11 @@ public class ScaleDependentMeasure {
/* Skalierungs Abhängige Approximationsgüten */
//unterschiedliche Alg.- auf einem Datensatz
/**
* Mean Square Error:
* @return Ergebnis
*/
public Double mse() {
double error = 0;
@ -41,10 +53,18 @@ public class ScaleDependentMeasure {
return error;
}
/**
* Root Mean Square Error
* @return Ergebnis
*/
public Double rmse() {
return Math.sqrt(mse());
}
/**
* Mean Absolute Error
* @return Ergebnis
*/
public Double mae() {
double error = 0;
for (Double d : errorValues) {
@ -54,6 +74,10 @@ public class ScaleDependentMeasure {
return error;
}
/**
* Median Absolute Error
* @return Ergebnis
*/
public Double mdae() {
return FastElementSelector
.randomizedSelect(errorValues, errorValues.size() * 0.5);

View File

@ -20,32 +20,45 @@ public class ScaledErrorBasedMeasure {
private ArrayList<Double> naivSampsonError;
private ArrayList<Double> scaledError;
/**
* Konstruktor
* @param lines Liste der Geraden
* @param m Steigung
* @param b y-Achsenabschnitt
* @param naivSlope naive Steigung
* @param naivInterception naiver y-Achsenabschnitt
*/
public ScaledErrorBasedMeasure(final LinkedList<Line> lines, Double m, Double b, Double naivSlope, Double naivInterception) {
this.sampsonError = new ArrayList<>();
this.naivSampsonError = new ArrayList<>();
this.scaledError = new ArrayList<>();
//Sampson-Fehler der naiven Mehtode
for (Line line : lines) {
Double e = Math.pow(naivSlope * line.getM() - line.getB() + naivInterception, 2) / (Math.pow(naivSlope, 2) + 1);
naivSampsonError.add(e);
}
//Sampson-Fehler der fortgeschrittenen Methode
for (Line line : lines) {
Double e = Math.pow(m * line.getM() - line.getB() + b, 2) / (Math.pow(m, 2) + 1);
sampsonError.add(e);
}
//skalierungs-Fehler
for (int i = 0; i < sampsonError.size(); i++) {
scaledError.add(sampsonError.get(i) / naivSampsonError.get(i));
}
}
/* Skalierungs Abhängige Approximationsgüten */
//unterschiedliche Alg.- auf einem Datensatz
/**
* Mean Square Error
* @return Ergebnis
*/
public Double mse() {
double error = 0;
for (Double d : scaledError) {
@ -55,10 +68,18 @@ public class ScaledErrorBasedMeasure {
return error;
}
/**
* Root Mean Square Error
* @return Ergebnis
*/
public Double rmse() {
return Math.sqrt(mse());
}
/**
* Mean Absolute Error:
* @return Ergebnis
*/
public Double mae() {
double error = 0;
for (Double d : scaledError) {
@ -68,6 +89,10 @@ public class ScaledErrorBasedMeasure {
return error;
}
/**
* Median Absolute Error
* @return Ergebnis
*/
public Double mdae() {
return FastElementSelector
.randomizedSelect(scaledError, scaledError.size() * 0.5);

View File

@ -20,18 +20,29 @@ public class DatasetGenerator extends Observable {
private Double b;
private Random random;
/**
* Konstruktor
* @param m Steigung
* @param b y-Achsenabschnitt
*/
public DatasetGenerator(Double m, Double b) {
this.m = m;
this.b = b;
random = new Random();
random.setSeed(9999);
}
/**
* Konstruktor
*/
public DatasetGenerator() {
random = new Random();
}
/**
* 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();
@ -55,16 +66,27 @@ public class DatasetGenerator extends Observable {
return lines;
}
/**
* Wrapper Methode zum generieren eines Datensatzes des typen: Gerade
* @param size Größe des Datensatzes
* @return Liste des Geraden
*/
public LinkedList<Line> generateDataLines(int size) {
LinkedList<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 LinkedList<Line> generateDataLines(LinkedList<Line> lines, int n) {
m = 5d;
b = 0d;
int size = 0;
HashMap<Double, Double> points = new HashMap<>();
@ -95,7 +117,13 @@ public class DatasetGenerator extends Observable {
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 LinkedList<Line> generateCircle(int size) {
LinkedList<Line> lines = new LinkedList<>();
@ -114,7 +142,6 @@ public class DatasetGenerator extends Observable {
double x = Math.cos(currentDistance);
double y = Math.sin(currentDistance);
Line line = new Line(x, y);
line.setId(i + "");
lines.add(line);
@ -123,7 +150,6 @@ public class DatasetGenerator extends Observable {
currentDistance += distance;
}
return generateDataLines(lines, size / 2);
}

View File

@ -22,17 +22,26 @@ public class DataExporter extends Observable {
private LinkedList<Line> lines;
private File file;
/**
* Konstruktor
* @param lines Liste der Geraden
* @param file Datei in die, die Informationen exportiert werden sollen
*/
public DataExporter(LinkedList<Line> lines, File file) {
this.file = file;
this.lines = lines;
}
/**
* Diese Methode schreibt die Geraden der Form: y = mx + b, in eine Komma-Separierte Datei (CSV).
* 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() {
CSVWriter writer = null;
try {
writer = new CSVWriter(new FileWriter(file), ',');
// feed in your array (or convert your data to an array)
String[] entries = new String[3];
for (Line line : lines) {
entries[0] = line.getId();

View File

@ -5,6 +5,7 @@ import model.Line;
import model.LineModel;
import presenter.Presenter;
import javax.swing.*;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
@ -26,7 +27,10 @@ public class DataImporter extends Observable {
private File file;
private CSVReader reader;
/**
* Konstruktor
* @param file Datei aus der die Informationen imortiert werden sollen.
*/
public DataImporter(File file) {
//System.out.println(this.model.getLines().size()+ " die Anzahl der aktuellen Lines.");
this.file = file;
@ -38,8 +42,13 @@ public class DataImporter extends Observable {
}
}
/**
* Diese Methode importiert liest zeile für zeile die Daten aus der Datei und baut eine Liste von Geraden auf.
* Dabei wird auf die richtige Form geachtet. Falls die Datei nicht, mindestens zwei Spalten enthält wird ein Fehler
* signalisiert und der Import wird abgebrochen.
* @return Liste der Geraden
*/
public LinkedList<Line> run() {
LinkedList<Line> list = new LinkedList<>();
try {
List<String[]> lines = reader.readAll();
@ -47,23 +56,38 @@ public class DataImporter extends Observable {
String[] result = {"import", lines.size() + "", ""};
//System.out.println("+-------------------------------------------------------------------------------+");
for (String[] nextLine : lines) {
// nextLine[] is an array of values from the line
Double x = Double.parseDouble(nextLine[1]);
Double y = Double.parseDouble(nextLine[2]) * (-1);
Line line = new Line(x, y);
line.setId(counter + "");
if (!list.contains(line)) {
list.add(line);
if (nextLine.length == 3) {
Double x = Double.parseDouble(nextLine[1]);
Double y = Double.parseDouble(nextLine[2]) * (-1);
Line line = new Line(x, y);
line.setId(nextLine[0] + "");
if (!list.contains(line)) {
list.add(line);
}
setChanged();
counter++;
result[2] = counter + "";
Thread.sleep(10);
notifyObservers(result);
} else if (nextLine.length == 2){
Double x = Double.parseDouble(nextLine[1]);
Double y = Double.parseDouble(nextLine[2]) * (-1);
Line line = new Line(x, y);
line.setId(counter + "");
if (!list.contains(line)) {
list.add(line);
}
setChanged();
counter++;
result[2] = counter + "";
Thread.sleep(10);
notifyObservers(result);
} 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);
return null;
}
//System.out.format("|\t\t\t\t\t %-11d \t|\t\t\t\t\t %-11f \t|\t\t\t\t\t %-11f \t\t\t\t\t|\n", id,x,y);
setChanged();
counter++;
result[2] = counter + "";
Thread.sleep(10);
notifyObservers(result);
}
//System.out.println("+-------------------------------------------------------------------------------+");
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {

View File

@ -19,13 +19,18 @@ public class EvalResultLatexExport {
private DefaultTableModel model;
private File file;
/**
* Konstruktor
* @param model TableModel aus dem exportiert werden soll
* @param file Datei in die exportiert werden soll
*/
public EvalResultLatexExport(DefaultTableModel model, File file) {
this.model = model;
this.file = file;
}
/**
* e.g. Source: <url>https://en.wikibooks.org/wiki/LaTeX/Tables</url>
* Quelle: <url>https://en.wikibooks.org/wiki/LaTeX/Tables</url>
* \begin{tabular}{l*{3}{c}}
* Team & P & W & D & L & F & A & Pts \\\hline
* Manchester United & 6 & 4 & 0 & 2 & 10 & 5 & 12 \\
@ -68,6 +73,9 @@ public class EvalResultLatexExport {
return doc.toString();
}
/**
* das schreiben der Informationen über den Stream in die Datei
*/
public void writeFile() {
FileWriter fileWriter = null;
BufferedWriter bufferedWriter = null;

View File

@ -206,7 +206,7 @@ public class EvaluationPanel extends JPanel {
//System.out.println ("Datei "+chooser.getSelectedFile()+ " ausgewählt.");
file = chooser.getSelectedFile();
final File input = file;
Thread t = new Thread(() -> ((Presenter) view.getPresenter()).startEvaluation(type, n, alg, input));
Thread t = new Thread(() -> ((Presenter) view.getPresenter()).startEvaluation(type, alg, input));
t.start();
}
});