Exemplo n.º 1
0
        /// <summary>
        /// Write the FSA in dot format.
        /// </summary>
        /// <param name="fa">the FSA to write</param>
        /// <param name="faName">the name of the FSA</param>
        /// <param name="tw">text writer for the output</param>
        /// <param name="rankdir">the main direction of the arrows</param>
        /// <param name="fontsize">the size of the font in labels</param>
        /// <param name="descr">function that describes the labels as strings</param>
        public static void AutomatonToDot <S>(Func <S, string> descr, IAutomaton <S> fa, string faName, System.IO.TextWriter tw, RANKDIR rankdir, int fontsize, bool showName)
        {
            ITransducer <S> faf     = fa as ITransducer <S>;
            Func <S, bool>  isfinal = lab => { return(faf == null ? false : faf.IsFinalRule(lab)); };

            List <Move <S> > epsilonmoves = new List <Move <S> >();
            Dictionary <Pair <int, int>, string> nonepsilonMoves = new Dictionary <Pair <int, int>, string>();
            Dictionary <int, string>             finalLabels     = new Dictionary <int, string>();

            foreach (var move in fa.GetMoves())
            {
                if (move.IsEpsilon)
                {
                    epsilonmoves.Add(move);
                }
                else if (isfinal(move.Label))
                {
                    string conLab = descr(move.Label);
                    if (!string.IsNullOrEmpty(conLab))
                    {
                        string lab;
                        if (finalLabels.TryGetValue(move.SourceState, out lab))
                        {
                            lab = lab + ", " + conLab;
                        }
                        else
                        {
                            lab = conLab;
                        }
                        finalLabels[move.SourceState] = lab;
                    }
                }
                else
                {
                    var    key = new Pair <int, int>(move.SourceState, move.TargetState);
                    string lab;
                    if (nonepsilonMoves.TryGetValue(key, out lab))
                    {
                        lab = lab + ",  " + descr(move.Label);
                    }
                    else
                    {
                        lab = descr(move.Label);
                    }
                    nonepsilonMoves[key] = lab;
                }
            }



            tw.WriteLine("digraph \"" + faName + "\" {");
            tw.WriteLine(string.Format("rankdir={0}; fontsize={1};", rankdir.ToString(), fontsize));
            tw.WriteLine();
            tw.WriteLine("//Initial state");
            tw.WriteLine(string.Format("preInit [style = filled, shape = plaintext, color = {1}, fillcolor = white, label = \"{0}\"]", (showName ? faName + ": " : " "), (showName ? "black" : "white")));
            tw.WriteLine("//Final states");
            foreach (int state in fa.GetStates())
            {
                if (fa.IsFinalState(state) && !finalLabels.ContainsKey(state))
                {
                    tw.WriteLine(string.Format("{1} [style = filled, shape = circle, fillcolor = white, fontsize = {0}, peripheries=2]", fontsize, state));
                }
                if (fa.IsFinalState(state) && finalLabels.ContainsKey(state))
                {
                    tw.WriteLine(string.Format("{1} [style = filled, shape = circle, fillcolor = white, fontsize = {0}]", fontsize, state));
                    tw.WriteLine(string.Format("f{0} [style = filled, shape = box, fillcolor = white, label=\"\", peripheries=2]", state));
                }
            }
            tw.WriteLine();
            tw.WriteLine("//Other states");
            foreach (int state in fa.GetStates())
            {
                if (!fa.IsFinalState(state))
                {
                    tw.WriteLine(string.Format("{1} [style = filled, shape = circle, fillcolor = white, fontsize = {0}]", fontsize, state));
                }
            }
            tw.WriteLine();
            tw.WriteLine("//Transitions");
            tw.WriteLine(string.Format("preInit -> {0}", fa.InitialState));
            foreach (Move <S> t in fa.GetMoves())
            {
                if (!isfinal(t.Label))
                {
                    tw.WriteLine(string.Format("{0} -> {1} [label = \"{2}\"{3}, fontsize = {4} ];", t.SourceState, t.TargetState,
                                               t.IsEpsilon ? "()" : descr(t.Label).Replace(@"\n", @"\x0A"),
                                               t.IsEpsilon ? "" : "", fontsize));
                }
                else if (finalLabels.ContainsKey(t.SourceState))
                {
                    tw.WriteLine(string.Format("{0} -> {1} [label = \"{2}\", fontsize = {3} ];", t.SourceState, "f" + t.TargetState,
                                               finalLabels[t.SourceState].Replace(@"\n", @"\x0A"), fontsize));
                }
            }
            tw.WriteLine("}");
        }
Exemplo n.º 2
0
        /// <summary>
        /// Write the automaton in dgml format.
        /// </summary>
        /// <param name="fa">the automaton to write</param>
        /// <param name="tw">text writer for the output</param>
        public static void AutomatonToDgml <S>(int k, IAutomaton <S> fa, string name, System.IO.TextWriter tw, Func <S, string> describeS = null)
        {
            ITransducer <S> faf          = fa as ITransducer <S>;
            bool            isTransducer = (faf != null);
            Func <S, bool>  isfinal      = lab => { return(isTransducer ? faf.IsFinalRule(lab) : false); };

            var finalMoves    = new Dictionary <int, List <S> >();
            var nonFinalMoves = new Dictionary <Tuple <int, int>, List <S> >();
            var epsilonmoves  = new List <Move <S> >();

            var nonEpsilonStates            = new HashSet <int>();
            Func <int, bool> IsEpsilonState = (s => !nonEpsilonStates.Contains(s));

            foreach (var move in fa.GetMoves())
            {
                if (move.IsEpsilon)
                {
                    epsilonmoves.Add(move);
                }

                else if (isfinal(move.Label) &&
                         !(faf.IsGuardTrue(move.Label) && faf.GetYieldsLength(move.Label) == 0))
                {
                    List <S> rules;
                    if (!finalMoves.TryGetValue(move.SourceState, out rules))
                    {
                        rules = new List <S>();
                        finalMoves[move.SourceState] = rules;
                    }
                    rules.Add(move.Label);
                }
                else if (!isfinal(move.Label))
                {
                    nonEpsilonStates.Add(move.SourceState);
                    List <S> rules;
                    var      p = new Tuple <int, int>(move.SourceState, move.TargetState);
                    if (!nonFinalMoves.TryGetValue(p, out rules))
                    {
                        rules            = new List <S>();
                        nonFinalMoves[p] = rules;
                    }
                    rules.Add(move.Label);
                }
            }

            tw.WriteLine("<?xml version=\"1.0\" encoding=\"utf-8\"?>");
            tw.WriteLine("<DirectedGraph xmlns=\"http://schemas.microsoft.com/vs/2009/dgml\" ZoomLevel=\"1.5\" GraphDirection=\"TopToBottom\" >");
            tw.WriteLine("<Nodes>");
            tw.WriteLine("<Node Id=\"init\" Label=\"{0}\" Stroke=\"white\" Background=\"white\"/>", name);
            foreach (int state in fa.GetStates())
            {
                if (state == fa.InitialState && fa.IsFinalState(state))
                {
                    tw.WriteLine("<Node Id=\"{0}\" Label=\"{1}\" Category=\"State\" >", state, fa.DescribeState(state));
                    if (!finalMoves.ContainsKey(state))
                    {
                        //if (IsEpsilonState(state))
                        //    tw.WriteLine("<Category Ref=\"EpsilonState\" />");
                        //else
                        tw.WriteLine("<Category Ref=\"FinalState\" />");
                    }
                    //tw.WriteLine("<Category Ref=\"InitialState\" />");
                    tw.WriteLine("</Node>");
                    if (finalMoves.ContainsKey(state))
                    {
                        tw.WriteLine("<Node Id=\"f{0}\" Label=\" \" Category=\"State\" >", state);
                        tw.WriteLine("<Category Ref=\"FinalState\" />");
                        tw.WriteLine("<Category Ref=\"SinkState\" />");
                        tw.WriteLine("</Node>");
                    }
                }
                else if (state == fa.InitialState)
                {
                    tw.WriteLine("<Node Id=\"{0}\" Label=\"{1}\" Category=\"State\" >", state, fa.DescribeState(state));
                    tw.WriteLine("<Category Ref=\"InitialState\" />");
                    tw.WriteLine("</Node>");
                }
                else if (fa.IsFinalState(state))
                {
                    tw.WriteLine("<Node Id=\"{0}\" Label=\"{1}\" Category=\"State\" >", state, fa.DescribeState(state));
                    if (!finalMoves.ContainsKey(state))
                    {
                        //if (IsEpsilonState(state))
                        //    tw.WriteLine("<Category Ref=\"EpsilonState\" />");
                        //else
                        tw.WriteLine("<Category Ref=\"FinalState\" />");
                    }
                    tw.WriteLine("</Node>");
                    if (finalMoves.ContainsKey(state))
                    {
                        tw.WriteLine("<Node Id=\"f{0}\" Label=\" \" Category=\"State\" >", state);
                        tw.WriteLine("<Category Ref=\"FinalState\" />");
                        tw.WriteLine("<Category Ref=\"SinkState\" />");
                        tw.WriteLine("</Node>");
                    }
                }
                else
                {
                    tw.WriteLine("<Node Id=\"{0}\" Label=\"{1}\" Category=\"State\" />", state, fa.DescribeState(state));
                }
            }
            tw.WriteLine("</Nodes>");
            tw.WriteLine("<Links>");
            tw.WriteLine("<Link Source=\"init\" Target=\"{0}\" Label=\"{1}\" Category=\"StartTransition\" />", fa.InitialState, fa.DescribeStartLabel());
            foreach (var move in epsilonmoves)
            {
                tw.WriteLine("<Link Source=\"{0}\" Target=\"{1}\" Category=\"EpsilonTransition\" />", move.SourceState, move.TargetState);
            }

            foreach (var move in nonFinalMoves)
            {
                tw.WriteLine(GetNonFinalRuleInfo(k, fa, faf, move.Key.Item1, move.Key.Item2, move.Value, describeS));
            }

            foreach (var move in finalMoves)
            {
                tw.WriteLine(GetFinalRuleInfo(k, faf, move.Key, move.Value));
            }

            tw.WriteLine("</Links>");
            WriteCategoriesAndStyles(tw);
            tw.WriteLine("</DirectedGraph>");
        }
Exemplo n.º 3
0
        /// <summary>
        /// Write the automaton in dgml format into the textwriter.
        /// </summary>
        public void Write <S>(IAutomaton <S> fa)
        {
            var nonEpsilonMoves = new Dictionary <(int, int), List <S> >();
            var epsilonmoves    = new List <Move <S> >();

            var nonEpsilonStates = new HashSet <int>();

            foreach (Move <S> move in fa.GetMoves())
            {
                if (move.IsEpsilon)
                {
                    epsilonmoves.Add(move);
                }
                else
                {
                    nonEpsilonStates.Add(move.SourceState);
                    var p = (move.SourceState, move.TargetState);
                    if (!nonEpsilonMoves.TryGetValue(p, out List <S>?rules))
                    {
                        rules = new List <S>();
                        nonEpsilonMoves[p] = rules;
                    }

                    Debug.Assert(move.Label is not null);
                    rules.Add(move.Label);
                }
            }

            _tw.WriteLine("<?xml version=\"1.0\" encoding=\"utf-8\"?>");
            _tw.WriteLine("<DirectedGraph xmlns=\"http://schemas.microsoft.com/vs/2009/dgml\" ZoomLevel=\"1.5\" GraphDirection=\"TopToBottom\" >");
            _tw.WriteLine("<Nodes>");
            _tw.WriteLine("<Node Id=\"dfa\" Label=\" \" Group=\"Collapsed\" Category=\"DFA\" DFAInfo=\"{0}\" />", GetDFAInfo(fa));
            _tw.WriteLine("<Node Id=\"dfainfo\" Category=\"DFAInfo\" Label=\"{0}\"/>", GetDFAInfo(fa));
            if (_onlyDFAinfo)
            {
                _tw.WriteLine("</Nodes>");
            }
            else
            {
                foreach (int state in fa.GetStates())
                {
                    _tw.WriteLine("<Node Id=\"{0}\" Label=\"{0}\" Category=\"State\" Group=\"{1}\" StateInfo=\"{2}\">", state, _hideStateInfo ? "Collapsed" : "Expanded", GetStateInfo(fa, state));
                    if (state == fa.InitialState)
                    {
                        _tw.WriteLine("<Category Ref=\"InitialState\" />");
                    }
                    if (fa.IsFinalState(state))
                    {
                        _tw.WriteLine("<Category Ref=\"FinalState\" />");
                    }
                    _tw.WriteLine("</Node>");
                    _tw.WriteLine("<Node Id=\"{0}info\" Label=\"{1}\" Category=\"StateInfo\"/>", state, GetStateInfo(fa, state));
                }
                _tw.WriteLine("</Nodes>");
                _tw.WriteLine("<Links>");
                _tw.WriteLine("<Link Source=\"dfa\" Target=\"{0}\" Label=\"{1}\" Category=\"StartTransition\" />", fa.InitialState, fa.DescribeStartLabel());
                _tw.WriteLine("<Link Source=\"dfa\" Target=\"dfainfo\" Label=\"\" Category=\"Contains\" />");

                foreach (Move <S> move in epsilonmoves)
                {
                    _tw.WriteLine("<Link Source=\"{0}\" Target=\"{1}\" Category=\"EpsilonTransition\" />", move.SourceState, move.TargetState);
                }

                foreach (KeyValuePair <(int, int), List <S> > move in nonEpsilonMoves)
                {
                    _tw.WriteLine(GetNonFinalRuleInfo(fa, move.Key.Item1, move.Key.Item2, move.Value));
                }

                foreach (int state in fa.GetStates())
                {
                    _tw.WriteLine("<Link Source=\"{0}\" Target=\"{0}info\" Category=\"Contains\" />", state);
                }

                _tw.WriteLine("</Links>");
                WriteCategoriesAndStyles();
            }
            _tw.WriteLine("</DirectedGraph>");
        }
Exemplo n.º 4
0
        /// <summary>
        /// Write the FSA in dot format.
        /// </summary>
        /// <param name="fa">the FSA to write</param>
        /// <param name="faName">the name of the FSA</param>
        /// <param name="tw">text writer for the output</param>
        /// <param name="rankdir">the main direction of the arrows</param>
        /// <param name="fontsize">the size of the font in labels</param>
        /// <param name="descr">function that describes the labels as strings</param>
        public static void AutomatonToDot <S>(Func <S, string> descr, IAutomaton <S> fa, string faName, System.IO.TextWriter tw, bool showName, Config config)
        {
            // TODO: find why is this here
            ITransducer <S> faf = fa as ITransducer <S>;
            // TODO: this is ineffective, hoist the faf == null check before the delegate assignment
            Func <S, bool> isfinal = lab => { return(faf == null ? false : faf.IsFinalRule(lab)); };

            // TODO: this block is mostly unused! clean up!
            // only finalLabels are used
            List <Move <S> > epsilonmoves = new List <Move <S> >();
            Dictionary <Tuple <int, int>, string> nonepsilonMoves = new Dictionary <Tuple <int, int>, string>();
            Dictionary <int, string> finalLabels = new Dictionary <int, string>();

            foreach (var move in fa.GetMoves())
            {
                if (move.IsEpsilon)
                {
                    epsilonmoves.Add(move);
                }
                else if (isfinal(move.Label))
                {
                    string conLab = descr(move.Label);
                    if (!string.IsNullOrEmpty(conLab))
                    {
                        string lab;
                        if (finalLabels.TryGetValue(move.SourceState, out lab))
                        {
                            lab = lab + ", " + conLab;
                        }
                        else
                        {
                            lab = conLab;
                        }
                        finalLabels[move.SourceState] = lab;
                    }
                }
                else
                {
                    var    key = new Tuple <int, int>(move.SourceState, move.TargetState);
                    string lab;
                    if (nonepsilonMoves.TryGetValue(key, out lab))
                    {
                        lab = lab + ",  " + descr(move.Label);
                    }
                    else
                    {
                        lab = descr(move.Label);
                    }
                    nonepsilonMoves[key] = lab;
                }
            }

            string sanitize(string input)
            {
                return
                    (input
                     .Replace("\\", "\\\\")
                     .Replace("\"", "\\\"")
                     //.Replace("<", "\\<")
                     //.Replace(">", "\\>")
                    );
            }

            string openLabelTag  = config.htmlLabels ? "<" : "\"";
            string closeLabelTag = config.htmlLabels ? ">" : "\"";


            tw.WriteLine("digraph \"" + faName + "\" {");
            tw.WriteLine(string.Format("rankdir={0}; fontsize={1};", config.rankdir.ToString(), config.fontsize));
            tw.WriteLine();
            tw.WriteLine("//Defaults");
            tw.WriteLine(string.Format($"node [style = filled, shape = " + config.shape.ToString() + ", fillcolor = white, fontsize = {0}, margin = 0.01]", config.fontsize));
            tw.WriteLine(string.Format("edge [ fontsize = {0} ]", config.fontsize));
            tw.WriteLine();
            tw.WriteLine("//Initial state format");
            {
                showName = showName && !string.IsNullOrEmpty(faName);
                tw.WriteLine(string.Format("preInit [shape = plaintext, color = {1}, label = \"{0}\"]", (showName ? faName + ": " : ""), (showName ? "black" : "white")));
            }
            tw.WriteLine();
            tw.WriteLine("// All other states format");
            foreach (int state in fa.GetStates())
            {
                if (fa.IsFinalState(state) && !finalLabels.ContainsKey(state))
                {
                    tw.WriteLine(string.Format("{0} [peripheries=2]", state));
                }
                if (fa.IsFinalState(state) && finalLabels.ContainsKey(state))
                {
                    tw.WriteLine(string.Format("{0} []", state));
                    tw.WriteLine(string.Format("f{0} [shape = box, label=\"\", peripheries=2]", state));
                }
                tw.WriteLine(string.Format("{0} [label = " + openLabelTag + "{1}" + closeLabelTag + "]", state, sanitize(fa.DescribeState(state))));
            }
            tw.WriteLine();
            tw.WriteLine("//Transitions");
            tw.WriteLine(string.Format("preInit -> {0}", fa.InitialState));
            foreach (Move <S> t in fa.GetMoves())
            {
                if (!isfinal(t.Label))
                {
                    tw.WriteLine(string.Format("{0} -> {1} [label = " + openLabelTag + "{2}" + closeLabelTag + (t.IsEpsilon ?  ", style=dashed" : "") + "];", t.SourceState, t.TargetState,
                                               t.IsEpsilon ? "ε" : sanitize(descr(t.Label))
                                               ));
                }
                else if (finalLabels.ContainsKey(t.SourceState))
                {
                    tw.WriteLine(string.Format("{0} -> {1} [label = " + openLabelTag + "{2}" + closeLabelTag + "];", t.SourceState, "f" + t.TargetState,
                                               sanitize(finalLabels[t.SourceState])
                                               ));
                }
            }
            tw.WriteLine("}");
        }