1 | #include "lemfst.h" |
---|
2 | |
---|
3 | LemFST::LemFST(const char* plik_fst) |
---|
4 | { |
---|
5 | fst = StdFst::Read(plik_fst); |
---|
6 | } |
---|
7 | |
---|
8 | |
---|
9 | LemFST::~LemFST(void) |
---|
10 | { |
---|
11 | delete fst; |
---|
12 | path.clear(); |
---|
13 | } |
---|
14 | |
---|
15 | /** Zwraca true jezeli s jest koncowym */ |
---|
16 | bool LemFST::accept(State s) { |
---|
17 | if (s == fst::kNoStateId) return false; |
---|
18 | return fst->Final(s)!=StdFst::Weight::Zero(); |
---|
19 | } |
---|
20 | |
---|
21 | |
---|
22 | LemFST::State LemFST::start() { |
---|
23 | return fst->Start(); |
---|
24 | } |
---|
25 | |
---|
26 | |
---|
27 | /** Przechodzi do nastepnego stanu po jednym znaku */ |
---|
28 | LemFST::State LemFST::next(State s, Char c) { |
---|
29 | if (s==fst::kNoStateId) return fst::kNoStateId; |
---|
30 | ArcsIt aiter(*fst, s); |
---|
31 | for (; !aiter.Done(); aiter.Next()) { |
---|
32 | StdArc arc = aiter.Value(); |
---|
33 | if (arc.ilabel==c) return arc.nextstate; |
---|
34 | |
---|
35 | } |
---|
36 | return fst::kNoStateId; |
---|
37 | } |
---|
38 | |
---|
39 | /** Konsumuje slowo W zaczynajac w stanie s. |
---|
40 | * Zwraca: |
---|
41 | * State (int64) - w jakim sie znajdzie |
---|
42 | * kNoStateId (-1) - gdy nie moze dokonac takiego przejscia. |
---|
43 | */ |
---|
44 | LemFST::State LemFST::next(State s, Word w) { |
---|
45 | if (s==fst::kNoStateId) return fst::kNoStateId; |
---|
46 | LemFST::WordIt it; |
---|
47 | State ns = s; |
---|
48 | for(it=w.begin(); it!=w.end(); ++it) { |
---|
49 | ns = next(ns, *it); |
---|
50 | if (ns==fst::kNoStateId) { |
---|
51 | return fst::kNoStateId; |
---|
52 | } |
---|
53 | } |
---|
54 | return ns; |
---|
55 | |
---|
56 | } |
---|
57 | |
---|
58 | /** Funkcja zwraca kolejne sciezki z automatu w formie generatora. |
---|
59 | * Ustawienie s na kNoStateId (lub -1) restartuje generator. |
---|
60 | * Dopoki s!=-1 metoda zwraca przy kolejnych wywolaniach kolejne sciezki od stanu s |
---|
61 | * do stanow konczacych. |
---|
62 | * Sciezke mozna odzyskac poprzez metode getPath(); |
---|
63 | */ |
---|
64 | long LemFST::cont(State s, Word *result, int maxPath) { |
---|
65 | // Restart generatora po podaniu -1 |
---|
66 | // Lub przekroczeniu dlugosci sciezki |
---|
67 | if (s==fst::kNoStateId || path.size() > maxPath) { |
---|
68 | path.clear(); |
---|
69 | return 0; |
---|
70 | } |
---|
71 | |
---|
72 | |
---|
73 | // Stos jest pusty. Mozemy dodac do niego wierzcholek poczatkowy. |
---|
74 | if (path.empty()) { |
---|
75 | path.push_back(getStateInfo(s, fst::kNoStateId, 0)); |
---|
76 | } |
---|
77 | while(!path.empty()) { |
---|
78 | |
---|
79 | // Zdejmujemy ze stosu stan i jego iterator: |
---|
80 | StateInfo *state = &path.back(); |
---|
81 | ArcsIt *ait = state->it; |
---|
82 | |
---|
83 | // Jezeli stan jest koncowy to zwracamy sciezke do stanu "s" |
---|
84 | // Dodatkowo sprawdzamy czy juz nie startowalismy z tego stanu, aby nie wyswietlac wielokrotnie tego samego |
---|
85 | if (!state->checked && accept(state->id)) { |
---|
86 | state->checked = true; |
---|
87 | StateInfo tState; |
---|
88 | PathRevIt pit=path.rbegin(); |
---|
89 | State prevId = pit->id; |
---|
90 | result->clear(); |
---|
91 | for(; pit!=path.rend(); ++pit) { |
---|
92 | tState = (*pit); |
---|
93 | if (tState.id == prevId && tState.prev!=fst::kNoStateId && tState.id !=s) { |
---|
94 | ArcsIt *tArcIt = tState.it; |
---|
95 | result->push_front(tState.symbol); |
---|
96 | } |
---|
97 | if (tState.prev==fst::kNoStateId) break; |
---|
98 | prevId = tState.prev; |
---|
99 | } |
---|
100 | ait->Next(); |
---|
101 | return path.size(); |
---|
102 | } |
---|
103 | |
---|
104 | |
---|
105 | // Skonczylismy sprawdzac dany iterator (stan). |
---|
106 | // Dlatego mozemy go usunac ze stosu. |
---|
107 | if (ait->Done()) { |
---|
108 | path.pop_back(); |
---|
109 | // Jezeli jakies wierzcholki sa jeszcze na stosie to kontynuuj: |
---|
110 | if (path.size() > 0) continue; |
---|
111 | // w.p.p zakoncz. |
---|
112 | else return 0; |
---|
113 | } |
---|
114 | |
---|
115 | |
---|
116 | // Odwiedzamy stan. |
---|
117 | // Dodajemy jego nastepnikow: |
---|
118 | for(; !ait->Done(); ait->Next()) { |
---|
119 | State next = ait->Value().nextstate; |
---|
120 | Char isymbol = ait->Value().ilabel; |
---|
121 | path.push_back(getStateInfo(next, state->id, isymbol)); |
---|
122 | } |
---|
123 | } // Koniec (while(!path.empty()) |
---|
124 | |
---|
125 | |
---|
126 | |
---|
127 | return 0; |
---|
128 | } |
---|
129 | |
---|
130 | |
---|
131 | /** Zwraca strukture StateInfo uzupelniajac ja o dane |
---|
132 | * Parametry: |
---|
133 | * s - ktory stan opisujemy |
---|
134 | * prev - poprzednik stanu w automacie |
---|
135 | * isymbol - symbol po jakim dostalismy sie z 'prev' do 's' |
---|
136 | */ |
---|
137 | inline const LemFST::StateInfo LemFST::getStateInfo(State s, State prev, Char isymbol) { |
---|
138 | StateInfo sInfo; |
---|
139 | sInfo.id = s; |
---|
140 | sInfo.it = new ArcsIt(*fst, s); //Wyciagamy iterator z automatu |
---|
141 | sInfo.symbol = isymbol; |
---|
142 | sInfo.prev = prev; |
---|
143 | sInfo.checked = false; // Czy stan byl juz sprawdzany jako koncowy |
---|
144 | return sInfo; |
---|
145 | } |
---|
146 | |
---|
147 | |
---|