Skip to content

Instantly share code, notes, and snippets.

@ruxo
Last active February 9, 2023 23:18
Show Gist options
  • Save ruxo/8eef3df825fc3c4c16fa to your computer and use it in GitHub Desktop.
Save ruxo/8eef3df825fc3c4c16fa to your computer and use it in GitHub Desktop.
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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment