FST  openfst-1.8.3
OpenFst Library
properties.cc
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 for updating property bits for various FST operations and
19 // string names of the properties.
20 
21 #include <fst/properties.h>
22 
23 #include <cstddef>
24 #include <cstdint>
25 #include <vector>
26 
27 #include <string_view>
28 
29 namespace fst {
30 
31 // These functions determine the properties associated with the FST result of
32 // various finite-state operations. The property arguments correspond to the
33 // operation's FST arguments. The properties returned assume the operation
34 // modifies its first argument. Bitwise-and this result with kCopyProperties for
35 // the case when a new (possibly delayed) FST is instead constructed.
36 
37 // Properties for a concatenatively-closed FST.
38 uint64_t ClosureProperties(uint64_t inprops, bool, bool delayed) {
39  auto outprops = (kError | kAcceptor | kUnweighted | kAccessible) & inprops;
40  if (inprops & kUnweighted) outprops |= kUnweightedCycles;
41  if (!delayed) {
42  outprops |=
44  inprops;
45  }
46  if (!delayed || inprops & kAccessible) {
50  inprops;
51  if ((inprops & kWeighted) && (inprops & kAccessible) &&
52  (inprops & kCoAccessible)) {
53  outprops |= kWeightedCycles;
54  }
55  }
56  return outprops;
57 }
58 
59 // Properties for a complemented FST.
60 uint64_t ComplementProperties(uint64_t inprops) {
61  auto outprops = kAcceptor | kUnweighted | kUnweightedCycles | kNoEpsilons |
64  outprops |=
66  if (inprops & kAccessible) {
68  }
69  return outprops;
70 }
71 
72 // Properties for a composed FST.
73 uint64_t ComposeProperties(uint64_t inprops1, uint64_t inprops2) {
74  auto outprops = kError & (inprops1 | inprops2);
75  if (inprops1 & kAcceptor && inprops2 & kAcceptor) {
76  outprops |= kAcceptor | kAccessible;
77  outprops |= (kNoEpsilons | kNoIEpsilons | kNoOEpsilons | kAcyclic |
79  inprops1 & inprops2;
80  if (kNoIEpsilons & inprops1 & inprops2) {
81  outprops |= (kIDeterministic | kODeterministic) & inprops1 & inprops2;
82  }
83  } else {
84  outprops |= kAccessible;
85  outprops |= (kAcceptor | kNoIEpsilons | kAcyclic | kInitialAcyclic) &
86  inprops1 & inprops2;
87  if (kNoIEpsilons & inprops1 & inprops2) {
88  outprops |= kIDeterministic & inprops1 & inprops2;
89  }
90  }
91  return outprops;
92 }
93 
94 // Properties for a concatenated FST.
95 uint64_t ConcatProperties(uint64_t inprops1, uint64_t inprops2, bool delayed) {
96  auto outprops = (kAcceptor | kUnweighted | kUnweightedCycles | kAcyclic) &
97  inprops1 & inprops2;
98  outprops |= kError & (inprops1 | inprops2);
99  const bool empty1 = delayed; // Can the first FST be the empty machine?
100  const bool empty2 = delayed; // Can the second FST be the empty machine?
101  if (!delayed) {
102  outprops |= (kExpanded | kMutable | kNotTopSorted | kNotString) & inprops1;
103  outprops |= (kNotTopSorted | kNotString) & inprops2;
104  }
105  if (!empty1) outprops |= (kInitialAcyclic | kInitialCyclic) & inprops1;
106  if (!delayed || inprops1 & kAccessible) {
111  inprops1;
112  }
113  if ((inprops1 & (kAccessible | kCoAccessible)) ==
114  (kAccessible | kCoAccessible) &&
115  !empty1) {
116  outprops |= kAccessible & inprops2;
117  if (!empty2) outprops |= kCoAccessible & inprops2;
118  if (!delayed || inprops2 & kAccessible) {
123  inprops2;
124  }
125  }
126  return outprops;
127 }
128 
129 // Properties for a determinized FST.
130 uint64_t DeterminizeProperties(uint64_t inprops, bool has_subsequential_label,
131  bool distinct_psubsequential_labels) {
132  auto outprops = kAccessible;
133  if ((kAcceptor & inprops) ||
134  ((kNoIEpsilons & inprops) && distinct_psubsequential_labels) ||
135  (has_subsequential_label && distinct_psubsequential_labels)) {
136  outprops |= kIDeterministic;
137  }
138  outprops |= (kError | kAcceptor | kAcyclic | kInitialAcyclic | kCoAccessible |
139  kString) &
140  inprops;
141  if ((inprops & kNoIEpsilons) && distinct_psubsequential_labels) {
142  outprops |= kNoEpsilons & inprops;
143  }
144  if (inprops & kAccessible) {
145  outprops |= (kIEpsilons | kOEpsilons | kCyclic) & inprops;
146  }
147  if (inprops & kAcceptor) outprops |= (kNoIEpsilons | kNoOEpsilons) & inprops;
148  if ((inprops & kNoIEpsilons) && has_subsequential_label) {
149  outprops |= kNoIEpsilons;
150  }
151  return outprops;
152 }
153 
154 // Properties for factored weight FST.
155 uint64_t FactorWeightProperties(uint64_t inprops) {
156  auto outprops = (kExpanded | kMutable | kError | kAcceptor | kAcyclic |
158  inprops;
159  if (inprops & kAccessible) {
163  inprops;
164  }
165  return outprops;
166 }
167 
168 // Properties for an inverted FST.
169 uint64_t InvertProperties(uint64_t inprops) {
170  auto outprops = (kExpanded | kMutable | kError | kAcceptor | kNotAcceptor |
176  inprops;
177  if (kIDeterministic & inprops) outprops |= kODeterministic;
178  if (kNonIDeterministic & inprops) outprops |= kNonODeterministic;
179  if (kODeterministic & inprops) outprops |= kIDeterministic;
180  if (kNonODeterministic & inprops) outprops |= kNonIDeterministic;
181 
182  if (kIEpsilons & inprops) outprops |= kOEpsilons;
183  if (kNoIEpsilons & inprops) outprops |= kNoOEpsilons;
184  if (kOEpsilons & inprops) outprops |= kIEpsilons;
185  if (kNoOEpsilons & inprops) outprops |= kNoIEpsilons;
186 
187  if (kILabelSorted & inprops) outprops |= kOLabelSorted;
188  if (kNotILabelSorted & inprops) outprops |= kNotOLabelSorted;
189  if (kOLabelSorted & inprops) outprops |= kILabelSorted;
190  if (kNotOLabelSorted & inprops) outprops |= kNotILabelSorted;
191  return outprops;
192 }
193 
194 // Properties for a projected FST.
195 uint64_t ProjectProperties(uint64_t inprops, bool project_input) {
196  auto outprops = kAcceptor;
197  outprops |= (kExpanded | kMutable | kError | kWeighted | kUnweighted |
201  kString | kNotString) &
202  inprops;
203  if (project_input) {
206  inprops;
207 
208  if (kIDeterministic & inprops) outprops |= kODeterministic;
209  if (kNonIDeterministic & inprops) outprops |= kNonODeterministic;
210 
211  if (kIEpsilons & inprops) outprops |= kOEpsilons | kEpsilons;
212  if (kNoIEpsilons & inprops) outprops |= kNoOEpsilons | kNoEpsilons;
213 
214  if (kILabelSorted & inprops) outprops |= kOLabelSorted;
215  if (kNotILabelSorted & inprops) outprops |= kNotOLabelSorted;
216  } else {
219  inprops;
220 
221  if (kODeterministic & inprops) outprops |= kIDeterministic;
222  if (kNonODeterministic & inprops) outprops |= kNonIDeterministic;
223 
224  if (kOEpsilons & inprops) outprops |= kIEpsilons | kEpsilons;
225  if (kNoOEpsilons & inprops) outprops |= kNoIEpsilons | kNoEpsilons;
226 
227  if (kOLabelSorted & inprops) outprops |= kILabelSorted;
228  if (kNotOLabelSorted & inprops) outprops |= kNotILabelSorted;
229  }
230  return outprops;
231 }
232 
233 // Properties for a randgen FST.
234 uint64_t RandGenProperties(uint64_t inprops, bool weighted) {
236  outprops |= inprops & kError;
237  if (weighted) {
238  outprops |= kTopSorted;
239  outprops |=
242  inprops;
243  } else {
244  outprops |= kUnweighted;
245  outprops |= (kAcceptor | kILabelSorted | kOLabelSorted) & inprops;
246  }
247  return outprops;
248 }
249 
250 // Properties for a replace FST.
251 uint64_t ReplaceProperties(const std::vector<uint64_t> &inprops, size_t root,
252  bool epsilon_on_call, bool epsilon_on_return,
253  bool out_epsilon_on_call, bool out_epsilon_on_return,
254  bool replace_transducer, bool no_empty_fsts,
255  bool all_ilabel_sorted, bool all_olabel_sorted,
256  bool all_negative_or_dense) {
257  if (inprops.empty()) return kNullProperties;
258  uint64_t outprops = 0;
259  for (auto inprop : inprops) outprops |= kError & inprop;
260  uint64_t access_props = no_empty_fsts ? kAccessible | kCoAccessible : 0;
261  for (auto inprop : inprops) {
262  access_props &= (inprop & (kAccessible | kCoAccessible));
263  }
264  if (access_props == (kAccessible | kCoAccessible)) {
265  outprops |= access_props;
266  if (inprops[root] & kInitialCyclic) outprops |= kInitialCyclic;
267  uint64_t props = 0;
268  bool string = true;
269  for (auto inprop : inprops) {
270  if (replace_transducer) props |= kNotAcceptor & inprop;
274  inprop;
275  if (!(inprop & kString)) string = false;
276  }
277  outprops |= props;
278  if (string) outprops |= kString;
279  }
280  bool acceptor = !replace_transducer;
281  bool ideterministic = !epsilon_on_call && epsilon_on_return;
282  bool no_iepsilons = !epsilon_on_call && !epsilon_on_return;
283  bool acyclic = true;
284  bool unweighted = true;
285  for (size_t i = 0; i < inprops.size(); ++i) {
286  if (!(inprops[i] & kAcceptor)) acceptor = false;
287  if (!(inprops[i] & kIDeterministic)) ideterministic = false;
288  if (!(inprops[i] & kNoIEpsilons)) no_iepsilons = false;
289  if (!(inprops[i] & kAcyclic)) acyclic = false;
290  if (!(inprops[i] & kUnweighted)) unweighted = false;
291  if (i != root && !(inprops[i] & kNoIEpsilons)) ideterministic = false;
292  }
293  if (acceptor) outprops |= kAcceptor;
294  if (ideterministic) outprops |= kIDeterministic;
295  if (no_iepsilons) outprops |= kNoIEpsilons;
296  if (acyclic) outprops |= kAcyclic;
297  if (unweighted) outprops |= kUnweighted;
298  if (inprops[root] & kInitialAcyclic) outprops |= kInitialAcyclic;
299  // We assume that all terminals are positive. The resulting ReplaceFst is
300  // known to be kILabelSorted when: (1) all sub-FSTs are kILabelSorted, (2) the
301  // input label of the return arc is epsilon, and (3) one of the 3 following
302  // conditions is satisfied:
303  //
304  // 1. the input label of the call arc is not epsilon
305  // 2. all non-terminals are negative, or
306  // 3. all non-terninals are positive and form a dense range containing 1.
307  if (all_ilabel_sorted && epsilon_on_return &&
308  (!epsilon_on_call || all_negative_or_dense)) {
309  outprops |= kILabelSorted;
310  }
311  // Similarly, the resulting ReplaceFst is known to be kOLabelSorted when: (1)
312  // all sub-FSTs are kOLabelSorted, (2) the output label of the return arc is
313  // epsilon, and (3) one of the 3 following conditions is satisfied:
314  //
315  // 1. the output label of the call arc is not epsilon
316  // 2. all non-terminals are negative, or
317  // 3. all non-terninals are positive and form a dense range containing 1.
318  if (all_olabel_sorted && out_epsilon_on_return &&
319  (!out_epsilon_on_call || all_negative_or_dense)) {
320  outprops |= kOLabelSorted;
321  }
322  return outprops;
323 }
324 
325 // Properties for a relabeled FST.
326 uint64_t RelabelProperties(uint64_t inprops) {
327  static constexpr auto outprops =
333  return outprops & inprops;
334 }
335 
336 // Properties for a reversed FST (the superinitial state limits this set).
337 uint64_t ReverseProperties(uint64_t inprops, bool has_superinitial) {
338  auto outprops = (kExpanded | kMutable | kError | kAcceptor | kNotAcceptor |
341  inprops;
342  if (has_superinitial) outprops |= kWeighted & inprops;
343  return outprops;
344 }
345 
346 // Properties for re-weighted FST.
347 uint64_t ReweightProperties(uint64_t inprops, bool added_start_epsilon) {
348  auto outprops = inprops & kWeightInvariantProperties;
349  outprops = outprops & ~kCoAccessible;
350  if (added_start_epsilon) {
353  }
354  return outprops;
355 }
356 
357 // Properties for an epsilon-removed FST.
358 uint64_t RmEpsilonProperties(uint64_t inprops, bool delayed) {
359  auto outprops = kNoEpsilons;
360  outprops |= (kError | kAcceptor | kAcyclic | kInitialAcyclic) & inprops;
361  if (inprops & kAcceptor) outprops |= kNoIEpsilons | kNoOEpsilons;
362  if (!delayed) {
363  outprops |= kExpanded | kMutable;
364  outprops |= kTopSorted & inprops;
365  }
366  if (!delayed || inprops & kAccessible) outprops |= kNotAcceptor & inprops;
367  return outprops;
368 }
369 
370 // Properties for shortest path. This function computes how the properties of
371 // the output of shortest path need to be updated, given that 'props' is already
372 // known.
373 uint64_t ShortestPathProperties(uint64_t props, bool tree) {
374  auto outprops =
376  if (!tree) outprops |= kCoAccessible;
377  return outprops;
378 }
379 
380 // Properties for a synchronized FST.
381 uint64_t SynchronizeProperties(uint64_t inprops) {
382  auto outprops = (kError | kAcceptor | kAcyclic | kAccessible | kCoAccessible |
384  inprops;
385  if (inprops & kAccessible) {
386  outprops |=
388  }
389  return outprops;
390 }
391 
392 // Properties for a unioned FST.
393 uint64_t UnionProperties(uint64_t inprops1, uint64_t inprops2, bool delayed) {
394  auto outprops =
396  inprops1 & inprops2;
397  outprops |= kError & (inprops1 | inprops2);
398  outprops |= kInitialAcyclic;
399  bool empty1 = delayed; // Can the first FST be the empty machine?
400  bool empty2 = delayed; // Can the second FST be the empty machine?
401  if (!delayed) {
402  outprops |= (kExpanded | kMutable | kNotTopSorted) & inprops1;
403  outprops |= kNotTopSorted & inprops2;
404  }
405  if (!empty1 && !empty2) {
406  outprops |= kEpsilons | kIEpsilons | kOEpsilons;
407  outprops |= kCoAccessible & inprops1 & inprops2;
408  }
409  // Note kNotCoAccessible does not hold because of kInitialAcyclic option.
410  if (!delayed || inprops1 & kAccessible) {
411  outprops |=
415  inprops1;
416  }
417  if (!delayed || inprops2 & kAccessible) {
422  inprops2;
423  }
424  return outprops;
425 }
426 
427 namespace internal {
428 // Property string names (indexed by bit position).
429 const std::string_view PropertyNames[] = {
430  // Binary.
431  "expanded", "mutable", "error", "", "", "", "", "", "", "", "", "", "", "",
432  "", "",
433  // Ternary.
434  "acceptor", "not acceptor", "input deterministic",
435  "non input deterministic", "output deterministic",
436  "non output deterministic", "input/output epsilons",
437  "no input/output epsilons", "input epsilons", "no input epsilons",
438  "output epsilons", "no output epsilons", "input label sorted",
439  "not input label sorted", "output label sorted", "not output label sorted",
440  "weighted", "unweighted", "cyclic", "acyclic", "cyclic at initial state",
441  "acyclic at initial state", "top sorted", "not top sorted", "accessible",
442  "not accessible", "coaccessible", "not coaccessible", "string",
443  "not string", "weighted cycles", "unweighted cycles"};
444 } // namespace internal
445 } // namespace fst
uint64_t ConcatProperties(uint64_t inprops1, uint64_t inprops2, bool delayed=false)
Definition: properties.cc:95
constexpr uint64_t kCyclic
Definition: properties.h:109
constexpr uint64_t kNotString
Definition: properties.h:139
uint64_t RandGenProperties(uint64_t inprops, bool weighted)
Definition: properties.cc:234
constexpr uint64_t kMutable
Definition: properties.h:49
constexpr uint64_t kWeightedCycles
Definition: properties.h:142
constexpr uint64_t kWeightInvariantProperties
Definition: properties.h:280
constexpr uint64_t kOEpsilons
Definition: properties.h:89
constexpr uint64_t kInitialCyclic
Definition: properties.h:114
uint64_t ComposeProperties(uint64_t inprops1, uint64_t inprops2)
Definition: properties.cc:73
constexpr uint64_t kCoAccessible
Definition: properties.h:129
uint64_t RmEpsilonProperties(uint64_t inprops, bool delayed=false)
Definition: properties.cc:358
constexpr uint64_t kNotAccessible
Definition: properties.h:126
constexpr uint64_t kNotTopSorted
Definition: properties.h:121
uint64_t ShortestPathProperties(uint64_t props, bool tree=false)
Definition: properties.cc:373
constexpr uint64_t kError
Definition: properties.h:52
constexpr uint64_t kInitialAcyclic
Definition: properties.h:116
constexpr uint64_t kUnweightedCycles
Definition: properties.h:145
constexpr uint64_t kEpsilons
Definition: properties.h:79
constexpr uint64_t kNotOLabelSorted
Definition: properties.h:101
constexpr uint64_t kTopSorted
Definition: properties.h:119
constexpr uint64_t kODeterministic
Definition: properties.h:74
uint64_t RelabelProperties(uint64_t inprops)
Definition: properties.cc:326
constexpr uint64_t kNonIDeterministic
Definition: properties.h:71
constexpr uint64_t kNotILabelSorted
Definition: properties.h:96
uint64_t ReverseProperties(uint64_t inprops, bool has_superinitial)
Definition: properties.cc:337
uint64_t ClosureProperties(uint64_t inprops, bool star, bool delayed=false)
Definition: properties.cc:38
uint64_t UnionProperties(uint64_t inprops1, uint64_t inprops2, bool delayed=false)
Definition: properties.cc:393
constexpr uint64_t kNoOEpsilons
Definition: properties.h:91
constexpr uint64_t kOLabelSorted
Definition: properties.h:99
constexpr uint64_t kNotAcceptor
Definition: properties.h:66
constexpr uint64_t kAcyclic
Definition: properties.h:111
uint64_t ReplaceProperties(const std::vector< uint64_t > &inprops, size_t root, bool epsilon_on_call, bool epsilon_on_return, bool out_epsilon_on_call, bool out_epsilon_on_return, bool replace_transducer, bool no_empty_fst, bool all_ilabel_sorted, bool all_olabel_sorted, bool all_negative_or_dense)
Definition: properties.cc:251
uint64_t FactorWeightProperties(uint64_t inprops)
Definition: properties.cc:155
constexpr uint64_t kNoEpsilons
Definition: properties.h:81
uint64_t ReweightProperties(uint64_t inprops, bool added_start_epsilon)
Definition: properties.cc:347
constexpr uint64_t kAccessible
Definition: properties.h:124
constexpr uint64_t kIDeterministic
Definition: properties.h:69
constexpr uint64_t kNullProperties
Definition: properties.h:150
uint64_t ComplementProperties(uint64_t inprops)
Definition: properties.cc:60
constexpr uint64_t kIEpsilons
Definition: properties.h:84
constexpr uint64_t kILabelSorted
Definition: properties.h:94
constexpr uint64_t kUnweighted
Definition: properties.h:106
uint64_t InvertProperties(uint64_t inprops)
Definition: properties.cc:169
uint64_t DeterminizeProperties(uint64_t inprops, bool has_subsequential_label, bool distinct_psubsequential_labels)
Definition: properties.cc:130
constexpr uint64_t kNonODeterministic
Definition: properties.h:76
const std::string_view PropertyNames[]
Definition: properties.cc:429
constexpr uint64_t kString
Definition: properties.h:136
uint64_t ProjectProperties(uint64_t inprops, bool project_input)
Definition: properties.cc:195
constexpr uint64_t kNotCoAccessible
Definition: properties.h:131
constexpr uint64_t kWeighted
Definition: properties.h:104
constexpr uint64_t kExpanded
Definition: properties.h:46
uint64_t SynchronizeProperties(uint64_t inprops)
Definition: properties.cc:381
constexpr uint64_t kNoIEpsilons
Definition: properties.h:86
constexpr uint64_t kAcceptor
Definition: properties.h:64