UNPKG

@thi.ng/fuzzy

Version:

Fuzzy logic operators & configurable rule inferencing engine

57 lines (56 loc) 1.77 kB
import { EPS } from "@thi.ng/math/api"; import { eqDelta } from "@thi.ng/math/eqdelta"; import { fit, fitClamped } from "@thi.ng/math/fit"; import { gaussian as $gaussian, sigmoid as $sigmoid } from "@thi.ng/math/mix"; const constant = (x) => () => x; const point = (p, eps = EPS) => (x) => eqDelta(x, p, eps) ? 1 : 0; const ramp = (a, b) => (x) => fitClamped(x, a, b, 0, 1); const triangle = (a, b, c) => (x) => x < a || x > c ? 0 : x <= b ? fit(x, a, b, 0, 1) : fit(x, b, c, 1, 0); const trapezoid = (a, b, c, d) => (x) => x < a || x > d ? 0 : x > b && x < c ? 1 : x <= b ? fit(x, a, b, 0, 1) : fit(x, c, d, 1, 0); const sigmoid = (bias, steep) => (x) => $sigmoid(bias, steep, x); const gaussian = (bias, sigma) => (x) => $gaussian(bias, sigma, x); const negate = (fn) => (x) => 1 - fn(x); const invRamp = (a, b) => negate(ramp(a, b)); const invSigmoid = (bias, steep) => negate(sigmoid(bias, steep)); const weighted = (fn, weight) => (x) => weight * fn(x); const alphaCut = (fn, alpha = 0.5) => (x) => { const y = fn(x); return y > alpha ? y : 0; }; const invAlphaCut = (fn, alpha = 0.5) => (x) => { const y = fn(x); return y < alpha ? y : 0; }; const compose = (op, initial, ...fns) => { const [a, b] = fns; switch (fns.length) { case 0: throw new Error("no fuzzy sets given"); case 1: return a; case 2: return (x) => op(a(x), b(x)); default: return (x) => fns.reduce((acc, f) => op(acc, f(x)), initial); } }; const intersect = (op, ...fns) => compose(op, 1, ...fns); const union = (op, ...fns) => compose(op, 0, ...fns); export { alphaCut, compose, constant, gaussian, intersect, invAlphaCut, invRamp, invSigmoid, negate, point, ramp, sigmoid, trapezoid, triangle, union, weighted };