public bool EmptinessSearch(GeneralizedBuchiAutomaton<AutomatonNode> a, AutomatonNode qi)
        {
            label = new Dictionary<AutomatonNode, HashSet<int>> ();
            foreach (var n in a.Nodes) {
                label.Add (n, new HashSet<int> ());
            }
            //for (int i = 0, length = a.Transitions.Count; i < length; i++) {
            //    label[i] = new HashSet<int> ();
            //}

            path.Push (qi);
            while (path.Count > 0) {
                var q = path.Peek ();
                //Console.WriteLine ("q={0}", q.Name);

                var succToProcess = a.Post(q).Except (path.Union (processed));
                while (succToProcess.Count () > 0) {
                    var succ = succToProcess.First ();
                    path.Push (succ);
                    label [succ] = new HashSet<int> ();
                    q = succ;
                    succToProcess = a.Post(q).Except (path.Union (processed));
                    //Console.WriteLine ("q={0}", q.Name);
                }
                //Console.WriteLine ("----");
                if (label[q].Count == 0 | a.AcceptanceCondition.Accept(q)) { //  a.AcceptanceSets.Any (x => x.Nodes.Contains (q))
                    var labelsToPropagate = label [q].Union (a.AcceptanceCondition.GetAcceptingConditions(q));
                    //Console.WriteLine ("labelsToPropagate={0}", string.Join (",", labelsToPropagate));

                    propagate (a, new [] { q }, labelsToPropagate);
                    if (label[q].SetEquals (a.AcceptanceCondition.AllKeys ())) {
                        goto ExitTrue;
                        // return true;
                    }
                }
                processed.Add (q);
                path.Pop ();
            }

            return false;

            ExitTrue : return true;
        }
        public bool EmptinessSearch(AutomatonNode qi, AutomatonNode bi)
        {
            foreach (var n in a.Nodes) {
                label.Add (n, new HashSet<int> ());
            }

            path.Push (new Tuple<AutomatonNode, AutomatonNode> (qi, bi));
            while (path.Count > 0) {
                var q = path.Peek ();

                var succToProcess = new Stack<Tuple<AutomatonNode, AutomatonNode>> ();

                var pup = new HashSet<Tuple<AutomatonNode, AutomatonNode>> (path.Union (processed));
                foreach (var t1 in a.GetTransitions (q.Item1)) {
                    foreach (var t2 in ba.Post (q.Item2, t1.Decoration)) {
                        //if (t1.Labels.IsSubsetOf (t2.Labels)) { fixme
                        var nt = new Tuple<AutomatonNode, AutomatonNode> (t1.Target, t2);
                            if (!pup.Contains (nt)) {
                                ////Console.WriteLine ("pushing from (" + a.Nodes[q.Item1].Name + ", " + q.Item2.Name + ") to (" + a.Nodes[nt.Item1].Name + ", " + nt.Item2.Name + ")");
                                succToProcess.Push (nt);
                            }
                        //}
                    }
                }

                while (succToProcess.Count () > 0) {
                    var succ = succToProcess.Pop ();
                    path.Push (succ);
                    label [succ.Item1] = new HashSet<int> ();
                    q = succ;

                    succToProcess = new Stack<Tuple<AutomatonNode, AutomatonNode>> ();
                    pup = new HashSet<Tuple<AutomatonNode,AutomatonNode>> (path.Union (processed));
                    foreach (var t1 in a.GetTransitions (q.Item1)) {
                        foreach (var t2 in ba.Post (q.Item2, t1.Decoration)) {
                            //if (t1.Labels.IsSubsetOf (t2.Labels)) {
                            var nt = new Tuple<AutomatonNode,AutomatonNode> (t1.Target, t2);
                                if (!pup.Contains (nt)) {
                                    ////Console.WriteLine ("pushing from (" + a.Nodes[q.Item1].Name + ", " + ba.Nodes[q.Item2].Name + ") to (" + a.Nodes[nt.Item1].Name + ", " + ba.Nodes[nt.Item2].Name + ")");
                                    succToProcess.Push (nt);
                                }
                            //}
                        }
                    }

                }
                ////Console.WriteLine ("----");
                if (label[q.Item1].Count == 0 | a.AcceptanceCondition.Accept(q.Item1)) {
                    var labelsToPropagate = label [q.Item1].Union (a.AcceptanceCondition.GetAcceptingConditions(q.Item1));

                    propagate (new [] { q }, labelsToPropagate);
                    if (label[q.Item1].SetEquals (a.AcceptanceCondition.AllKeys ())) {
                        goto ExitTrue;
                        // return true;
                    }
                }
                processed.Add (q);
                path.Pop ();
            }

            return false;

            ExitTrue : return true;
        }