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.

153 lines
4.9 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. // Functions and classes to compute the concatenative closure of an FST.
  19. #ifndef FST_CLOSURE_H_
  20. #define FST_CLOSURE_H_
  21. #include <algorithm>
  22. #include <vector>
  23. #include <fst/arc.h>
  24. #include <fst/cache.h>
  25. #include <fst/float-weight.h>
  26. #include <fst/fst.h>
  27. #include <fst/impl-to-fst.h>
  28. #include <fst/mutable-fst.h>
  29. #include <fst/properties.h>
  30. #include <fst/rational.h>
  31. namespace fst {
  32. // Computes the concatenative closure. This version modifies its
  33. // MutableFst input. If an FST transduces string x to y with weight a,
  34. // then its closure transduces x to y with weight a, xx to yy with
  35. // weight Times(a, a), xxx to yyy with Times(Times(a, a), a),
  36. // etc. If closure_type == CLOSURE_STAR, then the empty string is
  37. // transduced to itself with weight Weight::One() as well.
  38. //
  39. // Complexity:
  40. //
  41. // Time: O(V)
  42. // Space: O(V)
  43. //
  44. // where V is the number of states.
  45. template <class Arc>
  46. void Closure(MutableFst<Arc> *fst, ClosureType closure_type) {
  47. using Weight = typename Arc::Weight;
  48. const auto props = fst->Properties(kFstProperties, false);
  49. const auto start = fst->Start();
  50. for (StateIterator<MutableFst<Arc>> siter(*fst); !siter.Done();
  51. siter.Next()) {
  52. const auto s = siter.Value();
  53. const auto weight = fst->Final(s);
  54. if (weight != Weight::Zero()) fst->AddArc(s, Arc(0, 0, weight, start));
  55. }
  56. if (closure_type == CLOSURE_STAR) {
  57. fst->ReserveStates(fst->NumStates() + 1);
  58. const auto nstart = fst->AddState();
  59. fst->SetStart(nstart);
  60. fst->SetFinal(nstart);
  61. if (start != kNoStateId) fst->AddArc(nstart, Arc(0, 0, start));
  62. }
  63. fst->SetProperties(ClosureProperties(props, closure_type == CLOSURE_STAR),
  64. kFstProperties);
  65. }
  66. // Computes the concatenative closure. This version modifies its
  67. // RationalFst input.
  68. template <class Arc>
  69. void Closure(RationalFst<Arc> *fst, ClosureType closure_type) {
  70. fst->GetMutableImpl()->AddClosure(closure_type);
  71. }
  72. struct ClosureFstOptions : RationalFstOptions {
  73. ClosureType type;
  74. explicit ClosureFstOptions(const RationalFstOptions &opts,
  75. ClosureType type = CLOSURE_STAR)
  76. : RationalFstOptions(opts), type(type) {}
  77. explicit ClosureFstOptions(ClosureType type = CLOSURE_STAR) : type(type) {}
  78. };
  79. // Computes the concatenative closure. This version is a delayed FST. If an FST
  80. // transduces string x to y with weight a, then its closure transduces x to y
  81. // with weight a, xx to yy with weight Times(a, a), xxx to yyy with weight
  82. // Times(Times(a, a), a), etc. If closure_type == CLOSURE_STAR, then the empty
  83. // string is transduced to itself with weight Weight::One() as well.
  84. //
  85. // Complexity:
  86. //
  87. // Time: O(v)
  88. // Space: O(v)
  89. //
  90. // where v is the number of states visited. Constant time and space to visit an
  91. // input state or arc is assumed and exclusive of caching.
  92. template <class A>
  93. class ClosureFst : public RationalFst<A> {
  94. public:
  95. using Arc = A;
  96. ClosureFst(const Fst<Arc> &fst, ClosureType closure_type) {
  97. GetMutableImpl()->InitClosure(fst, closure_type);
  98. }
  99. ClosureFst(const Fst<Arc> &fst, const ClosureFstOptions &opts)
  100. : RationalFst<A>(opts) {
  101. GetMutableImpl()->InitClosure(fst, opts.type);
  102. }
  103. // See Fst<>::Copy() for doc.
  104. ClosureFst(const ClosureFst &fst, bool safe = false)
  105. : RationalFst<A>(fst, safe) {}
  106. // Gets a copy of this ClosureFst. See Fst<>::Copy() for further doc.
  107. ClosureFst *Copy(bool safe = false) const override {
  108. return new ClosureFst(*this, safe);
  109. }
  110. private:
  111. using ImplToFst<internal::RationalFstImpl<Arc>>::GetImpl;
  112. using ImplToFst<internal::RationalFstImpl<Arc>>::GetMutableImpl;
  113. };
  114. // Specialization for ClosureFst.
  115. template <class Arc>
  116. class StateIterator<ClosureFst<Arc>> : public StateIterator<RationalFst<Arc>> {
  117. public:
  118. explicit StateIterator(const ClosureFst<Arc> &fst)
  119. : StateIterator<RationalFst<Arc>>(fst) {}
  120. };
  121. // Specialization for ClosureFst.
  122. template <class Arc>
  123. class ArcIterator<ClosureFst<Arc>> : public ArcIterator<RationalFst<Arc>> {
  124. public:
  125. using StateId = typename Arc::StateId;
  126. ArcIterator(const ClosureFst<Arc> &fst, StateId s)
  127. : ArcIterator<RationalFst<Arc>>(fst, s) {}
  128. };
  129. // Useful alias when using StdArc.
  130. using StdClosureFst = ClosureFst<StdArc>;
  131. } // namespace fst
  132. #endif // FST_CLOSURE_H_