@thi.ng/fuzzy
    TypeScript icon, indicating that this package has built-in type declarations

    0.1.14 • Public • Published

    fuzzy

    npm version npm downloads Twitter Follow

    This project is part of the @thi.ng/umbrella monorepo.

    About

    Fuzzy logic operators & configurable rule inferencing engine.

    Features

    • Entirely declarative & functional approach
    • Fully type checked
    • Fuzzy set domain shaping & composition functions (incl. negated / inverse)
    • Various T-norms & S-norms, incl. parametric versions
    • Rules with multiple inputs/outputs and arbitrary term combinators (i.e. T-norms). Syntax sugar for common and/or rules.
    • Defuzzification via customizable strategies and options to balance precision vs. performance
      • Maxima: First, Last, Mean
      • Center-of-Gravity (COG)
    • Linguistic variable creation and term/set classification for given domain values
    • Fuzzy set visualization (via @thi.ng/fuzzy-viz)

    References / Further reading

    Status

    ALPHA - bleeding edge / work-in-progress

    Search or submit any issues for this package

    Support packages

    Installation

    yarn add @thi.ng/fuzzy
    // ES module
    <script type="module" src="https://unpkg.com/@thi.ng/fuzzy?module" crossorigin></script>
    
    // UMD
    <script src="https://unpkg.com/@thi.ng/fuzzy/lib/index.umd.js" crossorigin></script>

    Package sizes (gzipped, pre-treeshake): ESM: 1.64 KB / CJS: 1.82 KB / UMD: 1.74 KB

    Dependencies

    API

    Generated API docs

    (See tests for more usage examples).

    Fuzzy set generators & combinators

    Generators:

    • constant()
    • point()
    • ramp() / invRamp()
    • triangle()
    • trapezoid()
    • sigmoid() / invSigmoid()
    • gaussian()

    Combinators:

    • negate()
    • weighted()
    • alphaCut() / invAlphaCut()
    • compose() / intersect() / union()

    Linguistic variables

    Linguistic variables (short: L-vars) are groupings of named (and possibly overlapping) fuzzy sets within a given value domain. The can be used standalone or as inputs/outputs in rules (further below).

    The @thi.ng/fuzzy-viz package provides utilities to visualize the fuzzy sets of an L-var.

    fuzzy set visualization of the example l-var

    // temperature sets (in celsius)
    const temp = variable(
      // value domain
      [-20, 40],
      {
        freezing: invSigmoid(0, 2),
        cold: trapezoid(-1, 2, 16, 20),
        warm: trapezoid(15, 20, 30, 34),
        hot: sigmoid(32, 2)
      }
    );
    
    // evaluate all fuzzy sets for given domain value
    evaluate(temp, 18)
    // {
    //   freezing: 2.220446049250313e-16,
    //   cold: 0.5,
    //   warm: 0.6,
    //   hot: 6.914400106935423e-13
    // }
    
    evaluate(temp, 28)
    // {
    //   freezing: 0,
    //   cold: 0,
    //   warm: 1,
    //   hot: 0.0003353501304664781
    // }
    
    // classify temperature (min confidence 33%, default: 50%)
    classify(temp, 28, 0.33)
    // "warm"

    Rule creation & inferencing

    Example taken from Franck Dernoncourt's Introduction to Fuzzy Logic:

    fuzzy set illustration from F.Dernoncourt's tutorial

    // define fuzzy input variables
    const inputs = {
      food: variable([0, 10], {
        awful: invRamp(1, 3),
        delicious: ramp(7, 9),
      }),
      service: variable([0, 10], {
        poor: gaussian(0, 1.5),
        good: gaussian(5, 1.5),
        excellent: gaussian(10, 1.5),
      }),
    };
    
    const outputs = {
      tip: variable([0, 30], {
        low: triangle(0, 5, 10),
        medium: triangle(10, 15, 20),
        high: triangle(20, 25, 30),
      }),
    };
    
    // l-vars, rules and defuzzification are using generics for type safety
    // we define these 2 type aliases for brevity
    type I = typeof inputs;
    type O = typeof outputs;
    
    // rule definitions:
    // if service is poor OR food is awful -> tip is low
    // if service is normal -> tip is medium
    // if service is excellent OR food is delicious -> tip is high
    const rules = [
      or<I, O>({ food: "awful", service: "poor" }, { tip: "low" }),
      or<I, O>({ service: "good" }, { tip: "medium" }),
      or<I, O>({ food: "delicious", service: "excellent" }, { tip: "high" }),
    ];
    
    // defuzzification using default center-of-gravity strategy
    defuzz(
      inputs,
      outputs,
      rules,
      // input values
      { food: 7.32, service: 7.83 },
    );
    // { tip: 22.650000000000034 }
    
    // defuzz with custom strategy (note: each has further config options)
    defuzz(
      inputs,
      outputs,
      rules,
      // input values
      { food: 7.32, service: 7.83 },
      // custom defuzz strategy
      meanOfMaximaStrategy()
    );
    // { tip: 25.050000000000043 }

    Note: The results are slightly different than those in the textbook example, due to different gaussian fuzzy sets used for the service L-var.

    Using instrumentStrategy() from the upcoming @thi.ng/fuzzy-viz package, we can also visualize the final, transformed fuzzy sets used to compute crisp results and highlight the position of the crisp result value.

    Here is the ASCII art output for the centroidStrategy and using tnormMin (the default) to transform each rule's output set(s):

    // wrap existing strategy
    const strat = instrumentStrategy(centroidStrategy(), fuzzySetToAscii());
    
    // call defuzz as normal
    defuzz(inputs, outputs, rules, strat);
    
    // obtain secondary results via deref()
    console.log(strat.deref()[0]);
    ........................................................................|...........................
    ........................................................................|...........................
    ........................................................................|...........................
    ........................................................................|...........................
    ........................................................................|...........................
    ........................................................................|...........................
    ........................................................................|...........................
    ........................................................................|...........................
    ........................................................................|...........................
    ........................................................................|...........................
    ........................................................................|▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅▅.....
    .......................................................................▁|██████████████████████▇....
    ......................................................................▁█|███████████████████████▇...
    ....................................▅▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▅....▂██|████████████████████████▇..
    ...................................▅█████████████████████████████▅..▂███|██████████████████████████.
    ..................................▅███████████████████████████████▅▂████|███████████████████████████
                                                                            ^ 21.52
    

    Different results can be obtained by adjusting the T-norm used to transform each rule's output sets, here using tnormHamacher(2).

    .........................................................................|..........................
    .........................................................................|..........................
    .........................................................................|..........................
    .........................................................................|..........................
    .........................................................................|..........................
    .........................................................................|..........................
    .........................................................................|..........................
    .........................................................................|..........................
    .........................................................................|..........................
    .........................................................................|..........................
    .........................................................................|.........▃▂...............
    .........................................................................|.......▃███▆▂.............
    .........................................................................|....▁▅███████▇▃...........
    ................................................▁▃▆▃▁....................|.▁▄▇████████████▆▃........
    ...........................................▁▂▄▆███████▆▄▂▁..............▂|▇██████████████████▆▃▁....
    ...................................▁▂▃▄▅▆▇█████████████████▇▆▅▄▃▂▁..▂▄▆██|███████████████████████▅▃▁
                                                                             ^ 21.84
    

    ...or using tnormAczelAlsina(2) (there're many more available):

    ........................................................................|...........................
    ........................................................................|...........................
    ........................................................................|...........................
    ........................................................................|...........................
    ........................................................................|...........................
    ........................................................................|...........................
    ........................................................................|...........................
    ........................................................................|...........................
    ........................................................................|...........................
    ........................................................................|...........................
    ........................................................................|.....▂▃▄▅▅▅▅▅▄▄▃▁..........
    ........................................................................|.▂▅▇██████████████▆▄.......
    ........................................................................|▇████████████████████▆▂....
    ........................................▁▂▃▄▄▅▅▆▆▆▆▆▆▆▅▅▄▄▃▂▁.........▃█|███████████████████████▆▁..
    ....................................▂▄▇███████████████████████▇▄▂....▆██|█████████████████████████▄.
    ..................................▃▇█████████████████████████████▇▃▂████|██████████████████████████▇
                                                                            ^ 21.58
    

    Just for illustration purposes (and using a different example), SVG output can be obtained by merely switching to another instrumentation function (here fuzzySetToSvg()):

    fuzzySetToSvg() visualization example

    Authors

    Karsten Schmidt

    If this project contributes to an academic publication, please cite it as:

    @misc{thing-fuzzy,
      title = "@thi.ng/fuzzy",
      author = "Karsten Schmidt",
      note = "https://thi.ng/fuzzy",
      year = 2020
    }

    License

    © 2020 - 2021 Karsten Schmidt // Apache Software License 2.0

    Install

    npm i @thi.ng/fuzzy

    DownloadsWeekly Downloads

    12

    Version

    0.1.14

    License

    Apache-2.0

    Unpacked Size

    115 kB

    Total Files

    30

    Last publish

    Collaborators

    • avatar