예제 #1
0
        /**
         * /// Determinizes an fst. The result will be an equivalent fst that has the
         * /// property that no state has two transitions with the same input label. For
         * /// this algorithm, epsilon transitions are treated as regular symbols.
         * ///
         * /// @param fst the fst to determinize
         * /// @return the determinized fst
         */
        public static Fst Get(Fst fst)
        {
            if (fst.Semiring == null)
            {
                // semiring not provided
                return(null);
            }

            // initialize the queue and new fst
            Semiring semiring = fst.Semiring;
            Fst      res      = new Fst(semiring);

            res.Isyms = fst.Isyms;
            res.Osyms = fst.Osyms;

            // stores the queue (item in index 0 is next)
            Queue <List <Pair <State, float> > > queue = new Queue <List <Pair <State, float> > >();

            Dictionary <String, State> stateMapper = new Dictionary <String, State>();

            State  s           = new State(semiring.Zero);
            string stateString = "(" + fst.Start + "," + semiring.One + ")";

            queue.Enqueue(new List <Pair <State, float> >());
            queue.Peek().Add(new Pair <State, float>(fst.Start, semiring.One));
            res.AddState(s);
            stateMapper.Add(stateString, s);
            res.SetStart(s);

            while (queue.Count != 0)
            {
                List <Pair <State, float> > p = queue.Dequeue();
                State pnew = GetStateLabel(p, stateMapper);
                //queueRemoveAt(0);
                List <int> labels = GetUniqueLabels(fst, p);
                foreach (int label in labels)
                {
                    float wnew = semiring.Zero;
                    // calc w'
                    foreach (Pair <State, float> ps in p)
                    {
                        State old     = ps.GetLeft();
                        float u       = ps.GetRight();
                        int   numArcs = old.GetNumArcs();
                        for (int j = 0; j < numArcs; j++)
                        {
                            Arc arc = old.GetArc(j);
                            if (label == arc.Ilabel)
                            {
                                wnew = semiring.Plus(wnew,
                                                     semiring.Times(u, arc.Weight));
                            }
                        }
                    }

                    // calc new states
                    // keep residual weights to variable forQueue
                    List <Pair <State, float> > forQueue = new List <Pair <State, float> >();
                    foreach (Pair <State, float> ps in p)
                    {
                        State old        = ps.GetLeft();
                        float u          = ps.GetRight();
                        float wnewRevert = semiring.Divide(semiring.One, wnew);
                        int   numArcs    = old.GetNumArcs();
                        for (int j = 0; j < numArcs; j++)
                        {
                            Arc arc = old.GetArc(j);
                            if (label == arc.Ilabel)
                            {
                                State oldstate           = arc.NextState;
                                Pair <State, float> pair = GetPair(forQueue,
                                                                   oldstate, semiring.Zero);
                                pair.SetRight(semiring.Plus(
                                                  pair.GetRight(),
                                                  semiring.Times(wnewRevert,
                                                                 semiring.Times(u, arc.Weight))));
                            }
                        }
                    }

                    // build new state's id and new elements for queue
                    string qnewid = "";
                    foreach (Pair <State, float> ps in forQueue)
                    {
                        State old  = ps.GetLeft();
                        float unew = ps.GetRight();
                        if (!qnewid.Equals(""))
                        {
                            qnewid = qnewid + ",";
                        }
                        qnewid = qnewid + "(" + old + "," + unew + ")";
                    }

                    if (stateMapper.Get(qnewid) == null)
                    {
                        State qnew = new State(semiring.Zero);
                        res.AddState(qnew);
                        stateMapper.Add(qnewid, qnew);
                        // update new state's weight
                        float fw = qnew.FinalWeight;
                        foreach (Pair <State, float> ps in forQueue)
                        {
                            fw = semiring.Plus(fw, semiring.Times(ps.GetLeft().FinalWeight, ps.GetRight()));
                        }
                        qnew.FinalWeight = fw;

                        queue.Enqueue(forQueue);
                    }
                    pnew.AddArc(new Arc(label, label, wnew, stateMapper[qnewid]));
                }
            }

            return(res);
        }