jFuzzyLogic/html/fcl/tipper.cpp
2022-05-23 11:43:42 +02:00

224 lines
6.9 KiB
C++

//--------------------------------------------------------------------------------
// Code generated by jFuzzyLogic
// jFuzzyLogic Version : JFuzzyLogic 4.0 (build 2022-05-12), by Pablo Cingolani
// jFuzzyLogic created by Pablo Cingolani
//--------------------------------------------------------------------------------
#include <stdio.h>
#include <stdlib.h>
double ruleAccumulationMethod_max(double defuzzifierValue, double valueToAggregate) { return ( defuzzifierValue > valueToAggregate ? defuzzifierValue : valueToAggregate ); }
double ruleActivationMethod_min(double degreeOfSupport, double membership) { return (degreeOfSupport < membership ? degreeOfSupport : membership); }
double ruleConnectionMethod_and(double antecedent1, double antecedent2) { return (antecedent1 < antecedent2 ? antecedent1 : antecedent2); }
double ruleConnectionMethod_or(double antecedent1, double antecedent2) { return (antecedent1 > antecedent2 ? antecedent1 : antecedent2); }
class FunctionBlock_tipper {
public:
// VAR_INPUT
double food;
double service;
// VAR_OUTPUT
double tip;
private:
// FUZZIFY food
double food_delicious;
double food_rancid;
// FUZZIFY service
double service_excellent;
double service_good;
double service_poor;
// DEFUZZIFY tip
double defuzzify_tip[1000];
public:
FunctionBlock_tipper();
void calc();
void print();
private:
void defuzzify();
void fuzzify();
void reset();
double membership_food_delicious(double x);
double membership_food_rancid(double x);
double membership_service_excellent(double x);
double membership_service_good(double x);
double membership_service_poor(double x);
double membership_tip_average(double x);
double membership_tip_cheap(double x);
double membership_tip_generous(double x);
void calc_No1();
};
// Constructor
FunctionBlock_tipper::FunctionBlock_tipper() {
tip = 0.0;
}
// Calculate function block
void FunctionBlock_tipper::calc() {
reset();
fuzzify();
calc_No1();
defuzzify();
}
// RULEBLOCK No1
void FunctionBlock_tipper::calc_No1() {
// RULE 1 : IF (service IS poor) OR (food IS rancid) THEN tip IS cheap;
double degreeOfSupport_1 = 1.0 * ( ruleConnectionMethod_or(service_poor , food_rancid) );
if( degreeOfSupport_1 > 0 ) {
for (int i = 0 ; i < 1000 ; i++ ) {
double x = 0.0 + i * 0.03;
double membership = membership_tip_cheap(x);
double y = ruleActivationMethod_min( degreeOfSupport_1 , membership );
defuzzify_tip[i] = ruleAccumulationMethod_max( defuzzify_tip[i], y );
}
}
// RULE 2 : IF service IS good THEN tip IS average;
double degreeOfSupport_2 = 1.0 * ( service_good );
if( degreeOfSupport_2 > 0 ) {
for (int i = 0 ; i < 1000 ; i++ ) {
double x = 0.0 + i * 0.03;
double membership = membership_tip_average(x);
double y = ruleActivationMethod_min( degreeOfSupport_2 , membership );
defuzzify_tip[i] = ruleAccumulationMethod_max( defuzzify_tip[i], y );
}
}
// RULE 3 : IF (service IS excellent) AND (food IS delicious) THEN tip IS generous;
double degreeOfSupport_3 = 1.0 * ( ruleConnectionMethod_and(service_excellent , food_delicious) );
if( degreeOfSupport_3 > 0 ) {
for (int i = 0 ; i < 1000 ; i++ ) {
double x = 0.0 + i * 0.03;
double membership = membership_tip_generous(x);
double y = ruleActivationMethod_min( degreeOfSupport_3 , membership );
defuzzify_tip[i] = ruleAccumulationMethod_max( defuzzify_tip[i], y );
}
}
}
// Defuzzify
void FunctionBlock_tipper::defuzzify() {
double sum_tip = 0.0;
double wsum_tip = 0.0;
for (int i = 0; i < 1000 ; i++ ) {
double x = 0.0 + i * 0.03;
sum_tip += defuzzify_tip[i];
wsum_tip += x * defuzzify_tip[i];
}
tip = wsum_tip / sum_tip;
}
// Fuzzify all variables
void FunctionBlock_tipper::fuzzify() {
food_delicious = membership_food_delicious(food);
food_rancid = membership_food_rancid(food);
service_excellent = membership_service_excellent(service);
service_good = membership_service_good(service);
service_poor = membership_service_poor(service);
}
// Membership functions
double FunctionBlock_tipper::membership_food_delicious(double 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 ) );
}
double FunctionBlock_tipper::membership_food_rancid(double 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 ) );
}
double FunctionBlock_tipper::membership_service_excellent(double 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 ) );
}
double FunctionBlock_tipper::membership_service_good(double 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 ) );
}
double FunctionBlock_tipper::membership_service_poor(double 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 ) );
}
double FunctionBlock_tipper::membership_tip_average(double 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 ) );
}
double FunctionBlock_tipper::membership_tip_cheap(double 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 ) );
}
double FunctionBlock_tipper::membership_tip_generous(double 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
void FunctionBlock_tipper::print() {
printf("Function block tipper:\n");
printf(" Input %20s : %f\n", "food" , food);
printf(" %20s : %f\n", "food_delicious" , food_delicious);
printf(" %20s : %f\n", "food_rancid" , food_rancid);
printf(" Input %20s : %f\n", "service" , service);
printf(" %20s : %f\n", "service_excellent" , service_excellent);
printf(" %20s : %f\n", "service_good" , service_good);
printf(" %20s : %f\n", "service_poor" , service_poor);
printf(" Output %20s : %f\n", "tip" , tip);
}
// Reset output
void FunctionBlock_tipper::reset() {
for( int i=0 ; i < 1000 ; i++ ) { defuzzify_tip[i] = 0.0; }
}
int main(int argc, char *argv[]) {
// Create function blocks
FunctionBlock_tipper tipper;
// Parse input
if( argc > 1 ) { tipper.food = atof(argv[1]); }
if( argc > 2 ) { tipper.service = atof(argv[2]); }
// Calculate
tipper.calc();
// Show results
tipper.print();
}