FST  openfst-1.8.3
OpenFst Library
concat.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 // Functions and classes to compute the concatenation of two FSTs.
19 
20 #ifndef FST_CONCAT_H_
21 #define FST_CONCAT_H_
22 
23 #include <algorithm>
24 #include <vector>
25 
26 #include <fst/log.h>
27 #include <fst/arc.h>
28 #include <fst/cache.h>
29 #include <fst/expanded-fst.h>
30 #include <fst/float-weight.h>
31 #include <fst/fst.h>
32 #include <fst/impl-to-fst.h>
33 #include <fst/mutable-fst.h>
34 #include <fst/properties.h>
35 #include <fst/rational.h>
36 #include <fst/symbol-table.h>
37 #include <fst/util.h>
38 
39 namespace fst {
40 
41 // Computes the concatenation (product) of two FSTs. If FST1 transduces string
42 // x to y with weight a and FST2 transduces string w to v with weight b, then
43 // their concatenation transduces string xw to yv with weight Times(a, b).
44 //
45 // This version modifies its MutableFst argument (in first position).
46 //
47 // Complexity:
48 //
49 // Time: O(V1 + V2 + E2)
50 // Space: O(V1 + V2 + E2)
51 //
52 // where Vi is the number of states, and Ei is the number of arcs, of the ith
53 // FST.
54 template <class Arc>
55 void Concat(MutableFst<Arc> *fst1, const Fst<Arc> &fst2) {
56  using StateId = typename Arc::StateId;
57  using Weight = typename Arc::Weight;
58  // Checks that the symbol table are compatible.
59  if (!CompatSymbols(fst1->InputSymbols(), fst2.InputSymbols()) ||
60  !CompatSymbols(fst1->OutputSymbols(), fst2.OutputSymbols())) {
61  FSTERROR() << "Concat: Input/output symbol tables of 1st argument "
62  << "does not match input/output symbol tables of 2nd argument";
63  fst1->SetProperties(kError, kError);
64  return;
65  }
66  const auto props1 = fst1->Properties(kFstProperties, false);
67  const auto props2 = fst2.Properties(kFstProperties, false);
68  const auto start1 = fst1->Start();
69  if (start1 == kNoStateId) {
70  if (props2 & kError) fst1->SetProperties(kError, kError);
71  return;
72  }
73  const auto numstates1 = fst1->NumStates();
74  if (std::optional<StateId> numstates2 = fst2.NumStatesIfKnown()) {
75  fst1->ReserveStates(numstates1 + *numstates2);
76  }
77  for (StateIterator<Fst<Arc>> siter2(fst2); !siter2.Done(); siter2.Next()) {
78  const auto s1 = fst1->AddState();
79  const auto s2 = siter2.Value();
80  fst1->SetFinal(s1, fst2.Final(s2));
81  fst1->ReserveArcs(s1, fst2.NumArcs(s2));
82  for (ArcIterator<Fst<Arc>> aiter(fst2, s2); !aiter.Done(); aiter.Next()) {
83  auto arc = aiter.Value();
84  arc.nextstate += numstates1;
85  fst1->AddArc(s1, arc);
86  }
87  }
88  const auto start2 = fst2.Start();
89  for (StateId s1 = 0; s1 < numstates1; ++s1) {
90  const auto weight = fst1->Final(s1);
91  if (weight != Weight::Zero()) {
92  fst1->SetFinal(s1, Weight::Zero());
93  if (start2 != kNoStateId) {
94  fst1->AddArc(s1, Arc(0, 0, weight, start2 + numstates1));
95  }
96  }
97  }
98  if (start2 != kNoStateId) {
99  fst1->SetProperties(ConcatProperties(props1, props2), kFstProperties);
100  }
101 }
102 
103 // Computes the concatentation of two FSTs. This version modifies its
104 // RationalFst input (in first position).
105 template <class Arc>
106 void Concat(RationalFst<Arc> *fst1, const Fst<Arc> &fst2) {
107  fst1->GetMutableImpl()->AddConcat(fst2, true);
108 }
109 
110 // Computes the concatentation of two FSTs. This version modifies its
111 // MutableFst argument (in second position).
112 //
113 // Complexity:
114 //
115 // Time: O(V1 + E1)
116 // Space: O(V1 + E1)
117 //
118 // where Vi is the number of states, and Ei is the number of arcs, of the ith
119 // FST.
120 template <class Arc>
121 void Concat(const Fst<Arc> &fst1, MutableFst<Arc> *fst2) {
122  using StateId = typename Arc::StateId;
123  using Weight = typename Arc::Weight;
124  // Checks that the symbol table are compatible.
125  if (!CompatSymbols(fst1.InputSymbols(), fst2->InputSymbols()) ||
126  !CompatSymbols(fst1.OutputSymbols(), fst2->OutputSymbols())) {
127  FSTERROR() << "Concat: Input/output symbol tables of 1st argument "
128  << "does not match input/output symbol tables of 2nd argument";
129  fst2->SetProperties(kError, kError);
130  return;
131  }
132  const auto props1 = fst1.Properties(kFstProperties, false);
133  const auto props2 = fst2->Properties(kFstProperties, false);
134  const auto start2 = fst2->Start();
135  if (start2 == kNoStateId) {
136  if (props1 & kError) fst2->SetProperties(kError, kError);
137  return;
138  }
139  const auto numstates2 = fst2->NumStates();
140  if (std::optional<StateId> numstates1 = fst1.NumStatesIfKnown()) {
141  fst2->ReserveStates(numstates2 + *numstates1);
142  }
143  for (StateIterator<Fst<Arc>> siter(fst1); !siter.Done(); siter.Next()) {
144  const auto s1 = siter.Value();
145  const auto s2 = fst2->AddState();
146  const auto weight = fst1.Final(s1);
147  if (weight != Weight::Zero()) {
148  fst2->ReserveArcs(s2, fst1.NumArcs(s1) + 1);
149  fst2->AddArc(s2, Arc(0, 0, weight, start2));
150  } else {
151  fst2->ReserveArcs(s2, fst1.NumArcs(s1));
152  }
153  for (ArcIterator<Fst<Arc>> aiter(fst1, s1); !aiter.Done(); aiter.Next()) {
154  auto arc = aiter.Value();
155  arc.nextstate += numstates2;
156  fst2->AddArc(s2, arc);
157  }
158  }
159  const auto start1 = fst1.Start();
160  if (start1 != kNoStateId) {
161  fst2->SetStart(start1 + numstates2);
162  fst2->SetProperties(ConcatProperties(props1, props2), kFstProperties);
163  } else {
164  fst2->SetStart(fst2->AddState());
165  }
166 }
167 
168 // Same as the above but can handle arbitrarily many left-hand-side FSTs,
169 // preallocating the states.
170 template <class Arc>
171 void Concat(const std::vector<const Fst<Arc> *> &fsts1, MutableFst<Arc> *fst2) {
172  fst2->ReserveStates(CountStates(fsts1) + fst2->NumStates());
173  for (const auto *fst1 : fsts1) Concat(*fst1, fst2);
174 }
175 
176 // Computes the concatentation of two FSTs. This version modifies its
177 // RationalFst input (in second position).
178 template <class Arc>
179 void Concat(const Fst<Arc> &fst1, RationalFst<Arc> *fst2) {
180  fst2->GetMutableImpl()->AddConcat(fst1, false);
181 }
182 
184 
185 // Computes the concatenation (product) of two FSTs; this version is a delayed
186 // FST. If FST1 transduces string x to y with weight a and FST2 transduces
187 // string w to v with weight b, then their concatenation transduces string xw
188 // to yv with Times(a, b).
189 //
190 // Complexity:
191 //
192 // Time: O(v1 + e1 + v2 + e2),
193 // Space: O(v1 + v2)
194 //
195 // where vi is the number of states visited, and ei is the number of arcs
196 // visited, of the ith FST. Constant time and space to visit an input state or
197 // arc is assumed and exclusive of caching.
198 template <class A>
199 class ConcatFst : public RationalFst<A> {
200  public:
201  using Arc = A;
202  using StateId = typename Arc::StateId;
203  using Weight = typename Arc::Weight;
204 
205  ConcatFst(const Fst<Arc> &fst1, const Fst<Arc> &fst2) {
206  GetMutableImpl()->InitConcat(fst1, fst2);
207  }
208 
209  ConcatFst(const Fst<Arc> &fst1, const Fst<Arc> &fst2,
210  const ConcatFstOptions &opts)
211  : RationalFst<Arc>(opts) {
212  GetMutableImpl()->InitConcat(fst1, fst2);
213  }
214 
215  // See Fst<>::Copy() for doc.
216  ConcatFst(const ConcatFst &fst, bool safe = false)
217  : RationalFst<Arc>(fst, safe) {}
218 
219  // Get a copy of this ConcatFst. See Fst<>::Copy() for further doc.
220  ConcatFst *Copy(bool safe = false) const override {
221  return new ConcatFst(*this, safe);
222  }
223 
224  private:
227 };
228 
229 // Specialization for ConcatFst.
230 template <class Arc>
231 class StateIterator<ConcatFst<Arc>> : public StateIterator<RationalFst<Arc>> {
232  public:
234  : StateIterator<RationalFst<Arc>>(fst) {}
235 };
236 
237 // Specialization for ConcatFst.
238 template <class Arc>
239 class ArcIterator<ConcatFst<Arc>> : public ArcIterator<RationalFst<Arc>> {
240  public:
241  using StateId = typename Arc::StateId;
242 
244  : ArcIterator<RationalFst<Arc>>(fst, s) {}
245 };
246 
247 // Useful alias when using StdArc.
249 
250 } // namespace fst
251 
252 #endif // FST_CONCAT_H_
uint64_t ConcatProperties(uint64_t inprops1, uint64_t inprops2, bool delayed=false)
Definition: properties.cc:95
virtual uint64_t Properties(uint64_t mask, bool test) const =0
virtual size_t NumArcs(StateId) const =0
typename Arc::StateId StateId
Definition: concat.h:202
const SymbolTable * InputSymbols() const override=0
constexpr uint64_t kError
Definition: properties.h:52
ConcatFst(const Fst< Arc > &fst1, const Fst< Arc > &fst2, const ConcatFstOptions &opts)
Definition: concat.h:209
virtual Weight Final(StateId) const =0
virtual void SetStart(StateId)=0
typename ReplaceFst< Arc >::Arc Arc
Definition: fst.h:408
typename Arc::Weight Weight
Definition: concat.h:203
CacheOptions RationalFstOptions
Definition: rational.h:42
constexpr int kNoStateId
Definition: fst.h:196
virtual void ReserveArcs(StateId, size_t)
Definition: mutable-fst.h:104
ArcIterator(const ConcatFst< Arc > &fst, StateId s)
Definition: concat.h:243
#define FSTERROR()
Definition: util.h:56
const SymbolTable * OutputSymbols() const override=0
typename Arc::StateId StateId
Definition: concat.h:241
virtual void SetProperties(uint64_t props, uint64_t mask)=0
virtual StateId Start() const =0
ConcatFst(const Fst< Arc > &fst1, const Fst< Arc > &fst2)
Definition: concat.h:205
virtual std::optional< StateId > NumStatesIfKnown() const
Definition: fst.h:228
void Concat(MutableFst< Arc > *fst1, const Fst< Arc > &fst2)
Definition: concat.h:55
constexpr uint64_t kFstProperties
Definition: properties.h:326
virtual void AddArc(StateId, const Arc &)=0
typename ReplaceFst< Arc >::Arc Arc
Definition: cache.h:1202
virtual const SymbolTable * InputSymbols() const =0
Arc::StateId CountStates(const Fst< Arc > &fst)
Definition: expanded-fst.h:179
ConcatFst(const ConcatFst &fst, bool safe=false)
Definition: concat.h:216
virtual StateId AddState()=0
virtual void ReserveStates(size_t)
Definition: mutable-fst.h:101
virtual void SetFinal(StateId s, Weight weight=Weight::One())=0
StateIterator(const ConcatFst< Arc > &fst)
Definition: concat.h:233
bool CompatSymbols(const SymbolTable *syms1, const SymbolTable *syms2, bool warning=true)
ConcatFst * Copy(bool safe=false) const override
Definition: concat.h:220
internal::RationalFstImpl< A > * GetMutableImpl() const
Definition: impl-to-fst.h:125
virtual StateId NumStates() const =0
const internal::RationalFstImpl< A > * GetImpl() const
Definition: impl-to-fst.h:123
virtual const SymbolTable * OutputSymbols() const =0