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

135 lines
3.9 KiB
Java

package de.wwwu.awolf.presenter.algorithms.naiv;
import de.wwwu.awolf.model.Line;
import de.wwwu.awolf.model.communication.AlgorithmData;
import de.wwwu.awolf.model.communication.Data;
import de.wwwu.awolf.model.communication.SubscriberType;
import de.wwwu.awolf.presenter.AbstractPresenter;
import de.wwwu.awolf.presenter.algorithms.Algorithm;
import de.wwwu.awolf.presenter.util.FastElementSelector;
import de.wwwu.awolf.presenter.util.Logging;
import java.util.*;
import java.util.concurrent.Flow;
/**
* Implementierung verschiedener Algorithmen zur Berechnung von Ausgleichsgeraden.
*
* @Author: Armin Wolf
* @Email: a_wolf28@uni-muenster.de
* @Date: 15.09.2017.
*/
public class NaivLeastMedianOfSquaresEstimator implements Algorithm {
private static final Algorithm.Type type = Type.NAIV_LMS;
private List<Line> setOfLines = new ArrayList<>();
private int n;
private double ds, b, m;
private Flow.Subscriber<? super Data> subscriber;
private AbstractPresenter presenter;
/**
* Crude Algorithmus zum berechnen des LSM-Schätzers.
*/
private Line crudeAlg() {
ds = Double.MAX_VALUE;
b = 0d;
m = 0d;
List<Line> triple = new ArrayList<>();
double beta;
double alpha;
double dijk;
Logging.logInfo("=== S T A R T - naiv L M S ===");
long start;
long end;
start = System.currentTimeMillis();
for (Line i : setOfLines) {
for (Line j : setOfLines) {
for (Line k : setOfLines) {
triple.add(i);
triple.add(j);
triple.add(k);
Collections.sort(triple);
beta = (triple.get(0).getB() - triple.get(2).getB()) / (triple.get(0).getM() - triple.get(2).getM());
alpha = (triple.get(1).getB() + triple.get(2).getB() - (beta * (triple.get(1).getM() + triple.get(2).getM()))) * 0.5;
dijk = f(alpha, beta);
if (dijk < ds) {
ds = dijk;
b = alpha;
m = beta;
}
triple.clear();
}
}
}
end = System.currentTimeMillis();
Logging.logInfo("=== E N D - naiv L M S ===");
Logging.logInfo("Slope: " + getSlope() + ", y-Interception: " + getYInterception());
AlgorithmData data = new AlgorithmData();
data.setAlgorithmType(getType());
data.setType(SubscriberType.ALGORITHM);
data.setLineData(new Line(getSlope(), getYInterception()));
this.subscriber.onNext(data);
return new Line(getSlope(), getYInterception());
}
/**
* Berechnet die Gerade mit dem medianen Fehler
*
* @param a y-Achsenabschnitt
* @param b Steigung
* @return medianer Fehler
*/
private Double f(double a, double b) {
List<Double> res = new ArrayList<>();
for (Line p : setOfLines) {
res.add(Math.abs(p.getB() - (a + b * p.getM())));
}
return FastElementSelector.randomizedSelect(res, res.size() * 0.5);
}
@Override
public Line call() {
return crudeAlg();
}
@Override
public void setInput(Set<Line> lines) {
this.setOfLines = new LinkedList<>(lines);
}
@Override
public Type getType() {
return type;
}
@Override
public void setPresenter(AbstractPresenter presenter) {
this.presenter = presenter;
subscribe(presenter);
}
/**
* @return y-Achsenabschnitt
*/
public Double getYInterception() {
return b * -1;
}
/**
* @return Steigung
*/
public Double getSlope() {
return m * -1;
}
@Override
public void subscribe(Flow.Subscriber<? super Data> subscriber) {
this.subscriber = subscriber;
}
}