The class represents a fuzzy set.

The fuzzy sets are the base for all fuzzy applications. In a classical set, the membership of a given value to the set can always be defined as true (1) or false (0). In fuzzy sets, this membership can be a value in the range [0..1], representing the imprecision existent in many real world applications.

Let us consider, for example, fuzzy sets representing some temperature. In a given application, there is the need to represent a cool and warm temperature. Like in real life, the precise point when the temperature changes from cool to warm is not easy to find, and does not makes sense. If we consider the cool around 20 degrees and warm around 30 degrees, it is not simple to find a break point. If we take the mean, we can consider values greater than or equal 25 to be warm. But we can still consider 25 a bit cool. And a bit warm at the same time. This is where fuzzy sets can help.

Fuzzy sets are often used to compose Linguistic Variables, used in Fuzzy Inference Systems.

Sample usage:

// creating 2 fuzzy sets to represent Cool and Warm TrapezoidalFunction function1 = new TrapezoidalFunction( 13, 18, 23, 28 ); FuzzySet fsCool = new FuzzySet( "Cool", function1 ); TrapezoidalFunction function2 = new TrapezoidalFunction( 23, 28, 33, 38 ); FuzzySet fsWarm = new FuzzySet( "Warm", function2 ); // show membership to the Cool set for some values Console.WriteLine( "COOL" ); for ( int i = 13; i <= 28; i++ ) Console.WriteLine( fsCool.GetMembership( i ) ); // show membership to the Warm set for some values Console.WriteLine( "WARM" ); for ( int i = 23; i <= 38; i++ ) Console.WriteLine( fsWarm.GetMembership( i ) );
Example #1
1
        // Testing basic functionality of fuzzy sets
        private void runFuzzySetTestButton_Click(object sender, EventArgs e)
        {
            ClearDataSeries();

            // create 2 fuzzy sets to represent the Cool and Warm temperatures
            FuzzySet fsCool = new FuzzySet("Cool", new TrapezoidalFunction(13, 18, 23, 28));
            FuzzySet fsWarm = new FuzzySet("Warm", new TrapezoidalFunction(23, 28, 33, 38));

            // get membership of some points to the cool fuzzy set
            double[,] coolValues = new double[20, 2];
            for (int i = 10; i < 30; i++)
            {
                coolValues[i - 10, 0] = i;
                coolValues[i - 10, 1] = fsCool.GetMembership(i);
            }

            // getting memberships of some points to the warm fuzzy set
            double[,] warmValues = new double[20, 2];
            for (int i = 20; i < 40; i++)
            {
                warmValues[i - 20, 0] = i;
                warmValues[i - 20, 1] = fsWarm.GetMembership(i);
            }

            // plot membership to a chart
            chart.UpdateDataSeries("COOL", coolValues);
            chart.UpdateDataSeries("WARM", warmValues);
        }
Example #2
0
        // Testing basic functionality of linguistic variables
        private void runLingVarTestButton_Click(object sender, EventArgs e)
        {
            ClearDataSeries();

            // create a linguistic variable to represent temperature
            LinguisticVariable lvTemperature = new LinguisticVariable("Temperature", 0, 80);

            // create the linguistic labels (fuzzy sets) that compose the temperature 
            FuzzySet fsCold = new FuzzySet("Cold", new TrapezoidalFunction(10, 15, TrapezoidalFunction.EdgeType.Right));
            FuzzySet fsCool = new FuzzySet("Cool", new TrapezoidalFunction(10, 15, 20, 25));
            FuzzySet fsWarm = new FuzzySet("Warm", new TrapezoidalFunction(20, 25, 30, 35));
            FuzzySet fsHot = new FuzzySet("Hot", new TrapezoidalFunction(30, 35, TrapezoidalFunction.EdgeType.Left));

            // adding labels to the variable
            lvTemperature.AddLabel(fsCold);
            lvTemperature.AddLabel(fsCool);
            lvTemperature.AddLabel(fsWarm);
            lvTemperature.AddLabel(fsHot);

            // get membership of some points to the cool fuzzy set
            double[][,] chartValues = new double[4][,];
            for (int i = 0; i < 4; i++)
                chartValues[i] = new double[160, 2];

            // showing the shape of the linguistic variable - the shape of its labels memberships from start to end
            int j = 0;
            for (float x = 0; x < 80; x += 0.5f, j++)
            {
                double y1 = lvTemperature.GetLabelMembership("Cold", x);
                double y2 = lvTemperature.GetLabelMembership("Cool", x);
                double y3 = lvTemperature.GetLabelMembership("Warm", x);
                double y4 = lvTemperature.GetLabelMembership("Hot", x);

                chartValues[0][j, 0] = x;
                chartValues[0][j, 1] = y1;
                chartValues[1][j, 0] = x;
                chartValues[1][j, 1] = y2;
                chartValues[2][j, 0] = x;
                chartValues[2][j, 1] = y3;
                chartValues[3][j, 0] = x;
                chartValues[3][j, 1] = y4;
            }

            // plot membership to a chart
            chart.UpdateDataSeries("COLD", chartValues[0]);
            chart.UpdateDataSeries("COOL", chartValues[1]);
            chart.UpdateDataSeries("WARM", chartValues[2]);
            chart.UpdateDataSeries("HOT", chartValues[3]);
        }
Example #3
0
        /// <summary>
        /// Adds a linguistic label to the variable.
        /// </summary>
        ///
        /// <param name="label">A <see cref="FuzzySet"/> that will be a linguistic label of the linguistic variable.</param>
        ///
        /// <remarks>Linguistic labels are fuzzy sets (<see cref="FuzzySet"/>). Each
        /// label of the variable must have a unique name. The range of the label
        /// (left and right limits) cannot be greater than
        /// the linguistic variable range (start/end).</remarks>
        ///
        /// <exception cref="NullReferenceException">The fuzzy set was not initialized.</exception>
        /// <exception cref="ArgumentException">The linguistic label name already exists in the linguistic variable.</exception>
        /// <exception cref="ArgumentException">The left limit of the fuzzy set can not be lower than the linguistic variable's starting point.</exception>
        /// <exception cref="ArgumentException">"The right limit of the fuzzy set can not be greater than the linguistic variable's ending point."</exception>
        ///
        public void AddLabel(FuzzySet label)
        {
            // checking for existing name
            if (this.labels.ContainsKey(label.Name))
            {
                throw new ArgumentException("The linguistic label name already exists in the linguistic variable.");
            }

            // checking ranges
            if (label.LeftLimit < this.start)
            {
                throw new ArgumentException("The left limit of the fuzzy set can not be lower than the linguistic variable's starting point.");
            }
            if (label.RightLimit > this.end)
            {
                throw new ArgumentException("The right limit of the fuzzy set can not be greater than the linguistic variable's ending point.");
            }

            // adding label
            this.labels.Add(label.Name, label);
        }
        /// <summary>
        /// Adds a linguistic label to the variable. 
        /// </summary>
        /// 
        /// <param name="label">A <see cref="FuzzySet"/> that will be a linguistic label of the linguistic variable.</param>
        /// 
        /// <remarks>Linguistic labels are fuzzy sets (<see cref="FuzzySet"/>). Each
        /// label of the variable must have a unique name. The range of the label 
        /// (left and right limits) cannot be greater than 
        /// the linguistic variable range (start/end).</remarks>
        /// 
        /// <exception cref="NullReferenceException">The fuzzy set was not initialized.</exception>
        /// <exception cref="ArgumentException">The linguistic label name already exists in the linguistic variable.</exception>
        /// <exception cref="ArgumentException">The left limit of the fuzzy set can not be lower than the linguistic variable's starting point.</exception>
        /// <exception cref="ArgumentException">"The right limit of the fuzzy set can not be greater than the linguistic variable's ending point."</exception>
        /// 
        public void AddLabel( FuzzySet label )
        {
            // checking for existing name
            if ( this.labels.ContainsKey( label.Name ) )
                throw new ArgumentException( "The linguistic label name already exists in the linguistic variable." );

            // checking ranges
            if ( label.LeftLimit < this.start )
                throw new ArgumentException( "The left limit of the fuzzy set can not be lower than the linguistic variable's starting point." );
            if ( label.RightLimit > this.end )
                throw new ArgumentException( "The right limit of the fuzzy set can not be greater than the linguistic variable's ending point." );

            // adding label
            this.labels.Add( label.Name, label );
        }
        /// <summary>
        /// Converts the Fuzzy Rule to RPN (Reverse Polish Notation). For debug proposes, the string representation of the
        /// RPN expression can be acessed by calling <see cref="GetRPNExpression"/> method.
        /// </summary>
        ///
        private void ParseRule( )
        {
            // flag to incicate we are on consequent state
            bool consequent = false;

            // tokens like IF and THEN will be searched always in upper case
            string upRule = rule.ToUpper( );

            // the rule must start with IF, and must have a THEN somewhere
            if (!upRule.StartsWith("IF"))
            {
                throw new ArgumentException("A Fuzzy Rule must start with an IF statement.");
            }
            if (upRule.IndexOf("THEN") < 0)
            {
                throw new ArgumentException("Missing the consequent (THEN) statement.");
            }

            // building a list with all the expression (rule) string tokens
            string spacedRule = rule.Replace("(", " ( ").Replace(")", " ) ");

            // getting the tokens list
            string[] tokensList = GetRuleTokens(spacedRule);

            // stack to convert to RPN
            Stack <string> s = new Stack <string>( );
            // storing the last token
            string lastToken = "IF";
            // linguistic var read, used to build clause
            LinguisticVariable lingVar = null;

            // verifying each token
            for (int i = 0; i < tokensList.Length; i++)
            {
                // removing spaces
                string token = tokensList[i].Trim( );
                // getting upper case
                string upToken = token.ToUpper( );

                // ignoring these tokens
                if (upToken == "" || upToken == "IF")
                {
                    continue;
                }

                // if the THEN is found, the rule is now on consequent
                if (upToken == "THEN")
                {
                    lastToken  = upToken;
                    consequent = true;
                    continue;
                }

                // if we got a linguistic variable, an IS statement and a label is needed
                if (lastToken == "VAR")
                {
                    if (upToken == "IS")
                    {
                        lastToken = upToken;
                    }
                    else
                    {
                        throw new ArgumentException("An IS statement is expected after a linguistic variable.");
                    }
                }
                // if we got an IS statement, a label must follow it
                else if (lastToken == "IS")
                {
                    try
                    {
                        FuzzySet fs = lingVar.GetLabel(token);
                        Clause   c  = new Clause(lingVar, fs);
                        if (consequent)
                        {
                            output = c;
                        }
                        else
                        {
                            rpnTokenList.Add(c);
                        }
                        lastToken = "LAB";
                    }
                    catch (KeyNotFoundException)
                    {
                        throw new ArgumentException("Linguistic label " + token + " was not found on the variable " + lingVar.Name + ".");
                    }
                }
                // not VAR and not IS statement
                else
                {
                    // openning new scope
                    if (upToken == "(")
                    {
                        // if we are on consequent, only variables can be found
                        if (consequent)
                        {
                            throw new ArgumentException("Linguistic variable expected after a THEN statement.");
                        }
                        // if its a (, just push it
                        s.Push(upToken);
                        lastToken = upToken;
                    }
                    // operators
                    else if (upToken == "AND" || upToken == "OR" || unaryOperators.IndexOf(upToken) >= 0)
                    {
                        // if we are on consequent, only variables can be found
                        if (consequent)
                        {
                            throw new ArgumentException("Linguistic variable expected after a THEN statement.");
                        }

                        // pop all the higher priority operators until the stack is empty
                        while ((s.Count > 0) && (Priority(s.Peek( )) > Priority(upToken)))
                        {
                            rpnTokenList.Add(s.Pop( ));
                        }

                        // pushing the operator
                        s.Push(upToken);
                        lastToken = upToken;
                    }
                    // closing the scope
                    else if (upToken == ")")
                    {
                        // if we are on consequent, only variables can be found
                        if (consequent)
                        {
                            throw new ArgumentException("Linguistic variable expected after a THEN statement.");
                        }

                        // if there is nothing on the stack, an oppening parenthesis is missing.
                        if (s.Count == 0)
                        {
                            throw new ArgumentException("Openning parenthesis missing.");
                        }

                        // pop the tokens and copy to output until openning is found
                        while (s.Peek( ) != "(")
                        {
                            rpnTokenList.Add(s.Pop( ));
                            if (s.Count == 0)
                            {
                                throw new ArgumentException("Openning parenthesis missing.");
                            }
                        }
                        s.Pop( );

                        // saving last token...
                        lastToken = upToken;
                    }
                    // finally, the token is a variable
                    else
                    {
                        // find the variable
                        try
                        {
                            lingVar   = database.GetVariable(token);
                            lastToken = "VAR";
                        }
                        catch (KeyNotFoundException)
                        {
                            throw new ArgumentException("Linguistic variable " + token + " was not found on the database.");
                        }
                    }
                }
            }

            // popping all operators left in stack
            while (s.Count > 0)
            {
                rpnTokenList.Add(s.Pop( ));
            }
        }
Example #6
0
        // Hardcode initializing the Fuzzy Inference System
        void InitFuzzyEngine()
        {

            // Linguistic labels (fuzzy sets) that compose the distances
            FuzzySet fsNear = new FuzzySet("Near", new TrapezoidalFunction(15, 50, TrapezoidalFunction.EdgeType.Right));
            FuzzySet fsMedium = new FuzzySet("Medium", new TrapezoidalFunction(15, 50, 60, 100));
            FuzzySet fsFar = new FuzzySet("Far", new TrapezoidalFunction(60, 100, TrapezoidalFunction.EdgeType.Left));

            // Right Distance (Input)
            LinguisticVariable lvRight = new LinguisticVariable("RightDistance", 0, 120);
            lvRight.AddLabel(fsNear);
            lvRight.AddLabel(fsMedium);
            lvRight.AddLabel(fsFar);

            // Left Distance (Input)
            LinguisticVariable lvLeft = new LinguisticVariable("LeftDistance", 0, 120);
            lvLeft.AddLabel(fsNear);
            lvLeft.AddLabel(fsMedium);
            lvLeft.AddLabel(fsFar);

            // Front Distance (Input)
            LinguisticVariable lvFront = new LinguisticVariable("FrontalDistance", 0, 120);
            lvFront.AddLabel(fsNear);
            lvFront.AddLabel(fsMedium);
            lvFront.AddLabel(fsFar);

            // Linguistic labels (fuzzy sets) that compose the angle
            FuzzySet fsVN = new FuzzySet("VeryNegative", new TrapezoidalFunction(-40, -35, TrapezoidalFunction.EdgeType.Right));
            FuzzySet fsN = new FuzzySet("Negative", new TrapezoidalFunction(-40, -35, -25, -20));
            FuzzySet fsLN = new FuzzySet("LittleNegative", new TrapezoidalFunction(-25, -20, -10, -5));
            FuzzySet fsZero = new FuzzySet("Zero", new TrapezoidalFunction(-10, 5, 5, 10));
            FuzzySet fsLP = new FuzzySet("LittlePositive", new TrapezoidalFunction(5, 10, 20, 25));
            FuzzySet fsP = new FuzzySet("Positive", new TrapezoidalFunction(20, 25, 35, 40));
            FuzzySet fsVP = new FuzzySet("VeryPositive", new TrapezoidalFunction(35, 40, TrapezoidalFunction.EdgeType.Left));

            // Angle
            LinguisticVariable lvAngle = new LinguisticVariable("Angle", -50, 50);
            lvAngle.AddLabel(fsVN);
            lvAngle.AddLabel(fsN);
            lvAngle.AddLabel(fsLN);
            lvAngle.AddLabel(fsZero);
            lvAngle.AddLabel(fsLP);
            lvAngle.AddLabel(fsP);
            lvAngle.AddLabel(fsVP);

            // The database
            Database fuzzyDB = new Database();
            fuzzyDB.AddVariable(lvFront);
            fuzzyDB.AddVariable(lvLeft);
            fuzzyDB.AddVariable(lvRight);
            fuzzyDB.AddVariable(lvAngle);

            // Creating the inference system
            IS = new InferenceSystem(fuzzyDB, new CentroidDefuzzifier(1000));

            // Going Straight
            IS.NewRule("Rule 1", "IF FrontalDistance IS Far THEN Angle IS Zero");
            // Going Straight (if can go anywhere)
            IS.NewRule("Rule 2", "IF FrontalDistance IS Far AND RightDistance IS Far AND LeftDistance IS Far THEN Angle IS Zero");
            // Near right wall
            IS.NewRule("Rule 3", "IF RightDistance IS Near AND LeftDistance IS Not Near THEN Angle IS LittleNegative");
            // Near left wall
            IS.NewRule("Rule 4", "IF RightDistance IS Not Near AND LeftDistance IS Near THEN Angle IS LittlePositive");
            // Near front wall - room at right
            IS.NewRule("Rule 5", "IF RightDistance IS Far AND FrontalDistance IS Near THEN Angle IS Positive");
            // Near front wall - room at left
            IS.NewRule("Rule 6", "IF LeftDistance IS Far AND FrontalDistance IS Near THEN Angle IS Negative");
            // Near front wall - room at both sides - go right
            IS.NewRule("Rule 7", "IF RightDistance IS Far AND LeftDistance IS Far AND FrontalDistance IS Near THEN Angle IS Positive");
        }
Example #7
0
 /// <summary>
 /// Initializes a new instance of the <see cref="Clause"/> class.
 /// </summary>
 /// 
 /// <param name="variable">Linguistic variable of the clause. </param>
 /// 
 /// <param name="label">Label of the linguistic variable, a fuzzy set used as label into the linguistic variable.</param>
 /// 
 /// <exception cref="KeyNotFoundException">The label indicated was not found in the linguistic variable.</exception>
 /// 
 public Clause( LinguisticVariable variable, FuzzySet label )
 {
     // check if label belongs to var.
     variable.GetLabel( label.Name );
     
     // initializing attributes
     this.label    = label;
     this.variable = variable;
 }
Example #8
0
        /// <summary>
        /// Calculate the membership of a given value to a given label. Used to evaluate linguistics clauses like
        /// "X IS A", where X is a value and A is a linguistic label.
        /// </summary>
        ///
        /// <param name="labelName">Label (fuzzy set) to evaluate value's membership.</param>
        /// <param name="value">Value which label's membership will to be calculated.</param>
        ///
        /// <returns>Degree of membership [0..1] of the value to the label (fuzzy set).</returns>
        ///
        /// <exception cref="KeyNotFoundException">The label indicated in labelName was not found in the linguistic variable.</exception>
        ///
        public float GetLabelMembership(string labelName, float value)
        {
            FuzzySet fs = labels[labelName];

            return(fs.GetMembership(value));
        }