ruxo
1/10/2016 - 6:29 AM

Fuzzy logic

Fuzzy logic

type CategoryFunc = float -> float
type Category = string * CategoryFunc

module private CategoryRandom =
  let r = System.Random()

  let from n = r.Next n

[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
module Category =
  let eval x cat = (snd cat) x

let between(a,b) x = a <= x && x <= b

let triangleFunc(low, mid, high) input =
  if input = mid then 1.
  elif input |> between(low,mid) then (input - low) / (mid - low)
  elif input |> between(mid,high) then (high - input) / (high - mid)
  else 0.

let ptr =
  [ "v.accomodative", triangleFunc(0., 3.0, 6.0)
    "accomodative", triangleFunc(3.0, 6.0, 9.0)
    "tight", triangleFunc(5.0, 8.5, 12.0)
    "v.tight", triangleFunc(10.0, 12.0, 14.0)   ]

let inval = 7.5

let bins =
  ptr |> Seq.map (Category.eval inval >> (*) 100.) 
      |> Seq.zip (ptr |> Seq.map fst) 
      |> Seq.filter (fun (_,v) -> v > 0.)
      |> Seq.toList

let binRange =
  bins |> Seq.scan (fun (_,(_,high)) (name,bin) -> name, (high, high + bin)) ("",(0.,0.))
       |> Seq.skip 1
       |> Seq.toList

printfn "Bins:"
binRange |> Seq.iter (fun (name, (low,high)) -> printfn "\t%20s: %3f - %3f" name low high)

let total = bins |> Seq.fold (fun total -> snd >> (+) total) 0.

let randnum = float <| CategoryRandom.from (int total)

let output = binRange |> Seq.find (fun (_,range) -> between range randnum)

printfn "Output fuzzy category is ==> %s <==" (fst output)

printfn "category\tmembership"
printfn "--------\t----------"

bins |> Seq.iter (fun (name, v) -> printfn "%-15s %3f" name (v/total))
#r @"packages\MathNet.Numerics\lib\portable-net45+sl5+netcore45+MonoAndroid1+MonoTouch1\MathNet.Numerics.dll"
#r @"packages\MathNet.Numerics.FSharp\lib\portable-net45+sl5+netcore45+MonoAndroid1+MonoTouch1\MathNet.Numerics.FSharp.dll"

open MathNet.Numerics.LinearAlgebra

module Neurons =
  let thres theta x = if x >= theta then 1.0 else 0.0
  let binary2bipolar = (*)2. >> (+)(-1.)

module Hopfield =
  type NeuronType = Vector<float>
  type NeuronNetworkType = Matrix<float>

  let hop_threshold = Neurons.thres 0.0

  let correlationMatrix (x: NeuronType) = x.ToColumnMatrix() * x.ToRowMatrix() - NeuronNetworkType.Build.DenseIdentity(x.Count)

  let create (nr: NeuronNetworkType) (input: NeuronType) = (input * nr) |> Vector.map hop_threshold

  let validateTrainData inputs =
    match inputs |> List.map List.length with
    | [] -> None
    | x::xs -> if xs |> List.forall ((=)x) then Some inputs else None

  let private _train = Seq.map correlationMatrix >> Seq.reduce (+)

  let train = validateTrainData >> Option.map (List.map (List.map Neurons.binary2bipolar >> vector) >> _train)

let neurons =
  matrix [[ 0.0;-3.0; 3.0;-3.0]
          [-3.0; 0.0;-3.0; 3.0]
          [ 3.0;-3.0; 0.0;-3.0]
          [-3.0; 3.0;-3.0; 0.0]]

let A = [ 1.0; 0.0; 1.0; 0.0]
let B = [ 0.0; 1.0; 0.0; 1.0]

let hopfield = Hopfield.create neurons

printfn "A = %A" <| hopfield (vector A)
printfn "B = %A" <| hopfield (vector B)

let trained = Hopfield.train [A; B] |> Option.get

printfn "Trained matrix: \n%A" trained

let myhopfield = Hopfield.create trained
printfn "A = %A" <| myhopfield (vector A)
printfn "B = %A" <| myhopfield (vector B)
source https://www.nuget.org/api/v2
nuget FSharp.Core.Fluent-4.0
nuget MathNet.Numerics.FSharp