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 setOfLines = new ArrayList<>(); private int n; private double ds, b, m; private Flow.Subscriber subscriber; private AbstractPresenter presenter; /** * Crude Algorithmus zum berechnen des LSM-Schätzers. */ private Line crudeAlg() { ds = Double.MAX_VALUE; b = 0d; m = 0d; List 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 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 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 subscriber) { this.subscriber = subscriber; } }