예제 #1
0
        public async Task <ActionResult <MSE> > PostCB(MSE item)
        {
            _context.MSE.Add(item);
            await _context.SaveChangesAsync();

            return(CreatedAtAction(nameof(GetMSE), new { id = item.id }, item));
        }
예제 #2
0
            public void MSETest()
            {
                var actual   = new Matrix(4, 1);
                var expected = new Matrix(4, 1);

                actual.InRandomize();
                expected.InRandomize();

                var autoErr = new MSE().Evaluate(actual, expected);
                var error   = 0.0;

                for (var i = 0; i < actual.Rows; i++)
                {
                    for (var j = 0; j < actual.Columns; j++)
                    {
                        error += Math.Pow(expected[i, j] - actual[i, j], 2);
                    }
                }
                error /= actual.Rows * actual.Columns;
                Assert.IsTrue(Math.Abs(error - autoErr) < 0.01, new MSE().Type().ToString() + " Forward!");

                var autoDErr = new MSE().Backward(actual, expected);
                var dErr     = new Matrix(actual.Rows, actual.Columns);

                for (var i = 0; i < actual.Rows; i++)
                {
                    for (var j = 0; j < actual.Columns; j++)
                    {
                        dErr[i, j] = 2 * (actual[i, j] - expected[i, j]);
                    }
                }
                Assert.IsTrue(Math.Abs(dErr.FrobeniusNorm() - autoDErr.FrobeniusNorm()) < 0.01, new MSE().Type().ToString() + " Backward!");
            }
예제 #3
0
        private void btnloaddata_Click(object sender, RoutedEventArgs e)
        {
            DBConn dbconn = new DBConn();

            try
            {
                dbconn.DBOpen();
                MySqlCommand cmd = new MySqlCommand();
                cmd.Connection  = dbconn.myconn;
                cmd.CommandText = "SELECT * FROM member WHERE id = @id";
                cmd.Parameters.Add("@id", MySqlDbType.VarChar, 45);
                cmd.Parameters[0].Value = "5";
                MySqlDataAdapter adp = new MySqlDataAdapter(cmd);
                DataSet          ds  = new DataSet();

                adp.Fill(ds, "LoadDataBinding");
                dataGridCustomers.DataContext = ds;
            }
            catch (MySqlException MSE)
            {
                MessageBox.Show(MSE.ToString());
            }
            finally
            {
                dbconn.myconn.Close();
            }
        }
예제 #4
0
        public static Model Train(Data data, int maxNumerOfIterations)
        {
            var model = new Model {
                b = Enumerable.Repeat(10d, data.NumberOfFeatures + 1).ToArray()
            };
            var iteration = 0;
            var stepSize  = 0.01d;
            var oldError  = double.MaxValue;
            var error     = MSE.Calc(model, data);
            var threshold = 0.0001;

            while (iteration < maxNumerOfIterations && oldError - error > threshold || error > oldError)
            {
                var gradients = MSE.Gradients(model, data);
                //var stepSize = 1d / (2 + iteration);
                for (int i = 0; i < model.b.Length; i++)
                {
                    model.b[i] -= gradients[i] * stepSize;
                }
                Console.WriteLine($"iteration {iteration}, error {error}");
                Console.WriteLine($"\t Mode: [ {String.Join("| \t", model.b.Select(b => b.ToString()))} ]");
                Console.WriteLine($"\t Gradients: [ {String.Join(", ", gradients.Select(b => b.ToString()))} ]");
                oldError = error;
                error    = MSE.Calc(model, data);
                iteration++;
            }
            return(model);
        }
예제 #5
0
        private void Button_Click(object sender, RoutedEventArgs e)
        {
            DBConn dbconn = new DBConn();

            UID = this.ID.Text;
            UPW = this.PASSWD.Text;
            try
            {
                dbconn.DBOpen();
                MySqlCommand cmd = new MySqlCommand();
                cmd.Connection  = dbconn.myconn;
                cmd.CommandText = "SELECT * FROM member WHERE id = @id";
                cmd.Parameters.Add("@id", MySqlDbType.VarChar, 50);
                cmd.Parameters[0].Value = UID;
                MySqlDataAdapter adp = new MySqlDataAdapter(cmd);
                DataSet          ds  = new DataSet();

                adp.Fill(ds);

                foreach (DataRow r in ds.Tables[0].Rows)
                {
                    check = true;
                    if ((string)r["passwd"] == UPW)
                    {
                        dbconn.myconn.Close();
                        Uri uri = new Uri("mainPage.xaml", UriKind.Relative);
                        try
                        {
                            NavigationService.GetNavigationService(this).Navigate(new Uri("mainPage.xaml", UriKind.Relative));
                        }
                        catch (Exception ex)
                        {
                            MessageBox.Show(ex.ToString());
                        }
                    }
                    else
                    {
                        MessageBox.Show("비밀번호가 틀립니다.");
                    }
                }
                if (check == false)
                {
                    MessageBox.Show("아이디가 존재하지 않습니다.");
                }
                check = false;
            }
            catch (MySqlException MSE)
            {
                MessageBox.Show(MSE.ToString());
            }
            finally
            {
                dbconn.myconn.Close();
            }
        }
예제 #6
0
 private void button_ok_Click(object sender, EventArgs e)
 {
     if (isok == true)
     {
         button_ok.Enabled = false;
         button_ok.Text    = "请等待";
         MSE.MSEmake(CDB.cards, textBox_jpg.Text, comboBox_lang.Text, comboBox_style.Text);
         string str = " a -tzip " + textBox_save.Text + @" @list.txt";
         CCFile._7zip(path, textBox_jpg.Text, str);
         File.Delete(textBox_jpg.Text + "set");
         File.Delete(textBox_jpg.Text + "list.txt");
         MessageBox.Show("制作完成");
         button_ok.Text    = "开始导出";
         button_ok.Enabled = true;
     }
 }
        static void Main(string[] args)
        {
            //
            // 두께별로 계산된 MSE 를 통해
            // global minimum 일 때의 두께, MSE 값을 찾는다.
            //
            // 2021.03.26 이지원.
            //
            #region global minimum 탐색.
            MSE MyMSE = new MSE();

            double StartThickness = 700.0;
            double EndThickness   = 1300.0;
            double gap            = 5.0;

            // MSE 와 두께를 담을 배열을 선언, 초기화한다.
            double   numMSE      = (EndThickness - StartThickness) / gap + 1;
            double[] MSEs        = new double[(int)numMSE];
            double[] thicknesses = new double[(int)numMSE];

            // 두께별 MSE 를 계산해서 MSEs 배열에 저장한다.(두께 범위는 700 ~ 1300, 간격은 5)
            int idx = 0;
            for (double thickness = StartThickness; thickness <= EndThickness; thickness += gap)
            {
                thicknesses[idx] = thickness;
                MSEs[idx]        = MyMSE.returnMse(thickness);
                ++idx;
            }

            // MSEs 에서 global minimum 에서의 MSE, 두께값을 구한다.
            int    idxGlobalMinimum = 0;          // global minimum 에서의 index.
            double GlobalMinimum    = MSEs.Min(); // global minimum 값.
            int    LenData;

            // global minimum 에서의 index 를 찾는다.
            LenData = MSEs.Length;
            for (int i = 0; i < LenData; i++)
            {
                if (MSEs[i] == GlobalMinimum)
                {
                    idxGlobalMinimum = i;
                    break;
                }
            }
            WriteLine($"{thicknesses[idxGlobalMinimum]}     {MSEs[idxGlobalMinimum]}     {idxGlobalMinimum}");
            //1070     0.0016568615951739671     74

            // global minimum 에서의 두께 값.
            double globalD0  = thicknesses[idxGlobalMinimum];
            double globalMSE = MSEs[idxGlobalMinimum];

            #endregion


            //
            // 초기 두께를 다르게 하였을 때, global minimum에 수렴하도록 하는 최적화 알고리즘을 작성한다.
            // d0가 800, 1000, 1200 일때 수행시간, mse, 두께를 측정한다.
            // 2021.04.02 정지훈.
            //
            #region 두께 범위를 재설정하고 MSE를 구한다.
            double d_sol = 0.0;             // "실제" global minimum 이 되는 두께.

            // 이전 값을 가져야하는 변수에 현재 값을 초기화 해둔다.
            double preD0;                   // 이전 두께를 저장하는 변수.
            double preMSE = GlobalMinimum,  // 이전 MSE 를 저장하는 변수.
                   nowMSE = GlobalMinimum;  // 현재 MSE 를 저장하는 변수.

            // global minimum 을 찾는 시간을 측정한다.
            Stopwatch stopwatch = new Stopwatch();

            // 두께 간격, 현재 두께를 갱신한다.
            // 초기설정 두께
            double nowD0 = 1200;
            preD0 = 0;
            gap   = 0.5;

            // 이전 기울기와 현재 기울기를 저장 할 배열
            double[] gradient = new double[2] {
                0, 0
            };
            int cnt = 0;    // global minimum 을 찾기 위한 연산의 반복 횟수.

            // 초기값 설정
            double vt = 0;
            double gt = 0; //
            double mt = 0; // 아담

            // MSE를 계산하는 함수를 사용하기 위한 객체
            MSE mSE = new MSE();
            preMSE = mSE.returnMse(0);

            // 데이터 저장할 파일 열기
            StreamWriter writer;
            writer = File.CreateText(nowD0.ToString() + "nm_spectrum.dat");
            writer.WriteLine("반복횟수" + "\t" + "thickness[nm]" + "\t" + "MSE");
            // 시간 측정 시작
            stopwatch.Start();
            while (true)
            {
                ++cnt;
                WriteLine($"==== {cnt} 회차 ====");

                // 현재 두께의 mse를 구한다.
                nowMSE = mSE.returnMse(nowD0);

                // 콘솔 출력
                WriteLine($"predo : {preD0}     preMSE: {preMSE}\n" +
                          $"nowdo : {nowD0}     nowMSE: {nowMSE}\n" +
                          $"beforegradient : {gradient[0]}     gradient : {gradient[1]}\n" +
                          $"gap : {gap}     vt : {vt}");

                // 파일 출력
                writer.WriteLine($"{cnt}" + "\t" + $"{nowD0}" + "\t" + $"{nowMSE}");

                // 기울기의 부호가 바꼈는지 체크

                /*                bool a = true, b = true;
                 *              // 전의 기울기와 현재의 기울기의 부호가 다르면 a와 b를 false로 둔다.
                 *              // 기울기의 부호가 같으면 a, b 둘 중 하나만 false가 된다
                 *              _ = (gradient[0] >= 0) ? a = false : b = false;
                 *              _ = (gradient[1] >= 0) ? a = false : b = false;*/

                // 두 MSE 의 차이가 0.00001(10^-5) 이하이고 기울기의 부호가 바뀌면 while 문을 탈출한다.
                if (Abs(preMSE - nowMSE) <= 0.00001 && preD0 != nowD0)
                {
                    // global minimum 은 둘 중 작은 MSE 로 정한다.
                    GlobalMinimum = (preMSE < nowMSE) ? preMSE : nowMSE;
                    // 실제 두께는 global minimum 으로 정해진 MSE 와 짝이 되는 두께이다.
                    d_sol = (preMSE == GlobalMinimum) ? preD0 : nowD0;
                    goto Find_d_sol;
                }

                gradient[0] = gradient[1];
                // 2-2 첫번째에서 측정된 globalMSE와 현재 MSE 사이의 기울기를 측정함
                gradient[1] = (globalMSE - nowMSE) / (globalD0 - nowD0);
                preMSE      = nowMSE;
                preD0       = nowD0;

                //아담 수정
                //
                // 지수 가중평균
                // 데이터의 이동 평균을 구할 때, 오래된 데이터가 미치는 영향을 줄이는 방법
                // 사용 이유 : 손실함수의 최저점을 찾기 위해 사용
                // 지수 가중 평균의 근사식(v = 1 / (1 - beta))
                // 10 = 1 / (1 - 0.9) -> 베타가 0.9이면 10일간의 데이터를 가지고 가중 평균을 구한것
                // 1000 = (1 - 0.999) -> 베타가 0.999이면 1000일간의 데이터를 가지고 가중 평균을 구한것
                gt = gradient[0];
                mt = 0.9 * mt + (1 - 0.9) * gt;
                vt = 0.999 * vt + (1 - 0.999) * Math.Pow(gradient[0], 2);
                double mt_cap = mt / (1 - Math.Pow(0.9, cnt));
                double vt_cap = vt / (1 - Math.Pow(0.999, cnt));
                nowD0 = preD0 - (gap * mt_cap) / (Sqrt(vt_cap) + Math.Pow(10, -8));

                //베타2 = 0.999 베타1 = 0.9 알파 초깃값 = 0.001
                //gap = (0.001 * Sqrt(1-Math.Pow(0.999, cnt))) / (1- Math.Pow(0.9, cnt));
            }

Find_d_sol:
            // 콘솔 최종 데이터 출력
            WriteLine($"\n\n\n d_sol: {d_sol}    MSE: {GlobalMinimum}    idxGlobalMinimum: {idxGlobalMinimum}");
            stopwatch.Stop();
            WriteLine($"소요 시간: {stopwatch.ElapsedMilliseconds}ms");
            writer.WriteLine($"\n\n\n d_sol : {d_sol}" + "\t\t" + $"MSE_sol : {GlobalMinimum}" + "\t" + $"소요 시간 : {stopwatch.ElapsedMilliseconds}ms");

            // 파일 종료
            writer.Close();
            #endregion
        }
예제 #8
0
        private void GenerateButton_Click(object sender, RoutedEventArgs e)
        {
            InitializeFuzzySystem();

            // Make sure the selected values are compatible
            {
                bool invalid = true;

                if (fuzzySystem.Type == FuzzyType.Mamdani || fuzzySystem.Type == FuzzyType.Larsen)
                {
                    if (fuzzySystem.DefuzzMethod == DefuzzMethodType.COA || fuzzySystem.DefuzzMethod == DefuzzMethodType.COG || fuzzySystem.DefuzzMethod == DefuzzMethodType.MOM || fuzzySystem.DefuzzMethod == DefuzzMethodType.LOM || fuzzySystem.DefuzzMethod == DefuzzMethodType.SOM)
                    {
                        if (fuzzySystem.ImpMethod == ImpMethodType.min || fuzzySystem.ImpMethod == ImpMethodType.max)
                        {
                            invalid = false;
                        }
                    }
                }

                if (fuzzySystem.Type == FuzzyType.Sugeno)
                {
                    if (fuzzySystem.DefuzzMethod == DefuzzMethodType.wtaver || fuzzySystem.DefuzzMethod == DefuzzMethodType.wtsum)
                    {
                        if (fuzzySystem.ImpMethod == ImpMethodType.prod)
                        {
                            invalid = false;
                        }
                    }
                }

                if (invalid)
                {
                    MessageBox.Show("Incompatible fuzzy system type and defuzzification method.", "ERROR", MessageBoxButton.OK, MessageBoxImage.Error);
                    return;
                }
            }

            var watch = System.Diagnostics.Stopwatch.StartNew();

            List <Rule> rules = new List <Rule>();

            // Generate the rules
            if (fuzzySystem.Type == FuzzyType.Sugeno)
            {
                // Get a list of inputMF-combinations
                int ruleCount = 1;
                for (int inputId = 0; inputId < fuzzySystem.Inputs.Length; inputId++)
                {
                    ruleCount *= fuzzySystem.Inputs[inputId].NumMFs;
                }

                for (int i = 0; i < ruleCount; i++)
                {
                    rules.Add(new Rule());
                    rules[rules.Count - 1].Inputs     = new int[fuzzySystem.Inputs.Length];
                    rules[rules.Count - 1].Inputs[0]  = -1; // Uninitialized rule indicator
                    rules[rules.Count - 1].Outputs    = new int[fuzzySystem.Outputs.Length];
                    rules[rules.Count - 1].Outputs[0] = i + 1;
                }

                // Prepare outputs
                fuzzySystem.Outputs[0].NumMFs = ruleCount;
                for (int mfId = 0; mfId < fuzzySystem.Outputs[0].NumMFs; mfId++)
                {
                    fuzzySystem.Outputs[0].MFs[mfId]      = new MembershipFunction();
                    fuzzySystem.Outputs[0].MFs[mfId].Type = MFtype.constant;
                }

                Random RNG = new Random();
                for (int ruleId = 0; ruleId < rules.Count; ruleId++)
                {
                    bool newRuleFound = true;
                    do
                    {
                        for (int i = 0; i < rules[ruleId].Inputs.Length; i++)
                        {
                            rules[ruleId].Inputs[i] = RNG.Next(fuzzySystem.Inputs[i].NumMFs) + 1;
                        }
                        newRuleFound = true;
                        for (int r = 0; r < ruleId; r++)
                        {
                            if (rules[r].SameInput(rules[ruleId]))
                            {
                                newRuleFound = false;
                            }
                        }
                    }while (!newRuleFound);

                    // For each input combination we calculate their weights at each of the given coordinates

                    List <int>   itrValues = new List <int>();
                    List <float> weights   = new List <float>();

                    for (int itr = 0; itr < InputCoords[0].Count; itr++)
                    {
                        float weight = 1.0f;
                        for (int inputId = 0; inputId < fuzzySystem.NumInputs; inputId++)
                        {
                            weight = Math.Min(weight, fuzzySystem.Inputs[inputId].MFs[rules[ruleId].Inputs[inputId] - 1].GetMembershipValue(InputCoords[inputId][itr]));
                        }

                        // If both weights are >0, we store these weigths (or their min/avg) and the itr value for this combination
                        if (weight > 0.0f)
                        {
                            weights.Add(weight);
                            itrValues.Add(itr);
                        }
                    }

                    // We get the weighed average of the outputs for each combination
                    // Add a new MF to the output with this value, and set the rule to it
                    float result = 0.0f;
                    for (int i = 0; i < weights.Count; i++)
                    {
                        result += weights[i] * OutputCoords[0][itrValues[i]];
                    }
                    result /= weights.Sum();

                    fuzzySystem.Outputs[0].MFs[ruleId].Params[0] = result;
                }

                // Remove invalid rules/outputs (NaN output -> no matching input-output values were found)
                // Make new lists of the valid entries
                List <Rule> validRules = new List <Rule>();
                List <MembershipFunction> validOutputMFs = new List <MembershipFunction>();
                for (int i = 0; i < ruleCount; i++)
                {
                    if (!float.IsNaN(fuzzySystem.Outputs[0].MFs[i].Params[0]))
                    {
                        validRules.Add(rules[i]);
                        validRules[validRules.Count - 1].Outputs[0] = validRules.Count;
                        validOutputMFs.Add(fuzzySystem.Outputs[0].MFs[i]);
                    }
                }
                // Overwrite original arrays with the new ones
                rules = validRules;
                fuzzySystem.Outputs[0].NumMFs = validOutputMFs.Count;
                fuzzySystem.Outputs[0].MFs    = validOutputMFs.ToArray();
            }
            else if (fuzzySystem.Type == FuzzyType.Mamdani || fuzzySystem.Type == FuzzyType.Larsen)
            {
                // for each input-output data we have (rows in the txt)
                for (int itr = 0; itr < InputCoords[0].Count; itr++)
                {
                    // Get the value of each input's MFs at the specified points
                    List <List <float> > MFvalues = new List <List <float> >();   //MFvalues[input id][MF id]
                    // Add a list foreach ioput
                    for (int i = 0; i < fuzzySystem.NumInputs + fuzzySystem.NumOutputs; i++)
                    {
                        MFvalues.Add(new List <float>());
                    }

                    // for each input
                    for (int inputId = 0; inputId < InputCoords.Count; inputId++)
                    {
                        // for each MF
                        for (int mfID = 0; mfID < fuzzySystem.Inputs[inputId].NumMFs; mfID++)
                        {
                            // Get the membership value at the given coordinate
                            MFvalues[inputId].Add(fuzzySystem.Inputs[inputId].MFs[mfID].GetMembershipValue(InputCoords[inputId][itr]));
                        }
                    }

                    // for each output
                    for (int outputId = 0; outputId < OutputCoords.Count; outputId++)
                    {
                        // for each MF
                        for (int mfID = 0; mfID < fuzzySystem.Outputs[outputId].NumMFs; mfID++)
                        {
                            // Get the membership value at the given coordinate
                            MFvalues[fuzzySystem.NumInputs + outputId].Add(fuzzySystem.Outputs[outputId].MFs[mfID].GetMembershipValue(OutputCoords[outputId][itr]));
                        }
                    }

                    // Check if we have a NaN
                    bool hasNaN = false;
                    foreach (List <float> MFlist in MFvalues)
                    {
                        foreach (float f in MFlist)
                        {
                            if (float.IsNaN(f))
                            {
                                hasNaN = true;
                            }
                        }
                    }
                    if (hasNaN)
                    {
                        continue;
                    }

                    // Get each input's MF where the membership was the highest (randomly chosen if equal)
                    int[] highestMF = new int[fuzzySystem.NumInputs + fuzzySystem.NumOutputs];
                    for (int k = 0; k < fuzzySystem.NumInputs; k++)
                    {
                        // Find highest membership value
                        float highestVal = MFvalues[k][0];
                        for (int l = 1; l < fuzzySystem.Inputs[k].NumMFs; l++)
                        {
                            highestVal = Math.Max(MFvalues[k][l], highestVal);
                        }
                        // Find MFs that have the highest membership value we just found
                        List <int> MFsWithHighestVal = new List <int>();
                        for (int l = 0; l < fuzzySystem.Inputs[k].NumMFs; l++)
                        {
                            if (MFvalues[k][l] == highestVal)
                            {
                                MFsWithHighestVal.Add(l);
                            }
                        }
                        // Choose a random one of them
                        highestMF[k] = MFsWithHighestVal[(new Random()).Next(MFsWithHighestVal.Count)];
                    }
                    // Get each output's highest MF index
                    for (int k = 0; k < fuzzySystem.NumOutputs; k++)
                    {
                        // Find highest membership value
                        float highestVal = MFvalues[fuzzySystem.NumInputs + k][0];
                        for (int l = 1; l < fuzzySystem.Outputs[k].NumMFs; l++)
                        {
                            highestVal = Math.Max(MFvalues[fuzzySystem.NumInputs + k][l], highestVal);
                        }
                        // Find MFs that have the highest membership value we just found
                        List <int> MFsWithHighestVal = new List <int>();
                        for (int l = 0; l < fuzzySystem.Outputs[0].NumMFs; l++)
                        {
                            if (MFvalues[fuzzySystem.NumInputs + k][l] == highestVal)
                            {
                                MFsWithHighestVal.Add(l);
                            }
                        }
                        // Choose a random one of them
                        highestMF[fuzzySystem.NumInputs + k] = MFsWithHighestVal[(new Random()).Next(MFsWithHighestVal.Count)];
                    }
                    // Create rule
                    Rule newRule = new Rule()
                    {
                        ConnectionType = 1,
                        Inputs         = new int[fuzzySystem.NumInputs],
                        Outputs        = new int[fuzzySystem.NumOutputs],
                        Weight         = 1.0f
                    };
                    for (int i = 0; i < fuzzySystem.NumInputs; i++)
                    {
                        newRule.Inputs[i] = highestMF[i] + 1;
                    }
                    for (int i = 0; i < fuzzySystem.NumOutputs; i++)
                    {
                        newRule.Outputs[i] = highestMF[fuzzySystem.NumInputs + i] + 1;
                    }

                    // Add to rule list if the inputs don't match any existing rule
                    bool isRuleNew = true;
                    foreach (Rule rule in rules)
                    {
                        if (rule.SameInput(newRule))
                        {
                            isRuleNew = false;
                            break;
                        }
                    }
                    if (isRuleNew)
                    {
                        rules.Add(newRule);
                    }
                }
            }

            foreach (Rule rule in rules)
            {
                rule.ConnectionType = 1;
                rule.Weight         = 1.0f;
            }
            fuzzySystem.Rules = rules.ToArray();

            watch.Stop();

            GeneratedFuzzyBox.Text = fuzzySystem.ToString(IncludeValuesCheckBox.IsChecked == true);

            SaveButton.IsEnabled     = true;
            OptimizeButton.IsEnabled = true;
            UseButton.IsEnabled      = true;

            float MSE;

            try
            {
                fuzzySystem.LoadInputsAndSaveOutputs(InputFileTextBox.Text, OutputFileTextBox.Text.Replace(".txt", ".generated.txt"));
                MSE = FuzzySystem.GetOutputFilesMSE(OutputFileTextBox.Text, OutputFileTextBox.Text.Replace(".txt", ".generated.txt"));
            }
            catch (Exception exc)
            {
                MessageBox.Show(exc.Message, "Error", MessageBoxButton.OK);
                return;
            }

            MessageBox.Show("MSE: " + MSE.ToString(CultureInfo.InvariantCulture) + "\r\nRMSE: " + Math.Sqrt(MSE).ToString(CultureInfo.InvariantCulture) + "\r\nRMSEP: " + (Math.Sqrt(MSE) / (fuzzySystem.Outputs[0].Range[1] - fuzzySystem.Outputs[0].Range[0]) * 100.0f).ToString(CultureInfo.InvariantCulture) + "%\r\nGeneration time in milliseconds: " + watch.ElapsedMilliseconds, "Generation successful!", MessageBoxButton.OK);
        }