using System; using System.Collections.Generic; using System.Linq; using System.Text; using HeuristicLab.Problems.GrammaticalOptimization; namespace HeuristicLab.Algorithms.GrammaticalOptimization { public class ExhaustiveBreadthFirstSearch { public event Action FoundNewBestSolution; public event Action SolutionEvaluated; private readonly int maxLen; private readonly Queue bfsQueue = new Queue(); private readonly IProblem problem; public ExhaustiveBreadthFirstSearch(IProblem problem, int maxLen) { this.problem = problem; this.maxLen = maxLen; } public void Run(int maxIterations) { double bestQuality = double.MinValue; bfsQueue.Enqueue(new Sequence(problem.Grammar.SentenceSymbol)); var sentences = GenerateLanguage(problem.Grammar); var sentenceEnumerator = sentences.GetEnumerator(); for (int i = 0; sentenceEnumerator.MoveNext() && i < maxIterations; i++) { var sentence = sentenceEnumerator.Current.ToString(); var quality = problem.Evaluate(sentence) / problem.BestKnownQuality(maxLen); RaiseSolutionEvaluated(sentence, quality); if (quality > bestQuality) { bestQuality = quality; RaiseFoundNewBestSolution(sentence, quality); } } } // create sentences lazily private IEnumerable GenerateLanguage(IGrammar grammar) { while (bfsQueue.Any()) { var phrase = bfsQueue.Dequeue(); char nt = phrase.FirstNonTerminal; var alts = grammar.GetAlternatives(nt); foreach (var alt in alts) { var newPhrase = new Sequence(phrase); newPhrase.ReplaceAt(newPhrase.FirstNonTerminalIndex, 1, alt); if (newPhrase.IsTerminal && newPhrase.Length <= maxLen) { yield return newPhrase; } else if (grammar.MinPhraseLength(newPhrase) <= maxLen) { bfsQueue.Enqueue(newPhrase); } } } } private void RaiseSolutionEvaluated(string sentence, double quality) { var handler = SolutionEvaluated; if (handler != null) handler(sentence, quality); } private void RaiseFoundNewBestSolution(string sentence, double quality) { var handler = FoundNewBestSolution; if (handler != null) handler(sentence, quality); } } }