// The following code contains unit tests for Fuzzy Logicclasses and functions.
// Test 1 creates a left shoulder fuzzy set and tests the degree of membership
// function.
function test1() {
let fs = new FuzzySet_LeftShoulder(100, 50, 50);
let actual = '' + fs.calculateDOM(75) + ' '
+ fs.calculateDOM(100) + ' '
+ fs.calculateDOM(125);
let expected = '1 1 0.5';
compareStringsAndReport('Test 1', actual, expected);
}
// Test 2 creates a right shoulder fuzzy set and tests the degree of membership
// function.
function test2() {
let fs = new FuzzySet_RightShoulder(100, 50, 50);
let actual = '' + fs.calculateDOM(75) + ' '
+ fs.calculateDOM(100) + ' '
+ fs.calculateDOM(125);
let expected = '0.5 1 1';
compareStringsAndReport('Test 2', actual, expected);
}
// Test 3 creates a singleton fuzzy set and tests the degree of membership
// function.
function test3() {
let fs = new FuzzySet_Singleton(100, 50, 50);
let actual = '' + fs.calculateDOM(49) + ' '
+ fs.calculateDOM(51) + ' '
+ fs.calculateDOM(149);
let expected = '0 1 1';
compareStringsAndReport('Test 3', actual, expected);
}
// Test 4 creates a triangular fuzzy set and tests the degree of membership
// function.
function test4() {
let fs = new FuzzySet_Triangle(100, 50, 50);
let actual = '' + fs.calculateDOM(75) + ' '
+ fs.calculateDOM(100) + ' '
+ fs.calculateDOM(125);
let expected = '0.5 1 0.5';
compareStringsAndReport('Test 4', actual, expected);
}
// Test 5 creates a fuzzy variable with three sets and tests the fuzzification
// and defuzzification methods.
function test5() {
let fv = new FuzzyVariable()
.addLeftShoulderSet('left', 0, 50, 100)
.addTriangularSet('center', 50, 100, 150)
.addRightShoulderSet('right', 100, 150, 200)
.fuzzify(87.5);
fv.ORwithDOM(0.5);
let actual = '' + fv.sets['left'].DOM + ' '
+ fv.sets['center'].DOM + ' '
+ fv.sets['right'].DOM + ' '
+ fv.deFuzzifyMaxAv() + ' '
+ fv.deFuzzifyCentroid(15).toFixed(1);
let expected = '0.5 0.75 0.5 100 105.0';
compareStringsAndReport('Test 5', actual, expected);
}
// Test 6 creates a fuzzy AND operation and tests it on two triangular fuzzy sets.
function test6() {
let actual = new FuzzyAND([
new FuzzySet_Triangle(100, 50, 50).fuzzify(87.5),
new FuzzySet_Triangle(200, 50, 50).fuzzify(225)
]).getDOM();
let expected = 0.5;
compareAndReport('Test 6', actual, expected);
}
// Test 7 creates a fuzzy OR operation and tests it on two triangular fuzzy sets.
function test7() {
let actual = new FuzzyOR([
new FuzzySet_Triangle(100, 50, 50).fuzzify(87.5),
new FuzzySet_Triangle(200, 50, 50).fuzzify(225)
]).getDOM();
let expected = 0.75;
compareAndReport('Test 7', actual, expected);
}
// Test 8 creates and tests a fuzzy rule.
function test8() {
let rule = new FuzzyRule(
new FuzzyAND([
new FuzzySet_Triangle(100, 50, 50).fuzzify(87.5),
new FuzzySet_Triangle(200, 50, 50).fuzzify(225)
]),
new FuzzySet_Triangle(300, 50, 50)
);
let actual = rule.calculate().getDOM();
let expected = 0.5;
compareAndReport('Test 8', actual, expected);
}
// In test 9, fuzzy logic is employed to evaluate the desirability of a weapon.
// Each weapon has its own fuzzy module instance because the desirability
// inference is based on a unique set of rules specific to that weapon.
function test9() {
let m = new FuzzyModule();
let distToTarget = m.createVariable("distToTarget")
.addLeftShoulderSet("close", 0, 25, 150)
.addTriangularSet("medium", 25, 150, 300)
.addRightShoulderSet("far", 150, 300, 1000);
let desirability = m.createVariable("desirability")
.addRightShoulderSet("verydesirable", 50, 75, 100)
.addTriangularSet("desirable", 25, 50, 75)
.addLeftShoulderSet("undesirable", 0, 25, 50);
let ammoStatus = m.createVariable("ammoStatus")
.addRightShoulderSet("loads", 30, 60, 100)
.addTriangularSet("okay", 0, 30, 60)
.addTriangularSet("low", 0, 0, 30);
// close
m.addRule(new FuzzyAND([m.variables["distToTarget"].sets["close"],
m.variables["ammoStatus"].sets["loads"]]),
m.variables["desirability"].sets["verydesirable"]);
m.addRule(new FuzzyAND([m.variables["distToTarget"].sets["close"],
m.variables["ammoStatus"].sets["okay"]]),
m.variables["desirability"].sets["verydesirable"]);
m.addRule(new FuzzyAND([m.variables["distToTarget"].sets["close"],
m.variables["ammoStatus"].sets["low"]]),
m.variables["desirability"].sets["verydesirable"]);
// medium
m.addRule(new FuzzyAND([m.variables["distToTarget"].sets["medium"],
m.variables["ammoStatus"].sets["loads"]]),
m.variables["desirability"].sets["verydesirable"]);
m.addRule(new FuzzyAND([m.variables["distToTarget"].sets["medium"],
m.variables["ammoStatus"].sets["okay"]]),
m.variables["desirability"].sets["desirable"]);
m.addRule(new FuzzyAND([m.variables["distToTarget"].sets["medium"],
m.variables["ammoStatus"].sets["low"]]),
m.variables["desirability"].sets["undesirable"]);
// far
m.addRule(new FuzzyAND([m.variables["distToTarget"].sets["far"],
m.variables["ammoStatus"].sets["loads"]]),
m.variables["desirability"].sets["desirable"]);
m.addRule(new FuzzyAND([m.variables["distToTarget"].sets["far"],
m.variables["ammoStatus"].sets["okay"]]),
m.variables["desirability"].sets["undesirable"]);
m.addRule(new FuzzyAND([m.variables["distToTarget"].sets["far"],
m.variables["ammoStatus"].sets["low"]]),
m.variables["desirability"].sets["undesirable"]);
// Fuzzify distance and amount of ammo.
m.fuzzify("distToTarget", 150);
m.fuzzify("ammoStatus", 50);
// Calculate and defuzzify the result.
let actual = m.deFuzzify("desirability",
FuzzyModule.DefuzzifyMethod.max_av).toFixed(2);
let expected = 75;
compareAndReport('Test 9', actual, expected);
}
// In test 10, fuzzy logic is employed to evaluate the desirability of a weapon.
// Each weapon has its own fuzzy module instance because the desirability
// inference is based on a unique set of rules specific to that weapon.
function test10() {
let m = new FuzzyModule();
let distToTarget = m.createVariable("distToTarget")
.addLeftShoulderSet("close", 0, 25, 150)
.addTriangularSet("medium", 25, 150, 300)
.addRightShoulderSet("far", 150, 300, 1000);
let desirability = m.createVariable("desirability")
.addRightShoulderSet("verydesirable", 50, 75, 100)
.addTriangularSet("desirable", 25, 50, 75)
.addLeftShoulderSet("undesirable", 0, 25, 50);
let ammoStatus = m.createVariable("ammoStatus")
.addRightShoulderSet("loads", 10, 30, 100)
.addTriangularSet("okay", 0, 10, 30)
.addTriangularSet("low", 0, 0, 10);
// close
m.addRule(new FuzzyAND([m.variables["distToTarget"].sets["close"],
m.variables["ammoStatus"].sets["loads"]]),
m.variables["desirability"].sets["undesirable"]);
m.addRule(new FuzzyAND([m.variables["distToTarget"].sets["close"],
m.variables["ammoStatus"].sets["okay"]]),
m.variables["desirability"].sets["undesirable"]);
m.addRule(new FuzzyAND([m.variables["distToTarget"].sets["close"],
m.variables["ammoStatus"].sets["low"]]),
m.variables["desirability"].sets["undesirable"]);
// medium
m.addRule(new FuzzyAND([m.variables["distToTarget"].sets["medium"],
m.variables["ammoStatus"].sets["loads"]]),
m.variables["desirability"].sets["verydesirable"]);
m.addRule(new FuzzyAND([m.variables["distToTarget"].sets["medium"],
m.variables["ammoStatus"].sets["okay"]]),
m.variables["desirability"].sets["verydesirable"]);
m.addRule(new FuzzyAND([m.variables["distToTarget"].sets["medium"],
m.variables["ammoStatus"].sets["low"]]),
m.variables["desirability"].sets["desirable"]);
// far
m.addRule(new FuzzyAND([m.variables["distToTarget"].sets["far"],
m.variables["ammoStatus"].sets["loads"]]),
m.variables["desirability"].sets["desirable"]);
m.addRule(new FuzzyAND([m.variables["distToTarget"].sets["far"],
m.variables["ammoStatus"].sets["okay"]]),
m.variables["desirability"].sets["undesirable"]);
m.addRule(new FuzzyAND([m.variables["distToTarget"].sets["far"],
m.variables["ammoStatus"].sets["low"]]),
m.variables["desirability"].sets["undesirable"]);
// Fuzzify distance and amount of ammo.
m.fuzzify("distToTarget", 200);
m.fuzzify("ammoStatus", 8);
// Calculate and defuzzify the result.
let actual = m.deFuzzify("desirability",
FuzzyModule.DefuzzifyMethod.max_av).toFixed(2);
let expected = 60.42;
compareAndReport('Test 10', actual, expected);
}