The UniversalAutomaton::accepts() implementation is failing all acceptance tests. The automaton structure and bit vector encoding appear correct, but the acceptance condition is not properly implemented.
test_accepts_empty_to_emptyWord: ""
Input: ""
Expected: true (distance = 0)
Actual: false
Debug output:
- Initial state: {I#0} (1 position)
- No input to process
- Final state: {I#0} (still 1 I-type position)
- is_final() returns false (no M-type positions)
test_accepts_identicalWord: "test"
Input: "test"
Expected: true (distance = 0)
Actual: false
Debug output:
- Step 1: subword="$$test" (6 chars), next_state: 3 positions ✓
- Step 2: subword="$test" (5 chars), next_state: 3 positions ✓
- Step 3: subword="test" (4 chars), transition FAILED ✗
For empty word with empty input:
state.contains(M-type) → falseReason: For an empty word (length 0), being at position 0 with 0 errors means we've successfully matched the entire word. The position I#0 represents "at the start of the word", but for an empty word, start = end.
For non-empty words, transitions are failing after 2-3 steps.
Possible causes:
Current implementation:
fn is_final(&self, state: &UniversalState<V>) -> bool {
state.positions().any(|pos| pos.is_m_type())
}
This checks if the state contains any M-type position. But this might be:
F^∀,χ_n = M^χ_states
Final states are those in M^χ_states (containing M-type positions).
M^ε_s = {M + t#k | k ≥ -t - n ∧ -2n ≤ t ≤ 0 ∧ 0 ≤ k ≤ n}
M-type positions have:
This means M-type positions represent being "past" the word end.
h_n(w, x₁x₂...x_t) = β(x₁, s_n(w,1))β(x₂, s_n(w,2))...β(x_t, s_n(w,t))
Valid only if t ≤ |w| + n
The encoding processes t input characters against word w.
The automaton processes exactly t characters of input, where t is the input length. After processing:
But the acceptance should depend on whether we've successfully matched the entire word within the error budget!
The thesis automaton A^∀,χ_n is designed to work with the encoding h_n(w, x), which processes exactly |x| input characters. But:
The current implementation processes all input characters but doesn't handle the case where we need to consume remaining word characters (via deletions).
pub fn accepts(&self, word: &str, input: &str) -> bool {
// Special case: empty word
if word.is_empty() {
return input.len() <= self.max_distance as usize;
}
// ... rest of implementation
}
After processing all input, accept if:
fn is_accepting(&self, state: &UniversalState<V>, word_len: usize) -> bool {
state.positions().any(|pos| {
if pos.is_m_type() {
// M-type: past word end
true
} else {
// I-type: check if within n deletions of end
let offset = pos.offset();
let errors = pos.errors();
let remaining = word_len as i32 - offset;
remaining >= 0 && (errors + remaining as u8) <= self.max_distance
}
})
}
After processing all input, simulate deleting remaining word characters:
// After processing all input
for _ in 0..(word.len() - input.len()) {
// Simulate deletion transitions
// This would require implementing a special "epsilon" transition
}
Status: Under investigation Priority: High (blocks Phase 4 completion) Created: 2025-11-11
Can you improve this documentation?Edit on GitHub
cljdoc builds & hosts documentation for Clojure/Script libraries
| Ctrl+k | Jump to recent docs |
| ← | Move to previous article |
| → | Move to next article |
| Ctrl+/ | Jump to the search field |