Exemple #1
0
 /// <summary>
 /// Получает коэффициент нечеткой переменной
 /// </summary>
 /// <param name="var">нечеткая переменная</param>
 /// <returns>Значение коэффициента</returns>
 public double GetCoefficient(FuzzyVariable var)
 {
     if (var == null)
     {
         return(_constValue);
     }
     else
     {
         return(_coeffs[var]);
     }
 }
Exemple #2
0
 /// <summary>
 /// Установить коэффициент нечеткой переменной
 /// </summary>
 /// <param name="var">Нечеткая переменная</param>
 /// <param name="coeff">Новое значение коэффициента</param>
 public void SetCoefficient(FuzzyVariable var, double coeff)
 {
     if (var == null)
     {
         _constValue = coeff;
     }
     else
     {
         _coeffs[var] = coeff;
     }
 }
Exemple #3
0
 /// <summary>
 /// Создается единственное состояние
 /// </summary>
 /// <param name="var">Лингвистическая переменная к которой привязано условие</param>
 /// <param name="term">Терм в выражении "Переменная есть терм"</param>
 /// <param name="not">Содержит ли состояние отрицание</param>
 /// <param name="type">Модификатор</param>
 /// <returns>Созданное состояние</returns>
 public FuzzyCondition CreateCondition(FuzzyVariable var, FuzzyTerm term, bool not, HedgeType type)
 {
     return(new FuzzyCondition(var, term, not, type));
 }
Exemple #4
0
 /// <summary>
 /// Создается единственное состояние
 /// </summary>
 /// <param name="var">Лингвистическая переменная к которой привязано условие</param>
 /// <param name="term">Терм в выражении "Переменная есть терм"</param>
 /// <param name="not">Содержит ли состояние отрицание</param>
 /// <returns>Созданное состояние</returns>
 public FuzzyCondition CreateCondition(FuzzyVariable var, FuzzyTerm term, bool not)
 {
     return(new FuzzyCondition(var, term, not));
 }
Exemple #5
0
        /// <summary>
        /// Генерация базы правил на основе субстратной кластеризации
        /// </summary>
        private void Genfis()
        {
            //
            // Подготовка данных для кластеризации
            //
            int len = xin.Length + 1;                       // + 1, т.к. входные данне

            double[][] x = new double[len][];               // Создаем массив данных
            for (int i = 0; i < x.Length - 1; i++)          // Перебираем массивы
            {
                x[i] = xin[i];
            }
            x[x.Length - 1] = xout;

            //
            // Кластеризация данных
            //

            SubtractClustesing subclust = new SubtractClustesing(x, Radii, SqshFactor, AcceptRatio, RejectRatio);

            subclust.SubClust();
            double[][] centers = subclust.Centers;          // Центы кластеров
            double[]   sigmas  = subclust.Sigmas;           // Радиусы кластеров

            //
            // Ращипление центров кластеров
            //

            // Формирование центров кластеров
            double[][] centersIn  = new double[centers.Length - 1][];
            double[]   centersOut = centers[centers.Length - 1];
            for (int i = 0; i < centersIn.Length; i++)
            {
                centersIn[i] = centers[i];
            }
            // Формирование радиусов кластера
            double[] sigmaIn = new double[sigmas.Length - 1];
            for (int i = 0; i < sigmaIn.Length; i++)
            {
                sigmaIn[i] = sigmas[i];
            }
            double sigmaOut = sigmas[sigmas.Length - 1];

            //
            // Формируем входные переменные
            //

            for (int i = 0; i < centersIn.Length; i++)
            {
                // Создаем переменную
                double min, max;
                MinMax(xin[i], out max, out min);
                FuzzyVariable input = new FuzzyVariable(NameInput + (i + 1).ToString(), min, max);
                // Формируем термы / функции принадлежности
                for (int j = 0; j < centersIn[i].Length; j++)
                {
                    input.Terms.Add(
                        new FuzzyTerm(
                            NameMf + (j + 1).ToString(),
                            new NormalMembershipFunction(centersIn[i][j], sigmaIn[i])
                            )
                        );
                }
                // Заносим переменную в список
                Input.Add(input);
            }

            //
            // Формирование выходных переменных
            //

            SugenoVariable output = new SugenoVariable(NameOutput);

            for (int i = 0; i < centersOut.Length; i++)
            {
                Dictionary <FuzzyVariable, double> mf = new Dictionary <FuzzyVariable, double>();
                for (int j = 0; j < centersIn.Length; j++)                      // Перебираем входные переменные
                {
                    mf.Add(InputByName(NameInput + (j + 1).ToString()), 0.0);   // По умолчанию 0,0
                }
                // Константа тоже по умолчанию 0.0
                output.Functions.Add(CreateSugenoFunction(NameMf + (i + 1).ToString(), mf, 0.0));
            }
            Output.Add(output);

            //
            // Формировние базы правил типа
            // if (input1 is mf1) and (input2 is mf1) then (output1 is mf1)
            //
            rulesText = new string[centersOut.Length];          // Текстовое представление правил
            for (int i = 0; i < centersOut.Length; i++)
            {
                StringBuilder sb = new StringBuilder();
                sb.Append("if");
                for (int j = 0; j < centersIn.Length; j++)
                {
                    sb.Append(string.Format(" ({0} is {1}) ", NameInput + (j + 1).ToString(), NameMf + (i + 1).ToString()));
                    if (j != centersIn.Length - 1)
                    {
                        sb.Append("and");
                    }
                }
                sb.Append("then");
                sb.Append(string.Format(" ({0} is {1})", NameOutput, NameMf + (i + 1).ToString()));
                rulesText[i] = sb.ToString();
                Rules.Add(ParseRule(sb.ToString()));                    // Парсим правило
            }
        }
Exemple #6
0
        /// <summary>
        /// Обучение Fis
        /// </summary>
        /// <param name="anfisTrain">Функция обучения</param>
        public void Train(anfisTrain anfisTrain = null)
        {
            //
            // Генерация Fis
            //
            Genfis();
            //
            // Обучение Fis
            //
            int    epoch = 1;
            double epochError;

            if (Rules.Count == 0)
            {
                throw new Exception("Должно быть хотя бы одно правило.");
            }

            int k = xout.Length;                            // Количество параметров обучающей выборки
            int l = (xin.Length + 1) * Rules.Count;         // (m+1)n - m - количество входных переменных n - количество правил

            Matrix C = new Matrix(l, 1);                    // Столбец весовых коэффициентов
            Matrix Y = new Matrix(k, 1);                    // Вектор столбец выходных данных

            for (int i = 0; i < k; i++)
            {
                Y[i, 0] = xout[i];
            }

            errorTrain = new double[Epochs];
            while (epoch <= Epochs)
            {
                epochError = 0.0;                           // Ошибка на i эпохе
                //
                // Формирование матрицы коэффициентов
                //
                Matrix W  = new Matrix(k, l);
                Matrix ew = new Matrix(k, Rules.Count);
                for (int i = 0; i < k; i++)
                {
                    Dictionary <FuzzyVariable, double> inputValues = new Dictionary <FuzzyVariable, double>();
                    // По количеству переменных
                    for (int j = 0; j < xin.Length; j++)
                    {
                        inputValues.Add(InputByName(NameInput + (j + 1).ToString()), xin[j][i]);
                    }
                    // Посылки правил
                    Dictionary <FuzzyVariable, Dictionary <FuzzyTerm, double> > fuzzyInput = Fuzzify(inputValues);
                    // Агрегирование подусловий
                    Dictionary <SugenoFuzzyRule, double> rulesWeight = EvaluateConditions(fuzzyInput);
                    // Заключение правил
                    double        Stau = 0.0;
                    List <double> tau  = new List <double>();
                    foreach (double _tau in rulesWeight.Values)
                    {
                        Stau += _tau;
                        tau.Add(_tau);
                    }
                    double[] b = new double[tau.Count];
                    for (int j = 0; j < b.Length; j++)
                    {
                        b[j]     = tau[j] / Stau;
                        ew[i, j] = tau[j];
                    }
                    // Формирование входных переменных
                    double[] x = new double[xin.Length + 1];        // +1, т.к. x0 = 1
                    x[0] = 1;                                       // x0 = 1
                    for (int j = 1; j < x.Length; j++)
                    {
                        x[j] = xin[j - 1][i];                       // заполняем x1, x2,...,x3
                    }
                    int columnW = 0;
                    for (int g = 0; g < b.Length; g++)              // перебираем по заключениям
                    {
                        for (int d = 0; d < x.Length; d++)          // перебираем по входным данным
                        {
                            W[i, columnW] = b[g] * x[d];            // переменожаем коэффициенты на переменные
                            columnW++;                              // увеличиваем строку на 1
                        }
                    }
                }

                Matrix Winverse = W.PInverse();     // W+ псевдоинверстная матрица

                //
                // Если псевдоинверстная матрица не найдена
                //
                bool breakTrain = false;
                for (int i = 0; i < Winverse.N; i++)
                {
                    for (int j = 0; j < Winverse.M; j++)
                    {
                        if (double.IsNaN(Winverse[i, j]))
                        {
                            breakTrain = true;
                            break;
                        }
                    }
                    if (breakTrain)
                    {
                        break;
                    }
                }
                if (breakTrain)
                {
                    break;              // Прерываем обучение
                }
                C = Winverse * Y;       // Находим коэффициенты
                //
                // Нахождение вектора фактического выхода сети
                //
                Matrix Ystrich = W * C;
                //
                // Правим коэффициенты
                //
                for (int i = 0; i < Input.Count; i++)
                {
                    FuzzyVariable fv = Input[i];                // Забираем переменную
                    for (int j = 0; j < fv.Terms.Count; j++)
                    {
                        FuzzyTerm term = fv.Terms[j];               // Выбираем j терм i входной переменной
                        //
                        // Меняем в случае если функция принадлежности колоколообразная
                        //
                        IMembershipFunction mf = term.MembershipFunction;
                        if (mf is NormalMembershipFunction)
                        {
                            NormalMembershipFunction mfterm = (NormalMembershipFunction)mf;  // Приводим тип
                            //
                            // Перебираем все переменные k - количество выходных параметров
                            //

                            for (int g = 0; g < k; g++)
                            {
                                double b     = mfterm.B;
                                double sigma = mfterm.Sigma;
                                double xa    = xin[i][g] - b;             // xin - b

                                double yyStrih = Ystrich[g, 0] - xout[g]; // y' - y
                                double p       = ew[g, j];
                                double sp      = 0.0;
                                for (int q = 0; q < Rules.Count; q++)
                                {
                                    sp += ew[g, q];
                                }
                                double pb = p / (sp / Math.Pow(sigma, 2));   // (t/summt) / sigma^2
                                //
                                // Инициализируем матрицы для нахождения c
                                //
                                Matrix x = new Matrix(1, xin.Length + 1);
                                Matrix c = new Matrix(xin.Length + 1, 1);
                                x[0, 0] = 1;                                 //x0 = 1
                                for (int q = 1; q < x.M; q++)
                                {
                                    x[0, q] = xin[q - 1][g];
                                }
                                // Заполняем коэффициенты
                                int start = j * x.M;
                                for (int q = start; q < start + x.M; q++)
                                {
                                    c[q - start, 0] = C[q, 0];
                                }

                                // Перемножаем матрици
                                double cy = ((x * c)[0] - Ystrich[g, 0]);
                                //
                                // Корректируем B
                                //

                                b -= 2 * Nu * xa * yyStrih * cy * pb;

                                //
                                // Корректируем Sigma
                                //

                                sigma -= 2 * Nu * Math.Pow(xa, 2) * yyStrih * cy * pb;
                                //
                                // Условия переобучения и недопустимости применения условий
                                //

                                if (double.IsNaN(mfterm.Sigma) || double.IsNaN(mfterm.B))
                                {
                                    continue;   // Идем на следующую итерацию
                                }
                                else
                                {
                                    mfterm.B     = b;
                                    mfterm.Sigma = sigma;
                                }
                            }
                            //
                            // Загоняем терм обратно
                            //



                            fv.Terms[j].MembershipFunction = mfterm;
                        }
                        //
                        // TODO: Настройка остальных функций принадлежности не реализовано
                        //
                    }

                    Input[i] = fv;                      // Загоняем переменную обратно
                }
                //
                // Находим ошибку выхода
                //
                epochError = 0.0;
                for (int i = 0; i < Ystrich.N; i++)
                {
                    epochError += 0.5 * Math.Pow(Ystrich[i, 0] - xout[i], 2);
                }
                errorTrain[epoch - 1] = epochError;
                anfisTrain?.Invoke(epoch, Epochs, nu, epochError);
                Nu *= NuStep;
                epoch++;
            }   // Конец эпох обучения

            //
            // Применяем параметры коэффициентов y = c0 + c1 * x1 + c2 * x2 + ... + ci * xi
            //
            SetCoefficient(C);
            //
            // Перезаписываем правила в силу архитектуры сети
            //
            Rules.Clear();
            for (int i = 0; i < rulesText.Length; i++)
            {
                Rules.Add(ParseRule(rulesText[i]));
            }

            Console.WriteLine(Rules[0].ToString());
        }
        public string PremierLeague(double x1, double x2, double x3, double x4, double x5)
        {
            //
            // Create empty fuzzy system
            //
            MamdaniFuzzySystem fsGols = new MamdaniFuzzySystem();

            //
            // Create input variables for the system
            //
            FuzzyVariable fvGamer = new FuzzyVariable("gamerLosses", -6.0, 6.0);

            fvGamer.Terms.Add(new FuzzyTerm("x1_BS", new NormalMembershipFunction(-6, 2.55)));
            fvGamer.Terms.Add(new FuzzyTerm("x1_OS", new NormalMembershipFunction(0, 2.55)));
            fvGamer.Terms.Add(new FuzzyTerm("x1_KS", new NormalMembershipFunction(6, 2.55)));
            fsGols.Input.Add(fvGamer);

            FuzzyVariable fvGameDinamics = new FuzzyVariable("gameDinamics", -15.0, 15.0);

            fvGameDinamics.Terms.Add(new FuzzyTerm("x2_SP", new NormalMembershipFunction(-15, 4.25)));
            fvGameDinamics.Terms.Add(new FuzzyTerm("x2_P", new NormalMembershipFunction(-5, 4.25)));
            fvGameDinamics.Terms.Add(new FuzzyTerm("x2_V", new NormalMembershipFunction(5, 4.25)));
            fvGameDinamics.Terms.Add(new FuzzyTerm("x2_SV", new NormalMembershipFunction(15, 4.25)));
            fsGols.Input.Add(fvGameDinamics);

            FuzzyVariable fvClassDifferences = new FuzzyVariable("classDifferences", -19.0, 19.0);

            fvClassDifferences.Terms.Add(new FuzzyTerm("x3_L", new NormalMembershipFunction(-19, 2.76)));
            fvClassDifferences.Terms.Add(new FuzzyTerm("x3_VP", new NormalMembershipFunction(-9.5, 2.76)));
            fvClassDifferences.Terms.Add(new FuzzyTerm("x3_S", new NormalMembershipFunction(0, 2.76)));
            fvClassDifferences.Terms.Add(new FuzzyTerm("x3_NP", new NormalMembershipFunction(9.5, 2.76)));
            fvClassDifferences.Terms.Add(new FuzzyTerm("x3_A", new NormalMembershipFunction(-19, 2.76)));
            fsGols.Input.Add(fvClassDifferences);

            FuzzyVariable fvFieldFactor = new FuzzyVariable("fieldFactor", -2.0, 3.0);

            fvFieldFactor.Terms.Add(new FuzzyTerm("x4_ANd", new NormalMembershipFunction(-2, 0.7)));
            fvFieldFactor.Terms.Add(new FuzzyTerm("x4_Nd", new NormalMembershipFunction(-0.33, 0.7)));
            fvFieldFactor.Terms.Add(new FuzzyTerm("x4_Pr", new NormalMembershipFunction(1.33, 0.7)));
            fvFieldFactor.Terms.Add(new FuzzyTerm("x4_APr", new NormalMembershipFunction(3, 0.7)));
            fsGols.Input.Add(fvFieldFactor);

            FuzzyVariable fvCommandMatches = new FuzzyVariable("commandMatches", -60.0, 60.0);

            fvCommandMatches.Terms.Add(new FuzzyTerm("x5_Pz", new NormalMembershipFunction(-60.0, 8.5)));
            fvCommandMatches.Terms.Add(new FuzzyTerm("x5_R", new NormalMembershipFunction(0, 8.5)));
            fvCommandMatches.Terms.Add(new FuzzyTerm("x5_Rz", new NormalMembershipFunction(60.0, 8.5)));
            fsGols.Input.Add(fvCommandMatches);

            //
            // Create output variables for the system
            //
            FuzzyVariable fvGols = new FuzzyVariable("gols", -3.0, 3.0);

            fvGols.Terms.Add(new FuzzyTerm("y_KP", new NormalMembershipFunction(-3.0, 0.64)));
            fvGols.Terms.Add(new FuzzyTerm("y_P", new NormalMembershipFunction(-0.9, 0.44)));
            fvGols.Terms.Add(new FuzzyTerm("y_N", new NormalMembershipFunction(0, 0.44)));
            fvGols.Terms.Add(new FuzzyTerm("y_V", new NormalMembershipFunction(0.9, 0.44)));
            fvGols.Terms.Add(new FuzzyTerm("y_KV", new NormalMembershipFunction(3.0, 0.64)));
            fsGols.Output.Add(fvGols);

            //
            // Create three fuzzy rules
            //
            MamdaniFuzzyRule rule11 = fsGols.ParseRule("if ((gamerLosses is x1_BS ) and (gameDinamics is x2_SV ) " +
                                                       "and (classDifferences is x3_L) and (fieldFactor is x4_APr) and (commandMatches is x5_Rz)) " +
                                                       "then gols is y_KV");

            MamdaniFuzzyRule rule12 = fsGols.ParseRule("if ((gamerLosses is x1_OS) and (gameDinamics is x2_V)" +
                                                       " and (classDifferences is x3_VP) and (fieldFactor is x4_Pr) and (commandMatches is x5_Rz)) " +
                                                       "then gols is y_KV");

            MamdaniFuzzyRule rule13 = fsGols.ParseRule("if ((gamerLosses is x1_OS) and (gameDinamics is x2_P)" +
                                                       " and (classDifferences is x3_L) and (fieldFactor is x4_Pr) and (commandMatches is x5_Rz)) " +
                                                       "then gols is y_KV");

            MamdaniFuzzyRule rule14 = fsGols.ParseRule("if ((gamerLosses is x1_BS) and (gameDinamics is x2_V) " +
                                                       "and (classDifferences is x3_VP) and (fieldFactor is x4_Pr) and (commandMatches is x5_R)) " +
                                                       "then gols is y_KV");

            MamdaniFuzzyRule rule2 = fsGols.ParseRule("if ((gamerLosses is x1_OS ) and (gameDinamics is x2_V ) " +
                                                      "and (classDifferences is x3_S) and (fieldFactor is x4_Nd) and (commandMatches is x5_Rz)) or " +
                                                      "((gamerLosses is x1_KS) and (gameDinamics is x2_P) and (classDifferences is x3_VP)" +
                                                      "and(fieldFactor is x4_Pr) and (commandMatches is x5_R)) or ((gamerLosses is x1_OS) and " +
                                                      "(gameDinamics is x2_V) and (classDifferences is x3_S) and (fieldFactor is x4_Nd) " +
                                                      "and (commandMatches is x5_Rz)) or ((gamerLosses is x1_BS) and(gameDinamics is x2_SV) " +
                                                      "and (classDifferences is x3_NP) and (fieldFactor is x4_Pr) and (commandMatches is x5_R)) " +
                                                      "then gols is y_V");

            MamdaniFuzzyRule rule3 = fsGols.ParseRule("if ((gamerLosses is x1_OS ) and (gameDinamics is x2_V ) " +
                                                      "and (classDifferences is x3_S) and (fieldFactor is x4_Nd) and (commandMatches is x5_R)) or " +
                                                      "((gamerLosses is x1_KS) and (gameDinamics is x2_SP) and (classDifferences is x3_S)" +
                                                      "and(fieldFactor is x4_Nd) and (commandMatches is x5_R)) or ((gamerLosses is x1_OS) and " +
                                                      "(gameDinamics is x2_P) and (classDifferences is x3_NP) and (fieldFactor is x4_Pr) " +
                                                      "and (commandMatches is x5_Pz)) or ((gamerLosses is x1_BS) and(gameDinamics is x2_SP) " +
                                                      "and (classDifferences is x3_VP) and (fieldFactor is x4_Nd) and (commandMatches is x5_R)) " +
                                                      "then gols is y_N");

            MamdaniFuzzyRule rule4 = fsGols.ParseRule("if ((gamerLosses is x1_BS ) and (gameDinamics is x2_P ) " +
                                                      "and (classDifferences is x3_S) and (fieldFactor is x4_ANd) and (commandMatches is x5_R)) or " +
                                                      "((gamerLosses is x1_OS) and (gameDinamics is x2_V) and (classDifferences is x3_NP)" +
                                                      "and(fieldFactor is x4_Nd) and (commandMatches is x5_Pz)) or ((gamerLosses is x1_KS) and " +
                                                      "(gameDinamics is x2_SP) and (classDifferences is x3_S) and (fieldFactor is x4_Pr) " +
                                                      "and (commandMatches is x5_Pz)) or ((gamerLosses is x1_OS) and(gameDinamics is x2_P) " +
                                                      "and (classDifferences is x3_A) and (fieldFactor is x4_Nd) and (commandMatches is x5_R)) " +
                                                      "then gols is y_P");

            MamdaniFuzzyRule rule5 = fsGols.ParseRule("if ((gamerLosses is x1_KS ) and (gameDinamics is x2_SP ) " +
                                                      "and (classDifferences is x3_A) and (fieldFactor is x4_ANd) and (commandMatches is x5_R)) or " +
                                                      "((gamerLosses is x1_OS) and (gameDinamics is x2_SP) and (classDifferences is x3_NP)" +
                                                      "and(fieldFactor is x4_Nd) and (commandMatches is x5_Pz)) or ((gamerLosses is x1_KS) and " +
                                                      "(gameDinamics is x2_P) and (classDifferences is x3_NP) and (fieldFactor is x4_ANd) " +
                                                      "and (commandMatches is x5_R)) or ((gamerLosses is x1_BS) and(gameDinamics is x2_SP) " +
                                                      "and (classDifferences is x3_NP) and (fieldFactor is x4_Nd) and (commandMatches is x5_Pz)) " +
                                                      "then gols is y_KP");

            fsGols.Rules.Add(rule11);
            fsGols.Rules.Add(rule12);
            fsGols.Rules.Add(rule13);
            fsGols.Rules.Add(rule14);
            fsGols.Rules.Add(rule2);
            fsGols.Rules.Add(rule3);
            fsGols.Rules.Add(rule4);

            //
            // Associate input values with input variables
            //
            Dictionary <FuzzyVariable, double> inputValues = new Dictionary <FuzzyVariable, double>();

            inputValues.Add(fvGamer, x1);
            inputValues.Add(fvGameDinamics, x2);
            inputValues.Add(fvClassDifferences, x3);
            inputValues.Add(fvFieldFactor, x4);
            inputValues.Add(fvCommandMatches, x5);

            //
            // Calculate result: one output value for each output variable
            //
            Dictionary <FuzzyVariable, double> result = fsGols.Calculate(inputValues);

            //
            // Get output value for the 'tips' variable
            //
            Console.WriteLine(result[fvGols].ToString("f1"));

            return(result[fvGols].ToString("f1"));
        }