Merge branch 'powersort_M'

# Conflicts:
#	.idea/misc.xml
This commit is contained in:
M-H9 2024-12-11 14:01:56 +01:00
commit 2a3e3b3354
9 changed files with 337 additions and 2 deletions

2
.idea/misc.xml generated
View File

@ -3,5 +3,5 @@
<component name="FrameworkDetectionExcludesConfiguration">
<file type="web" url="file://$PROJECT_DIR$" />
</component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_23" project-jdk-name="openjdk-23" project-jdk-type="JavaSDK" />
<component name="ProjectRootManager" version="2" languageLevel="JDK_23" default="true" project-jdk-name="23" project-jdk-type="JavaSDK" />
</project>

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,298 @@
package de.uni_marburg.powersort.msort;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.stream.IntStream;
public class IMPL_M_1 {
private IMPL_M_1() {}
/**
* Sorts the given range, using the given workspace array slice
* for temp storage when possible. This method is designed to be
* invoked from public methods (in class Arrays) after performing
* any necessary array bounds checks and expanding parameters into
* the required forms.
*
* @param a the array to be sorted
* @param lo the index of the first element, inclusive, to be sorted
* @param hi the index of the last element, exclusive, to be sorted
* @param c the comparator to use
* @param work a workspace array (slice)
* @param workBase origin of usable space in work array
* @param workLen usable size of work array
* @since 1.8
*/
protected static int MERGE_COST = 0;
// Example usage
// int[] runs = new int[] {5, 3, 3, 14, 1, 2}; // example from slides
// //runs = new int[]{9, 16, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7};
//
// ArrayList<Integer> a = new ArrayList<>(IntStream.range(0, Arrays.stream(runs).sum()).boxed().collect(Collectors.toList()));
//
// System.out.println();
// fillWithAscRunsHighToLow(a, runs);
// MERGE_COST = 0;
// System.out.println("Sorting with Powersort:");
// powersort(a, this::extendRunIncreasingOnly);
// System.out.println("Merge cost: " + MERGE_COST);
// runs = [5,3,3,14,1,2];
// runs = [9,16,7,7,7,7,7,7,7,7,7,7];
//
// a = list(range(sum(runs)));
// fill_with_asc_runs_high_to_low(a, runs);
// MERGE_COST = 0;
// System.out.println("Sorting with Powersort:");
// powersort(a, extendRunIncreasingOnly);
// System.out.println("Merge cost: " + MERGE_COST);
public static void fillWithAscRunsHighToLow(List<Integer> A, int[] runLengths, int runLenFactor) {
int n = A.size();
assert IntStream.of(runLengths).sum() * runLenFactor == n;
for (int i = 0; i < n; i++) {
A.set(i, n - i);
}
int i = 0;
for (int l : runLengths) {
int L = l * runLenFactor;
List<Integer> sublist = A.subList(i, i + L);
Collections.sort(sublist);
i += L;
}
}
private static List<Integer> merge(List<Integer> run1, List<Integer> run2) {
List<Integer> result = new ArrayList<>();
while (!run1.isEmpty() && !run2.isEmpty()) {
if (run1.get(0) < run2.get(0)) {
result.add(run1.remove(0));
} else {
result.add(run2.remove(0));
}
}
result.addAll(run1);
result.addAll(run2);
return result;
}
private static void mergeInplace(List<Integer> a, int i, int m, int j) {
System.out.printf("Merge(%d, %d, %d)%n", i, m, j);
MERGE_COST += j - i;
List<Integer> sublist = merge(
new ArrayList<>(a.subList(i, m)),
new ArrayList<>(a.subList(m, j))
);
for (int k = 0; k < sublist.size(); k++) {
a.set(i + k, sublist.get(k));
}
}
static int extendRun(List<Integer> a, int i) {
if (i == a.size() - 1) {
return i + 1;
}
int j = i + 1;
if (a.get(i) <= a.get(j)) {
while (j < a.size() && a.get(j - 1) <= a.get(j)) {
j++;
}
} else {
while (j < a.size() && a.get(j - 1) > a.get(j)) {
j++;
}
List<Integer> sublist = a.subList(i, j);
Collections.reverse(sublist);
}
return j;
}
private static int extendRunIncreasingOnly(List<Integer> a, int i) {
if (i == a.size() - 1) {
return i + 1;
}
int j = i + 1;
while (j < a.size() && a.get(j - 1) <= a.get(j)) {
j++;
}
return j;
}
public static int power(int[] run1, int[] run2, int n) {
int i1 = run1[0], n1 = run1[1];
int i2 = run2[0], n2 = run2[1];
assert i1 >= 0;
assert i2 == i1 + n1;
assert n1 >= 1 && n2 >= 1;
assert i2 + n2 <= n;
double a = ((i1 + n1 / 2.0d) / n);
double b = ((i2 + n2 / 2.0d) / n);
int l = 0;
while (Math.floor(a * Math.pow(2, l)) == Math.floor(b * Math.pow(2, l))) {
l++;
}
return l;
}
public static int powerFast(int[] run1, int[] run2, int n) {
int i1 = run1[0], n1 = run1[1];
int i2 = run2[0], n2 = run2[1];
int a = 2 * i1 + n1;
int b = a + n1 + n2;
int l = 0;
while (true) {
l++;
if (a >= n) {
assert b >= a;
a -= n;
b -= n;
} else if (b >= n) {
break;
}
assert a < b && b < n;
a <<= 1;
b <<= 1;
}
return l;
}
public static void mergeTopmost2(List<Integer> a, List<int[]> runs) {
assert runs.size() >= 2;
int[] Y = runs.get(runs.size() - 2);
int[] Z = runs.get(runs.size() - 1);
assert Z[0] == Y[0] + Y[1];
mergeInplace(a, Y[0], Z[0], Z[0] + Z[1]);
runs.set(runs.size() - 2, new int[] {Y[0], Y[1] + Z[1], Y[2]});
runs.remove(runs.size() - 1);
}
public static void powerSort(List<Integer> a) {
int n = a.size();
int i = 0;
List<int[]> runs = new ArrayList<>();
int j = extendRun(a, i);
runs.add(new int[] {i, j - i, 0});
i = j;
while (i < n) {
j = extendRun(a, i);
int p = power(runs.get(runs.size() - 1), new int[] {i, j - i}, n);
while (p <= runs.get(runs.size() - 1)[2]) {
mergeTopmost2(a, runs);
}
runs.add(new int[] {i, j - i, p});
i = j;
}
while (runs.size() >= 2) {
mergeTopmost2(a, runs);
}
}
/* """Fills the given array A with ascending runs of the given list of run
lengths.
More precisely, the array is first filled n, n-1, ..., 1
and then for i=0..l-1 segments of runLengths.get(i) * runLenFactor
are sorted ascending.
The sum of all lengths in runLengths times runLenFactor should be equal to the
length of A.
"""*/
/* static <T> void sort(T[] a, int lo, int hi, Comparator<? super T> c,
T[] work, int workBase, int workLen) {
assert c != null && a != null && lo >= 0 && lo <= hi && hi <= a.length;
}*/
/*
public static final int MIN_MERGE=24;
public int mergeCost=0;
private final T []sortedArray;
public PowerSort(T[] sortedArray) {
super();
this.sortedArray = sortedArray;
}
ArrayList<Integer> run1 = new ArrayList<>();
ArrayList<Integer> run2 = new ArrayList<>();
private AbstractList<Integer> merge(ArrayList <Integer> run1, ArrayList<Integer> run2) {
ArrayList<Integer> result = new ArrayList<>();
while(run1.size() > 0 && run2.size() >0) {
if (run1.getFirst()<run2.getFirst()){
result.add(run1.getFirst());
run1.removeFirst();
}else {
result.add(run2.getFirst());
run2.removeFirst();
}
result.addAll(run1);
result.addAll(run2);
}
return result;
}
public void mergeInplace(int[] a, int[] i, int[] m, int[] j) {
//System.out.println("merge(" + i + "," + m + "," + j + ")");
System.out.printf("Merge(%d, %d, %d)%n", i, m, j);
// this.mergeCost += j - i;
for(int s =0; s < i.length && s< j.length ; s++) {
// int[] leftSubarray = copyOfRange(a, i, m);
// int[] rightSubarray = copyOfRange(a, m, j);
// int[] mergedSubarray = merge(leftSubarray, rightSubarray);
// System.arraycopy(mergedSubarray, 0, a, i, mergedSubarray.length);
//// mergeCost += j[s] - i[s];
// System.arraycopy(merge(Arrays.copyOfRange(a, i, m), Arrays.copyOfRange(a, m, j)), 0, a, i, j - i);
// a[i:j]=merge(a[i:m],a[m:j]);
}
}
public void power(int run1,int run2, int n) {
int i = run1;
int n1 = run1;
int j = run2;
int n2 = run2;
int a=(i + n1/2) / n;
int b=(j + n2/2) / n;
int l =0;
//while( Math.floor(a * 2**1)){
// Math.floor(b * );
// }
}
public void sorting(final int[] Array, final int left, final int right) {
}*/
}

View File

@ -0,0 +1,37 @@
package de.uni_marburg.powersort.msort;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import org.junit.jupiter.api.Test;
import static de.uni_marburg.powersort.msort.IMPL_M_1.MERGE_COST;
import static de.uni_marburg.powersort.msort.IMPL_M_1.extendRun;
import static de.uni_marburg.powersort.msort.IMPL_M_1.fillWithAscRunsHighToLow;
import static de.uni_marburg.powersort.msort.IMPL_M_1.powerSort;
class PowerSortTest {
@Test
public void testWithOneInputList() {
List<Integer> list = new ArrayList<>(List.of(5, 2, 8, 12, 1, 6));
extendRun(list, 0);
System.out.println(list);
// example from slides he wrote this
int[] runs = {5, 3, 3, 14, 1, 2};
// runs = new int[]{9, 16, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7};
List<Integer> a = new ArrayList<>(IntStream.range(0, Arrays.stream(runs).sum()).boxed().collect(Collectors.toList()));
System.out.println();
fillWithAscRunsHighToLow(a, runs, 1);
MERGE_COST = 0;
System.out.println("Sorting with Powersort:");
powerSort(a);
System.out.println("Merge cost: " + MERGE_COST);
}
}