F# write value in multidimensional array - arrays

I am trying to calculate covariance matrix
The operator 'expr.[idx]' has been used on an object of indeterminate
type based on information prior to this program point. Consider adding
further type constraints
CovMatrix.[a,b]
How to fix this and why it happens?
let FirstSeq = {1.0..10.0}
let SecondSeq = {20.0..30.0}
let All = seq {yield (0,FirstSeq); yield (1,SecondSeq)}
let cov(first:seq<float>)(second:seq<float>) =
Seq.map2 (*) first second
|> Seq.average
|> fun x -> x - Seq.average first * Seq.average second
let CreateCovMatrix(strangeList:seq<int * seq<float>>) =
let Size = Seq.length strangeList
let CovMatrix = Array2D.init Size Size
let CalculateCovMatrix =
for (a, i) in strangeList do
for (b, j) in strangeList do
CovMatrix.[a,b]=cov(i)(j)
CalculateCovMatrix
let result = CreateCovMatrix(All)
printf "%A" result

The function Array2D.init takes 3 parameters, you're missing the last one, which is the initialization function.
You can quick-fix it by writing:
let CovMatrix = Array2D.init Size Size (fun _ _ -> 0.)
Then you'll discover the next problem: assignment for mutable references is the <- operator, not = which is for comparison and let bindings.
So your function will look like this:
let CreateCovMatrix(strangeList:seq<int * seq<float>>) =
let Size = Seq.length strangeList
let CovMatrix = Array2D.init Size Size (fun _ _ -> 0.)
let CalculateCovMatrix =
for (a, i) in strangeList do
for (b, j) in strangeList do
CovMatrix.[a,b] <- cov(i)(j)
CalculateCovMatrix
But instead of specifying a function that ignores the inputs and return always zero, you can use the function Array2D.zeroCreate :
let CovMatrix = Array2D.zeroCreate Size Size

This kind of math is where functional programming excels,
although you're currently residing in the imperative paradigm. Gustavo handled your warnings, but even so your function won't give the desired result. Mixing functional and imperative concepts CreateCovMatrix now returns unit.
Good imperative:
let createCovMatrix(strangeList:seq<int * seq<float>>) =
let size = Seq.length strangeList
let covMatrix = Array2D.zeroCreate size size
for (a, i) in strangeList do
for (b, j) in strangeList do
covMatrix.[a,b]<-cov(i)(j)
covMatrix
Going functional:
let createCovMatrix strangeList =
strangeList
|> Seq.map (fun (a, i) -> Seq.map (fun (b, j) -> cov i j) strangeList)
|> array2D
Multi functional:
let createCovMatrix strangeList =
let mapper f = Seq.map f strangeList
mapper (fun (a, i) -> mapper (fun (b, j) -> cov i j))
|> array2D

Related

Assign variable to array element where variable and array can be modified independently in ocaml

Here is the problem I can't get around, I'm working in ocaml to copy the elements of an array to a new array. I want to be able to modify these arrays independently from each other, but no matter what I try, a change to one array is reflected in the other array as well.
Here is a simplified example:
type sampleType = { a : int; b : int array };;
let x = {a = 5; b = [|1, 2, 3|] };;
let y = x.b;;
Array.set y 1 6;;
After running these commands I want:
y - : int array = [|1; 6; 3|]
x - : sampleType = {a = 5; b = [|1; 2; 3|]}
Instead x is being changed along with y, and
x - : sampleType = {a = 5; b = [|1; 6; 3|]}
Any solutions to this problem?
As you see from your experiments, this code:
let y = x.b
makes y refer to the very same array as x.b. It doesn't create an independent array. To create an independent array, you need to copy:
let y = Array.copy x.b
I was specifically using 3d arrays, realized I had to apply Array.copy at the lowest level of the 3d array, rather than at the top level.
let arr = Array.init 3 (fun _ -> Array.init 3 (fun _ -> (Array.init 3 (fun _ -> {faces = [|0;1;2;3;4|]}))));;
let drr = Array.init 3 (fun i -> Array.init 3 (fun j -> Array.copy arr.(i).(j)));;
This gave me the result I needed.

F# Finding the Missing element between 2 arrays/lists

`So, I am very new to F#. I hope the issue is simple. I have been doing research and looking around. I have an "Incomplete structured construct at or before this point in expression" error. I feel like it might be something simple or I am way off.
The objective is:
There is an array of non negative integers. A second array is
formed by shuffling the elements of the first
array and deleting a random element. Given these two arrays, find which element is missing in the second
array. Linear searching is not allowed.
let FindMiss list =
match list with
| [] ->
[]
|firstElem::otherElements ->
let rand = new Random
let shuffle (arr : 'a array) =
let array = Array.copy arr
let n = array.Length
for x in 1..n do
let i = n-x
let j = rand.Next(i+1)
let tmp = array.[i]
array.[i] <- array.[j]
array.[j] <- tmp
array
return array
array.[rand].delete
|array::list ->
let d=collections.defaultdict(int)
for num in list do
d[num] +=1
for num in array1 do
if d[num]==0 then return num
else d[num]-=1
printfn "The missing Number is: %A" (FindMiss[4;2;1;7;5;6;3;2])
The task is to reimplement List.except?
If not, just use that 'except' then:
[1;2;3] |> List.except [1;2]
Or was the task "random removal of element in list"? Then this is "the answer": https://stackoverflow.com/a/2889972/5514938
For a start, for more readability, you can take the shuffling and deleting a random element in a separate function. For arrays, they may look like this:
let Shuffle arr =
let rand = System.Random()
arr |> Array.sortBy(fun _ -> rand.Next())
let RemoveRandom arr =
let rand = System.Random()
let lng = arr |> Array.length
let index = rand.Next lng
[|0..lng - 1 |]
|> Array.choose(fun x -> if x = index then None else Some(arr.[x]))
|> Shuffle
Further define the search function:
let FindMiss arr1 arr2 =
let sum1 = arr1 |> Array.sum
let sum2 = arr2 |> Array.sum
sum1 - sum2
Example:
let first = [| 4;2;1;7;5;6;3;2 |]
first |> printfn "%A"
let second = first |> RemoveRandom
second |> printfn "%A"
FindMiss first second |> printfn "Missing value is %i"
Print:
[|4; 2; 1; 7; 5; 6; 3; 2|]
[|2; 2; 3; 7; 1; 5; 6|]
Missing value is 4
Link:
https://dotnetfiddle.net/g6wKUX

In-array comparison in F#

Let's say that I want to do some in-array comparison in F#, e.g. determine whether a given integer array arr contains integers in strictly increasing order. I would do it like this:
let arri =
arr
|> Array.mapi (fun i e -> i, e)
let isArrStrictlyIncreasing =
arri
|> Array.tryFind (fun e ->
if fst e = arri.Length - 1 then
false
else
snd e >= snd arri.[1 + fst e])
|> Option.isNone
However, I am wondering if there is a more concise, "functional" way of making such in-array comparisons without the use of Array.mapi and if-else?
One simple way:
let isincr arr =
arr
|> Array.fold (fun (a,b) (c) -> ((b<c && a)),c) (true,System.Int32.MinValue)
|> fst
Couldn't you just do the following?
let expected = [| candidate.[0] .. candidate.[0] + candidate.Length - 1 |]
candidate = expected
This simply builds the array you'd expect, and uses F#'s Structural Equality to compare the two arrays.
A more general alternative might be this:
let isOrdered arr = arr |> Array.sort = arr
let hasDistinctMembers (arr : 'a array) =
let distinct = arr |> Seq.distinct |> Seq.toArray
distinct.Length = arr.Length
let isStrictlyIncreasing arr = arr |> isOrdered && arr |> hasDistinctMembers
Usage:
> isStrictlyIncreasing [| 7; 11; 8 |];;
val it : bool = false
> isStrictlyIncreasing [| 7..33 |];;
val it : bool = true
> isStrictlyIncreasing [| 7; 8; 11 |];;
val it : bool = true
> isStrictlyIncreasing [| 7; 7; 8; 11 |];;
val it : bool = false

How to calculate the "sliding sliced" fold of an array of int arrays in F#?

I have a function called calcArr_ArrOfArr in F# with the signature int [] -> int [][] -> int, i.e. calcArr_ArrOfArr takes two arguments, an int array and an array of int arrays, and returns an int.
I want to create the function calcArrOfArr with the signature int [][] -> int, which does the following:
let calcArrOfArr (arrOfArr : int [][]) =
Array.fold (fun acc e -> acc + (calcArr_ArrOfArr e arrOfArr.[?..])) 0 arrOfArr
where ? would be the index of e + 1.
In other words, in calcArrOfArr I want to apply calcArr_ArrOfArr to every element e of arrOfArr plus the "remaining portion" of arrOfArr, i.e. the slice of arrOfArr starting from after element e. Of course, for the last element of arrOfArr, nothing would be added to the accumulator, nor would an exception be thrown.
Is there a way to create calcArrOfArr in a functional way? An Array.foldi function would come handy...
If you feel you need Array.foldi, write one! The following snippet will extend the built-in Array module with a foldi:
module Array =
let foldi f z a =
a |> Array.fold (fun (i,a) x -> i+1, f i a x) (0,z) |> snd
Slicing from past-the-end gives you the empty array (i.e., [|0;1|].[2..] = [||]), so now your original suggestion works:
let calcArrOfArr (arrOfArr : int [][]) =
Array.foldi (fun i acc e -> acc + (calcArr_ArrOfArr e arrOfArr.[i+1..])) 0 arrOfArr
However, the slice arrOfArr.[i+1..] copies the array slice; this might be unfortunate for efficiency.
Haven't tested it, but this seems about right:
let calcArrOfArr (arrOfArr : int [][]) =
arrOfArr
|> Seq.mapi (fun i x -> i, x)
|> Seq.fold (fun acc (i, e) -> acc + (calcArr_ArrOfArr e arrOfArr.[i+1..])) 0

How to generate an array with a dynamic type in F#

I'm trying to write a function to return a dynamically typed array. Here is an example of one of the ways I've tried:
let rng = System.Random()
type ConvertType =
| AsInts
| AsFloat32s
| AsFloats
| AsInt64s
type InputType =
| Ints of int[]
| Float32s of float32[]
| Floats of float[]
| Int64s of int64[]
let genData : int -> int -> ConvertType -> InputType * int[] =
fun (sCount:int) (rCount:int) (ct:ConvertType) ->
let source =
match ct with
| AsInts -> Array.init sCount (fun _ -> rng.Next()) |> Array.map (fun e -> int e) |> Ints
| AsFloat32s -> Array.init sCount (fun _ -> rng.Next()) |> Array.map (fun e -> float32 e) |> Float32s
| AsFloats -> Array.init sCount (fun _ -> rng.Next()) |> Array.map (fun e -> float e) |> Floats
| AsInt64s -> Array.init sCount (fun _ -> rng.Next()) |> Array.map (fun e -> int64 e) |> Int64s
let indices = Array.init rCount (fun _ -> rng.Next sCount) |> Array.sort
source, indices
The problem I have is that on down when I use the function, I need the array to be the primitive type e.g. float32[] and not "InputType."
I have also tried doing it via an interface created by an inline function and using generics. I couldn't get that to work how I wanted either but I could have just been doing it wrong.
Edit:
Thanks for the great reply(s), I'll have to try that out today. I'm adding the edit because I solved my problem, although I didn't solve it how I wanted (i.e. like the answer). So an FYI for those who may look at this, I did the following:
let counts = [100; 1000; 10000]
let itCounts = [ 1000; 500; 200]
let helperFunct =
fun (count:int) (numIt:int) (genData : int -> int -> ('T[] * int[] )) ->
let c2 = int( count / 2 )
let source, indices = genData count c2
....
[<Test>]
let ``int test case`` () =
let genData sCount rCount =
let source = Array.init sCount (fun _ -> rng.Next())
let indices = Array.init rCount (fun _ -> rng.Next sCount) |> Array.sort
source, indices
(counts, itCounts) ||> List.Iter2 (fun s i -> helperFunct s i genData)
.....
Then each proceeding test case would be something like:
[<Test>]
let ``float test case`` () =
let genData sCount rCount =
let source = Array.init sCount (fun _ -> rng.Next()) |> Array.map (fun e -> float e)
let indices = Array.init rCount (fun _ -> rng.Next sCount) |> Array.sort
source, indices
.....
But, the whole reason I asked the question was that I was trying to avoid rewriting that genData function for every test case. In my real code, this temporary solution kept me from having to break up some stuff in the "helperFunct."
I think that your current design is actually quite good. By listing the supported types explicitly, you can be sure that people will not try to call the function to generate data of type that does not make sense (say byte).
You can write a generic function using System.Convert (which lets you convert value to an arbitrary type, but may fail if this does not make sense). It is also (very likely) going to be less efficient, but I have not measured that:
let genDataGeneric<'T> sCount rCount : 'T[] * int[] =
let genValue() = System.Convert.ChangeType(rng.Next(), typeof<'T>) |> unbox<'T>
let source = Array.init sCount (fun _ -> genValue())
let indices = Array.init rCount (fun _ -> rng.Next sCount) |> Array.sort
source, indices
You can then write
genDataGeneric<float> 10 10
but people can also write genDataGeneric<bool> and the code will either crash or produce nonsense, so that's why I think that your original approach had its benefits too.
Alternatively, you could parameterize the function to take a converter that turns int (which is what you get from rng.Next) to the type you want:
let inline genDataGeneric convertor sCount rCount : 'T[] * int[] =
let genValue() = rng.Next() |> convertor
let source = Array.init sCount (fun _ -> genValue())
let indices = Array.init rCount (fun _ -> rng.Next sCount) |> Array.sort
source, indices
Then you can write just getDataGeneric float 10 10 which is still quite elegant and it will be efficient too (I added inline because I think it can help here)
EDIT: Based on the Leaf's comment, I tried using the overloaded operator trick and it turns out you can also do this (this blog has the best explanation of what the hell is going on in the following weird snippet!):
// Specifies conversions that we want to allow
type Overloads = Overloads with
static member ($) (Overloads, fake:float) = fun (n:int) -> float n
static member ($) (Overloads, fake:int64) = fun (n:int) -> int64 n
let inline genDataGeneric sCount rCount : 'T[] * int[] =
let convert = (Overloads $ Unchecked.defaultof<'T>)
let genValue() = rng.Next() |> convert
let source = Array.init sCount (fun _ -> genValue())
let indices = Array.init rCount (fun _ -> rng.Next sCount) |> Array.sort
source, indices
let (r : float[] * _) = genDataGeneric 10 10 // This compiles & works
let (r : byte[] * _) = genDataGeneric 10 10 // This does not compile
This is interesting, but note that you still have to specify the type somewhere (either by usage later or using a type annotation). If you're using type annotation, then the earlier code is probably simpler and gives less confusing error messages. But the trick used here is certainly interesting.

Resources