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.

152 lines
5.0 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. #ifndef FST_SCRIPT_SHORTEST_PATH_H_
  18. #define FST_SCRIPT_SHORTEST_PATH_H_
  19. #include <cstdint>
  20. #include <memory>
  21. #include <tuple>
  22. #include <vector>
  23. #include <fst/log.h>
  24. #include <fst/arcfilter.h>
  25. #include <fst/fst.h>
  26. #include <fst/mutable-fst.h>
  27. #include <fst/properties.h>
  28. #include <fst/queue.h>
  29. #include <fst/shortest-path.h>
  30. #include <fst/util.h>
  31. #include <fst/weight.h>
  32. #include <fst/script/arcfilter-impl.h>
  33. #include <fst/script/fst-class.h>
  34. #include <fst/script/shortest-distance.h>
  35. #include <fst/script/weight-class.h>
  36. namespace fst {
  37. namespace script {
  38. // Slightly simplified interface: `has_distance` and `first_path` are disabled.
  39. struct ShortestPathOptions : public ShortestDistanceOptions {
  40. const int32_t nshortest;
  41. const bool unique;
  42. const WeightClass &weight_threshold;
  43. const int64_t state_threshold;
  44. ShortestPathOptions(QueueType queue_type, int32_t nshortest, bool unique,
  45. float delta, const WeightClass &weight_threshold,
  46. int64_t state_threshold = kNoStateId)
  47. : ShortestDistanceOptions(queue_type, ArcFilterType::ANY, kNoStateId,
  48. delta),
  49. nshortest(nshortest),
  50. unique(unique),
  51. weight_threshold(weight_threshold),
  52. state_threshold(state_threshold) {}
  53. };
  54. namespace internal {
  55. // Code to implement switching on queue types.
  56. template <class Arc, class Queue>
  57. void ShortestPath(const Fst<Arc> &ifst, MutableFst<Arc> *ofst,
  58. std::vector<typename Arc::Weight> *distance,
  59. const ShortestPathOptions &opts) {
  60. using ArcFilter = AnyArcFilter<Arc>;
  61. using Weight = typename Arc::Weight;
  62. if constexpr (IsPath<Weight>::value) {
  63. const std::unique_ptr<Queue> queue(
  64. QueueConstructor<Arc, Queue, ArcFilter>::Construct(ifst, distance));
  65. const fst::ShortestPathOptions<Arc, Queue, ArcFilter> sopts(
  66. queue.get(), ArcFilter(), opts.nshortest, opts.unique,
  67. /* has_distance=*/false, opts.delta, /* first_path=*/false,
  68. *opts.weight_threshold.GetWeight<Weight>(), opts.state_threshold);
  69. ShortestPath(ifst, ofst, distance, sopts);
  70. } else {
  71. FSTERROR() << "ShortestPath: Weight needs to have the path property: "
  72. << Arc::Weight::Type();
  73. ofst->SetProperties(kError, kError);
  74. }
  75. }
  76. template <class Arc>
  77. void ShortestPath(const Fst<Arc> &ifst, MutableFst<Arc> *ofst,
  78. const ShortestPathOptions &opts) {
  79. using StateId = typename Arc::StateId;
  80. using Weight = typename Arc::Weight;
  81. std::vector<Weight> distance;
  82. switch (opts.queue_type) {
  83. case AUTO_QUEUE: {
  84. ShortestPath<Arc, AutoQueue<StateId>>(ifst, ofst, &distance, opts);
  85. return;
  86. }
  87. case FIFO_QUEUE: {
  88. ShortestPath<Arc, FifoQueue<StateId>>(ifst, ofst, &distance, opts);
  89. return;
  90. }
  91. case LIFO_QUEUE: {
  92. ShortestPath<Arc, LifoQueue<StateId>>(ifst, ofst, &distance, opts);
  93. return;
  94. }
  95. case SHORTEST_FIRST_QUEUE: {
  96. if constexpr (IsIdempotent<Weight>::value) {
  97. ShortestPath<Arc, NaturalShortestFirstQueue<StateId, Weight>>(
  98. ifst, ofst, &distance, opts);
  99. } else {
  100. FSTERROR() << "ShortestPath: Bad queue type SHORTEST_FIRST_QUEUE for"
  101. << " non-idempotent Weight " << Weight::Type();
  102. ofst->SetProperties(kError, kError);
  103. }
  104. return;
  105. }
  106. case STATE_ORDER_QUEUE: {
  107. ShortestPath<Arc, StateOrderQueue<StateId>>(ifst, ofst, &distance, opts);
  108. return;
  109. }
  110. case TOP_ORDER_QUEUE: {
  111. ShortestPath<Arc, TopOrderQueue<StateId>>(ifst, ofst, &distance, opts);
  112. return;
  113. }
  114. default: {
  115. FSTERROR() << "ShortestPath: Unknown queue type: " << opts.queue_type;
  116. ofst->SetProperties(kError, kError);
  117. return;
  118. }
  119. }
  120. }
  121. } // namespace internal
  122. using FstShortestPathArgs = std::tuple<const FstClass &, MutableFstClass *,
  123. const ShortestPathOptions &>;
  124. template <class Arc>
  125. void ShortestPath(FstShortestPathArgs *args) {
  126. const Fst<Arc> &ifst = *std::get<0>(*args).GetFst<Arc>();
  127. MutableFst<Arc> *ofst = std::get<1>(*args)->GetMutableFst<Arc>();
  128. const ShortestPathOptions &opts = std::get<2>(*args);
  129. internal::ShortestPath(ifst, ofst, opts);
  130. }
  131. void ShortestPath(const FstClass &ifst, MutableFstClass *ofst,
  132. const ShortestPathOptions &opts);
  133. } // namespace script
  134. } // namespace fst
  135. #endif // FST_SCRIPT_SHORTEST_PATH_H_