Skip to content

Commit

Permalink
feat(fuzzy): update defuzz() output prep
Browse files Browse the repository at this point in the history
- add support for custom implications of rule outputs
- update/optimize rule weight handling
  • Loading branch information
postspectacular committed Dec 19, 2020
1 parent 8ec15fa commit 81abe8c
Showing 1 changed file with 25 additions and 8 deletions.
33 changes: 25 additions & 8 deletions packages/fuzzy/src/defuzz.ts
@@ -1,7 +1,8 @@
import type { IObjectOf } from "@thi.ng/api";
import type { FuzzyFn, LVar, Rule } from "./api";
import { cogStrategy } from "./cog";
import { weighted } from "./shapes";
import { constant, implication, weighted } from "./shapes";
import { tnormMin } from "./tnorms";

/**
* Takes an object of input {@link variable}s, an object of output variable,
Expand All @@ -10,32 +11,48 @@ import { weighted } from "./shapes";
* optional strategy (by default {@link cogStrategy} w/ its own default
* options). Returns object of computed output variable values.
*
* @remarks
* The `imply` T-norm (default: {@link tnormMin} is used to transform each
* rule's output set(s) using each rule's computed/aggregated truth value, as
* well as each rule's weight. Different T-norms might produce different fuzzy
* set shapes and different results, even if the defuzz strategy remains
* constant.
*
* @param ins
* @param outs
* @param rules
* @param vals
* @param strategy
* @param imply
*/
export const defuzz = (
ins: IObjectOf<LVar>,
outs: IObjectOf<LVar>,
rules: Rule[],
vals: IObjectOf<number>,
strategy = cogStrategy()
strategy = cogStrategy(),
imply = tnormMin
) => {
const ruleTerms = rules.map((r) => {
let acc: number | null = null;
let alpha: number | null = null;
for (let id in vals) {
if (r.if[id]) {
const v = ins[id].terms[r.if[id]](vals[id]);
acc = acc !== null ? r.op(acc, v) : v;
alpha = alpha !== null ? r.op(alpha, v) : v;
}
}
const weight = (acc || 0) * r.weight;
const terms: IObjectOf<FuzzyFn> = {};
for (let id in r.then) {
if (outs[id]) {
terms[id] = weighted(outs[id].terms[r.then[id]], weight);
if (alpha) {
const aterm = constant(alpha);
for (let id in r.then) {
if (outs[id]) {
const oterm = outs[id].terms[r.then[id]];
terms[id] = implication(
imply,
r.weight == 1 ? oterm : weighted(oterm, r.weight),
aterm
);
}
}
}
return terms;
Expand Down

0 comments on commit 81abe8c

Please sign in to comment.