FST  openfst-1.8.3
OpenFst Library
compose.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 // Compose an MPDT and an FST.
19 
20 #ifndef FST_EXTENSIONS_MPDT_COMPOSE_H_
21 #define FST_EXTENSIONS_MPDT_COMPOSE_H_
22 
23 #include <sys/types.h>
24 
25 #include <cstdint>
26 #include <list>
27 #include <utility>
28 #include <vector>
29 
32 #include <fst/compose-filter.h>
33 #include <fst/compose.h>
34 #include <fst/connect.h>
35 #include <fst/filter-state.h>
36 #include <fst/fst.h>
37 #include <fst/mutable-fst.h>
38 #include <fst/properties.h>
39 
40 namespace fst {
41 
42 template <class Filter>
44  public:
45  using FST1 = typename Filter::FST1;
46  using FST2 = typename Filter::FST2;
47  using Arc = typename Filter::Arc;
48  using Label = typename Arc::Label;
49  using StateId = typename Arc::StateId;
50  using Weight = typename Arc::Weight;
51 
52  using Matcher1 = typename Filter::Matcher1;
53  using Matcher2 = typename Filter::Matcher2;
54 
55  using StackId = StateId;
57  using FilterState1 = typename Filter::FilterState;
60 
61  MPdtParenFilter(const FST1 &fst1, const FST2 &fst2,
62  Matcher1 *matcher1 = nullptr, Matcher2 *matcher2 = nullptr,
63  const std::vector<std::pair<Label, Label>> *parens = nullptr,
64  const std::vector<Label> *assignments = nullptr,
65  bool expand = false, bool keep_parens = true)
66  : filter_(fst1, fst2, matcher1, matcher2),
67  parens_(parens ? *parens : std::vector<std::pair<Label, Label>>()),
68  assignments_(assignments ? *assignments : std::vector<Label>()),
69  expand_(expand),
70  keep_parens_(keep_parens),
71  fs_(FilterState::NoState()),
72  stack_(parens_, assignments_),
73  paren_id_(-1) {
74  if (parens) {
75  for (const auto &pair : *parens) {
76  parens_.push_back(pair);
77  GetMatcher1()->AddOpenParen(pair.first);
78  GetMatcher2()->AddOpenParen(pair.first);
79  if (!expand_) {
80  GetMatcher1()->AddCloseParen(pair.second);
81  GetMatcher2()->AddCloseParen(pair.second);
82  }
83  }
84  }
85  }
86 
87  MPdtParenFilter(const MPdtParenFilter &filter, bool safe = false)
88  : filter_(filter.filter_, safe),
89  parens_(filter.parens_),
90  expand_(filter.expand_),
91  keep_parens_(filter.keep_parens_),
92  fs_(FilterState::NoState()),
93  stack_(filter.parens_, filter.assignments_),
94  paren_id_(-1) {}
95 
96  FilterState Start() const {
97  return FilterState(filter_.Start(), FilterState2(0));
98  }
99 
100  void SetState(StateId s1, StateId s2, const FilterState &fs) {
101  fs_ = fs;
102  filter_.SetState(s1, s2, fs_.GetState1());
103  if (!expand_) return;
104  const auto paren_id = stack_.Top(fs.GetState2().GetState());
105  if (paren_id != paren_id_) {
106  if (paren_id_ != -1) {
107  GetMatcher1()->RemoveCloseParen(parens_[paren_id_].second);
108  GetMatcher2()->RemoveCloseParen(parens_[paren_id_].second);
109  }
110  paren_id_ = paren_id;
111  if (paren_id_ != -1) {
112  GetMatcher1()->AddCloseParen(parens_[paren_id_].second);
113  GetMatcher2()->AddCloseParen(parens_[paren_id_].second);
114  }
115  }
116  }
117 
118  FilterState FilterArc(Arc *arc1, Arc *arc2) const {
119  const auto fs1 = filter_.FilterArc(arc1, arc2);
120  const auto &fs2 = fs_.GetState2();
121  if (fs1 == FilterState1::NoState()) return FilterState::NoState();
122  if (arc1->olabel == kNoLabel && arc2->ilabel) { // arc2 parentheses.
123  if (keep_parens_) {
124  arc1->ilabel = arc2->ilabel;
125  } else if (arc2->ilabel) {
126  arc2->olabel = arc1->ilabel;
127  }
128  return FilterParen(arc2->ilabel, fs1, fs2);
129  } else if (arc2->ilabel == kNoLabel && arc1->olabel) { // arc1 parentheses
130  if (keep_parens_) {
131  arc2->olabel = arc1->olabel;
132  } else {
133  arc1->ilabel = arc2->olabel;
134  }
135  return FilterParen(arc1->olabel, fs1, fs2);
136  } else {
137  return FilterState(fs1, fs2);
138  }
139  }
140 
141  void FilterFinal(Weight *w1, Weight *w2) const {
142  if (fs_.GetState2().GetState() != 0) *w1 = Weight::Zero();
143  filter_.FilterFinal(w1, w2);
144  }
145 
146  // Returns respective matchers; ownership stays with filter.
147 
148  Matcher1 *GetMatcher1() { return filter_.GetMatcher1(); }
149 
150  Matcher2 *GetMatcher2() { return filter_.GetMatcher2(); }
151 
152  uint64_t Properties(uint64_t iprops) const {
153  const auto oprops = filter_.Properties(iprops);
155  }
156 
157  private:
158  const FilterState FilterParen(Label label, const FilterState1 &fs1,
159  const FilterState2 &fs2) const {
160  if (!expand_) return FilterState(fs1, fs2);
161  const auto stack_id = stack_.Find(fs2.GetState(), label);
162  if (stack_id < 0) {
163  return FilterState::NoState();
164  } else {
165  return FilterState(fs1, FilterState2(stack_id));
166  }
167  }
168 
169  Filter filter_;
170  std::vector<std::pair<Label, Label>> parens_;
171  std::vector<Label> assignments_;
172  bool expand_; // Expands to FST?
173  bool keep_parens_; // Retains parentheses in output?
174  FilterState fs_; // Current filter state.
175  mutable ParenStack stack_;
176  ssize_t paren_id_;
177 };
178 
179 // Class to setup composition options for MPDT composition. Default is to take
180 // the MPDT as the first composition argument.
181 template <class Arc, bool left_pdt = true>
183  : public ComposeFstOptions<
184  Arc, ParenMatcher<Fst<Arc>>,
185  MPdtParenFilter<AltSequenceComposeFilter<ParenMatcher<Fst<Arc>>>>> {
186  public:
187  using Label = typename Arc::Label;
190 
194 
196  const std::vector<std::pair<Label, Label>> &parens,
197  const std::vector<typename Arc::Label> &assignments,
198  const Fst<Arc> &ifst2, bool expand = false,
199  bool keep_parens = true) {
200  matcher1 = new MPdtMatcher(ifst1, MATCH_OUTPUT, kParenList);
201  matcher2 = new MPdtMatcher(ifst2, MATCH_INPUT, kParenLoop);
202  filter = new MPdtFilter(ifst1, ifst2, matcher1, matcher2, &parens,
203  &assignments, expand, keep_parens);
204  }
205 };
206 
207 // Class to setup composition options for PDT with FST composition.
208 // Specialization is for the FST as the first composition argument.
209 template <class Arc>
211  : public ComposeFstOptions<
212  Arc, ParenMatcher<Fst<Arc>>,
213  MPdtParenFilter<SequenceComposeFilter<ParenMatcher<Fst<Arc>>>>> {
214  public:
215  using Label = typename Arc::Label;
218 
222 
223  MPdtComposeFstOptions(const Fst<Arc> &ifst1, const Fst<Arc> &ifst2,
224  const std::vector<std::pair<Label, Label>> &parens,
225  const std::vector<typename Arc::Label> &assignments,
226  bool expand = false, bool keep_parens = true) {
227  matcher1 = new MPdtMatcher(ifst1, MATCH_OUTPUT, kParenLoop);
228  matcher2 = new MPdtMatcher(ifst2, MATCH_INPUT, kParenList);
229  filter = new MPdtFilter(ifst1, ifst2, matcher1, matcher2, &parens,
230  &assignments, expand, keep_parens);
231  }
232 };
233 
235  bool connect; // Connect output?
236  PdtComposeFilter filter_type; // Which pre-defined filter to use.
237 
239  bool connect = true,
241  : connect(connect), filter_type(filter_type) {}
242 };
243 
244 // Composes multi-pushdown transducer (MPDT) encoded as an FST (1st arg) and an
245 // FST (2nd arg) with the result also an MPDT encoded as an FST (3rd arg). In
246 // theMPDTs, some transitions are labeled with open or close parentheses (and
247 // associated with a stack). To be interpreted as an MPDT, the parents on each
248 // stack must balance on a path (see MPdtExpand()). The open-close parenthesis
249 // label pairs are passed using the parens arguments, and the stack assignments
250 // are passed using the assignments argument.
251 template <class Arc>
252 void Compose(
253  const Fst<Arc> &ifst1,
254  const std::vector<std::pair<typename Arc::Label, typename Arc::Label>>
255  &parens,
256  const std::vector<typename Arc::Label> &assignments, const Fst<Arc> &ifst2,
257  MutableFst<Arc> *ofst,
258  const MPdtComposeOptions &opts = MPdtComposeOptions()) {
259  bool expand = opts.filter_type != PdtComposeFilter::PAREN;
260  bool keep_parens = opts.filter_type != PdtComposeFilter::EXPAND;
261  MPdtComposeFstOptions<Arc, true> copts(ifst1, parens, assignments, ifst2,
262  expand, keep_parens);
263  copts.gc_limit = 0;
264  *ofst = ComposeFst<Arc>(ifst1, ifst2, copts);
265  if (opts.connect) Connect(ofst);
266 }
267 
268 // Composes an FST (1st arg) and a multi-pushdown transducer (MPDT) encoded as
269 // an FST (2nd arg) with the result also an MPDT encoded as an FST (3rd arg).
270 // In the MPDTs, some transitions are labeled with open or close parentheses
271 // (and associated with a stack). To be interpreted as an MPDT, the parents on
272 // each stack must balance on a path (see MPdtExpand()). The open-close
273 // parenthesis label pairs are passed using the parens arguments, and the stack
274 // assignments are passed using the assignments argument.
275 template <class Arc>
276 void Compose(
277  const Fst<Arc> &ifst1, const Fst<Arc> &ifst2,
278  const std::vector<std::pair<typename Arc::Label, typename Arc::Label>>
279  &parens,
280  const std::vector<typename Arc::Label> &assignments, MutableFst<Arc> *ofst,
281  const MPdtComposeOptions &opts = MPdtComposeOptions()) {
282  bool expand = opts.filter_type != PdtComposeFilter::PAREN;
283  bool keep_parens = opts.filter_type != PdtComposeFilter::EXPAND;
284  MPdtComposeFstOptions<Arc, false> copts(ifst1, ifst2, parens, assignments,
285  expand, keep_parens);
286  copts.gc_limit = 0;
287  *ofst = ComposeFst<Arc>(ifst1, ifst2, copts);
288  if (opts.connect) Connect(ofst);
289 }
290 
291 } // namespace fst
292 
293 #endif // FST_EXTENSIONS_MPDT_COMPOSE_H_
MPdtComposeFstOptions(const Fst< Arc > &ifst1, const Fst< Arc > &ifst2, const std::vector< std::pair< Label, Label >> &parens, const std::vector< typename Arc::Label > &assignments, bool expand=false, bool keep_parens=true)
Definition: compose.h:223
constexpr uint32_t kParenLoop
Definition: compose.h:48
typename SequenceComposeFilter< ParenMatcher< Fst< Arc > > >::Arc Arc
Definition: compose.h:47
constexpr int kNoLabel
Definition: fst.h:195
typename SequenceComposeFilter< ParenMatcher< Fst< Arc > > >::Matcher1 Matcher1
Definition: compose.h:52
Matcher1 * GetMatcher1()
Definition: compose.h:148
ssize_t Top(StackId stack_id) const
Definition: mpdt.h:130
MPdtParenFilter(const MPdtParenFilter &filter, bool safe=false)
Definition: compose.h:87
MPdtComposeFstOptions(const Fst< Arc > &ifst1, const std::vector< std::pair< Label, Label >> &parens, const std::vector< typename Arc::Label > &assignments, const Fst< Arc > &ifst2, bool expand=false, bool keep_parens=true)
Definition: compose.h:195
IntegerFilterState< StackId > FilterState2
Definition: compose.h:58
void FilterFinal(Weight *w1, Weight *w2) const
Definition: compose.h:141
void Connect(MutableFst< Arc > *fst)
Definition: connect.h:47
typename SequenceComposeFilter< ParenMatcher< Fst< Arc > > >::Matcher2 Matcher2
Definition: compose.h:53
constexpr uint32_t kParenList
Definition: compose.h:45
typename SequenceComposeFilter< ParenMatcher< Fst< Arc > > >::FilterState FilterState1
Definition: compose.h:57
FilterState FilterArc(Arc *arc1, Arc *arc2) const
Definition: compose.h:118
typename SequenceComposeFilter< ParenMatcher< Fst< Arc > > >::FST2 FST2
Definition: compose.h:46
void Compose(const Fst< Arc > &ifst1, const Fst< Arc > &ifst2, MutableFst< Arc > *ofst, const ComposeOptions &opts=ComposeOptions())
Definition: compose.h:1005
constexpr uint64_t kOLabelInvariantProperties
Definition: properties.h:270
MPdtParenFilter(const FST1 &fst1, const FST2 &fst2, Matcher1 *matcher1=nullptr, Matcher2 *matcher2=nullptr, const std::vector< std::pair< Label, Label >> *parens=nullptr, const std::vector< Label > *assignments=nullptr, bool expand=false, bool keep_parens=true)
Definition: compose.h:61
void SetState(StateId s1, StateId s2, const FilterState &fs)
Definition: compose.h:100
constexpr uint64_t kILabelInvariantProperties
Definition: properties.h:261
FilterState Start() const
Definition: compose.h:96
MPdtComposeOptions(bool connect=true, PdtComposeFilter filter_type=PdtComposeFilter::PAREN)
Definition: compose.h:238
typename Arc::Label Label
Definition: compose.h:187
const FilterState1 & GetState1() const
Definition: filter-state.h:175
PairFilterState< FilterState1, FilterState2 > FilterState
Definition: compose.h:59
PdtComposeFilter filter_type
Definition: compose.h:236
uint64_t Properties(uint64_t iprops) const
Definition: compose.h:152
Matcher2 * GetMatcher2()
Definition: compose.h:150
const FilterState2 & GetState2() const
Definition: filter-state.h:177
typename SequenceComposeFilter< ParenMatcher< Fst< Arc > > >::FST1 FST1
Definition: compose.h:45
size_t gc_limit
Definition: cache.h:52
PdtComposeFilter
Definition: compose.h:466
StackId Find(StackId stack_id, Label label)
Definition: mpdt.h:268