2020-03-21 00:37:09 +00:00
|
|
|
|
package de.wwwu.awolf.presenter.algorithms.advanced;
|
|
|
|
|
|
|
|
|
|
import de.wwwu.awolf.model.Interval;
|
|
|
|
|
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.Data;
|
|
|
|
|
import de.wwwu.awolf.model.communication.SubscriberType;
|
2020-03-28 15:24:35 +00:00
|
|
|
|
import de.wwwu.awolf.presenter.AbstractPresenter;
|
2020-03-21 00:37:09 +00:00
|
|
|
|
import de.wwwu.awolf.presenter.algorithms.Algorithm;
|
2020-03-23 06:58:40 +00:00
|
|
|
|
import de.wwwu.awolf.presenter.util.IntersectionComputer;
|
2020-03-21 00:37:09 +00:00
|
|
|
|
import de.wwwu.awolf.presenter.util.Logging;
|
|
|
|
|
|
2017-09-10 15:45:47 +00:00
|
|
|
|
import java.util.*;
|
2020-03-21 00:37:09 +00:00
|
|
|
|
import java.util.concurrent.Flow;
|
2017-09-10 15:45:47 +00:00
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Implementierung verschiedener Algorithmen zur Berechnung von Ausgleichsgeraden.
|
|
|
|
|
*
|
|
|
|
|
* @Author: Armin Wolf
|
|
|
|
|
* @Email: a_wolf28@uni-muenster.de
|
|
|
|
|
* @Date: 28.05.2017.
|
|
|
|
|
*/
|
2020-03-28 15:24:35 +00:00
|
|
|
|
public class LeastMedianOfSquaresEstimator implements Algorithm {
|
|
|
|
|
private static final Algorithm.Type type = Type.LMS;
|
2017-09-10 15:45:47 +00:00
|
|
|
|
|
2020-03-23 06:58:40 +00:00
|
|
|
|
private List<Line> setOfLines;
|
2017-09-10 15:45:47 +00:00
|
|
|
|
private int n;
|
|
|
|
|
private double quantileError;
|
|
|
|
|
private int kPlus;
|
|
|
|
|
private int kMinus;
|
2020-03-21 00:37:09 +00:00
|
|
|
|
private Queue<Interval> intervals;
|
2017-09-10 15:45:47 +00:00
|
|
|
|
private Interval subSlabU1;
|
|
|
|
|
private Interval subSlabU2;
|
|
|
|
|
private Line sigmaMin;
|
|
|
|
|
private double heightsigmaMin;
|
2019-08-01 05:19:04 +00:00
|
|
|
|
private double intersectionsPoint;
|
|
|
|
|
private double constant = 0.5;
|
2017-09-10 15:45:47 +00:00
|
|
|
|
|
2019-08-01 05:19:04 +00:00
|
|
|
|
private double slope;
|
|
|
|
|
private double yInterception;
|
2020-03-21 00:37:09 +00:00
|
|
|
|
private Flow.Subscriber<? super AlgorithmData> subscriber;
|
2020-03-28 15:24:35 +00:00
|
|
|
|
private AbstractPresenter presenter;
|
2017-09-10 15:45:47 +00:00
|
|
|
|
|
|
|
|
|
/**
|
2017-10-15 13:21:53 +00:00
|
|
|
|
* Algorithmus zum berechnen des LMS-Schätzers
|
2020-03-20 17:08:18 +00:00
|
|
|
|
* <p>
|
2017-10-15 13:21:53 +00:00
|
|
|
|
* Paper:
|
|
|
|
|
* Mount, David M, Nathan S Netanyahu, Kathleen Romanik, Ruth Silverman und Angela Y Wu
|
|
|
|
|
* „A practical approximation algorithm for the LMS line estimator“. 2007
|
|
|
|
|
* Computational statistics & data Analysis 51.5, S. 2461–2486
|
2017-09-10 15:45:47 +00:00
|
|
|
|
*/
|
2020-03-21 19:54:03 +00:00
|
|
|
|
@Override
|
|
|
|
|
public Line call() {
|
2020-03-28 15:24:35 +00:00
|
|
|
|
this.n = setOfLines.size();
|
|
|
|
|
double qPlus = 0.5;
|
|
|
|
|
quantileError = 0.1;
|
|
|
|
|
double qMinus = qPlus * (1 - quantileError);
|
|
|
|
|
kMinus = (int) Math.ceil(n * qMinus);
|
|
|
|
|
kPlus = (int) Math.ceil(n * qPlus);
|
2017-09-10 15:45:47 +00:00
|
|
|
|
|
2020-03-21 00:37:09 +00:00
|
|
|
|
Logging.logInfo("=== S T A R T - L M S ===");
|
2017-10-12 15:21:16 +00:00
|
|
|
|
long start;
|
|
|
|
|
long end;
|
|
|
|
|
start = System.currentTimeMillis();
|
|
|
|
|
|
2017-09-10 15:45:47 +00:00
|
|
|
|
//(2.) Let U <- (-inf, inf) be the initial active intervals...
|
|
|
|
|
Comparator<Interval> comparator = (o1, o2) -> {
|
|
|
|
|
if (o1.getDistance() < o2.getDistance()) {
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
if (o1.getDistance() > o2.getDistance()) {
|
|
|
|
|
return 1;
|
|
|
|
|
} else {
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
intervals = new PriorityQueue<>(comparator);
|
2020-03-23 06:58:40 +00:00
|
|
|
|
intervals.add(new Interval(-10000, 10000));
|
2017-09-10 15:45:47 +00:00
|
|
|
|
heightsigmaMin = Double.MAX_VALUE;
|
|
|
|
|
|
|
|
|
|
//(3.) Apply the following steps as long as the exists active intervals
|
|
|
|
|
boolean active = true;
|
|
|
|
|
Interval interval;
|
|
|
|
|
while (!this.intervals.isEmpty()) {
|
|
|
|
|
interval = this.intervals.peek();
|
|
|
|
|
if (interval.getActivity()) {
|
|
|
|
|
//(a.) Select any active Interval and calc. the inversions
|
|
|
|
|
int numberOfIntersections = countInversions(interval);
|
|
|
|
|
|
|
|
|
|
//(b.) apply plane sweep
|
|
|
|
|
if ((constant * n) >= numberOfIntersections) {
|
2017-10-12 15:21:16 +00:00
|
|
|
|
sigmaMin = pseudoSweep(interval);
|
2017-09-10 15:45:47 +00:00
|
|
|
|
} else {
|
|
|
|
|
//(c.) otherwise....
|
|
|
|
|
// get random intersections point...
|
2020-03-23 06:58:40 +00:00
|
|
|
|
Collection<Point> tmpIntersections = IntersectionComputer.getInstance().compute(setOfLines, interval.getLower(), interval.getUpper());
|
2019-08-01 05:19:04 +00:00
|
|
|
|
boolean found = false;
|
2020-03-21 00:37:09 +00:00
|
|
|
|
for (Point tmpIntersection : tmpIntersections) {
|
|
|
|
|
if (tmpIntersection.getX() > interval.getLower()
|
|
|
|
|
&& tmpIntersection.getX() < interval.getUpper()) {
|
|
|
|
|
intersectionsPoint = tmpIntersection.getX();
|
2019-08-01 05:19:04 +00:00
|
|
|
|
found = true;
|
2017-09-10 15:45:47 +00:00
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
2019-08-01 05:19:04 +00:00
|
|
|
|
if (found) {
|
2017-09-10 15:45:47 +00:00
|
|
|
|
splitActiveSlab(intersectionsPoint, interval);
|
|
|
|
|
//(d.) this may update sigma min
|
|
|
|
|
upperBound(intersectionsPoint);
|
|
|
|
|
//(e.) for i={1,2}, call lower bound(Ui)
|
|
|
|
|
lowerBound(subSlabU1);
|
|
|
|
|
lowerBound(subSlabU2);
|
|
|
|
|
|
|
|
|
|
if (subSlabU1.getActivity()) {
|
|
|
|
|
this.intervals.add(subSlabU1);
|
|
|
|
|
}
|
|
|
|
|
if (subSlabU2.getActivity()) {
|
|
|
|
|
this.intervals.add(subSlabU2);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
this.intervals.poll();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
this.intervals.remove(interval);
|
|
|
|
|
}
|
|
|
|
|
}
|
2017-10-12 15:21:16 +00:00
|
|
|
|
end = System.currentTimeMillis();
|
2020-03-23 06:58:40 +00:00
|
|
|
|
Logging.logInfo("=== E N D - L M S === " + ((end - start) / 1000));
|
2019-08-01 05:19:04 +00:00
|
|
|
|
|
2020-03-21 19:54:03 +00:00
|
|
|
|
return pepareResult();
|
2017-09-10 15:45:47 +00:00
|
|
|
|
}
|
|
|
|
|
|
2020-03-28 15:24:35 +00:00
|
|
|
|
@Override
|
|
|
|
|
public void setInput(Set<Line> lines) {
|
|
|
|
|
this.setOfLines = new LinkedList<>(lines);
|
|
|
|
|
setN(this.setOfLines.size());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public Type getType() {
|
|
|
|
|
return type;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public void setPresenter(AbstractPresenter presenter) {
|
|
|
|
|
this.presenter = presenter;
|
|
|
|
|
subscribe(presenter);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2017-09-10 15:45:47 +00:00
|
|
|
|
/**
|
2017-10-15 13:21:53 +00:00
|
|
|
|
* Liefert die Anzahl der Schnittpunkte in einem Intervall
|
2020-03-20 17:08:18 +00:00
|
|
|
|
*
|
2017-10-15 13:21:53 +00:00
|
|
|
|
* @param interval Intervall
|
|
|
|
|
* @return Anzahl der Schnittpunkte
|
2017-09-10 15:45:47 +00:00
|
|
|
|
*/
|
|
|
|
|
public int countInversions(Interval interval) {
|
2020-03-23 06:58:40 +00:00
|
|
|
|
return IntersectionComputer.getInstance().compute(setOfLines, interval.getLower(), interval.getUpper()).size();
|
2017-09-10 15:45:47 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
2017-10-15 13:21:53 +00:00
|
|
|
|
* In der Literatur wird ein planesweep vorrausgesetzt um in einem Intervall das minimale kMinus Segment zu
|
|
|
|
|
* identifizieren. An dieser Stelle wird eine naivere Lösung verwendet, mithilfe der Schleife werden alle
|
|
|
|
|
* Schnittpunkte betrachtet und bei passenden x-Koordinaten werden wird die vertikale Gerade auf kMinus Segmente
|
|
|
|
|
* untersucht.
|
|
|
|
|
*
|
2017-09-10 15:45:47 +00:00
|
|
|
|
* @param interval
|
|
|
|
|
* @return
|
|
|
|
|
*/
|
2017-10-12 15:21:16 +00:00
|
|
|
|
public Line pseudoSweep(Interval interval) {
|
2017-09-10 15:45:47 +00:00
|
|
|
|
|
|
|
|
|
//initialisiere die x-Queue mit den 2D Punkten und sortiere nach x-Lexikographischer Ordnung
|
2020-03-21 00:37:09 +00:00
|
|
|
|
List<Point> xQueue = new ArrayList<>();
|
2020-03-23 06:58:40 +00:00
|
|
|
|
Collection<Point> points = IntersectionComputer.getInstance().compute(setOfLines, interval.getLower(), interval.getUpper());
|
|
|
|
|
for (Point point : points) {
|
2017-09-10 15:45:47 +00:00
|
|
|
|
if (point.getX() >= interval.getLower() && point.getX() < interval.getUpper()) {
|
|
|
|
|
xQueue.add(point);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
Collections.sort(xQueue);
|
|
|
|
|
|
|
|
|
|
Line bracelet = sigmaMin;
|
|
|
|
|
double heightOfBracelet = heightsigmaMin;
|
|
|
|
|
|
|
|
|
|
for (Point current : xQueue) {
|
|
|
|
|
Double[] currentBracelet = calcKMinusBracelet(current, kMinus);
|
|
|
|
|
|
|
|
|
|
if (currentBracelet == null) {
|
|
|
|
|
continue;
|
|
|
|
|
} else if (currentBracelet[0] < heightOfBracelet) {
|
|
|
|
|
heightOfBracelet = currentBracelet[0];
|
|
|
|
|
bracelet = new Line(current.getX(), current.getX(), currentBracelet[1], currentBracelet[2]);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
interval.setActivity(false);
|
|
|
|
|
return bracelet;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Diese Methode spaltet den aktiven Interval an der x Koordinate point. Es werden zwei neue Slabs
|
|
|
|
|
* erzeugt.
|
|
|
|
|
*
|
|
|
|
|
* @param point x Koordinate an der, der Split geschieht.
|
|
|
|
|
*/
|
|
|
|
|
public void splitActiveSlab(double point, Interval active) {
|
|
|
|
|
subSlabU1 = new Interval(active.getLower() + 0.01, point);
|
|
|
|
|
subSlabU2 = new Interval(point, active.getUpper());
|
|
|
|
|
|
|
|
|
|
this.intervals.remove(active);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2017-10-15 13:21:53 +00:00
|
|
|
|
* Zu einer vertikalen Gerade werden kMinus Segmente erzeugt und geprüft ob eine bessere Lösung
|
|
|
|
|
* als SigmaMin vorliegt.
|
2020-03-20 17:08:18 +00:00
|
|
|
|
*
|
2017-10-15 13:21:53 +00:00
|
|
|
|
* @param point x-Koordinate zur Konstruktion der vertikalen Gerade
|
2017-09-10 15:45:47 +00:00
|
|
|
|
*/
|
|
|
|
|
public void upperBound(double point) {
|
|
|
|
|
|
|
|
|
|
double height = heightsigmaMin;
|
|
|
|
|
double tmpHeight;
|
2020-03-21 00:37:09 +00:00
|
|
|
|
List<Double> sortedLineSequence = getEjValues(point);
|
2017-09-10 15:45:47 +00:00
|
|
|
|
|
|
|
|
|
int itnbr = ((n - kMinus) + 1);
|
|
|
|
|
for (int i = 0; i < itnbr; i++) {
|
|
|
|
|
tmpHeight = sortedLineSequence.get((i + kMinus) - 1) - sortedLineSequence.get(i);
|
|
|
|
|
if (tmpHeight < height) {
|
|
|
|
|
height = tmpHeight;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (height < heightsigmaMin) {
|
|
|
|
|
heightsigmaMin = height;
|
|
|
|
|
if (sigmaMin != null) {
|
|
|
|
|
sigmaMin.setEndPoints(point, sortedLineSequence.get(i)
|
|
|
|
|
, point, sortedLineSequence.get((i + kMinus) - 1));
|
|
|
|
|
} else {
|
|
|
|
|
sigmaMin = new Line(point, point, sortedLineSequence.get(i),
|
|
|
|
|
sortedLineSequence.get((i + kMinus) - 1));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2017-10-15 13:21:53 +00:00
|
|
|
|
* Die Methode prüft ob das übergebene Intervall die untere Schranke einer potenziellen Lösung erfüllt.
|
2020-03-20 17:08:18 +00:00
|
|
|
|
*
|
2017-10-15 13:21:53 +00:00
|
|
|
|
* @param pslab übergebene Intervall
|
2017-09-10 15:45:47 +00:00
|
|
|
|
*/
|
|
|
|
|
public void lowerBound(Interval pslab) {
|
|
|
|
|
|
|
|
|
|
int[] alpha = new int[n];
|
|
|
|
|
int[] beta = new int[n];
|
|
|
|
|
int strictlyGreater = 0;
|
|
|
|
|
|
|
|
|
|
//Teil I.
|
2020-03-21 00:37:09 +00:00
|
|
|
|
List<Double> umaxList;
|
|
|
|
|
List<Double> uminList;
|
2017-09-10 15:45:47 +00:00
|
|
|
|
|
|
|
|
|
//y koordinaten der Schnittpunkte
|
2020-03-21 00:37:09 +00:00
|
|
|
|
List<Line> lines = new ArrayList<>();
|
2020-03-23 06:58:40 +00:00
|
|
|
|
for (Line p : setOfLines) {
|
2017-09-10 15:45:47 +00:00
|
|
|
|
lines.add(
|
|
|
|
|
new Line(pslab.getLower(), pslab.getUpper(), ((pslab.getLower() * p.getM()) + p.getB()),
|
|
|
|
|
((pslab.getUpper() * p.getM()) + p.getB())));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
umaxList = getEjValues(pslab.getUpper());
|
|
|
|
|
uminList = getEjValues(pslab.getLower());
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < n; i++) {
|
|
|
|
|
Line level = new Line(pslab.getLower(), pslab.getUpper(), uminList.get(i), umaxList.get(i));
|
|
|
|
|
for (Line line : lines) {
|
|
|
|
|
if ((line.getY1() < level.getY1()) && (line.getY2() < level.getY2())) {
|
|
|
|
|
alpha[i]++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ((line.getY1() > level.getY1()) && (line.getY2() > level.getY2())) {
|
|
|
|
|
strictlyGreater++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
beta[i] = n - (alpha[i] + strictlyGreater);
|
|
|
|
|
strictlyGreater = 0;
|
|
|
|
|
}
|
2017-09-18 18:44:10 +00:00
|
|
|
|
|
2017-09-10 15:45:47 +00:00
|
|
|
|
|
|
|
|
|
//Teil II.
|
|
|
|
|
int i = 0;
|
|
|
|
|
double h;
|
|
|
|
|
pslab.setActivity(false);
|
|
|
|
|
for (int j = 0; j < n; j++) {
|
|
|
|
|
while ((i < n && (Math.abs(beta[i] - alpha[j]) < kPlus))) {
|
|
|
|
|
i++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (i >= n) {
|
|
|
|
|
pslab.setActivity(false);
|
|
|
|
|
break;
|
|
|
|
|
} else {
|
|
|
|
|
h = Math.min(Math.abs(uminList.get(j) - uminList.get(i)),
|
|
|
|
|
Math.abs(umaxList.get(j) - umaxList.get(i)));
|
|
|
|
|
double error = 0.01;
|
|
|
|
|
if (((1 + error) * h) < heightsigmaMin) {
|
|
|
|
|
pslab.setActivity(true);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
i = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Berechnet die Schnittpunkte der Geraden und der vertikalen Gerade u. Im paper sind diese Werte
|
|
|
|
|
* als e_j Werte bekannt.
|
|
|
|
|
*
|
|
|
|
|
* @param u vertikale Gerade
|
|
|
|
|
* @return Liste der Schnittpunkte (da u bekannt werden nur die y Werte zurück gegeben)
|
|
|
|
|
*/
|
2020-03-21 00:37:09 +00:00
|
|
|
|
public List<Double> getEjValues(double u) {
|
2017-09-10 15:45:47 +00:00
|
|
|
|
|
2020-03-21 00:37:09 +00:00
|
|
|
|
List<Double> ret = new ArrayList<>();
|
2017-09-10 15:45:47 +00:00
|
|
|
|
|
2020-03-23 06:58:40 +00:00
|
|
|
|
for (Line p : setOfLines) {
|
2017-09-10 15:45:47 +00:00
|
|
|
|
ret.add((p.getM() * u) + p.getB());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Collections.sort(ret);
|
|
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Die Funktion berechnet anhand einer vertikalen Gerade x = px das sogenannte kleinste kMinus
|
|
|
|
|
* Bracelet. Mit anderen Worten es wird eine vertikale Teilgerade berechnet die mindestens kMinus
|
|
|
|
|
* Geraden schneidet und dabei minimal ist.
|
|
|
|
|
*
|
|
|
|
|
* @param px Koordinate um die "vertikale Gerade" zu simulieren.
|
|
|
|
|
* @return Das Array enthält höhe des Bracelet, e_j und e_(j + kMinus - 1)
|
|
|
|
|
*/
|
|
|
|
|
public Double[] calcKMinusBracelet(Point px, int kMinusValue) {
|
|
|
|
|
|
|
|
|
|
//y Koordinaten für das kMinus brecalet
|
2020-03-21 00:37:09 +00:00
|
|
|
|
List<Double> intersections = new LinkedList<>();
|
2020-03-23 06:58:40 +00:00
|
|
|
|
for (Line line : setOfLines) {
|
2017-09-10 15:45:47 +00:00
|
|
|
|
intersections.add((px.getX() * line.getM()) + line.getB());
|
|
|
|
|
}
|
|
|
|
|
if (intersections.size() >= kMinusValue) {
|
|
|
|
|
Collections.sort(intersections);
|
2020-03-21 00:37:09 +00:00
|
|
|
|
double height = Math.abs(intersections.get(0) - intersections.get(kMinusValue - 1));
|
|
|
|
|
return new Double[]{height, intersections.get(0), intersections.get(kMinusValue - 1)};
|
2017-09-10 15:45:47 +00:00
|
|
|
|
} else {
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
2020-03-21 19:54:03 +00:00
|
|
|
|
private Line pepareResult() {
|
2020-03-21 00:37:09 +00:00
|
|
|
|
if (this.subscriber != null) {
|
2017-09-10 15:45:47 +00:00
|
|
|
|
double m = (getSigmaMin().getX2() + getSigmaMin().getX1()) * 0.5;
|
|
|
|
|
double b = (getSigmaMin().getY2() + getSigmaMin().getY1()) * -0.5;
|
|
|
|
|
|
|
|
|
|
slope = m;
|
|
|
|
|
yInterception = b;
|
|
|
|
|
|
2020-03-21 00:37:09 +00:00
|
|
|
|
AlgorithmData data = new AlgorithmData();
|
|
|
|
|
data.setType(SubscriberType.LMS);
|
|
|
|
|
data.setLineData(new Line(m, b));
|
|
|
|
|
this.subscriber.onNext(data);
|
2017-09-10 15:45:47 +00:00
|
|
|
|
} else {
|
|
|
|
|
double m = (getSigmaMin().getX2() + getSigmaMin().getX1()) * 0.5;
|
|
|
|
|
double b = (getSigmaMin().getY2() + getSigmaMin().getY1()) * -0.5;
|
|
|
|
|
|
|
|
|
|
slope = m;
|
|
|
|
|
yInterception = b;
|
|
|
|
|
}
|
2020-03-21 19:54:03 +00:00
|
|
|
|
|
|
|
|
|
return new Line(getSlope(), getYInterception());
|
2017-09-10 15:45:47 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2017-10-15 13:21:53 +00:00
|
|
|
|
* @return Anzahl der Geraden
|
2017-09-10 15:45:47 +00:00
|
|
|
|
*/
|
|
|
|
|
public int getN() {
|
|
|
|
|
return n;
|
|
|
|
|
}
|
|
|
|
|
|
2017-10-15 13:21:53 +00:00
|
|
|
|
/**
|
|
|
|
|
* @param n Anzahl der Geraden
|
|
|
|
|
*/
|
2017-09-10 15:45:47 +00:00
|
|
|
|
public void setN(int n) {
|
|
|
|
|
this.n = n;
|
|
|
|
|
}
|
|
|
|
|
|
2017-10-15 13:21:53 +00:00
|
|
|
|
/**
|
|
|
|
|
* @param quantileError Parameter quantile Fehler
|
|
|
|
|
*/
|
2017-09-10 15:45:47 +00:00
|
|
|
|
public void setQuantileError(double quantileError) {
|
|
|
|
|
this.quantileError = quantileError;
|
|
|
|
|
}
|
|
|
|
|
|
2017-10-15 13:21:53 +00:00
|
|
|
|
/**
|
|
|
|
|
* @param kMinus kMinus index
|
|
|
|
|
*/
|
2017-09-10 15:45:47 +00:00
|
|
|
|
public void setkMinus(int kMinus) {
|
|
|
|
|
this.kMinus = kMinus;
|
|
|
|
|
}
|
|
|
|
|
|
2017-10-15 13:21:53 +00:00
|
|
|
|
/**
|
|
|
|
|
* @return duale Streifen Sigma_min
|
|
|
|
|
*/
|
2017-09-10 15:45:47 +00:00
|
|
|
|
public Line getSigmaMin() {
|
|
|
|
|
return sigmaMin;
|
|
|
|
|
}
|
|
|
|
|
|
2017-10-15 13:21:53 +00:00
|
|
|
|
/**
|
|
|
|
|
* @param sigmaMin duale Streifen Sigma_min
|
|
|
|
|
*/
|
2017-09-10 15:45:47 +00:00
|
|
|
|
public void setSigmaMin(Line sigmaMin) {
|
|
|
|
|
this.sigmaMin = sigmaMin;
|
|
|
|
|
}
|
|
|
|
|
|
2017-10-15 13:21:53 +00:00
|
|
|
|
/**
|
|
|
|
|
* @param heightsigmaMin höhe von Sigma_min
|
|
|
|
|
*/
|
2017-09-10 15:45:47 +00:00
|
|
|
|
public void setHeightsigmaMin(double heightsigmaMin) {
|
|
|
|
|
this.heightsigmaMin = heightsigmaMin;
|
|
|
|
|
}
|
|
|
|
|
|
2017-10-15 13:21:53 +00:00
|
|
|
|
/**
|
|
|
|
|
* @param constant Parameter Konstante
|
|
|
|
|
*/
|
2017-09-10 15:45:47 +00:00
|
|
|
|
public void setConstant(Double constant) {
|
|
|
|
|
this.constant = constant;
|
|
|
|
|
}
|
|
|
|
|
|
2017-10-15 13:21:53 +00:00
|
|
|
|
/**
|
|
|
|
|
* @return Steigung
|
|
|
|
|
*/
|
2017-09-10 15:45:47 +00:00
|
|
|
|
public Double getSlope() {
|
|
|
|
|
return slope;
|
|
|
|
|
}
|
|
|
|
|
|
2017-10-15 13:21:53 +00:00
|
|
|
|
/**
|
|
|
|
|
* @return y-Achsenabschnitt
|
|
|
|
|
*/
|
2020-03-21 19:54:03 +00:00
|
|
|
|
public Double getYInterception() {
|
2017-09-10 15:45:47 +00:00
|
|
|
|
return yInterception;
|
|
|
|
|
}
|
2020-03-21 00:37:09 +00:00
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public void subscribe(Flow.Subscriber<? super Data> subscriber) {
|
|
|
|
|
this.subscriber = subscriber;
|
|
|
|
|
}
|
2020-03-28 15:24:35 +00:00
|
|
|
|
|
2017-09-10 15:45:47 +00:00
|
|
|
|
}
|