1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
//! Utility types and data structures for FST operations.
//!
//! This module provides essential supporting utilities used throughout the ArcWeight
//! library for symbol management, state exploration queues, FST visualization, arc
//! encoding, and path iteration.
//!
//! # Overview
//!
//! The utilities in this module fall into several categories:
//!
//! | Component | Purpose | Complexity |
//! |-----------|---------|------------|
//! | [`SymbolTable`] | Symbol-to-label bidirectional mapping | O(1) lookup |
//! | [`Queue`] types | State exploration for FST algorithms | O(1) to O(log n) |
//! | [`EncodeMapper`] | Arc compression for memory efficiency | O(1) per arc |
//! | [`PathsIterator`] | Enumerate accepting paths | O(paths) |
//! | [`DrawingConfig`] | GraphViz DOT visualization | O(V + E) |
//!
//! # Symbol Tables
//!
//! [`SymbolTable`] manages bidirectional mapping between human-readable symbols and
//! numeric labels used in FST arcs:
//!
//! ```
//! use arcweight::utils::SymbolTable;
//!
//! let mut symbols = SymbolTable::new();
//!
//! // Add symbols and get their IDs
//! let cat_id = symbols.add_symbol("cat");
//! let dog_id = symbols.add_symbol("dog");
//!
//! // Bidirectional lookup
//! assert_eq!(symbols.find_id("cat"), Some(cat_id));
//! assert_eq!(symbols.find(cat_id), Some("cat"));
//!
//! // Epsilon is always label 0
//! assert_eq!(symbols.find(0), Some("<eps>"));
//! ```
//!
//! # Queue Types
//!
//! Different queue implementations support various FST traversal strategies:
//!
//! | Queue | Order | Algorithm | Complexity |
//! |-------|-------|-----------|------------|
//! | [`FifoQueue`] | First-In-First-Out | BFS, shortest path | O(1) |
//! | [`LifoQueue`] | Last-In-First-Out | DFS, cycle detection | O(1) |
//! | [`StateQueue`] | Priority-based | Dijkstra, A* | O(log n) |
//! | [`TopOrderQueue`] | Topological | DP on DAGs | O(1) |
//!
//! All queues implement the [`Queue`] trait for algorithm genericity:
//!
//! ```
//! use arcweight::prelude::*;
//! use arcweight::utils::{Queue, FifoQueue, LifoQueue};
//!
//! fn explore_fst<Q: Queue>(fst: &impl Fst<TropicalWeight>, mut queue: Q) {
//! if let Some(start) = fst.start() {
//! queue.enqueue(start);
//! while let Some(state) = queue.dequeue() {
//! for arc in fst.arcs(state) {
//! queue.enqueue(arc.nextstate);
//! }
//! }
//! }
//! }
//!
//! let fst = VectorFst::<TropicalWeight>::new();
//! explore_fst(&fst, FifoQueue::new()); // Breadth-first
//! explore_fst(&fst, LifoQueue::new()); // Depth-first
//! ```
//!
//! # Arc Encoding
//!
//! [`EncodeMapper`] compresses FST arcs by mapping repeated label pairs and weights
//! to compact integer representations:
//!
//! ```
//! use arcweight::utils::{EncodeMapper, EncodeType};
//! use arcweight::prelude::*;
//!
//! let mut encoder = EncodeMapper::<TropicalWeight>::new(EncodeType::EncodeLabelsOnly);
//!
//! let arc = Arc::new(97, 98, TropicalWeight::new(0.5), 1);
//! let encoded = encoder.encode(&arc);
//!
//! // Same label pair always maps to same encoded value
//! let arc2 = Arc::new(97, 98, TropicalWeight::new(1.0), 2);
//! let encoded2 = encoder.encode(&arc2);
//! assert_eq!(encoded.ilabel, encoded2.ilabel);
//! ```
//!
//! # Path Iteration
//!
//! [`PathsIterator`] and [`StringPathsIterator`] enumerate accepting paths through
//! an FST with optional filtering:
//!
//! ```
//! use arcweight::prelude::*;
//! use arcweight::utils::PathIterExt;
//!
//! let mut fst = VectorFst::<TropicalWeight>::new();
//! let s0 = fst.add_state();
//! let s1 = fst.add_state();
//! fst.set_start(s0);
//! fst.set_final(s1, TropicalWeight::one());
//! fst.add_arc(s0, Arc::new(1, 2, TropicalWeight::new(0.5), s1));
//!
//! for path in fst.paths_iter().with_max_paths(10) {
//! println!("Path weight: {:?}", path.weight);
//! }
//! ```
//!
//! # FST Visualization
//!
//! [`draw_fst`] generates GraphViz DOT format for FST visualization:
//!
//! ```
//! use arcweight::prelude::*;
//! use arcweight::utils::{draw_fst_default, DrawingConfig};
//!
//! let mut fst = VectorFst::<TropicalWeight>::new();
//! let s0 = fst.add_state();
//! let s1 = fst.add_state();
//! fst.set_start(s0);
//! fst.set_final(s1, TropicalWeight::one());
//! fst.add_arc(s0, Arc::new(1, 1, TropicalWeight::new(0.5), s1));
//!
//! let dot = draw_fst_default(&fst).unwrap();
//! // Output can be rendered with: dot -Tpng fst.dot -o fst.png
//! ```
//!
//! # Performance Characteristics
//!
//! | Component | Memory | Time (typical operation) |
//! |-----------|--------|-------------------------|
//! | `SymbolTable` | O(n) symbols | O(1) lookup |
//! | `FifoQueue` | O(n) states | O(1) enqueue/dequeue |
//! | `LifoQueue` | O(depth) | O(1) push/pop |
//! | `StateQueue` | O(n) states | O(log n) operations |
//! | `EncodeMapper` | O(unique labels) | O(1) per arc |
//!
//! # References
//!
//! - Mehryar Mohri, Fernando Pereira, and Michael Riley. 2002. Weighted
//! finite-state transducers in speech recognition. *Computer Speech &
//! Language* 16, 1 (2002), 69-88.
//! <https://doi.org/10.1006/csla.2001.0184>
pub use ;
pub use ;
pub use ;
pub use ;
pub use SymbolTable;