Exemplo n.º 1
0
        /// <summary>
        /// Apply the Minimum implication method to a membership function.
        /// </summary>
        /// <param name="inMf">membership function to implicate</param>
        /// <param name="outMf">membership function to hold the output</param>
        /// <param name="n">The antecedent to reshape the membership function with.</param>
        /// <param name="weight">The weight of the rule</param>
        public static MemberFunction ImpMin(MemberFunction inMf, double n, double weight)
        {
            MemberFunction outMf = new MemberFunction();

            outMf.Coords.Add(new double[] { inMf.Coords[0][0], inMf.Coords[0][1] * weight });

            int i;

            for (i = 1; i < inMf.Coords.Count - 1; i++)
            {
                if (inMf.Coords[i][1] > n)
                {
                    // Note: passing the indeces in backwards is fine and tested
                    outMf.Coords.Add(new double[] { inMf.getX(i, i - 1, n), n * weight });
                    break;
                }
                else
                {
                    outMf.Coords.Add(new double[] { inMf.Coords[i][0], inMf.Coords[i][1] * weight });
                }
            }
            // Now let's continue and fill in the rest (thus the i=i)
            for (int j = i; j < inMf.Coords.Count; j++)
            {
                if (inMf.Coords[j][1] < n)
                {
                    // Note: passing the ideces in backwards is fine and tested
                    outMf.Coords.Add(new double[] { inMf.getX(j, j - 1, n), n * weight });
                    outMf.Coords.Add(new double[] { inMf.Coords[j][0], inMf.Coords[j][1] * weight });
                }
            }
            return(outMf);
        }
Exemplo n.º 2
0
 /// <summary>
 /// Copy one member function into another
 /// </summary>
 /// <param name="mFunc"></param>
 public void Copy(MemberFunction mFunc)
 {
     Coords.Clear();
     foreach (double[] coord in mFunc.Coords)
     {
         Coords.Add(coord);
     }
     MaxY = mFunc.MaxY;
 }
Exemplo n.º 3
0
        /// <summary>
        /// The product Implicator
        /// Apply the Product implication method to a membership function.
        /// </summary>
        /// <param name="inMf">membership function to implicate</param>
        /// <param name="outMf">membership function to hold the output</param>
        /// <param name="n">The antecedent to reshape the membership function with.</param>
        /// <param name="weight">The weight of the rule</param>
        public static MemberFunction ImpProduct(MemberFunction inMf, double n, double weight)
        {
            MemberFunction outMf = new MemberFunction();

            for (int i = 0; i < inMf.Coords.Count; i++)
            {
                outMf.Coords.Add(new double [] { inMf.Coords[i][0], inMf.Coords[i][1] * n * weight });
            }
            return(outMf);
        }
Exemplo n.º 4
0
        /// <summary>
        /// Generalized Implicator
        /// </summary>
        /// <param name="inMf"></param>
        /// <param name="outMf"></param>
        /// <param name="n"></param>
        /// <param name="weight"></param>
        public MemberFunction ImplicatorOp(MemberFunction inMf, double n, double weight)
        {
            switch (_implicator)
            {
            case FISImplicator.FISImp_Min:
                return(FISOperators.ImpMin(inMf, n, weight));

            case FISImplicator.FISImp_Product:
                return(FISOperators.ImpProduct(inMf, n, weight));

            default:
                throw new ArgumentException("Invalid operator");
            }
        }
Exemplo n.º 5
0
        /// <summary>
        /// Generalized Aggregator
        /// </summary>
        /// <param name="inMf"></param>
        /// <param name="outMf"></param>
        private void AggregatorOp(MemberFunction inMf, MemberFunction outMf)
        {
            switch (_aggregator)
            {
            case FISAggregator.FISAgg_Max:
                FISOperators.AggMax(inMf, outMf);
                break;

            //case FISAggregator.FISAgg_Probor:
            //    FISOperators.AggProbor(inMf, outMf);
            //    break;
            case FISAggregator.FISAgg_Sum:
            default:
                throw new ArgumentException("Invalid operator");
            }
        }
Exemplo n.º 6
0
        /// <summary>
        /// Generalized Defizzifier
        /// </summary>
        /// <param name="mf"></param>
        private double DefuzzifierOp(MemberFunction mf)
        {
            switch (_defuzzifier)
            {
            case FISDefuzzifier.FISDefuzz_Bisect:
                return(Defuzzify.DefuzzBisect(mf));

            case FISDefuzzifier.FISDefuzz_Centroid:
                return(Defuzzify.DefuzzCentroid(mf));

            case FISDefuzzifier.FISDefuzz_LargeMax:
                return(Defuzzify.FISDefuzzLargeMax(mf));

            case FISDefuzzifier.FISDefuzz_MidMax:
                return(Defuzzify.FISDefuzzMidMax(mf));

            case FISDefuzzifier.FISDefuzz_SmallMax:
                return(Defuzzify.FISDefuzzSmallMax(mf));

            default:
                throw new ArgumentException("Invalid operator");
            }
        }
Exemplo n.º 7
0
 /// <summary>
 /// Add a member function to the set.
 /// </summary>
 /// <param name="sName">The name of the member function. Cannot contain spaces</param>
 /// <param name="mf">The member function to add.</param>
 public void addMF(string sName, MemberFunction mf)
 {
     if (0 == mf.Length)
     {
         throw new ArgumentException("The membership function cannot be added to the set because it has no vertices.");
     }
     else if ((mf.Coords[0][0] < _min) || (mf.Coords[mf.Length - 1][0] > _max))
     {
         throw new ArgumentException(string.Format("Membership function bounds ({0} {1}) do not fit in the set range ({2}) for this object.", mf.Coords[0][0], mf.Coords[mf.Length - 1][0], _min));
     }
     else if (Indices.ContainsKey(sName))
     {
         throw new ArgumentException(string.Format("The name '{0}' is already in use.", sName));
     }
     else if (sName.Contains(" "))
     {
         throw new ArgumentException(string.Format("Invalid name '{0}'. Spaces are not allowed.", sName));
     }
     else
     {
         MFunctions.Add(mf);
         Indices[sName] = MFunctions.Count - 1;
     }
 }
Exemplo n.º 8
0
        /// <summary>
        ///
        /// </summary>
        private void parseInputOutput(List <string> sLines, bool isInput)
        {
            string name     = "";
            double low      = 0;
            double high     = 0;
            int    numMfs   = 0;
            int    inputNum = 0; //starts at 1

            Dictionary <string, MemberFunction> mfs = new Dictionary <string, MemberFunction>();

            foreach (string line in sLines)
            {
                // First let's see if we can figure out what input index we have
                if (regexes[FISFileSection.INPUT].IsMatch(line))
                {
                    //[Input1] needs to be a number
                    string lineTrimmed = line.Trim();

                    if (!int.TryParse(lineTrimmed.Substring(6, lineTrimmed.Length - 7), out inputNum))
                    {
                        throw new Exception("Could not extract input/output index: " + line);
                    }
                }
                else
                {
                    string[] sLSplit = line.Split('=');
                    sLSplit[0] = sLSplit[0].ToLower();

                    // Example: Name='Depth'
                    if (sLSplit[0] == "name")
                    {
                        name = sLSplit[1].Replace("'", "");
                    }

                    // Example: Range=[0 4]
                    else if (sLSplit[0] == "range")
                    {
                        List <double> sRanges = RangeSquareBrackets(sLSplit[1]);

                        if (sRanges.Count != 2)
                        {
                            throw new Exception("Wrong number of ranges: " + line);
                        }

                        low  = sRanges[0];
                        high = sRanges[1];
                    }

                    // Example: NumMFs=4
                    else if (sLSplit[0] == "nummfs")
                    {
                        if (!int.TryParse(sLSplit[1], out numMfs))
                        {
                            throw new Exception("Could not parse number of member functions: " + line);
                        }
                    }

                    // Example: MF2='Moderate':'trapmf',[0.09 0.17 0.32 0.46]
                    else if (sLSplit[0].StartsWith("mf"))
                    {
                        int mfnum;
                        int.TryParse(sLSplit[0].Substring(2), out mfnum);
                        if (mfnum != mfs.Count + 1)
                        {
                            throw new Exception("Wrong number of memberfunctions: " + line);
                        }

                        string[] mflinesplit      = sLSplit[1].Split(',');
                        string[] mflinesplitsplit = mflinesplit[0].Split(':');
                        string   mfname           = mflinesplitsplit[0].Replace("'", "");
                        string   mftype           = mflinesplitsplit[1].Replace("'", "");

                        if (mfs.ContainsKey(mfname))
                        {
                            throw new Exception("Duplicate MF name detected: " + line);
                        }

                        List <double> vertices = RangeSquareBrackets(mflinesplit[1]);

                        switch (mftype)
                        {
                        case "trapmf":
                            if (vertices.Count != 4)
                            {
                                throw new Exception("Wrong number of vertices: " + line);
                            }
                            mfs[mfname] = new MemberFunction(vertices[0], vertices[1], vertices[2], vertices[3], 1);
                            break;

                        case "trimf":
                            if (vertices.Count != 3)
                            {
                                throw new Exception("Wrong number of vertices: " + line);
                            }
                            mfs[mfname] = new MemberFunction(vertices[0], vertices[1], vertices[2], 1);
                            break;

                        default:
                            throw new Exception("Unsupported MF type: " + line);
                        }
                    }
                }
            }

            // Now try to create a memberfunction set from all our parsed functions
            MemberFunctionSet mfSet = new MemberFunctionSet(low, high);

            foreach (KeyValuePair <string, MemberFunction> mfkvp in mfs)
            {
                mfSet.addMF(mfkvp.Key, mfkvp.Value);
            }

            if (isInput)
            {
                ruleset.setInputMFSet(inputNum - 1, name, mfSet);
            }
            else
            {
                ruleset.addOutputMFSet(name, mfSet);
            }
        }
Exemplo n.º 9
0
        /// <summary>
        /// Aggregate two membership functions using the Maximum method.
        /// </summary>
        /// <param name="inMf">One of the membership functions to aggregate.This one will not be modified.</param>
        /// <param name="outMf"> The other membership function to aggregate. This one will be modified to hold the</param>
        public static void AggMax(MemberFunction inMf, MemberFunction outMf)
        {
            if (0 == outMf.Coords.Count)
            {
                outMf.Copy(inMf);
            }
            else
            {
                // Key is X and Value is Y
                SortedDictionary <double, double> coords = new SortedDictionary <double, double>();

                foreach (double[] inMfXY in inMf.Coords)
                {
                    if (coords.ContainsKey(inMfXY[0]))
                    {
                        coords[inMfXY[0]] = Math.Max(coords[inMfXY[0]], Math.Max(inMfXY[1], outMf.fuzzify(inMfXY[0])));
                    }
                    else
                    {
                        coords[inMfXY[0]] = Math.Max(inMfXY[1], outMf.fuzzify(inMfXY[0]));
                    }
                }

                foreach (double[] outMfXY in outMf.Coords)
                {
                    if (coords.ContainsKey(outMfXY[0]))
                    {
                        coords[outMfXY[0]] = Math.Max(coords[outMfXY[0]], Math.Max(inMf.fuzzify(outMfXY[0]), outMfXY[1]));
                    }
                    else
                    {
                        coords[outMfXY[0]] = Math.Max(inMf.fuzzify(outMfXY[0]), outMfXY[1]);
                    }
                }

                // Let's empty out the MF and build it up again
                outMf.clear();

                // Now loop over every line segment in inMf and see if it intersects with any segment in outMf
                for (int i = 1; i < inMf.Coords.Count; i++)
                {
                    for (int j = 1; j < outMf.Coords.Count; j++)
                    {
                        Tuple <double, double, bool> intersect = IntersectLines(inMf.Coords[i - 1][0], inMf.Coords[i - 1][1],
                                                                                inMf.Coords[i][0], inMf.Coords[i][1], outMf.Coords[j - 1][0],
                                                                                outMf.Coords[j - 1][1], outMf.Coords[j][0], outMf.Coords[j][1]);
                        // Is there an intersection?
                        if (intersect.Item3 == true)
                        {
                            if (coords.ContainsKey(intersect.Item1))
                            {
                                coords[intersect.Item1] = Math.Max(coords[intersect.Item1], intersect.Item2);
                            }
                            else
                            {
                                coords[intersect.Item1] = intersect.Item2;
                            }
                        }
                    }
                }

                int counter = 0;
                foreach (KeyValuePair <double, double> kvp in coords)
                {
                    double x = kvp.Key;
                    // If the first value isn't zero then push a zero value onto the stack
                    if (counter == 0 && x != 0.0)
                    {
                        outMf.Coords.Add(new double[] { x, 0 });
                    }

                    outMf.Coords.Add(new double[] { x, coords[x] });

                    counter++;

                    // Push a zero onto the stack if the last value isn't zero
                    if (counter == coords.Count && coords[x] != 0.0)
                    {
                        outMf.Coords.Add(new double[] { x, 0 });
                    }
                }
            }
        }
Exemplo n.º 10
0
        /// <summary>
        /// Apply a FIS to a set of arrays.
        /// All data sets are assumed to be doubleing point. The data sets are referenced in the DoDData object
        /// with the keywords "old", "new", and "dod". ****** UPDATE *******
        /// </summary>
        /// <param name="dataArrays"></param>
        /// <param name="n"></param>
        /// <param name="checkNoData"></param>
        /// <param name="noDataValues"></param>
        /// <param name="noData"></param>
        /// <returns></returns>
        public double calculate(List <double[]> dataArrays, int n, bool checkNoData,
                                List <double> noDataValues, double noData)
        {
            List <List <double> > _fuzzyInputs = new List <List <double> >();
            MemberFunction        impMf        = new MemberFunction();
            MemberFunction        aggMf        = new MemberFunction();
            Rule   rule;
            double impValue;
            double v;

            if (checkNoData)
            {
                bool ok = true;
                for (int i = 0; i < Inputs.Count; i++)
                {
                    v = dataArrays[i][n];
                    if (v == noDataValues[i])
                    {
                        ok = false;
                        break;
                    }
                    string        inputName  = InputLookupMap.Forward[i];
                    List <double> fuzzymflst = new List <double>();
                    for (int j = 0; j < Inputs[inputName].MFunctions.Count; j++)
                    {
                        fuzzymflst.Add(Inputs[inputName].MFunctions[j].fuzzify(v));
                    }
                    _fuzzyInputs.Add(fuzzymflst);
                }
                if (ok)
                {
                    for (int r = 0; r < Rules.Count; r++)
                    {
                        rule = Rules[r];
                        // This is where the NOT calculation happens. First pick the first fuzzified value
                        impValue = _fuzzyInputs[rule.InputInd[0]][rule.MFSInd[0]];
                        // Now operate
                        for (int m = 1; m < rule.InputInd.Count; m++)
                        {
                            impValue = RuleOperator(rule, impValue, _fuzzyInputs[rule.InputInd[m]][rule.MFSInd[m]]);
                        }
                        impMf = ImplicatorOp(rule.Output, impValue, rule.Weight);
                        AggregatorOp(impMf, aggMf);
                    }
                    return(DefuzzifierOp(aggMf));
                }
                else
                {
                    return(noData);
                }
            }
            else
            {
                for (int i = 0; i < Inputs.Count; i++)
                {
                    v = dataArrays[i][n];
                    string inputName = InputLookupMap.Forward[i];
                    for (int j = 0; j < Inputs[inputName].MFunctions.Count; j++)
                    {
                        _fuzzyInputs[i][j] = Inputs[inputName].MFunctions[j].fuzzify(v);
                    }
                }
                for (int r = 0; r < Rules.Count; r++)
                {
                    rule = Rules[r];
                    // This is where the NOT calculation happens.
                    impValue = _fuzzyInputs[rule.InputInd[0]][rule.MFSInd[0]];
                    for (int m = 1; m < rule.InputInd.Count; m++)
                    {
                        impValue = RuleOperator(rule, impValue, _fuzzyInputs[rule.InputInd[m]][rule.MFSInd[m]]);
                    }
                    impMf = ImplicatorOp(rule.Output, impValue, rule.Weight);
                    AggregatorOp(impMf, aggMf);
                }
                return(DefuzzifierOp(aggMf));
            }
        }
Exemplo n.º 11
0
        /// <summary>
        /// Calculate a crisp output based on a set of inputs to this rule set.
        /// </summary>
        /// <param name="lInputs">Inputs The list of input values. These MUST be in the same order that the input variables</param>
        /// <returns></returns>
        public double calculate(List <double> lInputs, bool debug = false)
        {
            List <List <double> > _fuzzyInputs = new List <List <double> >();

            if (lInputs.Count != Inputs.Count)
            {
                return(-1);
            }

            int idx, jdx;

            for (idx = 0; idx < Inputs.Count; idx++)
            {
                string        inputName = InputLookupMap.Forward[idx];
                List <double> _fin      = new List <double>();
                for (jdx = 0; jdx < Inputs[inputName].Count; jdx++)
                {
                    _fin.Add(Inputs[inputName].MFunctions[jdx].fuzzify(lInputs[idx]));
                }
                _fuzzyInputs.Add(_fin);
            }

            if (debug == true)
            {
                Debug.WriteLine("Debug=================");
                _fuzzyInputs.ForEach(x => Debug.WriteLine(String.Format("INPUT: Fuzzy: ({0})", String.Join(", ", x))));
            }

            MemberFunction impMf = new MemberFunction();
            MemberFunction aggMf = new MemberFunction();

            // Loop over the rules and run the aggregator and implicators for each.
            for (int r = 0; r < Rules.Count; r++)
            {
                Rule   rule     = Rules[r];
                double impValue = getFuzzyVal(rule, 0, _fuzzyInputs);
                // Loop over rule items (probably same as number of inputs but not
                // if some are 0 value
                for (int i = 1; i < rule.InputInd.Count; i++)
                {
                    // For now this is "and" or "or"
                    double fuzzyInput = getFuzzyVal(rule, i, _fuzzyInputs);
                    impValue = RuleOperator(rule, impValue, fuzzyInput);
                }
                impMf = ImplicatorOp(rule.Output, impValue, rule.Weight);
                AggregatorOp(impMf, aggMf);

                if (debug == true)
                {
                    List <string> coords = new List <string>();
                    impMf.Coords.ForEach(x => coords.Add(String.Format("({0})", String.Join(", ", x))));
                    Debug.WriteLine(String.Format("IMP Coords Rule{1}: {0}", String.Join(" ", coords), r));
                }
            }

            double defuzzed = DefuzzifierOp(aggMf);

            if (debug == true)
            {
                List <string> coords = new List <string>();
                aggMf.Coords.ForEach(x => coords.Add(String.Format("({0})", String.Join(", ", x))));
                Debug.WriteLine(String.Format("Aggregated Coords: {0}", String.Join(" ", coords)));

                Debug.WriteLine(String.Format("Defuzzified: {0}", DefuzzifierOp(aggMf)));
                Debug.WriteLine("ENDDebug=================");
            }

            // The defuzzifier is where composite shape gets reduced
            // to a single number
            return(defuzzed);
        }