2 new algorithms and renaming old ones to better describe them

master
Selebrator 7 years ago
parent 8d213feecb
commit 0164050f66

@ -0,0 +1,33 @@
package _12._1.lukas;
import provided._12._1.Fibonacci;
/*
* F(2n) = F(n) * (2*F(n+1) - F(n)).
* F(2n+1) = F(n+1)^2 + F(n)^2.
*
* O(log(n))
*/
public class FibonacciDoubling extends Fibonacci {
@Override
public long calculate(int n) {
if(n < 0) {
throw new IllegalArgumentException("n must not be negative. Negafibonacci numbers are not supported.");
}
long a = 0L;
long b = 1L;
for(int bit = Integer.highestOneBit(n); bit != 0; bit >>>= 1) {
long aTemp = a * ((2 * b) - a);
long bTemp = a * a + b * b;
a = aTemp;
b = bTemp;
if((n & bit) != 0) {
long c = a + b;
a = b;
b = c;
}
}
return a;
}
}

@ -0,0 +1,20 @@
package _12._1.lukas;
import provided._12._1.Fibonacci;
// iterative, dynamic programing with minimal memory usage
public class FibonacciDynamicIterative extends Fibonacci {
@Override
public long calculate(int n) {
if(n < 0) {
throw new IllegalArgumentException("n must not be negative. Negafibonacci numbers are not supported.");
}
long a = 0L, b = 1L, c;
for(int i = 0; i < n; i++) {
c = a + b;
a = b;
b = c;
}
return a;
}
}

@ -5,12 +5,13 @@ import provided._12._1.Fibonacci;
import java.util.HashMap;
import java.util.Map;
public class FibonacciDynamic extends Fibonacci {
private static final Map<Integer, Long> memory = new HashMap<>();
// uses recursion and dynamic programing with persistent memory
public class FibonacciDynamicRecursivePersistent extends Fibonacci {
private final Map<Integer, Long> memory = new HashMap<>();
static {
memory.put(0, 0L);
memory.put(1, 1L);
{
this.memory.put(0, 0L);
this.memory.put(1, 1L);
}
@ -19,12 +20,12 @@ public class FibonacciDynamic extends Fibonacci {
if(n < 0) {
throw new IllegalArgumentException("n must not be negative. Negafibonacci numbers are not supported.");
}
if(memory.containsKey(n)) {
return memory.get(n);
if(this.memory.containsKey(n)) {
return this.memory.get(n);
}
long result = calculate(n - 1) + calculate(n - 2);
memory.put(n, result);
this.memory.put(n, result);
return result;
}
}

@ -5,12 +5,13 @@ import provided._12._1.Fibonacci;
import java.util.HashMap;
import java.util.Map;
public class FibonacciParallelDynamic extends Fibonacci {
private static final Map<Integer, Long> memory = new HashMap<>();
// eats up the heap
public class FibonacciDynamicRecursivePersistentParallel extends Fibonacci {
private final Map<Integer, Long> memory = new HashMap<>();
static {
memory.put(0, 0L);
memory.put(1, 1L);
{
this.memory.put(0, 0L);
this.memory.put(1, 1L);
}
@Override
@ -18,8 +19,8 @@ public class FibonacciParallelDynamic extends Fibonacci {
if(n < 0) {
throw new IllegalArgumentException("n must not be negative. Negafibonacci numbers are not supported.");
}
if(memory.containsKey(n)) {
return memory.get(n);
if(this.memory.containsKey(n)) {
return this.memory.get(n);
}
final long result;
@ -39,7 +40,7 @@ public class FibonacciParallelDynamic extends Fibonacci {
}
}
memory.put(n, result);
this.memory.put(n, result);
return result;
}
}

@ -2,7 +2,8 @@ package _12._1.lukas;
import provided._12._1.Fibonacci;
public class FibonacciParallelRecursive extends Fibonacci {
// rest in peace ram
public class FibonacciRecursiveParallel extends Fibonacci {
@Override
public long calculate(int n) {
if(n < 0) {

@ -6,39 +6,50 @@ public class FibonacciTiming {
private static final int[] NUMBERS = new int[]{ 3, 5, 8, 12, 9, 18, 15, 10, 7, 11, 20 };
private static final Fibonacci RECURSIVE = new FibonacciRecursive();
private static final Fibonacci PARALLEL_RECURSIVE = new FibonacciParallelRecursive();
private static final Fibonacci DYNAMIC = new FibonacciDynamic();
private static final Fibonacci PARALLEL_DYNAMIC = new FibonacciParallelDynamic();
private static final Fibonacci PARALLEL_RECURSIVE = new FibonacciRecursiveParallel();
private static final Fibonacci DYNAMIC = new FibonacciDynamicRecursivePersistent();
private static final Fibonacci PARALLEL_DYNAMIC = new FibonacciDynamicRecursivePersistentParallel();
private static final Fibonacci ITERATIVE = new FibonacciDynamicIterative();
// can take a few minutes
public static void main(String[] args) {
System.out.println("# Sequential");
System.out.println("FibonacciRecursive (first): " + formatTime(
Timing.measureNanos(() -> runOnNumbers(RECURSIVE))
Timing.measureNanos(() -> generateHeat(RECURSIVE))
));
System.out.println("FibonacciParallelRecursive (first): " + formatTime(
Timing.measureNanos(() -> runOnNumbers(PARALLEL_RECURSIVE))
System.out.println("FibonacciDynamicRecursivePersistent (first): " + formatTime(
Timing.measureNanos(() -> generateHeat(DYNAMIC))
));
System.out.println("FibonacciDynamic (first): " + formatTime(
Timing.measureNanos(() -> runOnNumbers(DYNAMIC))
));
System.out.println("FibonacciParallelDynamic (first): " + formatTime(
Timing.measureNanos(() -> runOnNumbers(PARALLEL_DYNAMIC))
System.out.println("FibonacciDynamicIterative (first): " + formatTime(
Timing.measureNanos(() -> generateHeat(ITERATIVE))
));
System.out.println("FibonacciRecursive (1M iteration average): " + formatTime(
Timing.measureAverageNanos(1000000, () -> runOnNumbers(RECURSIVE))
Timing.measureAverageNanos(1_000_000, () -> generateHeat(RECURSIVE))
));
System.out.println("FibonacciDynamicRecursivePersistent (1M iteration average): " + formatTime(
Timing.measureAverageNanos(1_000_000, () -> generateHeat(DYNAMIC))
));
System.out.println("FibonacciDynamicIterative (1M iteration average): " + formatTime(
Timing.measureAverageNanos(1_000_000, () -> generateHeat(ITERATIVE))
));
System.out.println("# Parallel");
System.out.println("FibonacciRecursiveParallel (first): " + formatTime(
Timing.measureNanos(() -> generateHeat(PARALLEL_RECURSIVE))
));
System.out.println("FibonacciParallelRecursive (4 iteration average): " + formatTime(
Timing.measureAverageNanos(4, () -> runOnNumbers(PARALLEL_RECURSIVE))
System.out.println("FibonacciDynamicRecursivePersistentParallel (first): " + formatTime(
Timing.measureNanos(() -> generateHeat(PARALLEL_DYNAMIC))
));
System.out.println("FibonacciDynamic (1M iteration average): " + formatTime(
Timing.measureAverageNanos(1000000, () -> runOnNumbers(DYNAMIC))
System.out.println("FibonacciRecursiveParallel (10 iteration average): " + formatTime(
Timing.measureAverageNanos(10, () -> generateHeat(PARALLEL_RECURSIVE))
));
System.out.println("FibonacciParallelDynamic (1K iteration average): " + formatTime(
Timing.measureAverageNanos(1000, () -> runOnNumbers(PARALLEL_DYNAMIC))
System.out.println("FibonacciDynamicRecursivePersistentParallel (1M iteration average): " + formatTime(
Timing.measureAverageNanos(1_000_000, () -> generateHeat(PARALLEL_DYNAMIC))
));
}
private static void runOnNumbers(Fibonacci calculator) {
private static void generateHeat(Fibonacci calculator) {
for(int n : NUMBERS) {
calculator.calculate(n);
}
@ -53,7 +64,7 @@ public class FibonacciTiming {
} else if(digits > 3) {
return Math.round(nanos / 1e1) / 1e2 + " microseconds";
} else {
return Math.round(nanos) + " nanosecond";
return Math.round(nanos) + " nanoseconds";
}
}
}

@ -28,20 +28,32 @@ public class FibonacciTest {
}
@Test
void parallelRecursive() {
Fibonacci calculator = new FibonacciParallelRecursive();
void recursiveParallel() {
Fibonacci calculator = new FibonacciRecursiveParallel();
NUMBERS.forEach((n, fn) -> Assertions.assertEquals(fn.longValue(), calculator.calculate(n)));
}
@Test
void dynamic() {
Fibonacci calculator = new FibonacciDynamic();
void dynamicRecursivePersistent() {
Fibonacci calculator = new FibonacciDynamicRecursivePersistent();
NUMBERS.forEach((n, fn) -> Assertions.assertEquals(fn.longValue(), calculator.calculate(n)));
}
@Test
void parallelDynamic() {
Fibonacci calculator = new FibonacciParallelDynamic();
void dynamicRecursivePersistentParallel() {
Fibonacci calculator = new FibonacciDynamicRecursivePersistentParallel();
NUMBERS.forEach((n, fn) -> Assertions.assertEquals(fn.longValue(), calculator.calculate(n)));
}
@Test
void dynamicIterative() {
Fibonacci calculator = new FibonacciDynamicIterative();
NUMBERS.forEach((n, fn) -> Assertions.assertEquals(fn.longValue(), calculator.calculate(n)));
}
@Test
void doubling() {
Fibonacci calculator = new FibonacciDoubling();
NUMBERS.forEach((n, fn) -> Assertions.assertEquals(fn.longValue(), calculator.calculate(n)));
}
}

Loading…
Cancel
Save