package Presenter.Algorithms; import Model.Line; import Model.Slab; import Presenter.InversionCounter; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.LinkedList; import java.util.concurrent.ThreadLocalRandom; /** * Implementierung verschiedener Algorithmen zur Berechnung von Ausgleichsgeraden. * * @Author: Armin Wolf * @Email: a_wolf28@uni-muenster.de * @Date: 28.05.2017. */ public class RepeatedMedianEstimator implements Algorithm { private LinkedList set; private HashMap> linePairs; private HashMap medianIntersections = new HashMap<>(); private HashMap> intersectionAbscissas = new HashMap<>(); private Slab interval; //in der Literatur als L_i, C_i, und R_i bekannt private ArrayList countLeftSlab; private ArrayList countCenterSlab; private ArrayList countRightSlab; //die Mengen L,C und R private ArrayList linesInLeftSlab; private ArrayList linesInCenterSlab; private ArrayList linesInRightSlab; private Double r; private Integer n; private Double k; private Double kLow; private Double kHigh; private Double beta; private Double thetaLow; private Double thetaHigh; public RepeatedMedianEstimator(LinkedList set) { this.set = set; interval = new Slab(-10000, 10000); n = set.size(); beta = 0.5; countLeftSlab = new ArrayList<>(); countCenterSlab = new ArrayList<>(); countRightSlab = new ArrayList<>(); for (int i = 0; i < n; i++) { countLeftSlab.add(0); countRightSlab.add(0); countCenterSlab.add(n - 1); intersectionAbscissas.put(set.get(i), new ArrayList<>()); } linesInLeftSlab = new ArrayList<>(); linesInCenterSlab = new ArrayList<>(set); linesInRightSlab = new ArrayList<>(); linePairs = new HashMap<>(); } /** * */ public void run() { while (linesInCenterSlab.size() != 1) { r = Math.ceil(Math.pow(n, beta)); ArrayList lines = sampleLines(linesInCenterSlab, r); InversionCounter invCounter = new InversionCounter(); //int intersectionCount = invCounter.run(lines, interval); //For each Sampled Line, compute its median intersection abscissa ArrayList medianIntersectionAbscissas = new ArrayList<>(); for (Line l : lines) { Double abscissa = estimateMedianIntersectionAbscissas(l); medianIntersections.put(l, abscissa); medianIntersectionAbscissas.add(abscissa); } //rank of the repeated median in C k = (Math.floor(n * 0.5) - linesInLeftSlab.size()); //compute k_lo and k_hi computeSlabBorders(); //Employ fast selection algorithm to determine the Elements Theta_lo and Theta_hi thetaLow = randomizedSelect(medianIntersectionAbscissas, 0, medianIntersectionAbscissas.size() - 1, kLow); thetaHigh = randomizedSelect(medianIntersectionAbscissas, 0, medianIntersectionAbscissas.size() - 1, kHigh); //For each dual Line in C count the number of intersection abscissas that lie //in each of the intervals. countNumberOfIntersectionsAbscissas(); //Based on this 3 counts, determine which of the subintervals contains the repeated median //and contract to this subiinterval. contractIntervals(); } System.out.println( "Ergebnis: " + thetaLow * (-1) + " * x + " + ( (linesInCenterSlab.get(0).getM() * (thetaLow * (-1))) + linesInCenterSlab.get(0) .getB())); } /** * * @param set * @param r * @return */ public ArrayList sampleLines(ArrayList set, Double r) { ArrayList sampledLines = new ArrayList<>(); for (int i = 0; i < r; i++) { sampledLines.add(set.get(ThreadLocalRandom.current().nextInt(0, linesInCenterSlab.size()))); } return sampledLines; } /** * * @param sampledLine * @return */ public Double estimateMedianIntersectionAbscissas(Line sampledLine) { Integer index = Integer.parseInt(sampledLine.getId()); ArrayList intersections = new ArrayList<>(); double intersection; for (Line line : linesInCenterSlab) { if (line != sampledLine) { intersection = (line.getB() - sampledLine.getB()) / (sampledLine.getM() - line.getM()); if (!intersectionAbscissas.get(line).contains(intersection)) intersectionAbscissas.get(line).add(intersection); if (!intersectionAbscissas.get(sampledLine).contains(intersection)) intersectionAbscissas.get(sampledLine).add(intersection); intersections.add(intersection); } } Collections.sort(intersections); double ki = Math.ceil((n - 1) / 2) - countLeftSlab.get(index); double i = (Math.ceil((Math.sqrt(n) * ki) / countCenterSlab.get(index))); int accessIndex; if (i < 0) accessIndex = 0; else if (i >= intersections.size()) accessIndex = intersections.size()-1; else accessIndex = (int) i; System.out.println(accessIndex); return intersections.get(accessIndex); } /** * */ public void computeSlabBorders() { kLow = Math .max(1, Math.floor(((r * k) / (linesInCenterSlab.size())) - ((3 * Math.sqrt(r)) / (2)))); kHigh = Math .min(r, Math.floor(((r * k) / (linesInCenterSlab.size())) + ((3 * Math.sqrt(r)) / (2)))); } /** * * @param a * @param start * @param end * @param i * @return */ public Double randomizedSelect(ArrayList a, int start, int end, double i) { if (start == end) { return a.get(start); } int q = randomizedPartition(a, start, end); int tmpPivot = q - start + 1; if (i == tmpPivot) { return a.get(q); } else if (i < tmpPivot) { return randomizedSelect(a, start, q - 1, i); } else { return randomizedSelect(a, q + 1, end, i - tmpPivot); } } /** * * @param a * @param start * @param end * @return */ public int randomizedPartition(ArrayList a, int start, int end) { int delta = Math.abs(end - start); int i = start + ThreadLocalRandom.current().nextInt(0, delta); Collections.swap(a, end, i); return partition(a, start, end); } /** * * @param a * @param start * @param end * @return */ public int partition(ArrayList a, int start, int end) { Double x = a.get(end); int i = start - 1; for (int j = start; j < end; j++) { if (a.get(j) <= x) { i++; Collections.swap(a, i, j); } } Collections.swap(a, i + 1, end); return i + 1; } /** * */ public void countNumberOfIntersectionsAbscissas() { for (Line line : linesInCenterSlab) { ArrayList intersections = intersectionAbscissas.get(line); Integer 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++; } } System.out.println("Linie: "+line.getId()+"\tLeft: "+left+"\t Center: "+center+"\t Right: "+right); countLeftSlab.set(index, left); countCenterSlab.set(index, center); countRightSlab.set(index, right); } } /** * */ public void contractIntervals() { //if (linesInLeftSlab.size() < Math.floor(n / 2) && Math.floor(n / 2) <= (linesInLeftSlab.size() // + linesInCenterSlab.size())) { for (int i = 0; i < linesInCenterSlab.size(); i++) { int left = countLeftSlab.get(i); int center = countCenterSlab.get(i); int right = countRightSlab.get(i); int 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); } // if (medianIntersections.get(linesInCenterSlab.get(i)) != null) { // if (medianIntersections.get(linesInCenterSlab.get(i)) <= thetaLow) { // linesInLeftSlab.add(linesInCenterSlab.get(i)); // linesInCenterSlab.remove(i); // countLeftSlab.set(i, countLeftSlab.get(i) + 1); // countCenterSlab.set(i, countCenterSlab.get(i) - 1); // } else if (medianIntersections.get(linesInCenterSlab.get(i)) > thetaHigh) { // linesInRightSlab.add(linesInCenterSlab.get(i)); // linesInCenterSlab.remove(i); // countRightSlab.set(i, countRightSlab.get(i) + 1); // countCenterSlab.set(i, countCenterSlab.get(i) - 1); // } // } // } // } //wähle C als C if (linesInLeftSlab.size() < Math.ceil(n/2) && Math.ceil(n/2) <= linesInLeftSlab.size()+linesInCenterSlab.size()){ interval.setLower(thetaLow + 0.1); interval.setUpper(thetaHigh); } // wähle L als C else if (Math.ceil(n/2) <= linesInLeftSlab.size()){ interval.setUpper(thetaLow); } //wähle R als C else if (linesInLeftSlab.size()+linesInCenterSlab.size() < Math.ceil(n/2) && Math.ceil(n/2) <= (linesInLeftSlab.size()+linesInCenterSlab.size()+linesInRightSlab.size()) ){ interval.setLower(thetaHigh - 0.1); } } }