XFL3: The Xfuzzy 3 specification language

Membership function definition

The membership functions are assigned to the linguistic labels that form a linguistic variable type. The structure of a membership function definition in a function package is as follows:

		mf identifier { blocks }                    

The blocks that can appear in a membership function definition are alias, parameter, requires, java, ansi_c, cplusplus, derivative, update and source.

The block alias is used to define alternative names to identify the function. Any of these identifiers can be used to refer the function. The syntax of the block alias is:

		alias identifier, identifier, ... ;                   

The block parameter allows the definition of those parameters which the function depends on. The last identifier can be followed by brackets to define a list of parameters. Its format is:

		parameter identifier, identifier, ..., identifier[] ;                   

The block requires expresses the constraints on the parameter values by means of a Java Boolean expression that validates the parameter values. This expression can also use the values of the variables 'min' and 'max', which represent the minimum and maximum values in the universe of discourse of the linguistic variable considered. The structure of this block is:

		requires { expression }                    

The blocks java, ansi_c and cplusplus describe the function behavior by means of its description as a function body in Java, C and C++ programming languages, respectively. The format of these blocks is the following:

		java { Java_function_body } 
		ansi_c { C_function_body } 
		cplusplus { C++_function_body } 

The definition of a membership function includes not only the description of the function behavior itself, but also the function behavior under the greater-or-equal and smaller-or-equal modifications, and the computation of the center and basis values of the membership function. As a consequence, the blocks java, ansi_c and cplusplus are divided into the following subblocks:

		equal { code } 
		greatereq { code } 
		smallereq { code } 
		center { code } 
		basis { code }    

The subblock equal describes the function behavior. The subblocks greatereq and smallereq describe the greater-or-equal and smaller-or-equal modifications, respectively. The input variable in these subblocks is called 'x', and the code can use the values of the function parameters and the variables 'min' and 'max', which represent the minimum and maximum values of the universe of discourse of the function. The subblocks greatereq and smallereq can be omitted. In that case, these transformations are computed by sweeping all the values of the universe of discourse. However, it is much more efficient to use an analytical function, so that the definition of these subblocks is strongly recommended.

The subblocks center and basis describe the center and basis of the membership function. The code of these subblocks can use the values of the function parameters and the variables 'min' and 'max'. This information is used by several simplified defuzzification methods. These subblocks are optional and their default functions return a zero value.

The block derivative describes the derivative function with respect to each function parameter. This block is also divided into the subblocks equal, greatereq, smallereq, center and basis. The code of these subblocks consists of Java expressions assigning values to the variable 'deriv[]'. The value of 'deriv[i]' represents the derivative of each function with respect to the i-th parameter of the membership function. The description of the derivative function allows to compute the system error derivative used by gradient descent-based learning algorithms. The format is:

		derivative { subblocks }                       

The block update is used to compute a valid set of parameter values (stored in the variable pos[]) from a tainting displacement (stored in the variable disp[]) generated in an automatic tuning process, taking into account which of the parameters are intended to be modified (stored in the boolean variable adj[]). A very common constraint in the displacement is to maintain the order of the parameters. The preprogrammed function sortedUpdate(pos,disp,adj) can be invoked to compute this restricted displacement. The Java code can also use the variables min', 'max' and 'step', which represent respectively the minimum, maximum and division of the universe of discourse. The syntax of the block update is:

		update { Java_function_body }                      

The block source is used to define Java code that is directly included in the class code generated for the function definition. This code allows to define local methods that can be used into other blocks. The structure is:

		source { Java_code }                      

The following example shows the definition of the membership function triangle.

 mf triangle {
   parameter a, b, c;
   requires { a<b && b<c && b>=min && b<=max }
   java {
    equal { return (a<x && x<=b? (x-a)/(b-a) : (b<x && x<c? (c-x)/(c-b) : 0)); }
    greatereq { return (x<a? 0 : (x>b? 1 : (x-a)/(b-a) )); }
    smallereq { return (x<b? 1 : (x>c? 0 : (c-x)/(c-b) )); }
    center { return b; }
    basis { return (c-a); }
   }
   ansi_c {
    equal { return (a<x && x<=b? (x-a)/(b-a) : (b<x && x<c? (c-x)/(c-b) : 0)); }
    greatereq { return (x<a? 0 : (x>b? 1 : (x-a)/(b-a) )); }
    smallereq { return (x<b? 1 : (x>c? 0 : (c-x)/(c-b) )); }
    center { return b; }
    basis { return (c-a); }
   }
   cplusplus {
    equal { return (a<x && x<=b? (x-a)/(b-a) : (b<x && x<c? (c-x)/(c-b) : 0)); }
    greatereq { return (x<a? 0 : (x>b? 1 : (x-a)/(b-a) )); }
    smallereq { return (x<b? 1 : (x>c? 0 : (c-x)/(c-b) )); }
    center { return b; }
    basis { return (c-a); }
   }
   derivative {
    equal {
     deriv[0] = (a<x && x<b ? (x-b)/((b-a)*(b-a)) : (x==a? 0.5/(a-b) : 0));
     deriv[1] = (a<x && x<b ? (a-x)/((b-a)*(b-a)) :
                (b<x && x<c ? (c-x)/((c-b)*(c-b)) :
                (x==b? 0.5/(a-b) + 0.5/(c-b) : 0)));
     deriv[2] = (b<x && x<c ? (x-b)/((c-b)*(c-b)) : (x==c? 0.5/(c-b) : 0));
    }
    greatereq {
     deriv[0] = (a<x && x<b ? (x-b)/((b-a)*(b-a)) : (x==a? 0.5/(a-b) : 0));
     deriv[1] = (a<x && x<b ? (a-x)/((b-a)*(b-a)) : (x==b? 0.5/(a-b) : 0));
     deriv[2] = 0;
    }
    smallereq {
     deriv[0] = 0;
     deriv[1] = (b<x && x<c ? (c-x)/((c-b)*(c-b)) : (x==b? 0.5/(c-b) : 0));
     deriv[2] = (b<x && x<c ? (x-b)/((c-b)*(c-b)) : (x==c? 0.5/(c-b) : 0));
    }
    center {
     deriv[0] = 1;
     deriv[1] = 1;
     deriv[2] = 1;
    }
    basis {
     deriv[0] = -1;
     deriv[1] = 0;
     deriv[2] = 1;
    }
   }
   update {
    pos = sortedUpdate(pos,desp,adj);
    if(pos[1]<min) pos[1]=min;
    if(pos[2]<=pos[1]) pos[2] = pos[1]+step;
    if(pos[1]>max) pos[1]=max;
    if(pos[0]>=pos[1]) pos[0] = pos[1]-step;
   }
  }

For comments, patches, bug reports, etc contact us at:   xfuzzy-team@imse-cnm.csic.es

©IMSE-CNM 2018