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