Skip to main content

Arc

Struct Arc 

Source
pub struct Arc<W: Semiring> {
    pub ilabel: Label,
    pub olabel: Label,
    pub weight: W,
    pub nextstate: StateId,
}
Expand description

A weighted arc (transition) in a finite-state transducer.

Arcs are the fundamental building blocks of FSTs, representing labeled, weighted transitions between states. Each arc specifies:

  • An input symbol to consume (or epsilon if ilabel == 0)
  • An output symbol to produce (or epsilon if olabel == 0)
  • A weight from the semiring W
  • The destination state

§Type Parameters

§Fields

FieldTypeDescription
ilabelLabelInput symbol (0 = epsilon)
olabelLabelOutput symbol (0 = epsilon)
weightWTransition weight
nextstateStateIdDestination state ID

§Examples

Creating different types of arcs:

use arcweight::prelude::*;

// Regular arc with different input/output labels
let arc1 = Arc::new(1, 2, TropicalWeight::new(0.5), 3);

// Acceptor arc (same input/output)
let arc2 = Arc::new(1, 1, TropicalWeight::one(), 2);

// Epsilon arc (input=0, output=0)
let epsilon = Arc::epsilon(TropicalWeight::new(0.1), 1);

assert_eq!(arc1.ilabel, 1);
assert_eq!(arc1.olabel, 2);
assert!(epsilon.is_epsilon());

Using arcs in FST construction:

use arcweight::prelude::*;

let mut fst = VectorFst::<TropicalWeight>::new();
let s0 = fst.add_state();
let s1 = fst.add_state();

// Add a transducer arc
fst.add_arc(s0, Arc::new(1, 2, TropicalWeight::new(0.5), s1));

Fields§

§ilabel: Label

Input label consumed by this transition.

A value of 0 indicates an epsilon transition on the input tape, meaning no symbol is consumed.

§olabel: Label

Output label produced by this transition.

A value of 0 indicates an epsilon transition on the output tape, meaning no symbol is produced.

§weight: W

Weight of this transition in the semiring W.

The weight represents the cost, probability, or other measure associated with taking this transition, as defined by the semiring.

§nextstate: StateId

Destination state ID.

The state that becomes current after taking this transition.

Implementations§

Source§

impl<W: Semiring> Arc<W>

Source

pub fn new(ilabel: Label, olabel: Label, weight: W, nextstate: StateId) -> Self

Creates a new arc with the specified labels, weight, and destination.

This is the primary constructor for arcs in FST construction.

§Arguments
  • ilabel - Input label (0 for epsilon)
  • olabel - Output label (0 for epsilon)
  • weight - Arc weight in the semiring
  • nextstate - Destination state ID
§Returns

A new Arc with the specified components.

§Examples
use arcweight::prelude::*;

let arc = Arc::new(1, 2, TropicalWeight::new(0.5), 3);

assert_eq!(arc.ilabel, 1);
assert_eq!(arc.olabel, 2);
assert_eq!(arc.weight, TropicalWeight::new(0.5));
assert_eq!(arc.nextstate, 3);
Examples found in repository?
examples/morphological_analyzer.rs (line 732)
714fn build_morphotactic_fst() -> VectorFst<TropicalWeight> {
715    let mut fst = VectorFst::new();
716    let start = fst.add_state();
717    let noun_stem = fst.add_state();
718    let noun_inflected = fst.add_state();
719    let final_state = fst.add_state();
720
721    fst.set_start(start);
722    fst.set_final(final_state, TropicalWeight::one());
723
724    // Simplified morphotactic FST structure
725    // Start → NounStem → NounInflected → Final
726
727    // Add noun stem "cat"
728    for ch in "cat".chars() {
729        let next = fst.add_state();
730        fst.add_arc(
731            start,
732            Arc::new(ch as u32, ch as u32, TropicalWeight::one(), next),
733        );
734    }
735
736    // Add morpheme boundary
737    fst.add_arc(
738        noun_stem,
739        Arc::new(
740            '+' as u32,
741            0, // epsilon output
742            TropicalWeight::one(),
743            noun_inflected,
744        ),
745    );
746
747    // Add plural suffix "s"
748    fst.add_arc(
749        noun_inflected,
750        Arc::new('s' as u32, 's' as u32, TropicalWeight::one(), final_state),
751    );
752
753    fst
754}
More examples
Hide additional examples
examples/spell_checking.rs (line 55)
33fn build_dictionary_fst(words: &[&str]) -> VectorFst<TropicalWeight> {
34    let mut fst = VectorFst::new();
35    let start = fst.add_state();
36    fst.set_start(start);
37
38    // Build a trie structure
39    let mut state_map: HashMap<Vec<char>, u32> = HashMap::new();
40    state_map.insert(vec![], start);
41
42    for word in words {
43        let chars: Vec<char> = word.chars().collect();
44        let mut prefix = vec![];
45
46        for (i, &ch) in chars.iter().enumerate() {
47            let current_state = *state_map.get(&prefix).unwrap();
48            prefix.push(ch);
49
50            if !state_map.contains_key(&prefix) {
51                let new_state = fst.add_state();
52                state_map.insert(prefix.clone(), new_state);
53                fst.add_arc(
54                    current_state,
55                    Arc::new(ch as u32, ch as u32, TropicalWeight::one(), new_state),
56                );
57            }
58
59            // If this is the last character, mark as final
60            if i == chars.len() - 1 {
61                let final_state = *state_map.get(&prefix).unwrap();
62                fst.set_final(final_state, TropicalWeight::one());
63            }
64        }
65    }
66
67    fst
68}
69
70/// Creates an FST that accepts all words within edit distance k of a target word
71///
72/// # Arguments
73/// * `target` - The target word to match against
74/// * `k` - Maximum allowed edit distance
75///
76/// # Returns
77/// An FST that accepts words within edit distance k of target
78fn build_edit_distance_fst(target: &str, k: usize) -> VectorFst<TropicalWeight> {
79    let mut fst = VectorFst::new();
80    let target_chars: Vec<char> = target.chars().collect();
81    let n = target_chars.len();
82
83    // Create states: (position in target, edits used)
84    let mut states = vec![vec![]; n + 1];
85    for (i, state_row) in states.iter_mut().enumerate().take(n + 1) {
86        for _j in 0..=k.min(i + k) {
87            state_row.push(fst.add_state());
88        }
89    }
90
91    // Start state
92    fst.set_start(states[0][0]);
93
94    // Final states - at end of target with <= k edits
95    for j in 0..=k.min(n + k) {
96        if j < states[n].len() {
97            fst.set_final(states[n][j], TropicalWeight::new(j as f32));
98        }
99    }
100
101    // Add transitions
102    for i in 0..n {
103        for j in 0..states[i].len() {
104            if j > i + k {
105                continue; // Skip impossible states
106            }
107
108            let current = states[i][j];
109
110            // Match (no cost)
111            if j < states[i + 1].len() {
112                fst.add_arc(
113                    current,
114                    Arc::new(
115                        target_chars[i] as u32,
116                        target_chars[i] as u32,
117                        TropicalWeight::one(),
118                        states[i + 1][j],
119                    ),
120                );
121            }
122
123            // If we can still make edits
124            if j < k {
125                // Substitution (cost 1)
126                if j + 1 < states[i + 1].len() {
127                    for c in b'a'..=b'z' {
128                        if c as char != target_chars[i] {
129                            fst.add_arc(
130                                current,
131                                Arc::new(
132                                    c as u32,
133                                    c as u32,
134                                    TropicalWeight::new(1.0),
135                                    states[i + 1][j + 1],
136                                ),
137                            );
138                        }
139                    }
140                }
141
142                // Deletion in target (consume target char with epsilon)
143                if j + 1 < states[i + 1].len() {
144                    fst.add_arc(
145                        current,
146                        Arc::new(
147                            0, // epsilon
148                            0, // epsilon
149                            TropicalWeight::new(1.0),
150                            states[i + 1][j + 1],
151                        ),
152                    );
153                }
154
155                // Insertion (consume input char)
156                if j + 1 < states[i].len() {
157                    for c in b'a'..=b'z' {
158                        fst.add_arc(
159                            current,
160                            Arc::new(
161                                c as u32,
162                                c as u32,
163                                TropicalWeight::new(1.0),
164                                states[i][j + 1],
165                            ),
166                        );
167                    }
168                }
169            }
170        }
171    }
172
173    // Handle insertions at the end
174    for j in 0..states[n].len() {
175        if j < k && j + 1 < states[n].len() {
176            let current = states[n][j];
177            for c in b'a'..=b'z' {
178                fst.add_arc(
179                    current,
180                    Arc::new(
181                        c as u32,
182                        c as u32,
183                        TropicalWeight::new(1.0),
184                        states[n][j + 1],
185                    ),
186                );
187            }
188        }
189    }
190
191    fst
192}
examples/number_date_normalizer.rs (lines 380-385)
357fn build_number_normalization_fst() -> VectorFst<TropicalWeight> {
358    let mut fst = VectorFst::new();
359    let start = fst.add_state();
360    fst.set_start(start);
361    fst.set_final(start, TropicalWeight::one());
362
363    // Add some simple number transformations
364    let number_rules = vec![
365        ("one", "1"),
366        ("two", "2"),
367        ("three", "3"),
368        ("four", "4"),
369        ("five", "5"),
370    ];
371
372    for (word, digit) in number_rules {
373        let mut current = start;
374
375        // Accept the word
376        for ch in word.chars() {
377            let next = fst.add_state();
378            fst.add_arc(
379                current,
380                Arc::new(
381                    ch as u32,
382                    0, // epsilon output during word
383                    TropicalWeight::one(),
384                    next,
385                ),
386            );
387            current = next;
388        }
389
390        // Output the digit
391        for ch in digit.chars() {
392            let next = fst.add_state();
393            fst.add_arc(
394                current,
395                Arc::new(
396                    0, // epsilon input
397                    ch as u32,
398                    TropicalWeight::one(),
399                    next,
400                ),
401            );
402            current = next;
403        }
404
405        // Connect back to start for more normalizations
406        fst.add_arc(
407            current,
408            Arc::new(
409                0, // epsilon
410                0, // epsilon
411                TropicalWeight::one(),
412                start,
413            ),
414        );
415    }
416
417    fst
418}
examples/pronunciation_lexicon.rs (lines 195-200)
176fn build_simple_lexicon(entries: &[LexiconEntry]) -> VectorFst<TropicalWeight> {
177    let mut fst = VectorFst::new();
178    let start = fst.add_state();
179    fst.set_start(start);
180
181    for entry in entries {
182        // For each pronunciation, create a separate path
183        for pronunciation in &entry.pronunciations {
184            let mut states = vec![start];
185
186            // Create states for each character in the word
187            for _ in 0..entry.word.len() {
188                states.push(fst.add_state());
189            }
190
191            // Add transitions for each character
192            for (i, ch) in entry.word.chars().enumerate() {
193                fst.add_arc(
194                    states[i],
195                    Arc::new(
196                        ch as u32,
197                        ch as u32, // Output the same character for now
198                        TropicalWeight::one(),
199                        states[i + 1],
200                    ),
201                );
202            }
203
204            // At the end of the word, output the pronunciation
205            let mut current = states[entry.word.len()];
206            for phoneme in pronunciation {
207                let next = fst.add_state();
208                fst.add_arc(
209                    current,
210                    Arc::new(
211                        0, // epsilon input
212                        phoneme.to_label(),
213                        TropicalWeight::one(),
214                        next,
215                    ),
216                );
217                current = next;
218            }
219
220            fst.set_final(current, TropicalWeight::one());
221        }
222    }
223
224    fst
225}
226
227/// Build an FST that accepts a single word
228fn word_acceptor(word: &str) -> VectorFst<TropicalWeight> {
229    let mut fst = VectorFst::new();
230    let mut current = fst.add_state();
231    fst.set_start(current);
232
233    for ch in word.chars() {
234        let next = fst.add_state();
235        fst.add_arc(
236            current,
237            Arc::new(ch as u32, ch as u32, TropicalWeight::one(), next),
238        );
239        current = next;
240    }
241
242    fst.set_final(current, TropicalWeight::one());
243    fst
244}
245
246/// Look up pronunciations for a word using the lexicon
247fn lookup_word_in_lexicon(entries: &[LexiconEntry], word: &str) -> Option<Vec<Vec<Phoneme>>> {
248    for entry in entries {
249        if entry.word == word {
250            return Some(entry.pronunciations.clone());
251        }
252    }
253    None
254}
255
256/// Build a G2P (Grapheme-to-Phoneme) FST for unknown words
257fn build_g2p_rules() -> VectorFst<TropicalWeight> {
258    let mut fst = VectorFst::new();
259    let start = fst.add_state();
260    fst.set_start(start);
261    fst.set_final(start, TropicalWeight::one());
262
263    // Simple G2P rules - in practice this would be much more sophisticated
264    let rules = vec![
265        ('a', Phoneme::AE),
266        ('e', Phoneme::EH),
267        ('i', Phoneme::IH),
268        ('o', Phoneme::AO),
269        ('u', Phoneme::AH),
270        ('b', Phoneme::B),
271        ('c', Phoneme::K),
272        ('d', Phoneme::D),
273        ('f', Phoneme::F),
274        ('g', Phoneme::G),
275        ('h', Phoneme::HH),
276        ('j', Phoneme::JH),
277        ('k', Phoneme::K),
278        ('l', Phoneme::L),
279        ('m', Phoneme::M),
280        ('n', Phoneme::N),
281        ('p', Phoneme::P),
282        ('r', Phoneme::R),
283        ('s', Phoneme::S),
284        ('t', Phoneme::T),
285        ('v', Phoneme::V),
286        ('w', Phoneme::W),
287        ('y', Phoneme::Y),
288        ('z', Phoneme::Z),
289    ];
290
291    for (grapheme, phoneme) in rules {
292        fst.add_arc(
293            start,
294            Arc::new(
295                grapheme as u32,
296                phoneme.to_label(),
297                TropicalWeight::new(1.0),
298                start,
299            ),
300        );
301    }
302
303    fst
304}
examples/transliteration.rs (line 1007)
982fn build_transliteration_fst(rules: &[TransliterationRule]) -> VectorFst<TropicalWeight> {
983    let mut fst = VectorFst::new();
984    let start = fst.add_state();
985    fst.set_start(start);
986    fst.set_final(start, TropicalWeight::one());
987
988    // Sort rules by source length (longest first) to handle digraphs
989    let mut sorted_rules = rules.to_vec();
990    sorted_rules.sort_by(|a, b| b.source.len().cmp(&a.source.len()));
991
992    for rule in &sorted_rules {
993        let mut current = start;
994
995        // Process each character in the source
996        let source_chars: Vec<char> = rule.source.chars().collect();
997        for (i, &ch) in source_chars.iter().enumerate() {
998            if i == source_chars.len() - 1 {
999                // Last character - output the target
1000                let target_chars: Vec<char> = rule.target.chars().collect();
1001                let _target_state = start;
1002
1003                for &target_ch in &target_chars {
1004                    let next = fst.add_state();
1005                    fst.add_arc(
1006                        current,
1007                        Arc::new(ch as u32, target_ch as u32, TropicalWeight::one(), next),
1008                    );
1009                    current = next;
1010                }
1011
1012                // Connect back to start for more characters
1013                fst.add_arc(
1014                    current,
1015                    Arc::new(
1016                        0, // epsilon
1017                        0, // epsilon
1018                        TropicalWeight::one(),
1019                        start,
1020                    ),
1021                );
1022            } else {
1023                // Intermediate character
1024                let next = fst.add_state();
1025                fst.add_arc(
1026                    current,
1027                    Arc::new(
1028                        ch as u32,
1029                        0, // epsilon output
1030                        TropicalWeight::one(),
1031                        next,
1032                    ),
1033                );
1034                current = next;
1035            }
1036        }
1037    }
1038
1039    // Add pass-through for unknown characters
1040    for ch in 0..=127u8 {
1041        if ch.is_ascii() {
1042            fst.add_arc(
1043                start,
1044                Arc::new(ch as u32, ch as u32, TropicalWeight::one(), start),
1045            );
1046        }
1047    }
1048
1049    fst
1050}
examples/phonological_rules.rs (lines 106-111)
88fn build_vowel_harmony_fst() -> VectorFst<TropicalWeight> {
89    let mut fst = VectorFst::new();
90    let start = fst.add_state();
91    let back_state = fst.add_state();
92    let front_state = fst.add_state();
93
94    fst.set_start(start);
95    fst.set_final(start, TropicalWeight::one());
96    fst.set_final(back_state, TropicalWeight::one());
97    fst.set_final(front_state, TropicalWeight::one());
98
99    // Back vowels trigger back harmony
100    let back_vowels = ['a', 'o', 'u'];
101    let front_vowels = ['e', 'i'];
102
103    for &vowel in &back_vowels {
104        fst.add_arc(
105            start,
106            Arc::new(
107                vowel as u32,
108                vowel as u32,
109                TropicalWeight::one(),
110                back_state,
111            ),
112        );
113        fst.add_arc(
114            back_state,
115            Arc::new(
116                vowel as u32,
117                vowel as u32,
118                TropicalWeight::one(),
119                back_state,
120            ),
121        );
122    }
123
124    for &vowel in &front_vowels {
125        fst.add_arc(
126            start,
127            Arc::new(
128                vowel as u32,
129                vowel as u32,
130                TropicalWeight::one(),
131                front_state,
132            ),
133        );
134        fst.add_arc(
135            front_state,
136            Arc::new(
137                vowel as u32,
138                vowel as u32,
139                TropicalWeight::one(),
140                front_state,
141            ),
142        );
143    }
144
145    // Harmonizing vowel: 'E' becomes 'e' in front context, 'a' in back context
146    fst.add_arc(
147        back_state,
148        Arc::new('E' as u32, 'a' as u32, TropicalWeight::one(), back_state),
149    );
150
151    fst.add_arc(
152        front_state,
153        Arc::new('E' as u32, 'e' as u32, TropicalWeight::one(), front_state),
154    );
155
156    // Consonants are transparent
157    let consonants = "bcdfghjklmnpqrstvwxyz";
158    for ch in consonants.chars() {
159        fst.add_arc(
160            start,
161            Arc::new(ch as u32, ch as u32, TropicalWeight::one(), start),
162        );
163        fst.add_arc(
164            back_state,
165            Arc::new(ch as u32, ch as u32, TropicalWeight::one(), back_state),
166        );
167        fst.add_arc(
168            front_state,
169            Arc::new(ch as u32, ch as u32, TropicalWeight::one(), front_state),
170        );
171    }
172
173    fst
174}
175
176/// Build FST for consonant cluster simplification
177/// Example: /kt/ -> /t/ (cluster reduction)
178fn build_cluster_simplification_fst() -> VectorFst<TropicalWeight> {
179    let mut fst = VectorFst::new();
180    let start = fst.add_state();
181    let k_state = fst.add_state();
182
183    fst.set_start(start);
184    fst.set_final(start, TropicalWeight::one());
185
186    // /k/ followed by /t/ becomes just /t/
187    fst.add_arc(
188        start,
189        Arc::new(
190            'k' as u32,
191            0, // epsilon output (delete k)
192            TropicalWeight::one(),
193            k_state,
194        ),
195    );
196
197    fst.add_arc(
198        k_state,
199        Arc::new('t' as u32, 't' as u32, TropicalWeight::one(), start),
200    );
201
202    // All other characters pass through unchanged
203    for ch in b'a'..=b'z' {
204        let ch = ch as char;
205        if ch != 'k' {
206            fst.add_arc(
207                start,
208                Arc::new(ch as u32, ch as u32, TropicalWeight::one(), start),
209            );
210        }
211    }
212
213    // k in other contexts passes through
214    for ch in b'a'..=b'z' {
215        let ch = ch as char;
216        if ch != 't' {
217            fst.add_arc(
218                k_state,
219                Arc::new(
220                    ch as u32,
221                    'k' as u32, // output the k we held
222                    TropicalWeight::one(),
223                    start,
224                ),
225            );
226            // Then process the current character
227            fst.add_arc(
228                start,
229                Arc::new(ch as u32, ch as u32, TropicalWeight::one(), start),
230            );
231        }
232    }
233
234    fst
235}
236
237/// Build FST for vowel epenthesis (insertion)
238/// Example: Insert 'i' to break consonant clusters
239fn build_epenthesis_fst() -> VectorFst<TropicalWeight> {
240    let mut fst = VectorFst::new();
241    let start = fst.add_state();
242    let consonant_state = fst.add_state();
243
244    fst.set_start(start);
245    fst.set_final(start, TropicalWeight::one());
246    fst.set_final(consonant_state, TropicalWeight::one());
247
248    let vowels = "aeiou";
249    let consonants = "bcdfghjklmnpqrstvwxyz";
250
251    // Vowels pass through and reset to start
252    for ch in vowels.chars() {
253        fst.add_arc(
254            start,
255            Arc::new(ch as u32, ch as u32, TropicalWeight::one(), start),
256        );
257        fst.add_arc(
258            consonant_state,
259            Arc::new(ch as u32, ch as u32, TropicalWeight::one(), start),
260        );
261    }
262
263    // First consonant goes to consonant state
264    for ch in consonants.chars() {
265        fst.add_arc(
266            start,
267            Arc::new(ch as u32, ch as u32, TropicalWeight::one(), consonant_state),
268        );
269    }
270
271    // Second consonant triggers epenthesis
272    for ch in consonants.chars() {
273        fst.add_arc(
274            consonant_state,
275            Arc::new(
276                ch as u32,
277                'i' as u32, // insert epenthetic vowel
278                TropicalWeight::one(),
279                start,
280            ),
281        );
282        // Then output the consonant
283        fst.add_arc(
284            start,
285            Arc::new(
286                0, // epsilon input
287                ch as u32,
288                TropicalWeight::one(),
289                consonant_state,
290            ),
291        );
292    }
293
294    fst
295}
296
297/// Build FST for final devoicing (German-style)
298/// Example: /d/ -> /t/ / _#
299fn build_final_devoicing_fst() -> VectorFst<TropicalWeight> {
300    let mut fst = VectorFst::new();
301    let start = fst.add_state();
302    let voiced_state = fst.add_state();
303
304    fst.set_start(start);
305    fst.set_final(start, TropicalWeight::one());
306
307    // Final voiced consonants become voiceless
308    fst.set_final(voiced_state, TropicalWeight::new(0.0)); // Cost for devoicing
309
310    let voiced_obstruents = ['b', 'd', 'g', 'z', 'v'];
311    let voiceless_obstruents = ['p', 't', 'k', 's', 'f'];
312
313    // Map voiced to voiceless at word end
314    for (&voiced, &voiceless) in voiced_obstruents.iter().zip(voiceless_obstruents.iter()) {
315        fst.add_arc(
316            start,
317            Arc::new(
318                voiced as u32,
319                voiceless as u32,
320                TropicalWeight::one(),
321                voiced_state,
322            ),
323        );
324    }
325
326    // All other characters pass through
327    for ch in b'a'..=b'z' {
328        let ch = ch as char;
329        if !voiced_obstruents.contains(&ch) {
330            fst.add_arc(
331                start,
332                Arc::new(ch as u32, ch as u32, TropicalWeight::one(), start),
333            );
334        }
335    }
336
337    // Non-final voiced consonants pass through unchanged
338    for ch in b'a'..=b'z' {
339        let ch = ch as char;
340        fst.add_arc(
341            voiced_state,
342            Arc::new(ch as u32, ch as u32, TropicalWeight::one(), start),
343        );
344    }
345
346    fst
347}
348
349/// Build FST that accepts a word
350fn build_word_fst(word: &str) -> VectorFst<TropicalWeight> {
351    let mut fst = VectorFst::new();
352    let mut current = fst.add_state();
353    fst.set_start(current);
354
355    for ch in word.chars() {
356        let next = fst.add_state();
357        fst.add_arc(
358            current,
359            Arc::new(ch as u32, ch as u32, TropicalWeight::one(), next),
360        );
361        current = next;
362    }
363
364    fst.set_final(current, TropicalWeight::one());
365    fst
366}
Source

pub fn epsilon(weight: W, nextstate: StateId) -> Self

Creates an epsilon arc (no input or output symbol).

Epsilon arcs have input and output labels of 0, representing transitions that neither consume nor produce symbols. These are commonly used in NFA-to-DFA conversions and composition algorithms.

§Arguments
  • weight - Arc weight in the semiring
  • nextstate - Destination state ID
§Returns

A new Arc with ilabel = 0 and olabel = 0.

§Examples
use arcweight::prelude::*;

let epsilon = Arc::epsilon(TropicalWeight::one(), 2);

assert_eq!(epsilon.ilabel, 0);
assert_eq!(epsilon.olabel, 0);
assert!(epsilon.is_epsilon());
assert!(epsilon.is_epsilon_input());
assert!(epsilon.is_epsilon_output());
Source

pub fn is_epsilon_input(&self) -> bool

Returns true if the input label is epsilon (0).

An epsilon input means this transition does not consume any symbol from the input tape.

§Returns

true if ilabel == 0, false otherwise.

§Examples
use arcweight::prelude::*;

let eps = Arc::new(0, 5, TropicalWeight::one(), 1);
let regular = Arc::new(1, 5, TropicalWeight::one(), 1);

assert!(eps.is_epsilon_input());
assert!(!regular.is_epsilon_input());
Source

pub fn is_epsilon_output(&self) -> bool

Returns true if the output label is epsilon (0).

An epsilon output means this transition does not produce any symbol on the output tape.

§Returns

true if olabel == 0, false otherwise.

§Examples
use arcweight::prelude::*;

let eps = Arc::new(5, 0, TropicalWeight::one(), 1);
let regular = Arc::new(5, 1, TropicalWeight::one(), 1);

assert!(eps.is_epsilon_output());
assert!(!regular.is_epsilon_output());
Source

pub fn is_epsilon(&self) -> bool

Returns true if both input and output labels are epsilon.

A fully epsilon arc neither consumes input nor produces output, representing a “free” transition between states. Such arcs are commonly removed during epsilon removal optimization.

§Returns

true if both ilabel == 0 and olabel == 0, false otherwise.

§Examples
use arcweight::prelude::*;

let full_eps = Arc::epsilon(TropicalWeight::one(), 1);
let input_eps = Arc::new(0, 5, TropicalWeight::one(), 1);
let regular = Arc::new(1, 2, TropicalWeight::one(), 1);

assert!(full_eps.is_epsilon());
assert!(!input_eps.is_epsilon());  // Only input is epsilon
assert!(!regular.is_epsilon());

Trait Implementations§

Source§

impl<W: Clone + Semiring> Clone for Arc<W>

Source§

fn clone(&self) -> Arc<W>

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl<W: Debug + Semiring> Debug for Arc<W>

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl<'de, W> Deserialize<'de> for Arc<W>
where W: Deserialize<'de> + Semiring,

Source§

fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>
where __D: Deserializer<'de>,

Deserialize this value from the given Serde deserializer. Read more
Source§

impl<W: Semiring> Display for Arc<W>

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl<W: Eq + Semiring> Eq for Arc<W>

Source§

impl<W: Hash + Semiring> Hash for Arc<W>

Source§

fn hash<__H: Hasher>(&self, state: &mut __H)

Feeds this value into the given Hasher. Read more
1.3.0 · Source§

fn hash_slice<H>(data: &[Self], state: &mut H)
where H: Hasher, Self: Sized,

Feeds a slice of this type into the given Hasher. Read more
Source§

impl<W: PartialEq + Semiring> PartialEq for Arc<W>

Source§

fn eq(&self, other: &Arc<W>) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 (const: unstable) · Source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
Source§

impl<W> Serialize for Arc<W>
where W: Serialize + Semiring,

Source§

fn serialize<__S>(&self, __serializer: __S) -> Result<__S::Ok, __S::Error>
where __S: Serializer,

Serialize this value into the given Serde serializer. Read more
Source§

impl<W: PartialEq + Semiring> StructuralPartialEq for Arc<W>

Auto Trait Implementations§

§

impl<W> Freeze for Arc<W>
where W: Freeze,

§

impl<W> RefUnwindSafe for Arc<W>
where W: RefUnwindSafe,

§

impl<W> Send for Arc<W>

§

impl<W> Sync for Arc<W>

§

impl<W> Unpin for Arc<W>
where W: Unpin,

§

impl<W> UnsafeUnpin for Arc<W>
where W: UnsafeUnpin,

§

impl<W> UnwindSafe for Arc<W>
where W: UnwindSafe,

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> ArchivePointee for T

Source§

type ArchivedMetadata = ()

The archived version of the pointer metadata for this type.
Source§

fn pointer_metadata( _: &<T as ArchivePointee>::ArchivedMetadata, ) -> <T as Pointee>::Metadata

Converts some archived metadata to the pointer metadata for itself.
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> DeserializeOwned for T
where T: for<'de> Deserialize<'de>,

Source§

impl<T> Downcast<T> for T

Source§

fn downcast(&self) -> &T

Source§

impl<Q, K> Equivalent<K> for Q
where Q: Eq + ?Sized, K: Borrow<Q> + ?Sized,

Source§

fn equivalent(&self, key: &K) -> bool

Checks if this value is equivalent to the given key. Read more
Source§

impl<Q, K> Equivalent<K> for Q
where Q: Eq + ?Sized, K: Borrow<Q> + ?Sized,

Source§

fn equivalent(&self, key: &K) -> bool

Compare self to key and return true if they are equal.
Source§

impl<Q, K> Equivalent<K> for Q
where Q: Eq + ?Sized, K: Borrow<Q> + ?Sized,

Source§

fn equivalent(&self, key: &K) -> bool

Checks if this value is equivalent to the given key. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

impl<T> LayoutRaw for T

Source§

fn layout_raw(_: <T as Pointee>::Metadata) -> Result<Layout, LayoutError>

Returns the layout of the type.
Source§

impl<T, N1, N2> Niching<NichedOption<T, N1>> for N2
where T: SharedNiching<N1, N2>, N1: Niching<T>, N2: Niching<T>,

Source§

unsafe fn is_niched(niched: *const NichedOption<T, N1>) -> bool

Returns whether the given value has been niched. Read more
Source§

fn resolve_niched(out: Place<NichedOption<T, N1>>)

Writes data to out indicating that a T is niched.
Source§

impl<T> Pointable for T

Source§

const ALIGN: usize

The alignment of pointer.
Source§

type Init = T

The type for initializers.
Source§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
Source§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
Source§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
Source§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
Source§

impl<T> Pointee for T

Source§

type Metadata = ()

The metadata type for pointers and references to this type.
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T> ToString for T
where T: Display + ?Sized,

Source§

fn to_string(&self) -> String

Converts the given value to a String. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> Upcast<T> for T

Source§

fn upcast(&self) -> Option<&T>

Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V

Source§

impl<T> WasmNotSend for T
where T: Send,

Source§

impl<T> WasmNotSendSync for T

Source§

impl<T> WasmNotSync for T
where T: Sync,