FST  openfst-1.8.2
OpenFst Library
union.h
Go to the documentation of this file.
1 // Copyright 2005-2020 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 union of two FSTs.
19 
20 #ifndef FST_UNION_H_
21 #define FST_UNION_H_
22 
23 #include <algorithm>
24 #include <utility>
25 #include <vector>
26 
27 
28 #include <fst/expanded-fst.h>
29 #include <fst/mutable-fst.h>
30 #include <fst/rational.h>
31 
32 
33 namespace fst {
34 
35 // Computes the union (sum) of two FSTs. This version writes the union to an
36 // output MutableFst. If A transduces string x to y with weight a and B
37 // transduces string w to v with weight b, then their union transduces x to y
38 // with weight a and w to v with weight b.
39 //
40 // Complexity:
41 //
42 // Time: (V_2 + E_2)
43 // Space: O(V_2 + E_2)
44 //
45 // where Vi is the number of states, and Ei is the number of arcs, in the ith
46 // FST.
47 template <class Arc>
48 void Union(MutableFst<Arc> *fst1, const Fst<Arc> &fst2) {
49  // Checks for symbol table compatibility.
50  if (!CompatSymbols(fst1->InputSymbols(), fst2.InputSymbols()) ||
51  !CompatSymbols(fst1->OutputSymbols(), fst2.OutputSymbols())) {
52  FSTERROR() << "Union: Input/output symbol tables of 1st argument "
53  << "do not match input/output symbol tables of 2nd argument";
54  fst1->SetProperties(kError, kError);
55  return;
56  }
57  const auto numstates1 = fst1->NumStates();
58  const bool initial_acyclic1 =
60  const auto props1 = fst1->Properties(kFstProperties, false);
61  const auto props2 = fst2.Properties(kFstProperties, false);
62  const auto start2 = fst2.Start();
63  if (start2 == kNoStateId) {
64  if (props2 & kError) fst1->SetProperties(kError, kError);
65  return;
66  }
67  if (fst2.Properties(kExpanded, false)) {
68  fst1->ReserveStates(numstates1 + CountStates(fst2) +
69  (initial_acyclic1 ? 0 : 1));
70  }
71  for (StateIterator<Fst<Arc>> siter(fst2); !siter.Done(); siter.Next()) {
72  const auto s1 = fst1->AddState();
73  const auto s2 = siter.Value();
74  fst1->SetFinal(s1, fst2.Final(s2));
75  fst1->ReserveArcs(s1, fst2.NumArcs(s2));
76  for (ArcIterator<Fst<Arc>> aiter(fst2, s2); !aiter.Done(); aiter.Next()) {
77  auto arc = aiter.Value(); // Copy intended.
78  arc.nextstate += numstates1;
79  fst1->AddArc(s1, std::move(arc));
80  }
81  }
82  const auto start1 = fst1->Start();
83  if (start1 == kNoStateId) {
84  fst1->SetStart(start2);
85  fst1->SetProperties(props2, kCopyProperties);
86  return;
87  }
88  if (initial_acyclic1) {
89  fst1->AddArc(start1, Arc(0, 0, start2 + numstates1));
90  } else {
91  const auto nstart1 = fst1->AddState();
92  fst1->SetStart(nstart1);
93  fst1->AddArc(nstart1, Arc(0, 0, start1));
94  fst1->AddArc(nstart1, Arc(0, 0, start2 + numstates1));
95  }
96  fst1->SetProperties(UnionProperties(props1, props2), kFstProperties);
97 }
98 
99 // Same as the above but can handle arbitrarily many right-hand-side FSTs,
100 // preallocating the states.
101 template <class Arc>
102 void Union(MutableFst<Arc> *fst1, const std::vector<const Fst<Arc> *> &fsts2) {
103  // We add 1 just in case fst1 has an initial cycle.
104  fst1->ReserveStates(1 + fst1->NumStates() + CountStates(fsts2));
105  for (const auto *fst2 : fsts2) Union(fst1, *fst2);
106 }
107 
108 // Computes the union of two FSTs, modifying the RationalFst argument.
109 template <class Arc>
110 void Union(RationalFst<Arc> *fst1, const Fst<Arc> &fst2) {
111  fst1->GetMutableImpl()->AddUnion(fst2);
112 }
113 
115 
116 // Computes the union (sum) of two FSTs. This version is a delayed FST. If A
117 // transduces string x to y with weight a and B transduces string w to v with
118 // weight b, then their union transduces x to y with weight a and w to v with
119 // weight b.
120 //
121 // Complexity:
122 //
123 // Time: O(v_1 + e_1 + v_2 + e_2)
124 // Space: O(v_1 + v_2)
125 //
126 // where vi is the number of states visited, and ei is the number of arcs
127 // visited, in the ith FST. Constant time and space to visit an input state or
128 // arc is assumed and exclusive of caching.
129 template <class A>
130 class UnionFst : public RationalFst<A> {
131  public:
132  using Arc = A;
133  using StateId = typename Arc::StateId;
134  using Weight = typename Arc::Weight;
135 
136  UnionFst(const Fst<Arc> &fst1, const Fst<Arc> &fst2) {
137  GetMutableImpl()->InitUnion(fst1, fst2);
138  }
139 
140  UnionFst(const Fst<Arc> &fst1, const Fst<Arc> &fst2,
141  const UnionFstOptions &opts)
142  : RationalFst<Arc>(opts) {
143  GetMutableImpl()->InitUnion(fst1, fst2);
144  }
145 
146  // See Fst<>::Copy() for doc.
147  UnionFst(const UnionFst &fst, bool safe = false)
148  : RationalFst<Arc>(fst, safe) {}
149 
150  // Gets a copy of this UnionFst. See Fst<>::Copy() for further doc.
151  UnionFst *Copy(bool safe = false) const override {
152  return new UnionFst(*this, safe);
153  }
154 
155  private:
158 };
159 
160 // Specialization for UnionFst.
161 template <class Arc>
162 class StateIterator<UnionFst<Arc>> : public StateIterator<RationalFst<Arc>> {
163  public:
164  explicit StateIterator(const UnionFst<Arc> &fst)
165  : StateIterator<RationalFst<Arc>>(fst) {}
166 };
167 
168 // Specialization for UnionFst.
169 template <class Arc>
170 class ArcIterator<UnionFst<Arc>> : public ArcIterator<RationalFst<Arc>> {
171  public:
172  using StateId = typename Arc::StateId;
173 
175  : ArcIterator<RationalFst<Arc>>(fst, s) {}
176 };
177 
179 
180 } // namespace fst
181 
182 #endif // FST_UNION_H_
virtual uint64_t Properties(uint64_t mask, bool test) const =0
StateIterator(const UnionFst< Arc > &fst)
Definition: union.h:164
virtual size_t NumArcs(StateId) const =0
const SymbolTable * InputSymbols() const override=0
constexpr uint64_t kError
Definition: properties.h:51
constexpr uint64_t kInitialAcyclic
Definition: properties.h:115
virtual Weight Final(StateId) const =0
virtual void SetStart(StateId)=0
typename ReplaceFst< Arc >::Arc Arc
Definition: fst.h:408
CacheOptions RationalFstOptions
Definition: rational.h:36
constexpr int kNoStateId
Definition: fst.h:202
virtual void ReserveArcs(StateId, size_t)
Definition: mutable-fst.h:99
#define FSTERROR()
Definition: util.h:53
UnionFst(const Fst< Arc > &fst1, const Fst< Arc > &fst2)
Definition: union.h:136
const SymbolTable * OutputSymbols() const override=0
typename Arc::StateId StateId
Definition: rational.h:270
uint64_t UnionProperties(uint64_t inprops1, uint64_t inprops2, bool delayed=false)
Definition: properties.cc:394
void Union(RationalFst< Arc > *fst1, const Fst< Arc > &fst2)
Definition: union.h:110
constexpr uint64_t kCopyProperties
Definition: properties.h:162
virtual void SetProperties(uint64_t props, uint64_t mask)=0
typename Arc::StateId StateId
Definition: rational.h:315
virtual StateId Start() const =0
constexpr uint64_t kFstProperties
Definition: properties.h:325
virtual void AddArc(StateId, const Arc &)=0
typename ReplaceFst< Arc >::Arc Arc
Definition: cache.h:1195
virtual const SymbolTable * InputSymbols() const =0
Arc::StateId CountStates(const Fst< Arc > &fst)
Definition: expanded-fst.h:169
virtual StateId AddState()=0
virtual void ReserveStates(size_t)
Definition: mutable-fst.h:96
virtual void SetFinal(StateId s, Weight weight=Weight::One())=0
ArcIterator(const UnionFst< Arc > &fst, StateId s)
Definition: union.h:174
typename Arc::Weight Weight
Definition: union.h:134
UnionFst(const Fst< Arc > &fst1, const Fst< Arc > &fst2, const UnionFstOptions &opts)
Definition: union.h:140
bool CompatSymbols(const SymbolTable *syms1, const SymbolTable *syms2, bool warning=true)
UnionFst(const UnionFst &fst, bool safe=false)
Definition: union.h:147
internal::RationalFstImpl< A > * GetMutableImpl() const
Definition: fst.h:1028
virtual StateId NumStates() const =0
constexpr uint64_t kExpanded
Definition: properties.h:45
UnionFst * Copy(bool safe=false) const override
Definition: union.h:151
const internal::RationalFstImpl< A > * GetImpl() const
Definition: fst.h:1026
virtual const SymbolTable * OutputSymbols() const =0