Click here to Skip to main content
15,886,857 members
Articles / Programming Languages / C#

Fuzzy Framework

Rate me:
Please Sign up or sign in to vote.
4.93/5 (107 votes)
27 Jan 2011CPOL26 min read 139.5K   12.5K   185  
In the following article, we briefly introduce Fuzzy Framework library which supports calculations based on fuzzy logic in .NET.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using FuzzyFramework.Deffuzification;
using FuzzyFramework.Dimensions;
using System.Drawing;
using FuzzyFramework.Sets;
using System.Collections.ObjectModel;

namespace FuzzyFramework.Graphics
{
    /// <summary>
    /// Provides source for a TreeView component to represent a fuzzy relation in a transparent, hierarchical way.
    /// </summary>
    public class TreeSource
    {
        private FuzzyRelation _relation;
        private Deffuzification.Defuzzification _deffuzification = null;
        private Dictionary<IDimension, System.Decimal> _inputs;
        IDimension _variableDimension;

        public static readonly Color GraphBackgroundColor = Color.White;
        public static readonly Color UnspecifiedDimensionFontColor = Color.Blue;
        public static readonly Color SpecifiedDimensionFontColor = Color.Black;
        public static readonly Color VariableDimensionFontColor = Color.Orange;
        public static readonly Color UnnamedNodeFontColor = Color.Green;
        public static readonly Color OperatorFontColor = Color.Red;


        public static readonly bool GraphSupportOnly = true;
        
        /// <summary>
        /// Creates new instance of the TreeSource for the specifed relation
        /// </summary>
        /// <param name="relation">Fuzzy relation to represent as a hierarchical list</param>
        /// <param name="inputs">Set of specified values for particular dimensions.</param>
        /// <param name="variableDimension">Dimension which should be put on the x-axis</param>
        public TreeSource(FuzzyRelation relation, Dictionary<IDimension, System.Decimal> inputs, IDimension variableDimension)
        {
            _relation = relation;
            _inputs = inputs;
            _variableDimension = variableDimension;
        }

        /// <summary>
        /// Creates new instance of the TreeSource for the specifed relation
        /// </summary>
        /// <param name="deffuzification">Relation wrapped in a deffuzification. In this case, the hierarchy will also contain information about applied deffuzification.</param>
        public TreeSource(Defuzzification deffuzification)
        {
            _relation = deffuzification.Relation;
            _deffuzification = deffuzification;
            _inputs = deffuzification.Inputs;
            _variableDimension = deffuzification.OutputDimension;
        }
        
        /// <summary>
        /// Fills in the specified System.Windows.Forms.TreeView component with content representing the fuzzy relation
        /// </summary>
        /// <param name="treeView">Treeview component to display the relation's hierararchy</param>
        /// <param name="pictureBox">PictureBox component to display grapfs for particular nodes, where possible</param>
        /// <param name="label">Label to display caption for the picture</param>
        public void BuildTree ( TreeView treeView, PictureBox pictureBox, Label label)
        {
            ImageList imageList = new ImageList();
            imageList.Images.Add("dimensions", Resources.Graph);
            imageList.Images.Add("function", Resources.Function);
            imageList.Images.Add("subrelations", Resources.Function);
            imageList.Images.Add("fuzzySet", Resources.Function);
            imageList.Images.Add("nodeFuzzyRelation", Resources.Function);
            imageList.Images.Add("dimensionType", Resources.Function);
            imageList.Images.Add("dimensionDiscreteKnown", Resources.Function);
            imageList.Images.Add("dimensionDiscreteUnknown", Resources.Function);
            imageList.Images.Add("dimensionContinuousKnown", Resources.Function);
            imageList.Images.Add("dimensionContinuousUnknown", Resources.Function);

 
            RelationImage img = new RelationImage(_relation, _inputs, _variableDimension);
            img.SupportOnly = true;

            Bitmap bmp = new Bitmap(300, 200);
            imageList.Images.Add(bmp);

            treeView.ImageList = imageList;
            pictureBox.BackColor = GraphBackgroundColor;
            pictureBox.Image = null;
            label.Text = "";
            
            treeView.BeginUpdate();
            treeView.Nodes.Clear();

            buildSubTree(_relation, treeView.Nodes, pictureBox, label);

            treeView.EndUpdate();
        }

        /// <summary>
        /// Method to be invoked recursively to build the whole tree
        /// </summary>
        /// <param name="nodeCollection"></param>
        /// <param name="pictureBox"></param>
        /// <param name="label"></param>
        protected void buildSubTree(FuzzyRelation subrelation, TreeNodeCollection nodeCollection, PictureBox pictureBox, Label label)
        {
            TreeNode tnThis;

            if (subrelation is FuzzySet)
            {
                FuzzySet fs = (FuzzySet)subrelation;
                tnThis = new TreeNode();
                if (!String.IsNullOrEmpty(fs.Caption))
                {
                    tnThis.Text = fs.Caption;
                }
                else
                {
                    tnThis.Text = "Fuzzy Set";
                    tnThis.ForeColor = UnnamedNodeFontColor;
                }
                tnThis.ImageKey = "fuzzySet";
                tnThis.SelectedImageKey = "fuzzySet";

                TreeNode tnDimType = new TreeNode("Type: " + (fs.Dimensions[0] is IContinuousDimension ? "Continuous" : "Discrete"));
                tnDimType.ImageKey = "dimensionType";
                tnDimType.SelectedImageKey = "dimensionType";
                tnThis.Nodes.Add(tnDimType);
            }
            else
            {
                NodeFuzzyRelation nfr = (NodeFuzzyRelation)subrelation;
                tnThis = new TreeNode("Multidimensional Relation");
                tnThis.ForeColor = UnnamedNodeFontColor;
                tnThis.ImageKey = "nodeFuzzyRelation";
                tnThis.SelectedImageKey = "nodeFuzzyRelation";

                TreeNode tnSubrelations = new TreeNode(nfr.Operator.Caption);
                tnSubrelations.ImageKey = "subrelations";
                tnSubrelations.SelectedImageKey = "subrelations";
                tnSubrelations.ForeColor = OperatorFontColor;
                tnThis.Nodes.Add(tnSubrelations);

                //Find all operands. Several commutative operands of same type from different nested levels will be displayed together
                List<FuzzyRelation> nestedSubrelations = new List<FuzzyRelation>();
                findNestedOperands(nfr, nestedSubrelations);

                foreach(FuzzyRelation nestedSubrelation in nestedSubrelations)
                {
                    buildSubTree(nestedSubrelation, tnSubrelations.Nodes, pictureBox, label);
                }
            }

            #region Dimensions;

            TreeNode tnDimensions = new TreeNode("Dimension" + ((subrelation.Dimensions.Count() > 1) ? "s" : "") );
            tnDimensions.ImageKey = "dimensions";
            tnDimensions.SelectedImageKey = "dimensions";
            tnThis.Nodes.Add(tnDimensions);

            foreach(IDimension dimension in subrelation.Dimensions)
            {
                bool blnKnown = _inputs.ContainsKey(dimension);
                bool blnContinuous = dimension is IContinuousDimension;
                Color fontColor;

                string strDimCaption = String.IsNullOrEmpty(dimension.Name) ? "Dimension" : dimension.Name;

                if (blnKnown)
                {
                    if (blnContinuous)
                    {
                        strDimCaption += String.Format("={0:F5} {1}", _inputs[dimension], ((IContinuousDimension)dimension).Unit);
                    }
                    else
                    {
                        IDiscreteDimension discreteDim = (IDiscreteDimension)dimension;
                        if (discreteDim.DefaultSet != null)
                            strDimCaption += "=" + discreteDim.DefaultSet.GetMember(_inputs[dimension]);
                        else
                            strDimCaption += String.Format("=#{0:F0}", _inputs[dimension]);
                    }
                    fontColor = SpecifiedDimensionFontColor;
                }
                else
                    fontColor = UnspecifiedDimensionFontColor;

                if (dimension == _variableDimension)
                    fontColor = VariableDimensionFontColor;

                string imageKey = String.Format("dimension{0}{1}", blnContinuous ? "Continuous" : "Discrete", blnKnown ? "Known" : "Unknown");

                TreeNode tnDimension = new TreeNode(strDimCaption);
                tnDimension.ImageKey = imageKey;
                tnDimension.SelectedImageKey = imageKey;
                tnDimension.ForeColor = fontColor;
                addToolTip(tnDimension, dimension.Description);

                tnDimensions.Nodes.Add(tnDimension);
            }
            #endregion

            #region Function
            
            #endregion
            nodeCollection.Add(tnThis);
        }

        protected void addToolTip(TreeNode node, string text)
        {
            if (!String.IsNullOrEmpty(text))
            {
                node.ToolTipText = text;
            }
        }

        /// <summary>
        /// Several commutative operands of same type from different nested levels will be joined in a single list
        /// </summary>
        /// <param name="relation"></param>
        /// <param name="foundNestedSubrelations"></param>
        protected void findNestedOperands(NodeFuzzyRelation relation, List<FuzzyRelation> foundNestedSubrelations)
        {
            if (relation.Subrelation1 is NodeFuzzyRelation && ((NodeFuzzyRelation)relation.Subrelation1).Operator.GetType() == relation.Operator.GetType())
            {
                   findNestedOperands((NodeFuzzyRelation)relation.Subrelation1, foundNestedSubrelations);
            }
            else
            {
                foundNestedSubrelations.Add(relation.Subrelation1);
            }

            if (relation.Subrelation2 != null)
            {
                if (relation.Subrelation2 is NodeFuzzyRelation && ((NodeFuzzyRelation)relation.Subrelation2).Operator.GetType() == relation.Operator.GetType())
                {
                    findNestedOperands((NodeFuzzyRelation)relation.Subrelation2, foundNestedSubrelations);
                }
                else
                {
                    foundNestedSubrelations.Add(relation.Subrelation2);
                }
            }
        }


        /// <summary>
        /// Relation to display
        /// </summary>
        public FuzzyRelation Relation
        {
            get
            {
                return _relation;
            }
        }

        /// <summary>
        /// Deffuzification applied on the fuzzy relation. Null if no deffuzification specified.
        /// </summary>
        public Deffuzification.Defuzzification Deffuzification
        {
            get
            {
                return _deffuzification;
            }
        }
    }
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Student
Czech Republic Czech Republic
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions