algorithms-for-computing-li.../LinearRegressionTool/src/main/java/de/wwwu/awolf/presenter/algorithms/naiv/NaivRepeatedMedianEstimator...

142 lines
4.1 KiB
Java

package de.wwwu.awolf.presenter.algorithms.naiv;
import de.wwwu.awolf.model.Line;
import de.wwwu.awolf.model.Point;
import de.wwwu.awolf.presenter.algorithms.Algorithm;
import de.wwwu.awolf.presenter.util.FastElementSelector;
import de.wwwu.awolf.presenter.util.Logging;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* Implementierung verschiedener Algorithmen zur Berechnung von Ausgleichsgeraden.
*
* @Author: Armin Wolf
* @Email: a_wolf28@uni-muenster.de
* @Date: 15.09.2017.
*/
public class NaivRepeatedMedianEstimator implements Algorithm {
private List<Line> lines;
private Map<String, List<Double>> slopesPerLine;
private Map<String, List<Double>> interceptPerLine;
private List<Double> xMedians;
private List<Double> yMedians;
private double medianX;
private double medianY;
/**
* Konstruktor
*
* @param lines Liste der Geraden
*/
public NaivRepeatedMedianEstimator(List<Line> lines) {
this.lines = lines;
slopesPerLine = new HashMap<>();
interceptPerLine = new HashMap<>();
xMedians = new ArrayList<>();
yMedians = new ArrayList<>();
}
@Override
public void run() {
//init the List for the slopes
Logging.logInfo("=== S T A R T - naiv R M ===");
long start;
long end;
start = System.currentTimeMillis();
for (Line leq : lines) {
slopesPerLine.computeIfAbsent(leq.getId(), k -> new ArrayList<>());
interceptPerLine.computeIfAbsent(leq.getId(), k -> new ArrayList<>());
}
//calculate all slopes for each line
Point ret;
for (int i = 0; i < lines.size(); i++) {
for (int j = i + 1; j < lines.size(); j++) {
ret = calculateLine(lines.get(i), lines.get(j));
slopesPerLine.get(lines.get(i).getId()).add(ret.getX());
interceptPerLine.get(lines.get(i).getId()).add(ret.getY());
}
}
//berechne mediane Steigung
for (String l : slopesPerLine.keySet()) {
List<Double> list = slopesPerLine.get(l);
int size = list.size() / 2;
if (size > 0) {
double medianX = FastElementSelector.randomizedSelect(list, size);
xMedians.add(medianX);
}
}
//berechne medianen y-Achsenabschnitt
for (String l : interceptPerLine.keySet()) {
List<Double> list = interceptPerLine.get(l);
int size = list.size() / 2;
if (size > 0) {
double medianY = FastElementSelector.randomizedSelect(list, size);
yMedians.add(medianY);
}
}
medianX = FastElementSelector.randomizedSelect(xMedians, xMedians.size() * 0.5);
medianY = FastElementSelector.randomizedSelect(yMedians, yMedians.size() * 0.5);
end = System.currentTimeMillis();
Logging.logInfo("Zeit: " + ((end - start) / 1000));
}
@Override
public void pepareResult() {
}
/**
* Berechnet die Geraden zwischen zwei Punkten im dualen Raum.
*
* @param startPoint Gerade 1 => Startpunkt mit den Koordianten (m,b)
* @param endPoint Gerade 2 => Endpunkt mit den Koordianten (m', b')
* @return
*/
private Point calculateLine(Line startPoint, Line endPoint) {
double xi;
double xj;
double yi;
double yj;
if (endPoint.getM() > startPoint.getM()) {
xi = startPoint.getM();
yi = startPoint.getB();
xj = endPoint.getM();
yj = endPoint.getB();
} else {
xj = startPoint.getM();
yj = startPoint.getB();
xi = endPoint.getM();
yi = endPoint.getB();
}
double m = (yj - yi) / (xj - xi);
double b = ((xj * yi) - (xi * yj)) / (xj - xi);
return new Point(m, b);
}
/**
* @return Steigung
*/
public double getM() {
return medianX * -1;
}
/**
* @return y-Achsenabschnitt
*/
public double getB() {
return medianY * -1;
}
}