FST  openfst-1.8.4
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) {
351  // TODO: Use contains() when C++20 is allowed in OpenFST.
352  unmapped = oov_label2index_.find(i) == oov_label2index_.end();
353  }
354  if (unmapped || it->second == data_->FinalLabel()) {
355  pairs->emplace_back(i, label2index.size() + 1);
356  }
357  }
358  }
359  }
360 
361  // Set current state. Optionally set state associated
362  // with arc iterator to be passed to Reach.
363  void SetState(StateId s, StateId aiter_s = kNoStateId) {
364  s_ = s;
365  if (aiter_s != kNoStateId) {
366  accumulator_->SetState(aiter_s);
367  if (accumulator_->Error()) error_ = true;
368  lower_bound_.SetState(aiter_s);
369  }
370  }
371 
372  // Can reach this label from current state?
373  // Original labels must be transformed by the Relabel methods above.
374  bool Reach(Label label) const {
375  if (label == 0 || error_) return false;
376  return data_->GetIntervalSet(s_).Member(label);
377  }
378 
379  // Can reach final state (via epsilon transitions) from this state?
380  bool ReachFinal() const {
381  if (error_) return false;
382  return data_->GetIntervalSet(s_).Member(data_->FinalLabel());
383  }
384 
385  // Initialize with secondary FST to be used with Reach(Iterator,...).
386  // If reach_input = true, then arc input labels are considered in
387  // Reach(aiter, ...), o.w. output labels are considered. If copy is true, then
388  // the FST is a copy of the FST used in the previous call to this method
389  // (useful to avoid unnecessary updates).
390  template <class FST>
391  void ReachInit(const FST &fst, bool reach_input, bool copy = false) {
392  reach_fst_input_ = reach_input;
393  if (!fst.Properties(reach_fst_input_ ? kILabelSorted : kOLabelSorted,
394  true)) {
395  FSTERROR() << "LabelReachable::ReachInit: Fst is not sorted";
396  error_ = true;
397  }
398  accumulator_->Init(fst, copy);
399  if (accumulator_->Error()) error_ = true;
400  lower_bound_.Init(fst, /*reach_input=*/reach_input, /*is_copy=*/copy);
401  }
402 
403  // Can reach any arc iterator label between iterator positions
404  // aiter_begin and aiter_end?
405  // Arc iterator labels must be transformed by the Relabel methods
406  // above. If compute_weight is true, user may call ReachWeight().
407  template <class Iterator>
408  bool Reach(Iterator *aiter, ssize_t aiter_begin, ssize_t aiter_end,
409  bool compute_weight) {
410  if (error_) return false;
411  const auto &interval_set = data_->GetIntervalSet(s_);
412  ++ncalls_;
413  nintervals_ += interval_set.Size();
414  reach_begin_ = -1;
415  reach_end_ = -1;
416  reach_weight_ = Weight::Zero();
417  const auto flags = aiter->Flags(); // Save flags to restore them on exit.
418  aiter->SetFlags(kArcNoCache, kArcNoCache); // Makes caching optional.
419  aiter->Seek(aiter_begin);
420  if (2 * (aiter_end - aiter_begin) < interval_set.Size()) {
421  // Checks each arc against intervals, setting arc iterator flags to only
422  // compute the ilabel or olabel values, since they are the only values
423  // required for most of the arcs processed.
424  aiter->SetFlags(reach_fst_input_ ? kArcILabelValue : kArcOLabelValue,
426  Label reach_label = kNoLabel;
427  for (auto aiter_pos = aiter_begin; aiter_pos < aiter_end;
428  aiter->Next(), ++aiter_pos) {
429  const auto &arc = aiter->Value();
430  const auto label = reach_fst_input_ ? arc.ilabel : arc.olabel;
431  if (label == reach_label || Reach(label)) {
432  reach_label = label;
433  if (reach_begin_ < 0) reach_begin_ = aiter_pos;
434  reach_end_ = aiter_pos + 1;
435  if (compute_weight) {
436  if (!(aiter->Flags() & kArcWeightValue)) {
437  // If arc.weight wasn't computed by the call to aiter->Value()
438  // above, we need to call aiter->Value() again after having set
439  // the arc iterator flags to compute the arc weight value.
440  aiter->SetFlags(kArcWeightValue, kArcValueFlags);
441  const auto &arcb = aiter->Value();
442  // Call the accumulator.
443  reach_weight_ = accumulator_->Sum(reach_weight_, arcb.weight);
444  // Only ilabel or olabel required to process the following arcs.
445  aiter->SetFlags(
446  reach_fst_input_ ? kArcILabelValue : kArcOLabelValue,
448  } else {
449  // Calls the accumulator.
450  reach_weight_ = accumulator_->Sum(reach_weight_, arc.weight);
451  }
452  }
453  }
454  }
455  } else {
456  // Checks each interval against arcs.
457  auto begin_low = aiter_begin;
458  auto end_low = aiter_begin;
459  for (const auto &interval : interval_set) {
460  begin_low = lower_bound_(aiter, end_low, aiter_end, interval.begin);
461  end_low = lower_bound_(aiter, begin_low, aiter_end, interval.end);
462  if (end_low - begin_low > 0) {
463  if (reach_begin_ < 0) reach_begin_ = begin_low;
464  reach_end_ = end_low;
465  if (compute_weight) {
466  aiter->SetFlags(kArcWeightValue, kArcValueFlags);
467  reach_weight_ =
468  accumulator_->Sum(reach_weight_, aiter, begin_low, end_low);
469  }
470  }
471  }
472  }
473  aiter->SetFlags(flags, kArcFlags); // Restores original flag values.
474  return reach_begin_ >= 0;
475  }
476 
477  // Returns iterator position of first matching arc.
478  ssize_t ReachBegin() const { return reach_begin_; }
479 
480  // Returns iterator position one past last matching arc.
481  ssize_t ReachEnd() const { return reach_end_; }
482 
483  // Return the sum of the weights for matching arcs. Valid only if
484  // compute_weight was true in Reach() call.
485  Weight ReachWeight() const { return reach_weight_; }
486 
487  // Access to the relabeling map. Excludes epsilon (0) label but
488  // includes kNoLabel that is used internally for super-final
489  // transitions.
490  const std::unordered_map<Label, Label> &Label2Index() const {
491  return *data_->Label2Index();
492  }
493 
494  const Data *GetData() const { return data_.get(); }
495 
496  std::shared_ptr<Data> GetSharedData() const { return data_; }
497 
498  bool Error() const { return error_ || accumulator_->Error(); }
499 
500  private:
501  // Redirects labeled arcs (input or output labels determined by ReachInput())
502  // to new label-specific final states. Each original final state is
503  // redirected via a transition labeled with kNoLabel to a new
504  // kNoLabel-specific final state. Creates super-initial state for all states
505  // with zero in-degree.
506  void TransformFst() {
507  auto ins = fst_->NumStates();
508  auto ons = ins;
509  std::vector<ssize_t> indeg(ins, 0);
510  // Redirects labeled arcs to new final states.
511  for (StateId s = 0; s < ins; ++s) {
512  for (MutableArcIterator<VectorFst<Arc>> aiter(fst_.get(), s);
513  !aiter.Done(); aiter.Next()) {
514  auto arc = aiter.Value();
515  const auto label = data_->ReachInput() ? arc.ilabel : arc.olabel;
516  if (label) {
517  if (auto insert_result = label2state_.emplace(label, ons);
518  insert_result.second) {
519  indeg.push_back(0);
520  ++ons;
521  }
522  arc.nextstate = label2state_[label];
523  aiter.SetValue(arc);
524  }
525  ++indeg[arc.nextstate]; // Finds in-degrees for next step.
526  }
527  // Redirects final weights to new final state.
528  auto final_weight = fst_->Final(s);
529  if (final_weight != Weight::Zero()) {
530  if (auto insert_result = label2state_.emplace(kNoLabel, ons);
531  insert_result.second) {
532  indeg.push_back(0);
533  ++ons;
534  }
535  const auto nextstate = label2state_[kNoLabel];
536  fst_->EmplaceArc(s, kNoLabel, kNoLabel, std::move(final_weight),
537  nextstate);
538  ++indeg[nextstate]; // Finds in-degrees for next step.
539  fst_->SetFinal(s, Weight::Zero());
540  }
541  }
542  // Adds new final states to the FST.
543  while (fst_->NumStates() < ons) {
544  StateId s = fst_->AddState();
545  fst_->SetFinal(s);
546  }
547  // Creates a super-initial state for all states with zero in-degree.
548  const auto start = fst_->AddState();
549  fst_->SetStart(start);
550  for (StateId s = 0; s < start; ++s) {
551  if (indeg[s] == 0) fst_->EmplaceArc(start, 0, 0, s);
552  }
553  }
554 
555  void FindIntervals(StateId ins) {
556  StateReachable<Arc, Label, LabelIntervalSet> state_reachable(*fst_);
557  if (state_reachable.Error()) {
558  error_ = true;
559  return;
560  }
561  auto &state2index = state_reachable.State2Index();
562  auto &interval_sets = *data_->MutableIntervalSets();
563  interval_sets = state_reachable.IntervalSets();
564  interval_sets.resize(ins);
565  auto &label2index = *data_->MutableLabel2Index();
566  for (const auto &kv : label2state_) {
567  Label i = state2index[kv.second];
568  label2index[kv.first] = i;
569  if (kv.first == kNoLabel) data_->SetFinalLabel(i);
570  }
571  label2state_.clear();
572  double nintervals = 0;
573  ssize_t non_intervals = 0;
574  for (StateId s = 0; s < ins; ++s) {
575  nintervals += interval_sets[s].Size();
576  if (interval_sets[s].Size() > 1) {
577  ++non_intervals;
578  VLOG(3) << "state: " << s
579  << " # of intervals: " << interval_sets[s].Size();
580  }
581  }
582  VLOG(2) << "# of states: " << ins;
583  VLOG(2) << "# of intervals: " << nintervals;
584  VLOG(2) << "# of intervals/state: " << nintervals / ins;
585  VLOG(2) << "# of non-interval states: " << non_intervals;
586  }
587 
588  std::unique_ptr<VectorFst<Arc>> fst_;
589  // Current state
590  StateId s_;
591  // Finds final state for a label
592  std::unordered_map<Label, StateId> label2state_;
593  // Iterator position of first match.
594  ssize_t reach_begin_;
595  // Iterator position after last match.
596  ssize_t reach_end_;
597  // Gives weight sum of arc iterator arcs with reachable labels.
598  Weight reach_weight_;
599  // Shareable data between copies.
600  std::shared_ptr<Data> data_;
601  // Sums arc weights.
602  std::unique_ptr<Accumulator> accumulator_;
603  // Functor for computing LowerBound(Iterator*, begin, end, label).
604  LowerBound lower_bound_;
605  // Relabeling map for OOV labels.
606  std::unordered_map<Label, Label> oov_label2index_;
607  double ncalls_ = 0;
608  double nintervals_ = 0;
609  bool reach_fst_input_ = false;
610  bool error_ = false;
611 };
612 
613 } // namespace fst
614 
615 #endif // FST_LABEL_REACHABLE_H_
void Relabel(MutableFst< Arc > *fst, bool relabel_input)
typename Data::LabelIntervalSet LabelIntervalSet
constexpr uint8_t kArcValueFlags
Definition: fst.h:452
typename Arc::Weight Weight
constexpr int kNoLabel
Definition: fst.h:194
const std::unordered_map< Label, Label > * Label2Index() const
const std::vector< ISet > & IntervalSets()
ssize_t ReachEnd() const
constexpr uint8_t kArcNoCache
Definition: fst.h:451
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:454
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:443
std::unordered_map< Label, Label > * MutableLabel2Index()
std::unique_ptr< T > WrapUnique(T *ptr)
Definition: compat.h:134
void SetState(StateId aiter_s)
constexpr int kNoStateId
Definition: fst.h:195
Label Relabel(Label label)
const Arc & Value() const
Definition: fst.h:535
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:229
#define FSTERROR()
Definition: util.h:57
void SetFlags(uint8_t flags, uint8_t mask)
Definition: fst.h:569
int NumIntervalSets() const
static LabelReachableData * Read(std::istream &istrm, const FstReadOptions &opts)
void Seek(size_t a)
Definition: fst.h:555
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:445
#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:447
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:81
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)