/// <summary> /// Metoda oblicza funkcję błędu. /// </summary> /// <param name="words">Zbiór słów</param> /// <param name="current">Cząsteczka, której automat będzie porównywany</param> /// <param name="best">Najlepszy znaleziony automat</param> /// <param name="alphabet">Alfabet</param> /// <returns>Zwraca wartość funkcji błędu</returns> private static int CalculateErrorFunction(ref string[] words, Particle current, Automata best, char[] alphabet) { int sum = 0; for (int i = 0; i < words.Length; i++) for (int j = i + 1; j < words.Length; j++) if (!Utils.CompareAutomats(current.Automata.StateTable, best.StateTable, words[i], words[j], alphabet)) sum++; return sum; }
/// <summary> /// Algorytm aproksymujacy automat. /// </summary> /// <param name="swarm">Rój cząsteczek.</param> /// <param name="globalBest">Cząsteczka, dla której znaleziono najlepsze dopasowanie. Początkowo ma największy możliwy rozmiar.</param> /// <param name="givenAutomaton">Automat, który próbujemy przybliżyć</param> /// <param name="maxSpeed">Maksymalna liczba stanów.</param> /// <param name="calculationsTime">Czas obliczeń podany w godzinach.</param> /// <param name="error">Zadowalająca wartość błędu.</param> /// <param name="words">Słowa do testowania.</param> /// <param name="alphabet">Alfabet.</param> /// <param name="bg">Wątek do obliczeń</param> /// <param name="maxIterationsNoChange">Ilość iteracji, po których zostaje wygenerowany nowy rój</param> /// <param name="c1">Pierwszy współczynnik akceleracji</param> /// <param name="c2">Drugi współczynnik akceleracji</param> /// <param name="c3">Trzeci współczynnik akceleracji</param> /// <returns></returns> public static Particle ApproximateAutomaton(Particle[] swarm, Particle globalBest, Automata givenAutomaton, int maxSpeed, int calculationsTime, int error, string[] words, char[] alphabet, ref BackgroundWorker bg, int maxIterationsNoChange, double c1, double c2, double c3) { globalBest.Automata.MaxNumberOfStates = maxSpeed; InitTimer(calculationsTime); _bestError = CalculateErrorFunction(ref words, globalBest, givenAutomaton, alphabet, ref bg); globalBest.PersonalBest = _bestError; foreach (var s in swarm) for (int i = 0; i < s.Automata.MaxNumberOfStates * s.Automata.NumberOfSymbols; i++) { _r = new Random(i * DateTime.Now.Millisecond); s.Velocity[i] = _r.NextDouble() * maxSpeed; } _iterationsNoChange = 0; while (_minutes > 0 && _bestError > error) { if (_iterationsNoChange++ > maxIterationsNoChange) { _iterationsNoChange = 0; swarm = Utils.GenerateRandomSwarm(swarm.Length, givenAutomaton.NumberOfSymbols, givenAutomaton.MaxNumberOfStates); } foreach (var s in swarm) { _currentError = CalculateErrorFunction(ref words, s, givenAutomaton, alphabet, ref bg); if (s.PersonalBest > _currentError) { s.PersonalBest = _currentError; s.PersonalBestAutomata = s.Automata; } if (globalBest.PersonalBest > _currentError) { globalBest.PersonalBest = _currentError; int size = s.Automata.NumberOfStates * s.Automata.NumberOfSymbols; globalBest.Automata.StateTable = new int[size]; for (int i = 0; i < size; i++) globalBest.Automata.StateTable[i] = s.Automata.StateTable[i]; globalBest.Automata.NumberOfStates = s.Automata.NumberOfStates; _iterationsNoChange = 0; } if (_currentError < _bestError) { _bestError = _currentError; double errorsPercent = Math.Round(((double)_bestError / (double)(words.Length * (words.Length - 1))) * 100, 2); bg.ReportProgress(-1, errorsPercent); } } foreach (var s in swarm) { #region making vectors equal int max = globalBest.Automata.MaxNumberOfStates * globalBest.Automata.NumberOfSymbols; var pb = s.PersonalBestAutomata.StateTable; var gb = globalBest.Automata.StateTable; var posOld = s.Automata.StateTable; Array.Resize(ref posOld, max); Array.Resize(ref pb, max); Array.Resize(ref gb, max); #endregion #region updating velocity for (int i = 0; i < s.Velocity.Length; i++) { _r = new Random(i * DateTime.Now.Millisecond); Random r1 = new Random(i * DateTime.Now.Millisecond + 1); Random r2 = new Random(i * DateTime.Now.Millisecond + 2); Random r3 = new Random(i * DateTime.Now.Millisecond + 3); s.Velocity[i] = c1 * r1.NextDouble() * s.Velocity[i] + c2 * r2.NextDouble() * (pb[i] - s.Velocity[i]) + c3 * r3.NextDouble() * (gb[i] - s.Velocity[i]); if (s.Velocity[i] > maxSpeed || s.Velocity[i] < -maxSpeed) s.Velocity[i] = _r.Next(-maxSpeed, maxSpeed); } #endregion #region updating position int[] pos = new int[max]; for (int i = 0; i < max; i++) pos[i] = Math.Round(posOld[i] + s.Velocity[i]) > s.Automata.MaxNumberOfStates ? _r.Next(1, s.Automata.MaxNumberOfStates + 1) : (int)Math.Round((double)posOld[i] + (int)s.Velocity[i]); int[] npos = null; for (int i = 0; i < max; i++) { if (pos[i] < 1) { if (i < s.Automata.NumberOfSymbols) { npos = new int[s.Automata.NumberOfSymbols]; for (int j = 0; j < s.Automata.NumberOfSymbols; j++) npos[j] = 1; s.Automata.NumberOfStates = 1; } else { int newLength = i / s.Automata.NumberOfSymbols; npos = new int[newLength * s.Automata.NumberOfSymbols]; for (int j = 0; j < newLength * s.Automata.NumberOfSymbols; j++) npos[j] = pos[j]; s.Automata.NumberOfStates = newLength; } pos = npos; break; } npos = pos; } var posMax = pos.Max(); if (posMax > s.Automata.NumberOfStates) { if (posMax > s.Automata.MaxNumberOfStates) { posMax = s.Automata.MaxNumberOfStates; for (int i = 0; i < pos.Length; i++) if (pos[i] > s.Automata.MaxNumberOfStates) pos[i] = s.Automata.MaxNumberOfStates; } int newLength = (posMax * s.Automata.NumberOfSymbols); int[] newtab = new int[newLength]; for (int j = 0; j < npos.Length; j++) newtab[j] = pos[j]; for (int j = npos.Length; j < newLength; j++) newtab[j] = _r.Next(1, posMax + 1); pos = newtab; } s.Automata.NumberOfStates = pos.Length / s.Automata.NumberOfSymbols; for (int i = 0; i < pos.Length; i++) if (pos[i] > s.Automata.NumberOfStates) pos[i] = s.Automata.NumberOfStates; s.Automata.StateTable = pos; #endregion } } if (_minutes == 0) Console.WriteLine(@"timeout"); Automata bestAutomata = globalBest.Automata; Utils.ReduceUnreachableStates(ref bestAutomata); globalBest.Automata = bestAutomata; return globalBest; }
/// <summary> /// Metoda oblicza funkcję błędu. /// </summary> /// <param name="words">Zbiór słów</param> /// <param name="current">Cząsteczka, której automat będzie porównywany</param> /// <param name="best">Najlepszy znaleziony automat</param> /// <param name="alphabet">Alfabet</param> /// <param name="bg">Wątek do obliczeń</param> /// <returns>Zwraca wartość funkcji błędu</returns> private static int CalculateErrorFunction(ref string[] words, Particle current, Automata best, char[] alphabet, ref BackgroundWorker bg) { int sum = 0; for (int i = 0; i < words.Length; i++) for (int j = i + 1; j < words.Length; j++) if (!Utils.CompareAutomats(current.Automata.StateTable, best.StateTable, words[i], words[j], alphabet)) sum++; double errorsPercent = Math.Round(((double)_bestError / (double)(words.Length * (words.Length - 1))) * 100, 2); if (bg != null) bg.ReportProgress(-1, errorsPercent); return sum; }
private void buttonStart_Click(object sender, EventArgs e) { labelErrorsTest.Text = "100%"; labelErrorsTrening.Text = "100%"; labelProgress.Text = "Generowanie zbiorów testowych..."; labelProgress.Refresh(); _minutes = int.Parse(textBoxTime.Text); _error = int.Parse(textBoxError.Text); if (!_isFile) return; _fileAutomata.MaxNumberOfStates = _maxState; var numberofsymbols = _fileAutomata.NumberOfSymbols; var alphabet = Utils.GenerateAlphabeth(numberofsymbols); var swarm = Utils.GenerateRandomSwarm(_swarmSize, _fileAutomata.NumberOfSymbols, _fileAutomata.MaxNumberOfStates); var gbeststates = r.Next(1, _fileAutomata.MaxNumberOfStates); var tab2 = new int[gbeststates * _fileAutomata.NumberOfSymbols]; for (int j = 0; j < tab2.Length; j++) { r = new Random(j * DateTime.Now.Millisecond); tab2[j] = r.Next(1, gbeststates); } Particle gbest = new Particle(new Automata { NumberOfStates = gbeststates, NumberOfSymbols = _fileAutomata.NumberOfSymbols, StateTable = tab2, MaxNumberOfStates = _fileAutomata.MaxNumberOfStates }, null); List<string> trainingDictionary = new List<string>(); List<string> testDictionary = new List<string>(); if (checkBoxOwnTrainingDictionary.Checked) { string wordsString = richTextBoxTrainingDictionary.Text; string[] words = wordsString.Split('\n'); if (words.Length == 0 || (words.Length == 1 && words[0] == "")) { labelProgress.Text = "Niepoprawny zbiór treningowy!"; MessageBox.Show("Zbiór treningowy nie może być pusty!"); return; } foreach (var word in words) { for (int i = 0; i < word.Length; i++) if (!alphabet.Contains(word[i])) { labelProgress.Text = "Niepoprawny zbiór treningowy!"; MessageBox.Show("Jedno ze słów w zbiorze treningowym zawiera niedozwolony znak!"); return; } trainingDictionary.Add(word); } } else Utils.GenerateTrainingDictionary(ref trainingDictionary, alphabet, _fileAutomata.MaxNumberOfStates, _wordLength); if(checkBoxOwnTestDictionary.Checked) { string wordsString = richTextBoxTestDictionary.Text; string[] words = wordsString.Split('\n'); if (words.Length == 0 || (words.Length == 1 && words[0] == "")) { labelProgress.Text = "Niepoprawny zbiór testowy!"; MessageBox.Show("Zbiór testowy nie może być pusty!"); return; } foreach (var word in words) { for (int i = 0; i < word.Length; i++) if (!alphabet.Contains(word[i])) { labelProgress.Text = "Niepoprawny zbiór testowy!"; MessageBox.Show("Jedno ze słów w zbiorze testowym zawiera niedozwolony znak!"); return; } testDictionary.Add(word); } } else Utils.GenerateTestDictionary(ref testDictionary, alphabet, _maxState); _ar = new Argument { Alpahbet = alphabet, GlobalBest = gbest, Minutes = _minutes, Swarm = swarm, Words = trainingDictionary.ToArray(), TestWords = testDictionary.ToArray() }; buttonFileOpen.Enabled = false; buttonStart.Enabled = false; labelProgress.Text = "Trwa rekonstrukcja automatu..."; _bg.RunWorkerAsync(_ar); }