fixed the issue with rm estimator
This commit is contained in:
parent
2a003fee9a
commit
bef956bf4c
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -4,8 +4,8 @@
|
||||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
<groupId>wwu</groupId>
|
<groupId>de.wwu.awolf</groupId>
|
||||||
<artifactId>Masterarbeit</artifactId>
|
<artifactId>masterarbeit</artifactId>
|
||||||
<version>1.0</version>
|
<version>1.0</version>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
|
@ -13,13 +13,13 @@
|
||||||
<plugin>
|
<plugin>
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
<artifactId>maven-compiler-plugin</artifactId>
|
<artifactId>maven-compiler-plugin</artifactId>
|
||||||
|
<version>3.8.1</version>
|
||||||
<configuration>
|
<configuration>
|
||||||
<source>11</source>
|
<source>11</source>
|
||||||
<target>11</target>
|
<target>11</target>
|
||||||
</configuration>
|
</configuration>
|
||||||
</plugin>
|
</plugin>
|
||||||
|
|
||||||
|
|
||||||
<!-- Maven Assembly Plugin -->
|
<!-- Maven Assembly Plugin -->
|
||||||
<plugin>
|
<plugin>
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
@ -49,21 +49,6 @@
|
||||||
</execution>
|
</execution>
|
||||||
</executions>
|
</executions>
|
||||||
</plugin>
|
</plugin>
|
||||||
<plugin>
|
|
||||||
<groupId>com.googlecode.mavennatives</groupId>
|
|
||||||
<artifactId>maven-nativedependencies-plugin</artifactId>
|
|
||||||
<version>0.0.7</version>
|
|
||||||
<executions>
|
|
||||||
<execution>
|
|
||||||
<id>unpacknatives</id>
|
|
||||||
<phase>generate-resources</phase>
|
|
||||||
<goals>
|
|
||||||
<goal>copy</goal>
|
|
||||||
</goals>
|
|
||||||
</execution>
|
|
||||||
</executions>
|
|
||||||
</plugin>
|
|
||||||
|
|
||||||
<plugin>
|
<plugin>
|
||||||
<groupId>org.sonarsource.scanner.maven</groupId>
|
<groupId>org.sonarsource.scanner.maven</groupId>
|
||||||
<artifactId>sonar-maven-plugin</artifactId>
|
<artifactId>sonar-maven-plugin</artifactId>
|
||||||
|
@ -88,20 +73,6 @@
|
||||||
<version>4.12</version>
|
<version>4.12</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!-- OpenCSV-->
|
|
||||||
<dependency>
|
|
||||||
<groupId>com.opencsv</groupId>
|
|
||||||
<artifactId>opencsv</artifactId>
|
|
||||||
<version>3.9</version>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<!-- JTattoo Look and Feel -->
|
|
||||||
<dependency>
|
|
||||||
<groupId>com.jtattoo</groupId>
|
|
||||||
<artifactId>JTattoo</artifactId>
|
|
||||||
<version>1.6.11</version>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<!-- https://mvnrepository.com/artifact/commons-io/commons-io -->
|
<!-- https://mvnrepository.com/artifact/commons-io/commons-io -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>commons-io</groupId>
|
<groupId>commons-io</groupId>
|
||||||
|
@ -109,12 +80,6 @@
|
||||||
<version>2.5</version>
|
<version>2.5</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.openpnp</groupId>
|
|
||||||
<artifactId>opencv</artifactId>
|
|
||||||
<version>3.2.0-1</version>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>log4j</groupId>
|
<groupId>log4j</groupId>
|
||||||
<artifactId>log4j</artifactId>
|
<artifactId>log4j</artifactId>
|
||||||
|
@ -122,13 +87,16 @@
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>commons-cli</groupId>
|
<groupId>com.opencsv</groupId>
|
||||||
<artifactId>commons-cli</artifactId>
|
<artifactId>opencsv</artifactId>
|
||||||
<version>1.4</version>
|
<version>5.1</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.google.guava</groupId>
|
||||||
|
<artifactId>guava</artifactId>
|
||||||
|
<version>28.2-jre</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
|
|
||||||
</project>
|
</project>
|
|
@ -51,10 +51,26 @@ public class Line {
|
||||||
this.m = m;
|
this.m = m;
|
||||||
this.b = b;
|
this.b = b;
|
||||||
|
|
||||||
this.x1 = MIN;
|
this.x1 = calculateX1(MIN);
|
||||||
this.y1 = (MIN * m) + b;
|
this.y1 = calculateY1(MIN);
|
||||||
this.x2 = MAX * 0.5;
|
this.x2 = calculateX2(MAX * 0.5);
|
||||||
this.y2 = ((MAX * 0.5) * m) + b;
|
this.y2 = calculateY2(MAX * 0.5);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Double calculateX1(Double min) {
|
||||||
|
return (double) min;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Double calculateY1(Double min) {
|
||||||
|
return (min * m) + b;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Double calculateX2(Double max) {
|
||||||
|
return (double) max;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Double calculateY2(Double max) {
|
||||||
|
return (max * m) + b;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -188,4 +204,74 @@ public class Line {
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "Line m: " + this.getM() + ", b: " + this.getB();
|
return "Line m: " + this.getM() + ", b: " + this.getB();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public Point intersect(Line line) {
|
||||||
|
double x = (line.b - this.b) / (this.m - line.m);
|
||||||
|
double y = this.m * x + this.b;
|
||||||
|
|
||||||
|
return new Point(x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Given three colinear points p, q, r, the function checks if
|
||||||
|
// point q lies on line segment 'pr'
|
||||||
|
public boolean onSegment(Point p, Point q, Point r) {
|
||||||
|
if (q.getX() <= Math.max(p.getX(), r.getX()) && q.getX() >= Math.min(p.getX(), r.getX()) &&
|
||||||
|
q.getY() <= Math.max(p.getY(), r.getY()) && q.getY() >= Math.min(p.getY(), r.getY()))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// To find orientation of ordered triplet (p, q, r).
|
||||||
|
// The function returns following values
|
||||||
|
// 0 --> p, q and r are colinear
|
||||||
|
// 1 --> Clockwise
|
||||||
|
// 2 --> Counterclockwise
|
||||||
|
public int orientation(Point p, Point q, Point r) {
|
||||||
|
// See https://www.geeksforgeeks.org/orientation-3-ordered-points/
|
||||||
|
// for details of below formula.
|
||||||
|
double val = (q.getY() - p.getY()) * (r.getX() - q.getX()) -
|
||||||
|
(q.getX() - p.getX()) * (r.getY() - q.getY());
|
||||||
|
|
||||||
|
if (val == 0) return 0; // colinear
|
||||||
|
|
||||||
|
return (val > 0) ? 1 : 2; // clock or counterclock wise
|
||||||
|
}
|
||||||
|
|
||||||
|
// The main function that returns true if line segment 'p1q1'
|
||||||
|
// and 'p2q2' intersect.
|
||||||
|
// Line A: y = mx + b -->
|
||||||
|
public boolean doIntersect(Line line, double lower, double upper) {
|
||||||
|
//this
|
||||||
|
Point p1 = new Point(calculateX1(lower), calculateY1(lower));
|
||||||
|
Point q1 = new Point(calculateX2(upper), calculateY2(upper));
|
||||||
|
Point p2 = new Point(line.calculateX1(lower), line.calculateY1(lower));
|
||||||
|
Point q2 = new Point(line.calculateX2(upper), line.calculateY2(upper));
|
||||||
|
// Find the four orientations needed for general and
|
||||||
|
// special cases
|
||||||
|
int o1 = orientation(p1, q1, p2);
|
||||||
|
int o2 = orientation(p1, q1, q2);
|
||||||
|
int o3 = orientation(p2, q2, p1);
|
||||||
|
int o4 = orientation(p2, q2, q1);
|
||||||
|
|
||||||
|
// General case
|
||||||
|
if (o1 != o2 && o3 != o4)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
// Special Cases
|
||||||
|
// p1, q1 and p2 are colinear and p2 lies on segment p1q1
|
||||||
|
if (o1 == 0 && onSegment(p1, p2, q1)) return true;
|
||||||
|
|
||||||
|
// p1, q1 and q2 are colinear and q2 lies on segment p1q1
|
||||||
|
if (o2 == 0 && onSegment(p1, q2, q1)) return true;
|
||||||
|
|
||||||
|
// p2, q2 and p1 are colinear and p1 lies on segment p2q2
|
||||||
|
if (o3 == 0 && onSegment(p2, p1, q2)) return true;
|
||||||
|
|
||||||
|
// p2, q2 and q1 are colinear and q1 lies on segment p2q2
|
||||||
|
if (o4 == 0 && onSegment(p2, q1, q2)) return true;
|
||||||
|
|
||||||
|
return false; // Doesn't fall in any of the above cases
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,7 +13,6 @@ import java.util.List;
|
||||||
*/
|
*/
|
||||||
public class LineModel {
|
public class LineModel {
|
||||||
|
|
||||||
private List<Point> nodes;
|
|
||||||
private List<Line> lines;
|
private List<Line> lines;
|
||||||
private Double xMinimum;
|
private Double xMinimum;
|
||||||
private Double xMaximum;
|
private Double xMaximum;
|
||||||
|
@ -24,7 +23,6 @@ public class LineModel {
|
||||||
* Konstruktor
|
* Konstruktor
|
||||||
*/
|
*/
|
||||||
public LineModel() {
|
public LineModel() {
|
||||||
nodes = new ArrayList<>();
|
|
||||||
lines = new LinkedList<>();
|
lines = new LinkedList<>();
|
||||||
|
|
||||||
xMinimum = Double.MAX_VALUE;
|
xMinimum = Double.MAX_VALUE;
|
||||||
|
@ -34,14 +32,6 @@ public class LineModel {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Fügt einen Schnittpunkt zum Modell hinzu
|
|
||||||
*
|
|
||||||
* @param node Schnittpunkt
|
|
||||||
*/
|
|
||||||
public void addNode(Point node) {
|
|
||||||
this.nodes.add(node);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fügt eine Gerade zu dem Modell hinzu
|
* Fügt eine Gerade zu dem Modell hinzu
|
||||||
|
@ -52,19 +42,6 @@ public class LineModel {
|
||||||
this.lines.add(line);
|
this.lines.add(line);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @return Liste der Schnittpunkte
|
|
||||||
*/
|
|
||||||
public List<Point> getNodes() {
|
|
||||||
return nodes;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param nodes Liste der Schnittpunkte
|
|
||||||
*/
|
|
||||||
public void setNodes(List<Point> nodes) {
|
|
||||||
this.nodes = nodes;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return Liste der Geraden
|
* @return Liste der Geraden
|
||||||
|
|
|
@ -114,4 +114,8 @@ public class Point implements Comparable<Point> {
|
||||||
public void setId(String id) {
|
public void setId(String id) {
|
||||||
this.id = id;
|
this.id = id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -90,47 +90,6 @@ public abstract class AbstractPresenter implements Flow.Subscriber<Data> {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Startet das parallele Berechnen der Schnittpunkte der Geraden die im Modell enthalten sind.
|
|
||||||
*/
|
|
||||||
private void startIntersectionCalculation() {
|
|
||||||
getExecutor().submit(() -> {
|
|
||||||
getModel().resetRanges();
|
|
||||||
IntersectionComputer intersectionComputer = new IntersectionComputer(getModel().getLines());
|
|
||||||
getModel().setNodes(intersectionComputer.compute());
|
|
||||||
|
|
||||||
getModel().setxMaximum(intersectionComputer.getxMaximum());
|
|
||||||
getModel().setxMinimum(intersectionComputer.getxMinimum());
|
|
||||||
getModel().setyMaximum(intersectionComputer.getyMaximum());
|
|
||||||
getModel().setyMinimum(intersectionComputer.getyMinimum());
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Wrapper Methode die das berechnen der Schnittpunkte anstößt und die Ergebnisse(Anzahl der Schnittpunkte)
|
|
||||||
* visuell darstellt.
|
|
||||||
*/
|
|
||||||
protected void computeIntersections() {
|
|
||||||
getExecutor().submit(() -> {
|
|
||||||
long start, end;
|
|
||||||
start = System.currentTimeMillis();
|
|
||||||
startIntersectionCalculation();
|
|
||||||
end = System.currentTimeMillis();
|
|
||||||
Logging.logInfo("Computing intersections took " + (end - start) / 1000 + "ms");
|
|
||||||
});
|
|
||||||
|
|
||||||
//darstellung der Ergebnisse
|
|
||||||
SwingUtilities.invokeLater(() -> {
|
|
||||||
getView().enableFunctionality();
|
|
||||||
getView().getProgressDialog().dispose();
|
|
||||||
});
|
|
||||||
|
|
||||||
Logging.logInfo("Informationen zu dem aktuellen Modell");
|
|
||||||
Logging.logInfo("Anzahl der Geraden: " + getModel().getLines().size() + ".");
|
|
||||||
Logging.logInfo("Anzahl der Schnittpunkte: " + getModel().getNodes().size() + ".");
|
|
||||||
Logging.logInfo("Import war Erfolgreich!");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return das zu grunde legende Modell
|
* @return das zu grunde legende Modell
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -63,10 +63,6 @@ public class Presenter extends AbstractPresenter {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void visualizeDualLines() {
|
|
||||||
getView().createDualityDialog();
|
|
||||||
}
|
|
||||||
|
|
||||||
/***************************************************************************************************************************
|
/***************************************************************************************************************************
|
||||||
* Ausführung der Algorithmen
|
* Ausführung der Algorithmen
|
||||||
***************************************************************************************************************************/
|
***************************************************************************************************************************/
|
||||||
|
@ -81,7 +77,7 @@ public class Presenter extends AbstractPresenter {
|
||||||
//Parameter für den Algortihmus
|
//Parameter für den Algortihmus
|
||||||
Double constant = Double.parseDouble(input[0]);
|
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);
|
LeastMedianOfSquaresEstimator lms = new LeastMedianOfSquaresEstimator(getModel().getLines(), this);
|
||||||
//setzen der Parameter
|
//setzen der Parameter
|
||||||
lms.setConstant(constant);
|
lms.setConstant(constant);
|
||||||
lms.setQuantileError(error);
|
lms.setQuantileError(error);
|
||||||
|
@ -114,7 +110,7 @@ public class Presenter extends AbstractPresenter {
|
||||||
*/
|
*/
|
||||||
public void calculateTS(String input) {
|
public void calculateTS(String input) {
|
||||||
if (input != null) {
|
if (input != null) {
|
||||||
TheilSenEstimator ts = new TheilSenEstimator(getModel().getLines(), getModel().getNodes(), this);
|
TheilSenEstimator ts = new TheilSenEstimator(getModel().getLines(), this);
|
||||||
//Presenter soll die Klasse überwachen
|
//Presenter soll die Klasse überwachen
|
||||||
getExecutor().submit(ts);
|
getExecutor().submit(ts);
|
||||||
}
|
}
|
||||||
|
@ -131,12 +127,10 @@ public class Presenter extends AbstractPresenter {
|
||||||
*/
|
*/
|
||||||
public void startImport(File file) {
|
public void startImport(File file) {
|
||||||
List<Line> data = getDataProvider().getData(file);
|
List<Line> data = getDataProvider().getData(file);
|
||||||
if (data != null) {
|
//Berechnung der Schnittpunkte und vis. der Ergebnisse (anz. Geraden, anz. Schnittpunkte)
|
||||||
//Berechnung der Schnittpunkte und vis. der Ergebnisse (anz. Geraden, anz. Schnittpunkte)
|
getModel().setLines(data);
|
||||||
getModel().setLines(data);
|
getView().enableFunctionality();
|
||||||
computeIntersections();
|
Logging.logInfo("Import successfully! " + Thread.currentThread().getName());
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -166,8 +160,8 @@ public class Presenter extends AbstractPresenter {
|
||||||
public void generateDataset(int n, DataProvider.DataType type) {
|
public void generateDataset(int n, DataProvider.DataType type) {
|
||||||
List<Line> data = getDataProvider().getData(type, n);
|
List<Line> data = getDataProvider().getData(type, n);
|
||||||
getModel().setLines(data);
|
getModel().setLines(data);
|
||||||
computeIntersections();
|
|
||||||
getView().enableFunctionality();
|
getView().enableFunctionality();
|
||||||
|
Logging.logInfo("Generated successfully!" + Thread.currentThread().getName());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -8,7 +8,7 @@ import de.wwwu.awolf.model.communication.Data;
|
||||||
import de.wwwu.awolf.model.communication.SubscriberType;
|
import de.wwwu.awolf.model.communication.SubscriberType;
|
||||||
import de.wwwu.awolf.presenter.Presenter;
|
import de.wwwu.awolf.presenter.Presenter;
|
||||||
import de.wwwu.awolf.presenter.algorithms.Algorithm;
|
import de.wwwu.awolf.presenter.algorithms.Algorithm;
|
||||||
import de.wwwu.awolf.presenter.util.IntersectionCounter;
|
import de.wwwu.awolf.presenter.util.IntersectionComputer;
|
||||||
import de.wwwu.awolf.presenter.util.Logging;
|
import de.wwwu.awolf.presenter.util.Logging;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
@ -23,9 +23,7 @@ import java.util.concurrent.Flow;
|
||||||
*/
|
*/
|
||||||
public class LeastMedianOfSquaresEstimator implements Algorithm, Flow.Publisher<Data> {
|
public class LeastMedianOfSquaresEstimator implements Algorithm, Flow.Publisher<Data> {
|
||||||
|
|
||||||
private List<Line> set;
|
private List<Line> setOfLines;
|
||||||
private List<Point> intersections;
|
|
||||||
private IntersectionCounter invCounter = new IntersectionCounter();
|
|
||||||
private int n;
|
private int n;
|
||||||
private double quantileError;
|
private double quantileError;
|
||||||
private int kPlus;
|
private int kPlus;
|
||||||
|
@ -45,16 +43,13 @@ public class LeastMedianOfSquaresEstimator implements Algorithm, Flow.Publisher<
|
||||||
/**
|
/**
|
||||||
* Konstruktor
|
* Konstruktor
|
||||||
*
|
*
|
||||||
* @param set Liste der Geraden
|
* @param setOfLines Liste der Geraden
|
||||||
* @param intersections Liste der Schnittpunkte
|
|
||||||
* @param presenter Presenter (Beobachter)
|
* @param presenter Presenter (Beobachter)
|
||||||
*/
|
*/
|
||||||
public LeastMedianOfSquaresEstimator(List<Line> set, List<Point> intersections,
|
public LeastMedianOfSquaresEstimator(List<Line> setOfLines, Presenter presenter) {
|
||||||
Presenter presenter) {
|
this.setOfLines = setOfLines;
|
||||||
this.set = set;
|
|
||||||
this.intersections = intersections;
|
|
||||||
|
|
||||||
n = set.size();
|
n = setOfLines.size();
|
||||||
double qPlus = 0.5;
|
double qPlus = 0.5;
|
||||||
quantileError = 0.1;
|
quantileError = 0.1;
|
||||||
double qMinus = qPlus * (1 - quantileError);
|
double qMinus = qPlus * (1 - quantileError);
|
||||||
|
@ -66,11 +61,10 @@ public class LeastMedianOfSquaresEstimator implements Algorithm, Flow.Publisher<
|
||||||
/**
|
/**
|
||||||
* Konstruktor
|
* Konstruktor
|
||||||
*
|
*
|
||||||
* @param set Liste der Geraden
|
* @param setOfLines Liste der Geraden
|
||||||
* @param intersections Liste der Schnittpunkte
|
|
||||||
*/
|
*/
|
||||||
public LeastMedianOfSquaresEstimator(List<Line> set, List<Point> intersections) {
|
public LeastMedianOfSquaresEstimator(List<Line> setOfLines) {
|
||||||
this(set, intersections, null);
|
this(setOfLines, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -101,9 +95,8 @@ public class LeastMedianOfSquaresEstimator implements Algorithm, Flow.Publisher<
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
intervals = new PriorityQueue<>(comparator);
|
intervals = new PriorityQueue<>(comparator);
|
||||||
intervals.add(new Interval(-100000, 100000));
|
intervals.add(new Interval(-10000, 10000));
|
||||||
heightsigmaMin = Double.MAX_VALUE;
|
heightsigmaMin = Double.MAX_VALUE;
|
||||||
List<Point> tmpIntersections = new ArrayList<>(intersections);
|
|
||||||
|
|
||||||
//(3.) Apply the following steps as long as the exists active intervals
|
//(3.) Apply the following steps as long as the exists active intervals
|
||||||
boolean active = true;
|
boolean active = true;
|
||||||
|
@ -120,7 +113,7 @@ public class LeastMedianOfSquaresEstimator implements Algorithm, Flow.Publisher<
|
||||||
} else {
|
} else {
|
||||||
//(c.) otherwise....
|
//(c.) otherwise....
|
||||||
// get random intersections point...
|
// get random intersections point...
|
||||||
Collections.shuffle(tmpIntersections);
|
Collection<Point> tmpIntersections = IntersectionComputer.getInstance().compute(setOfLines, interval.getLower(), interval.getUpper());
|
||||||
boolean found = false;
|
boolean found = false;
|
||||||
for (Point tmpIntersection : tmpIntersections) {
|
for (Point tmpIntersection : tmpIntersections) {
|
||||||
if (tmpIntersection.getX() > interval.getLower()
|
if (tmpIntersection.getX() > interval.getLower()
|
||||||
|
@ -154,7 +147,7 @@ public class LeastMedianOfSquaresEstimator implements Algorithm, Flow.Publisher<
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
end = System.currentTimeMillis();
|
end = System.currentTimeMillis();
|
||||||
Logging.logInfo("Zeit: " + ((end - start) / 1000));
|
Logging.logInfo("=== E N D - L M S === " + ((end - start) / 1000));
|
||||||
|
|
||||||
return pepareResult();
|
return pepareResult();
|
||||||
}
|
}
|
||||||
|
@ -166,7 +159,7 @@ public class LeastMedianOfSquaresEstimator implements Algorithm, Flow.Publisher<
|
||||||
* @return Anzahl der Schnittpunkte
|
* @return Anzahl der Schnittpunkte
|
||||||
*/
|
*/
|
||||||
public int countInversions(Interval interval) {
|
public int countInversions(Interval interval) {
|
||||||
return invCounter.run(set, interval);
|
return IntersectionComputer.getInstance().compute(setOfLines, interval.getLower(), interval.getUpper()).size();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -183,7 +176,8 @@ public class LeastMedianOfSquaresEstimator implements Algorithm, Flow.Publisher<
|
||||||
|
|
||||||
//initialisiere die x-Queue mit den 2D Punkten und sortiere nach x-Lexikographischer Ordnung
|
//initialisiere die x-Queue mit den 2D Punkten und sortiere nach x-Lexikographischer Ordnung
|
||||||
List<Point> xQueue = new ArrayList<>();
|
List<Point> xQueue = new ArrayList<>();
|
||||||
for (Point point : intersections) {
|
Collection<Point> points = IntersectionComputer.getInstance().compute(setOfLines, interval.getLower(), interval.getUpper());
|
||||||
|
for (Point point : points) {
|
||||||
if (point.getX() >= interval.getLower() && point.getX() < interval.getUpper()) {
|
if (point.getX() >= interval.getLower() && point.getX() < interval.getUpper()) {
|
||||||
xQueue.add(point);
|
xQueue.add(point);
|
||||||
}
|
}
|
||||||
|
@ -271,7 +265,7 @@ public class LeastMedianOfSquaresEstimator implements Algorithm, Flow.Publisher<
|
||||||
|
|
||||||
//y koordinaten der Schnittpunkte
|
//y koordinaten der Schnittpunkte
|
||||||
List<Line> lines = new ArrayList<>();
|
List<Line> lines = new ArrayList<>();
|
||||||
for (Line p : set) {
|
for (Line p : setOfLines) {
|
||||||
lines.add(
|
lines.add(
|
||||||
new Line(pslab.getLower(), pslab.getUpper(), ((pslab.getLower() * p.getM()) + p.getB()),
|
new Line(pslab.getLower(), pslab.getUpper(), ((pslab.getLower() * p.getM()) + p.getB()),
|
||||||
((pslab.getUpper() * p.getM()) + p.getB())));
|
((pslab.getUpper() * p.getM()) + p.getB())));
|
||||||
|
@ -333,7 +327,7 @@ public class LeastMedianOfSquaresEstimator implements Algorithm, Flow.Publisher<
|
||||||
|
|
||||||
List<Double> ret = new ArrayList<>();
|
List<Double> ret = new ArrayList<>();
|
||||||
|
|
||||||
for (Line p : set) {
|
for (Line p : setOfLines) {
|
||||||
ret.add((p.getM() * u) + p.getB());
|
ret.add((p.getM() * u) + p.getB());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -354,7 +348,7 @@ public class LeastMedianOfSquaresEstimator implements Algorithm, Flow.Publisher<
|
||||||
|
|
||||||
//y Koordinaten für das kMinus brecalet
|
//y Koordinaten für das kMinus brecalet
|
||||||
List<Double> intersections = new LinkedList<>();
|
List<Double> intersections = new LinkedList<>();
|
||||||
for (Line line : set) {
|
for (Line line : setOfLines) {
|
||||||
intersections.add((px.getX() * line.getM()) + line.getB());
|
intersections.add((px.getX() * line.getM()) + line.getB());
|
||||||
}
|
}
|
||||||
if (intersections.size() >= kMinusValue) {
|
if (intersections.size() >= kMinusValue) {
|
||||||
|
|
|
@ -2,20 +2,15 @@ package de.wwwu.awolf.presenter.algorithms.advanced;
|
||||||
|
|
||||||
import de.wwwu.awolf.model.Interval;
|
import de.wwwu.awolf.model.Interval;
|
||||||
import de.wwwu.awolf.model.Line;
|
import de.wwwu.awolf.model.Line;
|
||||||
|
import de.wwwu.awolf.model.Point;
|
||||||
import de.wwwu.awolf.model.communication.AlgorithmData;
|
import de.wwwu.awolf.model.communication.AlgorithmData;
|
||||||
import de.wwwu.awolf.model.communication.Data;
|
import de.wwwu.awolf.model.communication.Data;
|
||||||
import de.wwwu.awolf.model.communication.SubscriberType;
|
import de.wwwu.awolf.model.communication.SubscriberType;
|
||||||
import de.wwwu.awolf.presenter.Presenter;
|
import de.wwwu.awolf.presenter.Presenter;
|
||||||
import de.wwwu.awolf.presenter.algorithms.Algorithm;
|
import de.wwwu.awolf.presenter.algorithms.Algorithm;
|
||||||
import de.wwwu.awolf.presenter.util.FastElementSelector;
|
import de.wwwu.awolf.presenter.util.*;
|
||||||
import de.wwwu.awolf.presenter.util.IntersectionCounter;
|
|
||||||
import de.wwwu.awolf.presenter.util.Logging;
|
|
||||||
import de.wwwu.awolf.presenter.util.RandomSampler;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.*;
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.concurrent.Flow;
|
import java.util.concurrent.Flow;
|
||||||
|
|
||||||
|
|
||||||
|
@ -29,20 +24,19 @@ import java.util.concurrent.Flow;
|
||||||
public class RepeatedMedianEstimator implements Algorithm, Flow.Publisher<Data> {
|
public class RepeatedMedianEstimator implements Algorithm, Flow.Publisher<Data> {
|
||||||
|
|
||||||
private Presenter presenter;
|
private Presenter presenter;
|
||||||
private List<Line> set;
|
private List<Line> setOfLines;
|
||||||
private Map<Line, Double> medianIntersections = new HashMap<>();
|
|
||||||
private Map<Line, ArrayList<Double>> intersectionAbscissas = new HashMap<>();
|
|
||||||
private Interval interval;
|
private Interval interval;
|
||||||
|
private Interval original;
|
||||||
|
|
||||||
//in der Literatur als L_i, C_i, und R_i bekannt
|
//in der Literatur als L_i, C_i, und R_i bekannt
|
||||||
private List<Double> countLeftSlab;
|
private int countLeftSlab;
|
||||||
private List<Double> countCenterSlab;
|
private int countCenterSlab;
|
||||||
private List<Double> countRightSlab;
|
private int countRightSlab;
|
||||||
|
|
||||||
//die Mengen L,C und R
|
//in der Literatur als L_i, C_i, und R_i bekannt
|
||||||
private List<Line> linesInLeftSlab;
|
private Set<Point> intersectionsInLeftSlab;
|
||||||
private List<Line> linesInCenterSlab;
|
private Set<Point> intersectionsInCenterSlab;
|
||||||
private List<Line> linesInRightSlab;
|
private Set<Point> intersectionsInRightSlab;
|
||||||
|
|
||||||
private double r;
|
private double r;
|
||||||
private int n;
|
private int n;
|
||||||
|
@ -51,9 +45,6 @@ public class RepeatedMedianEstimator implements Algorithm, Flow.Publisher<Data>
|
||||||
private double kHigh;
|
private double kHigh;
|
||||||
private double beta;
|
private double beta;
|
||||||
|
|
||||||
private double thetaLow;
|
|
||||||
private double thetaHigh;
|
|
||||||
|
|
||||||
private double slope;
|
private double slope;
|
||||||
private double yInterception;
|
private double yInterception;
|
||||||
private Flow.Subscriber<? super AlgorithmData> subscriber;
|
private Flow.Subscriber<? super AlgorithmData> subscriber;
|
||||||
|
@ -61,39 +52,41 @@ public class RepeatedMedianEstimator implements Algorithm, Flow.Publisher<Data>
|
||||||
/**
|
/**
|
||||||
* Konstruktor
|
* Konstruktor
|
||||||
*
|
*
|
||||||
* @param set Liste der Geraden
|
* @param setOfLines Liste der Geraden
|
||||||
* @param presenter Presenter (Beobachter)
|
* @param presenter Presenter (Beobachter)
|
||||||
*/
|
*/
|
||||||
public RepeatedMedianEstimator(List<Line> set, Presenter presenter) {
|
public RepeatedMedianEstimator(List<Line> setOfLines, Presenter presenter) {
|
||||||
this.set = set;
|
this.setOfLines = setOfLines;
|
||||||
this.presenter = presenter;
|
this.presenter = presenter;
|
||||||
interval = new Interval(-10000, 10000);
|
interval = new Interval(-10000, 10000);
|
||||||
n = set.size();
|
original = new Interval(-10000,10000);
|
||||||
|
n = setOfLines.size();
|
||||||
beta = 0.5;
|
beta = 0.5;
|
||||||
countLeftSlab = new ArrayList<>();
|
|
||||||
countCenterSlab = new ArrayList<>();
|
intersectionsInLeftSlab = new HashSet<>();
|
||||||
countRightSlab = new ArrayList<>();
|
intersectionsInCenterSlab = new HashSet<>();
|
||||||
|
intersectionsInRightSlab = new HashSet<>();
|
||||||
|
|
||||||
|
intersectionsInLeftSlab.add(new Point(0d,0d));
|
||||||
|
intersectionsInCenterSlab.add(new Point(0d,0d));
|
||||||
|
intersectionsInCenterSlab.add(new Point(0d,0d));
|
||||||
|
|
||||||
|
|
||||||
for (int i = 0; i < n; i++) {
|
for (int i = 0; i < n; i++) {
|
||||||
countLeftSlab.add(0d);
|
countLeftSlab = 0;
|
||||||
countRightSlab.add(0d);
|
countRightSlab = 0;
|
||||||
countCenterSlab.add(n - 1.0);
|
countCenterSlab = setOfLines.size();
|
||||||
intersectionAbscissas.put(set.get(i), new ArrayList<>());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
linesInLeftSlab = new ArrayList<>();
|
|
||||||
linesInCenterSlab = new ArrayList<>(set);
|
|
||||||
linesInRightSlab = new ArrayList<>();
|
|
||||||
subscribe(presenter);
|
subscribe(presenter);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Konstruktor
|
* Konstruktor
|
||||||
*
|
*
|
||||||
* @param set Liste der Geraden
|
* @param setOfLines Liste der Geraden
|
||||||
*/
|
*/
|
||||||
public RepeatedMedianEstimator(List<Line> set) {
|
public RepeatedMedianEstimator(List<Line> setOfLines) {
|
||||||
this(set, null);
|
this(setOfLines, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -110,42 +103,46 @@ public class RepeatedMedianEstimator implements Algorithm, Flow.Publisher<Data>
|
||||||
long start;
|
long start;
|
||||||
long end;
|
long end;
|
||||||
start = System.currentTimeMillis();
|
start = System.currentTimeMillis();
|
||||||
|
double thetaLow = 0;
|
||||||
|
double thetaHigh = 0;
|
||||||
|
|
||||||
while (linesInCenterSlab.size() != 1) {
|
while (countCenterSlab > 1) {
|
||||||
n = linesInCenterSlab.size();
|
n = countCenterSlab;
|
||||||
r = Math.ceil(Math.pow(n, beta));
|
r = Math.ceil(Math.pow(n, beta));
|
||||||
List<Line> lines = RandomSampler.run(linesInCenterSlab, r, linesInCenterSlab.size());
|
List<Line> lines = RandomSampler.run(setOfLines, r);
|
||||||
|
|
||||||
//Für jede Gerade aus der Stichprobe wird der Schnittpunkt mit der medianen
|
//Für jede Gerade aus der Stichprobe wird der Schnittpunkt mit der medianen
|
||||||
//x-Koordinate bestimmt
|
//x-Koordinate bestimmt
|
||||||
List<Double> medianIntersectionAbscissas = new ArrayList<>();
|
List<Double> medianIntersectionAbscissas = new ArrayList<>();
|
||||||
for (Line l : lines) {
|
final double lowerBound = thetaLow;
|
||||||
Double abscissa = estimateMedianIntersectionAbscissas(l);
|
final double upperBound = thetaHigh;
|
||||||
medianIntersections.put(l, abscissa);
|
if (!lines.isEmpty()) {
|
||||||
medianIntersectionAbscissas.add(abscissa);
|
lines.forEach(line -> medianIntersectionAbscissas.add(estimateMedianIntersectionAbscissas(lines, line)));
|
||||||
}
|
}
|
||||||
|
|
||||||
//Rang vom RM-Wert in C
|
//Rang vom RM-Wert in C
|
||||||
k = Math.max(1, Math.min(set.size(), (Math.ceil(n * 0.5) - linesInLeftSlab.size())));
|
k = Math.max(1, Math.min(n, (Math.ceil(n * 0.5) - countLeftSlab)));
|
||||||
|
|
||||||
//berechne k_lo und k_hi
|
//berechne k_lo und k_hi
|
||||||
computeSlabBorders();
|
computeSlabBorders();
|
||||||
|
|
||||||
//Berechne die Elemente mit dem Rang Theta_lo und Theta_hi
|
//Berechne die Elemente mit dem Rang Theta_lo und Theta_hi
|
||||||
|
Collections.sort(medianIntersectionAbscissas);
|
||||||
thetaLow = FastElementSelector.randomizedSelect(medianIntersectionAbscissas, kLow);
|
thetaLow = FastElementSelector.randomizedSelect(medianIntersectionAbscissas, kLow);
|
||||||
thetaHigh = FastElementSelector.randomizedSelect(medianIntersectionAbscissas, kHigh);
|
thetaHigh = FastElementSelector.randomizedSelect(medianIntersectionAbscissas, kHigh);
|
||||||
|
|
||||||
//Für jede Gerade in C wird die Anzahl der Schnittpunkte die im Intervall liegen hochgezählt
|
//Für jede Gerade in C wird die Anzahl der Schnittpunkte die im Intervall liegen hochgezählt
|
||||||
countNumberOfIntersectionsAbscissas();
|
countNumberOfIntersectionsAbscissas(thetaLow, thetaHigh);
|
||||||
|
|
||||||
//verkleinere das Intervall
|
//verkleinere das Intervall
|
||||||
contractIntervals();
|
contractIntervals(thetaLow, thetaHigh);
|
||||||
|
|
||||||
}
|
}
|
||||||
end = System.currentTimeMillis();
|
|
||||||
Logging.logInfo("Zeit: " + ((end - start) / 1000));
|
|
||||||
|
|
||||||
return pepareResult();
|
end = System.currentTimeMillis();
|
||||||
|
Logging.logInfo("=== E N D - R M === " + ((end - start) / 1000));
|
||||||
|
|
||||||
|
return pepareResult(thetaLow, thetaHigh);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -155,18 +152,20 @@ public class RepeatedMedianEstimator implements Algorithm, Flow.Publisher<Data>
|
||||||
* @param sampledLine Stichprobe von Geraden
|
* @param sampledLine Stichprobe von Geraden
|
||||||
* @return mediane x-Koordinate über den Schnittpunkten
|
* @return mediane x-Koordinate über den Schnittpunkten
|
||||||
*/
|
*/
|
||||||
public Double estimateMedianIntersectionAbscissas(Line sampledLine) {
|
public Double estimateMedianIntersectionAbscissas(List<Line> lines, Line sampledLine) {
|
||||||
|
|
||||||
int index = Integer.parseInt(sampledLine.getId());
|
|
||||||
IntersectionCounter intersectionCounter = new IntersectionCounter();
|
IntersectionCounter intersectionCounter = new IntersectionCounter();
|
||||||
List<Double> intersections = intersectionCounter.calculateIntersectionAbscissas(linesInCenterSlab, sampledLine);
|
List<Double> intersections = intersectionCounter.calculateIntersectionAbscissas(lines, sampledLine, original.getLower(), original.getUpper());
|
||||||
|
List<Double> left = intersectionCounter.calculateIntersectionAbscissas(lines, sampledLine, original.getLower(), interval.getLower());
|
||||||
|
List<Double> center = intersectionCounter.calculateIntersectionAbscissas(lines, sampledLine, interval.getLower(), interval.getUpper());
|
||||||
|
|
||||||
double ki = Math.ceil((n - 1) * 0.5) - FastElementSelector.randomizedSelect(countLeftSlab, index);
|
|
||||||
double i = (Math.ceil((Math.sqrt(n) * ki) / FastElementSelector.randomizedSelect(countCenterSlab, index)));
|
double ki = Math.ceil((n - 1) * 0.5) - left.size();
|
||||||
|
double i = (Math.ceil((Math.sqrt(n) * ki) / center.size()));
|
||||||
int accessIndex;
|
int accessIndex;
|
||||||
if (i < 0)
|
if (i < 0)
|
||||||
accessIndex = 0;
|
accessIndex = 0;
|
||||||
else if (i >= intersections.size())
|
else if (i >= intersections.size() && !intersections.isEmpty())
|
||||||
accessIndex = intersections.size() - 1;
|
accessIndex = intersections.size() - 1;
|
||||||
else
|
else
|
||||||
accessIndex = (int) i;
|
accessIndex = (int) i;
|
||||||
|
@ -178,9 +177,9 @@ public class RepeatedMedianEstimator implements Algorithm, Flow.Publisher<Data>
|
||||||
* Berechnet die potenziell neuen Intervallgrenzen.
|
* Berechnet die potenziell neuen Intervallgrenzen.
|
||||||
*/
|
*/
|
||||||
public void computeSlabBorders() {
|
public void computeSlabBorders() {
|
||||||
kLow = Math.max(1, Math.floor(((r * k) / (linesInCenterSlab.size()))
|
kLow = Math.max(1, Math.floor(((r * k) / (countCenterSlab))
|
||||||
- ((3 * Math.sqrt(r)) * (0.5))));
|
- ((3 * Math.sqrt(r)) * (0.5))));
|
||||||
kHigh = Math.min(r, Math.floor(((r * k) / (linesInCenterSlab.size()))
|
kHigh = Math.min(r, Math.floor(((r * k) / (countCenterSlab))
|
||||||
+ ((3 * Math.sqrt(r)) * (0.5))));
|
+ ((3 * Math.sqrt(r)) * (0.5))));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -189,87 +188,56 @@ public class RepeatedMedianEstimator implements Algorithm, Flow.Publisher<Data>
|
||||||
* Berechnet die Anzahl der Schnittpunkte pro Bereich. Insgesammt gibt es drei Bereiche:
|
* Berechnet die Anzahl der Schnittpunkte pro Bereich. Insgesammt gibt es drei Bereiche:
|
||||||
* Im Intervall => (a,b], vor dem Intervall => (a', a], hinter dem Intervall => (b, b'].
|
* Im Intervall => (a,b], vor dem Intervall => (a', a], hinter dem Intervall => (b, b'].
|
||||||
*/
|
*/
|
||||||
public void countNumberOfIntersectionsAbscissas() {
|
public void countNumberOfIntersectionsAbscissas(final double lower, final double upper) {
|
||||||
for (Line line : linesInCenterSlab) {
|
IntersectionComputer instance = IntersectionComputer.getInstance();
|
||||||
List<Double> intersections = intersectionAbscissas.get(line);
|
|
||||||
int index = Integer.parseInt(line.getId());
|
|
||||||
int left = 0;
|
|
||||||
int center = 0;
|
|
||||||
int right = 0;
|
|
||||||
|
|
||||||
for (Double intersection : intersections) {
|
|
||||||
if (intersection <= thetaLow) {
|
|
||||||
left++;
|
|
||||||
} else if (intersection > thetaLow && intersection <= thetaHigh) {
|
|
||||||
center++;
|
|
||||||
} else if (intersection > thetaHigh) {
|
|
||||||
right++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
countLeftSlab.set(index, (double) left);
|
intersectionsInLeftSlab = new HashSet<>(instance.compute(setOfLines, interval.getLower(), lower));
|
||||||
countCenterSlab.set(index, (double) center);
|
intersectionsInCenterSlab = new HashSet<>(instance.compute(setOfLines, lower, upper));
|
||||||
countRightSlab.set(index, (double) right);
|
intersectionsInRightSlab = new HashSet<>(instance.compute(setOfLines, upper, interval.getUpper()));
|
||||||
}
|
|
||||||
|
|
||||||
|
int tmp = new HashSet<>(instance.compute(setOfLines, interval.getLower(), interval.getUpper())).size();
|
||||||
|
countLeftSlab = intersectionsInLeftSlab.size();
|
||||||
|
countCenterSlab = intersectionsInCenterSlab.size();
|
||||||
|
countRightSlab = intersectionsInRightSlab.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TODO bad idea!!!
|
|
||||||
* Verkleinert das aktuelle Intervall. Eines der drei Bereiche wird als neues Intervall gewählt.
|
* Verkleinert das aktuelle Intervall. Eines der drei Bereiche wird als neues Intervall gewählt.
|
||||||
* Auf diesem Intervall werden dann in der nächsten Iteration wieder drei Bereiche bestimmt.
|
* Auf diesem Intervall werden dann in der nächsten Iteration wieder drei Bereiche bestimmt.
|
||||||
*/
|
*/
|
||||||
public void contractIntervals() {
|
public void contractIntervals(final double lower, final double upper) {
|
||||||
for (int i = 0; i < linesInCenterSlab.size(); i++) {
|
double max = Math.max(countLeftSlab, Math.max(countCenterSlab, countRightSlab));
|
||||||
|
|
||||||
double left = countLeftSlab.get(i);
|
boolean newIntervalIsC = countLeftSlab < Math.ceil(n * 0.5) && Math.ceil(n * 0.5) <= countLeftSlab + countCenterSlab;
|
||||||
double center = countCenterSlab.get(i);
|
boolean newIntervalIsL = Math.ceil(n * 0.5) <= countLeftSlab;
|
||||||
double right = countRightSlab.get(i);
|
boolean newIntervalIsR = countLeftSlab + countCenterSlab < Math.ceil(n * 0.5) && Math.ceil(n * 0.5) <= (countLeftSlab + countCenterSlab + countRightSlab);
|
||||||
|
|
||||||
double max = Math.max(left, Math.max(center, right));
|
|
||||||
|
|
||||||
if (left == max) {
|
|
||||||
linesInLeftSlab.add(linesInCenterSlab.get(i));
|
|
||||||
linesInCenterSlab.remove(i);
|
|
||||||
} else if (right == max) {
|
|
||||||
linesInRightSlab.add(linesInCenterSlab.get(i));
|
|
||||||
linesInCenterSlab.remove(i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//wähle C als C
|
//wähle C als C
|
||||||
if (linesInLeftSlab.size() < Math.ceil(n * 0.5) && Math.ceil(n * 0.5) <= linesInLeftSlab.size() + linesInCenterSlab.size()) {
|
if (newIntervalIsC) {
|
||||||
interval.setLower(thetaLow + 0.1);
|
interval.setLower(lower);
|
||||||
interval.setUpper(thetaHigh);
|
interval.setUpper(upper);
|
||||||
}
|
} else if (newIntervalIsL) {
|
||||||
// wähle L als C
|
interval.setUpper(lower);
|
||||||
else if (Math.ceil(n * 0.5) <= linesInLeftSlab.size()) {
|
} else if (newIntervalIsR) {
|
||||||
interval.setUpper(thetaLow);
|
interval.setLower(upper);
|
||||||
}
|
|
||||||
//wähle R als C
|
|
||||||
else if (linesInLeftSlab.size() + linesInCenterSlab.size() < Math.ceil(n * 0.5) && Math.ceil(n * 0.5) <= (linesInLeftSlab.size() + linesInCenterSlab.size() + linesInRightSlab.size())) {
|
|
||||||
interval.setLower(thetaHigh - 0.1);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Line pepareResult() {
|
private Line pepareResult(final double thetaLow, final double thetaHigh) {
|
||||||
if (this.subscriber != null) {
|
slope = thetaLow;
|
||||||
double m = thetaLow;
|
List<Double> potentialYInterceptions = new ArrayList<>();
|
||||||
double b = (-1) * (
|
setOfLines.forEach(line -> {
|
||||||
(linesInCenterSlab.get(0).getM() * (thetaLow)) + linesInCenterSlab.get(0)
|
potentialYInterceptions.add(line.getB() - (slope * line.getM()));
|
||||||
.getB());
|
});
|
||||||
|
|
||||||
slope = m;
|
yInterception = FastElementSelector.randomizedSelect(potentialYInterceptions, Math.floor(potentialYInterceptions.size() * 0.5 ));
|
||||||
yInterception = b;
|
|
||||||
|
if (this.subscriber != null) {
|
||||||
AlgorithmData data = new AlgorithmData();
|
AlgorithmData data = new AlgorithmData();
|
||||||
data.setType(SubscriberType.RM);
|
data.setType(SubscriberType.RM);
|
||||||
data.setLineData(new Line(m, b));
|
data.setLineData(new Line(getSlope(), getyInterception()));
|
||||||
this.subscriber.onNext(data);
|
this.subscriber.onNext(data);
|
||||||
} else {
|
|
||||||
double m = thetaLow;
|
|
||||||
double b = (-1) * ((linesInCenterSlab.get(0).getM() * (thetaLow)) + linesInCenterSlab.get(0).getB());
|
|
||||||
slope = m;
|
|
||||||
yInterception = b;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return new Line(getSlope(), getyInterception());
|
return new Line(getSlope(), getyInterception());
|
||||||
|
@ -341,21 +309,21 @@ public class RepeatedMedianEstimator implements Algorithm, Flow.Publisher<Data>
|
||||||
/**
|
/**
|
||||||
* @return verteilung der Punkte
|
* @return verteilung der Punkte
|
||||||
*/
|
*/
|
||||||
public List<Double> getCountLeftSlab() {
|
public int getCountLeftSlab() {
|
||||||
return countLeftSlab;
|
return countLeftSlab;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return verteilung der Punkte
|
* @return verteilung der Punkte
|
||||||
*/
|
*/
|
||||||
public List<Double> getCountCenterSlab() {
|
public int getCountCenterSlab() {
|
||||||
return countCenterSlab;
|
return countCenterSlab;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return verteilung der Punkte
|
* @return verteilung der Punkte
|
||||||
*/
|
*/
|
||||||
public List<Double> getCountRightSlab() {
|
public int getCountRightSlab() {
|
||||||
return countRightSlab;
|
return countRightSlab;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,15 +8,9 @@ import de.wwwu.awolf.model.communication.Data;
|
||||||
import de.wwwu.awolf.model.communication.SubscriberType;
|
import de.wwwu.awolf.model.communication.SubscriberType;
|
||||||
import de.wwwu.awolf.presenter.Presenter;
|
import de.wwwu.awolf.presenter.Presenter;
|
||||||
import de.wwwu.awolf.presenter.algorithms.Algorithm;
|
import de.wwwu.awolf.presenter.algorithms.Algorithm;
|
||||||
import de.wwwu.awolf.presenter.util.BinomialCoeffizient;
|
import de.wwwu.awolf.presenter.util.*;
|
||||||
import de.wwwu.awolf.presenter.util.FastElementSelector;
|
|
||||||
import de.wwwu.awolf.presenter.util.IntersectionCounter;
|
|
||||||
import de.wwwu.awolf.presenter.util.RandomSampler;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.*;
|
||||||
import java.util.LinkedHashSet;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Set;
|
|
||||||
import java.util.concurrent.Flow;
|
import java.util.concurrent.Flow;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -32,12 +26,8 @@ public class TheilSenEstimator implements Algorithm, Flow.Publisher<Data> {
|
||||||
private final double NEGATIV_INF = -99999.0;
|
private final double NEGATIV_INF = -99999.0;
|
||||||
private final double EPSILON = 0.00001;
|
private final double EPSILON = 0.00001;
|
||||||
private List<Line> setOfLines;
|
private List<Line> setOfLines;
|
||||||
private List<Point> setOfIntersections;
|
|
||||||
private List<Point> intervalIntersections;
|
private List<Point> intervalIntersections;
|
||||||
private List<Double> sampledIntersections;
|
private List<Point> sampledIntersections;
|
||||||
//wird benötigt um den y Achsenabschnitt zu Berechnen
|
|
||||||
private List<Double> yCoordinates;
|
|
||||||
private List<Double> xCoordinates;
|
|
||||||
//Hilfsvariablen (siehe original Paper)
|
//Hilfsvariablen (siehe original Paper)
|
||||||
private double j;
|
private double j;
|
||||||
private int jA;
|
private int jA;
|
||||||
|
@ -53,24 +43,21 @@ public class TheilSenEstimator implements Algorithm, Flow.Publisher<Data> {
|
||||||
private double slope;
|
private double slope;
|
||||||
private double yInterception;
|
private double yInterception;
|
||||||
private Flow.Subscriber<? super AlgorithmData> subscriber;
|
private Flow.Subscriber<? super AlgorithmData> subscriber;
|
||||||
|
private Collection<Point> setOfIntersections;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Konstruktor
|
* Konstruktor
|
||||||
*
|
*
|
||||||
* @param setOfLines Liste der Geraden
|
* @param setOfLines Liste der Geraden
|
||||||
* @param setOfIntersections Liste der Schnittpunkte
|
|
||||||
* @param presenter Presenter (Beobachter)
|
* @param presenter Presenter (Beobachter)
|
||||||
*/
|
*/
|
||||||
public TheilSenEstimator(List<Line> setOfLines, List<Point> setOfIntersections, Presenter presenter) {
|
public TheilSenEstimator(List<Line> setOfLines, Presenter presenter) {
|
||||||
|
|
||||||
this.setOfLines = new ArrayList<>(setOfLines);
|
this.setOfLines = new ArrayList<>(setOfLines);
|
||||||
this.setOfIntersections = new ArrayList<>(setOfIntersections);
|
this.setOfIntersections = new HashSet<>();
|
||||||
this.intervalIntersections = new ArrayList<>(setOfIntersections);
|
|
||||||
|
|
||||||
this.n = setOfLines.size();
|
this.n = setOfLines.size();
|
||||||
this.sampledIntersections = new ArrayList<>();
|
this.sampledIntersections = new ArrayList<>();
|
||||||
this.yCoordinates = new ArrayList<>();
|
|
||||||
this.xCoordinates = new ArrayList<>();
|
|
||||||
this.N = BinomialCoeffizient.run(n, 2);
|
this.N = BinomialCoeffizient.run(n, 2);
|
||||||
//this.k = Integer.valueOf((int) (N * 0.5)) - 1;
|
//this.k = Integer.valueOf((int) (N * 0.5)) - 1;
|
||||||
this.k = (int) (N / 2);
|
this.k = (int) (N / 2);
|
||||||
|
@ -83,10 +70,9 @@ public class TheilSenEstimator implements Algorithm, Flow.Publisher<Data> {
|
||||||
* Konstruktor
|
* Konstruktor
|
||||||
*
|
*
|
||||||
* @param setOfLines Liste der Geraden
|
* @param setOfLines Liste der Geraden
|
||||||
* @param setOfIntersections Liste der Schnittpunkte
|
|
||||||
*/
|
*/
|
||||||
public TheilSenEstimator(List<Line> setOfLines, List<Point> setOfIntersections) {
|
public TheilSenEstimator(List<Line> setOfLines) {
|
||||||
this(setOfLines, setOfIntersections, null);
|
this(setOfLines, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -105,7 +91,7 @@ public class TheilSenEstimator implements Algorithm, Flow.Publisher<Data> {
|
||||||
break;
|
break;
|
||||||
} else {
|
} else {
|
||||||
//Anzahl der Schnittpunkte im Intervall [-Inf, a)
|
//Anzahl der Schnittpunkte im Intervall [-Inf, a)
|
||||||
int numberOfIntersections = getOpenIntervalSize(NEGATIV_INF, interval.getLower(), setOfIntersections);
|
int numberOfIntersections = getOpenIntervalSize(NEGATIV_INF, interval.getLower());
|
||||||
|
|
||||||
//Randomized Interpolating Search
|
//Randomized Interpolating Search
|
||||||
j = (r / N) * (double) (k - numberOfIntersections);
|
j = (r / N) * (double) (k - numberOfIntersections);
|
||||||
|
@ -119,20 +105,27 @@ public class TheilSenEstimator implements Algorithm, Flow.Publisher<Data> {
|
||||||
do {
|
do {
|
||||||
//zufällige Stichprobe
|
//zufällige Stichprobe
|
||||||
sampledIntersections = RandomSampler.run(intervalIntersections, r);
|
sampledIntersections = RandomSampler.run(intervalIntersections, r);
|
||||||
aVariant = FastElementSelector.randomizedSelect(sampledIntersections, jA);
|
|
||||||
bVariant = FastElementSelector.randomizedSelect(sampledIntersections, jB);
|
aVariant = FastElementSelector.randomizedSelect(getIntersectionAbscissas(sampledIntersections), jA);
|
||||||
|
bVariant = FastElementSelector.randomizedSelect(getIntersectionAbscissas(sampledIntersections), jB);
|
||||||
} while (!checkCondition());
|
} while (!checkCondition());
|
||||||
|
|
||||||
interval.setLower(aVariant);
|
interval.setLower(aVariant);
|
||||||
interval.setUpper(bVariant);
|
interval.setUpper(bVariant);
|
||||||
intervalIntersections = getOpenIntervalElements(interval.getLower(), interval.getUpper());
|
intervalIntersections = getOpenIntervalElements(interval.getLower(), interval.getUpper());
|
||||||
N = getOpenIntervalSize(interval.getLower(), interval.getUpper(), intervalIntersections);
|
N = getOpenIntervalSize(interval.getLower(), interval.getUpper());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return pepareResult();
|
return pepareResult();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private List<Double> getIntersectionAbscissas(List<Point> interections) {
|
||||||
|
List<Double> abscissas = new ArrayList<>();
|
||||||
|
interections.forEach(e -> abscissas.add(e.getX()));
|
||||||
|
return abscissas;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Diese Funktion überprüft ob die Bedingung für das Interval erfüllt ist. Dabei muss der k-te
|
* Diese Funktion überprüft ob die Bedingung für das Interval erfüllt ist. Dabei muss der k-te
|
||||||
|
@ -183,15 +176,10 @@ public class TheilSenEstimator implements Algorithm, Flow.Publisher<Data> {
|
||||||
* @param b obere Grenze des Intrvals
|
* @param b obere Grenze des Intrvals
|
||||||
* @return Anzahl der Schnittpunkte im Interval (a,b)
|
* @return Anzahl der Schnittpunkte im Interval (a,b)
|
||||||
*/
|
*/
|
||||||
public int getOpenIntervalSize(double a, double b, List<Point> set) {
|
public int getOpenIntervalSize(double a, double b) {
|
||||||
int counter = 0;
|
Collection<Point> intersections = IntersectionComputer.getInstance().compute(setOfLines, a, b);
|
||||||
for (int i = 0; i < set.size(); i++) {
|
setOfIntersections.addAll(intersections);
|
||||||
Point x = set.get(i);
|
return intersections.size();
|
||||||
if (x.getX() > a && x.getX() < b) {
|
|
||||||
counter++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return counter;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -227,17 +215,19 @@ public class TheilSenEstimator implements Algorithm, Flow.Publisher<Data> {
|
||||||
resultAbscissas.add(p.getX());
|
resultAbscissas.add(p.getX());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
List<Double> yCoords = new ArrayList<>();
|
||||||
|
|
||||||
for (Point p : setOfIntersections) {
|
for (Point p : setOfIntersections) {
|
||||||
yCoordinates.add(p.getY());
|
yCoords.add(p.getY());
|
||||||
}
|
}
|
||||||
|
|
||||||
double pseudoIndex = getOpenIntervalSize(NEGATIV_INF, interval.getLower(), setOfIntersections) * 1.0;
|
double pseudoIndex = getOpenIntervalSize(NEGATIV_INF, interval.getLower()) * 1.0;
|
||||||
m = FastElementSelector.randomizedSelect(resultAbscissas, k - pseudoIndex);
|
m = FastElementSelector.randomizedSelect(resultAbscissas, k - pseudoIndex);
|
||||||
|
|
||||||
Set<Double> unique = new LinkedHashSet<>(yCoordinates);
|
Set<Double> unique = new LinkedHashSet<>(yCoords);
|
||||||
yCoordinates.clear();
|
yCoords.clear();
|
||||||
yCoordinates.addAll(unique);
|
yCoords.addAll(unique);
|
||||||
b = FastElementSelector.randomizedSelect(yCoordinates, yCoordinates.size() * 0.5) * -1;
|
b = FastElementSelector.randomizedSelect(yCoords, yCoords.size() * 0.5) * -1;
|
||||||
slope = m;
|
slope = m;
|
||||||
yInterception = b;
|
yInterception = b;
|
||||||
|
|
||||||
|
|
|
@ -16,13 +16,12 @@ import java.util.Map;
|
||||||
*/
|
*/
|
||||||
public class DatasetGenerator {
|
public class DatasetGenerator {
|
||||||
|
|
||||||
private static SecureRandom random;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Konstruktor
|
* Konstruktor
|
||||||
*/
|
*/
|
||||||
private DatasetGenerator() {
|
private DatasetGenerator() {
|
||||||
random = new SecureRandom();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -34,6 +33,7 @@ public class DatasetGenerator {
|
||||||
* @return Liste des Geraden
|
* @return Liste des Geraden
|
||||||
*/
|
*/
|
||||||
public static List<Line> generateDataLines(List<Line> lines, int n) {
|
public static List<Line> generateDataLines(List<Line> lines, int n) {
|
||||||
|
|
||||||
double m = 5d;
|
double m = 5d;
|
||||||
double b = 0d;
|
double b = 0d;
|
||||||
|
|
||||||
|
@ -42,6 +42,7 @@ public class DatasetGenerator {
|
||||||
|
|
||||||
//speichere die Koordinaten in einer HashMap, damit keine Punkte
|
//speichere die Koordinaten in einer HashMap, damit keine Punkte
|
||||||
//entstehen deren x-Koordinate zu sehr beieinander liegt.
|
//entstehen deren x-Koordinate zu sehr beieinander liegt.
|
||||||
|
SecureRandom random = new SecureRandom();
|
||||||
while (size < n) {
|
while (size < n) {
|
||||||
double y = random.nextGaussian();
|
double y = random.nextGaussian();
|
||||||
double signal = m * y + b;
|
double signal = m * y + b;
|
||||||
|
@ -54,8 +55,8 @@ public class DatasetGenerator {
|
||||||
}
|
}
|
||||||
|
|
||||||
int idx = lines.size();
|
int idx = lines.size();
|
||||||
for (Double d : points.keySet()) {
|
for (Map.Entry<Double, Double> d : points.entrySet()) {
|
||||||
Line line = new Line(d, points.get(d));
|
Line line = new Line(d.getKey(), d.getValue());
|
||||||
line.setId(idx + "");
|
line.setId(idx + "");
|
||||||
lines.add(line);
|
lines.add(line);
|
||||||
idx++;
|
idx++;
|
||||||
|
|
|
@ -2,7 +2,6 @@ package de.wwwu.awolf.presenter.data.io;
|
||||||
|
|
||||||
import com.opencsv.CSVWriter;
|
import com.opencsv.CSVWriter;
|
||||||
import de.wwwu.awolf.model.Line;
|
import de.wwwu.awolf.model.Line;
|
||||||
import de.wwwu.awolf.model.communication.Data;
|
|
||||||
import de.wwwu.awolf.presenter.util.Logging;
|
import de.wwwu.awolf.presenter.util.Logging;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
@ -43,7 +42,7 @@ public class DataExporter implements Runnable {
|
||||||
CSVWriter writer = null;
|
CSVWriter writer = null;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
writer = new CSVWriter(new FileWriter(file), ',');
|
writer = new CSVWriter(new FileWriter(file));
|
||||||
String[] entries = new String[3];
|
String[] entries = new String[3];
|
||||||
for (Line line : lines) {
|
for (Line line : lines) {
|
||||||
entries[0] = line.getId();
|
entries[0] = line.getId();
|
||||||
|
|
|
@ -24,15 +24,15 @@ public class AlgorithmComparison {
|
||||||
private final Map<Algorithm.Type, Algorithm> algorithmMap;
|
private final Map<Algorithm.Type, Algorithm> algorithmMap;
|
||||||
private final CompletionService<Line> completionService;
|
private final CompletionService<Line> completionService;
|
||||||
|
|
||||||
public AlgorithmComparison(List<Algorithm.Type> types, List<Line> lines, List<Point> nodes) {
|
public AlgorithmComparison(List<Algorithm.Type> types, List<Line> lines) {
|
||||||
this.types = types;
|
this.types = types;
|
||||||
this.executorService = Executors.newFixedThreadPool(3);
|
this.executorService = Executors.newFixedThreadPool(3);
|
||||||
completionService = new ExecutorCompletionService<>(this.executorService);
|
completionService = new ExecutorCompletionService<>(this.executorService);
|
||||||
|
|
||||||
algorithmMap = new EnumMap<>(Algorithm.Type.class);
|
algorithmMap = new EnumMap<>(Algorithm.Type.class);
|
||||||
algorithmMap.put(Algorithm.Type.LMS, new LeastMedianOfSquaresEstimator(lines, nodes));
|
algorithmMap.put(Algorithm.Type.LMS, new LeastMedianOfSquaresEstimator(lines));
|
||||||
algorithmMap.put(Algorithm.Type.RM, new RepeatedMedianEstimator(lines));
|
algorithmMap.put(Algorithm.Type.RM, new RepeatedMedianEstimator(lines));
|
||||||
algorithmMap.put(Algorithm.Type.TS, new TheilSenEstimator(lines, nodes));
|
algorithmMap.put(Algorithm.Type.TS, new TheilSenEstimator(lines));
|
||||||
algorithmMap.put(Algorithm.Type.NAIV_LMS, new NaivLeastMedianOfSquaresEstimator(lines));
|
algorithmMap.put(Algorithm.Type.NAIV_LMS, new NaivLeastMedianOfSquaresEstimator(lines));
|
||||||
algorithmMap.put(Algorithm.Type.NAIV_RM, new NaivRepeatedMedianEstimator(lines));
|
algorithmMap.put(Algorithm.Type.NAIV_RM, new NaivRepeatedMedianEstimator(lines));
|
||||||
algorithmMap.put(Algorithm.Type.NAIV_TS, new NaivTheilSenEstimator(lines));
|
algorithmMap.put(Algorithm.Type.NAIV_TS, new NaivTheilSenEstimator(lines));
|
||||||
|
|
|
@ -67,9 +67,6 @@ public class EvaluateAlgorithms implements Runnable, Flow.Publisher<Data> {
|
||||||
this.type = type;
|
this.type = type;
|
||||||
this.iterations = n;
|
this.iterations = n;
|
||||||
this.alg = alg;
|
this.alg = alg;
|
||||||
|
|
||||||
IntersectionComputer computer = new IntersectionComputer(arrangement.getLines());
|
|
||||||
arrangement.setNodes(computer.compute());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -93,14 +90,11 @@ public class EvaluateAlgorithms implements Runnable, Flow.Publisher<Data> {
|
||||||
|
|
||||||
this.type = type;
|
this.type = type;
|
||||||
this.alg = alg;
|
this.alg = alg;
|
||||||
|
|
||||||
IntersectionComputer computer = new IntersectionComputer(arrangement.getLines());
|
|
||||||
arrangement.setNodes(computer.compute());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private Map<Algorithm.Type, Map<String, String>> benchmarkSameEstimator(final Algorithm.Type advanced, final Algorithm.Type naiv) {
|
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());
|
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()));
|
AlgorithmComparison comparison = new AlgorithmComparison(Arrays.asList(naiv, advanced), Collections.unmodifiableList(arrangement.getLines()));
|
||||||
ComparisonResult comparisonResult = comparison.compare();
|
ComparisonResult comparisonResult = comparison.compare();
|
||||||
|
|
||||||
|
|
||||||
|
@ -115,11 +109,10 @@ public class EvaluateAlgorithms implements Runnable, Flow.Publisher<Data> {
|
||||||
|
|
||||||
private Map<Algorithm.Type, Map<String, String>> benchmarkDifferentEstimators(List<Algorithm.Type> types) {
|
private Map<Algorithm.Type, Map<String, String>> benchmarkDifferentEstimators(List<Algorithm.Type> types) {
|
||||||
Logging.logInfo("AlgorithmComparison with Types: " + types);
|
Logging.logInfo("AlgorithmComparison with Types: " + types);
|
||||||
AlgorithmComparison comparison = new AlgorithmComparison(types, Collections.unmodifiableList(arrangement.getLines()), Collections.unmodifiableList(arrangement.getNodes()));
|
AlgorithmComparison comparison = new AlgorithmComparison(types, Collections.unmodifiableList(arrangement.getLines()));
|
||||||
ComparisonResult comparisonResult = comparison.compare();
|
ComparisonResult comparisonResult = comparison.compare();
|
||||||
|
|
||||||
Map<String, String> multipleResults = new HashMap<>();
|
types.forEach(typeEntry -> this.resultMapping.put(typeEntry, getPercentigeErrorBasedMeasure(arrangement.getLines(), comparisonResult, typeEntry)));
|
||||||
types.forEach(type -> this.resultMapping.put(type, getPercentigeErrorBasedMeasure(arrangement.getLines(), comparisonResult, type)));
|
|
||||||
Logging.logInfo("finished with execution of the algorithms.");
|
Logging.logInfo("finished with execution of the algorithms.");
|
||||||
return this.resultMapping;
|
return this.resultMapping;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,159 +0,0 @@
|
||||||
package de.wwwu.awolf.presenter.evaluation.measures;
|
|
||||||
|
|
||||||
import de.wwwu.awolf.model.Line;
|
|
||||||
import de.wwwu.awolf.model.communication.Data;
|
|
||||||
import de.wwwu.awolf.model.communication.SubscriberType;
|
|
||||||
import de.wwwu.awolf.model.communication.TypeData;
|
|
||||||
import de.wwwu.awolf.presenter.Presenter;
|
|
||||||
import de.wwwu.awolf.presenter.util.Logging;
|
|
||||||
import org.opencv.core.*;
|
|
||||||
import org.opencv.imgcodecs.Imgcodecs;
|
|
||||||
import org.opencv.imgproc.Imgproc;
|
|
||||||
|
|
||||||
import javax.swing.*;
|
|
||||||
import java.awt.image.BufferedImage;
|
|
||||||
import java.awt.image.DataBufferByte;
|
|
||||||
import java.io.File;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.concurrent.Flow;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Implementierung verschiedener Algorithmen zur Berechnung von Ausgleichsgeraden.
|
|
||||||
*
|
|
||||||
* @Author: Armin Wolf
|
|
||||||
* @Email: a_wolf28@uni-muenster.de
|
|
||||||
* @Date: 17.09.2017.
|
|
||||||
*/
|
|
||||||
public class PictureProcessor implements Flow.Publisher<Data> {
|
|
||||||
|
|
||||||
private Mat image;
|
|
||||||
private Mat contour;
|
|
||||||
private Presenter presenter;
|
|
||||||
private File file;
|
|
||||||
private ArrayList<MatOfPoint> contours;
|
|
||||||
private double contourLength;
|
|
||||||
private Flow.Subscriber<? super Data> subscriber;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Konstruktor
|
|
||||||
*
|
|
||||||
* @param presenter Presenter
|
|
||||||
* @param file Bilddatei
|
|
||||||
*/
|
|
||||||
public PictureProcessor(Presenter presenter, File file) {
|
|
||||||
this.file = file;
|
|
||||||
this.presenter = presenter;
|
|
||||||
subscribe(presenter);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* startet den Import des Bild und die Vorverarbeitung
|
|
||||||
*/
|
|
||||||
public void run() {
|
|
||||||
image = Imgcodecs.imread(file.getAbsolutePath());
|
|
||||||
contour = process(image);
|
|
||||||
contourLength = image.width() * 0.3;
|
|
||||||
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);
|
|
||||||
Imgcodecs.imwrite(file.getAbsolutePath().substring(0, file.getAbsolutePath().lastIndexOf(".")) + "-orig.png", image);
|
|
||||||
Imgproc.cvtColor(image, source, Imgproc.COLOR_BGR2GRAY);
|
|
||||||
Imgcodecs.imwrite(file.getAbsolutePath().substring(0, file.getAbsolutePath().lastIndexOf(".")) + "-Greyscale.png", source);
|
|
||||||
Imgproc.GaussianBlur(source, threshold, new Size(3, 3), 0, 0);
|
|
||||||
Imgproc.Canny(threshold, source, 300, 600, 5, true);
|
|
||||||
Imgcodecs.imwrite(file.getAbsolutePath().substring(0, file.getAbsolutePath().lastIndexOf(".")) + "-Canny.png", source);
|
|
||||||
//Konturen berechnen und filtern
|
|
||||||
contours = new ArrayList<>();
|
|
||||||
Imgproc.findContours(source, contours, new Mat(), Imgproc.RETR_TREE, Imgproc.CHAIN_APPROX_SIMPLE, new Point(0, 0));
|
|
||||||
Mat viscont = new Mat(source.size(), source.type());
|
|
||||||
double minArea = 50;
|
|
||||||
double maxArea = 0.2 * image.cols() * image.rows();
|
|
||||||
for (int i = 0; i < contours.size(); i++) {
|
|
||||||
double acutualArea = Imgproc.contourArea(contours.get(i));
|
|
||||||
if (minArea < acutualArea && maxArea > acutualArea) {
|
|
||||||
Imgproc.drawContours(viscont, contours, i, new Scalar(255, 0, 0), 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Imgcodecs.imwrite(file.getAbsolutePath().substring(0, file.getAbsolutePath().lastIndexOf(".")) + "-Contour.png", viscont);
|
|
||||||
Mat resized = new Mat();
|
|
||||||
Imgproc.resize(viscont, resized, new Size(560, 560));
|
|
||||||
SwingUtilities.invokeLater(() -> {
|
|
||||||
JDialog dialog = new JDialog();
|
|
||||||
dialog.setSize(560, 560);
|
|
||||||
JLabel label = new JLabel();
|
|
||||||
label.setSize(560, 560);
|
|
||||||
label.setIcon(new ImageIcon(toBufferedImage(resized)));
|
|
||||||
dialog.add(label);
|
|
||||||
dialog.setVisible(true);
|
|
||||||
});
|
|
||||||
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) {
|
|
||||||
type = BufferedImage.TYPE_3BYTE_BGR;
|
|
||||||
}
|
|
||||||
int bufferSize = m.channels() * m.cols() * m.rows();
|
|
||||||
byte[] b = new byte[bufferSize];
|
|
||||||
m.get(0, 0, b); // get all the pixels
|
|
||||||
BufferedImage image = new BufferedImage(m.cols(), m.rows(), type);
|
|
||||||
final byte[] targetPixels = ((DataBufferByte) image.getRaster().getDataBuffer()).getData();
|
|
||||||
System.arraycopy(b, 0, targetPixels, 0, b.length);
|
|
||||||
return image;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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;
|
|
||||||
double maxArea = 0.2 * image.cols() * image.rows();
|
|
||||||
int id = 0;
|
|
||||||
for (int j = 0; j < contours.size(); j++) {
|
|
||||||
Point[] p = contours.get(j).toArray();
|
|
||||||
double acutualArea = Imgproc.contourArea(contours.get(j));
|
|
||||||
if (minArea < acutualArea && maxArea > acutualArea) {
|
|
||||||
for (int i = 0; i < p.length; i++) {
|
|
||||||
Line line = new Line(-1 * (500 - p[i].x), p[i].y);
|
|
||||||
line.setId("" + id++);
|
|
||||||
presenter.getModel().getLines().add(line);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TypeData data = new TypeData();
|
|
||||||
data.setType(SubscriberType.PICTURE);
|
|
||||||
this.subscriber.onNext(data);
|
|
||||||
});
|
|
||||||
t.start();
|
|
||||||
try {
|
|
||||||
t.join();
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
Logging.logError(e.getMessage(), e);
|
|
||||||
Thread.currentThread().interrupt();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void subscribe(Flow.Subscriber<? super Data> subscriber) {
|
|
||||||
this.subscriber = subscriber;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -21,6 +21,7 @@ public class FastElementSelector {
|
||||||
* @return das Element
|
* @return das Element
|
||||||
*/
|
*/
|
||||||
public static Double randomizedSelect(List<Double> a, double i) {
|
public static Double randomizedSelect(List<Double> a, double i) {
|
||||||
|
|
||||||
int start = 0;
|
int start = 0;
|
||||||
int end = a.size() - 1;
|
int end = a.size() - 1;
|
||||||
|
|
||||||
|
|
|
@ -1,13 +1,16 @@
|
||||||
package de.wwwu.awolf.presenter.util;
|
package de.wwwu.awolf.presenter.util;
|
||||||
|
|
||||||
import de.wwwu.awolf.model.Interval;
|
import com.google.common.collect.Lists;
|
||||||
|
import com.google.common.collect.Sets;
|
||||||
import de.wwwu.awolf.model.Line;
|
import de.wwwu.awolf.model.Line;
|
||||||
import de.wwwu.awolf.model.Point;
|
import de.wwwu.awolf.model.Point;
|
||||||
|
import org.jfree.util.Log;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.*;
|
||||||
import java.util.List;
|
import java.util.concurrent.ForkJoinPool;
|
||||||
import java.util.Set;
|
import java.util.concurrent.ForkJoinTask;
|
||||||
import java.util.TreeSet;
|
import java.util.concurrent.RecursiveTask;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implementierung verschiedener Algorithmen zur Berechnung von Ausgleichsgeraden.
|
* Implementierung verschiedener Algorithmen zur Berechnung von Ausgleichsgeraden.
|
||||||
|
@ -18,32 +21,68 @@ import java.util.TreeSet;
|
||||||
*/
|
*/
|
||||||
public class IntersectionComputer {
|
public class IntersectionComputer {
|
||||||
|
|
||||||
private List<Line> lines;
|
private static IntersectionComputer instance;
|
||||||
private Set<Point> intersections;
|
|
||||||
|
|
||||||
private Double xMinimum;
|
|
||||||
private Double xMaximum;
|
|
||||||
private Double yMinimum;
|
|
||||||
private Double yMaximum;
|
|
||||||
|
|
||||||
private Thread[] worker;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Konstruktor
|
* Konstruktor
|
||||||
*
|
|
||||||
* @param lines Liste der Geraden
|
|
||||||
*/
|
*/
|
||||||
public IntersectionComputer(List<Line> lines) {
|
private IntersectionComputer() {
|
||||||
this.lines = lines;
|
|
||||||
this.worker = new Thread[4];
|
|
||||||
this.intersections = new TreeSet<>();
|
|
||||||
|
|
||||||
xMinimum = Double.MAX_VALUE;
|
|
||||||
xMaximum = Double.MIN_VALUE;
|
|
||||||
yMinimum = Double.MAX_VALUE;
|
|
||||||
yMaximum = Double.MIN_VALUE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private class RecursiveComputationTask extends RecursiveTask<Collection<Point>> {
|
||||||
|
|
||||||
|
private static final int THRESHOLD = 20;
|
||||||
|
|
||||||
|
private final List<Line> lines;
|
||||||
|
private final List<Line> fullList;
|
||||||
|
private final double lower;
|
||||||
|
private final double upper;
|
||||||
|
|
||||||
|
public RecursiveComputationTask(final List<Line> fullList, final List<Line> lines, final double lower, final double upper) {
|
||||||
|
this.lines = lines;
|
||||||
|
this.fullList = fullList;
|
||||||
|
this.lower = lower;
|
||||||
|
this.upper = upper;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Collection<Point> compute() {
|
||||||
|
if (this.lines.isEmpty()){
|
||||||
|
return Collections.emptyList();
|
||||||
|
} else if (this.lines.size() > THRESHOLD) {
|
||||||
|
Logging.logInfo("Bigger than threshold, split into subtask.");
|
||||||
|
return ForkJoinTask.invokeAll(createSubTask()).stream().map(ForkJoinTask::join).flatMap(Collection::stream).collect(Collectors.toList());
|
||||||
|
} else {
|
||||||
|
return work(this.lines, this.lines, this.lower, this.upper);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Collection<RecursiveComputationTask> createSubTask() {
|
||||||
|
List<RecursiveComputationTask> dividedTasks = new ArrayList<>();
|
||||||
|
dividedTasks.add(new RecursiveComputationTask(this.fullList, this.lines.subList(0, this.lines.size() / 2), this.lower, this.upper));
|
||||||
|
dividedTasks.add(new RecursiveComputationTask(this.fullList, this.lines.subList(this.lines.size() / 2, this.lines.size()), this.lower, this.upper));
|
||||||
|
return dividedTasks;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Collection<Point> work(List<Line> fullList, List<Line> lines, double lower, double higher) {
|
||||||
|
Set<Point> points = new HashSet<>();
|
||||||
|
List<List<Line>> lists = Lists.cartesianProduct(new ArrayList<>(fullList), new ArrayList<>(lines));
|
||||||
|
lists.forEach(entry -> {
|
||||||
|
if (entry.get(0).doIntersect(entry.get(1), lower, upper)) {
|
||||||
|
Point intersect = entry.get(0).intersect(entry.get(1));
|
||||||
|
if (intersect.getX() > lower && intersect.getX() <= higher) {
|
||||||
|
points.add(intersect);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return new HashSet<>(points);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Berechnet zu einer gegebenen Menge von dualen Geraden die Schnittpunkte. Dafür wird ein modifizierter Merge-Sort
|
* 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
|
* Algorithmus verwendett. Um die Performance zu steigern wird die Berechnung ab einer passenden Größe auf vier
|
||||||
|
@ -53,141 +92,21 @@ public class IntersectionComputer {
|
||||||
* @param higher obere Schranke
|
* @param higher obere Schranke
|
||||||
* @return Liste der Schnittpunkte
|
* @return Liste der Schnittpunkte
|
||||||
*/
|
*/
|
||||||
public ArrayList<Point> compute(final double lower, final double higher) {
|
public Collection<Point> compute(final List<Line> lines, final double lower, final double higher) {
|
||||||
|
Logging.logInfo("Open ForkJoinPool");
|
||||||
|
ForkJoinPool pool = ForkJoinPool.commonPool();
|
||||||
|
RecursiveComputationTask recursiveComputationTask = new RecursiveComputationTask(lines, lines, lower, higher);
|
||||||
|
pool.execute(recursiveComputationTask);
|
||||||
|
return recursiveComputationTask.join();
|
||||||
|
}
|
||||||
|
|
||||||
if (lines.size() > 16) {
|
public static IntersectionComputer getInstance() {
|
||||||
worker[0] = new Thread(() -> {
|
if (instance == null) {
|
||||||
work(lines.subList(0, (lines.size() / 4)), lower, higher);
|
instance = new IntersectionComputer();
|
||||||
});
|
Logging.logInfo("Created instance of IntersectionComputer");
|
||||||
worker[0].start();
|
|
||||||
worker[1] = new Thread(() -> {
|
|
||||||
work(lines.subList((lines.size() / 4) + 1, (lines.size() / 2)), lower, higher);
|
|
||||||
});
|
|
||||||
worker[1].start();
|
|
||||||
worker[2] = new Thread(() -> {
|
|
||||||
work(lines.subList((lines.size() / 2) + 1, 3 * (lines.size() / 4)), lower, higher);
|
|
||||||
});
|
|
||||||
worker[2].start();
|
|
||||||
worker[3] = new Thread(() -> {
|
|
||||||
work(lines.subList(3 * (lines.size() / 4) + 1, (lines.size())), lower, higher);
|
|
||||||
});
|
|
||||||
worker[3].start();
|
|
||||||
|
|
||||||
|
|
||||||
for (Thread t : worker) {
|
|
||||||
try {
|
|
||||||
t.join();
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
Logging.logError(e.getMessage(), e);
|
|
||||||
Thread.currentThread().interrupt();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
work(lines, lower, higher);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return new ArrayList<>(intersections);
|
return instance;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 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);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void work(List<Line> lines, double lower, double higher) {
|
|
||||||
IntersectionCounter counter = new IntersectionCounter();
|
|
||||||
int count = counter.run(lines, new Interval(lower, higher));
|
|
||||||
ArrayList<Point> points = counter.calculateIntersectionAbscissas();
|
|
||||||
for (Point p : points) {
|
|
||||||
if (!isFound(p)) {
|
|
||||||
addIntersection(p);
|
|
||||||
setRanges(p);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Synchronisierter Zugriff auf die Liste der Geraden
|
|
||||||
*
|
|
||||||
* @return Liste der Geraden
|
|
||||||
*/
|
|
||||||
public synchronized List<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) {
|
|
||||||
return intersections.contains(p);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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;
|
|
||||||
yMaximum = (point.getY() > yMaximum) ? point.getY() : yMaximum;
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -210,20 +210,43 @@ public class IntersectionCounter {
|
||||||
* @param sampledLine eine spezielle Gerade
|
* @param sampledLine eine spezielle Gerade
|
||||||
* @return Liste mit x Koordinaten der Schnittpunkte
|
* @return Liste mit x Koordinaten der Schnittpunkte
|
||||||
*/
|
*/
|
||||||
public List<Double> calculateIntersectionAbscissas(List<Line> set, Line sampledLine) {
|
public List<Double> calculateIntersectionAbscissas(List<Line> set, Line sampledLine, double lower, double upper) {
|
||||||
List<Line> lines = new LinkedList<>(set);
|
List<Line> lines = new LinkedList<>(set);
|
||||||
List<Double> intersections = new ArrayList<>();
|
Set<Double> intersections = new HashSet<>();
|
||||||
double intersection;
|
|
||||||
|
|
||||||
for (Line line : lines) {
|
for (Line line : lines) {
|
||||||
if (line != sampledLine) {
|
if (line != sampledLine) {
|
||||||
intersection = (line.getB() - sampledLine.getB()) / (sampledLine.getM() - line.getM());
|
if (sampledLine.doIntersect(line, lower, upper)){
|
||||||
intersections.add(intersection);
|
intersections.add(sampledLine.intersect(line).getX());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return intersections;
|
return new ArrayList<>(intersections);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Berechnet die Schnittpunkte zwischen einer gegebenen Gerade und einer Menge an Geraden.
|
||||||
|
*
|
||||||
|
* @param set Menge an Geraden
|
||||||
|
* @param sampledLine eine spezielle Gerade
|
||||||
|
* @return Liste mit x Koordinaten der Schnittpunkte
|
||||||
|
*/
|
||||||
|
public List<Double> calculateIntersectionYInterception(List<Line> set, Line sampledLine, double lower, double upper) {
|
||||||
|
List<Line> lines = new LinkedList<>(set);
|
||||||
|
Set<Double> intersections = new HashSet<>();
|
||||||
|
|
||||||
|
for (Line line : lines) {
|
||||||
|
if (line != sampledLine) {
|
||||||
|
if (sampledLine.doIntersect(line, lower, upper)){
|
||||||
|
intersections.add(sampledLine.intersect(line).getY());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return new ArrayList<>(intersections);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,9 @@ import org.apache.log4j.Logger;
|
||||||
public class Logging {
|
public class Logging {
|
||||||
private static Logger logger = Logger.getRootLogger();
|
private static Logger logger = Logger.getRootLogger();
|
||||||
|
|
||||||
|
private Logging() {
|
||||||
|
}
|
||||||
|
|
||||||
public static void logInfo(final String message, Throwable throwable) {
|
public static void logInfo(final String message, Throwable throwable) {
|
||||||
logger.info(message, throwable);
|
logger.info(message, throwable);
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@ package de.wwwu.awolf.presenter.util;
|
||||||
import de.wwwu.awolf.model.Line;
|
import de.wwwu.awolf.model.Line;
|
||||||
import de.wwwu.awolf.model.Point;
|
import de.wwwu.awolf.model.Point;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
import java.security.SecureRandom;
|
import java.security.SecureRandom;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@ -29,38 +30,14 @@ public class RandomSampler {
|
||||||
* @param r Anzahl der zu wählenden Geraden
|
* @param r Anzahl der zu wählenden Geraden
|
||||||
* @return <code>r</code> Elementige zufällige Stichprobe an Geraden
|
* @return <code>r</code> Elementige zufällige Stichprobe an Geraden
|
||||||
*/
|
*/
|
||||||
public static List<Line> run(List<Line> set, Double r, Integer indexOfEnd) {
|
public static <T extends Object> List<T> run(List<T> set, Double r) {
|
||||||
|
int index = 0;
|
||||||
List<Line> sampledLines = new ArrayList<>();
|
List<T> sampled = new ArrayList<>();
|
||||||
|
for (int i=0; i<r; i++) {
|
||||||
for (int i = 0; i < r; i++) {
|
index = random.nextInt(set.size());
|
||||||
sampledLines.add(set.get(random.nextInt(indexOfEnd)));
|
sampled.add(set.get(index));
|
||||||
}
|
}
|
||||||
|
return sampled;
|
||||||
return sampledLines;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Diese Methode liefert eine <code>r</code> Elementige zufällige Stichprobe van Schnittpunkten.
|
|
||||||
*
|
|
||||||
* @param set Die gesammtmenge der Geraden aus denen gewählt werden soll
|
|
||||||
* @param r Anzahl der zu wählenden Geraden
|
|
||||||
* @return <code>r</code> Elementige zufällige Stichprobe an Schnittpunkten
|
|
||||||
*/
|
|
||||||
public static List<Double> run(List<Point> set, Double r) {
|
|
||||||
|
|
||||||
List<Double> sampledLines = new ArrayList<>();
|
|
||||||
for (Point p : set) {
|
|
||||||
sampledLines.add(p.getX());
|
|
||||||
}
|
|
||||||
|
|
||||||
int inputSize = sampledLines.size();
|
|
||||||
for (int i = 0; i < r; i++) {
|
|
||||||
int indexToSwap = i + random.nextInt(inputSize - i);
|
|
||||||
Double temp = sampledLines.get(i);
|
|
||||||
sampledLines.set(i, sampledLines.get(indexToSwap));
|
|
||||||
sampledLines.set(indexToSwap, temp);
|
|
||||||
}
|
|
||||||
return new ArrayList<>(sampledLines.subList(0, r.intValue()));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,8 +20,6 @@ import javax.imageio.ImageIO;
|
||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.Serializable;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
@ -91,36 +89,6 @@ public class MainFrame extends JFrame {
|
||||||
* visualisierungs methoden
|
* visualisierungs methoden
|
||||||
******************************************************************************************************************/
|
******************************************************************************************************************/
|
||||||
|
|
||||||
/**
|
|
||||||
* Erzeugt den Dialog für die duale Darstellung
|
|
||||||
*/
|
|
||||||
public void createDualityDialog() {
|
|
||||||
arrangement = new DualityPanel();
|
|
||||||
arrangementDialog = new JDialog();
|
|
||||||
arrangementDialog.setTitle("Dualraum - Dialog");
|
|
||||||
arrangementDialog.setMinimumSize(new Dimension(1024, 768));
|
|
||||||
arrangementDialog.setPreferredSize(new Dimension(800, 800));
|
|
||||||
arrangementDialog.setLocationRelativeTo(this);
|
|
||||||
arrangementDialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
|
|
||||||
arrangementButton.addActionListener(new DualityVisualizerListener((Presenter) getPresenter()));
|
|
||||||
arrangement.clear();
|
|
||||||
arrangement.setPrameters(getPresenter().getModel().getLines(),
|
|
||||||
getPresenter().getModel().getNodes(),
|
|
||||||
getPresenter().getModel().getxMinimum(),
|
|
||||||
getPresenter().getModel().getxMaximum(),
|
|
||||||
getPresenter().getModel().getyMinimum(),
|
|
||||||
getPresenter().getModel().getyMaximum());
|
|
||||||
arrangement.createArrangement();
|
|
||||||
|
|
||||||
SwingUtilities.invokeLater(() -> {
|
|
||||||
arrangementDialog.add(arrangement);
|
|
||||||
arrangementDialog.setLocationRelativeTo(this);
|
|
||||||
arrangementDialog.revalidate();
|
|
||||||
arrangementDialog.repaint();
|
|
||||||
arrangementDialog.setVisible(true);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Visualisiert das Ergebnis des LMS-Schätzers
|
* Visualisiert das Ergebnis des LMS-Schätzers
|
||||||
*
|
*
|
||||||
|
@ -427,12 +395,11 @@ public class MainFrame extends JFrame {
|
||||||
menu.addActionListeners();
|
menu.addActionListeners();
|
||||||
|
|
||||||
//action listener für diese Klasse
|
//action listener für diese Klasse
|
||||||
arrangementButton.addActionListener(new DualityVisualizerListener((Presenter) getPresenter()));
|
|
||||||
lmsPanel.getStartButton().addActionListener(new StartAlgorithmListener(((Presenter) getPresenter()), lmsPanel));
|
lmsPanel.getStartButton().addActionListener(new StartAlgorithmListener(((Presenter) getPresenter()), lmsPanel));
|
||||||
rmPanel.getStartButton().addActionListener(new StartAlgorithmListener(((Presenter) getPresenter()), rmPanel));
|
rmPanel.getStartButton().addActionListener(new StartAlgorithmListener(((Presenter) getPresenter()), rmPanel));
|
||||||
tsPanel.getStartButton().addActionListener(new StartAlgorithmListener(((Presenter) getPresenter()), tsPanel));
|
tsPanel.getStartButton().addActionListener(new StartAlgorithmListener(((Presenter) getPresenter()), tsPanel));
|
||||||
importButton.addActionListener(new ImportDataListener((Presenter) this.getPresenter(), this));
|
importButton.addActionListener(new ImportDataListener((Presenter) this.getPresenter()));
|
||||||
exportButton.addActionListener(new ExportDataListener((Presenter) this.getPresenter(), this));
|
exportButton.addActionListener(new ExportDataListener((Presenter) this.getPresenter()));
|
||||||
generateButton.addActionListener(new GenerateDataListener((Presenter) this.getPresenter()));
|
generateButton.addActionListener(new GenerateDataListener((Presenter) this.getPresenter()));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -75,11 +75,13 @@ public class MenuBar {
|
||||||
this.exitItem.addActionListener(e -> {
|
this.exitItem.addActionListener(e -> {
|
||||||
System.exit(0);
|
System.exit(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
this.evaluateItem.addActionListener(e -> {
|
this.evaluateItem.addActionListener(e -> {
|
||||||
view.showEvauluationDialog();
|
view.showEvauluationDialog();
|
||||||
});
|
});
|
||||||
this.importItem.addActionListener(new ImportDataListener((Presenter) view.getPresenter(), view));
|
|
||||||
this.exportItem.addActionListener(new ExportDataListener((Presenter) view.getPresenter(), view));
|
this.importItem.addActionListener(new ImportDataListener((Presenter) view.getPresenter()));
|
||||||
|
this.exportItem.addActionListener(new ExportDataListener((Presenter) view.getPresenter()));
|
||||||
this.generateItem.addActionListener(new GenerateDataListener((Presenter) view.getPresenter()));
|
this.generateItem.addActionListener(new GenerateDataListener((Presenter) view.getPresenter()));
|
||||||
this.aboutItem.addActionListener(e -> {
|
this.aboutItem.addActionListener(e -> {
|
||||||
SwingUtilities.invokeLater(() -> {
|
SwingUtilities.invokeLater(() -> {
|
||||||
|
|
|
@ -1,35 +0,0 @@
|
||||||
package de.wwwu.awolf.view.listener;
|
|
||||||
|
|
||||||
import de.wwwu.awolf.presenter.Presenter;
|
|
||||||
|
|
||||||
import javax.swing.*;
|
|
||||||
import java.awt.event.ActionEvent;
|
|
||||||
import java.awt.event.ActionListener;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Implementierung verschiedener Algorithmen zur Berechnung von Ausgleichsgeraden.
|
|
||||||
*
|
|
||||||
* @Author: Armin Wolf
|
|
||||||
* @Email: a_wolf28@uni-muenster.de
|
|
||||||
* @Date: 10.09.2017.
|
|
||||||
*/
|
|
||||||
public class DualityVisualizerListener implements ActionListener {
|
|
||||||
|
|
||||||
private Presenter presenter;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Konstruktor
|
|
||||||
*
|
|
||||||
* @param presenter Presenter
|
|
||||||
*/
|
|
||||||
public DualityVisualizerListener(Presenter presenter) {
|
|
||||||
this.presenter = presenter;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void actionPerformed(ActionEvent e) {
|
|
||||||
SwingUtilities.invokeLater(() -> {
|
|
||||||
presenter.visualizeDualLines();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,6 +1,7 @@
|
||||||
package de.wwwu.awolf.view.listener;
|
package de.wwwu.awolf.view.listener;
|
||||||
|
|
||||||
import de.wwwu.awolf.presenter.Presenter;
|
import de.wwwu.awolf.presenter.Presenter;
|
||||||
|
import de.wwwu.awolf.presenter.util.Logging;
|
||||||
|
|
||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
import javax.swing.filechooser.FileNameExtensionFilter;
|
import javax.swing.filechooser.FileNameExtensionFilter;
|
||||||
|
@ -20,36 +21,32 @@ import java.io.File;
|
||||||
public class ExportDataListener implements ActionListener {
|
public class ExportDataListener implements ActionListener {
|
||||||
|
|
||||||
private Presenter presenter;
|
private Presenter presenter;
|
||||||
private Container component;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Konstruktor
|
* Konstruktor
|
||||||
*
|
*
|
||||||
* @param presenter Presenter
|
* @param presenter Presenter
|
||||||
* @param component visuelle Elternkomponente
|
|
||||||
*/
|
*/
|
||||||
public ExportDataListener(Presenter presenter, Container component) {
|
public ExportDataListener(Presenter presenter) {
|
||||||
this.presenter = presenter;
|
this.presenter = presenter;
|
||||||
this.component = component;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void actionPerformed(ActionEvent e) {
|
public void actionPerformed(ActionEvent e) {
|
||||||
SwingUtilities.invokeLater(() -> {
|
SwingUtilities.invokeLater(() -> {
|
||||||
File file = null;
|
File file = null;
|
||||||
JFileChooser chooser = new JFileChooser(FileSystemView.getFileSystemView().getHomeDirectory());
|
JFileChooser chooser = new JFileChooser();
|
||||||
chooser.setPreferredSize(new Dimension(800, 700));
|
chooser.setPreferredSize(new Dimension(800, 700));
|
||||||
chooser.setFileFilter(new FileNameExtensionFilter("Comma-Separated Value, (*.csv)", "csv", "text"));
|
chooser.setFileFilter(new FileNameExtensionFilter("Comma-Separated Value, (*.csv)", "csv", "text"));
|
||||||
chooser.setMultiSelectionEnabled(false);
|
chooser.setMultiSelectionEnabled(false);
|
||||||
chooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
|
chooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
|
||||||
|
|
||||||
|
|
||||||
if (chooser.showSaveDialog(component) == JFileChooser.APPROVE_OPTION) {
|
if (chooser.showSaveDialog(null) == JFileChooser.APPROVE_OPTION) {
|
||||||
//Logging.logInfo ("Datei "+chooser.getSelectedFile()+ " ausgewählt.");
|
Logging.logInfo ("Datei "+chooser.getSelectedFile()+ " ausgewählt.");
|
||||||
file = chooser.getSelectedFile();
|
file = chooser.getSelectedFile();
|
||||||
String filename = file.getAbsolutePath().contains(".csv") ? file.getAbsolutePath() : file.getAbsolutePath().concat(".csv");
|
String filename = file.getAbsolutePath().contains(".csv") ? file.getAbsolutePath() : file.getAbsolutePath().concat(".csv");
|
||||||
File withExtension = new File(filename);
|
final File input = new File(filename);
|
||||||
final File input = withExtension;
|
|
||||||
Thread t = new Thread(() -> presenter.startExport(input));
|
Thread t = new Thread(() -> presenter.startExport(input));
|
||||||
t.start();
|
t.start();
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@ package de.wwwu.awolf.view.listener;
|
||||||
|
|
||||||
import de.wwwu.awolf.presenter.Presenter;
|
import de.wwwu.awolf.presenter.Presenter;
|
||||||
import de.wwwu.awolf.presenter.data.DataProvider;
|
import de.wwwu.awolf.presenter.data.DataProvider;
|
||||||
|
import de.wwwu.awolf.presenter.util.Logging;
|
||||||
|
|
||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
|
@ -36,6 +37,7 @@ public class GenerateDataListener implements ActionListener {
|
||||||
@Override
|
@Override
|
||||||
public void actionPerformed(ActionEvent e) {
|
public void actionPerformed(ActionEvent e) {
|
||||||
SwingUtilities.invokeLater(() -> {
|
SwingUtilities.invokeLater(() -> {
|
||||||
|
Logging.logInfo("Thread: " + Thread.currentThread().getName());
|
||||||
if (dialog == null || !dialog.isVisible()) {
|
if (dialog == null || !dialog.isVisible()) {
|
||||||
dialog = new JDialog();
|
dialog = new JDialog();
|
||||||
dialog.setTitle("generiere Datensatz");
|
dialog.setTitle("generiere Datensatz");
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package de.wwwu.awolf.view.listener;
|
package de.wwwu.awolf.view.listener;
|
||||||
|
|
||||||
import de.wwwu.awolf.presenter.Presenter;
|
import de.wwwu.awolf.presenter.Presenter;
|
||||||
|
import de.wwwu.awolf.presenter.util.Logging;
|
||||||
|
|
||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
import javax.swing.filechooser.FileNameExtensionFilter;
|
import javax.swing.filechooser.FileNameExtensionFilter;
|
||||||
|
@ -20,32 +21,29 @@ import java.io.File;
|
||||||
public class ImportDataListener implements ActionListener {
|
public class ImportDataListener implements ActionListener {
|
||||||
|
|
||||||
private Presenter presenter;
|
private Presenter presenter;
|
||||||
private Container component;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Konstruktor
|
* Konstruktor
|
||||||
*
|
*
|
||||||
* @param presenter Presenter
|
* @param presenter Presenter
|
||||||
* @param component visuelle Elternkomponente
|
|
||||||
*/
|
*/
|
||||||
public ImportDataListener(Presenter presenter, Container component) {
|
public ImportDataListener(Presenter presenter) {
|
||||||
this.presenter = presenter;
|
this.presenter = presenter;
|
||||||
this.component = component;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void actionPerformed(ActionEvent e) {
|
public void actionPerformed(ActionEvent e) {
|
||||||
SwingUtilities.invokeLater(() -> {
|
SwingUtilities.invokeLater(() -> {
|
||||||
File file = null;
|
Logging.logInfo("Thread: " + Thread.currentThread().getName());
|
||||||
JFileChooser chooser = new JFileChooser(FileSystemView.getFileSystemView().getHomeDirectory());
|
JFileChooser chooser = new JFileChooser();
|
||||||
chooser.setPreferredSize(new Dimension(800, 700));
|
chooser.setPreferredSize(new Dimension(800, 700));
|
||||||
chooser.setFileFilter(new FileNameExtensionFilter("Comma-Separated Value, (*.csv)", "csv", "text"));
|
chooser.setFileFilter(new FileNameExtensionFilter("Comma-Separated Value, (*.csv)", "csv", "text"));
|
||||||
|
|
||||||
chooser.setMultiSelectionEnabled(false);
|
chooser.setMultiSelectionEnabled(false);
|
||||||
chooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
|
chooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
|
||||||
|
|
||||||
|
File file = null;
|
||||||
if (chooser.showOpenDialog(component) == JFileChooser.APPROVE_OPTION) {
|
if (chooser.showOpenDialog(null) == JFileChooser.APPROVE_OPTION) {
|
||||||
//Logging.logInfo ("Datei "+chooser.getSelectedFile()+ " ausgewählt.");
|
//Logging.logInfo ("Datei "+chooser.getSelectedFile()+ " ausgewählt.");
|
||||||
file = chooser.getSelectedFile();
|
file = chooser.getSelectedFile();
|
||||||
final File input = file;
|
final File input = file;
|
||||||
|
@ -53,5 +51,6 @@ public class ImportDataListener implements ActionListener {
|
||||||
t.start();
|
t.start();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,6 @@ import de.wwwu.awolf.model.Line;
|
||||||
import de.wwwu.awolf.presenter.Presenter;
|
import de.wwwu.awolf.presenter.Presenter;
|
||||||
import de.wwwu.awolf.presenter.algorithms.Algorithm;
|
import de.wwwu.awolf.presenter.algorithms.Algorithm;
|
||||||
import de.wwwu.awolf.presenter.data.DataProvider;
|
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.MainFrame;
|
||||||
import de.wwwu.awolf.view.custom.ButtonGroupAtLeastTwo;
|
import de.wwwu.awolf.view.custom.ButtonGroupAtLeastTwo;
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
# Root logger option
|
# Root logger option
|
||||||
log4j.rootLogger=INFO, file, stdout
|
log4j.rootLogger=DEBUG, file, stdout
|
||||||
# Direct log messages to a log file
|
# Direct log messages to a log file
|
||||||
log4j.appender.file=org.apache.log4j.RollingFileAppender
|
log4j.appender.file=org.apache.log4j.RollingFileAppender
|
||||||
log4j.appender.file.File=D:\\Git\\master-implementierung\\LinearRegressionTool\\log4j\\app.log
|
log4j.appender.file.File=D:\\Git\\master-implementierung\\LinearRegressionTool\\log4j\\app.log
|
||||||
|
|
|
@ -23,7 +23,6 @@ import static org.junit.Assert.*;
|
||||||
public class LeastMedianOfSquaresEstimatorTest {
|
public class LeastMedianOfSquaresEstimatorTest {
|
||||||
|
|
||||||
private LeastMedianOfSquaresEstimator lms;
|
private LeastMedianOfSquaresEstimator lms;
|
||||||
private IntersectionComputer intersectionComputer;
|
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void setUp(){
|
public void setUp(){
|
||||||
|
@ -32,15 +31,12 @@ public class LeastMedianOfSquaresEstimatorTest {
|
||||||
|
|
||||||
|
|
||||||
LinkedList<Line> lines = new LinkedList<>();
|
LinkedList<Line> lines = new LinkedList<>();
|
||||||
ArrayList<Point> intersections = new ArrayList<>();
|
|
||||||
|
|
||||||
for (int i = 0; i < 5; i++) {
|
for (int i = 0; i < 5; i++) {
|
||||||
lines.add(new Line(x[i], y[i]));
|
lines.add(new Line(x[i], y[i]));
|
||||||
}
|
}
|
||||||
|
|
||||||
intersectionComputer = new IntersectionComputer(lines);
|
lms = new LeastMedianOfSquaresEstimator(lines);
|
||||||
intersections = intersectionComputer.compute();
|
|
||||||
lms = new LeastMedianOfSquaresEstimator(lines, intersections);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -23,7 +23,6 @@ import static org.junit.Assert.*;
|
||||||
public class TheilSenEstimatorTest {
|
public class TheilSenEstimatorTest {
|
||||||
|
|
||||||
TheilSenEstimator estimator;
|
TheilSenEstimator estimator;
|
||||||
IntersectionComputer intersectionComputer;
|
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void setUp(){
|
public void setUp(){
|
||||||
|
@ -32,15 +31,12 @@ public class TheilSenEstimatorTest {
|
||||||
|
|
||||||
|
|
||||||
List<Line> lines = new LinkedList<>();
|
List<Line> lines = new LinkedList<>();
|
||||||
List<Point> intersections = new ArrayList<>();
|
|
||||||
|
|
||||||
for (int i = 0; i < 5; i++) {
|
for (int i = 0; i < 5; i++) {
|
||||||
lines.add(new Line(x[i], y[i]));
|
lines.add(new Line(x[i], y[i]));
|
||||||
}
|
}
|
||||||
|
|
||||||
intersectionComputer = new IntersectionComputer(lines);
|
estimator = new TheilSenEstimator(lines);
|
||||||
intersections = intersectionComputer.compute();
|
|
||||||
estimator = new TheilSenEstimator(lines, intersections);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,58 +0,0 @@
|
||||||
package de.wwwu.awolf.presenter.util;
|
|
||||||
|
|
||||||
import de.wwwu.awolf.model.Line;
|
|
||||||
import de.wwwu.awolf.model.LineModel;
|
|
||||||
import de.wwwu.awolf.model.Point;
|
|
||||||
import org.junit.Before;
|
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import static org.junit.Assert.*;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Implementierung verschiedener Algorithmen zur Berechnung von Ausgleichsgeraden.
|
|
||||||
*
|
|
||||||
* @Author: Armin Wolf
|
|
||||||
* @Email: a_wolf28@uni-muenster.de
|
|
||||||
* @Date: 23.10.2017.
|
|
||||||
*/
|
|
||||||
public class IntersectionComputerTest {
|
|
||||||
|
|
||||||
private IntersectionComputer intersectionComputer;
|
|
||||||
private LineModel lineModel;
|
|
||||||
|
|
||||||
@Before
|
|
||||||
public void setUp() throws Exception {
|
|
||||||
lineModel = new LineModel();
|
|
||||||
lineModel.addLine(new Line(3,13,10,3));
|
|
||||||
lineModel.addLine(new Line(1,9,1,9));
|
|
||||||
lineModel.addLine(new Line(1,12,4,6));
|
|
||||||
intersectionComputer = new IntersectionComputer(lineModel.getLines());
|
|
||||||
}
|
|
||||||
@Test
|
|
||||||
public void compute() throws Exception {
|
|
||||||
|
|
||||||
List<Point> intersections = intersectionComputer.compute();
|
|
||||||
double[] expectedX = {4.66, 7.11, 9.39};
|
|
||||||
double[] expectedY = {4.66, 7.11, 5.52};
|
|
||||||
|
|
||||||
double[] actualX = new double[3];
|
|
||||||
double[] actualY = new double[3];
|
|
||||||
|
|
||||||
for (int i=0;i<3;i++){
|
|
||||||
actualX[i] = intersections.get(i).getX();
|
|
||||||
actualY[i] = intersections.get(i).getY();
|
|
||||||
}
|
|
||||||
|
|
||||||
Arrays.sort(expectedX);
|
|
||||||
Arrays.sort(actualX);
|
|
||||||
assertArrayEquals(expectedX, actualX, 0.01d);
|
|
||||||
|
|
||||||
Arrays.sort(expectedY);
|
|
||||||
Arrays.sort(actualY);
|
|
||||||
assertArrayEquals(expectedY, actualY, 0.01d);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
Loading…
Reference in New Issue