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.

235 lines
7.3 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 sort arcs in an FST.
  19. #ifndef FST_ARCSORT_H_
  20. #define FST_ARCSORT_H_
  21. #include <sys/types.h>
  22. #include <algorithm>
  23. #include <cstddef>
  24. #include <cstdint>
  25. #include <string>
  26. #include <tuple>
  27. #include <vector>
  28. #include <fst/arc-map.h>
  29. #include <fst/arc.h>
  30. #include <fst/cache.h>
  31. #include <fst/fst.h>
  32. #include <fst/mutable-fst.h>
  33. #include <fst/properties.h>
  34. #include <fst/state-map.h>
  35. namespace fst {
  36. template <class Arc, class Compare>
  37. class ArcSortMapper {
  38. public:
  39. using FromArc = Arc;
  40. using ToArc = Arc;
  41. using StateId = typename Arc::StateId;
  42. using Weight = typename Arc::Weight;
  43. constexpr ArcSortMapper(const Fst<Arc> &fst, const Compare &comp)
  44. : fst_(fst), comp_(comp), i_(0) {}
  45. // Allows updating Fst argument; pass only if changed.
  46. ArcSortMapper(const ArcSortMapper<Arc, Compare> &mapper,
  47. const Fst<Arc> *fst = nullptr)
  48. : fst_(fst ? *fst : mapper.fst_), comp_(mapper.comp_), i_(0) {}
  49. StateId Start() { return fst_.Start(); }
  50. Weight Final(StateId s) const { return fst_.Final(s); }
  51. void SetState(StateId s) {
  52. i_ = 0;
  53. arcs_.clear();
  54. arcs_.reserve(fst_.NumArcs(s));
  55. for (ArcIterator<Fst<Arc>> aiter(fst_, s); !aiter.Done(); aiter.Next()) {
  56. arcs_.push_back(aiter.Value());
  57. }
  58. std::stable_sort(arcs_.begin(), arcs_.end(), comp_);
  59. }
  60. bool Done() const { return i_ >= arcs_.size(); }
  61. const Arc &Value() const { return arcs_[i_]; }
  62. void Next() { ++i_; }
  63. MapSymbolsAction InputSymbolsAction() const { return MAP_COPY_SYMBOLS; }
  64. MapSymbolsAction OutputSymbolsAction() const { return MAP_COPY_SYMBOLS; }
  65. uint64_t Properties(uint64_t props) const { return comp_.Properties(props); }
  66. private:
  67. const Fst<Arc> &fst_;
  68. const Compare &comp_;
  69. std::vector<Arc> arcs_;
  70. ssize_t i_; // current arc position
  71. ArcSortMapper &operator=(const ArcSortMapper &) = delete;
  72. };
  73. // Sorts the arcs in an FST according to function object 'comp' of type Compare.
  74. // This version modifies its input. Comparison function objects ILabelCompare
  75. // and OLabelCompare are provided by the library. In general, Compare must meet
  76. // the requirements for a comparison function object (e.g., similar to those
  77. // used by std::sort). It must also have a member Properties(uint64_t) that
  78. // specifies the known properties of the sorted FST; it takes as argument the
  79. // input FST's known properties before the sort.
  80. //
  81. // Complexity:
  82. //
  83. // - Time: O(v d log d)
  84. // - Space: O(d)
  85. //
  86. // where v = # of states and d = maximum out-degree.
  87. template <class Arc, class Compare>
  88. void ArcSort(MutableFst<Arc> *fst, Compare comp) {
  89. ArcSortMapper<Arc, Compare> mapper(*fst, comp);
  90. StateMap(fst, mapper);
  91. }
  92. using ArcSortFstOptions = CacheOptions;
  93. // Sorts the arcs in an FST according to function object 'comp' of type Compare.
  94. // This version is a delayed FST. Comparsion function objects ILabelCompare and
  95. // OLabelCompare are provided by the library. In general, Compare must meet the
  96. // requirements for a comparision function object (e.g., similar to those
  97. // used by std::sort). It must also have a member Properties(uint64_t) that
  98. // specifies the known properties of the sorted FST; it takes as argument the
  99. // input FST's known properties.
  100. //
  101. // Complexity:
  102. //
  103. // - Time: O(v d log d)
  104. // - Space: O(d)
  105. //
  106. // where v = # of states visited, d = maximum out-degree of states visited.
  107. // Constant time and space to visit an input state is assumed and exclusive of
  108. // caching.
  109. template <class Arc, class Compare>
  110. class ArcSortFst : public StateMapFst<Arc, Arc, ArcSortMapper<Arc, Compare>> {
  111. using StateMapFst<Arc, Arc, ArcSortMapper<Arc, Compare>>::GetImpl;
  112. public:
  113. using StateId = typename Arc::StateId;
  114. using Mapper = ArcSortMapper<Arc, Compare>;
  115. ArcSortFst(const Fst<Arc> &fst, const Compare &comp)
  116. : StateMapFst<Arc, Arc, Mapper>(fst,
  117. ArcSortMapper<Arc, Compare>(fst, comp)) {}
  118. ArcSortFst(const Fst<Arc> &fst, const Compare &comp,
  119. const ArcSortFstOptions &opts)
  120. : StateMapFst<Arc, Arc, Mapper>(fst, Mapper(fst, comp), opts) {}
  121. // See Fst<>::Copy() for doc.
  122. ArcSortFst(const ArcSortFst &fst, bool safe = false)
  123. : StateMapFst<Arc, Arc, Mapper>(fst, safe) {}
  124. // Gets a copy of this ArcSortFst. See Fst<>::Copy() for further doc.
  125. ArcSortFst *Copy(bool safe = false) const override {
  126. return new ArcSortFst(*this, safe);
  127. }
  128. size_t NumArcs(StateId s) const override {
  129. return GetImpl()->GetFst()->NumArcs(s);
  130. }
  131. size_t NumInputEpsilons(StateId s) const override {
  132. return GetImpl()->GetFst()->NumInputEpsilons(s);
  133. }
  134. size_t NumOutputEpsilons(StateId s) const override {
  135. return GetImpl()->GetFst()->NumOutputEpsilons(s);
  136. }
  137. };
  138. // Specialization for ArcSortFst.
  139. template <class Arc, class Compare>
  140. class StateIterator<ArcSortFst<Arc, Compare>>
  141. : public StateIterator<StateMapFst<Arc, Arc, ArcSortMapper<Arc, Compare>>> {
  142. public:
  143. explicit StateIterator(const ArcSortFst<Arc, Compare> &fst)
  144. : StateIterator<StateMapFst<Arc, Arc, ArcSortMapper<Arc, Compare>>>(fst) {
  145. }
  146. };
  147. // Specialization for ArcSortFst.
  148. template <class Arc, class Compare>
  149. class ArcIterator<ArcSortFst<Arc, Compare>>
  150. : public ArcIterator<StateMapFst<Arc, Arc, ArcSortMapper<Arc, Compare>>> {
  151. public:
  152. ArcIterator(const ArcSortFst<Arc, Compare> &fst, typename Arc::StateId s)
  153. : ArcIterator<StateMapFst<Arc, Arc, ArcSortMapper<Arc, Compare>>>(fst,
  154. s) {}
  155. };
  156. // Compare class for comparing input labels of arcs.
  157. template <class Arc>
  158. class ILabelCompare {
  159. public:
  160. constexpr ILabelCompare() = default;
  161. constexpr bool operator()(const Arc &lhs, const Arc &rhs) const {
  162. return std::forward_as_tuple(lhs.ilabel, lhs.olabel) <
  163. std::forward_as_tuple(rhs.ilabel, rhs.olabel);
  164. }
  165. constexpr uint64_t Properties(uint64_t props) const {
  166. return (props & kArcSortProperties) | kILabelSorted |
  167. (props & kAcceptor ? kOLabelSorted : 0);
  168. }
  169. };
  170. // Compare class for comparing output labels of arcs.
  171. template <class Arc>
  172. class OLabelCompare {
  173. public:
  174. constexpr OLabelCompare() = default;
  175. constexpr bool operator()(const Arc &lhs, const Arc &rhs) const {
  176. return std::forward_as_tuple(lhs.olabel, lhs.ilabel) <
  177. std::forward_as_tuple(rhs.olabel, rhs.ilabel);
  178. }
  179. constexpr uint64_t Properties(uint64_t props) const {
  180. return (props & kArcSortProperties) | kOLabelSorted |
  181. (props & kAcceptor ? kILabelSorted : 0);
  182. }
  183. };
  184. // Useful aliases when using StdArc.
  185. template <class Compare>
  186. using StdArcSortFst = ArcSortFst<StdArc, Compare>;
  187. using StdILabelCompare = ILabelCompare<StdArc>;
  188. using StdOLabelCompare = OLabelCompare<StdArc>;
  189. } // namespace fst
  190. #endif // FST_ARCSORT_H_