Skip to content

Instantly share code, notes, and snippets.

@lontivero
Created November 11, 2022 20:43
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save lontivero/1be4083fb85373893759a18e9cd5e246 to your computer and use it in GitHub Desktop.
Save lontivero/1be4083fb85373893759a18e9cd5e246 to your computer and use it in GitHub Desktop.
FuzzyLogic

Fuzzy logic example

Here we implement an example from Youtube: https://www.youtube.com/watch?v=__0nZuG4sTw where bankers can use fuzzy logic to evaluate the level of risk of someone according to his/her credit score.

Run the code

You can play with this using the same number used in the youtube video.

$ dotnet fsi fuzzy.fsx

Enter credit score: 660
(bad, Trapezoidal (0.0, 0.0, 550.0, 650.0)) => 0
(neutral, Triangular (550.0, 650.0, 750.0)) => 0.9
(good, Trapezoidal (650.0, 750.0, 1000.0, 1000.0)) => 0.1
defuzzified value: 0.4607142857142857
open System
module FuzzyLogic =
type FunctionShape =
| Triangular of float * float * float
| Trapezoidal of float * float * float * float
let (|LessThanOrEqualTo|_|) k value = if value <= k then Some() else None
let (|GreaterThanOrEqualTo|_|) k value = if value >= k then Some() else None
let (|Between|_|) b e value = if value >= b && value <= e then Some() else None
let triangular a b c x =
match x with
| LessThanOrEqualTo a -> 0.0
| Between a b -> (x - a) / (b - a)
| Between b c -> (c - x) / (c - b)
| GreaterThanOrEqualTo c -> 0.0
let trapezoidal a b c d x =
match x with
| LessThanOrEqualTo a -> 0.0
| Between a b -> (x - a) / (b - a)
| Between b c -> 1.0
| Between c d -> (d - x) / (d - c)
| GreaterThanOrEqualTo d -> 0.0
let eval (f: FunctionShape) =
match f with
| Triangular (a, b, c) -> triangular a b c
| Trapezoidal (a, b, c, d) -> trapezoidal a b c d
let area (f: FunctionShape) h =
match f with
| Trapezoidal (a, b, c, d) -> (b - a) * h / 2.0 + (c - b) * h + (d - c) * h / 2.0
| Triangular (a, b, c) -> (c - a) * h / 2.0
type Centroid = float * float
let centroid (f: FunctionShape) h: Centroid =
match f with
| Trapezoidal (a, b, c, d) -> a + (0.25 - a) / 2.0, h / 2.0
| Triangular (a, b, c) -> a + (c - a) * h / 2.0, h / 3.0
type CategoryName = string
type Category = CategoryName * FunctionShape
type FuzzyValue = float list
let fuzzyfy (categories: Category list) score : FuzzyValue =
categories
|> Seq.map (fun (_, f) -> eval f score)
|> Seq.toList
let defuzzyfy (categories: Category list) (fuzzy_value: FuzzyValue) : float =
let data =
fuzzy_value
|> List.zip categories
|> List.map (fun ((_, f), v) -> area f v, centroid f v)
let s1 = data |> List.sumBy (fun (a, (x, _)) -> x * a)
let sum_areas = data |> List.sumBy (fun (a, _) -> a)
s1 / sum_areas
let credit_according_to_banckers : FuzzyLogic.Category list =
[ "bad", FuzzyLogic.Trapezoidal (0, 0, 550, 650)
"neutral", FuzzyLogic.Triangular (550, 650, 750)
"good", FuzzyLogic.Trapezoidal(650, 750, 1000, 1000)]
let risk_according_to_bankers : FuzzyLogic.Category list =
[ "low risk", FuzzyLogic.Trapezoidal (0, 0, 0.25, 0.5)
"mid risk", FuzzyLogic.Triangular (0.25, 0.50, 0.75)
"high risk", FuzzyLogic.Trapezoidal (0.50, 0.75, 1, 1)
]
Console.Write ("Enter credit score: ")
let crips_credit_score = Console.ReadLine() |> float
let fuzzy_value_for_credit = FuzzyLogic.fuzzyfy credit_according_to_banckers crips_credit_score
fuzzy_value_for_credit
|> List.zip credit_according_to_banckers
|> List.iter (fun (n, v) -> Console.WriteLine ($"{n} => {v}") )
fuzzy_value_for_credit
|> FuzzyLogic.defuzzyfy risk_according_to_bankers
|> fun v -> Console.WriteLine($"defuzzified value: {v}")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment