Strange Behavior in F# Parallel Sequence - f#

I have written the following code to generate all possible combinations of some numbers:
let allCombinations (counts:int[]) =
let currentPositions = Array.create (counts.Length) 0
let idx = ref (counts.Length-1)
seq{
while currentPositions.[0]<counts.[0] do
yield currentPositions
currentPositions.[!idx]<-currentPositions.[!idx]+1
while currentPositions.[!idx] >= counts.[!idx] && !idx>=1 do
currentPositions.[!idx]<-0
idx:=!idx-1
currentPositions.[!idx]<-currentPositions.[!idx]+1
idx:=counts.Length-1
}
I am consuming the sequence in some other part of the program like this:
allCombinations counts |> Seq.map (fun idx -> buildGuess n digitsPerPos idx) ...
So far so good. The programs runs as expected and generates the combinations. For input [|2;2;2|] it generates the eight values:
[|0; 0; 0|]
[|0; 0; 1|]
[|0; 1; 0|]
[|0; 1; 1|]
[|1; 0; 0|]
[|1; 0; 1|]
[|1; 1; 0|]
[|1; 1; 1|]
However when I use PSeq to parallelise the generated sequence all values to be consumed change to [|2;0;0|] which is the last value of the currentPositions array in the while loop above.
If i use
yield (currentPositions|>Array.copy)
instead of
yield currentPositions
everything works ok in both sequential and parallel versions.
Why does this happen; Is there a most efficient way to yield the result; Thank you in advance;

The problem is that you're creating a single array which you're mutating between iterations.
You can take the parallelism out of the equation by building a list of the results instead of printing them out one by one - if you build the list first and then print them all, you'll see the same result; the list will contain the same reference 8 times, always to the same array instance.
Basically to avoid side-effects, you need each result to be independent of the other - so you should create a separate array each time.

Related

Why doesn't this Fibonacci Number function work in O(log N)?

So the Fibonacci number for log (N) — without matrices.
Ni // i-th Fibonacci number
= Ni-1 + Ni-2 // by definition
= (Ni-2 + Ni-3) + Ni-2 // unwrap Ni-1
= 2*Ni-2 + Ni-3 // reduce the equation
= 2*(Ni-3 + Ni-4) + Ni-3 //unwrap Ni-2
// And so on
= 3*Ni-3 + 2*Ni-4
= 5*Ni-4 + 3*Ni-5
= 8*Ni-5 + 5*Ni-6
= Nk*Ni-k + Nk-1*Ni-k-1
Now we write a recursive function, where at each step we take k~=I/2.
static long N(long i)
{
if (i < 2) return 1;
long k=i/2;
return N(k) * N(i - k) + N(k - 1) * N(i - k - 1);
}
Where is the fault?
You get a recursion formula for the effort: T(n) = 4T(n/2) + O(1). (disregarding the fact that the numbers get bigger, so the O(1) does not even hold). It's clear from this that T(n) is not in O(log(n)). Instead one gets by the master theorem T(n) is in O(n^2).
Btw, this is even slower than the trivial algorithm to calculate all Fibonacci numbers up to n.
The four N calls inside the function each have an argument of around i/2. So the length of the stack of N calls in total is roughly equal to log2N, but because each call generates four more, the bottom 'layer' of calls has 4^log2N = O(n2) Thus, the fault is that N calls itself four times. With only two calls, as in the conventional iterative method, it would be O(n). I don't know of any way to do this with only one call, which could be O(log n).
An O(n) version based on this formula would be:
static long N(long i) {
if (i<2) {
return 1;
}
long k = i/2;
long val1;
long val2;
val1 = N(k-1);
val2 = N(k);
if (i%2==0) {
return val2*val2+val1*val1;
}
return val2*(val2+val1)+val1*val2;
}
which makes 2 N calls per function, making it O(n).
public class fibonacci {
public static int count=0;
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
int i = scan.nextInt();
System.out.println("value of i ="+ i);
int result = fun(i);
System.out.println("final result is " +result);
}
public static int fun(int i) {
count++;
System.out.println("fun is called and count is "+count);
if(i < 2) {
System.out.println("function returned");
return 1;
}
int k = i/2;
int part1 = fun(k);
int part2 = fun(i-k);
int part3 = fun(k-1);
int part4 = fun(i-k-1);
return ((part1*part2) + (part3*part4)); /*RESULT WILL BE SAME FOR BOTH METHODS*/
//return ((fun(k)*fun(i-k))+(fun(k-1)*fun(i-k-1)));
}
}
I tried to code to problem defined by you in java. What i observed is that complexity of above code is not completely O(N^2) but less than that.But as per conventions and standards the worst case complexity is O(N^2) including some other factors like computation(division,multiplication) and comparison time analysis.
The output of above code gives me information about how many times the function
fun(int i) computes and is being called.
OUTPUT
So including the time taken for comparison and division, multiplication operations, the worst case time complexity is O(N^2) not O(LogN).
Ok if we use Analysis of the recursive Fibonacci program technique.Then we end up getting a simple equation
T(N) = 4* T(N/2) + O(1)
where O(1) is some constant time.
So let's apply Master's method on this equation.
According to Master's method
T(n) = aT(n/b) + f(n) where a >= 1 and b > 1
There are following three cases:
If f(n) = Θ(nc) where c < Logba then T(n) = Θ(nLogba)
If f(n) = Θ(nc) where c = Logba then T(n) = Θ(ncLog n)
If f(n) = Θ(nc) where c > Logba then T(n) = Θ(f(n))
And in our equation a=4 , b=2 & c=0.
As case 1 c < logba => 0 < 2 (which is log base 2 and equals to 2) is satisfied
hence T(n) = O(n^2).
For more information about how master's algorithm works please visit: Analysis of Algorithms
Your idea is correct, and it will perform in O(log n) provided you don't compute the same formula
over and over again. The whole point of having N(k) * N(i-k) is to have (k = i - k) so you only have to compute one instead of two. But if you only call recursively, you are performing the computation twice.
What you need is called memoization. That is, store every value that you already have computed, and
if it comes up again, then you get it in O(1).
Here's an example
const int MAX = 10000;
// memoization array
int f[MAX] = {0};
// Return nth fibonacci number using memoization
int fib(int n) {
// Base case
if (n == 0)
return 0;
if (n == 1 || n == 2)
return (f[n] = 1);
// If fib(n) is already computed
if (f[n]) return f[n];
// (n & 1) is 1 iff n is odd
int k = n/2;
// Applying your formula
f[n] = fib(k) * fib(n - k) + fib(k - 1) * fib(n - k - 1);
return f[n];
}

F sharp KMP Algorithm is stuck in the first while loop if i use a pattern with the same characters at the first two indces

I am playing around with the KMP algorithm in f sharp. While it works for patterns like "ATAT" (result will be [|0; 0; 1; 2;|]) , the first while loop enters a deadlock when the first 2 characters of a string are the same and the 3rd is another, for example "AAT".
I understand why: first, i gets incremented to 1. now the first condition for the while loop is true, while the second is also true, because "A" <> "T". Now it sets i to prefixtable.[!i], which is 1 again, and here we go.
Can you guys give me a hint on how to solve this?
let kMPrefix (pattern : string) =
let (m : int) = pattern.Length - 1
let prefixTable = Array.create pattern.Length 0
// i : longest proper prefix that is also a suffix
let i = ref 0
// j: the index of the pattern for which the prefix value will be calculated
// starts with 1 because the first prefix value is always 0
for j in 1 .. m do
while !i > 0 && pattern.[!i] <> pattern.[j] do
i := prefixTable.[!i]
if pattern.[!i] = pattern.[j] then
i := !i+1
Array.set prefixTable j !i
prefixTable
I'm not sure how to repair the code with a small modification, since it doesn't match the KMP algorithm's lookup table contents (at least the ones I've found on Wikipedia), which are:
-1 for index 0
Otherwise, the count of consecutive elements before the current position that match the beginning (excluding the beginning itself)
Therefore, I'd expect output for "ATAT" to be [|-1; 0; 0; 1|], not [|0; 0; 1; 2;|].
This type of problem might be better to reason about in functional style. To create the KMP table, you could use a recursive function that fills the table one by one, keeping track of how many recent characters match the beginning, and start running it at the second character's index.
A possible implementation:
let buildKmpPrefixTable (pattern : string) =
let prefixTable = Array.zeroCreate pattern.Length
let rec run startIndex matchCount =
let writeIndex = startIndex + matchCount
if writeIndex < pattern.Length then
if pattern.[writeIndex] = pattern.[matchCount] then
prefixTable.[writeIndex] <- matchCount
run startIndex (matchCount + 1)
else
prefixTable.[writeIndex] <- matchCount
run (writeIndex + 1) 0
run 1 0
if pattern.Length > 0 then prefixTable.[0] <- -1
prefixTable
This approach isn't in danger of any endless loops/recursion, because all code paths of run either increase writeIndex in the next iteration or finish iterating.
Note on terminology: the error you are describing in the question is an endless loop or, more generally, non-terminating iteration. Deadlock refers specifically to a situation in which a thread waits for a lock that will never be released because the thread holding it is itself waiting for a lock that will never be released for the same reason.

F#: how to generate a list range with descending elements?

[1..4] could help to generate
[1;2;3;4]
But I wish to generate a range like this:
[10;8;6;4;2]
How to use range semantics to achieve this(interval+descending)? Is a "for" loop mandatory in this case?
Thanks a lot.
Try this:
[10 .. -2 .. 2] ;;
// val it : int list = [10; 8; 6; 4; 2]
The value in the middle specifies the interval.

Comparing Runtimes - Theoretical to Actual

Firstly, sorry for the long post, but I must be detailed in my explanation here. So here's what I have. I have code that measures the runtime of mergesort and radix sort algorithms for four different sizes of data.
Mergesort runtimes:
N = 10; runtime = 3499 nanoseconds
N = 100; runtime = 39600 nanoseconds
N = 1000; runtime = 470199 nanoseconds
N = 10000; runtime = 6227399 nanoseconds
Radixsort runtimes:
N = 10; runtime = 19200 nanoseconds
N = 100; runtime = 135099 nanoseconds
N = 1000; runtime = 1317799 nanoseconds
N = 10000; runtime = 14208600 nanoseconds
I have also measured the runtime of a single operation to be roughly 1000 nanoseconds on this machine. This was recommended by the professor as a means help convert theoretical runtimes to something that we can compare to the actual runtimes. For mergesort, I have O(n log(n)) as the runtime, and for radixsort I have O(nk), although I'm not entirely sure what the k represents. He suggested we do the following conversion, so I've done it for each one of the mergesorts. I don't know how to do this for radixsort, as I don't know how to factor in the 'k'. My understanding is that 'k' basically refers to the number of digits, but you can essentially stick with whichever will be larger (N or k), so since my N is always larger than k in the cases I'm working with, I'm just going to consider Radix as O(N). K is limited to six digits at the most, where N begins at 10 at the lowest value.
1000ns * theoreticalruntime
For example, 1000ns * 10 log2(10)
Mergesort:
N = 10; 33219.3 nanoseconds
N = 100; 664385.6 nanoseconds
N = 1000; 9.96578428 * 10^6 nanoseconds
N = 10000; 1.3287712379549449 * 10^8 nanoseconds
Radixsort: (1000ns per operation * N)
N = 10; 10000
N = 100; 100000
N = 1000; 1000000
N = 10000; 10000000
So here's where my issue comes in. One, I don't know how to do this calculation for the radixsort theoretical runtime. Two, I don't know exactly how to compare these values using a graph (the requirement).
In class, he was discussing using logs to "normalize" the data. The Y-axis would be N and the X-axis would be time, but he was talking about being able to use logs to change the N values from 10, 100, 1000, and 10000 to where they would show up as N = 1, 2, 3, 4. I have no idea how to do this, and I don't really know what I'd be plotting on the graph. If there's a better place I could be asking this, please point me in that direction. Time runs short.

F# Floating point ranges are experimental and may be deprecated

I'm trying to make a little function to interpolate between two values with a given increment.
[ 1.0 .. 0.5 .. 20.0 ]
The compiler tells me that this is deprecated, and suggests using ints then casting to float. But this seems a bit long-winded if I have a fractional increment - do I have to divide my start and end values by my increment, then multiple again afterwards? (yeuch!).
I saw something somewhere once about using sequence comprehensions to do this, but I can't remember how.
Help, please.
TL;DR: F# PowerPack's BigRational type is the way to go.
What's Wrong with Floating-point Loops
As many have pointed out, float values are not suitable for looping:
They do have Round Off Error, just like with 1/3 in decimal, we inevitably lose all digits starting at a certain exponent;
They do experience Catastrophic Cancellation (when subtracting two almost equal numbers, the result is rounded to zero);
They always have non-zero Machine epsilon, so the error is increased with every math operation (unless we are adding different numbers many times so that errors mutually cancel out -- but this is not the case for the loops);
They do have different accuracy across the range: the number of unique values in a range [0.0000001 .. 0.0000002] is equivalent to the number of unique values in [1000000 .. 2000000];
Solution
What can instantly solve the above problems, is switching back to integer logic.
With F# PowerPack, you may use BigRational type:
open Microsoft.FSharp.Math
// [1 .. 1/3 .. 20]
[1N .. 1N/3N .. 20N]
|> List.map float
|> List.iter (printf "%f; ")
Note, I took my liberty to set the step to 1/3 because 0.5 from your question actually has an exact binary representation 0.1b and is represented as +1.00000000000000000000000 * 2-1; hence it does not produce any cumulative summation error.
Outputs:
1.000000; 1.333333; 1.666667; 2.000000; 2.333333; 2.666667; 3.000000; (skipped) 18.000000; 18.333333; 18.666667; 19.000000; 19.333333; 19.666667; 20.000000;
// [0.2 .. 0.1 .. 3]
[1N/5N .. 1N/10N .. 3N]
|> List.map float
|> List.iter (printf "%f; ")
Outputs:
0.200000; 0.300000; 0.400000; 0.500000; (skipped) 2.800000; 2.900000; 3.000000;
Conclusion
BigRational uses integer computations, which are not slower than for floating-points;
The round-off occurs only once for each value (upon conversion to a float, but not within the loop);
BigRational acts as if the machine epsilon were zero;
There is an obvious limitation: you can't use irrational numbers like pi or sqrt(2) as they have no exact representation as a fraction. It does not seem to be a very big problem because usually, we are not looping over both rational and irrational numbers, e.g. [1 .. pi/2 .. 42]. If we do (like for geometry computations), there's usually a way to reduce the irrational part, e.g. switching from radians to degrees.
Further reading:
What Every Computer Scientist Should Know About Floating-Point Arithmetic
Numeric types in PowerPack
Interestingly, float ranges don't appear to be deprecated anymore. And I remember seeing a question recently (sorry, couldn't track it down) talking about the inherent issues which manifest with float ranges, e.g.
> let xl = [0.2 .. 0.1 .. 3.0];;
val xl : float list =
[0.2; 0.3; 0.4; 0.5; 0.6; 0.7; 0.8; 0.9; 1.0; 1.1; 1.2; 1.3; 1.4; 1.5; 1.6;
1.7; 1.8; 1.9; 2.0; 2.1; 2.2; 2.3; 2.4; 2.5; 2.6; 2.7; 2.8; 2.9]
I just wanted to point out that you can use ranges on decimal types with a lot less of these kind of rounding issues, e.g.
> [0.2m .. 0.1m .. 3.0m];;
val it : decimal list =
[0.2M; 0.3M; 0.4M; 0.5M; 0.6M; 0.7M; 0.8M; 0.9M; 1.0M; 1.1M; 1.2M; 1.3M;
1.4M; 1.5M; 1.6M; 1.7M; 1.8M; 1.9M; 2.0M; 2.1M; 2.2M; 2.3M; 2.4M; 2.5M;
2.6M; 2.7M; 2.8M; 2.9M; 3.0M]
And if you really do need floats in the end, then you can do something like
> {0.2m .. 0.1m .. 3.0m} |> Seq.map float |> Seq.toList;;
val it : float list =
[0.2; 0.3; 0.4; 0.5; 0.6; 0.7; 0.8; 0.9; 1.0; 1.1; 1.2; 1.3; 1.4; 1.5; 1.6;
1.7; 1.8; 1.9; 2.0; 2.1; 2.2; 2.3; 2.4; 2.5; 2.6; 2.7; 2.8; 2.9; 3.0]
As Jon and others pointed out, floating point range expressions are not numerically robust. For example [0.0 .. 0.1 .. 0.3] equals [0.0 .. 0.1 .. 0.2]. Using Decimal or Int Types in the range expression is probably better.
For floats I use this function, it first increases the total range 3 times by the smallest float step. I am not sure if this algorithm is very robust now. But it is good enough for me to insure that the stop value is included in the Seq:
let floatrange start step stop =
if step = 0.0 then failwith "stepsize cannot be zero"
let range = stop - start
|> BitConverter.DoubleToInt64Bits
|> (+) 3L
|> BitConverter.Int64BitsToDouble
let steps = range/step
if steps < 0.0 then failwith "stop value cannot be reached"
let rec frange (start, i, steps) =
seq { if i <= steps then
yield start + i*step
yield! frange (start, (i + 1.0), steps) }
frange (start, 0.0, steps)
Try the following sequence expression
seq { 2 .. 40 } |> Seq.map (fun x -> (float x) / 2.0)
You can also write a relatively simple function to generate the range:
let rec frange(from:float, by:float, tof:float) =
seq { if (from < tof) then
yield from
yield! frange(from + by, tof) }
Using this you can just write:
frange(1.0, 0.5, 20.0)
Updated version of Tomas Petricek's answer, which compiles, and works for decreasing ranges (and works with units of measure):
(but it doesn't look as pretty)
let rec frange(from:float<'a>, by:float<'a>, tof:float<'a>) =
// (extra ' here for formatting)
seq {
yield from
if (float by > 0.) then
if (from + by <= tof) then yield! frange(from + by, by, tof)
else
if (from + by >= tof) then yield! frange(from + by, by, tof)
}
#r "FSharp.Powerpack"
open Math.SI
frange(1.0<m>, -0.5<m>, -2.1<m>)
UPDATE I don't know if this is new, or if it was always possible, but I just discovered (here), that this - simpler - syntax is also possible:
let dl = 9.5 / 11.
let min = 21.5 + dl
let max = 40.5 - dl
let a = [ for z in min .. dl .. max -> z ]
let b = a.Length
(Watch out, there's a gotcha in this particular example :)

Resources