Certainty Factors

This section describes a first attempt to provide some form of certainty factor (CF) capability for fuzzy rules. It is guided by the features provided in FuzzyCLIPS, a fuzzy extension to the CLIPS expert system shell. As an introduction let's take a look at some of the features of FuzzyCLIPS rules and facts that supported the calculation of certainty factors. Bear in mind at this point that it is expected that the reader has considerable understanding of rule based systems and as well has understood the fuzzy java rules of this toolkit (and hopefully the formulation of fuzzy rules in Jess as well).

(defrule rule-with-CFs
    "this is a rule with a certainty factor associated with it"
    (declare (CF 0.8)) ; rule has a CF of 0.8
    (person-age ?name ?age&:(> ?age 50))
=>
    (assert (person-weightClass ?name over-weight))
)

The above rule says that if we find a person over 50 years of age then we can expect that that person will be overweight. The certainty factor for the rule says that we have only 80% confidence that this rule is correct. Therefore the asserted fact that the person is overweight will be assigned a certainty of 0.8. This assumes that the certainty of the fact for the person's age was 1.0. However, if the fact had been asserted like:

(assert (person-age Ronald 55) CF 0.9)

This says that we were only certain of Ronald's age with a 0.9 certainty factor. In this case the fact would have been asserted as:

(person-weightClass Ronald over-weight) CF 0.72

Since we were only 0.8 certain of our rule and 0.9 certain of the age then we are 0.9 * 0.8 = 0.72 certain of the weight class for the person. Of course there are many ways to combine these certainties and FuzzyCLIPS does it this way. Ideally we would like more control over this and FuzzyCLIPS does not provide this at a simple level (one can modify the C code and change this ... it's actually not too difficult for a keen programmer).

If the rule had several patterns to be matched against facts in the rule premises (also referred to as the antecedents of the rule or the left hand side, LHS, of the rule), then the certainty for the asserted fact (on the right hand side, RHS, of the rule) would be calculated by:

CF of rule * (minimum CF of all facts that matched on the RHS of the rule)

Note that to this point all of the facts have been so-called crisp (or non-fuzzy). Let's consider a simple example with a fuzzy antecedent and a fuzzy conclusion (or asserted fact). In FuzzyCLIPS we might have:

(defrule temp-low-adjust-thermostat-up
    (temperature low)
=>
    (assert (adjust-thermostat up))
)

In this case one can easily argue that a kind of uncertainty is built into the handling of such a fuzzy rule. The input temperature fact does not have to match the (temperature low) fuzzy fact exactly. There merely needs to be a fuzzy fact for temperature (this would be the actual temperature expressed as a fuzzy set) that partially matches (overlaps) the fuzzy set of temperature low. That measure of overlap would then be used to determine the shape of the output fuzzy fact for adjusting the thermostat. An example of this can be seen in the FuzzyRules section of this documentation. Most rules that are purely fuzzy rely on this and further consideration of certainty factors on top of the fuzzy inferencing is not utilized. In FuzzyCLIPS this is possible and the rule and the fuzzy facts can have certainty factors associated with them. The calculation of certainty factors for these cases is explained in the FuzzyCLIPS documentation and will not be covered here.

There is however, and interesting and useful case that merits some consideration. This involves fuzzy antecedents and crisp conclusions.

(defrule fuzzy-crisp-rule
     (person (name ?n) (height short))
 =>
     (assert (result ?n short))
)

In this case a fuzzy concept height is short has been defined. The rule wants to recognize the people who have some degree of shortness and capture that degree of shortness somehow.  A standard rule without certainty factors would allow a person of some height that matches the short concept marginally (small overlap in the short fuzzy set and the person's fuzzified height fuzzy set) to produce the same conclusion as someone who matches the short concept quite well. In both cases the fact (result Bob short) or (result Harry short) would be produced. As you can now see these crisp facts beg for some measure attached to them that distinguishes between the two.  This is handled in FuzzyCLIPS by calculating the certainty factor for crisp facts that are asserted when there are fuzzy facts matched on the RHS of the rule in a special way. The certainty factor is based on the measure of similarity between the fuzzy antecedent and the fuzzy input that matched it. This similarity becomes the CF for the crisp fact. So in our case this means that the person whose height matches short only a bit will have a small CF while a person who matches short quite well will have a large CF. Again this is a simplified situation since we could add more fuzzy antecedents on the LHS of the rule. Then the minimum of the similarities is used. FuzzyCLIPS handles the even more complex situation of a mix of fuzzy and crisp antecedents, with the input facts having CFs assigned to them but we will not discuss this here. It is perhaps not common to operate in this manner and most difficult to determine the meaning of such calculations anyway.

So where does this leave us as far as the FuzzyJ Toolkit is concerned and FuzzyJess as well. At this point there has been no attempt to provide a complete (but complex) solution as found in FuzzyCLIPS. However, enough hooks have been provided to support the two very common uses, fuzzy antecedents with fuzzy conclusions (nothing to do here really since the fuzzy inferencing takes care of things) and fuzzy antecedents with crisp conclusions.

First let’s look at the purely Java situation and the support for FuzzyRules. Obviously the FuzzyRules execute and satisfy the fuzzy antecedent and conclusion situation. However there are some methods that can assist in writing Java programs that need to determine the measure of similarity or matching between FuzzyValues in the antecedent/input pairs of a rule (or between FuzzyValues outside of the context of rules).

similarity

Provides the similarity measure of two fuzzy values. We've seen this before.

maximumOfIntersection

Find the minimum membership values between two FuzzyValues at all x values and then find the maximum of these minimums (in effect take the intersection of the 2 FuzzyValues and find the maximum membership value of this). This is the measure of overlap or degree of matching of two fuzzy values.

The above methods can be used in many ways to achieve the same functionality as the CF calculation in FuzzyCLIPS fuzzy/crisp rules. In fact this provides two methods to calculate the certainty factor for a FuzzyRule, either similarity or degree of matching. By iterating over all of the pairs of inputs and antecedents for a rule it is easy to calculate the FuzzyCLIPS equivalent (or even calculate some other novel measure).

Consider an incomplete set of Java code for the fuzzy-crisp-rule above.

// FuzzyVariable and FuzzyRule have been defined.
// The rule may have a fuzzy conclusion but in this case has none.
// In fact one could argue for the need to even have a FuzzyRule for this
// extremely simple case!
FuzzyValueVector antecedents = fuzzyCrispRule.getAntecedents();
FuzzyValueVector inputs = fuzzyCrispRule.getInputs();
// We know there is only 1 pair here but ...
double similarity = 1.0;
for (int i=0; i<antecedents.size(); i++)
{ double localSimilarity = antecedents.fuzzyValueAt(i).similarity(inputs.fuzzyValueAt(i));
  if (localSimilarity < similarity)
     similarity = localSimilarity;
}
System.out.println("The person's height is short with degree " + similarity);

In Jess we provide two Jess User Functions to assist in doing the same thing, (fuzzy-rule-similarity) and (fuzzy-rule-match-score). A complete example in Jess code illustrates the use of the two functions. Effectively fuzzy-rule-similarity provides the same value that FuzzyCLIPS would for a fuzzy-crisp rule's CF for the crisp facts to be asserted. The other function, fuzzy-rule-match-score, is similar but uses a different measure of similarity if you like, the degree of matching between the fuzzy values.

 ;; A simple example to test a complete FuzzyJess program (no Java code at all).
 ;;
 ;; Note: future versions (beyond 5.0a5) of Jess will allow us to use --
 ;;
 ;;             (new FuzzyValue ... )
 ;;       etc.
 ;;
 ;;       will no longer always need to fully qualify the classes!
 ;;
 ;; Example as shown will give result ...
 ;;
 ;; Jack is tall with degree (similarity) 0.5363321799307958
 ;; Jack is tall with degree (match) 0.588235294117647
 ;; Randy is tall with degree (similarity) 1.0
 ;; Randy is tall with degree (match) 1.0
 ;; Ralph is tall with degree (similarity) 0.4117647058823532
 ;; Ralph is tall with degree (match) 0.49999999999999994
 

 (defglobal ?*heightFvar* = (new nrc.fuzzy.FuzzyVariable "height" 0.0 10.0 "feet"))

 (defglobal ?*rlf* = (new nrc.fuzzy.RightLinearFunction))
 (defglobal ?*llf* = (new nrc.fuzzy.LeftLinearFunction))

 (deftemplate person
    (slot name)
    (slot height)
 )

 (defrule init
    (declare (salience 100))
   =>
    (load-package nrc.fuzzy.jess.FuzzyFunctions)
    (?*heightFvar* addTerm "short"  (new nrc.fuzzy.RFuzzySet 0.0 5.0 ?*rlf*))
    (?*heightFvar* addTerm "medium" (new nrc.fuzzy.TrapezoidFuzzySet 4.0 4.8 5.5 6.0))
    (?*heightFvar* addTerm "tall"   (new nrc.fuzzy.LFuzzySet 5.5 6.0 ?*llf*))

    (assert (person (name "Ralph")
                 (height (new nrc.fuzzy.FuzzyValue ?*heightFvar*
                              (new nrc.fuzzy.PIFuzzySet 5.7 0.1)))
         )
         (person (name "Timothy")
                 (height (new nrc.fuzzy.FuzzyValue ?*heightFvar*
                              (new nrc.fuzzy.PIFuzzySet 4.0 0.1)))
         )
         (person (name "Randy")
                 (height (new nrc.fuzzy.FuzzyValue ?*heightFvar*
                              (new nrc.fuzzy.PIFuzzySet 6.5 0.1)))
         )
         (person (name "Jack")
                 (height (new nrc.fuzzy.FuzzyValue ?*heightFvar*
                              (new nrc.fuzzy.PIFuzzySet 5.75 0.1)))
         )
     )
 )

 (defrule identify-tall-people "determine strength of tallness for a person"
   (person (name ?n) (height ?ht&:(fuzzy-match ?ht "tall")))
  =>
   (printout t ?n " is tall with degree (similarity) " (fuzzy-rule-similarity) crlf)
   (printout t ?n " is tall with degree (match) " (fuzzy-rule-match-score) crlf)
 )

One might note that the use of the RightLinearFunction (LeftLinearFunction) with the RfuzzySet (LfuzzySet) could simply be replaced by the RightLinearFuzzySet (LeftLinearFuzzySet) that was added for convenience in FuzzyJ version 1.3.

In version 1.5 of FuzzyJ/FuzzyJess the two user functions have been modified to use the FuzzyRule DefaultAntecedentCombineOperator to decide how to combine the similarities (or matches) of the antecedents and the inputs. Previously a minimum was always performed. See FuzzyRules/Multiple Antecedents in a Rule to recall the details of the AntecedentCombineOperators.


This has laid a foundation for future consideration of Certainty Factors or other useful measures that can be added to the toolkit. Comments, are welcome.
 
 

Return to Table of Contents