166 lines
5.1 KiB
Java
166 lines
5.1 KiB
Java
package Presenter.Algorithms;
|
|
|
|
import Model.Line;
|
|
import Model.Pair;
|
|
import Model.Point;
|
|
import Model.Slab;
|
|
|
|
import java.util.ArrayList;
|
|
import java.util.Collections;
|
|
import java.util.HashMap;
|
|
import java.util.List;
|
|
|
|
/**
|
|
* Implementierung verschiedener Algorithmen zur Berechnung von Ausgleichsgeraden.
|
|
*
|
|
* @Author: Armin Wolf
|
|
* @Email: a_wolf28@uni-muenster.de
|
|
* @Date: 18.06.2017.
|
|
*/
|
|
public class InversionCounter {
|
|
|
|
private HashMap<Integer, Integer> dictionaryTO;
|
|
private HashMap<Integer, Integer> dictionaryBACK;
|
|
private ArrayList<Integer> substituted;
|
|
private ArrayList<Pair> inversions;
|
|
|
|
//indexieren der Punkte damit die schnittpunkte berechnet werden können
|
|
private HashMap<Integer, Integer> secondaryIndex;
|
|
private ArrayList<Point> umin;
|
|
private ArrayList<Point> umax;
|
|
|
|
|
|
public int run(List<Integer> a, List<Integer> b){
|
|
|
|
dictionaryTO = new HashMap<>();
|
|
dictionaryBACK = new HashMap<>();
|
|
substituted = new ArrayList<>();
|
|
inversions = new ArrayList<>();
|
|
|
|
ArrayList<Integer> temp = new ArrayList<>();
|
|
|
|
temp.addAll(a);
|
|
|
|
for (int i=0;i<a.size();i++){
|
|
dictionaryTO.put(a.get(i), i+1 );
|
|
dictionaryBACK.put(i+1 , a.get(i));
|
|
}
|
|
|
|
for (int j=0;j<b.size();j++){
|
|
substituted.add(dictionaryTO.get(b.get(j)));
|
|
}
|
|
|
|
int ret = countInversions(substituted, 0, substituted.size()-1, temp);
|
|
|
|
dictionaryTO = null;
|
|
substituted = null;
|
|
inversions = null;
|
|
|
|
|
|
return ret;
|
|
}
|
|
|
|
public int run(List<Line> set, Slab slab){
|
|
ArrayList<Integer> listA = new ArrayList<>();
|
|
ArrayList<Integer> listB = new ArrayList<>();
|
|
|
|
prepareData(set, slab, listA, listB);
|
|
return run(listA, listB);
|
|
}
|
|
|
|
|
|
private void prepareData(List<Line> set, Slab slab, ArrayList<Integer> listA, ArrayList<Integer> listB){
|
|
secondaryIndex = new HashMap<>();
|
|
umin = new ArrayList<>();
|
|
umax = new ArrayList<>();
|
|
|
|
int counter = 0;
|
|
for (Line p : set) {
|
|
//vertauscht das Point standardmäßig die x lexikografische Ordnung betrachtet
|
|
umin.add(new Point(slab.getLower() * p.getM() + p.getB(),p.getM(), counter+""));
|
|
umax.add(new Point(slab.getUpper() * p.getM() + p.getB(),p.getM() ,counter+""));
|
|
counter++;
|
|
}
|
|
|
|
for (int i=0; i<umin.size();i++){
|
|
int id = Integer.parseInt(umin.get(i).getId());
|
|
secondaryIndex.put(id, i);
|
|
}
|
|
|
|
Collections.sort(umin);
|
|
Collections.sort(umax);
|
|
|
|
for (Point p : umax){
|
|
int x = Integer.parseInt(p.getId());
|
|
listB.add(secondaryIndex.get(x));
|
|
}
|
|
|
|
for (Point q : umin){
|
|
int x = Integer.parseInt(q.getId());
|
|
listA.add(secondaryIndex.get(x));
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
* Angepasster Merge-Sort Algorithmus.
|
|
* Die Funktion bekommt neben den standard Parametern zusätzlich eine Liste mit Elementen
|
|
* die als Groundtruth dienen.
|
|
* @param a Eingabefeld mit den Elementen die überprüft werden sollen.
|
|
* @param start Startpunkt des Eingabefeldes.
|
|
* @param end Endpunkt des Eingabefeldes.
|
|
* @param aux Groundtruth Ordnung um die Anzahl der Inversionen zu bestimmen.
|
|
* @return Anzahl der inversionen zwischen a und aux.
|
|
*/
|
|
public int countInversions(List<Integer> a, int start, int end, List<Integer> aux) {
|
|
if (start >= end) {
|
|
return 0;
|
|
}
|
|
int invCount = 0;
|
|
int mid = start + (end - start) / 2;
|
|
int invCountLeft = countInversions(a, start, mid, aux); // divide and conquer
|
|
int invCountRight = countInversions(a, mid + 1, end, aux); // divide and conquer
|
|
invCount += (invCountLeft + invCountRight);
|
|
for (int i = start; i <= end; i++) {
|
|
aux.set(i, a.get(i));
|
|
}
|
|
int left = start;
|
|
int right = mid + 1;
|
|
int index = start;
|
|
while (left <= mid && right <= end) {
|
|
if (aux.get(left) < aux.get(right)) {
|
|
a.set(index++, aux.get(left++));
|
|
} else {
|
|
|
|
for (int i=left; i<=mid;i++){
|
|
// System.out.println(aux.get(i)+" -- "+ aux.get(right));
|
|
inversions.add(new Pair(aux.get(i), aux.get(right)));
|
|
}
|
|
a.set(index++, aux.get(right++));
|
|
invCount += mid - left + 1; // number of inversions for aux[right]
|
|
}
|
|
}
|
|
while (left <= mid) {
|
|
a.set(index++, aux.get(left++));
|
|
}
|
|
// no need to copy over remaining aux[right++] because they are already inside a
|
|
return invCount;
|
|
}
|
|
|
|
|
|
public ArrayList<Pair> getInversionPairs(){
|
|
ArrayList<Pair> result = new ArrayList<>();
|
|
|
|
for (int i=0;i<inversions.size();i++){
|
|
result.add(new Pair(dictionaryBACK.get(inversions.get(i).getP1()), dictionaryBACK.get(inversions.get(i).getP2())));
|
|
}
|
|
//for (Pair p : result){
|
|
// System.out.println(p.getP1() + " <==> " + p.getP2());
|
|
//}
|
|
|
|
|
|
return result;
|
|
}
|
|
|
|
}
|