using System; using System.Collections.Generic; using System.Linq; using System.Text; using HeuristicLab.Problems.GrammaticalOptimization; namespace HeuristicLab.Algorithms.GrammaticalOptimization { public class ExhaustiveDepthFirstSearch { public event Action FoundNewBestSolution; public event Action SolutionEvaluated; private readonly int maxLen; private readonly Stack stack = new Stack(); private readonly IProblem problem; public ExhaustiveDepthFirstSearch(IProblem problem, int maxLen) { this.maxLen = maxLen; this.problem = problem; } public void Run(int maxIterations) { double bestQuality = double.MinValue; stack.Push(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 (stack.Any()) { var phrase = stack.Pop(); 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) { stack.Push(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); } } }