New Features, Changes and Helpful Hints

This section describes new features that have been added as well as changes or fixes that have been made to FuzzyJ. It also provides some helpful hints about how to use the Toolkit (beyond what is covered in the basic parts of the User Guide).

Modifications

           Version 1.7 Modifications

                      New Rule Executor TsukamotoRuleExecutor

                      Added method getXForMembership in FuzzySet and FuzzyValue (and new exception)

           Version 1.6 Modifications

                      Fuzzy Set Plotting Errors

                      New FuzzySet types GaussianFuzzySet, LeftGaussianFuzzySet and RightGaussianFuzzySet added

Version 1.5a Modifications

                      Changes to Combining Fuzzy Match Scores When Multiple Fuzzy Antecedents

Version 1.5 Modifications

           New Defuzzification  Methods for FuzzyValueVector Class

           Combining Fuzzy Match Scores When Multiple Fuzzy Antecedents

           FuzzySets Can Have Membership Values Larger Than 1

fuzzySum Operation for FuzzyValues/FuzzySets

New FuzzyJess Functions

FuzzySet Method simplifySet Fixed

Version 1.4 Modifications

           FuzzyVariable

           TriangleFuzzySet

Version 1.3 Modifications

           SingletonFuzzySet

           LeftLinearFuzzySet and RightLinearFuzzySet

                      WeightedAverageDefuzzify

                      Problems fixed

 

Programming Helpers

           Fuzzifying Crisp Values

           Implementing Takagi-Sugeno-Kang type rules

                  Implementing Kosko’s SAM (Standard Additive Method)

           Implementing Tsukamoto type rules

Version 1.7 Modifications

New Rule Executor TsukamotoRuleExecutor - Added a special RuleExecutor (like MamdaniMinMaxMinRule Executor and LarsenProductMaxMinRuleExecutor) to implement the Tsukamoto type rules. In this case the conclusion fuzzy values are always expected to have strictly increasing or strictly decreasing functions fuzzy sets that cover all membership values from 0.0 to 1.0.  When the rule fires the outputs are fuzzy sets that have a single value (singletons) with the membership value equal to the degree of match of the antecedents (or the DOF, Degree of Fulfillment of the rule). For Details see Implementing Tsukamoto Rules.

Method getXForMembership for FuzzyValues &FuzzySets  – Added a method that when given a membership value returns the first X value that has that membership value. This is most useful with FuzzySets that are strictly increasing or strictly decreasing and cover all membership values (like SFuzzySet, ZFuzzySet, LeftLinearFuzzySet, RightLinearFuzzySet, etc.). Consider the following examples:


 


X

 
Version 1.6 Modifications

Fixed Fuzzy Set Plotting errors – Some minor problems with the plots of fuzzy sets were fixed. The plotted points were sometimes missing (at the right end of the plot) or too far to the left.

New FuzzySet types GaussianFuzzySet, LeftGaussianFuzzySet and RightGaussianFuzzySet  – Added new fuzzy sets that have a Gaussian distribution shape. For details see the FuzzyJ API. These are similar to the PI, S, and Z fuzzy sets but may be more useful in some situations.

Version 1.5a Modifications

Change to Classes for Combining Fuzzy Match Scores When Multiple Fuzzy Antecedents – In version 1.5 the classes added to do the combining of match score when there were multiple fuzzy values in the antecedents were not implemented as well as they should have been. The implementation required that each AntecedentCombineOperator provide an execute method that took two doubles and returned the result of the operator on these two arguments. However, performing the operator pair wise on the match values severely restricts the type of operators that one can use. It has been changed so that the execute method receives the entire list of match scores as an array instead of pairs of values. This allows for more flexibility in the type of operators that can be implemented. To demonstrate the point, a new class, CompensatoryAddAntecedentCombineOperator, has been included in version 1.5a. This implements an operator that can give a value that will be greater than the minimum of the values and will always be greater than or equal to the product of the values. In some cases this may be a better choice. For example, if two of three match scores are 1.0 and the third is 0.1. Then in some situations it might be more acceptable to use a value somewhere between 0.1 and 1 as the combining value. The compensatory add operation is described in Fuzzy Set Theory and Its Application by Zimmermann (Kluwer Academic Publishers, 1990). The equation for the compensatory add is shown below.

where xi are the m match values and g is a parameter that controls the compensation factor for the calculation. If g is 0 then this reduces to the product of the match values. The default value of g is 0.562, which is supposed to give reasonable and expected (intuitive?) results. Again this depends on the application and what is suitable. With the previous (rather poor) implementation this type of operator could not have been implemented. Note that when a CompensatoryAddAntecedentCombineOperator object is created one can specify the g value (or one can use a setGamma method on the object).

Version 1.5 Modifications

New Defuzzification  Methods for FuzzyValueVector Class – Previously one could not do Defuzzification on a FuzzyValueVector object. Now all of the defuzzification strategies can be applied to a FuzzyValueVector. The details for these methods can be found in the FuzzyJ API but we’ll describe them here briefly. In all cases the FuzzyValues in the FuzzyValueVector must have the same FuzzyVariable. The motivation for this was to allow more flexibility in performing Global Contribution for the outputs of FuzzyRules. Rather than doing a union (or sum or other operation) as the rules fire, one can store the individual results in FuzzyValueVectors and decide how to combine them after all of the rules have fired. The weightedAverageDefuzzify method uses all of the x-values in all of the FuzzyValues in the vector to perform its calculation. This is a different than one would obtain by doing a fuzzy union of the outputs and then a weightedAverageDefuzzify on the single FuzzyValue. In particular if the outputs were all singletons and some of the singleton outputs were at the same x value (with perhaps different membership values) then the extra weighting of the singletons at the same value would be lost since the union operation would just record one membership value at that x position (the maximum). In the FuzzyValueVector, the defuzzification would use both membership values at the same x position giving more weight to this x position in the calculation. The question remains, is this a good thing to do? Well it depends on your needs and this provides the flexibility to achieve the desired outcome. For the maximumDefuzzify method we calculate the mean of the x values with maximum membership values over the entire set of FuzzyValues. Similar comments can be made as for the weightedAverageDefuzzify. In the case of momentDefuzzify, the moments and areas for each are of each FuzzyValue is used to calculate the defuzzified value. This means that the overlapping areas if the individual FuzzyValues contribute more than they would have if the FuzzyValues were combined first using a union operation. Again, in some instance this is the desired method of defuzzification. One can get an identical result to the momentDefuzzify on a FuzzyValueVector by doing Global Contribution of the output values with a fuzzy sum operation (rather than the default union). Then a momentDefuzzify on the resultant ‘summed’ FuzzyValue would give the same result. This is common in methods like Kosko’s SAM method (Standard Additive Method).  The bottom line here is the increase in flexibility in how one collects the results of multiple rules that fire and how the results can be defuzzified.

New Classes to Control the Operation Used to Combine Fuzzy Match Scores When Multiple Fuzzy Antecedents – Several Classes have been added to provide a general way to combine the match scores of multiple fuzzy antecedents and their corresponding fuzzy inputs. Prior to this release there was only one choice – the minimum of the match scores was used. Some techniques, such as Kosko’s SAM method (Standard Additive Method) require that the combining of these fuzzy match scores be done by multiplying the individual scores. So an interface, AntecedentCombineOperatorInterface, an abstract class, AntecedentCombineOperator, that implements the interface and two extensions of the abstract class, MinimumAntecedentCombineOperatorInterface and ProductAntecedentCombineOperator were created to provide two ways to perform this combining of the scores. By extending the abstract class other operators could also be defined if needed. At the same time the FuzzyRule class was modified to allow it to maintain a default antecedent combine operator (that is used when a rule is created without specifying a particular operator) and a particular operator for each rule. This is described in the chapter on FuzzyRules and in the chapter on FuzzyJess.

FuzzySets Can Have Membership Values Larger Than 1 – It has always been true, although not necessarily documented, that FuzzySets could have membership values greater than 1. However, the documentation has been updated to reflect this and the methods that deal with this have been made consistent or have modified to do an ‘appropriate’ thing when they encounter FuzzySets with membership values greater than 1. Normally, FuzzySets will not have values exceeding 1 but in certain cases it can happen and it needs to be allowed. Users can create FuzzySets to specifically hold such values (using insertSetPoint or appendSetPoint). They are responsible for the use and care of such FuzzySets and must know what will happen as the operate on them. The new fuzzy operation fuzzySum allows one to add FuzzySets (this is described below) and in this case FuzzySets with membership values greater than 1 may be created. This is especially useful for dong global contribution of fuzzy outputs of rules (needed for Kosko’s SAM method). It must be stressed that the user must be careful when creating FuzzySets with membership values greater than 1.

fuzzySum Operation for FuzzyValues/FuzzySets – Two FuzzyValues can now be added together using a fuzzySum method. The result is a FuzzyValue with a FuzzySet whose membership value at any x position is the sum of the membership values at the corresponding x position of the individual FuzzySets. See the description in the FuzzyJ API for FuzzyValues.


 


New FuzzyJess Functions – Six new functions were added. They can all be done using calls to Java functions but these functions might make it simpler to perform the actions. The functions are:

(set-fuzzy-global-contribution-operator operator)

(get-fuzzy-global-contribution-operator)

(set-default-fuzzy-rule-executor executor)

(get-default-fuzzy-rule-executor)

(set-default-antecedent-combine-operator operator)

(get-default-antecedent-combine-operator)

For details see the chapter on FuzzyJess.

FuzzySet Method simplifySet Fixed – This would not be noticed by most users but there was a minor problem with the way FuzzySets were being simplified to remove unnecessary points.

 

Version 1.4 Modifications

FuzzyVariableThis class was extended by adding 4 new methods to access and remove fuzzy terms. The new methods are:

           findTerms() – returns an enumeration with the set of FuzzyValues that represent the terms of the FuzzyVariable

           findTermNames() – returns an enumeration with the set of String names of the terms of the FuzzyVariable

           removeTerm( String term ) – removes a specified term from the set of terms of the FuzzyVariable

           removeTerms() – removes a all terms from the set of terms of the FuzzyVariable

 

TriangleFuzzySet – A constructor with 2 arguments has been in the code since the beginning but for some reason was not public so it was redefined to be public. The constructor  arguments are the center x value of the triangle and the full width of the base of the triangle. So a triangle fuzzy set constructed with the parameters 3.0 and 2.0 would create a fuzzy set identical to one created by specifying the 3 points (2.0, 0.0), (3.0, 1.0) and (4.0, 0.0).

Version 1.3 Modifications

SingletonFuzzySet  This class is used to build specialized FuzzySets that have a single value with membership value of 1.0. Note that such a FuzzySet requires 3 points in it's definition:

 

e.g. (x,0) (x,1) (x,0)

 

The diagram below shows a SingletonFuzzySet.

 

 

The Constructors have been defined to make the generation of such curves as simple as possible. Only 1 point is required to define the singleton shape. This is a specialization of the TriangleFuzzySet where the left, middle and right x values are the same. A common use for such FuzzySets is in the creation of Takagi-Sugeno-Kang type rules where the consequents of the rules are singleton values (or expressions that result in a single value). See the section on Takagi-Sugeno-Kang rules below.

 

LeftLinearFuzzySet and RightLinearFuzzySet – These fuzzy sets have been added to make is easier to create fuzzy sets similar to the SFuzzySet and ZFuzzySet with straight lines rather than curved lines between the 0 and 1 values in the set. They are shown below.

 

RightLinearFuzzySet

 

LeftLinearFuzzySet

 

 

WeightedAverageDefuzzify – This is a new method defined for FuzzyValues that calculates the weighted average of the values of a fuzzy set as the defuzzification value. This is slightly different than the maximumDefuzzify since maximumDefuzzify uses only points that have the same membership value (the one that is the maximum in the set of points). The weightedAverageDefuzzify uses all of the points with non-zero membership values and calculates the weighted average of these x values using the membership values as weights in this average.

This doesn't always work well because there can be x ranges where the y value is constant at the max value and other places where the max is only reached for a single x value. When this happens the single value gets too much of a say in determining the defuzzified value. So use moment defuzzify in cases like this.

 

             /------\                   /\

            /        \                 /  \

         --/          \---------------/    \-------------

                 ^       ^

                 |       |

                 |       | gives this as the weighted average

                 | this is more reasonable?

 

 

However, it is especially effective if the output has a number of singleton points in it. This might be, for example, when one has only singleton values describing the output fuzzy values (Takagi-Sugeno-Kang zero order type rules). In this case one gets a result that is expected and one that results in an exception with the momentDefuzzify (since the area is 0) and a poor result with the maximumDefuzzify (since only the values with the max membership are used; maximumDefuzzify would yield a result of 20 in the example below).

 

 

      1.0                 |

                          |

      0.5        |        |

                 |        |        |

         --------|--------|--------|--------

         0      10        20       30      40

                        ^

                        |

                        | gives 18.57 as the weighted average  

 

      (10*0.5 + 20*1 + 30*0.25) / (0.5 + 1 + 0.25) = 18.57

 

Fixed problem with parsing linguistic expressions in multi-threaded systems – The classes responsible for parsing linguistic expressions (“very hot or cold”) were using static variables to store information. This was inappropriate when in a multi-threaded system. The static variables were replaced with non-static variables.

Fixed/recognized a  problem related to Jess shadow facts that have fuzzy values in a slot – In Jess when a fact is asserted that is ‘identical’ to an existing fact is asserted nothing happens since duplicate facts are not allowed. In FuzzyJess where slots can have FuzzyValues facts are considered to be ‘identical’ when all of the non-fuzzy (crisp) slots are the same (equal) and when the fuzzy values have the same FuzzyVariable. For example, if a fact is created by the assert

           (assert (fan (ID fan1) (speed (new FuzzyValue ?*speedFuzzyVar* “slow”))))

and later another assert

           (assert (fan (ID fan1) (speed (new FuzzyValue ?*speedFuzzyVar* “medium”))))

is executed, then the 2 facts are considered to be ‘identical’. If these were ‘identical’ non-fuzzy facts, then the second assert would have no effect since the fact already exists. For fuzzy facts these 2 facts are combined (global contribution) such that the crisp values are the same and the fuzzy values are merged using a union operation. So in effect the old (initial) fact is deleted and the new combined fact is asserted (similar to a fact modify). This however, presents 2 problems when using shadow facts, facts created from Java Bean classes in Jess. The first issue is that for a Java Bean to cause an update to a shadow fact it uses the firePropertyChange method:

           m_pcs.firePropertyChange("beanAttribute",

                                oldAttributeValue,

                                newAttributeValue);

 

In this case if the old and new values are ‘equal’ then the slot in the shadow fact is not updated. In the case of FuzzyValue attributes (slots) the values are ‘equal’ when the FuzzyValues share the same FuzzyVariable, even if the fuzzy sets for the FuzzyValues are different. This means that the slot will not be updated and the slot values of the fuzzy slot will not be combined as required. The solution here is to use:

 

           m_pcs.firePropertyChange("beanAttribute",

                                null,

                                newAttributeValue);

and do a test of the values using equalsStar for the FuzzyValues before calling the firePropertyChange method if desired. This will ensure that the slot is updated. Well, actually it won’t in version 6.1a2 (or earlier) of Jess since Jess internally also checks for the equality of the slots and will not replace the slot with the new one if they are ‘equal’. This required a change to the Jess code so that it does not block the update of the slot. So the requirement is to use Jess 6.1a3 or later.

Programming Helpers

Fuzzifying crisp values – One of the steps that is normally required when implementing a fuzzy system is to fuzzify a crisp value so that it can be compared to a fuzzy value in the antecedents (RHS) of a fuzzy rule. This is commonly done using a TriangleFuzzySet or a SingletonFuzzySet. The TriangleFuzzySet allows on to encode the inaccuracy of a crisp value. For example if reading a temperature the temperature sensor is usually accurate within some precision, say 0.05 Degrees. So we might encode the crisp value using:

           new TriangleFuzzySet(x-.05, x, x+0.05)

However, FuzzyValues have a Universe of Discourse (UOD), that is the range of allowed values. If in the above example the x value is closer than 0.05 to either end of this UOD range then we will get an exception (out of range). This would mean it is necessary to do a lot of checking to make sure that this does not happen or catch the exception and treat it differently. A feature of FuzzyJ that may not be widely known allows us to deal with this in a fairly simple way. For a FuzzyValue one can use the static method setConfineFuzzySetsToUOD.

           FuzzyValue.setConfineFuzzySetsToUOD(true);

Once set to true this confines all FuzzySets to the x boundaries specified by the Universe of Discourse. This is achieved by truncating the FuzzySet at the UOD boundaries. Consider the example below:

The FuzzySet on the left is a depiction of the set before being confined to the UOD (Universe of Discourse), and the FuzzySet to the right is the same set after being confined. Essentially, the set to the right is the same FuzzySet; however, all points outside the UOD now have a membership value of zero. Note that this is in fact equivalent to doing an intersection between the given FuzzySet and the RectangleFuzzySet(lowXBound, highXBound), but this is considerably more efficient.

One should be careful about setting this to true for all time since you may miss important exceptions. When fuzzifying crisp values it might be best to do something like:

FuzzyValue.setConfineFuzzySetsToUOD(true);
FuzzyValue fv = new FuzzyValue(myFuzzyVar, TriangleFuzzySet(x-.05, x, x+0.05));
FuzzyValue.setConfineFuzzySetsToUOD(false);

Implementing Takagi-Sugeno-Kang (TSK) type rules with FuzzyJ and FuzzyJessA TSK type rule is different from the rules we have considered in the rest of this user guide. In general the fuzzy rules have had a set of fuzzy inputs and a set of fuzzy outputs. However, TSK rules have fuzzy inputs but they have specialized crisp outputs that are generally either constants (zero order TSK rules) or crisp outputs that are defined by a function that computes a crisp value (usually a function of the crisp values of the input variable). For example we might have:

           If pressure is low and temperature is medium then valve opening is 0.7   

This is a zero order TSK. We might also a rule something like:

           If pressure is low and temperature is medium then valve opening is 5*p + 3*t   

where p is the current input pressure and t is the current input temperature (crisp values). Typically we’ll have a set of rules.

If X is X1 and Y is Y1 then z = f1(x,y)
If X is X2 and Y is Y2 then z = f2(x,y)
...
If X is Xn and Y is Yn then z = fn(x,y)

Where x and y are the current crisp values of X and Y. Each of the outputs is calculated and the result is a weighted average of the outputs, with the weights (wi) being the degree of matching of the LHS of the rules. So the final crisp value of this set of rules is:

      (w1*f1(x,y) + w2*f2(x,y) + … + wn*fn(x,y)) / (w1 + w2 + … + wn)

This is easily implemented in FuzzyJ and FuzzyJess using singleton fuzzy values and the weighted average defuzzify method. In FuzzyJess we might have rules that look like:

      (defrule tempCold-pressureHot

            (temperature ?t&:(fuzzy-match ?t “cold”))

            (pressure ?p&:(fuzzy-match ?p “hot”))

       =>

            (assert (valve-opening (new FuzzyValue ?*valveFV*

(new SingletonFuzzyValue (+ (* 3 ?*t*) (* 5 ?*p*))))

)

      )

 

where ?*valveFV* is the FuzzyVariable for the valve setting and ?*t* and ?*p* hold the current values of the temperature and pressure in crisp form. The output of this rule is a singleton fuzzy value with a fuzzy set that has a non-zero value only at the x position

 (+ (* 3 ?*t*) (* 5 ?*p*))))

 

and a membership value that is the degree of matching for the fuzzy inputs of the rule. Each of the rules will provide a singleton output and the final output value will be an aggregate these singleton values into a FuzzyValue with multiple singleton values each of a (potentially) different height. By using the weightedAverageDefuzzify method on the aggregated fuzzy output we will get the required TSK rule result.

 

In Java the same thing can be accomplished by setting the consequents of the rules just prior to firing the rules. Consider the simple example (simpleRule.java) provided with the FuzzyJ Toolkit distribution. The 4th step is to fire the rule.

 

// Step 4 (execute the rule with these inputs)

 

     // remove any inputs associated with the rule, then add the new inputs to the rule

     hotLow.removeAllInputs();

     hotLow.addInput(inputTemp);

     hotLow.addInput(inputFlow);

     // fire the rule to get a vector of FuzzyValues that represents the outputs

     FuzzyValueVector fvv = hotLow.execute();

 

We can change this so that we define the consequent (conclusion) just before we fire the rule.

 

// Step 4 (execute the rule with these inputs)

 

     // remove any inputs associated with the rule, then add the new inputs to the rule

     hotLow.removeAllInputs();

     hotLow.addInput(inputTemp);

     hotLow.addInput(inputFlow);

     // dynamically define the conclusion for the rule based on the crisp inputs

     double crispHotValveChange = 0.0;  // this could be any function, not just a constant

     double crispColdValveChange = 0.5; // this could be any function, not just a constant

     hotLow.removeAllConclusions();

     hotLow.addConclusion(new FuzzyValue(hotValveChange,

new SingletonFuzzySet(crispHotValveChange));

     hotLow.addConclusion(new FuzzyValue(coldValveChange,

new SingletonFuzzySet(crispColdValveChange));

     // fire the rule to get a vector of FuzzyValues that represents the outputs

     FuzzyValueVector fvv = hotLow.execute();

 

 

Implementing Kosko’s SAM (Standard Additive Method) – In his book, Fuzzy Engineering (see references), Bart Kosko describes a method for fuzzy rule systems that he refers to as the Standard Additive Method (SAM). This method can be implemented in FuzzyJ/FuzzyJess by using the MamdaniMinMaxMinRuleExecutor, the ProductAntecedentCombineOperator, doing Global Contribution of fuzzy outputs with the fuzzySum operation and defuzzifying the resultant FuzzyValue with the momentDefuzzify method.

 

Implementing Tsukamoto Type Rules – Tsukamoto rules use consequents that are strictly increasing or strictly decreasing functions. When a rule fires and the outputs are generated a crisp x value and a membership value are recorded. The membership value is the DOF (Degree of Fulfillment or degree of matching) of the rule. The x value is chosen by looking at the consequent fuzzy set to see which x value has that membership value. The final output of all of the rules is the weighted average of all the x values, using the membership values as the weights. In FuzzyJ we have a special RuleExecutor, TsukamotoRuleExecutor, that generates outputs that are singleton fuzzy values at the selected x value with a membership value equal to the DOF of the rule. These output fuzzy values should be combined using the fuzzySum method (rather than the default fuzzyUnion) and then defuzzified using the weightedAverageDefuzzify method. This produces the Tsukamoto inference results. In summary to implement Tsukamoto type rules:

 

1. Make sure the rules fuzzy outputs are defined using strictly increasing or strictly decreasing functions that cover all of the membership values from 0.0 to 1.0 (some example fuzzy sets that have this property are SFuzzySet, ZFuzzySet, LeftLinearFuzzySet, and RightLineraFuzzySet.

 

2. Use the fuzzySum method as the rule output combine (global contribution) operator.

 

3. Use the weightedAverageDefuzzify method to defuzzify the combined output of the rules.

 

This is shown below for a simple 2-rule situation.

 


 


Return to Table of Contents

Return to Top of Page