My code seems to freeze up after the last iteration on my async workflow. is it a bug in the code or does it simply take realy long (20 min plus) to wrap up the work flow?
let rec list_primes x y =
//returns an array with all primes between x and y
if x < y then
if is_prime x (x |> sqrt |> floor) then
printfn "%A" x
x :: list_primes (x + 1.0) y
else
let n_x = x |> next_prime
n_x :: list_primes (n_x + 1.0) y
else
[]
let filt (x:float) =
if x < 10000.0 then
true
else
false
let list_of_primes = List.filter (filt) (list_primes 1000.0 10000.0)
let iter = [0..((List.length list_of_primes)-3)]
let equal_difference (list:List<float>) iter =
printfn "%A" iter
async{
let mutable a = [|[||]|]
for x in (iter + 1)..(list.Length - 1) do
printfn "inside loop, x = %A" x
let temp = test_sum_in_list list.[x] list.[iter] list
//let temp1 = test_sum_in_list (list.[x] + list.[iter]) list.[x] list
if temp then
a <- Array.append a [|[|list.[x]; list.[iter]; (list.[x] + list.[iter]);|]|]
printf "added %A" a
let result = a
return result
}
let result = iter
|> List.map (equal_difference list_of_primes)
|> Async.Parallel
|> Async.RunSynchronously
Related
Is it possible to debug F# or, like LINQ in C#, is this effectively impossible?
I'm working through Machine Learning Projects for .NET Developers and am using F# for the first time.
I tried to edit the example exercise. The C# version was easy to get running, but my attempt at the F# version just hangs.
What can I do to trace the problem?
open System.IO
type Observation = { Label:string; Pixels: int[] }
type Distance = int[] * int[] -> int
type Classifier = int[] -> string
let toObservation (csvData:string) =
let columns = csvData.Split(',')
let label = columns.[0]
let pixels = columns.[1..] |> Array.map int
{ Label = label; Pixels = pixels }
let reader path =
let data = File.ReadAllLines path
data.[1..]
|> Array.map toObservation
let trainingPath = __SOURCE_DIRECTORY__ + #"../../Data/trainingsample.csv"
let training = reader trainingPath
let manhattanDistance (pixels1,pixels2) =
Array.zip pixels1 pixels2
|> Array.map (fun (x,y) -> abs (x-y))
|> Array.sum
let euclideanDistance (pixels1,pixels2) =
Array.zip pixels1 pixels2
|> Array.map (fun (x,y) -> pown (x-y) 2)
|> Array.sum
let dotCountDistance(pixels1, pixels2) =
let t1 = pixels1 |> Array.map (fun(z) -> if z > 128 then 1 else 0) |> Array.sum
let t2 = pixels2 |> Array.map (fun(z) -> if z > 128 then 1 else 0) |> Array.sum
abs(t1 - t2)
let train (trainingset:Observation[]) (dist:Distance) =
let classify (pixels:int[]) =
trainingset
|> Array.minBy (fun x -> dist (x.Pixels, pixels))
|> fun x -> x.Label
classify
//
// This is my new function
//
let train2 (trainingset:Observation[]) (dist:Distance) =
let classify (pixels:int[]) =
trainingset
|> Array.map (fun(z) -> dist(z.Pixels, pixels), z.Label)
|> Array.groupBy(fun (a, y) -> y)
|> Array.map(fun (lbl, ds) -> lbl, (ds |> Array.map(fun (p, q) -> p) |> Array.sum ) * 100 / (ds |> Array.length))
|> Array.sortByDescending( fun (lbl, s) -> s)
|> fun z -> z.[0]
|> fun (lbl, s) -> lbl
classify
//
//
//
let validationPath = __SOURCE_DIRECTORY__ + #"../../Data/validationsample.csv"
let validation = reader validationPath
let evaluate validationSet classifier =
validationSet
|> Array.averageBy (fun x -> if classifier x.Pixels = x.Label then 1. else 0.)
|> printfn "Correct: %.3f"
let manhattanModel = train training manhattanDistance
let euclideanModel = train training euclideanDistance
let dotCountModel = train training dotCountDistance
let manhattanModel2 = train2 training manhattanDistance
let euclideanModel2 = train2 training euclideanDistance
let dotCountModel2 = train2 training dotCountDistance
printfn "Manhattan"
evaluate validation manhattanModel // <------------------- This just hangs.
printfn "Euclidean"
evaluate validation euclideanModel
printfn "Dot Count"
evaluate validation dotCountModel
// Illustration: full distance function
let d (X,Y) =
Array.zip X Y
|> Array.map (fun (x,y) -> pown (x-y) 2)
|> Array.sum
|> sqrt
Here is ,y C# version that works
return data.Select(z => new { z.Label, D = distance.Between(z.Pixels, pixels) })
.GroupBy(z => z.Label)
.Select(z => new { Label = z.Key, MeanDistance = z.Average(y => y.D) })
.OrderBy(z => z.MeanDistance).First()
.Label;
You can debug a script in F# Interactive (make sure you have this option turned on, first).
I had the same behavior you did, it hangs. I ran the same code as a console program, and it ran in a few seconds. (The output was "Correct: 0.934"). So, I believe this is a problem, perhaps a bug, with F# Interactive.
I'm new to F# and I'm struggling to figure out how I could combine the numbers in a float list to a float.
If I have the list
let floatList = [ 9.0; 8.0; 3.0 ]
I would like a function where the return value is a float of value 983.0. How would I go about this problem?
You go through the list, multiply the previously accumulated number by 10, then add the current element of the list:
((9 * 10) + 8) * 10 + 3 = 983
A handy way to go through the list while keeping an "accumulator" is List.fold:
floatList
|> List.fold (fun acc n -> acc*10 + n) 0
Chain rev, mapi(map with index) and sum functions
let digits = [| 9.0; 8.0; 3.0 |]
let result =
Array.rev digits
|> Array.mapi (fun i x -> x * (10.0 ** float i))
|> Array.sum
printfn "%f" result
Because array can return it's length without iterating over the collection, you can remove "reversing" and calculate offset for power based on the index and length
let digits = [| 9.0; 8.0; 3.0 |]
let result =
Array.mapi (fun i x -> x * (10.0 ** float (digits.Length - i))) digits
|> Array.sum
printfn "%f" result
This is a way to do it
let floatList = [ 9.0; 8.0; 3.0 ]
let rec loop mult list =
match list with
| head :: tail -> (mult * head) + (loop (mult / 10.) tail)
| [] -> 0.
let mult = 10. ** float ((List.length floatList) - 1) // len 1 = 1. len 2 = 10. len 3 = 100
let result = loop mult floatList
printfn "%f" result
How to convert the following code to async ones?
let m1 x = x * 2
let m2 s =
let l = [1..10]
l |> List.iter(fun x -> printfn "%d" (m1 x))
s // the function returns something
The following will get an error.
let n1 x = async { return x * 2 }
let n2 s =
async {
let l = [1..10] // l will be generated by s
l |> List.iter(fun x ->
let y = do! n1 x // ERROR: This construct may only be used within computation expressions
printfn "%d" y)
return s
}
The following will get rid of the error but it calls n1 synchronously.
let n2 s =
async {
let l = [1..10]
l |> List.iter(fun x ->
async {
let! y = n1 x
printfn "%d" y
} |> Async.RunSynchronously)
return s
}
n2 will be called in a List.iter in another function. So at the outermost level, I want to do Async.Parallel for the list.
You can use a for .. in .. do expression:
let n1 x = async { return x * 2 }
let n2 s =
async {
let l = [1..10] // l will be generated by s
for x in l do
let! y = n1 x
printfn "%d" y
return s
}
Trying to learn F#, by solving some programming puzzles. I don't want to add too many details about the problem as I don't want to spoil the fun for others.
Basically, the issue is to find all 4-uples { (i,j,k,l) | i ^ j ^ k ^ l != 0 } with no repetition (eg., (1,1,1,2) and (1,1,2,1) are the same and should be counted just once).
I have found a O(n^3) approach which works, please see countImperative(a,b,c,d) below. But I also tried to refactor the code as to get rid of the nested for loops. However, I could not do so without a significant performance penalty. It was my impression that F#'s syntactic sugar would allow a more concise style (using pipes and folds), letting the compiler do the heavy-lifting to produce comparably fast code (compared to my nested for loops). The big performance hit comes from the calculation of the partial2 sum.
Here's the code:
open System
open System.Diagnostics
open System.Collections
module quadruples =
[<EntryPoint>]
let main argv =
let input = "2000 2000 2000 2000"
let ordered = [ for x in input.Split([|' '|]) -> Convert.ToInt32(x) ] |> List.sort
let a,b,c,d = ordered.[0], ordered.[1], ordered.[2], ordered.[3]
let inner(a,b) = a * (a-1) / 2 + a * (b-a)
let sw = new Stopwatch()
sw.Start()
let partial1 = [ 1.. b ] |> List.fold (fun acc j -> acc + (int64 ((min a j) * inner(c-j+1, d-j+1)))) 0L
sw.Stop()
let elapsed1 = (sw.ElapsedMilliseconds |> double) / 1000.0
printfn "Partial1: %f s" elapsed1
sw.Restart()
let combinations = [ for i in 1..a do for j in i+1..b do yield (j,i^^^j) ]
let range = [ 1..c ]
let partial2 = combinations |> List.fold(fun acc (j,x) -> acc + (range |> List.skip(j-1) |> List.fold(fun acc k -> if k ^^^ x < k || k ^^^ x > d then acc + 1L else acc) 0L)) 0L
sw.Stop()
let elapsed2 = (sw.ElapsedMilliseconds |> double) / 1000.0
printfn "Partial2: %f s" elapsed2
printfn "Functional: %d, Elapsed: %f s" (partial1 + partial2) (elapsed1 + elapsed2)
// "imperative" approach
let countImperative(a,b,c,d) =
let mutable count = seq { 1..b } |> Seq.fold (fun acc j -> acc + (int64 ((min a j) * inner(c-j+1, d-j+1)))) 0L
for i in 1..a do
for j in i+1..b do
let x = i ^^^ j
for k in j..c do
let y = x ^^^ k
if y < k || y > d then
count <- count + 1L
count
sw.Restart();
let count = countImperative(a,b,c,d)
sw.Stop()
printfn "Imperative: %d, Elapsed: %f s" count ((sw.ElapsedMilliseconds |> double) / 1000.0)
0 // return an integer exit code
So my question was, if there is any way to speed up the code (specifically the calculation of partial2) while maintaining F#'s nice syntax.
let highs = [| 2; 4; 6 |]
let lows = [| 1; 5; 10 |]
I want to get 2 arrays from the above: if the element in highs is smaller than the corresponding element in lows, then swap them. So, I can get the final 2 arrays:
let trueHighs = [| 2; 5; 10 |]
let trueLows = [| 1; 4; 6 |]
How do I do this?
Similar with JaredPar's answer but simpler:
let trueHighs, trueLows =
Array.zip highs lows
|> Array.map (fun (x, y) -> if x >= y then (x, y) else (y, x))
|> Array.unzip
Another more concise version:
let trueHighs, trueLows =
(highs, lows)
||> Array.map2 (fun x y -> if x >= y then (x, y) else (y, x))
|> Array.unzip
Here is the code you should use:
let n = highs.Length
let trueHighs = Array.init n (fun i -> max highs.[i] lows.[i])
let trueLows = Array.init n (fun i -> min highs.[i] lows.[i])
If performance is uber-critical, you're probably better off with an imperative approach.
let n = highs.Length
let trueHighs = Array.zeroCreate n
let trueLows = Array.zeroCreate n
for i = 0 to n-1 do
let hi = highs.[i]
let lo = lows.[i]
if hi > lo then
trueHighs.[i] <- hi
trueLows.[i] <- lo
else
trueHighs.[i] <- lo
trueLows.[i] <- hi
Try the following
let trueHighs, trueLows =
let zipped =
highs
|> Seq.ofArray
|> Seq.zip (lows |> Seq.ofArray)
|> Seq.map (fun (x, y) -> min x y, max x y)
let lows = zipped |> Seq.map fst |> Array.ofSeq
let highs = zipped |> Seq.map snd |> Array.ofSeq
highs, lows