#include <cstdio>
#include "openfst/lib/vector-fst.h"
#include "openfst/lib/compose.h"
#include "openfst/lib/determinize.h"
#include "openfst/lib/minimize.h"
#include "openfst/lib/rmepsilon.h"
#include "openfst/lib/arcsort.h"
#include "openfst/lib/connect.h"
using namespace fst;
using Fst_ = VectorFst<StdArc>;
using W = TropicalWeight;
static Fst_ grammar() {
Fst_ g; g.AddState(); g.SetStart(0); g.SetFinal(0, W::One());
g.AddArc(0, StdArc(1, 1, W(1.0), 0)); g.AddArc(0, StdArc(2, 2, W(2.0), 0)); g.AddArc(0, StdArc(3, 3, W(1.5), 0)); g.AddArc(0, StdArc(4, 4, W(0.5), 0)); g.AddArc(0, StdArc(5, 5, W(0.25), 0)); return g;
}
static Fst_ lexicon() {
Fst_ l; for (int i = 0; i < 15; ++i) l.AddState();
l.SetStart(0); l.SetFinal(0, W::One());
l.AddArc(0, StdArc(1, 1, W::One(), 1));
l.AddArc(1, StdArc(2, 0, W::One(), 2));
l.AddArc(2, StdArc(3, 0, W::One(), 0));
l.AddArc(0, StdArc(1, 2, W::One(), 3));
l.AddArc(3, StdArc(2, 0, W::One(), 4));
l.AddArc(4, StdArc(4, 0, W::One(), 5));
l.AddArc(5, StdArc(5, 0, W::One(), 0));
l.AddArc(0, StdArc(1, 3, W::One(), 6));
l.AddArc(6, StdArc(2, 0, W::One(), 7));
l.AddArc(7, StdArc(4, 0, W::One(), 8));
l.AddArc(8, StdArc(3, 0, W::One(), 0));
l.AddArc(0, StdArc(3, 4, W::One(), 9));
l.AddArc(9, StdArc(6, 0, W::One(), 10));
l.AddArc(10, StdArc(7, 0, W::One(), 0));
l.AddArc(0, StdArc(3, 5, W::One(), 12));
l.AddArc(12, StdArc(6, 0, W::One(), 13));
l.AddArc(13, StdArc(8, 0, W::One(), 0));
return l;
}
static Fst_ hmm() {
Fst_ h; h.AddState(); h.SetStart(0); h.SetFinal(0, W::One());
for (int p : {1, 2, 3, 4, 6}) {
const int s = h.AddState();
h.AddArc(0, StdArc(10 * p + 1, p, W::One(), s));
h.AddArc(s, StdArc(10 * p + 2, 0, W::One(), 0));
}
for (int d : {5, 7, 8}) h.AddArc(0, StdArc(d, d, W::One(), 0)); return h;
}
static void show(const char* name, const Fst_& f) {
int arcs = 0;
for (StateIterator<Fst_> s(f); !s.Done(); s.Next()) arcs += f.NumArcs(s.Value());
printf("%-6s %d states %d arcs\n", name, f.NumStates(), arcs);
}
int main(int argc, char** argv) {
Fst_ g = grammar(), l = lexicon(), h = hmm();
show("G", g); show("L", l); show("H", h);
ArcSort(&l, OLabelCompare<StdArc>());
Fst_ lg; Compose(l, g, &lg); show("L.G", lg);
RmEpsilon(&lg); show("rmeps", lg);
Fst_ dlg; Determinize(lg, &dlg); show("det", dlg);
ArcSort(&h, OLabelCompare<StdArc>());
ArcSort(&dlg, ILabelCompare<StdArc>());
Fst_ hlg; Compose(h, dlg, &hlg); show("H.LG", hlg);
RmEpsilon(&hlg);
Fst_ dhlg; Determinize(hlg, &dhlg); show("det", dhlg);
Minimize(&dhlg); show("min", dhlg);
Connect(&dhlg); show("HLG", dhlg);
if (argc > 1 && !dhlg.Write(argv[1])) return 1;
return 0;
}