jFuzzyLogic/html/fcl/tipper.js

212 lines
5.9 KiB
JavaScript
Raw Permalink Normal View History

2022-05-23 11:43:42 +02:00
//--------------------------------------------------------------------------------
// Code generated by jFuzzyLogic
//--------------------------------------------------------------------------------
function ruleAccumulationMethod_max(defuzzifierValue, valueToAggregate) {
return (defuzzifierValue > valueToAggregate ? defuzzifierValue : valueToAggregate);
}
function ruleActivationMethod_min(degreeOfSupport, membership) {
return (degreeOfSupport < membership ? degreeOfSupport : membership);
}
function ruleConnectionMethod_and(antecedent1, antecedent2) {
return (antecedent1 < antecedent2 ? antecedent1 : antecedent2);
}
function ruleConnectionMethod_or(antecedent1, antecedent2) {
return (antecedent1 > antecedent2 ? antecedent1 : antecedent2);
}
class FunctionBlock_tipper {
// VAR_INPUT
food;
service;
// VAR_OUTPUT
tip;
// FUZZIFY food
food_delicious;
food_rancid;
// FUZZIFY service
service_excellent;
service_good;
service_poor;
// DEFUZZIFY tip
defuzzify_tip;
// Constructor
constructor() {
this.tip = 0.0;
this.defuzzify_tip = new Array(1000);
}
// Calculate function block
calc() {
this.reset();
this.fuzzify();
this.calc_No1();
this.defuzzify();
}
// RULEBLOCK No1
calc_No1() {
// RULE 1 : IF (service IS poor) OR (food IS rancid) THEN tip IS cheap;
let degreeOfSupport_1 = 1.0 * (ruleConnectionMethod_or(this.service_poor, this.food_rancid));
if (degreeOfSupport_1 > 0) {
for (let i = 0; i < 1000; i++) {
let x = 0.0 + i * 0.03;
let membership = this.membership_tip_cheap(x);
let y = ruleActivationMethod_min(degreeOfSupport_1 , membership);
this.defuzzify_tip[i] = ruleAccumulationMethod_max(this.defuzzify_tip[i], y);
}
}
// RULE 2 : IF service IS good THEN tip IS average;
let degreeOfSupport_2 = 1.0 * (this.service_good);
if (degreeOfSupport_2 > 0) {
for (let i = 0; i < 1000; i++) {
let x = 0.0 + i * 0.03;
let membership = this.membership_tip_average(x);
let y = ruleActivationMethod_min(degreeOfSupport_2 , membership);
this.defuzzify_tip[i] = ruleAccumulationMethod_max(this.defuzzify_tip[i], y);
}
}
// RULE 3 : IF (service IS excellent) AND (food IS delicious) THEN tip IS generous;
let degreeOfSupport_3 = 1.0 * (ruleConnectionMethod_and(this.service_excellent, this.food_delicious));
if (degreeOfSupport_3 > 0) {
for (let i = 0; i < 1000; i++) {
let x = 0.0 + i * 0.03;
let membership = this.membership_tip_generous(x);
let y = ruleActivationMethod_min(degreeOfSupport_3 , membership);
this.defuzzify_tip[i] = ruleAccumulationMethod_max(this.defuzzify_tip[i], y);
}
}
}
// Defuzzify
defuzzify() {
let sum_tip = 0.0;
let wsum_tip = 0.0;
let x;
for (let i = 0; i < 1000; i++) {
x = 0.0 + i * 0.03;
sum_tip += this.defuzzify_tip[i];
wsum_tip += x * this.defuzzify_tip[i];
}
2022-07-27 19:11:50 +02:00
if (sum_tip == 0) {
sum_tip = 1.0;
}
2022-05-23 11:43:42 +02:00
this.tip = wsum_tip / sum_tip;
}
// Fuzzify all variables
fuzzify() {
this.food_delicious = this.membership_food_delicious(this.food);
this.food_rancid = this.membership_food_rancid(this.food);
this.service_excellent = this.membership_service_excellent(this.service);
this.service_good = this.membership_service_good(this.service);
this.service_poor = this.membership_service_poor(this.service);
}
// Membership functions
membership_food_delicious(x) {
if (x <= 7.0) return 0.0;
if (x > 9.0) return 1.0;
if (x <= 9.0) return 0.0 + (1.0 - 0.0) * ((x - 7.0) / (9.0 - 7.0));
}
membership_food_rancid(x) {
if (x <= 0.0) return 1.0;
if (x > 3.0) return 0.0;
if (x <= 1.0) return 1.0 + (1.0 - 1.0) * ((x - 0.0) / (1.0 - 0.0));
if (x <= 3.0) return 1.0 + (0.0 - 1.0) * ((x - 1.0) / (3.0 - 1.0));
}
membership_service_excellent(x) {
if (x <= 6.0) return 0.0;
if (x > 9.0) return 1.0;
if (x <= 9.0) return 0.0 + (1.0 - 0.0) * ((x - 6.0) / (9.0 - 6.0));
}
membership_service_good(x) {
if (x <= 1.0) return 0.0;
if (x > 9.0) return 0.0;
if (x <= 4.0) return 0.0 + (1.0 - 0.0) * ((x - 1.0) / (4.0 - 1.0));
if (x <= 6.0) return 1.0 + (1.0 - 1.0) * ((x - 4.0) / (6.0 - 4.0));
if (x <= 9.0) return 1.0 + (0.0 - 1.0) * ((x - 6.0) / (9.0 - 6.0));
}
membership_service_poor(x) {
if (x <= 0.0) return 1.0;
if (x > 4.0) return 0.0;
if (x <= 4.0) return 1.0 + (0.0 - 1.0) * ((x - 0.0) / (4.0 - 0.0));
}
membership_tip_average(x) {
if (x <= 10.0) return 0.0;
if (x > 20.0) return 0.0;
if (x <= 15.0) return 0.0 + (1.0 - 0.0) * ((x - 10.0) / (15.0 - 10.0));
if (x <= 20.0) return 1.0 + (0.0 - 1.0) * ((x - 15.0) / (20.0 - 15.0));
}
membership_tip_cheap(x) {
if (x <= 0.0) return 0.0;
if (x > 10.0) return 0.0;
if (x <= 5.0) return 0.0 + (1.0 - 0.0) * ((x - 0.0) / (5.0 - 0.0));
if (x <= 10.0) return 1.0 + (0.0 - 1.0) * ((x - 5.0) / (10.0 - 5.0));
}
membership_tip_generous(x) {
if (x <= 20.0) return 0.0;
if (x > 30.0) return 0.0;
if (x <= 25.0) return 0.0 + (1.0 - 0.0) * ((x - 20.0) / (25.0 - 20.0));
if (x <= 30.0) return 1.0 + (0.0 - 1.0) * ((x - 25.0) / (30.0 - 25.0));
}
// Print
print() {
console.log("Function block tipper:\n");
console.log(" Input %s: %f\n", "food" , this.food);
console.log(" %s: %f\n", "food_delicious" , this.food_delicious);
console.log(" %s: %f\n", "food_rancid" , this.food_rancid);
console.log(" Input %s: %f\n", "service" , this.service);
console.log(" %s: %f\n", "service_excellent" , this.service_excellent);
console.log(" %s: %f\n", "service_good" , this.service_good);
console.log(" %s: %f\n", "service_poor" , this.service_poor);
console.log(" Output %s: %f\n", "tip" , this.tip);
}
// Reset output
reset() {
for (let i = 0 ; i < 1000; i++) {
this.defuzzify_tip[i] = 0.0;
}
}
};
function main(food, service) {
// Create function blocks
const tipper = new FunctionBlock_tipper();
// Parse input
tipper.food = food;
tipper.service = service;
// Calculate
tipper.calc();
// Show results
tipper.print();
2022-07-27 13:51:24 +02:00
return [tipper.tip];
2022-05-23 11:43:42 +02:00
}