From 49fdc3e21c6f25380f8dc652faafbb415b8873c7 Mon Sep 17 00:00:00 2001 From: Armin Wolf Date: Tue, 1 Aug 2017 21:59:33 +0200 Subject: [PATCH] =?UTF-8?q?Generator=20-=20scaled=20based=20appr.=20g?= =?UTF-8?q?=C3=BCten?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/Model/Line.java | 20 +- .../YOrderLineComparatorBegin.java | 2 +- .../Comparators/YOrderLineComparatorEnd.java | 2 +- .../Algorithms/IntersectionCounter.java | 7 +- .../LeastMedianOfSquaresEstimator.java | 17 +- .../Algorithms/RepeatedMedianEstimator.java | 17 ++ .../Algorithms/TheilSenEstimator.java | 17 ++ .../Evaluation/EvaluateAlgorithms.java | 149 ++++++++++++++ src/main/java/Presenter/Presenter.java | 193 ++++++++---------- src/main/java/View/MainFrame.java | 4 +- 10 files changed, 301 insertions(+), 127 deletions(-) rename src/main/java/Presenter/{ => Algorithms}/Comparators/YOrderLineComparatorBegin.java (93%) rename src/main/java/Presenter/{ => Algorithms}/Comparators/YOrderLineComparatorEnd.java (93%) create mode 100644 src/main/java/Presenter/Evaluation/EvaluateAlgorithms.java diff --git a/src/main/java/Model/Line.java b/src/main/java/Model/Line.java index 893778b..df0db8e 100644 --- a/src/main/java/Model/Line.java +++ b/src/main/java/Model/Line.java @@ -9,6 +9,10 @@ package Model; */ public class Line { + private final Double MAX = 9999d; + private final Double MIN = -9999d; + + private double m; private double b; @@ -23,10 +27,10 @@ public class Line { this.m = m; this.b = b; - this.x1 = Double.MIN_VALUE; - this.y1 = (Double.MIN_VALUE * m) + b; - this.x2 = Double.MAX_VALUE * 0.5; - this.y2 = ((Double.MAX_VALUE * 0.5) * m) + b; + this.x1 = MIN; + this.y1 = (MIN * m) + b; + this.x2 = MAX * 0.5; + this.y2 = ((MAX * 0.5) * m) + b; this.id = id; } @@ -35,10 +39,10 @@ public class Line { this.m = m; this.b = b; - this.x1 = Double.MIN_VALUE; - this.y1 = (Double.MIN_VALUE * m) + b; - this.x2 = Double.MAX_VALUE * 0.5; - this.y2 = ((Double.MAX_VALUE * 0.5) * m) + b; + this.x1 = MIN; + this.y1 = (MIN * m) + b; + this.x2 = MAX * 0.5; + this.y2 = ((MAX * 0.5) * m) + b; } public Line(double x1, double x2, double y1, double y2) { diff --git a/src/main/java/Presenter/Comparators/YOrderLineComparatorBegin.java b/src/main/java/Presenter/Algorithms/Comparators/YOrderLineComparatorBegin.java similarity index 93% rename from src/main/java/Presenter/Comparators/YOrderLineComparatorBegin.java rename to src/main/java/Presenter/Algorithms/Comparators/YOrderLineComparatorBegin.java index 104d959..117899b 100644 --- a/src/main/java/Presenter/Comparators/YOrderLineComparatorBegin.java +++ b/src/main/java/Presenter/Algorithms/Comparators/YOrderLineComparatorBegin.java @@ -1,4 +1,4 @@ -package Presenter.Comparators; +package Presenter.Algorithms.Comparators; import Model.Line; import java.util.Comparator; diff --git a/src/main/java/Presenter/Comparators/YOrderLineComparatorEnd.java b/src/main/java/Presenter/Algorithms/Comparators/YOrderLineComparatorEnd.java similarity index 93% rename from src/main/java/Presenter/Comparators/YOrderLineComparatorEnd.java rename to src/main/java/Presenter/Algorithms/Comparators/YOrderLineComparatorEnd.java index e6f3ab7..e64a512 100644 --- a/src/main/java/Presenter/Comparators/YOrderLineComparatorEnd.java +++ b/src/main/java/Presenter/Algorithms/Comparators/YOrderLineComparatorEnd.java @@ -1,4 +1,4 @@ -package Presenter.Comparators; +package Presenter.Algorithms.Comparators; import Model.Line; import java.util.Comparator; diff --git a/src/main/java/Presenter/Algorithms/IntersectionCounter.java b/src/main/java/Presenter/Algorithms/IntersectionCounter.java index 5c3ecfd..4ca8852 100644 --- a/src/main/java/Presenter/Algorithms/IntersectionCounter.java +++ b/src/main/java/Presenter/Algorithms/IntersectionCounter.java @@ -1,9 +1,8 @@ package Presenter.Algorithms; import Model.*; -import Presenter.Comparators.YOrderLineComparatorBegin; -import Presenter.Comparators.YOrderLineComparatorEnd; -import Presenter.Presenter; +import Presenter.Algorithms.Comparators.YOrderLineComparatorBegin; +import Presenter.Algorithms.Comparators.YOrderLineComparatorEnd; import java.util.ArrayList; import java.util.Collections; @@ -226,8 +225,6 @@ public class IntersectionCounter { /** * Diese Methode liefert nur nach dem Ausführen der run Funktion Sinnvolle Werte. - * - * */ public void calculateIntersectionAbscissas(Arrangement model){ ArrayList result = new ArrayList<>(); diff --git a/src/main/java/Presenter/Algorithms/LeastMedianOfSquaresEstimator.java b/src/main/java/Presenter/Algorithms/LeastMedianOfSquaresEstimator.java index 9b04923..51ed030 100644 --- a/src/main/java/Presenter/Algorithms/LeastMedianOfSquaresEstimator.java +++ b/src/main/java/Presenter/Algorithms/LeastMedianOfSquaresEstimator.java @@ -37,7 +37,10 @@ public class LeastMedianOfSquaresEstimator extends Observable implements Algorit private Line sigmaMin; private double heightsigmaMin; private Double intersectionsPoint; - private Double constant; + private Double constant = 0.5; + + private Double slope; + private Double yInterception; public LeastMedianOfSquaresEstimator(LinkedList set, LinkedList intersections, Presenter presenter) { @@ -355,6 +358,10 @@ public class LeastMedianOfSquaresEstimator extends Observable implements Algorit setChanged(); double m = (getSigmaMin().getX2() + getSigmaMin().getX1()) * 0.5; double b = (getSigmaMin().getY2() + getSigmaMin().getY1()) * -0.5; + + slope = m; + yInterception = b; + String[] result = {"lms", m+"", b+""}; notifyObservers(result); } @@ -460,4 +467,12 @@ public class LeastMedianOfSquaresEstimator extends Observable implements Algorit public void setConstant(Double constant) { this.constant = constant; } + + public Double getSlope() { + return slope; + } + + public Double getyInterception() { + return yInterception; + } } diff --git a/src/main/java/Presenter/Algorithms/RepeatedMedianEstimator.java b/src/main/java/Presenter/Algorithms/RepeatedMedianEstimator.java index f47e6ce..071175b 100644 --- a/src/main/java/Presenter/Algorithms/RepeatedMedianEstimator.java +++ b/src/main/java/Presenter/Algorithms/RepeatedMedianEstimator.java @@ -44,6 +44,9 @@ public class RepeatedMedianEstimator extends Observable implements Algorithm { private Double thetaLow; private Double thetaHigh; + private Double slope; + private Double yInterception; + public RepeatedMedianEstimator(LinkedList set, Presenter presenter) { this.set = set; @@ -68,6 +71,10 @@ public class RepeatedMedianEstimator extends Observable implements Algorithm { linePairs = new HashMap<>(); } + public RepeatedMedianEstimator(LinkedList set) { + this(set,null); + } + /** * */ @@ -272,6 +279,8 @@ public class RepeatedMedianEstimator extends Observable implements Algorithm { (linesInCenterSlab.get(0).getM() * (thetaLow)) + linesInCenterSlab.get(0) .getB()); + slope = m; + yInterception = b; String[] result = new String[]{"rm", m+"", b+""}; notifyObservers(result); } @@ -432,6 +441,14 @@ public class RepeatedMedianEstimator extends Observable implements Algorithm { public void setThetaHigh(Double thetaHigh) { this.thetaHigh = thetaHigh; } + + public Double getSlope() { + return slope; + } + + public Double getyInterception() { + return yInterception; + } } diff --git a/src/main/java/Presenter/Algorithms/TheilSenEstimator.java b/src/main/java/Presenter/Algorithms/TheilSenEstimator.java index 407c5e7..17cb4f9 100644 --- a/src/main/java/Presenter/Algorithms/TheilSenEstimator.java +++ b/src/main/java/Presenter/Algorithms/TheilSenEstimator.java @@ -46,6 +46,9 @@ public class TheilSenEstimator extends Observable implements Algorithm { private Double aVariant; private Double bVariant; + private Double slope; + private Double yInterception; + public TheilSenEstimator(LinkedList setOfLines, LinkedList setOfIntersections, Presenter presenter) { this.presenter = presenter; @@ -68,6 +71,10 @@ public class TheilSenEstimator extends Observable implements Algorithm { } } + public TheilSenEstimator(LinkedList setOfLines, LinkedList setOfIntersections) { + this(setOfLines,setOfIntersections,null); + } + /** * Randomisierter Algorithmus zur Berechnung des Theil-Sen Schätzers. * Algorithmus stammt aus dem Paper: @@ -244,10 +251,20 @@ public class TheilSenEstimator extends Observable implements Algorithm { b = (x * m) - y; + slope = m; + yInterception = b; + String[] result = new String[]{"ts", m + "", b + ""}; notifyObservers(result); } } + public Double getSlope() { + return slope; + } + + public Double getyInterception() { + return yInterception; + } } diff --git a/src/main/java/Presenter/Evaluation/EvaluateAlgorithms.java b/src/main/java/Presenter/Evaluation/EvaluateAlgorithms.java new file mode 100644 index 0000000..505c216 --- /dev/null +++ b/src/main/java/Presenter/Evaluation/EvaluateAlgorithms.java @@ -0,0 +1,149 @@ +package Presenter.Evaluation; + +import Model.Arrangement; +import Model.Interval; +import Model.Line; +import Presenter.Algorithms.*; +import Presenter.Generator.DatasetGenerator; + +import java.util.ArrayList; +import java.util.LinkedList; +import java.util.List; + +/** + * Implementierung verschiedener Algorithmen zur Berechnung von Ausgleichsgeraden. + * + * @Author: Armin Wolf + * @Email: a_wolf28@uni-muenster.de + * @Date: 01.08.2017. + */ +public class EvaluateAlgorithms { + + private Arrangement arrangement; + private Double[] lmsResult; + private Double[] rmResult; + private Double[] tsResult; + + + public EvaluateAlgorithms(){ + this.arrangement = new Arrangement(); + } + + public static void main(String args[]){ + EvaluateAlgorithms e = new EvaluateAlgorithms(); + try { + e.run(); + } catch (InterruptedException e1) { + e1.printStackTrace(); + } + } + + public void run() throws InterruptedException { + + Thread thread = new Thread(() -> { + DatasetGenerator generator = new DatasetGenerator(); + arrangement.setLines(generator.generateDataset()); + + IntersectionCounter counter = new IntersectionCounter(); + counter.run(arrangement.getLines(), new Interval(-99999,99999)); + counter.calculateIntersectionAbscissas(arrangement); + }); + thread.start(); + thread.join(); + + + Thread lms = new Thread(() -> { + LeastMedianOfSquaresEstimator lmsAlg = new LeastMedianOfSquaresEstimator(arrangement.getLines() + ,arrangement.getNodes()); + lmsAlg.run(); + + List errors = sampsonError(arrangement.getLines(), lmsAlg.getSlope(), lmsAlg.getyInterception()); + lmsResult = getResults(errors); + }); + Thread rm = new Thread(() -> { + RepeatedMedianEstimator rmAlg = new RepeatedMedianEstimator(arrangement.getLines()); + rmAlg.run(); + List errors = sampsonError(arrangement.getLines(), rmAlg.getSlope(), rmAlg.getyInterception()); + rmResult = getResults(errors); + }); + Thread ts = new Thread(() -> { + TheilSenEstimator tsAlg = new TheilSenEstimator(arrangement.getLines(), arrangement.getNodes()); + tsAlg.run(); + + List errors = sampsonError(arrangement.getLines(), tsAlg.getSlope(), tsAlg.getyInterception()); + tsResult = getResults(errors); + }); + + lms.start(); + rm.start(); + ts.start(); + lms.join(); + rm.join(); + ts.join(); + + for (int i=0;i<4;i++){ + System.out.println("LMS: "+ lmsResult[i] + "\tTS: " + tsResult[i] + "\tRM: " + rmResult[i] + "\t"); + } + } + + + public Double[] getResults(List errorValues){ + + Double[] ret = new Double[4]; + ret[0] = mse(errorValues); + ret[1] = rmse(errorValues); + ret[2] = mae(errorValues); + ret[3] = mdae(errorValues); + + return ret; + + } + + /* Skalierungs Abhängige Approximationsgüten */ + public Double mse(List errorValues){ + double error = 0; + + for (Double d : errorValues){ + error += Math.pow(d,2); + } + + error /= errorValues.size(); + + return error; + } + + public Double rmse(List errorValues){ + return Math.sqrt(mse(errorValues)); + } + + public Double mae(List errorValues){ + double error = 0; + + for (Double d : errorValues){ + error += Math.abs(d); + } + + error /= errorValues.size(); + + return error; + } + + public Double mdae(List errorValues){ + return FastElementSelector.randomizedSelect((ArrayList) errorValues, errorValues.size()*0.5); + } + + + public List sampsonError(LinkedList lines, Double m, Double b){ + + //Liste mit den Fehler zu jedem Punkt + List sampsonrror = new ArrayList<>(); + + for (Line line : lines){ + Double error = Math.pow(m * line.getM() - line.getB() + b, 2) / (Math.pow(m,2) + 1); + sampsonrror.add(error); + } + + return sampsonrror; + } + +} diff --git a/src/main/java/Presenter/Presenter.java b/src/main/java/Presenter/Presenter.java index 61c2305..2aa2e5f 100644 --- a/src/main/java/Presenter/Presenter.java +++ b/src/main/java/Presenter/Presenter.java @@ -31,37 +31,16 @@ public class Presenter implements Observer { private Arrangement model; private MainFrame view; + /* Threads */ + private Thread tsThread; + private Thread rmThread; + private Thread lmsThread; + private Thread importThread; + private Thread generatorThread; + public Presenter(Arrangement model, MainFrame view) { this.model = model; this.view = view; - /* Double[] x = {1d, 2d, 3d, 4d, 10d, 12d, 18d}; - Double[] y = {9d, 15d, 19d, 20d, 45d, 55d, 78d}; - Double[] x = {18d, 24d, 30d, 34d, 38d}; - Double[] y = {18d, 26d, 30d, 40d, 70d}; - Double[] x = {1d,3d,4d,5d,8d}; - Double[] y = {4d,2d,1d,0d,0d}; - view.logHeading("Duale Darstellung der Punkte als Geraden:"); - for (int j = 0; j < x.length; j++) { - Line p = new Line(x[j], y[j]); - p.setId(j+""); - view.log("f(x) = " + p.getM() + "x + " + p.getB()); - this.model.addLine(p); - } - - calcArrangementNodes(); - //print - List heading = new LinkedList<>(); - List> rows = new LinkedList<>(); - heading.add("X - Koordinate"); - heading.add("Y - Koordinate"); - for (Point p : model.getNodes()) { - LinkedList rowEntry = new LinkedList<>(); - rowEntry.add(p.getX().toString()); - rowEntry.add(p.getY().toString()); - rows.add(rowEntry); - } - view.logHeading("Schnittpunkte der Dualen Geraden:"); - view.createTable(heading, rows); */ } @@ -112,7 +91,7 @@ public class Presenter implements Observer { }); setup(); Thread t = new Thread(() -> { - calcArrangementNodes(); + calculateIntersections(); }); t.start(); try { @@ -138,35 +117,64 @@ public class Presenter implements Observer { ***************************************************************************************************************************/ public void calculateLMS(String[] input) { if (input[0] != null && input[1] != null){ - Double constant = Double.parseDouble(input[0]); - Double error = Double.parseDouble(input[1]); - LeastMedianOfSquaresEstimator lms = new LeastMedianOfSquaresEstimator(getModel().getLines(), getModel().getNodes(), this); - lms.setConstant(constant); - lms.setQuantileError(error); - lms.addObserver(this); - lms.run(); - lms.getResult(); + if (lmsThread == null || !lmsThread.isAlive()){ + lmsThread = new Thread(() -> { + Double constant = Double.parseDouble(input[0]); + Double error = Double.parseDouble(input[1]); + LeastMedianOfSquaresEstimator lms = new LeastMedianOfSquaresEstimator(getModel().getLines(), getModel().getNodes(), this); + lms.setConstant(constant); + lms.setQuantileError(error); + lms.addObserver(this); + lms.run(); + lms.getResult(); + }); + lmsThread.start(); + try { + lmsThread.join(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } } } public void calculateRM(String input){ if (input != null){ - RepeatedMedianEstimator rm = new RepeatedMedianEstimator(getModel().getLines(), this); - Double parameter = Double.parseDouble(input); - rm.setBeta(parameter); - rm.addObserver(this); - rm.run(); - rm.getResult(); + if (rmThread == null || !rmThread.isAlive()){ + rmThread = new Thread(() -> { + RepeatedMedianEstimator rm = new RepeatedMedianEstimator(getModel().getLines(), this); + Double parameter = Double.parseDouble(input); + rm.setBeta(parameter); + rm.addObserver(this); + rm.run(); + rm.getResult(); + }); + rmThread.start(); + try { + rmThread.join(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } } } - public void calculateTS(String input){ if (input != null){ - TheilSenEstimator ts = new TheilSenEstimator(getModel().getLines(), getModel().getNodes(),this); - ts.addObserver(this); - ts.run(); - ts.getResult(); + if (tsThread == null || !tsThread.isAlive()){ + tsThread = new Thread(() ->{ + TheilSenEstimator ts = new TheilSenEstimator(getModel().getLines(), getModel().getNodes(),this); + ts.addObserver(this); + ts.run(); + ts.getResult(); + }); + tsThread.start(); + try { + tsThread.join(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } } } @@ -202,45 +210,9 @@ public class Presenter implements Observer { getView().log("
"); } - // public Point calcIntersection(Line a, Line b) { - // Line p1 = a; - // Line p2 = b; - // - // Double x = (p1.getB() - p2.getB()) / (p2.getM() - p1.getM()); - // Double y = ((p1.getM() * p2.getB()) - (p2.getM() * p1.getB())) / (p1.getM() - p2.getM()); - // - // return new Point(x, y); - // } - - public void calcArrangementNodes() { + public void calculateIntersections() { try { Thread thread = new Thread(() -> { - /*Double xMinimum = Double.MAX_VALUE; - Double xMaximum = Double.MIN_VALUE; - Double yMinimum = Double.MAX_VALUE; - Double yMaximum = Double.MIN_VALUE; - - for (int i = 0; i < getLines().size(); i++) { - for (int j = i; j < getLines().size(); j++) { - if (i != j) { - Point intersection = calcIntersection(getLines().get(j), getLines().get(i)); - - if (intersection.getX() != Double.POSITIVE_INFINITY && intersection.getX() != Double.NEGATIVE_INFINITY && - intersection.getY() != Double.POSITIVE_INFINITY && intersection.getY() != Double.NEGATIVE_INFINITY ){ - xMinimum = xMinimum > intersection.getX() ? intersection.getX() : xMinimum; - xMaximum = xMaximum < intersection.getX() ? intersection.getX() : xMaximum; - yMinimum = yMinimum > intersection.getY() ? intersection.getY() : yMinimum; - yMaximum = yMaximum < intersection.getY() ? intersection.getY() : yMaximum; - - model.addNode(intersection); - } - } - } - } - model.setxMinimum(xMinimum); - model.setxMaximum(xMaximum); - model.setyMaximum(yMaximum); - model.setyMinimum(yMinimum);*/ IntersectionCounter counter = new IntersectionCounter(); counter.run(getLines(), new Interval(-99999,99999)); counter.calculateIntersectionAbscissas(getModel()); @@ -255,34 +227,37 @@ public class Presenter implements Observer { } } - public LinkedList calcArrangementLines() { - LinkedList lineCoordinates = new LinkedList<>(); - double x1 = -1000; - double x2 = 1000; - - for (Line point : model.getLines()) { - double y1 = (point.getM() * x1 + point.getB()); - double y2 = (point.getM() * x2 + point.getB()); - Line line = new Line(x1, x2, y1, y2); - line.setId(point.getId()); - lineCoordinates.add(line); - } - - return lineCoordinates; - } - public void startImport(File file){ - DataImporter importer = new DataImporter(file, this); - importer.addObserver(this); - importer.run(); + if (importThread == null || !importThread.isAlive()){ + importThread = new Thread(()->{ + DataImporter importer = new DataImporter(file, this); + importer.addObserver(this); + importer.run(); + }); + importThread.start(); + try { + importThread.join(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } } public void generateDataset(){ - DatasetGenerator generator = new DatasetGenerator(); - getModel().setLines((LinkedList) generator.generateDataset()); - calcArrangementNodes(); - getView().enableFunctionality(); - + if (generatorThread == null || !generatorThread.isAlive()){ + generatorThread = new Thread(() -> { + DatasetGenerator generator = new DatasetGenerator(); + getModel().setLines(generator.generateDataset()); + calculateIntersections(); + getView().enableFunctionality(); + }); + generatorThread.start(); + try { + generatorThread.join(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } } /*************************************************************************************************************************** diff --git a/src/main/java/View/MainFrame.java b/src/main/java/View/MainFrame.java index 52932ac..b6b45e8 100644 --- a/src/main/java/View/MainFrame.java +++ b/src/main/java/View/MainFrame.java @@ -81,7 +81,7 @@ public class MainFrame extends JFrame { arrangementDialog.setSize(new Dimension(800, 800)); arrangementDialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE); arrangement.clear(); - arrangement.setPrameters(getPresenter().calcArrangementLines(), + arrangement.setPrameters(getPresenter().getLines(), getPresenter().getModel().getNodes(), getPresenter().getModel().getxMinimum(), getPresenter().getModel().getxMaximum(), @@ -178,7 +178,7 @@ public class MainFrame extends JFrame { } private void setDimensions() { - this.setMinimumSize(new Dimension(1366,768)); + this.setMinimumSize(new Dimension(1024,768)); this.setExtendedState(JFrame.MAXIMIZED_BOTH); lmsPanel.setMinimumSize(new Dimension(400, 500)); rmPanel.setMinimumSize(new Dimension(400, 500));