@thi.ng/fuzzy
Version:
Fuzzy logic operators & configurable rule inferencing engine
57 lines (56 loc) • 1.77 kB
JavaScript
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
};