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
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
//! # ArcWeight - Weighted Finite State Transducers for Rust
//!
//! A high-performance, type-safe library for constructing, combining, optimizing,
//! and searching weighted finite state transducers (WFSTs) and automata.
//!
//! ## Overview
//!
//! ArcWeight provides a toolkit for working with finite state machines,
//! from simple acceptors to complex weighted transducers. Built with performance and
//! correctness in mind, it leverages Rust's type system to ensure compile-time safety
//! while maintaining the flexibility needed for FST operations.
//!
//! The library implements the theoretical framework of weighted finite-state transducers
//! as formalized by Mohri, providing efficient algorithms for composition, determinization,
//! minimization, and shortest-path computation over arbitrary semirings.
//!
//! ## Key Features
//!
//! ### FST Support
//! - **Multiple implementations:** [`fst::VectorFst`] for construction, [`fst::ConstFst`] for deployment
//! - **Lazy evaluation:** On-demand computation with [`fst::LazyFstImpl`]
//! - **Memory efficiency:** Compact representations and caching strategies
//!
//! ### Extensible Semiring Library
//! - **Wide variety of semirings**, including:
//! - [`semiring::TropicalWeight`]
//! - [`semiring::ProbabilityWeight`]
//! - [`semiring::BooleanWeight`]
//! - [`semiring::LogWeight`]
//! - [`semiring::ProductWeight`]
//! - [`semiring::StringWeight`]
//! - **Extensible framework:** Implement custom semirings via traits
//!
//! ### Extensive Algorithm Library
//! - **Core operations:** [`algorithms::compose`], [`algorithms::concat`], [`algorithms::union`], [`algorithms::closure`]
//! - **Optimizations:** [`algorithms::minimize`], [`algorithms::determinize`], [`algorithms::remove_epsilons`]
//! - **Path algorithms:** [`algorithms::shortest_path`], [`algorithms::randgen`]
//! - **Additional transforms:** [`algorithms::synchronize`], [`algorithms::push_weights`]
//!
//! ### Property Analysis
//! - **Automatic property tracking:** Detect determinism, cyclicity, connectivity
//! - **Optimization guidance:** Algorithm selection based on FST properties
//! - **Efficient computation:** $`O(|V| + |E|)`$ property analysis
//!
//! ## Quick Start
//!
//! ```rust
//! use arcweight::prelude::*;
//!
//! // Build a simple acceptor for the pattern "ab+"
//! let mut fst = VectorFst::<TropicalWeight>::new();
//! let s0 = fst.add_state();
//! let s1 = fst.add_state();
//! let s2 = fst.add_state();
//!
//! fst.set_start(s0);
//! fst.set_final(s2, TropicalWeight::one());
//!
//! // Add transitions: 'a' -> 'b' -> 'b'*
//! fst.add_arc(s0, Arc::new('a' as u32, 'a' as u32, TropicalWeight::new(1.0), s1));
//! fst.add_arc(s1, Arc::new('b' as u32, 'b' as u32, TropicalWeight::new(0.5), s2));
//! fst.add_arc(s2, Arc::new('b' as u32, 'b' as u32, TropicalWeight::new(0.5), s2));
//!
//! // Find shortest accepting path
//! let shortest: VectorFst<TropicalWeight> = shortest_path(&fst, ShortestPathConfig::default())?;
//!
//! // Minimize the FST
//! let minimal: VectorFst<TropicalWeight> = minimize(&fst)?;
//! # Ok::<(), arcweight::Error>(())
//! ```
//!
//! ## Common Use Cases
//!
//! ### Building a Transducer
//!
//! ```
//! use arcweight::prelude::*;
//!
//! // Create a transducer that uppercases ASCII letters
//! let mut fst = VectorFst::<TropicalWeight>::new();
//! let state = fst.add_state();
//! fst.set_start(state);
//! fst.set_final(state, TropicalWeight::one());
//!
//! // Add lowercase->uppercase mappings
//! for c in b'a'..=b'z' {
//! let lower = c as u32;
//! let upper = (c - 32) as u32; // ASCII uppercase
//! fst.add_arc(state, Arc::new(lower, upper, TropicalWeight::one(), state));
//! }
//! ```
//!
//! ### Composing FSTs
//!
//! ```
//! use arcweight::prelude::*;
//!
//! // Compose two transducers to create a pipeline
//! fn create_pipeline() -> Result<VectorFst<TropicalWeight>> {
//! let fst1 = VectorFst::<TropicalWeight>::new(); // First transducer
//! let fst2 = VectorFst::<TropicalWeight>::new(); // Second transducer
//!
//! // Compose: output of fst1 feeds into input of fst2
//! compose_default(&fst1, &fst2)
//! }
//! ```
//!
//! ## Module Organization
//!
//! The library is organized into focused modules, each handling a specific aspect
//! of FST functionality:
//!
//! ### Core Modules
//!
//! - [`arc`] - Arc types representing FST transitions
//! - [`mod@fst`] - FST implementations and traits
//! - [`semiring`] - Weight types and algebraic operations
//!
//! ### Algorithm Modules
//!
//! - [`algorithms`] - FST algorithms and transformations
//! - [`properties`] - Property computation and analysis
//!
//! ### Support Modules
//!
//! - [`io`] - Serialization and file format support
//! - [`utils`] - Symbol tables and utility types
//! - [`prelude`] - Convenient re-exports of common types
//!
//! ## Performance Guidelines
//!
//! 1. **Choose the right FST type:** Use [`fst::VectorFst`] for construction, [`fst::ConstFst`] for deployment
//! 2. **Leverage properties:** Let the library detect and optimize based on FST properties
//! 3. **Batch operations:** Combine multiple operations when possible
//! 4. **Use lazy evaluation:** For large FSTs, consider lazy implementations
//!
//! ## Additional Topics
//!
//! - **Custom Semirings:** Implement the [`Semiring`] trait for domain-specific weights
//! - **Lazy Computation:** Use [`fst::LazyFstImpl`] for on-demand arc generation
//! - **Memory Optimization:** Employ [`fst::CompactFst`] for memory-constrained environments
//! - **Parallel Algorithms:** Some algorithms support parallel execution (feature-gated)
//!
//! ## References
//!
//! The algorithms and data structures in this library are based on foundational
//! work in weighted finite-state transducer theory:
//!
//! - Mehryar Mohri. 1997. Finite-state transducers in language and speech processing.
//! *Computational Linguistics* 23, 2 (June 1997), 269-311.
//!
//! - Mehryar Mohri, Fernando Pereira, and Michael Riley. 2002. Weighted finite-state
//! transducers in speech recognition. *Computer Speech & Language* 16, 1 (2002), 69-88.
//!
//! - Cyril Allauzen, Michael Riley, Johan Schalkwyk, Wojciech Skut, and Mehryar Mohri.
//! 2007. OpenFst: A general and efficient weighted finite-state transducer library.
//! In *Proceedings of the 12th International Conference on Implementation and
//! Application of Automata (CIAA'07)*. Springer-Verlag, Berlin, Heidelberg, 11-23.
// Global allocator for fast-alloc feature
static GLOBAL: MiMalloc = MiMalloc;
// Re-export key items at crate root
pub use ;
pub use ;
pub use ;
/// Library-wide error type for FST operations.
///
/// This enum represents all possible errors that can occur during FST
/// construction, manipulation, and I/O operations. It implements the
/// standard [`std::error::Error`] trait for seamless integration with
/// Rust's error handling ecosystem.
///
/// # Variants
///
/// - [`Error::InvalidOperation`] - FST structural or semantic violations
/// - [`Error::Io`] - File system and I/O failures
/// - [`Error::Serialization`] - Format conversion errors
/// - [`Error::Algorithm`] - Algorithm precondition violations
///
/// # Examples
///
/// Handling errors with pattern matching:
///
/// ```
/// use arcweight::{Error, Result};
///
/// fn process_fst() -> Result<()> {
/// // ... FST operations ...
/// # Ok(())
/// }
///
/// match process_fst() {
/// Ok(()) => println!("Success"),
/// Err(Error::InvalidOperation(msg)) => eprintln!("Invalid operation: {}", msg),
/// Err(Error::Algorithm(msg)) => eprintln!("Algorithm error: {}", msg),
/// Err(e) => eprintln!("Other error: {}", e),
/// }
/// ```
///
/// Using the `?` operator for error propagation:
///
/// ```
/// use arcweight::prelude::*;
///
/// fn pipeline() -> Result<VectorFst<TropicalWeight>> {
/// let fst = VectorFst::<TropicalWeight>::new();
/// let minimized = minimize(&fst)?;
/// Ok(minimized)
/// }
/// ```
/// Library-wide result type for fallible FST operations.
///
/// This is a type alias for `std::result::Result<T, Error>`, providing
/// a convenient shorthand for functions that may fail with an [`Error`].
///
/// # Examples
///
/// ```
/// use arcweight::prelude::*;
///
/// fn create_acceptor() -> Result<VectorFst<TropicalWeight>> {
/// let mut fst = VectorFst::<TropicalWeight>::new();
/// let s0 = fst.add_state();
/// fst.set_start(s0);
/// fst.set_final(s0, TropicalWeight::one());
/// Ok(fst)
/// }
/// ```
pub type Result<T> = Result;