#region License Information /* HeuristicLab * Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL) * * This file is part of HeuristicLab. * * HeuristicLab is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * HeuristicLab is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with HeuristicLab. If not, see . */ #endregion using System; using System.Diagnostics; using System.IO; using HeuristicLab.Common; using HeuristicLab.Core; using HeuristicLab.Persistence.Default.CompositeSerializers.Storable; namespace HeuristicLab.Algorithms.DataAnalysis.SymRegGrammarEnumeration { [Item("SearchGraphVisualizer", "")] [StorableClass] internal class SearchGraphVisualizer : Item, IGrammarEnumerationAnalyzer { private readonly string dotFileName = Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory) + @"\searchgraph.dot"; private TextWriterTraceListener dotFileTrace; public SearchGraphVisualizer() { } protected SearchGraphVisualizer(SearchGraphVisualizer original, Cloner cloner) : base(original, cloner) { } [StorableConstructor] protected SearchGraphVisualizer(bool deserializing) : base(deserializing) { } public override IDeepCloneable Clone(Cloner cloner) { return new SearchGraphVisualizer(this, cloner); } public void Register(GrammarEnumerationAlgorithm algorithm) { algorithm.Started += GrammarEnumerationAlgorithmOnStarted; algorithm.Stopped += GrammarEnumerationAlgorithmOnStopped; algorithm.ExceptionOccurred += GrammarEnumerationAlgorithmOnStopped; algorithm.PhraseFetched += PhraseFetched; algorithm.PhraseDerived += PhraseDerived; algorithm.SentenceGenerated += SentenceGenerated; } public void Deregister(GrammarEnumerationAlgorithm algorithm) { algorithm.Started -= GrammarEnumerationAlgorithmOnStarted; algorithm.Stopped -= GrammarEnumerationAlgorithmOnStopped; algorithm.ExceptionOccurred -= GrammarEnumerationAlgorithmOnStopped; algorithm.PhraseFetched -= PhraseFetched; algorithm.PhraseDerived -= PhraseDerived; algorithm.SentenceGenerated -= SentenceGenerated; } private void GrammarEnumerationAlgorithmOnStarted(object sender, EventArgs eventArgs) { dotFileTrace = new TextWriterTraceListener(new FileStream(dotFileName, FileMode.Create)); ((StreamWriter)dotFileTrace.Writer).AutoFlush = true; dotFileTrace.WriteLine("digraph searchgraph { pad=0.02; nodesep=0.3; ranksep=0.02;ratio=0.5625;"); } private void GrammarEnumerationAlgorithmOnStopped(object sender, EventArgs eventArgs) { try { var alg = (GrammarEnumerationAlgorithm)sender; var phrase0 = new SymbolList(new[] { alg.Grammar.StartSymbol }); var phrase0Hash = alg.Grammar.Hasher.CalcHashCode(phrase0); dotFileTrace.WriteLine($"{phrase0Hash} [label=\"{phrase0}\", shape=doublecircle]; }}"); dotFileTrace.Flush(); } catch (Exception) { dotFileTrace.Close(); throw; } } private void PhraseFetched(object sender, PhraseEventArgs phraseEventArgs) { dotFileTrace.WriteLine($"{phraseEventArgs.Hash} [label=\"{phraseEventArgs.Phrase}\"];"); } private void PhraseDerived(object sender, PhraseAddedEventArgs args) { dotFileTrace.WriteLine($"{args.ParentHash} -> {args.NewHash} [label=\"{args.ExpandedSymbol.StringRepresentation} + → {args.ExpandedProduction}\"];"); } private void SentenceGenerated(object sender, PhraseAddedEventArgs args) { var alg = (GrammarEnumerationAlgorithm)sender; dotFileTrace.WriteLine($"{args.NewHash} [label=\"{alg.Grammar.ToInfixString(args.NewPhrase)}\", style=\"filled\", fillcolor=\"#f79423\", color=\"#f79423\"];"); } } }