/// <summary> /// Transform the specified Non-Deterministic Buchi Automata into a Deterministic Rabin Automata. /// </summary> /// <param name="ba">Buchi Automata.</param> public static RabinAutomaton<AutomatonNode> Determinize(this BuchiAutomaton<AutomatonNode> ba) { var Transitions = new Dictionary<SafraTree, List<SafraTransition>> (); // For more details about the algorithm, check "Determinization of Büchi-Automata" by Markus Roggenbach var initial = new SafraTree (new [] { ba.InitialNode }, ba); var pending = new Stack<SafraTree> (new [] { initial }); var visited = new HashSet<SafraTree> (); while (pending.Count > 0) { var source = pending.Pop (); visited.Add (source); foreach (var a in ba.GetOutDecorations (source.MacroState)) { var target = source.Clone (); target.RemoveAllMarks (); // Step 1 target.Create (); // Step 2 target.Update (a.LiteralSet); // Step 3 target.HorizontalMerge (); // Step 4 target.RemoveEmpty (); // Step 5 if (target.MacroState.Count > 0) { target.VerticalMerge (); // Step 6 if (!Transitions.ContainsKey (source)) Transitions.Add (source, new List<SafraTransition> ()); Transitions[source].Add (new SafraTransition (a.LiteralSet, target)); if (!Transitions.ContainsKey (target) & !pending.Contains (target)) pending.Push (target); } } } var rabin = new RabinAutomaton<AutomatonNode> (new AutomatonNodeFactory ()); var mapping = new Dictionary<SafraTree, AutomatonNode> (); foreach (var t in Transitions.Keys) { var n = rabin.AddNode (); mapping.Add (t, n); } rabin.SetInitialNode (mapping [initial]); foreach (var t in Transitions) { foreach (var e in t.Value) { rabin.AddTransition (mapping [t.Key], mapping [e.Target], new LiteralSetDecoration (e.Labels)); } } foreach (int k in Transitions.Keys.Select(t => t.Id).Distinct ()) { var r1 = Transitions.Keys.Where (x => !x.ContainsIdentifier (k)).Select (x => mapping[x]); var r2 = Transitions.Keys.Where (x => x.ContainsMarkedNode (k)).Select (x => mapping[x]); rabin.AddToAcceptance (r1, r2); } return rabin; }
static string PrintTree(SafraTree t, int indent = 0) { return new String ('-', indent) + t.Id + " - " + string.Join (",", t.MacroState.Select (x => x.Name)) + " - " + (t.Mark ? "!" : "") + "\n" + string.Join ("\n", t.Children.Select (x => PrintTree (x, indent + 1))); }
/// <summary> /// Creates a new child if there is a set in the macro state that is accepting in the Buchi Automata. /// The procedure is recursively applied on children. /// </summary> public void Create() { var children = Children.ToList (); var inter = ((BuchiAcceptance<AutomatonNode>) ba.AcceptanceCondition).GetAcceptingNodes (MacroState); if (inter.Any ()) { var newNode = new SafraTree (inter, ba); Children.Add (newNode); } foreach (var c in children) { c.Create (); } }
/// <summary> /// Initializes a new instance of the /// <see cref="LtlSharp.Translators.SafraDeterminization+SafraTransition"/> class /// with the specified label and target safra tree. /// </summary> /// <param name="labels">Labels.</param> /// <param name="target">Target.</param> public SafraTransition(LiteralSet labels, SafraTree target) { this.Labels = labels; this.Target = target; }