You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

637 lines
20 KiB

  1. // Copyright 2005-2024 Google LLC
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the 'License');
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an 'AS IS' BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. //
  15. // See www.openfst.org for extensive documentation on this weighted
  16. // finite-state transducer library.
  17. //
  18. // Class to encode and decode an FST.
  19. #ifndef FST_ENCODE_H_
  20. #define FST_ENCODE_H_
  21. #include <climits>
  22. #include <cstddef>
  23. #include <cstdint>
  24. #include <ios>
  25. #include <iostream>
  26. #include <istream>
  27. #include <memory>
  28. #include <ostream>
  29. #include <string>
  30. #include <utility>
  31. #include <vector>
  32. #include <fst/log.h>
  33. #include <fst/arc-map.h>
  34. #include <fst/arc.h>
  35. #include <fst/cache.h>
  36. #include <fstream>
  37. #include <fst/float-weight.h>
  38. #include <fst/fst.h>
  39. #include <fst/impl-to-fst.h>
  40. #include <fst/mutable-fst.h>
  41. #include <fst/properties.h>
  42. #include <fst/rmfinalepsilon.h>
  43. #include <fst/symbol-table.h>
  44. #include <fst/util.h>
  45. #include <unordered_map>
  46. #include <string_view>
  47. namespace fst {
  48. enum EncodeType { ENCODE = 1, DECODE = 2 };
  49. inline constexpr uint8_t kEncodeLabels = 0x01;
  50. inline constexpr uint8_t kEncodeWeights = 0x02;
  51. inline constexpr uint8_t kEncodeFlags = 0x03;
  52. namespace internal {
  53. // Bits storing whether or not an encode table has input and/or output symbol
  54. // tables, for internal use only.
  55. inline constexpr uint8_t kEncodeHasISymbols = 0x04;
  56. inline constexpr uint8_t kEncodeHasOSymbols = 0x08;
  57. // Identifies stream data as an encode table (and its endianity).
  58. inline constexpr int32_t kEncodeMagicNumber = 2128178506;
  59. // TODO(b/141172858): deprecated, remove by 2020-01-01.
  60. inline constexpr int32_t kEncodeDeprecatedMagicNumber = 2129983209;
  61. } // namespace internal
  62. // Header for the encoder table.
  63. class EncodeTableHeader {
  64. public:
  65. EncodeTableHeader() = default;
  66. // Getters.
  67. const std::string &ArcType() const { return arctype_; }
  68. uint8_t Flags() const { return flags_; }
  69. size_t Size() const { return size_; }
  70. // Setters.
  71. void SetArcType(std::string_view arctype) {
  72. arctype_ = std::string(arctype);
  73. }
  74. void SetFlags(uint8_t flags) { flags_ = flags; }
  75. void SetSize(size_t size) { size_ = size; }
  76. // IO.
  77. bool Read(std::istream &strm, std::string_view source);
  78. bool Write(std::ostream &strm, std::string_view source) const;
  79. private:
  80. std::string arctype_;
  81. uint8_t flags_;
  82. size_t size_;
  83. };
  84. namespace internal {
  85. // The following class encapsulates implementation details for the encoding and
  86. // decoding of label/weight triples used for encoding and decoding of FSTs. The
  87. // EncodeTable is bidirectional, i.e, it stores both the Triple of encode labels
  88. // and weights to a unique label, and the reverse.
  89. template <class Arc>
  90. class EncodeTable {
  91. public:
  92. using Label = typename Arc::Label;
  93. using Weight = typename Arc::Weight;
  94. // Encoded data consists of arc input/output labels and arc weight.
  95. struct Triple {
  96. Triple() = default;
  97. Triple(Label ilabel, Label olabel, Weight weight)
  98. : ilabel(ilabel), olabel(olabel), weight(std::move(weight)) {}
  99. // Constructs from arc and flags.
  100. Triple(const Arc &arc, uint8_t flags)
  101. : ilabel(arc.ilabel),
  102. olabel(flags & kEncodeLabels ? arc.olabel : 0),
  103. weight(flags & kEncodeWeights ? arc.weight : Weight::One()) {}
  104. static std::unique_ptr<Triple> Read(std::istream &strm) {
  105. auto triple = std::make_unique<Triple>();
  106. ReadType(strm, &triple->ilabel);
  107. ReadType(strm, &triple->olabel);
  108. ReadType(strm, &triple->weight);
  109. return triple;
  110. }
  111. void Write(std::ostream &strm) const {
  112. WriteType(strm, ilabel);
  113. WriteType(strm, olabel);
  114. WriteType(strm, weight);
  115. }
  116. // Exploited below for TripleEqual functor.
  117. bool operator==(const Triple &other) const {
  118. return (ilabel == other.ilabel && olabel == other.olabel &&
  119. weight == other.weight);
  120. }
  121. Label ilabel;
  122. Label olabel;
  123. Weight weight;
  124. };
  125. // Equality functor for two Triple pointers.
  126. struct TripleEqual {
  127. bool operator()(const Triple *x, const Triple *y) const { return *x == *y; }
  128. };
  129. // Hash functor for one Triple pointer.
  130. class TripleHash {
  131. public:
  132. explicit TripleHash(uint8_t flags) : flags_(flags) {}
  133. size_t operator()(const Triple *triple) const {
  134. size_t hash = triple->ilabel;
  135. static constexpr int lshift = 5;
  136. static constexpr int rshift = CHAR_BIT * sizeof(size_t) - 5;
  137. if (flags_ & kEncodeLabels) {
  138. hash = hash << lshift ^ hash >> rshift ^ triple->olabel;
  139. }
  140. if (flags_ & kEncodeWeights) {
  141. hash = hash << lshift ^ hash >> rshift ^ triple->weight.Hash();
  142. }
  143. return hash;
  144. }
  145. private:
  146. uint8_t flags_;
  147. };
  148. explicit EncodeTable(uint8_t flags)
  149. : flags_(flags), triple2label_(1024, TripleHash(flags)) {}
  150. // Given an arc, encodes either input/output labels or input/costs or both.
  151. Label Encode(const Arc &arc) {
  152. // Encoding weights of a weighted superfinal transition could result in
  153. // a clash with a true epsilon arc; to avoid this we hallucinate kNoLabel
  154. // labels instead.
  155. if (arc.nextstate == kNoStateId && (flags_ & kEncodeWeights)) {
  156. return Encode(std::make_unique<Triple>(kNoLabel, kNoLabel, arc.weight));
  157. } else {
  158. return Encode(std::make_unique<Triple>(arc, flags_));
  159. }
  160. }
  161. // Given an encoded arc label, decodes back to input/output labels and costs.
  162. const Triple *Decode(Label label) const {
  163. if (label < 1 || label > triples_.size()) {
  164. LOG(ERROR) << "EncodeTable::Decode: Unknown decode label: " << label;
  165. return nullptr;
  166. }
  167. return triples_[label - 1].get();
  168. }
  169. size_t Size() const { return triples_.size(); }
  170. static EncodeTable *Read(std::istream &strm, std::string_view source);
  171. bool Write(std::ostream &strm, std::string_view source) const;
  172. // This is masked to hide internal-only isymbol and osymbol bits.
  173. uint8_t Flags() const { return flags_ & kEncodeFlags; }
  174. const SymbolTable *InputSymbols() const { return isymbols_.get(); }
  175. const SymbolTable *OutputSymbols() const { return osymbols_.get(); }
  176. void SetInputSymbols(const SymbolTable *syms) {
  177. if (syms) {
  178. isymbols_.reset(syms->Copy());
  179. flags_ |= kEncodeHasISymbols;
  180. } else {
  181. isymbols_.reset();
  182. flags_ &= ~kEncodeHasISymbols;
  183. }
  184. }
  185. void SetOutputSymbols(const SymbolTable *syms) {
  186. if (syms) {
  187. osymbols_.reset(syms->Copy());
  188. flags_ |= kEncodeHasOSymbols;
  189. } else {
  190. osymbols_.reset();
  191. flags_ &= ~kEncodeHasOSymbols;
  192. }
  193. }
  194. private:
  195. Label Encode(std::unique_ptr<Triple> triple) {
  196. auto insert_result =
  197. triple2label_.emplace(triple.get(), triples_.size() + 1);
  198. if (insert_result.second) triples_.push_back(std::move(triple));
  199. return insert_result.first->second;
  200. }
  201. uint8_t flags_;
  202. std::vector<std::unique_ptr<Triple>> triples_;
  203. std::unordered_map<const Triple *, Label, TripleHash, TripleEqual>
  204. triple2label_;
  205. std::unique_ptr<SymbolTable> isymbols_;
  206. std::unique_ptr<SymbolTable> osymbols_;
  207. EncodeTable(const EncodeTable &) = delete;
  208. EncodeTable &operator=(const EncodeTable &) = delete;
  209. };
  210. template <class Arc>
  211. EncodeTable<Arc> *EncodeTable<Arc>::Read(std::istream &strm,
  212. std::string_view source) {
  213. EncodeTableHeader hdr;
  214. if (!hdr.Read(strm, source)) return nullptr;
  215. const auto flags = hdr.Flags();
  216. const auto size = hdr.Size();
  217. auto table = std::make_unique<EncodeTable>(flags);
  218. for (int64_t i = 0; i < size; ++i) {
  219. table->triples_.emplace_back(std::move(Triple::Read(strm)));
  220. table->triple2label_[table->triples_.back().get()] = table->triples_.size();
  221. }
  222. if (flags & kEncodeHasISymbols) {
  223. table->isymbols_.reset(SymbolTable::Read(strm, source));
  224. }
  225. if (flags & kEncodeHasOSymbols) {
  226. table->osymbols_.reset(SymbolTable::Read(strm, source));
  227. }
  228. if (!strm) {
  229. LOG(ERROR) << "EncodeTable::Read: Read failed: " << source;
  230. return nullptr;
  231. }
  232. return table.release();
  233. }
  234. template <class Arc>
  235. bool EncodeTable<Arc>::Write(std::ostream &strm,
  236. std::string_view source) const {
  237. EncodeTableHeader hdr;
  238. hdr.SetArcType(Arc::Type());
  239. hdr.SetFlags(flags_); // Real flags, not masked ones.
  240. hdr.SetSize(Size());
  241. if (!hdr.Write(strm, source)) return false;
  242. for (const auto &triple : triples_) triple->Write(strm);
  243. if (flags_ & kEncodeHasISymbols) isymbols_->Write(strm);
  244. if (flags_ & kEncodeHasOSymbols) osymbols_->Write(strm);
  245. strm.flush();
  246. if (!strm) {
  247. LOG(ERROR) << "EncodeTable::Write: Write failed: " << source;
  248. return false;
  249. }
  250. return true;
  251. }
  252. } // namespace internal
  253. // A mapper to encode/decode weighted transducers. Encoding of an FST is used
  254. // for performing classical determinization or minimization on a weighted
  255. // transducer viewing it as an unweighted acceptor over encoded labels.
  256. //
  257. // The mapper stores the encoding in a local hash table (EncodeTable). This
  258. // table is shared (and reference-counted) between the encoder and decoder.
  259. // A decoder has read-only access to the EncodeTable.
  260. //
  261. // The EncodeMapper allows on the fly encoding of the machine. As the
  262. // EncodeTable is generated the same table may by used to decode the machine
  263. // on the fly. For example in the following sequence of operations
  264. //
  265. // Encode -> Determinize -> Decode
  266. //
  267. // we will use the encoding table generated during the encode step in the
  268. // decode, even though the encoding is not complete.
  269. template <class Arc>
  270. class EncodeMapper {
  271. using Label = typename Arc::Label;
  272. using Weight = typename Arc::Weight;
  273. public:
  274. explicit EncodeMapper(uint8_t flags, EncodeType type = ENCODE)
  275. : flags_(flags),
  276. type_(type),
  277. table_(std::make_shared<internal::EncodeTable<Arc>>(flags)),
  278. error_(false) {}
  279. EncodeMapper(const EncodeMapper &mapper)
  280. : flags_(mapper.flags_),
  281. type_(mapper.type_),
  282. table_(mapper.table_),
  283. error_(false) {}
  284. // Copy constructor but setting the type, typically to DECODE.
  285. EncodeMapper(const EncodeMapper &mapper, EncodeType type)
  286. : flags_(mapper.flags_),
  287. type_(type),
  288. table_(mapper.table_),
  289. error_(mapper.error_) {}
  290. Arc operator()(const Arc &arc);
  291. MapFinalAction FinalAction() const {
  292. return (type_ == ENCODE && (flags_ & kEncodeWeights))
  293. ? MAP_REQUIRE_SUPERFINAL
  294. : MAP_NO_SUPERFINAL;
  295. }
  296. constexpr MapSymbolsAction InputSymbolsAction() const {
  297. return MAP_CLEAR_SYMBOLS;
  298. }
  299. constexpr MapSymbolsAction OutputSymbolsAction() const {
  300. return MAP_CLEAR_SYMBOLS;
  301. }
  302. uint8_t Flags() const { return flags_; }
  303. uint64_t Properties(uint64_t inprops) {
  304. uint64_t outprops = inprops;
  305. if (error_) outprops |= kError;
  306. uint64_t mask = kFstProperties;
  307. if (flags_ & kEncodeLabels) {
  308. mask &= kILabelInvariantProperties & kOLabelInvariantProperties;
  309. }
  310. if (flags_ & kEncodeWeights) {
  311. mask &= kILabelInvariantProperties & kWeightInvariantProperties &
  312. (type_ == ENCODE ? kAddSuperFinalProperties
  313. : kRmSuperFinalProperties);
  314. }
  315. if (type_ == ENCODE) mask |= kIDeterministic;
  316. outprops &= mask;
  317. if (type_ == ENCODE) {
  318. if (flags_ & kEncodeLabels) {
  319. outprops |= kAcceptor;
  320. }
  321. if (flags_ & kEncodeWeights) {
  322. outprops |= kUnweighted | kUnweightedCycles;
  323. }
  324. }
  325. return outprops;
  326. }
  327. EncodeType Type() const { return type_; }
  328. static EncodeMapper *Read(std::istream &strm, std::string_view source,
  329. EncodeType type = ENCODE) {
  330. auto *table = internal::EncodeTable<Arc>::Read(strm, source);
  331. return table ? new EncodeMapper(table->Flags(), type, table) : nullptr;
  332. }
  333. static EncodeMapper *Read(std::string_view source,
  334. EncodeType type = ENCODE) {
  335. std::ifstream strm(std::string(source),
  336. std::ios_base::in | std::ios_base::binary);
  337. if (!strm) {
  338. LOG(ERROR) << "EncodeMapper: Can't open file: " << source;
  339. return nullptr;
  340. }
  341. return Read(strm, source, type);
  342. }
  343. bool Write(std::ostream &strm, std::string_view source) const {
  344. return table_->Write(strm, source);
  345. }
  346. bool Write(std::string_view source) const {
  347. std::ofstream strm(std::string(source),
  348. std::ios_base::out | std::ios_base::binary);
  349. if (!strm) {
  350. LOG(ERROR) << "EncodeMapper: Can't open file: " << source;
  351. return false;
  352. }
  353. return Write(strm, source);
  354. }
  355. const SymbolTable *InputSymbols() const { return table_->InputSymbols(); }
  356. const SymbolTable *OutputSymbols() const { return table_->OutputSymbols(); }
  357. void SetInputSymbols(const SymbolTable *syms) {
  358. table_->SetInputSymbols(syms);
  359. }
  360. void SetOutputSymbols(const SymbolTable *syms) {
  361. table_->SetOutputSymbols(syms);
  362. }
  363. private:
  364. uint8_t flags_;
  365. EncodeType type_;
  366. std::shared_ptr<internal::EncodeTable<Arc>> table_;
  367. bool error_;
  368. explicit EncodeMapper(uint8_t flags, EncodeType type,
  369. internal::EncodeTable<Arc> *table)
  370. : flags_(flags), type_(type), table_(table), error_(false) {}
  371. EncodeMapper &operator=(const EncodeMapper &) = delete;
  372. };
  373. template <class Arc>
  374. Arc EncodeMapper<Arc>::operator()(const Arc &arc) {
  375. if (type_ == ENCODE) {
  376. // If this arc is a hallucinated final state, and we're either not encoding
  377. // weights, or we're encoding weights but this is non-final, we use an
  378. // identity-encoding.
  379. if (arc.nextstate == kNoStateId &&
  380. ((!(flags_ & kEncodeWeights) ||
  381. ((flags_ & kEncodeWeights) && arc.weight == Weight::Zero())))) {
  382. return arc;
  383. } else {
  384. const auto label = table_->Encode(arc);
  385. return Arc(label, flags_ & kEncodeLabels ? label : arc.olabel,
  386. flags_ & kEncodeWeights ? Weight::One() : arc.weight,
  387. arc.nextstate);
  388. }
  389. } else { // type_ == DECODE
  390. if (arc.nextstate == kNoStateId) {
  391. return arc;
  392. } else {
  393. if (arc.ilabel == 0) return arc;
  394. if (flags_ & kEncodeLabels && arc.ilabel != arc.olabel) {
  395. FSTERROR() << "EncodeMapper: Label-encoded arc has different "
  396. "input and output labels";
  397. error_ = true;
  398. }
  399. if (flags_ & kEncodeWeights && arc.weight != Weight::One()) {
  400. FSTERROR() << "EncodeMapper: Weight-encoded arc has non-trivial weight";
  401. error_ = true;
  402. }
  403. const auto triple = table_->Decode(arc.ilabel);
  404. if (!triple) {
  405. FSTERROR() << "EncodeMapper: Decode failed";
  406. error_ = true;
  407. return Arc(kNoLabel, kNoLabel, Weight::NoWeight(), arc.nextstate);
  408. } else if (triple->ilabel == kNoLabel) {
  409. // Hallucinated kNoLabel from a weighted superfinal transition.
  410. return Arc(0, 0, triple->weight, arc.nextstate);
  411. } else {
  412. return Arc(triple->ilabel,
  413. flags_ & kEncodeLabels ? triple->olabel : arc.olabel,
  414. flags_ & kEncodeWeights ? triple->weight : arc.weight,
  415. arc.nextstate);
  416. }
  417. }
  418. }
  419. }
  420. // Complexity: O(E + V).
  421. template <class Arc>
  422. inline void Encode(MutableFst<Arc> *fst, EncodeMapper<Arc> *mapper) {
  423. mapper->SetInputSymbols(fst->InputSymbols());
  424. mapper->SetOutputSymbols(fst->OutputSymbols());
  425. ArcMap(fst, mapper);
  426. }
  427. template <class Arc>
  428. inline void Decode(MutableFst<Arc> *fst, const EncodeMapper<Arc> &mapper) {
  429. ArcMap(fst, EncodeMapper<Arc>(mapper, DECODE));
  430. RmFinalEpsilon(fst);
  431. fst->SetInputSymbols(mapper.InputSymbols());
  432. fst->SetOutputSymbols(mapper.OutputSymbols());
  433. }
  434. // On-the-fly encoding of an input FST.
  435. //
  436. // Complexity:
  437. //
  438. // Construction: O(1)
  439. // Traversal: O(e + v)
  440. //
  441. // where e is the number of arcs visited and v is the number of states visited.
  442. // Constant time and space to visit an input state or arc is assumed and
  443. // exclusive of caching.
  444. template <class Arc>
  445. class EncodeFst : public ArcMapFst<Arc, Arc, EncodeMapper<Arc>> {
  446. public:
  447. using Mapper = EncodeMapper<Arc>;
  448. using Impl = internal::ArcMapFstImpl<Arc, Arc, Mapper>;
  449. EncodeFst(const Fst<Arc> &fst, Mapper *encoder)
  450. : ArcMapFst<Arc, Arc, Mapper>(fst, encoder, ArcMapFstOptions()) {
  451. encoder->SetInputSymbols(fst.InputSymbols());
  452. encoder->SetOutputSymbols(fst.OutputSymbols());
  453. }
  454. EncodeFst(const Fst<Arc> &fst, const Mapper &encoder)
  455. : ArcMapFst<Arc, Arc, Mapper>(fst, encoder, ArcMapFstOptions()) {}
  456. // See Fst<>::Copy() for doc.
  457. EncodeFst(const EncodeFst &fst, bool copy = false)
  458. : ArcMapFst<Arc, Arc, Mapper>(fst, copy) {}
  459. // Makes a copy of this EncodeFst. See Fst<>::Copy() for further doc.
  460. EncodeFst *Copy(bool safe = false) const override {
  461. if (safe) {
  462. FSTERROR() << "EncodeFst::Copy(true): Not allowed";
  463. GetImpl()->SetProperties(kError, kError);
  464. }
  465. return new EncodeFst(*this);
  466. }
  467. private:
  468. using ImplToFst<Impl>::GetImpl;
  469. using ImplToFst<Impl>::GetMutableImpl;
  470. };
  471. // On-the-fly decoding of an input FST.
  472. //
  473. // Complexity:
  474. //
  475. // Construction: O(1).
  476. // Traversal: O(e + v)
  477. //
  478. // Constant time and space to visit an input state or arc is assumed and
  479. // exclusive of caching.
  480. template <class Arc>
  481. class DecodeFst : public ArcMapFst<Arc, Arc, EncodeMapper<Arc>> {
  482. public:
  483. using Mapper = EncodeMapper<Arc>;
  484. using Impl = internal::ArcMapFstImpl<Arc, Arc, Mapper>;
  485. DecodeFst(const Fst<Arc> &fst, const Mapper &encoder)
  486. : ArcMapFst<Arc, Arc, Mapper>(fst, Mapper(encoder, DECODE),
  487. ArcMapFstOptions()) {
  488. GetMutableImpl()->SetInputSymbols(encoder.InputSymbols());
  489. GetMutableImpl()->SetOutputSymbols(encoder.OutputSymbols());
  490. }
  491. // See Fst<>::Copy() for doc.
  492. DecodeFst(const DecodeFst &fst, bool safe = false)
  493. : ArcMapFst<Arc, Arc, Mapper>(fst, safe) {}
  494. // Makes a copy of this DecodeFst. See Fst<>::Copy() for further doc.
  495. DecodeFst *Copy(bool safe = false) const override {
  496. return new DecodeFst(*this, safe);
  497. }
  498. private:
  499. using ImplToFst<Impl>::GetImpl;
  500. using ImplToFst<Impl>::GetMutableImpl;
  501. };
  502. // Specialization for EncodeFst.
  503. template <class Arc>
  504. class StateIterator<EncodeFst<Arc>>
  505. : public StateIterator<ArcMapFst<Arc, Arc, EncodeMapper<Arc>>> {
  506. public:
  507. explicit StateIterator(const EncodeFst<Arc> &fst)
  508. : StateIterator<ArcMapFst<Arc, Arc, EncodeMapper<Arc>>>(fst) {}
  509. };
  510. // Specialization for EncodeFst.
  511. template <class Arc>
  512. class ArcIterator<EncodeFst<Arc>>
  513. : public ArcIterator<ArcMapFst<Arc, Arc, EncodeMapper<Arc>>> {
  514. public:
  515. ArcIterator(const EncodeFst<Arc> &fst, typename Arc::StateId s)
  516. : ArcIterator<ArcMapFst<Arc, Arc, EncodeMapper<Arc>>>(fst, s) {}
  517. };
  518. // Specialization for DecodeFst.
  519. template <class Arc>
  520. class StateIterator<DecodeFst<Arc>>
  521. : public StateIterator<ArcMapFst<Arc, Arc, EncodeMapper<Arc>>> {
  522. public:
  523. explicit StateIterator(const DecodeFst<Arc> &fst)
  524. : StateIterator<ArcMapFst<Arc, Arc, EncodeMapper<Arc>>>(fst) {}
  525. };
  526. // Specialization for DecodeFst.
  527. template <class Arc>
  528. class ArcIterator<DecodeFst<Arc>>
  529. : public ArcIterator<ArcMapFst<Arc, Arc, EncodeMapper<Arc>>> {
  530. public:
  531. ArcIterator(const DecodeFst<Arc> &fst, typename Arc::StateId s)
  532. : ArcIterator<ArcMapFst<Arc, Arc, EncodeMapper<Arc>>>(fst, s) {}
  533. };
  534. // Useful aliases when using StdArc.
  535. using StdEncodeFst = EncodeFst<StdArc>;
  536. using StdDecodeFst = DecodeFst<StdArc>;
  537. } // namespace fst
  538. #endif // FST_ENCODE_H_