[5f4d9c3] | 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 | |
---|