FST  openfst-1.8.3
OpenFst Library
label-reachable.h
Go to the documentation of this file.
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 determine if a non-epsilon label can be read as the first
19 // non-epsilon symbol along some path from a given state.
20 
21 #ifndef FST_LABEL_REACHABLE_H_
22 #define FST_LABEL_REACHABLE_H_
23 
24 #include <sys/types.h>
25 
26 #include <cstddef>
27 #include <istream>
28 #include <memory>
29 #include <ostream>
30 #include <utility>
31 #include <vector>
32 
33 #include <fst/log.h>
34 #include <fst/accumulator.h>
35 #include <fst/arcsort.h>
36 #include <fst/fst.h>
37 #include <fst/interval-set.h>
38 #include <fst/mutable-fst.h>
39 #include <fst/properties.h>
40 #include <fst/state-reachable.h>
41 #include <fst/util.h>
42 #include <fst/vector-fst.h>
43 #include <unordered_map>
44 
45 namespace fst {
46 
47 // Stores shareable data for label reachable class copies.
48 template <typename Label>
50  public:
53 
54  explicit LabelReachableData(bool reach_input, bool keep_relabel_data = true)
55  : reach_input_(reach_input),
56  keep_relabel_data_(keep_relabel_data),
57  have_relabel_data_(true),
58  final_label_(kNoLabel) {}
59 
60  ~LabelReachableData() = default;
61 
62  bool ReachInput() const { return reach_input_; }
63 
64  std::vector<LabelIntervalSet> *MutableIntervalSets() {
65  return &interval_sets_;
66  }
67 
68  const LabelIntervalSet &GetIntervalSet(int s) const {
69  return interval_sets_[s];
70  }
71 
72  int NumIntervalSets() const { return interval_sets_.size(); }
73 
74  std::unordered_map<Label, Label> *MutableLabel2Index() {
75  if (!have_relabel_data_) {
76  FSTERROR() << "LabelReachableData: No relabeling data";
77  }
78  return &label2index_;
79  }
80 
81  const std::unordered_map<Label, Label> *Label2Index() const {
82  if (!have_relabel_data_) {
83  FSTERROR() << "LabelReachableData: No relabeling data";
84  }
85  return &label2index_;
86  }
87 
88  void SetFinalLabel(Label final_label) { final_label_ = final_label; }
89 
90  Label FinalLabel() const { return final_label_; }
91 
92  static LabelReachableData *Read(std::istream &istrm,
93  const FstReadOptions &opts) {
94  // NB: Using `new` to access private constructor.
95  auto data = fst::WrapUnique(new LabelReachableData());
96  ReadType(istrm, &data->reach_input_);
97  ReadType(istrm, &data->keep_relabel_data_);
98  data->have_relabel_data_ = data->keep_relabel_data_;
99  if (data->keep_relabel_data_) ReadType(istrm, &data->label2index_);
100  ReadType(istrm, &data->final_label_);
101  ReadType(istrm, &data->interval_sets_);
102  return data.release();
103  }
104 
105  bool Write(std::ostream &ostrm, const FstWriteOptions &opts) const {
106  WriteType(ostrm, reach_input_);
107  WriteType(ostrm, keep_relabel_data_);
108  if (keep_relabel_data_) WriteType(ostrm, label2index_);
109  WriteType(ostrm, FinalLabel());
110  WriteType(ostrm, interval_sets_);
111  return true;
112  }
113 
114  private:
115  LabelReachableData() = default;
116 
117  bool reach_input_; // Input labels considered?
118  bool keep_relabel_data_; // Save label2index_ to file?
119  bool have_relabel_data_; // Using label2index_?
120  Label final_label_; // Final label.
121  std::unordered_map<Label, Label> label2index_; // Finds index for a label.
122  std::vector<LabelIntervalSet> interval_sets_; // Interval sets per state.
123 };
124 
125 // Apply a new state order to a vector of LabelIntervalSets. order[i] gives
126 // the StateId after sorting that corresponds to the StateId i before
127 // sorting; it must therefore be a permutation of the input FST's StateId
128 // sequence.
129 template <typename Label, typename StateId>
130 bool StateSort(std::vector<IntervalSet<Label>> *interval_sets,
131  const std::vector<StateId> &order) {
132  if (order.size() != interval_sets->size()) {
133  FSTERROR() << "StateSort: Bad order vector size: " << order.size()
134  << ", expected: " << interval_sets->size();
135  return false;
136  }
137  std::vector<IntervalSet<Label>> reordered_interval_sets(
138  interval_sets->size());
139  // TODO(jrosenstock): Use storage-efficient cycle-following algorithm
140  // from StateSort(MutableFst *, order).
141  for (StateId s = 0; s < order.size(); ++s) {
142  reordered_interval_sets[order[s]] = std::move((*interval_sets)[s]);
143  }
144  *interval_sets = std::move(reordered_interval_sets);
145  return true;
146 }
147 
148 // Apply a new state order to LabelReachableData.
149 template <typename Label, typename StateId>
151  const std::vector<StateId> &order) {
152  return StateSort(data->MutableIntervalSets(), order);
153 }
154 
155 // Functor to find the LowerBound of a Label using an ArcIterator.
156 // Used by LabelReachable. Other, more efficient implementations of
157 // this interface specialized to certain FST types may be used instead.
158 template <class Arc>
160  public:
161  using Label = typename Arc::Label;
162  using StateId = typename Arc::StateId;
163 
164  // Initializes with the FST that will later supply the ArcIterator for
165  // `operator()`. `reach_input` specified whether `operator()` will search
166  // input or output labels. If `is_copy == true`, then `fst` is a copy
167  // of the one previously passed to `Init`, so any expensive initialization
168  // can be skipped.
169  template <class FST>
170  void Init(const FST &fst, bool reach_input, bool is_copy) {
171  reach_input_ = reach_input;
172  }
173 
174  // Sets state that will be searched by `operator()`.
175  void SetState(StateId aiter_s) {}
176 
177  // Positions `aiter` at the first Arc with `label >= match_label` in the
178  // half-open interval `[aiter_begin, aiter_end)`. Returns the position
179  // of `aiter`. `aiter` must be an iterator of the FST that was passed to
180  // `Init`.
181  template <class ArcIterator>
182  ssize_t operator()(ArcIterator *aiter, ssize_t aiter_begin, ssize_t aiter_end,
183  Label match_label) const {
184  // Only needs to compute the ilabel or olabel of arcs when performing the
185  // binary search.
186  aiter->SetFlags(reach_input_ ? kArcILabelValue : kArcOLabelValue,
188  ssize_t low = aiter_begin;
189  ssize_t high = aiter_end;
190  while (low < high) {
191  const ssize_t mid = low + (high - low) / 2;
192  aiter->Seek(mid);
193  auto label = reach_input_ ? aiter->Value().ilabel : aiter->Value().olabel;
194  if (label < match_label) {
195  low = mid + 1;
196  } else {
197  high = mid;
198  }
199  }
200  aiter->Seek(low);
202  return low;
203  }
204 
205  private:
206  bool reach_input_ = false;
207 };
208 
209 // Tests reachability of labels from a given state. If reach_input is true, then
210 // input labels are considered, o.w. output labels are considered. To test for
211 // reachability from a state s, first do SetState(s), then a label l can be
212 // reached from state s of FST f iff Reach(r) is true where r = Relabel(l). The
213 // relabeling is required to ensure the consecutive ones property (C1P); this
214 // allows a compact representation of the reachable labels. See Section 2.3.3 of
215 // "A Generalized Composition Algorithm for Weighted Finite-State Transducers",
216 // Cyril Allauzen, Michael Riley, Johan Schalkwyk, Interspeech 2009.
217 // https://static.googleusercontent.com/media/research.google.com/en//pubs/archive/35539.pdf
218 
219 // The whole FST can be relabeled instead with Relabel(&f, reach_input) so that
220 // the test Reach(r) applies directly to the labels of the transformed FST f.
221 // The relabeled FST will also be sorted appropriately for composition.
222 //
223 // Reachablity of a final state from state s (via an epsilon path) can be
224 // tested with ReachFinal().
225 //
226 // Reachability can also be tested on the set of labels specified by an arc
227 // iterator, useful for FST composition. In particular, Reach(aiter, ...) is
228 // true if labels on the input (output) side of the transitions of the arc
229 // iterator, when iter_input is true (false), can be reached from the state s.
230 // The iterator labels must have already been relabeled.
231 //
232 // With the arc iterator test of reachability, the begin position, end position
233 // and accumulated arc weight of the matches can be returned. The optional
234 // template argument controls how reachable arc weights are accumulated. The
235 // default uses semiring Plus(). Alternative ones can be used to distribute the
236 // weights in composition in various ways.
237 template <class Arc, class Accumulator = DefaultAccumulator<Arc>,
238  class D = LabelReachableData<typename Arc::Label>,
239  class LB = LabelLowerBound<Arc>>
241  public:
242  using Label = typename Arc::Label;
243  using StateId = typename Arc::StateId;
244  using Weight = typename Arc::Weight;
245  using Data = D;
246  using LowerBound = LB;
247 
248  using LabelIntervalSet = typename Data::LabelIntervalSet;
249 
251 
252  LabelReachable(const Fst<Arc> &fst, bool reach_input,
253  std::unique_ptr<Accumulator> accumulator = nullptr,
254  bool keep_relabel_data = true)
255  : fst_(std::make_unique<VectorFst<Arc>>(fst)),
256  s_(kNoStateId),
257  data_(std::make_shared<Data>(reach_input, keep_relabel_data)),
258  accumulator_(accumulator ? std::move(accumulator)
259  : std::make_unique<Accumulator>()) {
260  const auto ins = fst_->NumStates();
261  TransformFst();
262  FindIntervals(ins);
263  fst_.reset();
264  }
265 
266  explicit LabelReachable(std::shared_ptr<Data> data,
267  std::unique_ptr<Accumulator> accumulator = nullptr)
268  : s_(kNoStateId),
269  data_(std::move(data)),
270  accumulator_(accumulator ? std::move(accumulator)
271  : std::make_unique<Accumulator>()) {}
272 
273  LabelReachable(const LabelReachable &reachable, bool safe = false)
274  : s_(kNoStateId),
275  data_(reachable.data_),
276  accumulator_(
277  std::make_unique<Accumulator>(*reachable.accumulator_, safe)),
278  lower_bound_(reachable.lower_bound_),
279  reach_fst_input_(reachable.reach_fst_input_),
280  error_(reachable.error_) {}
281 
283  if (ncalls_ > 0) {
284  VLOG(2) << "# of calls: " << ncalls_;
285  VLOG(2) << "# of intervals/call: " << (nintervals_ / ncalls_);
286  }
287  }
288 
289  // Relabels w.r.t labels that give compact label sets.
290  Label Relabel(Label label) {
291  if (label == 0 || error_) return label;
292  const auto &label2index = *data_->Label2Index();
293  if (auto iter = label2index.find(label); iter != label2index.end()) {
294  return iter->second;
295  }
296  auto &relabel = oov_label2index_[label];
297  if (!relabel) {
298  // Adds new label.
299  relabel = label2index.size() + oov_label2index_.size() + 1;
300  }
301  return relabel;
302  }
303 
304  // Relabels FST w.r.t to labels that give compact label sets.
305  void Relabel(MutableFst<Arc> *fst, bool relabel_input) {
306  for (StateIterator<MutableFst<Arc>> siter(*fst); !siter.Done();
307  siter.Next()) {
308  for (MutableArcIterator<MutableFst<Arc>> aiter(fst, siter.Value());
309  !aiter.Done(); aiter.Next()) {
310  auto arc = aiter.Value();
311  if (relabel_input) {
312  arc.ilabel = Relabel(arc.ilabel);
313  } else {
314  arc.olabel = Relabel(arc.olabel);
315  }
316  aiter.SetValue(arc);
317  }
318  }
319  if (relabel_input) {
320  ArcSort(fst, ILabelCompare<Arc>());
321  fst->SetInputSymbols(nullptr);
322  } else {
323  ArcSort(fst, OLabelCompare<Arc>());
324  fst->SetOutputSymbols(nullptr);
325  }
326  }
327 
328  // Returns relabeling pairs (cf. relabel.h::Relabel()). If avoid_collisions is
329  // true, extra pairs are added to ensure no collisions when relabeling
330  // automata that have labels unseen here.
331  void RelabelPairs(std::vector<std::pair<Label, Label>> *pairs,
332  bool avoid_collisions = false) {
333  pairs->clear();
334  const auto &label2index = *data_->Label2Index();
335  // Maps labels to their new values in [1, label2index().size()].
336  for (const auto &kv : label2index) {
337  if (kv.second != data_->FinalLabel()) {
338  pairs->emplace_back(kv);
339  }
340  }
341  // Maps oov labels to their values > label2index().size().
342  pairs->insert(pairs->end(), oov_label2index_.begin(),
343  oov_label2index_.end());
344  if (avoid_collisions) {
345  // Ensures any label in [1, label2index().size()] is mapped either
346  // by the above steps or to label2index() + 1 (to avoid collisions).
347  for (size_t i = 1; i <= label2index.size(); ++i) {
348  const auto it = label2index.find(i);
349  bool unmapped = it == label2index.end();
350  if (unmapped) unmapped = oov_label2index_.count(i) == 0;
351  if (unmapped || it->second == data_->FinalLabel()) {
352  pairs->emplace_back(i, label2index.size() + 1);
353  }
354  }
355  }
356  }
357 
358  // Set current state. Optionally set state associated
359  // with arc iterator to be passed to Reach.
360  void SetState(StateId s, StateId aiter_s = kNoStateId) {
361  s_ = s;
362  if (aiter_s != kNoStateId) {
363  accumulator_->SetState(aiter_s);
364  if (accumulator_->Error()) error_ = true;
365  lower_bound_.SetState(aiter_s);
366  }
367  }
368 
369  // Can reach this label from current state?
370  // Original labels must be transformed by the Relabel methods above.
371  bool Reach(Label label) const {
372  if (label == 0 || error_) return false;
373  return data_->GetIntervalSet(s_).Member(label);
374  }
375 
376  // Can reach final state (via epsilon transitions) from this state?
377  bool ReachFinal() const {
378  if (error_) return false;
379  return data_->GetIntervalSet(s_).Member(data_->FinalLabel());
380  }
381 
382  // Initialize with secondary FST to be used with Reach(Iterator,...).
383  // If reach_input = true, then arc input labels are considered in
384  // Reach(aiter, ...), o.w. output labels are considered. If copy is true, then
385  // the FST is a copy of the FST used in the previous call to this method
386  // (useful to avoid unnecessary updates).
387  template <class FST>
388  void ReachInit(const FST &fst, bool reach_input, bool copy = false) {
389  reach_fst_input_ = reach_input;
390  if (!fst.Properties(reach_fst_input_ ? kILabelSorted : kOLabelSorted,
391  true)) {
392  FSTERROR() << "LabelReachable::ReachInit: Fst is not sorted";
393  error_ = true;
394  }
395  accumulator_->Init(fst, copy);
396  if (accumulator_->Error()) error_ = true;
397  lower_bound_.Init(fst, /*reach_input=*/reach_input, /*is_copy=*/copy);
398  }
399 
400  // Can reach any arc iterator label between iterator positions
401  // aiter_begin and aiter_end?
402  // Arc iterator labels must be transformed by the Relabel methods
403  // above. If compute_weight is true, user may call ReachWeight().
404  template <class Iterator>
405  bool Reach(Iterator *aiter, ssize_t aiter_begin, ssize_t aiter_end,
406  bool compute_weight) {
407  if (error_) return false;
408  const auto &interval_set = data_->GetIntervalSet(s_);
409  ++ncalls_;
410  nintervals_ += interval_set.Size();
411  reach_begin_ = -1;
412  reach_end_ = -1;
413  reach_weight_ = Weight::Zero();
414  const auto flags = aiter->Flags(); // Save flags to restore them on exit.
415  aiter->SetFlags(kArcNoCache, kArcNoCache); // Makes caching optional.
416  aiter->Seek(aiter_begin);
417  if (2 * (aiter_end - aiter_begin) < interval_set.Size()) {
418  // Checks each arc against intervals, setting arc iterator flags to only
419  // compute the ilabel or olabel values, since they are the only values
420  // required for most of the arcs processed.
421  aiter->SetFlags(reach_fst_input_ ? kArcILabelValue : kArcOLabelValue,
423  Label reach_label = kNoLabel;
424  for (auto aiter_pos = aiter_begin; aiter_pos < aiter_end;
425  aiter->Next(), ++aiter_pos) {
426  const auto &arc = aiter->Value();
427  const auto label = reach_fst_input_ ? arc.ilabel : arc.olabel;
428  if (label == reach_label || Reach(label)) {
429  reach_label = label;
430  if (reach_begin_ < 0) reach_begin_ = aiter_pos;
431  reach_end_ = aiter_pos + 1;
432  if (compute_weight) {
433  if (!(aiter->Flags() & kArcWeightValue)) {
434  // If arc.weight wasn't computed by the call to aiter->Value()
435  // above, we need to call aiter->Value() again after having set
436  // the arc iterator flags to compute the arc weight value.
437  aiter->SetFlags(kArcWeightValue, kArcValueFlags);
438  const auto &arcb = aiter->Value();
439  // Call the accumulator.
440  reach_weight_ = accumulator_->Sum(reach_weight_, arcb.weight);
441  // Only ilabel or olabel required to process the following arcs.
442  aiter->SetFlags(
443  reach_fst_input_ ? kArcILabelValue : kArcOLabelValue,
445  } else {
446  // Calls the accumulator.
447  reach_weight_ = accumulator_->Sum(reach_weight_, arc.weight);
448  }
449  }
450  }
451  }
452  } else {
453  // Checks each interval against arcs.
454  auto begin_low = aiter_begin;
455  auto end_low = aiter_begin;
456  for (const auto &interval : interval_set) {
457  begin_low = lower_bound_(aiter, end_low, aiter_end, interval.begin);
458  end_low = lower_bound_(aiter, begin_low, aiter_end, interval.end);
459  if (end_low - begin_low > 0) {
460  if (reach_begin_ < 0) reach_begin_ = begin_low;
461  reach_end_ = end_low;
462  if (compute_weight) {
463  aiter->SetFlags(kArcWeightValue, kArcValueFlags);
464  reach_weight_ =
465  accumulator_->Sum(reach_weight_, aiter, begin_low, end_low);
466  }
467  }
468  }
469  }
470  aiter->SetFlags(flags, kArcFlags); // Restores original flag values.
471  return reach_begin_ >= 0;
472  }
473 
474  // Returns iterator position of first matching arc.
475  ssize_t ReachBegin() const { return reach_begin_; }
476 
477  // Returns iterator position one past last matching arc.
478  ssize_t ReachEnd() const { return reach_end_; }
479 
480  // Return the sum of the weights for matching arcs. Valid only if
481  // compute_weight was true in Reach() call.
482  Weight ReachWeight() const { return reach_weight_; }
483 
484  // Access to the relabeling map. Excludes epsilon (0) label but
485  // includes kNoLabel that is used internally for super-final
486  // transitions.
487  const std::unordered_map<Label, Label> &Label2Index() const {
488  return *data_->Label2Index();
489  }
490 
491  const Data *GetData() const { return data_.get(); }
492 
493  std::shared_ptr<Data> GetSharedData() const { return data_; }
494 
495  bool Error() const { return error_ || accumulator_->Error(); }
496 
497  private:
498  // Redirects labeled arcs (input or output labels determined by ReachInput())
499  // to new label-specific final states. Each original final state is
500  // redirected via a transition labeled with kNoLabel to a new
501  // kNoLabel-specific final state. Creates super-initial state for all states
502  // with zero in-degree.
503  void TransformFst() {
504  auto ins = fst_->NumStates();
505  auto ons = ins;
506  std::vector<ssize_t> indeg(ins, 0);
507  // Redirects labeled arcs to new final states.
508  for (StateId s = 0; s < ins; ++s) {
509  for (MutableArcIterator<VectorFst<Arc>> aiter(fst_.get(), s);
510  !aiter.Done(); aiter.Next()) {
511  auto arc = aiter.Value();
512  const auto label = data_->ReachInput() ? arc.ilabel : arc.olabel;
513  if (label) {
514  if (auto insert_result = label2state_.emplace(label, ons);
515  insert_result.second) {
516  indeg.push_back(0);
517  ++ons;
518  }
519  arc.nextstate = label2state_[label];
520  aiter.SetValue(arc);
521  }
522  ++indeg[arc.nextstate]; // Finds in-degrees for next step.
523  }
524  // Redirects final weights to new final state.
525  auto final_weight = fst_->Final(s);
526  if (final_weight != Weight::Zero()) {
527  if (auto insert_result = label2state_.emplace(kNoLabel, ons);
528  insert_result.second) {
529  indeg.push_back(0);
530  ++ons;
531  }
532  const auto nextstate = label2state_[kNoLabel];
533  fst_->EmplaceArc(s, kNoLabel, kNoLabel, std::move(final_weight),
534  nextstate);
535  ++indeg[nextstate]; // Finds in-degrees for next step.
536  fst_->SetFinal(s, Weight::Zero());
537  }
538  }
539  // Adds new final states to the FST.
540  while (fst_->NumStates() < ons) {
541  StateId s = fst_->AddState();
542  fst_->SetFinal(s);
543  }
544  // Creates a super-initial state for all states with zero in-degree.
545  const auto start = fst_->AddState();
546  fst_->SetStart(start);
547  for (StateId s = 0; s < start; ++s) {
548  if (indeg[s] == 0) fst_->EmplaceArc(start, 0, 0, s);
549  }
550  }
551 
552  void FindIntervals(StateId ins) {
553  StateReachable<Arc, Label, LabelIntervalSet> state_reachable(*fst_);
554  if (state_reachable.Error()) {
555  error_ = true;
556  return;
557  }
558  auto &state2index = state_reachable.State2Index();
559  auto &interval_sets = *data_->MutableIntervalSets();
560  interval_sets = state_reachable.IntervalSets();
561  interval_sets.resize(ins);
562  auto &label2index = *data_->MutableLabel2Index();
563  for (const auto &kv : label2state_) {
564  Label i = state2index[kv.second];
565  label2index[kv.first] = i;
566  if (kv.first == kNoLabel) data_->SetFinalLabel(i);
567  }
568  label2state_.clear();
569  double nintervals = 0;
570  ssize_t non_intervals = 0;
571  for (StateId s = 0; s < ins; ++s) {
572  nintervals += interval_sets[s].Size();
573  if (interval_sets[s].Size() > 1) {
574  ++non_intervals;
575  VLOG(3) << "state: " << s
576  << " # of intervals: " << interval_sets[s].Size();
577  }
578  }
579  VLOG(2) << "# of states: " << ins;
580  VLOG(2) << "# of intervals: " << nintervals;
581  VLOG(2) << "# of intervals/state: " << nintervals / ins;
582  VLOG(2) << "# of non-interval states: " << non_intervals;
583  }
584 
585  std::unique_ptr<VectorFst<Arc>> fst_;
586  // Current state
587  StateId s_;
588  // Finds final state for a label
589  std::unordered_map<Label, StateId> label2state_;
590  // Iterator position of first match.
591  ssize_t reach_begin_;
592  // Iterator position after last match.
593  ssize_t reach_end_;
594  // Gives weight sum of arc iterator arcs with reachable labels.
595  Weight reach_weight_;
596  // Shareable data between copies.
597  std::shared_ptr<Data> data_;
598  // Sums arc weights.
599  std::unique_ptr<Accumulator> accumulator_;
600  // Functor for computing LowerBound(Iterator*, begin, end, label).
601  LowerBound lower_bound_;
602  // Relabeling map for OOV labels.
603  std::unordered_map<Label, Label> oov_label2index_;
604  double ncalls_ = 0;
605  double nintervals_ = 0;
606  bool reach_fst_input_ = false;
607  bool error_ = false;
608 };
609 
610 } // namespace fst
611 
612 #endif // FST_LABEL_REACHABLE_H_
void Relabel(MutableFst< Arc > *fst, bool relabel_input)
typename Data::LabelIntervalSet LabelIntervalSet
constexpr uint8_t kArcValueFlags
Definition: fst.h:453
typename Arc::Weight Weight
constexpr int kNoLabel
Definition: fst.h:195
const std::unordered_map< Label, Label > * Label2Index() const
const std::vector< ISet > & IntervalSets()
ssize_t ReachEnd() const
constexpr uint8_t kArcNoCache
Definition: fst.h:452
std::shared_ptr< Data > GetSharedData() const
std::vector< Index > & State2Index()
LabelReachable(const LabelReachable &reachable, bool safe=false)
void SetFinalLabel(Label final_label)
typename Arc::Label Label
constexpr uint8_t kArcFlags
Definition: fst.h:455
virtual void SetInputSymbols(const SymbolTable *isyms)=0
bool Reach(Iterator *aiter, ssize_t aiter_begin, ssize_t aiter_end, bool compute_weight)
constexpr uint8_t kArcILabelValue
Definition: fst.h:444
std::unordered_map< Label, Label > * MutableLabel2Index()
std::unique_ptr< T > WrapUnique(T *ptr)
Definition: compat.h:132
void SetState(StateId aiter_s)
constexpr int kNoStateId
Definition: fst.h:196
Label Relabel(Label label)
const Arc & Value() const
Definition: fst.h:536
LabelReachableData(bool reach_input, bool keep_relabel_data=true)
void Relabel(MutableFst< Arc > *fst, const std::vector< std::pair< typename Arc::Label, typename Arc::Label >> &ipairs, const std::vector< std::pair< typename Arc::Label, typename Arc::Label >> &opairs)
Definition: relabel.h:49
void RelabelPairs(std::vector< std::pair< Label, Label >> *pairs, bool avoid_collisions=false)
std::ostream & WriteType(std::ostream &strm, const T t)
Definition: util.h:228
#define FSTERROR()
Definition: util.h:56
void SetFlags(uint8_t flags, uint8_t mask)
Definition: fst.h:570
int NumIntervalSets() const
static LabelReachableData * Read(std::istream &istrm, const FstReadOptions &opts)
void Seek(size_t a)
Definition: fst.h:556
void ArcSort(MutableFst< Arc > *fst, Compare comp)
Definition: arcsort.h:109
constexpr uint64_t kOLabelSorted
Definition: properties.h:99
typename Arc::StateId StateId
LabelReachable(const Fst< Arc > &fst, bool reach_input, std::unique_ptr< Accumulator > accumulator=nullptr, bool keep_relabel_data=true)
constexpr uint8_t kArcOLabelValue
Definition: fst.h:446
#define VLOG(level)
Definition: log.h:54
ssize_t operator()(ArcIterator *aiter, ssize_t aiter_begin, ssize_t aiter_end, Label match_label) const
bool Reach(Label label) const
typename Arc::Label Label
typename LabelIntervalSet::Interval Interval
const Data * GetData() const
Weight ReachWeight() const
bool ReachFinal() const
constexpr uint8_t kArcWeightValue
Definition: fst.h:448
constexpr uint64_t kILabelSorted
Definition: properties.h:94
Label FinalLabel() const
LabelReachable(std::shared_ptr< Data > data, std::unique_ptr< Accumulator > accumulator=nullptr)
ssize_t ReachBegin() const
const std::unordered_map< Label, Label > & Label2Index() const
std::istream & ReadType(std::istream &strm, T *t)
Definition: util.h:80
virtual void SetOutputSymbols(const SymbolTable *osyms)=0
IntInterval< T > Interval
Definition: interval-set.h:125
void SetState(StateId s, StateId aiter_s=kNoStateId)
typename Arc::StateId StateId
std::vector< LabelIntervalSet > * MutableIntervalSets()
void ReachInit(const FST &fst, bool reach_input, bool copy=false)
bool Write(std::ostream &ostrm, const FstWriteOptions &opts) const
bool StateSort(std::vector< IntervalSet< Label >> *interval_sets, const std::vector< StateId > &order)
const LabelIntervalSet & GetIntervalSet(int s) const
typename LabelIntervalSet::Interval Interval
void Init(const FST &fst, bool reach_input, bool is_copy)