Skip to content

Commit

Permalink
FuzzyModule: Enhance API
Browse files Browse the repository at this point in the history
  • Loading branch information
Mugen87 committed Jan 5, 2019
1 parent 4d3b4e6 commit 749a2a1
Show file tree
Hide file tree
Showing 9 changed files with 309 additions and 11 deletions.
63 changes: 57 additions & 6 deletions examples/fuzzy/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -13,19 +13,70 @@

import * as YUKA from '../../build/yuka.module.js';

const flv = new YUKA.FuzzyVariable();
const fuzzyModule = new YUKA.FuzzyModule();

// FLV distance to target

const distanceToTarget = new YUKA.FuzzyVariable();

const targetClose = new YUKA.LeftShoulderFuzzySet( 0, 25, 150 );
const targetMedium = new YUKA.TriangularFuzzySet( 25, 150, 300 );
const targetFar = new YUKA.RightShoulderFuzzySet( 150, 300, 500 );

flv.add( targetClose );
flv.add( targetMedium );
flv.add( targetFar );
distanceToTarget.add( targetClose );
distanceToTarget.add( targetMedium );
distanceToTarget.add( targetFar );

fuzzyModule.addFLV( 'distanceToTarget', distanceToTarget );

// FLV ammo status

const ammoStatus = new YUKA.FuzzyVariable();

const ammoLow = new YUKA.LeftShoulderFuzzySet( 0, 0, 10 );
const ammoOkay = new YUKA.TriangularFuzzySet( 0, 10, 30 );
const ammoFull = new YUKA.RightShoulderFuzzySet( 10, 30, 40 );

ammoStatus.add( ammoLow );
ammoStatus.add( ammoOkay );
ammoStatus.add( ammoFull );

fuzzyModule.addFLV( 'ammoStatus', ammoStatus );

// FLV desirability

const desirability = new YUKA.FuzzyVariable();

const undesirable = new YUKA.LeftShoulderFuzzySet( 0, 25, 50 );
const desirable = new YUKA.TriangularFuzzySet( 25, 50, 75 );
const veryDesirable = new YUKA.RightShoulderFuzzySet( 50, 75, 100 );

desirability.add( undesirable );
desirability.add( desirable );
desirability.add( veryDesirable );

fuzzyModule.addFLV( 'desirability', desirability );

// rules

fuzzyModule.addRule( new YUKA.FuzzyRule( new YUKA.FuzzyAND( targetClose, ammoLow ), undesirable ) );
fuzzyModule.addRule( new YUKA.FuzzyRule( new YUKA.FuzzyAND( targetClose, ammoOkay ), undesirable ) );
fuzzyModule.addRule( new YUKA.FuzzyRule( new YUKA.FuzzyAND( targetClose, ammoFull ), undesirable ) );

fuzzyModule.addRule( new YUKA.FuzzyRule( new YUKA.FuzzyAND( targetMedium, ammoLow ), desirable ) );
fuzzyModule.addRule( new YUKA.FuzzyRule( new YUKA.FuzzyAND( targetMedium, ammoOkay ), veryDesirable ) );
fuzzyModule.addRule( new YUKA.FuzzyRule( new YUKA.FuzzyAND( targetMedium, ammoFull ), veryDesirable ) );

fuzzyModule.addRule( new YUKA.FuzzyRule( new YUKA.FuzzyAND( targetFar, ammoLow ), undesirable ) );
fuzzyModule.addRule( new YUKA.FuzzyRule( new YUKA.FuzzyAND( targetFar, ammoOkay ), undesirable ) );
fuzzyModule.addRule( new YUKA.FuzzyRule( new YUKA.FuzzyAND( targetFar, ammoFull ), desirable ) );

// fuzzy inference

flv.fuzzify( 50 );
fuzzyModule.fuzzify( 'distanceToTarget', 200 );
fuzzyModule.fuzzify( 'ammoStatus', 8 );

console.log( flv.defuzzifyMaxAv() );
console.log( fuzzyModule.defuzzify( 'desirability' ) );

</script>

Expand Down
48 changes: 48 additions & 0 deletions src/fuzzy/FuzzyCompositeTerm.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import { FuzzyTerm } from './FuzzyTerm.js';

/**
* TODO
*
* @author {@link https://github.com/Mugen87|Mugen87}
*/
class FuzzyCompositeTerm extends FuzzyTerm {

constructor( terms ) {

super();

this.terms = terms;

}

clearDegreeOfMembership() {

const terms = this.terms;

for ( let i = 0, l = terms.length; i < l; i ++ ) {

terms[ i ].clearDegreeOfMembership();

}

return this;

}

updateDegreeOfMembership( value ) {

const terms = this.terms;

for ( let i = 0, l = terms.length; i < l; i ++ ) {

terms[ i ].updateDegreeOfMembership( value );

}

return this;

}

}

export { FuzzyCompositeTerm };
53 changes: 49 additions & 4 deletions src/fuzzy/FuzzyModule.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,22 +7,67 @@ class FuzzyModule {

constructor() {

this.rules = new Set();
this.variables = new Map();
this.rules = new Array();
this.flvs = new Map();

}

addFLV( name, flv ) {

this.variables.set( name, flv );
this.flvs.set( name, flv );

return this;

}

addRule( rule ) {

this.rules.add( rule );
this.rules.push( rule );

return this;

}

fuzzify( name, value ) {

const flv = this.flvs.get( name );

flv.fuzzify( value );

}

defuzzify( name ) {

const flvs = this.flvs;
const rules = this.rules;

this.initConsequents();

for ( let i = 0, l = rules.length; i < l; i ++ ) {

const rule = rules[ i ];

rule.evaluate();

}

const flv = flvs.get( name );

return flv.defuzzifyMaxAv();

}

initConsequents() {

const rules = this.rules;

for ( let i = 0, l = rules.length; i < l; i ++ ) {

const rule = rules[ i ];

rule.initConsequent();

}

return this;

Expand Down
29 changes: 29 additions & 0 deletions src/fuzzy/FuzzyRule.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/**
* TODO
*
* @author {@link https://github.com/Mugen87|Mugen87}
*/
class FuzzyRule {

constructor( antecedent, consequence ) {

this.antecedent = antecedent;
this.consequence = consequence;

}

initConsequent() {

this.consequence.clearDegreeOfMembership();

}

evaluate() {

this.consequence.updateDegreeOfMembership( this.antecedent.getDegreeOfMembership() );

}

}

export { FuzzyRule };
30 changes: 29 additions & 1 deletion src/fuzzy/FuzzySet.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
import { FuzzyTerm } from './FuzzyTerm.js';

/**
* Base class for fuzzy sets.
*
* @author {@link https://github.com/Mugen87|Mugen87}
*/
class FuzzySet {
class FuzzySet extends FuzzyTerm {

constructor( representativeValue = 0 ) {

super();

this.degreeOfMembership = 0;
this.representativeValue = representativeValue;

Expand All @@ -19,6 +23,30 @@ class FuzzySet {

computeDegreeOfMembership( /* value */ ) {}

// FuzzyTerm API

clearDegreeOfMembership() {

this.degreeOfMembership = 0;

return this;

}

getDegreeOfMembership() {

return this.degreeOfMembership;

}

updateDegreeOfMembership( value ) {

if ( value > this.degreeOfMembership ) this.degreeOfMembership = value;

return this;

}

}

export { FuzzySet };
16 changes: 16 additions & 0 deletions src/fuzzy/FuzzyTerm.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
/**
* TODO
*
* @author {@link https://github.com/Mugen87|Mugen87}
*/
class FuzzyTerm {

clearDegreeOfMembership() {}

getDegreeOfMembership() {}

updateDegreeOfMembership() {}

}

export { FuzzyTerm };
38 changes: 38 additions & 0 deletions src/fuzzy/operators/FuzzyAND.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { FuzzyCompositeTerm } from '../FuzzyCompositeTerm.js';

/**
* TODO
*
* @author {@link https://github.com/Mugen87|Mugen87}
*/
class FuzzyAND extends FuzzyCompositeTerm {

constructor() {

const terms = Array.from( arguments );

super( terms );

}

getDegreeOfMembership() {

const terms = this.terms;
let minDOM = Infinity;

for ( let i = 0, l = terms.length; i < l; i ++ ) {

const term = terms[ i ];
const currentDOM = term.getDegreeOfMembership();

if ( currentDOM < minDOM ) minDOM = currentDOM;

}

return minDOM;

}

}

export { FuzzyAND };
38 changes: 38 additions & 0 deletions src/fuzzy/operators/FuzzyOR.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { FuzzyCompositeTerm } from '../FuzzyCompositeTerm.js';

/**
* TODO
*
* @author {@link https://github.com/Mugen87|Mugen87}
*/
class FuzzyOR extends FuzzyCompositeTerm {

constructor() {

const terms = Array.from( arguments );

super( terms );

}

getDegreeOfMembership() {

const terms = this.terms;
let maxDOM = - Infinity;

for ( let i = 0, l = terms.length; i < l; i ++ ) {

const term = terms[ i ];
const currentDOM = term.getDegreeOfMembership();

if ( currentDOM > maxDOM ) maxDOM = currentDOM;

}

return maxDOM;

}

}

export { FuzzyOR };
5 changes: 5 additions & 0 deletions src/yuka.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,17 @@ export { Time } from './core/Time.js';
export { Telegram } from './core/Telegram.js';
export { State } from './fsm/State.js';
export { StateMachine } from './fsm/StateMachine.js';
// export { FuzzyAND } from './fuzzy/operators/FuzzyAND.js';
// export { FuzzyOR } from './fuzzy/operators/FuzzyOR.js';
// export { LeftShoulderFuzzySet } from './fuzzy/sets/LeftShoulderFuzzySet.js';
// export { RightShoulderFuzzySet } from './fuzzy/sets/RightShoulderFuzzySet.js';
// export { SingletonFuzzySet } from './fuzzy/sets/SingletonFuzzySet.js';
// export { TriangularFuzzySet } from './fuzzy/sets/TriangularFuzzySet.js';
// export { FuzzyCompositeTerm } from './fuzzy/FuzzyCompositeTerm.js';
// export { FuzzyModule } from './fuzzy/FuzzyModule.js';
// export { FuzzyRule } from './fuzzy/FuzzyRule.js';
// export { FuzzySet } from './fuzzy/FuzzySet.js';
// export { FuzzyTerm } from './fuzzy/FuzzyTerm.js';
// export { FuzzyVariable } from './fuzzy/FuzzyVariable.js';
export { CompositeGoal } from './goal/CompositeGoal.js';
export { Goal } from './goal/Goal.js';
Expand Down

0 comments on commit 749a2a1

Please sign in to comment.